Merge "msm: Kconfig: sync the 8226 and 8610 config options"
diff --git a/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt b/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt
index e62b9ec..9ac1cbd 100644
--- a/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt
+++ b/Documentation/devicetree/bindings/arm/msm/mpm_counter.txt
@@ -1,4 +1,4 @@
-* MSM Timetick counter (mpm-v2)
+* MSM MPM sleep counter (mpm-v2)
 
 The MPM provides a timetick that starts when the device is powered up and
 is not reset by any of the boot loaders or the HLOS. The MPM timetick counter
@@ -6,12 +6,14 @@
 
 The required nodes for the MPM timetick counter driver are:
 
-- compatible: "qcom,mpm-counter"
+- compatible: "qcom,mpm2-sleep-counter"
 - reg: Specifies the physical address of the timetick count register.
+- clock-frequency: the physical counter frequency.
 
 Example:
-	qcom,mpm-counter@fc4a3000 {
-		compatible = "qcom,mpm-counter";
+	qcom,mpm2-sleep-counter@fc4a3000 {
+		compatible = "qcom,mpm2-sleep-counter";
 		reg = <0xfc4a3000 0x1000>;
+		clock-frequency = <32768>;
 	};
 
diff --git a/Documentation/devicetree/bindings/arm/msm/pmu.txt b/Documentation/devicetree/bindings/arm/msm/pmu.txt
new file mode 100644
index 0000000..0bd5e58
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/pmu.txt
@@ -0,0 +1,40 @@
+* Qcom Performance Monitor Units
+Qcom cores have several PMUs for counting CPU side, L2 and bus side events.
+
+For the L1CC PMU:
+In most cases the L1 cache controller PMU is a per cpu unit. The irq-is-percpu
+flag becomes a requirement if this is the case.
+
+Required Properties:
+
+- compatible : Should be "qcom,krait-pmu"
+- interrupts : 1 combined interrupt or 1 per core. See the devicetree/bindings/gic.txt for more details on this format.
+
+Optional:
+
+- qcom,irq-is-percpu: 	Define this if the IRQ of the PMU is a PPI. This will tell perf to use
+			the per_cpu IRQ API for request and free.
+
+Example:
+
+ arm-pmu {
+                compatible = "qcom,krait-pmu";
+                qcom,irq-is-percpu;
+                interrupts = <1 7 0xf00>;
+        };
+
+For the L2CC PMU:
+If the L2 cache controller PMU is available, its DT bindings should be defined as
+follows.
+
+Required Properties:
+
+- compatible: Should be "qcom,l2-pmu"
+- interrupts : 1 combined interrupt.
+
+Example:
+
+  l2-pmu {
+                compatible = "qcom,l2-pmu";
+                interrupts = <0 1 0>;
+        };
diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt
new file mode 100644
index 0000000..10c1bbf
--- /dev/null
+++ b/Documentation/devicetree/bindings/platform/msm/qpnp-coincell.txt
@@ -0,0 +1,44 @@
+Qualcomm QPNP Coincell - coincell battery charger devices
+
+Required properties:
+- compatible:      Must be "qcom,qpnp-coincell".
+- reg:             Specifies the SPMI address and size for this coincell device.
+
+Required structure:
+- A qcom,qpnp-coincell node must be a child of an SPMI node that has specified
+	the spmi-slave-container property.
+
+Optional properties:
+- qcom,rset-ohms:	Specifies the resistance of the current limiting
+			resistor in ohms.  Four values are supported:
+			800, 1200, 1700, and 2100.
+- qcom,vset-millivolts:	Specifies the coincell charging voltage in millivolts.
+			Four values are supported: 2500, 3000, 3100, and 3200.
+- qcom,charge-enable:	Specifies if coincell charging should be enabled or not.
+			0 = disable charging, 1 = enabled charging
+
+If any of the optional properties are not specified, then the hardware default
+values for the unspecified properties will be used instead.
+
+Example:
+	qcom,spmi@fc4c0000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		interrupt-controller;
+		#interrupt-cells = <3>;
+
+		qcom,pm8941@1 {
+			spmi-slave-container;
+			reg = <0x1>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			qcom,coincell@2800 {
+				compatible = "qcom,qpnp-coincell";
+				reg = <0x2800 0x100>;
+				qcom,rset-ohms = <800>;
+				qcom,vset-millivolts = <3100>;
+				qcom,charge-enable = <1>;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index 4590227..9b58464 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -26,7 +26,6 @@
 - qcom,chg-vddmax-mv:			Target voltage of battery in mV.
 - qcom,chg-vddsafe-mv:			Maximum Vdd voltage in mV.
 - qcom,chg-vinmin-mv:			Minimum input voltage in mV.
-- qcom,chg-vbatdet-mv:			Battery charging resume voltage in mV.
 - qcom,chg-ibatmax-ma:			Maximum battery charge current in mA
 - qcom,chg-ibatterm-ma:			Current at which charging is terminated.
 - qcom,chg-ibatsafe-ma:			Safety battery current setting
@@ -36,6 +35,7 @@
 Parent node optional properties:
 - qcom,chg-maxinput-usb-ma:		Maximum input current USB.
 - qcom,chg-maxinput-dc-ma:		Maximum input current DC.
+- qcom,chg-vbatdet-delta-mv:		Battery charging resume delta.
 - qcom,chg-charging-disabled:		Set this property to disable charging
 					by default. This can then be overriden
 					writing the the module parameter
@@ -44,6 +44,16 @@
 					battery temperature of 250 decidegree
 					Celsius, state of charge to be 50%
 					and disable charging.
+- qcom,chg-warm-bat-degc:		Warm battery temperature in degC.
+- qcom,chg-cool-bat-degc:		Cool battery temperature in degC.
+					Note that if both warm and cool battery
+					temperatures are set, the corresponding
+					ibatmax and bat-mv properties are
+					required to be set.
+- qcom,chg-ibatmax-cool-ma:		Maximum cool battery charge current.
+- qcom,chg-ibatmax-warm-ma:		Maximum warm battery charge current.
+- qcom,chg-warm-bat-mv:			Warm temperature battery target voltage.
+- qcom,chg-cool-bat-mv:			Cool temperature battery target voltage.
 
 Sub node required structure:
 - A qcom,chg node must be a child of an SPMI node that has specified
@@ -132,11 +142,17 @@
 		qcom,chg-vddmax-mv = <4200>;
 		qcom,chg-vddsafe-mv = <4200>;
 		qcom,chg-vinmin-mv = <4200>;
-		qcom,chg-vbatdet-mv = <4200>;
 		qcom,chg-ibatmax-ma = <1500>;
 		qcom,chg-ibatterm-ma = <200>;
 		qcom,chg-ibatsafe-ma = <1500>;
 		qcom,chg-thermal-mitigation = <1500 700 600 325>;
+		qcom,chg-cool-bat-degc = <10>;
+		qcom,chg-cool-bat-mv = <4100>;
+		qcom,chg-ibatmax-warm-ma = <350>;
+		qcom,chg-warm-bat-degc = <45>;
+		qcom,chg-warm-bat-mv = <4100>;
+		qcom,chg-ibatmax-cool-ma = <350>;
+		qcom,chg-vbatdet-delta-mv = <60>;
 
 		qcom,chg-chgr@1000 {
 			reg = <0x1000 0x100>;
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 6cf59ee..df88caa 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -114,6 +114,7 @@
 - qcom,usb2-enable-hsphy2: If present, select second PHY for USB operation.
 - qcom,pool-64-bit-align: If present then the pool's memory will be aligned
   to 64 bits
+- qcom,enable_hbm: if present host bus manager is enabled.
 
 Example MSM HSUSB EHCI controller device node :
 	ehci: qcom,ehci-host@f9a55000 {
diff --git a/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi b/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
new file mode 100644
index 0000000..ded9494
--- /dev/null
+++ b/arch/arm/boot/dts/msm-pm8226-rpm-regulator.dtsi
@@ -0,0 +1,492 @@
+/* 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.
+ */
+
+&rpm_bus {
+	rpm-regulator-smpa1 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s1 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_s1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa3 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s3 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_s3";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa4 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s4 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_s4";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa5 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <5>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s5 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_s5";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l1 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l2 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l2";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l3 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l3";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l4 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l4";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <5>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l5 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l5";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <6>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l6 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l6";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <7>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l7 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l7";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <8>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l8 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l8";
+			qcom,set = <1>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <9>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l9 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l9";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <10>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l10 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l10";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <12>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l12 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l12";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <14>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l14 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l14";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <15>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l15 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l15";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa16 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <16>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l16 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l16";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <17>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l17 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l17";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa18 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <18>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l18 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l18";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa19 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <19>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l19 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l19";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa20 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <20>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l20 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l20";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa21 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <21>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l21 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l21";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa22 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <22>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l22 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l22";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa23 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <23>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l23 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l23";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa24 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <24>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l24 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l24";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa26 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <26>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l26 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l26";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa27 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <27>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l27 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l27";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa28 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <28>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l28 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l28";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-vsa1 {
+		compatible = "qcom,rpm-regulator-smd-resource";
+		qcom,resource-name = "vsa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <2>;
+		status = "disabled";
+
+		regulator-lvs1 {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_lvs1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 28ca985..79acd7f 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -85,6 +85,11 @@
 			qcom,sample-rate = <4>;
 		};
 
+		pm8941_coincell: qcom,coincell@2800 {
+			compatible = "qcom,qpnp-coincell";
+			reg = <0x2800 0x100>;
+		};
+
 		pm8941_bms: qcom,bms {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-bms";
@@ -161,11 +166,17 @@
 			qcom,chg-vddmax-mv = <4200>;
 			qcom,chg-vddsafe-mv = <4200>;
 			qcom,chg-vinmin-mv = <4200>;
-			qcom,chg-vbatdet-mv = <4100>;
 			qcom,chg-ibatmax-ma = <1500>;
 			qcom,chg-ibatterm-ma = <200>;
 			qcom,chg-ibatsafe-ma = <1500>;
 			qcom,chg-thermal-mitigation = <1500 700 600 325>;
+			qcom,chg-cool-bat-degc = <10>;
+			qcom,chg-cool-bat-mv = <4100>;
+			qcom,chg-ibatmax-warm-ma = <350>;
+			qcom,chg-warm-bat-degc = <45>;
+			qcom,chg-warm-bat-mv = <4100>;
+			qcom,chg-ibatmax-cool-ma = <350>;
+			qcom,chg-vbatdet-delta-mv = <350>;
 
 			qcom,chg-chgr@1000 {
 				status = "disabled";
diff --git a/arch/arm/boot/dts/msm8226-iommu.dtsi b/arch/arm/boot/dts/msm8226-iommu.dtsi
index bddafc9..460068b 100644
--- a/arch/arm/boot/dts/msm8226-iommu.dtsi
+++ b/arch/arm/boot/dts/msm8226-iommu.dtsi
@@ -14,6 +14,7 @@
 
 &jpeg_iommu {
 	status = "ok";
+	qcom,iommu-enable-halt;
 
 	qcom,iommu-bfb-regs =  <0x204c
 				0x2050
@@ -50,6 +51,7 @@
 
 &mdp_iommu {
 	status = "ok";
+	qcom,iommu-enable-halt;
 
 	qcom,iommu-bfb-regs =  <0x204c
 				0x2050
@@ -92,6 +94,7 @@
 
 &venus_iommu {
 	status = "ok";
+	qcom,iommu-enable-halt;
 
 	qcom,iommu-bfb-regs =  <0x204c
 				0x2050
@@ -154,6 +157,7 @@
 
 &kgsl_iommu {
 	status = "ok";
+	qcom,iommu-enable-halt;
 
 	qcom,iommu-bfb-regs =  <0x204c
 				0x2050
@@ -184,6 +188,7 @@
 
 &vfe_iommu {
 	status = "ok";
+	qcom,iommu-enable-halt;
 
 	qcom,iommu-bfb-regs =  <0x204c
 				0x2050
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 8168826..c39d987 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -10,300 +10,374 @@
  * GNU General Public License for more details.
  */
 
-/* Stub Regulators */
-
-/ {
-	pm8226_s1_corner: regulator-s1-corner {
-		compatible = "qcom,stub-regulator";
-		regulator-name = "8226_s1_corner";
-		qcom,hpm-min-load = <100000>;
-		regulator-min-microvolt = <1>;
-		regulator-max-microvolt = <7>;
-		qcom,consumer-supplies = "vdd_dig", "";
-	};
-};
-
 /* QPNP controlled regulators: */
 
 &spmi_bus {
-
 	qcom,pm8226@1 {
-
-		pm8226_s1: regulator@1400 {
-			status = "okay";
-			regulator-name = "8226_s1";
-			qcom,enable-time = <500>;
-			qcom,system-load = <100000>;
-			regulator-always-on;
-			regulator-min-microvolt = <1150000>;
-			regulator-max-microvolt = <1150000>;
-		};
-
 		pm8226_s2: regulator@1700 {
 			status = "okay";
 			regulator-name = "8226_s2";
 			qcom,enable-time = <500>;
 			qcom,system-load = <100000>;
-			regulator-always-on;
 			regulator-min-microvolt = <1050000>;
 			regulator-max-microvolt = <1150000>;
-		};
-
-		pm8226_s3: regulator@1a00 {
-			status = "okay";
-			regulator-name = "8226_s3";
-			qcom,enable-time = <500>;
-			qcom,system-load = <100000>;
 			regulator-always-on;
-			regulator-min-microvolt = <1300000>;
+		};
+	};
+};
+
+/* RPM controlled regulators: */
+
+&rpm_bus {
+	rpm-regulator-smpa1 {
+		status = "okay";
+		pm8226_s1: regulator-s1 {
+			regulator-min-microvolt = <500000>;
+			regulator-max-microvolt = <1275000>;
+			status = "okay";
+		};
+		pm8226_s1_corner: regulator-s1-corner {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_s1_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+			qcom,consumer-supplies = "vdd_dig", "";
+		};
+		pm8226_s1_corner_ao: regulator-s1-corner-ao {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_s1_corner_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+		};
+	};
+
+	rpm-regulator-smpa3 {
+		status = "okay";
+		pm8226_s3: regulator-s3 {
+			regulator-min-microvolt = <1200000>;
 			regulator-max-microvolt = <1300000>;
-		};
-
-		pm8226_s4: regulator@1d00 {
+			qcom,init-voltage = <1200000>;
 			status = "okay";
-			regulator-name = "8226_s4";
-			qcom,enable-time = <500>;
-			qcom,system-load = <100000>;
-			regulator-always-on;
+		};
+	};
+
+	rpm-regulator-smpa4 {
+		status = "okay";
+		pm8226_s4: regulator-s4 {
 			regulator-min-microvolt = <2100000>;
 			regulator-max-microvolt = <2100000>;
-		};
-
-		pm8226_s5: regulator@2000 {
+			qcom,init-voltage = <2100000>;
 			status = "okay";
-			regulator-name = "8226_s5";
-			qcom,enable-time = <500>;
+		};
+	};
+
+	rpm-regulator-smpa5 {
+		status = "okay";
+		pm8226_s5: regulator-s5 {
 			regulator-min-microvolt = <1150000>;
 			regulator-max-microvolt = <1150000>;
-		};
-
-		pm8226_l1: regulator@4000 {
+			qcom,init-voltage = <1150000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		status = "okay";
+		pm8226_l1: regulator-l1 {
 			regulator-name = "8226_l1";
-			parent-supply = <&pm8226_s3>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1225000>;
 			regulator-max-microvolt = <1225000>;
-		};
-
-		pm8226_l2: regulator@4100 {
+			qcom,init-voltage = <1225000>;
 			status = "okay";
-			regulator-name = "8226_l2";
-			parent-supply = <&pm8226_s3>;
-			regulator-always-on;
-			qcom,enable-time = <200>;
-			qcom,system-load = <10000>;
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		status = "okay";
+		pm8226_l2: regulator-l2 {
 			regulator-min-microvolt = <1200000>;
 			regulator-max-microvolt = <1200000>;
-		};
-
-		pm8226_l3: regulator@4200 {
+			qcom,init-voltage = <1200000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		status = "okay";
+		pm8226_l3: regulator-l3 {
 			regulator-name = "8226_l3";
-			parent-supply = <&pm8226_s3>;
-			qcom,system-load = <10000>;
-			regulator-always-on;
-			qcom,enable-time = <200>;
-			regulator-min-microvolt = <1150000>;
-			regulator-max-microvolt = <1150000>;
-		};
-
-		pm8226_l4: regulator@4300 {
+			regulator-min-microvolt = <750000>;
+			regulator-max-microvolt = <1275000>;
 			status = "okay";
+		};
+		pm8226_l3_ao: regulator-3-ao {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l3_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <750000>;
+			regulator-max-microvolt = <1275000>;
+			status = "okay";
+		};
+		pm8226_l3_so: regulator-l3-so {
+			compatible = "qcom,rpm-regulator-smd";
+			regulator-name = "8226_l3_so";
+			qcom,set = <2>;
+			regulator-min-microvolt = <750000>;
+			regulator-max-microvolt = <1275000>;
+			qcom,init-voltage = <750000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+		status = "okay";
+		pm8226_l4: regulator-l4 {
 			regulator-name = "8226_l4";
-			parent-supply = <&pm8226_s3>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1200000>;
 			regulator-max-microvolt = <1200000>;
-		};
-
-		pm8226_l5: regulator@4400 {
+			qcom,init-voltage = <1200000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		status = "okay";
+		pm8226_l5: regulator-l5 {
 			regulator-name = "8226_l5";
-			parent-supply = <&pm8226_s3>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1200000>;
 			regulator-max-microvolt = <1200000>;
-		};
-
-		pm8226_l6: regulator@4500 {
+			qcom,init-voltage = <1200000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		status = "okay";
+		pm8226_l6: regulator-l6 {
 			regulator-name = "8226_l6";
-			parent-supply = <&pm8226_s4>;
-			qcom,system-load = <10000>;
-			regulator-always-on;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
-		};
-
-		pm8226_l7: regulator@4600 {
+			qcom,init-voltage = <1800000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		status = "okay";
+		pm8226_l7: regulator-l7 {
 			regulator-name = "8226_l7";
-			parent-supply = <&pm8226_s4>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1850000>;
 			regulator-max-microvolt = <1850000>;
-		};
-
-		pm8226_l8: regulator@4700 {
+			qcom,init-voltage = <1850000>;
 			status = "okay";
-			regulator-name = "8226_l8";
-			parent-supply = <&pm8226_s4>;
-			qcom,enable-time = <200>;
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		status = "okay";
+		pm8226_l8: regulator-l8 {
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
 			qcom,consumer-supplies = "vdd_sr2_pll", "";
 		};
+	};
 
-		pm8226_l9: regulator@4800 {
-			status = "okay";
+	rpm-regulator-ldoa9 {
+		status = "okay";
+		pm8226_l9: regulator-l9 {
 			regulator-name = "8226_l9";
-			parent-supply = <&pm8226_s4>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <2050000>;
 			regulator-max-microvolt = <2050000>;
-		};
-
-		pm8226_l10: regulator@4900 {
+			qcom,init-voltage = <2050000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		status = "okay";
+		pm8226_l10: regulator-l10 {
 			regulator-name = "8226_l10";
-			parent-supply = <&pm8226_s4>;
-			qcom,enable-time = <200>;
-			qcom,system-load = <5000>;
-			regulator-always-on;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
-		};
-
-		pm8226_l12: regulator@4b00 {
+			qcom,init-voltage = <1800000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+		status = "okay";
+		pm8226_l12: regulator-l12 {
 			regulator-name = "8226_l12";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <1800000>;
-		};
-
-		pm8226_l14: regulator@4d00 {
+			qcom,init-voltage = <1800000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		status = "okay";
+		pm8226_l14: regulator-l14 {
 			regulator-name = "8226_l14";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <2750000>;
 			regulator-max-microvolt = <2750000>;
-		};
-
-		pm8226_l15: regulator@4e00 {
+			qcom,init-voltage = <2750000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+		status = "okay";
+		pm8226_l15: regulator-l15 {
 			regulator-name = "8226_l15";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <2800000>;
 			regulator-max-microvolt = <2800000>;
-		};
-
-		pm8226_l16: regulator@4f00 {
+			qcom,init-voltage = <2800000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa16 {
+		status = "okay";
+		pm8226_l16: regulator-l16 {
 			regulator-name = "8226_l16";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <3000000>;
 			regulator-max-microvolt = <3300000>;
-		};
-
-		pm8226_l17: regulator@5000 {
+			qcom,init-voltage = <3300000>;
 			status = "okay";
-			regulator-name = "8226_l17";
-			qcom,enable-time = <200>;
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		status = "okay";
+		pm8226_l17: regulator-l17 {
 			regulator-min-microvolt = <2950000>;
 			regulator-max-microvolt = <2950000>;
-		};
-
-		pm8226_l18: regulator@5100 {
+			qcom,init-voltage = <2950000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa18 {
+		status = "okay";
+		pm8226_l18: regulator-l18 {
 			regulator-name = "8226_l18";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <2950000>;
 			regulator-max-microvolt = <2950000>;
-		};
-
-		pm8226_l19: regulator@5200 {
+			qcom,init-voltage = <2950000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa19 {
+		status = "okay";
+		pm8226_l19: regulator-l19 {
 			regulator-name = "8226_l19";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <2850000>;
 			regulator-max-microvolt = <2850000>;
-		};
-
-		pm8226_l20: regulator@5300 {
+			qcom,init-voltage = <2850000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa20 {
+		status = "okay";
+		pm8226_l20: regulator-l20 {
 			regulator-name = "8226_l20";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <3075000>;
 			regulator-max-microvolt = <3075000>;
-		};
-
-		pm8226_l21: regulator@5400 {
+			qcom,init-voltage = <3075000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa21 {
+		status = "okay";
+		pm8226_l21: regulator-l21 {
 			regulator-name = "8226_l21";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <2950000>;
-		};
-
-		pm8226_l22: regulator@5500 {
+			qcom,init-voltage = <2950000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa22 {
+		status = "okay";
+		pm8226_l22: regulator-l22 {
 			regulator-name = "8226_l22";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <2950000>;
-		};
-
-		pm8226_l23: regulator@5600 {
+			qcom,init-voltage = <2950000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa23 {
+		status = "okay";
+		pm8226_l23: regulator-l23 {
 			regulator-name = "8226_l23";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <2950000>;
-		};
-
-		pm8226_l24: regulator@5700 {
+			qcom,init-voltage = <2950000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa24 {
+		status = "okay";
+		pm8226_l24: regulator-l24 {
 			regulator-name = "8226_l24";
-			parent-supply = <&pm8226_s3>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1300000>;
 			regulator-max-microvolt = <1300000>;
-		};
-
-		pm8226_l26: regulator@5900 {
+			qcom,init-voltage = <1300000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa26 {
+		status = "okay";
+		pm8226_l26: regulator-l26 {
 			regulator-name = "8226_l26";
-			parent-supply = <&pm8226_s3>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1225000>;
 			regulator-max-microvolt = <1225000>;
-		};
-
-		pm8226_l27: regulator@5a00 {
+			qcom,init-voltage = <1225000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa27 {
+		status = "okay";
+		pm8226_l27: regulator-l27 {
 			regulator-name = "8226_l27";
-			parent-supply = <&pm8226_s4>;
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <2050000>;
 			regulator-max-microvolt = <2050000>;
-		};
-
-		pm8226_l28: regulator@5b00 {
+			qcom,init-voltage = <2050000>;
 			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa28 {
+		status = "okay";
+		pm8226_l28: regulator-l28 {
 			regulator-name = "8226_l28";
-			qcom,enable-time = <200>;
 			regulator-min-microvolt = <1800000>;
 			regulator-max-microvolt = <2950000>;
-		};
-
-		pm8226_lvs1: regulator@8000 {
+			qcom,init-voltage = <2950000>;
 			status = "okay";
-			regulator-name = "8226_lvs1";
-			parent-supply = <&pm8226_l6>;
-			qcom,enable-time = <200>;
+		};
+	};
+
+	rpm-regulator-vsa1 {
+		status = "okay";
+		pm8226_lvs1: regulator-lvs1 {
+			status = "okay";
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 2ceaaaa..f0cddfb 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -504,7 +504,7 @@
 		reg = <0xfdd00000 0x2000>,
 		      <0xfdd02000 0x2000>,
 		      <0xfe039000 0x400>,
-		      <0xfec00000 0x180000>;
+		      <0xfec00000 0x20000>;
 		reg-names = "ocmem_ctrl_physical", "dm_ctrl_physical", "br_ctrl_physical", "ocmem_physical";
 		interrupts = <0 76 0 0 77 0>;
 		interrupt-names = "ocmem_irq", "dm_irq";
@@ -513,12 +513,12 @@
 		qcom,resource-type = <0x706d636f>;
 		#address-cells = <1>;
 		#size-cells = <1>;
-		ranges = <0x0 0xfec00000 0x180000>;
+		ranges = <0x0 0xfec00000 0x20000>;
 
 		partition@0 {
-			reg = <0x0 0x100000>;
+			reg = <0x0 0x20000>;
 			qcom,ocmem-part-name = "graphics";
-			qcom,ocmem-part-min = <0x80000>;
+			qcom,ocmem-part-min = <0x20000>;
 		};
 	};
 
@@ -637,6 +637,11 @@
 		qcom,memory-reservation-type = "EBI1";
 		qcom,memory-reservation-size = <0x100000>; /* 1M EBI1 buffer */
 	};
+	qcom,msm-rng@f9bff000 {
+                compatible = "qcom,msm-rng";
+                reg = <0xf9bff000 0x200>;
+                qcom,msm-rng-iface-clk;
+	};
 };
 
 &gdsc_venus {
@@ -663,6 +668,7 @@
 	status = "ok";
 };
 
+/include/ "msm-pm8226-rpm-regulator.dtsi"
 /include/ "msm-pm8226.dtsi"
 /include/ "msm8226-regulator.dtsi"
 
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 2dff4c7..fe0ebf9 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -437,6 +437,19 @@
 		vdd_cx-supply = <&pm8110_s1_corner>;
 		qcom,firmware-name = "adsp";
 	};
+
+	tsens: tsens@fc4a8000 {
+		compatible = "qcom,msm-tsens";
+		reg = <0xfc4a8000 0x2000>,
+		      <0xfc4b8000 0x1000>;
+		reg-names = "tsens_physical", "tsens_eeprom_physical";
+		interrupts = <0 184 0>;
+		qcom,sensors = <2>;
+		qcom,slope = <2901 2846>;
+		qcom,calib-mode = "fuse_map2";
+		qcom,calibration-less-mode;
+	};
+
 };
 
 &gdsc_vfe {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 99886c7..3ebdbb6 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -84,9 +84,10 @@
 		clock-frequency = <19200000>;
 	};
 
-	qcom,mpm-counter@fc4a3000 {
-		compatible = "qcom,mpm-counter";
+	qcom,mpm2-sleep-counter@fc4a3000 {
+		compatible = "qcom,mpm2-sleep-counter";
 		reg = <0xfc4a3000 0x1000>;
+		clock-frequency = <32768>;
 	};
 
 	msm_vidc: qcom,vidc@fdc00000 {
@@ -1382,6 +1383,17 @@
 		reg = <0xfa00000 0x200000>;
 		status = "disable";
 	};
+
+	cpu-pmu {
+		compatible = "qcom,krait-pmu";
+		qcom,irq-is-percpu;
+		interrupts = <1 7 0xf00>;
+	};
+
+	l2-pmu {
+		compatible = "qcom,l2-pmu";
+		interrupts = <0 1 0>;
+	};
 };
 
 &gdsc_venus {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index e1501ac..78786f6 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -52,6 +52,12 @@
 		qcom,direct-connect-irqs = <8>;
 	};
 
+	qcom,mpm2-sleep-counter@fc4a3000 {
+		compatible = "qcom,mpm2-sleep-counter";
+		reg = <0xfc4a3000 0x1000>;
+		clock-frequency = <32768>;
+	};
+
 	timer: msm-qtimer@f9021000 {
 		compatible = "arm,armv7-timer";
 		reg = <0xF9021000 0x1000>;
@@ -731,6 +737,17 @@
 		status = "disable";
 	};
 
+	cpu-pmu {
+                compatible = "arm,cortex-a5-pmu";
+                qcom,irq-is-percpu;
+                interrupts = <1 7 0x00>;
+        };
+
+        l2-pmu {
+                compatible = "qcom,l2-pmu";
+                interrupts = <0 1 0>;
+        };
+
 };
 
 /include/ "msm-pm8019-rpm-regulator.dtsi"
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index fc6bcd6..c59c4fc 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -141,6 +141,7 @@
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM=y
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP_INT=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 9a2e82e..ea10007 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -291,6 +291,7 @@
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP_INT=y
+CONFIG_QPNP_REVID=y
 CONFIG_SLIMBUS_MSM_NGD=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
@@ -422,6 +423,7 @@
 CONFIG_QPNP_PWM=y
 CONFIG_QPNP_POWER_ON=y
 CONFIG_QPNP_CLKDIV=y
+CONFIG_QPNP_COINCELL=y
 CONFIG_MSM_IOMMU=y
 CONFIG_MOBICORE_SUPPORT=m
 CONFIG_MOBICORE_API=m
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 85f29b9..077c7a6 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -296,6 +296,7 @@
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB=y
 CONFIG_MSM_QPNP_INT=y
+CONFIG_QPNP_REVID=y
 CONFIG_SLIMBUS_MSM_NGD=y
 CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
@@ -430,6 +431,7 @@
 CONFIG_QPNP_PWM=y
 CONFIG_QPNP_POWER_ON=y
 CONFIG_QPNP_CLKDIV=y
+CONFIG_QPNP_COINCELL=y
 CONFIG_MSM_IOMMU=y
 CONFIG_MSM_IOMMU_PMON=y
 CONFIG_MOBICORE_SUPPORT=m
diff --git a/arch/arm/include/asm/pmu.h b/arch/arm/include/asm/pmu.h
index d1a3e61..e1fc42f 100644
--- a/arch/arm/include/asm/pmu.h
+++ b/arch/arm/include/asm/pmu.h
@@ -52,6 +52,10 @@
 	void (*disable_irq)(int irq);
 };
 
+extern int multicore_request_irq(int irq, irq_handler_t *handle_irq);
+extern void multicore_free_irq(int irq);
+extern struct arm_pmu_platdata multicore_data;
+
 #ifdef CONFIG_CPU_HAS_PMU
 
 /**
@@ -151,9 +155,6 @@
 			    struct hw_perf_event *hwc,
 			    int idx);
 
-extern void enable_irq_callback(void *);
-extern void disable_irq_callback(void *);
-
 #endif /* CONFIG_HW_PERF_EVENTS */
 
 #endif /* __ARM_PMU_H__ */
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 5311d74..cef66ec 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -21,6 +21,7 @@
 #include <linux/spinlock.h>
 #include <linux/uaccess.h>
 #include <linux/irq.h>
+#include <linux/of.h>
 
 #include <asm/cputype.h>
 #include <asm/irq.h>
@@ -51,6 +52,8 @@
 /* Set at runtime when we know what CPU type we are. */
 static struct arm_pmu *cpu_pmu;
 
+static int per_cpu_irq;
+
 enum arm_perf_pmu_ids
 armpmu_get_pmu_id(void)
 {
@@ -381,6 +384,58 @@
 	return plat->handle_irq(irq, dev, armpmu->handle_irq);
 }
 
+static DEFINE_PER_CPU(u32, pmu_irq_cookie);
+
+void enable_irq_callback(void *info)
+{
+	int irq = *(unsigned int *)info;
+	enable_percpu_irq(irq, IRQ_TYPE_EDGE_RISING);
+}
+
+void disable_irq_callback(void *info)
+{
+	int irq = *(unsigned int *)info;
+	disable_percpu_irq(irq);
+}
+
+int
+multicore_request_irq(int irq, irq_handler_t *handle_irq)
+{
+	int err = 0;
+	int cpu;
+
+	err = request_percpu_irq(irq, *handle_irq, "l1-armpmu",
+			&pmu_irq_cookie);
+
+	if (!err) {
+		for_each_cpu(cpu, cpu_online_mask) {
+			smp_call_function_single(cpu,
+					enable_irq_callback, &irq, 1);
+		}
+	}
+
+	return err;
+}
+
+void
+multicore_free_irq(int irq)
+{
+	int cpu;
+
+	if (irq >= 0) {
+		for_each_cpu(cpu, cpu_online_mask) {
+			smp_call_function_single(cpu,
+					disable_irq_callback, &irq, 1);
+		}
+		free_percpu_irq(irq, &pmu_irq_cookie);
+	}
+}
+
+struct arm_pmu_platdata multicore_data = {
+	.request_pmu_irq = multicore_request_irq,
+	.free_pmu_irq = multicore_free_irq,
+};
+
 int
 armpmu_generic_request_irq(int irq, irq_handler_t *handle_irq)
 {
@@ -689,11 +744,12 @@
 	{.compatible = "arm,cortex-a8-pmu"},
 	{.compatible = "arm,arm1136-pmu"},
 	{.compatible = "arm,arm1176-pmu"},
+	{.compatible = "qcom,krait-pmu"},
 	{},
 };
 
 static struct platform_device_id armpmu_plat_device_ids[] = {
-	{.name = "cpu-arm-pmu"},
+	{.name = "cpu-pmu"},
 	{},
 };
 
@@ -703,12 +759,16 @@
 		return -ENODEV;
 
 	cpu_pmu->plat_device = pdev;
+
+	if (per_cpu_irq == 1)
+		cpu_pmu->plat_device->dev.platform_data = &multicore_data;
+
 	return 0;
 }
 
 static struct platform_driver armpmu_driver = {
 	.driver		= {
-		.name	= "cpu-arm-pmu",
+		.name	= "cpu-pmu",
 		.of_match_table = armpmu_of_device_ids,
 	},
 	.probe		= armpmu_device_probe,
@@ -756,18 +816,6 @@
 	return 0;
 }
 
-void enable_irq_callback(void *info)
-{
-	int irq = *(unsigned int *)info;
-	enable_percpu_irq(irq, IRQ_TYPE_EDGE_RISING);
-}
-
-void disable_irq_callback(void *info)
-{
-	int irq = *(unsigned int *)info;
-	disable_percpu_irq(irq);
-}
-
 /*
  * PMU hardware loses all context when a CPU goes offline.
  * When a CPU is hotplugged back in, since some hardware registers are
@@ -881,6 +929,24 @@
 	.notifier_call = perf_cpu_pm_notifier,
 };
 
+#ifdef CONFIG_OF
+static inline int get_dt_irq_prop(void)
+{
+	struct device_node *np = NULL;
+	int err = -1;
+
+	np = of_find_matching_node(NULL, armpmu_of_device_ids);
+	if (np)
+		err = of_property_read_bool(np, "qcom,irq-is-percpu");
+	else
+		pr_err("Perf: can't find DT node.\n");
+
+	return err;
+}
+#else
+static inline int get_dt_irq_prop(void) {return 0; }
+#endif
+
 /*
  * CPU PMU identification and registration.
  */
@@ -956,6 +1022,8 @@
 		register_cpu_notifier(&pmu_cpu_notifier);
 		armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW);
 		cpu_pm_register_notifier(&perf_cpu_pm_notifier_block);
+		per_cpu_irq = get_dt_irq_prop();
+
 	} else {
 		pr_info("no hardware support available\n");
 	}
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 7d0f051..ce557b1 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2859,4 +2859,12 @@
 	depends on SERIAL_MSM_HS
 	help
 		Select if BLSP based UART Core v.14 or higher is present.
+
+config MSM_BOOT_STATS
+	bool "Use MSM boot stats reporting"
+	help
+	 Use this to report msm boot stats such as bootloader throughput,
+	 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.
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index cb5e712..fb7e4e3 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -29,15 +29,17 @@
 obj-$(CONFIG_DEBUG_FS) += acpuclock-krait-debug.o
 endif
 obj-$(CONFIG_ARCH_MSM7X27) += acpuclock-7627.o acpuclock-8625q.o clock-pll.o
-obj-$(CONFIG_ARCH_MSM_SCORPION) += pmu.o
 obj-$(CONFIG_ARCH_MSM_SCORPIONMP) += perf_event_msm_l2.o
-obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o perf_event_msm_krait_l2.o
+ifndef CONFIG_OF
+obj-$(CONFIG_HW_PERF_EVENTS) += pmu.o
+endif
+obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o perf_event_msm_krait_l2.o
 obj-$(CONFIG_ARCH_MSM_KRAIT) += krait-scm.o
 ifdef CONFIG_HW_PERF_EVENTS
-obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o perf_event_msm_pl310.o
-obj-$(CONFIG_ARCH_MSM9625) += pmu.o perf_event_msm_pl310.o
-obj-$(CONFIG_ARCH_MSM8625) += pmu.o perf_event_msm_pl310.o
-obj-$(CONFIG_ARCH_MSM9615) += pmu.o perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM7X27A) += perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM9625) += perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM8625) += perf_event_msm_pl310.o
+obj-$(CONFIG_ARCH_MSM9615) += perf_event_msm_pl310.o
 obj-$(CONFIG_DEBUG_FS) += perf_debug.o
 endif
 
@@ -193,6 +195,7 @@
 obj-$(CONFIG_ARCH_MSM8X60) += clock-rpm.o
 obj-$(CONFIG_ARCH_MSM8X60) += saw-regulator.o
 obj-$(CONFIG_ARCH_MSM8X60) += footswitch-8x60.o
+obj-$(CONFIG_MSM_BOOT_STATS) += boot_stats.o
 
 ifdef CONFIG_MSM_RPM_REGULATOR
 obj-y += rpm-regulator.o
@@ -300,7 +303,7 @@
 obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.o acpuclock-8930ab.o
 obj-$(CONFIG_ARCH_MPQ8092) += board-8092.o board-8092-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8226) += board-8226.o board-8226-gpiomux.o
-obj-$(CONFIG_ARCH_MSM8226) += clock-local2.o clock-pll.o clock-8226.o clock-rpm.o clock-voter.o clock-mdss-8974.o
+obj-$(CONFIG_ARCH_MSM8226) += clock-local2.o clock-pll.o clock-8226.o clock-rpm.o clock-voter.o clock-mdss-8226.o
 obj-$(CONFIG_ARCH_MSM8226) += acpuclock-8226.o acpuclock-cortex.o
 obj-$(CONFIG_ARCH_MSM8610) += board-8610.o board-8610-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8610) += clock-local2.o clock-pll.o clock-8610.o clock-rpm.o clock-voter.o
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index efd0045..83c14a8 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -308,6 +308,168 @@
 	{ 0, { 0 } }
 };
 
+static struct acpu_level acpu_freq_tbl_2g_pvs1[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   800000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   810000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   820000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   830000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   840000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   850000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   860000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  875000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  885000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  895000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  910000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  920000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  930000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  945000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  960000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  975000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  990000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16), 1005000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16), 1020000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1030000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19), 1045000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1060000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1075000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2g_pvs2[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   785000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   795000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   805000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   815000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   825000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   835000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   845000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  855000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  865000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  875000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  890000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  900000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  910000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  925000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  940000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  955000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  970000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  980000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  995000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16), 1005000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19), 1020000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1035000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2g_pvs3[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   775000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   780000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   790000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   800000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   810000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   820000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   830000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  840000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  850000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  860000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  875000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  885000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  895000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  910000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  925000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  935000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  950000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  960000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  970000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  985000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  995000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1010000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2g_pvs4[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   775000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   780000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   790000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   800000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   810000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   820000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  830000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  840000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  850000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  870000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  880000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  895000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  910000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  920000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  940000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  950000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  960000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  975000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  985000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2g_pvs5[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   750000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   760000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   770000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   780000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   790000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   800000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   810000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  820000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  830000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  840000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  850000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  860000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  870000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  880000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  890000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  900000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  920000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  930000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  940000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  955000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  965000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  975000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2g_pvs6[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   750000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   750000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   760000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   770000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   780000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   790000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   800000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  810000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  820000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  830000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  840000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  850000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  860000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  870000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  875000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  885000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  905000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  915000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  920000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  930000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  940000, 3200000 },
+	{ 1, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 3200000 },
+	{ 0, { 0 } }
+};
+
 static struct acpu_level acpu_freq_tbl_2p3g_pvs0[] __initdata = {
 	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   800000,  400000 },
 	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   800000, 3200000 },
@@ -339,6 +501,192 @@
 	{ 0, { 0 } }
 };
 
+static struct acpu_level acpu_freq_tbl_2p3g_pvs1[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   800000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   800000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   800000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   800000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   800000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   810000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   820000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  830000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  840000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  850000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  860000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  875000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  885000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  895000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  910000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  920000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  930000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  945000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  960000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  975000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  990000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19), 1005000, 3200000 },
+	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 3200000 },
+	{ 1, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 3200000 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 3200000 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p3g_pvs2[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   775000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   775000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   775000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   785000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   795000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   805000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  815000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  825000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  835000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  845000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  855000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  865000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  875000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  890000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  900000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  910000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  925000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  940000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  955000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  970000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  980000, 3200000 },
+	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  995000, 3200000 },
+	{ 1, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 3200000 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 3200000 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p3g_pvs3[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   775000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   775000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   775000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   775000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   780000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   790000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  800000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  810000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  820000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  830000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  840000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  850000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  860000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  875000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  885000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  895000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  910000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  925000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  935000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  950000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  960000, 3200000 },
+	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  970000, 3200000 },
+	{ 1, { 2035200, HFPLL, 1, 106 }, L2(19),  985000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  995000, 3200000 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 3200000 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p3g_pvs4[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   775000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   775000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   775000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   775000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   775000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   775000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   780000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  790000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  800000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  810000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  820000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  830000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  840000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  850000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  860000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  870000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  880000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  895000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  910000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  920000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  930000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  940000, 3200000 },
+	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  950000, 3200000 },
+	{ 1, { 2035200, HFPLL, 1, 106 }, L2(19),  960000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  975000, 3200000 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  985000, 3200000 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p3g_pvs5[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   750000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   750000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   750000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   750000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   750000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   760000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   770000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  780000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  790000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  800000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  810000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  820000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  830000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  840000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  850000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  860000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  870000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  880000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  890000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  900000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  910000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  920000, 3200000 },
+	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  930000, 3200000 },
+	{ 1, { 2035200, HFPLL, 1, 106 }, L2(19),  940000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  955000, 3200000 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  965000, 3200000 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  975000, 3200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p3g_pvs6[] __initdata = {
+	{ 1, {  300000, PLL_0, 0,   0 }, L2(0),   750000,  400000 },
+	{ 0, {  345600, HFPLL, 2,  36 }, L2(3),   750000, 3200000 },
+	{ 1, {  422400, HFPLL, 2,  44 }, L2(3),   750000, 3200000 },
+	{ 0, {  499200, HFPLL, 2,  52 }, L2(6),   750000, 3200000 },
+	{ 1, {  576000, HFPLL, 1,  30 }, L2(6),   750000, 3200000 },
+	{ 1, {  652800, HFPLL, 1,  34 }, L2(7),   750000, 3200000 },
+	{ 1, {  729600, HFPLL, 1,  38 }, L2(7),   760000, 3200000 },
+	{ 0, {  806400, HFPLL, 1,  42 }, L2(10),  770000, 3200000 },
+	{ 1, {  883200, HFPLL, 1,  46 }, L2(10),  780000, 3200000 },
+	{ 0, {  960000, HFPLL, 1,  50 }, L2(10),  790000, 3200000 },
+	{ 1, { 1036800, HFPLL, 1,  54 }, L2(10),  800000, 3200000 },
+	{ 0, { 1113600, HFPLL, 1,  58 }, L2(12),  810000, 3200000 },
+	{ 0, { 1190400, HFPLL, 1,  62 }, L2(12),  820000, 3200000 },
+	{ 0, { 1267200, HFPLL, 1,  66 }, L2(12),  830000, 3200000 },
+	{ 1, { 1344000, HFPLL, 1,  70 }, L2(12),  840000, 3200000 },
+	{ 0, { 1420800, HFPLL, 1,  74 }, L2(16),  850000, 3200000 },
+	{ 0, { 1497600, HFPLL, 1,  78 }, L2(16),  860000, 3200000 },
+	{ 0, { 1574400, HFPLL, 1,  82 }, L2(16),  870000, 3200000 },
+	{ 0, { 1651200, HFPLL, 1,  86 }, L2(16),  875000, 3200000 },
+	{ 1, { 1728000, HFPLL, 1,  90 }, L2(16),  885000, 3200000 },
+	{ 0, { 1804800, HFPLL, 1,  94 }, L2(19),  895000, 3200000 },
+	{ 0, { 1881600, HFPLL, 1,  98 }, L2(19),  905000, 3200000 },
+	{ 0, { 1958400, HFPLL, 1, 102 }, L2(19),  915000, 3200000 },
+	{ 1, { 2035200, HFPLL, 1, 106 }, L2(19),  920000, 3200000 },
+	{ 0, { 2112000, HFPLL, 1, 110 }, L2(19),  930000, 3200000 },
+	{ 0, { 2188800, HFPLL, 1, 114 }, L2(19),  940000, 3200000 },
+	{ 1, { 2265600, HFPLL, 1, 118 }, L2(19),  950000, 3200000 },
+	{ 0, { 0 } }
+};
+
 static struct pvs_table pvs_v1[NUM_SPEED_BINS][NUM_PVS] __initdata = {
 	/* 8974v1 1.7GHz Parts */
 	[0][0] = { acpu_freq_tbl_v1_pvs0, sizeof(acpu_freq_tbl_v1_pvs0) },
@@ -351,23 +699,23 @@
 static struct pvs_table pvs_v2[NUM_SPEED_BINS][NUM_PVS] __initdata = {
 	/* 8974v2 2.0GHz Parts */
 	[0][0] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][1] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][2] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][3] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][4] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][5] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][6] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
-	[0][7] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
+	[0][1] = { acpu_freq_tbl_2g_pvs1, sizeof(acpu_freq_tbl_2g_pvs1) },
+	[0][2] = { acpu_freq_tbl_2g_pvs2, sizeof(acpu_freq_tbl_2g_pvs2) },
+	[0][3] = { acpu_freq_tbl_2g_pvs3, sizeof(acpu_freq_tbl_2g_pvs3) },
+	[0][4] = { acpu_freq_tbl_2g_pvs4, sizeof(acpu_freq_tbl_2g_pvs4) },
+	[0][5] = { acpu_freq_tbl_2g_pvs5, sizeof(acpu_freq_tbl_2g_pvs5) },
+	[0][6] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
+	[0][7] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
 
 	/* 8974v2 2.3GHz Parts */
 	[1][0] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][1] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][2] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][3] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][4] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][5] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][6] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
-	[1][7] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
+	[1][1] = { acpu_freq_tbl_2p3g_pvs1, sizeof(acpu_freq_tbl_2p3g_pvs1) },
+	[1][2] = { acpu_freq_tbl_2p3g_pvs2, sizeof(acpu_freq_tbl_2p3g_pvs2) },
+	[1][3] = { acpu_freq_tbl_2p3g_pvs3, sizeof(acpu_freq_tbl_2p3g_pvs3) },
+	[1][4] = { acpu_freq_tbl_2p3g_pvs4, sizeof(acpu_freq_tbl_2p3g_pvs4) },
+	[1][5] = { acpu_freq_tbl_2p3g_pvs5, sizeof(acpu_freq_tbl_2p3g_pvs5) },
+	[1][6] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
+	[1][7] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
 };
 
 static struct msm_bus_scale_pdata bus_scale_data __initdata = {
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 5db52dd..41263f8 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -114,6 +114,29 @@
 	},
 };
 
+static struct gpiomux_setting lcd_rst_act_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+	.dir = GPIOMUX_OUT_LOW,
+};
+
+static struct gpiomux_setting lcd_rst_sus_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config msm_lcd_configs[] __initdata = {
+	{
+		.gpio = 25,
+		.settings = {
+			[GPIOMUX_ACTIVE]    = &lcd_rst_act_cfg,
+			[GPIOMUX_SUSPENDED] = &lcd_rst_sus_cfg,
+		},
+	}
+};
+
 static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
 	{
 		.gpio      = 0,		/* BLSP1 QUP1 SPI_DATA_MOSI */
@@ -225,4 +248,6 @@
 	msm_gpiomux_install(&sd_card_det, 1);
 	msm_gpiomux_install(msm_synaptics_configs,
 			ARRAY_SIZE(msm_synaptics_configs));
+	msm_gpiomux_install_nowrite(msm_lcd_configs,
+			ARRAY_SIZE(msm_lcd_configs));
 }
diff --git a/arch/arm/mach-msm/boot_stats.c b/arch/arm/mach-msm/boot_stats.c
new file mode 100644
index 0000000..afb4374
--- /dev/null
+++ b/arch/arm/mach-msm/boot_stats.c
@@ -0,0 +1,100 @@
+/* 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/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/smp.h>
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/sched.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <mach/msm_iomap.h>
+
+#include "boot_stats.h"
+
+#define MSM_BOOT_STATS_IMEM_START	(MSM_IMEM_BASE+0x6b0)
+
+static void __iomem *mpm_counter_base;
+static uint32_t mpm_counter_freq;
+static struct boot_stats *boot_stats =
+				(void __iomem *)(MSM_BOOT_STATS_IMEM_START);
+
+static const struct of_device_id mpm_counter_of_match[]	= {
+	{ .compatible	= "qcom,mpm2-sleep-counter",	},
+	{},
+};
+
+static int mpm_parse_dt(void)
+{
+	struct device_node *np;
+	u32 freq;
+
+	np = of_find_matching_node(NULL, mpm_counter_of_match);
+	if (!np) {
+		pr_err("mpm_counter: can't find DT node\n");
+		return -ENODEV;
+	}
+
+	if (!of_property_read_u32(np, "clock-frequency", &freq))
+		mpm_counter_freq = freq;
+	else
+		return -ENODEV;
+
+	if (of_get_address(np, 0, NULL, NULL)) {
+		mpm_counter_base = of_iomap(np, 0);
+		if (!mpm_counter_base) {
+			pr_err("mpm_counter: cant map counter base\n");
+			return -ENODEV;
+		}
+	}
+
+	return 0;
+}
+
+static void print_boot_stats(void)
+{
+	pr_info("KPI: Bootloader start count = %u\n",
+			boot_stats->bootloader_start);
+	pr_info("KPI: Bootloader end count = %u\n",
+			boot_stats->bootloader_end);
+	pr_info("KPI: Bootloader display count = %u\n",
+			boot_stats->bootloader_display);
+	pr_info("KPI: Bootloader load kernel count = %u\n",
+			boot_stats->bootloader_load_kernel);
+	pr_info("KPI: Kernel MPM timestamp = %u\n",
+			__raw_readl(mpm_counter_base));
+	pr_info("KPI: Kernel MPM Clock frequency = %u\n",
+			mpm_counter_freq);
+}
+
+int boot_stats_init(void)
+{
+	int ret;
+
+	if (!boot_stats)
+		return -ENODEV;
+
+	ret = mpm_parse_dt();
+	if (ret < 0)
+		return -ENODEV;
+
+	print_boot_stats();
+
+	return 0;
+}
+
diff --git a/arch/arm/mach-msm/boot_stats.h b/arch/arm/mach-msm/boot_stats.h
new file mode 100644
index 0000000..93e36a2
--- /dev/null
+++ b/arch/arm/mach-msm/boot_stats.h
@@ -0,0 +1,24 @@
+/* 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.
+ */
+
+struct boot_stats {
+	uint32_t bootloader_start;
+	uint32_t bootloader_end;
+	uint32_t bootloader_display;
+	uint32_t bootloader_load_kernel;
+};
+
+#ifdef CONFIG_MSM_BOOT_STATS
+int boot_stats_init(void);
+#else
+static inline int boot_stats_init(void) { return 0; }
+#endif
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 5b8ee92..813b210 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3342,7 +3342,7 @@
 	"fdc84000.qcom,iommu"),
 	CLK_LOOKUP("iface_clk", venus0_ahb_clk.c, "fdc84000.qcom,iommu"),
 	CLK_LOOKUP("core_clk", venus0_axi_clk.c, "fdc84000.qcom,iommu"),
-
+	CLK_LOOKUP("iface_clk", gcc_prng_ahb_clk.c, "f9bff000.qcom,msm-rng"),
 	CLK_LOOKUP("cam_gp0_clk", camss_gp0_clk.c, ""),
 	CLK_LOOKUP("cam_gp1_clk", camss_gp1_clk.c, ""),
 	CLK_LOOKUP("iface_clk", camss_micro_ahb_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-mdss-8226.c b/arch/arm/mach-msm/clock-mdss-8226.c
new file mode 100644
index 0000000..e7eca7b
--- /dev/null
+++ b/arch/arm/mach-msm/clock-mdss-8226.c
@@ -0,0 +1,346 @@
+/* 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/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/iopoll.h>
+#include <linux/clk.h>
+
+#include <asm/processor.h>
+#include <mach/msm_iomap.h>
+#include <mach/clk-provider.h>
+
+#include "clock-mdss-8226.h"
+
+#define REG_R(addr)		readl_relaxed(addr)
+#define REG_W(data, addr)	writel_relaxed(data, addr)
+
+#define GDSC_PHYS		0xFD8C2304
+#define GDSC_SIZE		0x4
+
+#define DSI_PHY_PHYS		0xFD922800
+#define DSI_PHY_SIZE		0x00000800
+
+static unsigned char *mdss_dsi_base;
+static unsigned char *gdsc_base;
+static int pll_byte_clk_rate;
+static int pll_pclk_rate;
+static int pll_initialized;
+static struct clk *mdss_dsi_ahb_clk;
+static unsigned long dsi_pll_rate;
+
+void __init mdss_clk_ctrl_pre_init(struct clk *ahb_clk)
+{
+	BUG_ON(ahb_clk == NULL);
+
+	gdsc_base = ioremap(GDSC_PHYS, GDSC_SIZE);
+	if (!gdsc_base)
+		pr_err("%s: unable to remap gdsc base", __func__);
+
+	mdss_dsi_base = ioremap(DSI_PHY_PHYS, DSI_PHY_SIZE);
+	if (!mdss_dsi_base)
+		pr_err("%s: unable to remap dsi base", __func__);
+
+	mdss_dsi_ahb_clk = ahb_clk;
+}
+
+#define PLL_POLL_MAX_READS 10
+#define PLL_POLL_TIMEOUT_US 50
+
+static int mdss_gdsc_enabled(void)
+{
+	if (!gdsc_base)
+		return 0;
+
+	return !!(readl_relaxed(gdsc_base) & BIT(31));
+}
+
+static int mdss_dsi_check_pll_lock(void)
+{
+	u32 status;
+
+	clk_prepare_enable(mdss_dsi_ahb_clk);
+	/* poll for PLL ready status */
+	if (readl_poll_timeout_noirq((mdss_dsi_base + 0x02c0),
+				status,
+				((status & BIT(0)) == 1),
+				PLL_POLL_MAX_READS, PLL_POLL_TIMEOUT_US)) {
+		pr_err("%s: DSI PLL status=%x failed to Lock\n",
+				__func__, status);
+		pll_initialized = 0;
+	} else {
+		pll_initialized = 1;
+	}
+	clk_disable_unprepare(mdss_dsi_ahb_clk);
+
+	return pll_initialized;
+}
+
+static long mdss_dsi_pll_byte_round_rate(struct clk *c, unsigned long rate)
+{
+	if (pll_initialized) {
+		return pll_byte_clk_rate;
+	} else {
+		pr_err("%s: DSI PLL not configured\n", __func__);
+		return -EINVAL;
+	}
+}
+
+static long mdss_dsi_pll_pixel_round_rate(struct clk *c, unsigned long rate)
+{
+	if (pll_initialized) {
+		return pll_pclk_rate;
+	} else {
+		pr_err("%s: Configure Byte clk first\n", __func__);
+		return -EINVAL;
+	}
+}
+
+static int mdss_dsi_pll_pixel_set_rate(struct clk *c, unsigned long rate)
+{
+	if (pll_initialized) {
+		pll_pclk_rate = (rate * 3) / 2;
+		pr_debug("%s: pll_pclk_rate=%d\n", __func__, pll_pclk_rate);
+		return 0;
+	} else {
+		pr_err("%s: Configure Byte clk first\n", __func__);
+		return -EINVAL;
+	}
+}
+
+static int __mdss_dsi_pll_byte_set_rate(struct clk *c, unsigned long rate)
+{
+	pr_debug("%s: rate=%ld\n", __func__, rate);
+
+	if (pll_initialized)
+		return 0;
+
+	REG_W(0x70, mdss_dsi_base + 0x0230); /* LPFC1 CFG */
+	REG_W(0x08, mdss_dsi_base + 0x022c); /* LPFR CFG */
+	REG_W(0x02, mdss_dsi_base + 0x0210); /* VREG CFG */
+	REG_W(0x00, mdss_dsi_base + 0x0204); /* postDiv1 */
+	REG_W(0x01, mdss_dsi_base + 0x0200); /* REFCLK CFG */
+	REG_W(0x03, mdss_dsi_base + 0x0224); /* postDiv2 */
+	REG_W(0x00, mdss_dsi_base + 0x0238); /* SDM CFG0 */
+	REG_W(0x0b, mdss_dsi_base + 0x023c); /* SDM CFG1 */
+	REG_W(0x00, mdss_dsi_base + 0x0240); /* SDM CFG2 */
+	REG_W(0x6c, mdss_dsi_base + 0x0244); /* SDM CFG3 */
+	REG_W(0x02, mdss_dsi_base + 0x0208); /* ChgPump */
+	REG_W(0x31, mdss_dsi_base + 0x020c); /* VCOLPF CFG */
+	REG_W(0x15, mdss_dsi_base + 0x0234); /* LPFC2 CFG */
+
+	REG_W(0x30, mdss_dsi_base + 0x0284); /* CAL CFG6 */
+	REG_W(0x00, mdss_dsi_base + 0x0288); /* CAL CFG7 */
+	REG_W(0x60, mdss_dsi_base + 0x028c); /* CAL CFG8 */
+	REG_W(0x00, mdss_dsi_base + 0x0290); /* CAL CFG9 */
+	REG_W(0xdd, mdss_dsi_base + 0x0294); /* CAL CFG10 */
+	REG_W(0x01, mdss_dsi_base + 0x0298); /* CAL CFG11 */
+
+	REG_W(0x03, mdss_dsi_base + 0x0228); /* postDiv3 */
+	REG_W(0x2b, mdss_dsi_base + 0x0278); /* Cal CFG3 */
+	REG_W(0x66, mdss_dsi_base + 0x027c); /* Cal CFG4 */
+	REG_W(0x05, mdss_dsi_base + 0x0264); /* LKDET CFG2 */
+	REG_W(0x00, mdss_dsi_base + 0x0248); /* SDM CFG4 */
+	REG_W(0x00, mdss_dsi_base + 0x0214); /* PWRGEN CFG */
+	REG_W(0x0a, mdss_dsi_base + 0x026c); /* CAL CFG0 */
+	REG_W(0x20, mdss_dsi_base + 0x029c); /* EFUSE CFG */
+
+	dsi_pll_rate = rate;
+	pll_byte_clk_rate = rate;
+
+	pr_debug("%s: PLL initialized. bcl=%d\n", __func__, pll_byte_clk_rate);
+	pll_initialized = 1;
+
+	return 0;
+}
+
+static int mdss_dsi_pll_byte_set_rate(struct clk *c, unsigned long rate)
+{
+	int ret;
+
+	clk_prepare_enable(mdss_dsi_ahb_clk);
+	ret = __mdss_dsi_pll_byte_set_rate(c, rate);
+	clk_disable_unprepare(mdss_dsi_ahb_clk);
+
+	return ret;
+}
+
+static void mdss_dsi_uniphy_pll_lock_detect_setting(void)
+{
+	REG_W(0x04, mdss_dsi_base + 0x0264); /* LKDetect CFG2 */
+	udelay(100);
+	REG_W(0x05, mdss_dsi_base + 0x0264); /* LKDetect CFG2 */
+	udelay(500);
+}
+
+static void mdss_dsi_uniphy_pll_sw_reset(void)
+{
+	REG_W(0x01, mdss_dsi_base + 0x0268); /* PLL TEST CFG */
+	udelay(1);
+	REG_W(0x00, mdss_dsi_base + 0x0268); /* PLL TEST CFG */
+	udelay(1);
+}
+
+static int __mdss_dsi_pll_enable(struct clk *c)
+{
+	u32 status;
+	u32 max_reads, timeout_us;
+	int i;
+
+	if (!pll_initialized) {
+		if (dsi_pll_rate)
+			__mdss_dsi_pll_byte_set_rate(c, dsi_pll_rate);
+		else
+			pr_err("%s: Calling clk_en before set_rate\n",
+				__func__);
+	}
+
+	mdss_dsi_uniphy_pll_sw_reset();
+	/* PLL power up */
+	/* Add HW recommended delay between
+	   register writes for the update to propagate */
+	REG_W(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
+	udelay(20);
+	REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
+	udelay(100);
+	REG_W(0x0d, mdss_dsi_base + 0x0220); /* GLB CFG */
+	udelay(20);
+	REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
+	udelay(200);
+
+	for (i = 0; i < 3; i++) {
+		mdss_dsi_uniphy_pll_lock_detect_setting();
+		/* poll for PLL ready status */
+		max_reads = 5;
+		timeout_us = 100;
+		if (readl_poll_timeout_noirq((mdss_dsi_base + 0x02c0),
+				   status,
+				   ((status & 0x01) == 1),
+					     max_reads, timeout_us)) {
+			pr_debug("%s: DSI PLL status=%x failed to Lock\n",
+			       __func__, status);
+			pr_debug("%s:Trying to power UP PLL again\n",
+			       __func__);
+		} else
+			break;
+
+		mdss_dsi_uniphy_pll_sw_reset();
+		udelay(1000);
+		/* Add HW recommended delay between
+		   register writes for the update to propagate */
+		REG_W(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
+		udelay(20);
+		REG_W(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
+		udelay(100);
+		REG_W(0x0d, mdss_dsi_base + 0x0220); /* GLB CFG */
+		udelay(20);
+		REG_W(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
+		udelay(200);
+	}
+
+	if ((status & 0x01) != 1) {
+		pr_err("%s: DSI PLL status=%x failed to Lock\n",
+		       __func__, status);
+		return -EINVAL;
+	}
+
+	pr_debug("%s: **** PLL Lock success\n", __func__);
+
+	return 0;
+}
+
+static void __mdss_dsi_pll_disable(void)
+{
+	writel_relaxed(0x00, mdss_dsi_base + 0x0220); /* GLB CFG */
+	pr_debug("%s: **** disable pll Initialize\n", __func__);
+	pll_initialized = 0;
+}
+
+static DEFINE_SPINLOCK(dsipll_lock);
+static int dsipll_refcount;
+
+static void mdss_dsi_pll_disable(struct clk *c)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dsipll_lock, flags);
+	if (WARN(dsipll_refcount == 0, "DSI PLL clock is unbalanced"))
+		goto out;
+	if (dsipll_refcount == 1)
+		__mdss_dsi_pll_disable();
+	dsipll_refcount--;
+out:
+	spin_unlock_irqrestore(&dsipll_lock, flags);
+}
+
+static int mdss_dsi_pll_enable(struct clk *c)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&dsipll_lock, flags);
+	if (dsipll_refcount == 0) {
+		ret = __mdss_dsi_pll_enable(c);
+		if (ret < 0)
+			goto out;
+	}
+	dsipll_refcount++;
+out:
+	spin_unlock_irqrestore(&dsipll_lock, flags);
+	return ret;
+}
+
+/* todo: Adjust these values appropriately */
+static enum handoff mdss_dsi_pll_byte_handoff(struct clk *c)
+{
+	if (mdss_gdsc_enabled() && mdss_dsi_check_pll_lock()) {
+		c->rate = 59000000;
+		dsi_pll_rate = 59000000;
+		pll_byte_clk_rate = 59000000;
+		pll_pclk_rate = 117000000;
+		dsipll_refcount++;
+		return HANDOFF_ENABLED_CLK;
+	}
+
+	return HANDOFF_DISABLED_CLK;
+}
+
+/* todo: Adjust these values appropriately */
+static enum handoff mdss_dsi_pll_pixel_handoff(struct clk *c)
+{
+	if (mdss_gdsc_enabled() && mdss_dsi_check_pll_lock()) {
+		c->rate = 117000000;
+		dsipll_refcount++;
+		return HANDOFF_ENABLED_CLK;
+	}
+
+	return HANDOFF_DISABLED_CLK;
+}
+
+struct clk_ops clk_ops_dsi_pixel_pll = {
+	.enable = mdss_dsi_pll_enable,
+	.disable = mdss_dsi_pll_disable,
+	.set_rate = mdss_dsi_pll_pixel_set_rate,
+	.round_rate = mdss_dsi_pll_pixel_round_rate,
+	.handoff = mdss_dsi_pll_pixel_handoff,
+};
+
+struct clk_ops clk_ops_dsi_byte_pll = {
+	.enable = mdss_dsi_pll_enable,
+	.disable = mdss_dsi_pll_disable,
+	.set_rate = mdss_dsi_pll_byte_set_rate,
+	.round_rate = mdss_dsi_pll_byte_round_rate,
+	.handoff = mdss_dsi_pll_byte_handoff,
+};
diff --git a/arch/arm/mach-msm/clock-mdss-8226.h b/arch/arm/mach-msm/clock-mdss-8226.h
new file mode 100644
index 0000000..dcf4f92
--- /dev/null
+++ b/arch/arm/mach-msm/clock-mdss-8226.h
@@ -0,0 +1,22 @@
+/* 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_CLOCK_MDSS_8226
+#define __ARCH_ARM_MACH_MSM_CLOCK_MDSS_8226
+
+extern struct clk_ops clk_ops_dsi_byte_pll;
+extern struct clk_ops clk_ops_dsi_pixel_pll;
+
+void mdss_clk_ctrl_pre_init(struct clk *ahb_clk);
+void mdss_clk_ctrl_post_init(void);
+
+#endif /* __ARCH_ARM_MACH_MSM_CLOCK_MDSS_8226 */
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index d3574c8..8c53ea5 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -69,7 +69,6 @@
 #endif
 
 #ifndef __ASSEMBLY__
-void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment);
 void *allocate_contiguous_ebi(unsigned long, unsigned long, int);
 unsigned long allocate_contiguous_ebi_nomap(unsigned long, unsigned long);
 void clean_and_invalidate_caches(unsigned long, unsigned long, unsigned long);
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index f3bd34a..5f11806 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -107,34 +107,6 @@
 	outer_inv_range(pstart, pstart + length);
 }
 
-void * __init alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
-{
-	void *unused_addr = NULL;
-	unsigned long addr, tmp_size, unused_size;
-
-	/* Allocate maximum size needed, see where it ends up.
-	 * Then free it -- in this path there are no other allocators
-	 * so we can depend on getting the same address back
-	 * when we allocate a smaller piece that is aligned
-	 * at the end (if necessary) and the piece we really want,
-	 * then free the unused first piece.
-	 */
-
-	tmp_size = size + alignment - PAGE_SIZE;
-	addr = (unsigned long)alloc_bootmem(tmp_size);
-	free_bootmem(__pa(addr), tmp_size);
-
-	unused_size = alignment - (addr % alignment);
-	if (unused_size)
-		unused_addr = alloc_bootmem(unused_size);
-
-	addr = (unsigned long)alloc_bootmem(size);
-	if (unused_size)
-		free_bootmem(__pa(unused_addr), unused_size);
-
-	return (void *)addr;
-}
-
 char *memtype_name[] = {
 	"SMI_KERNEL",
 	"SMI",
diff --git a/arch/arm/mach-msm/msm_mpmctr.c b/arch/arm/mach-msm/msm_mpmctr.c
index 4ab82ab..cc0c1c3 100644
--- a/arch/arm/mach-msm/msm_mpmctr.c
+++ b/arch/arm/mach-msm/msm_mpmctr.c
@@ -54,7 +54,7 @@
 }
 
 static struct of_device_id msm_mpmctr_of_match[] = {
-	{.compatible = "qcom,mpm-counter"},
+	{.compatible = "qcom,mpm2-sleep-counter"},
 	{}
 };
 
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 0579145..7f2f528 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -27,6 +27,7 @@
 	"2  Perf: Toggle PMU IRQ when CPU's are hotplugged\n"
 	"3  Perf: Correct irq for CPU hotplug detection\n"
 	"4  Perf: Check perf activity on correct CPU\n"
+	"5  Perf: Add DT support for L1 and L2 PMU\n"
 ;
 
 static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/arch/arm/mach-msm/perf_event_msm_krait_l2.c b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
index 34b9426..ad34457 100644
--- a/arch/arm/mach-msm/perf_event_msm_krait_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_krait_l2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -564,6 +564,14 @@
 	.pmu.attr_groups		= msm_l2_pmu_attr_grps,
 };
 
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id l2pmu_of_device_ids[] = {
+	{.compatible = "qcom,l2-pmu"},
+	{},
+};
+
 static int __devinit krait_l2_pmu_device_probe(struct platform_device *pdev)
 {
 	krait_l2_pmu.plat_device = pdev;
@@ -576,7 +584,8 @@
 
 static struct platform_driver krait_l2_pmu_driver = {
 	.driver		= {
-		.name	= "l2-arm-pmu",
+		.name	= "l2-pmu",
+		.of_match_table = l2pmu_of_device_ids,
 	},
 	.probe		= krait_l2_pmu_device_probe,
 };
diff --git a/arch/arm/mach-msm/perf_event_msm_l2.c b/arch/arm/mach-msm/perf_event_msm_l2.c
index f78487a..efd5e21 100644
--- a/arch/arm/mach-msm/perf_event_msm_l2.c
+++ b/arch/arm/mach-msm/perf_event_msm_l2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -917,7 +917,7 @@
 
 static struct platform_driver scorpion_l2_pmu_driver = {
 	.driver		= {
-		.name	= "l2-arm-pmu",
+		.name	= "l2-pmu",
 	},
 	.probe		= scorpion_l2_pmu_device_probe,
 };
diff --git a/arch/arm/mach-msm/perf_event_msm_pl310.c b/arch/arm/mach-msm/perf_event_msm_pl310.c
index e2a580f..a0d96bf 100644
--- a/arch/arm/mach-msm/perf_event_msm_pl310.c
+++ b/arch/arm/mach-msm/perf_event_msm_pl310.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 ARM Limited
- * 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
@@ -415,9 +415,18 @@
 	return 0;
 }
 
+/*
+ * PMU platform driver and devicetree bindings.
+ */
+static struct of_device_id l2pmu_of_device_ids[] = {
+	{.compatible = "qcom,l2-pmu"},
+	{},
+};
+
 static struct platform_driver l2x0pmu_driver = {
 	.driver		= {
-		.name	= "l2-arm-pmu",
+		.name	= "l2-pmu",
+		.of_match_table = l2pmu_of_device_ids,
 	},
 	.probe		= l2x0pmu_device_probe,
 };
diff --git a/arch/arm/mach-msm/pmu.c b/arch/arm/mach-msm/pmu.c
index febeb19..57378c7 100644
--- a/arch/arm/mach-msm/pmu.c
+++ b/arch/arm/mach-msm/pmu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,62 +15,6 @@
 #include <mach/irqs.h>
 #include <mach/socinfo.h>
 
-/*
- * If a GIC is present, then all IRQ's < 32 are PPI's and can only be
- * requested and free'd using the percpu IRQ API.
- * If a VIC is present, then only the traditional request, free API works.
- *
- * All MPCore's have GIC's. The Cortex A5 however may or may not be MPcore, but
- * it still has a GIC. Except, the 7x27a, which is an A5 and yet has a VIC.
- * So if the chip is A5 but does not have a GIC, default to the traditional
- * IRQ {request, free}_irq API.
- */
-
-#if defined(CONFIG_ARCH_MSM_KRAITMP) || defined(CONFIG_ARCH_MSM_SCORPIONMP) \
-	|| defined(CONFIG_ARCH_MSM8625) || \
-	(defined(CONFIG_ARCH_MSM_CORTEX_A5) && !defined(CONFIG_MSM_VIC))
-
-static DEFINE_PER_CPU(u32, pmu_irq_cookie);
-
-static int
-multicore_request_irq(int irq, irq_handler_t *handle_irq)
-{
-	int err = 0;
-	int cpu;
-
-	err = request_percpu_irq(irq, *handle_irq, "l1-armpmu",
-			&pmu_irq_cookie);
-
-	if (!err) {
-		for_each_cpu(cpu, cpu_online_mask) {
-			smp_call_function_single(cpu,
-					enable_irq_callback, &irq, 1);
-		}
-	}
-
-	return err;
-}
-
-static void
-multicore_free_irq(int irq)
-{
-	int cpu;
-
-	if (irq >= 0) {
-		for_each_cpu(cpu, cpu_online_mask) {
-			smp_call_function_single(cpu,
-					disable_irq_callback, &irq, 1);
-		}
-		free_percpu_irq(irq, &pmu_irq_cookie);
-	}
-}
-
-static struct arm_pmu_platdata multicore_data = {
-	.request_pmu_irq = multicore_request_irq,
-	.free_pmu_irq = multicore_free_irq,
-};
-#endif
-
 static struct resource cpu_pmu_resource[] = {
 	{
 		.start = INT_ARMQC_PERFMON,
@@ -89,7 +33,7 @@
 };
 
 static struct platform_device l2_pmu_device = {
-	.name		= "l2-arm-pmu",
+	.name		= "l2-pmu",
 	.id		= ARM_PMU_DEVICE_L2CC,
 	.resource	= l2_pmu_resource,
 	.num_resources	= ARRAY_SIZE(l2_pmu_resource),
@@ -98,7 +42,7 @@
 #endif
 
 static struct platform_device cpu_pmu_device = {
-	.name		= "cpu-arm-pmu",
+	.name		= "cpu-pmu",
 	.id		= ARM_PMU_DEVICE_CPU,
 	.resource	= cpu_pmu_resource,
 	.num_resources	= ARRAY_SIZE(cpu_pmu_resource),
@@ -120,7 +64,7 @@
 };
 
 static struct platform_device msm8625_cpu_pmu_device = {
-	.name		= "cpu-arm-pmu",
+	.name		= "cpu-pmu",
 	.id		= ARM_PMU_DEVICE_CPU,
 	.resource	= msm8625_cpu_pmu_resource,
 	.num_resources	= ARRAY_SIZE(msm8625_cpu_pmu_resource),
@@ -135,7 +79,7 @@
 };
 
 static struct platform_device msm8625_l2_pmu_device = {
-	.name		= "l2-arm-pmu",
+	.name		= "l2-pmu",
 	.id		= ARM_PMU_DEVICE_L2CC,
 	.resource	= msm8625_l2_pmu_resource,
 	.num_resources	= ARRAY_SIZE(msm8625_l2_pmu_resource),
@@ -156,7 +100,6 @@
 	 * handlers to call the percpu API.
 	 * Defaults to unicore API {request,free}_irq().
 	 * See arch/arm/kernel/perf_event.c
-	 * See Comment above on the A5 and MSM_VIC.
 	 */
 #if defined(CONFIG_ARCH_MSM_KRAITMP) || defined(CONFIG_ARCH_MSM_SCORPIONMP) \
 	|| (defined(CONFIG_ARCH_MSM_CORTEX_A5) && !defined(CONFIG_MSM_VIC))
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 3da1c63..efbd8c6 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -29,6 +29,7 @@
 #include <mach/socinfo.h>
 
 #include "smd_private.h"
+#include "boot_stats.h"
 
 #define BUILD_ID_LENGTH 32
 
@@ -1139,6 +1140,7 @@
 	if (socinfo->v1.id < ARRAY_SIZE(cpu_of_id))
 		cur_cpu = cpu_of_id[socinfo->v1.id];
 
+	boot_stats_init();
 	socinfo_print();
 
 	return 0;
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index be71347..3d5614b 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -787,6 +787,8 @@
 
 			spin_lock_irqsave(&cpufreq_driver_lock, flags);
 			cpumask_copy(managed_policy->cpus, policy->cpus);
+			cpumask_and(managed_policy->cpus,
+					managed_policy->cpus, cpu_online_mask);
 			per_cpu(cpufreq_cpu_data, cpu) = managed_policy;
 			spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
 
diff --git a/drivers/crypto/msm/qce.c b/drivers/crypto/msm/qce.c
index 7f8460b..5c1cc5a 100644
--- a/drivers/crypto/msm/qce.c
+++ b/drivers/crypto/msm/qce.c
@@ -505,19 +505,6 @@
 	return nents;
 }
 
-static int dma_map_pmem_sg(struct buf_info *pmem, unsigned entries,
-						struct scatterlist *sg)
-{
-	int i = 0;
-	for (i = 0; i < entries; i++) {
-
-		sg->dma_address = (dma_addr_t)pmem->offset;
-		sg++;
-		pmem++;
-	}
-	return 0;
-}
-
 static int _probe_ce_engine(struct qce_device *pce_dev)
 {
 	unsigned int val;
@@ -1084,52 +1071,6 @@
 	return 0;
 };
 
-static int _ablk_cipher_use_pmem_complete(struct qce_device *pce_dev)
-{
-	struct ablkcipher_request *areq;
-	uint32_t iv_out[4];
-	unsigned char iv[4 * sizeof(uint32_t)];
-	uint32_t status;
-
-	areq = (struct ablkcipher_request *) pce_dev->areq;
-
-	/* check ce error status */
-	status = readl_relaxed(pce_dev->iobase + CRYPTO_STATUS_REG);
-	if (status & (1 << CRYPTO_SW_ERR)) {
-		pce_dev->err++;
-		dev_err(pce_dev->pdev,
-			"Qualcomm Crypto Error at 0x%x, status%x\n",
-			pce_dev->phy_iobase, status);
-		_init_ce_engine(pce_dev);
-		clk_disable(pce_dev->ce_clk);
-		pce_dev->qce_cb(areq, NULL, NULL, -ENXIO);
-		return 0;
-	};
-
-	/* get iv out */
-	if (pce_dev->mode == QCE_MODE_ECB) {
-		clk_disable(pce_dev->ce_clk);
-		pce_dev->qce_cb(areq, NULL, NULL, pce_dev->chan_ce_in_status |
-					pce_dev->chan_ce_out_status);
-	} else {
-		iv_out[0] = readl_relaxed(pce_dev->iobase +
-							CRYPTO_CNTR0_IV0_REG);
-		iv_out[1] = readl_relaxed(pce_dev->iobase +
-							CRYPTO_CNTR1_IV1_REG);
-		iv_out[2] = readl_relaxed(pce_dev->iobase +
-							CRYPTO_CNTR2_IV2_REG);
-		iv_out[3] = readl_relaxed(pce_dev->iobase +
-							CRYPTO_CNTR3_IV3_REG);
-
-		_net_words_to_byte_stream(iv_out, iv, sizeof(iv));
-		clk_disable(pce_dev->ce_clk);
-		pce_dev->qce_cb(areq, NULL, iv, pce_dev->chan_ce_in_status |
-					pce_dev->chan_ce_out_status);
-	}
-
-	return 0;
-};
-
 static int qce_split_and_insert_dm_desc(struct dmov_desc *pdesc,
 			unsigned int plen, unsigned int paddr, int *index)
 {
@@ -1555,53 +1496,6 @@
 };
 
 
-static void _ablk_cipher_ce_in_call_back_pmem(struct msm_dmov_cmd *cmd_ptr,
-		unsigned int result, struct msm_dmov_errdata *err)
-{
-	struct qce_device *pce_dev;
-
-	pce_dev = (struct qce_device *) cmd_ptr->user;
-	if (result != ADM_STATUS_OK) {
-		dev_err(pce_dev->pdev, "Qualcomm ADM status error %x\n",
-						result);
-		pce_dev->chan_ce_in_status = -1;
-	} else
-		pce_dev->chan_ce_in_status = 0;
-
-	pce_dev->chan_ce_in_state = QCE_CHAN_STATE_COMP;
-	if (pce_dev->chan_ce_out_state == QCE_CHAN_STATE_COMP) {
-		pce_dev->chan_ce_in_state = QCE_CHAN_STATE_IDLE;
-		pce_dev->chan_ce_out_state = QCE_CHAN_STATE_IDLE;
-
-		/* done */
-		_ablk_cipher_use_pmem_complete(pce_dev);
-	}
-};
-
-static void _ablk_cipher_ce_out_call_back_pmem(struct msm_dmov_cmd *cmd_ptr,
-		unsigned int result, struct msm_dmov_errdata *err)
-{
-	struct qce_device *pce_dev;
-
-	pce_dev = (struct qce_device *) cmd_ptr->user;
-	if (result != ADM_STATUS_OK) {
-		dev_err(pce_dev->pdev, "Qualcomm ADM status error %x\n",
-						result);
-		pce_dev->chan_ce_out_status = -1;
-	} else {
-		pce_dev->chan_ce_out_status = 0;
-	};
-
-	pce_dev->chan_ce_out_state = QCE_CHAN_STATE_COMP;
-	if (pce_dev->chan_ce_in_state == QCE_CHAN_STATE_COMP) {
-		pce_dev->chan_ce_in_state = QCE_CHAN_STATE_IDLE;
-		pce_dev->chan_ce_out_state = QCE_CHAN_STATE_IDLE;
-
-		/* done */
-		_ablk_cipher_use_pmem_complete(pce_dev);
-	}
-};
-
 static int _setup_cmd_template(struct qce_device *pce_dev)
 {
 	dmov_sg *pcmd;
@@ -2183,14 +2077,9 @@
 	/* cipher input       */
 	pce_dev->src_nents = count_sg(areq->src, areq->nbytes);
 
-	if (c_req->use_pmem != 1)
-		qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
+	qce_dma_map_sg(pce_dev->pdev, areq->src, pce_dev->src_nents,
 			(areq->src == areq->dst) ? DMA_BIDIRECTIONAL :
 								DMA_TO_DEVICE);
-	else
-		dma_map_pmem_sg(&c_req->pmem->src[0], pce_dev->src_nents,
-								areq->src);
-
 	if (_chain_sg_buffer_in(pce_dev, areq->src, areq->nbytes) < 0) {
 		rc = -ENOMEM;
 		goto bad;
@@ -2199,12 +2088,8 @@
 	/* cipher output      */
 	if (areq->src != areq->dst) {
 		pce_dev->dst_nents = count_sg(areq->dst, areq->nbytes);
-		if (c_req->use_pmem != 1)
-			qce_dma_map_sg(pce_dev->pdev, areq->dst,
+		qce_dma_map_sg(pce_dev->pdev, areq->dst,
 					pce_dev->dst_nents, DMA_FROM_DEVICE);
-		else
-			dma_map_pmem_sg(&c_req->pmem->dst[0],
-					pce_dev->dst_nents, areq->dst);
 	};
 	if (_chain_sg_buffer_out(pce_dev, areq->dst, areq->nbytes) < 0) {
 		rc = -ENOMEM;
@@ -2241,34 +2126,25 @@
 	/* setup for callback, and issue command to adm */
 	pce_dev->areq = areq;
 	pce_dev->qce_cb = c_req->qce_cb;
-	if (c_req->use_pmem == 1) {
-		pce_dev->chan_ce_in_cmd->complete_func =
-					_ablk_cipher_ce_in_call_back_pmem;
-		pce_dev->chan_ce_out_cmd->complete_func =
-					_ablk_cipher_ce_out_call_back_pmem;
-	} else {
-		pce_dev->chan_ce_in_cmd->complete_func =
+	pce_dev->chan_ce_in_cmd->complete_func =
 					_ablk_cipher_ce_in_call_back;
-		pce_dev->chan_ce_out_cmd->complete_func =
+	pce_dev->chan_ce_out_cmd->complete_func =
 					_ablk_cipher_ce_out_call_back;
-	}
 	rc = _qce_start_dma(pce_dev, true, true);
 
 	if (rc == 0)
 		return 0;
 bad:
-	if (c_req->use_pmem != 1) {
-		if (pce_dev->dst_nents) {
-			qce_dma_unmap_sg(pce_dev->pdev, areq->dst,
-				pce_dev->dst_nents, DMA_FROM_DEVICE);
-		}
-		if (pce_dev->src_nents) {
-			qce_dma_unmap_sg(pce_dev->pdev, areq->src,
-					pce_dev->src_nents,
-					(areq->src == areq->dst) ?
-						DMA_BIDIRECTIONAL :
-						DMA_TO_DEVICE);
-		}
+	if (pce_dev->dst_nents) {
+		qce_dma_unmap_sg(pce_dev->pdev, areq->dst,
+			pce_dev->dst_nents, DMA_FROM_DEVICE);
+	}
+	if (pce_dev->src_nents) {
+		qce_dma_unmap_sg(pce_dev->pdev, areq->src,
+				pce_dev->src_nents,
+				(areq->src == areq->dst) ?
+					DMA_BIDIRECTIONAL :
+					DMA_TO_DEVICE);
 	}
 	return rc;
 }
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 41ab8dc..2440404 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -12,7 +12,7 @@
  * GNU General Public License for more details.
  */
 #include <linux/mman.h>
-#include <linux/android_pmem.h>
+
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
@@ -454,14 +454,12 @@
 
 	/* start the command on the podev->active_command */
 	qcedev_areq = podev->active_command;
-
 	qcedev_areq->cipher_req.cookie = qcedev_areq->handle;
-	creq.use_pmem = qcedev_areq->cipher_op_req.use_pmem;
-	if (qcedev_areq->cipher_op_req.use_pmem == QCEDEV_USE_PMEM)
-		creq.pmem = &qcedev_areq->cipher_op_req.pmem;
-	else
-		creq.pmem = NULL;
-
+	if (qcedev_areq->cipher_op_req.use_pmem == QCEDEV_USE_PMEM) {
+		pr_err("%s: Use of PMEM is not supported\n", __func__);
+		goto unsupported;
+	}
+	creq.pmem = NULL;
 	switch (qcedev_areq->cipher_op_req.alg) {
 	case QCEDEV_ALG_DES:
 		creq.alg = CIPHER_ALG_DES;
@@ -1274,224 +1272,6 @@
 		return qcedev_hmac_final(areq, handle);
 }
 
-#ifdef CONFIG_ANDROID_PMEM
-static int qcedev_pmem_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
-						struct qcedev_handle *handle)
-{
-	int i = 0;
-	int err = 0;
-	struct scatterlist *sg_src = NULL;
-	struct scatterlist *sg_dst = NULL;
-	struct scatterlist *sg_ndex = NULL;
-	struct file *file_src = NULL;
-	struct file *file_dst = NULL;
-	unsigned long paddr;
-	unsigned long kvaddr;
-	unsigned long len;
-
-	sg_src = kmalloc((sizeof(struct scatterlist) *
-				areq->cipher_op_req.entries),	GFP_KERNEL);
-	if (sg_src == NULL) {
-		pr_err("%s: Can't Allocate memory:sg_src 0x%x\n",
-			__func__, (uint32_t)sg_src);
-		return -ENOMEM;
-
-	}
-	memset(sg_src, 0, (sizeof(struct scatterlist) *
-				areq->cipher_op_req.entries));
-	sg_ndex = sg_src;
-	areq->cipher_req.creq.src = sg_src;
-
-	/* address src */
-	get_pmem_file(areq->cipher_op_req.pmem.fd_src, &paddr,
-					&kvaddr, &len, &file_src);
-
-	for (i = 0; i < areq->cipher_op_req.entries; i++) {
-		sg_set_buf(sg_ndex,
-		((uint8_t *)(areq->cipher_op_req.pmem.src[i].offset) + kvaddr),
-		areq->cipher_op_req.pmem.src[i].len);
-		sg_ndex++;
-	}
-	sg_mark_end(--sg_ndex);
-
-	for (i = 0; i < areq->cipher_op_req.entries; i++)
-		areq->cipher_op_req.pmem.src[i].offset += (uint32_t)paddr;
-
-	/* address dst */
-	/* If not place encryption/decryption */
-	if (areq->cipher_op_req.in_place_op != 1) {
-		sg_dst = kmalloc((sizeof(struct scatterlist) *
-				areq->cipher_op_req.entries), GFP_KERNEL);
-		if (sg_dst == NULL) {
-			pr_err("%s: Can't Allocate memory: sg_dst 0x%x\n",
-			__func__, (uint32_t)sg_dst);
-			return -ENOMEM;
-		}
-		memset(sg_dst, 0, (sizeof(struct scatterlist) *
-					areq->cipher_op_req.entries));
-		areq->cipher_req.creq.dst = sg_dst;
-		sg_ndex = sg_dst;
-
-		get_pmem_file(areq->cipher_op_req.pmem.fd_dst, &paddr,
-					&kvaddr, &len, &file_dst);
-		for (i = 0; i < areq->cipher_op_req.entries; i++)
-			sg_set_buf(sg_ndex++,
-			((uint8_t *)(areq->cipher_op_req.pmem.dst[i].offset)
-			+ kvaddr), areq->cipher_op_req.pmem.dst[i].len);
-		sg_mark_end(--sg_ndex);
-
-		for (i = 0; i < areq->cipher_op_req.entries; i++)
-			areq->cipher_op_req.pmem.dst[i].offset +=
-							(uint32_t)paddr;
-	} else {
-		areq->cipher_req.creq.dst = sg_src;
-		for (i = 0; i < areq->cipher_op_req.entries; i++) {
-			areq->cipher_op_req.pmem.dst[i].offset =
-				areq->cipher_op_req.pmem.src[i].offset;
-			areq->cipher_op_req.pmem.dst[i].len =
-				areq->cipher_op_req.pmem.src[i].len;
-		}
-	}
-
-	areq->cipher_req.creq.nbytes = areq->cipher_op_req.data_len;
-	areq->cipher_req.creq.info = areq->cipher_op_req.iv;
-
-	err = submit_req(areq, handle);
-
-	kfree(sg_src);
-	kfree(sg_dst);
-
-	if (file_dst)
-		put_pmem_file(file_dst);
-	if (file_src)
-		put_pmem_file(file_src);
-
-	return err;
-};
-
-
-static int qcedev_pmem_ablk_cipher(struct qcedev_async_req *qcedev_areq,
-						struct qcedev_handle *handle)
-{
-	int err = 0;
-	int i = 0;
-	int j = 0;
-	int k = 0;
-	int num_entries = 0;
-	uint32_t total = 0;
-	struct qcedev_cipher_op_req *saved_req;
-	struct qcedev_cipher_op_req *creq = &qcedev_areq->cipher_op_req;
-
-	saved_req = kmalloc(sizeof(struct qcedev_cipher_op_req), GFP_KERNEL);
-	if (saved_req == NULL) {
-		pr_err(KERN_ERR "%s:Can't Allocate mem:saved_req 0x%x\n",
-		__func__, (uint32_t)saved_req);
-		return -ENOMEM;
-	}
-	memcpy(saved_req, creq, sizeof(struct qcedev_cipher_op_req));
-
-	if (qcedev_areq->cipher_op_req.data_len > QCE_MAX_OPER_DATA) {
-
-		struct qcedev_cipher_op_req req;
-
-		/* save the original req structure */
-		memcpy(&req, creq, sizeof(struct qcedev_cipher_op_req));
-
-		i = 0;
-		/* Address 32 KB  at a time */
-		while ((i < req.entries) && (err == 0)) {
-			if (creq->pmem.src[i].len > QCE_MAX_OPER_DATA) {
-				creq->pmem.src[0].len =	QCE_MAX_OPER_DATA;
-				if (i > 0) {
-					creq->pmem.src[0].offset =
-						creq->pmem.src[i].offset;
-				}
-
-				creq->data_len = QCE_MAX_OPER_DATA;
-				creq->entries = 1;
-
-				err =
-				qcedev_pmem_ablk_cipher_max_xfer(qcedev_areq,
-								handle);
-
-				creq->pmem.src[i].len =	req.pmem.src[i].len -
-							QCE_MAX_OPER_DATA;
-				creq->pmem.src[i].offset =
-						req.pmem.src[i].offset +
-						QCE_MAX_OPER_DATA;
-				req.pmem.src[i].offset =
-						creq->pmem.src[i].offset;
-				req.pmem.src[i].len = creq->pmem.src[i].len;
-			} else {
-				total = 0;
-				for (j = i; j < req.entries; j++) {
-					num_entries++;
-					if ((total + creq->pmem.src[j].len)
-							>= QCE_MAX_OPER_DATA) {
-						creq->pmem.src[j].len =
-						QCE_MAX_OPER_DATA - total;
-						total = QCE_MAX_OPER_DATA;
-						break;
-					}
-					total += creq->pmem.src[j].len;
-				}
-
-				creq->data_len = total;
-				if (i > 0)
-					for (k = 0; k < num_entries; k++) {
-						creq->pmem.src[k].len =
-						creq->pmem.src[i+k].len;
-						creq->pmem.src[k].offset =
-						creq->pmem.src[i+k].offset;
-					}
-				creq->entries =  num_entries;
-
-				i = j;
-				err =
-				qcedev_pmem_ablk_cipher_max_xfer(qcedev_areq,
-								handle);
-				num_entries = 0;
-
-					creq->pmem.src[i].offset =
-						req.pmem.src[i].offset +
-						creq->pmem.src[i].len;
-					creq->pmem.src[i].len =
-						req.pmem.src[i].len -
-						creq->pmem.src[i].len;
-					req.pmem.src[i].offset =
-						creq->pmem.src[i].offset;
-					req.pmem.src[i].len =
-						creq->pmem.src[i].len;
-
-				if (creq->pmem.src[i].len == 0)
-					i++;
-			}
-
-		} /* end of while ((i < req.entries) && (err == 0)) */
-
-	} else
-		err = qcedev_pmem_ablk_cipher_max_xfer(qcedev_areq, handle);
-
-	/* Restore the original req structure */
-	for (i = 0; i < saved_req->entries; i++) {
-		creq->pmem.src[i].len = saved_req->pmem.src[i].len;
-		creq->pmem.src[i].offset = saved_req->pmem.src[i].offset;
-	}
-	creq->entries = saved_req->entries;
-	creq->data_len = saved_req->data_len;
-	kfree(saved_req);
-
-	return err;
-
-}
-#else
-static int qcedev_pmem_ablk_cipher(struct qcedev_async_req *qcedev_areq,
-						struct qcedev_handle *handle)
-{
-	return -EPERM;
-}
-#endif/*CONFIG_ANDROID_PMEM*/
-
 static int qcedev_vbuf_ablk_cipher_max_xfer(struct qcedev_async_req *areq,
 				int *di, struct qcedev_handle *handle,
 				uint8_t *k_align_src)
@@ -1753,6 +1533,10 @@
 static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req,
 						struct qcedev_control *podev)
 {
+	if (req->use_pmem) {
+		pr_err("%s: Use of PMEM is not supported\n", __func__);
+		goto error;
+	}
 	if ((req->entries == 0) || (req->data_len == 0))
 		goto error;
 	if ((req->alg >= QCEDEV_ALG_LAST) ||
@@ -1792,15 +1576,6 @@
 	if (req->byteoffset) {
 		if (req->mode != QCEDEV_AES_MODE_CTR)
 			goto error;
-		else { /* if using CTR mode make sure not using Pmem */
-			if (req->use_pmem)
-				goto error;
-		}
-	}
-	/* if using PMEM with non-zero byteoffset, ensure it is in_place_op */
-	if (req->use_pmem) {
-		if (!req->in_place_op)
-			goto error;
 	}
 	/* Ensure zer ivlen for ECB  mode  */
 	if (req->ivlen != 0) {
@@ -1890,10 +1665,7 @@
 				podev))
 			return -EINVAL;
 
-		if (qcedev_areq.cipher_op_req.use_pmem)
-			err = qcedev_pmem_ablk_cipher(&qcedev_areq, handle);
-		else
-			err = qcedev_vbuf_ablk_cipher(&qcedev_areq, handle);
+		err = qcedev_vbuf_ablk_cipher(&qcedev_areq, handle);
 		if (err)
 			return err;
 		if (__copy_to_user((void __user *)arg,
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index b1a45bf..bf45a63 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -251,23 +251,19 @@
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
 
-	result = kgsl_mmu_map_global(pagetable, &rb->buffer_desc,
-				     GSL_PT_PAGE_RV);
+	result = kgsl_mmu_map_global(pagetable, &rb->buffer_desc);
 	if (result)
 		goto error;
 
-	result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc,
-				     GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+	result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc);
 	if (result)
 		goto unmap_buffer_desc;
 
-	result = kgsl_mmu_map_global(pagetable, &device->memstore,
-				     GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+	result = kgsl_mmu_map_global(pagetable, &device->memstore);
 	if (result)
 		goto unmap_memptrs_desc;
 
-	result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory,
-				     GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+	result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory);
 	if (result)
 		goto unmap_memstore_desc;
 
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 5cdf911..69b34fa 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -485,6 +485,7 @@
 	 */
 	rb->sizedwords = KGSL_RB_SIZE >> 2;
 
+	rb->buffer_desc.flags = KGSL_MEMFLAGS_GPUREADONLY;
 	/* allocate memory for ringbuffer */
 	status = kgsl_allocate_contiguous(&rb->buffer_desc,
 		(rb->sizedwords << 2));
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 130474a..6e1ecd1 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1871,10 +1871,7 @@
 	else if (entry->memdesc.size >= SZ_64K)
 		kgsl_memdesc_set_align(&entry->memdesc, ilog2(SZ_64));
 
-	result = kgsl_mmu_map(private->pagetable,
-			      &entry->memdesc,
-			      GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
-
+	result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
 	if (result)
 		goto error_put_file_ptr;
 
@@ -2065,8 +2062,7 @@
 	if (result)
 		return result;
 
-	result = kgsl_mmu_map(private->pagetable, &entry->memdesc,
-				kgsl_memdesc_protflags(&entry->memdesc));
+	result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
 	if (result)
 		goto err;
 
@@ -2104,8 +2100,7 @@
 		goto err;
 
 	if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
-		result = kgsl_mmu_map(private->pagetable, &entry->memdesc,
-				kgsl_memdesc_protflags(&entry->memdesc));
+		result = kgsl_mmu_map(private->pagetable, &entry->memdesc);
 		if (result)
 			goto err;
 	}
@@ -2719,8 +2714,7 @@
 	if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) {
 		entry->memdesc.gpuaddr = vma->vm_start;
 
-		ret = kgsl_mmu_map(private->pagetable, &entry->memdesc,
-				   kgsl_memdesc_protflags(&entry->memdesc));
+		ret = kgsl_mmu_map(private->pagetable, &entry->memdesc);
 		if (ret) {
 			kgsl_mem_entry_put(entry);
 			return ret;
@@ -2753,6 +2747,29 @@
 	}
 
 	vma->vm_ops = &kgsl_gpumem_vm_ops;
+
+	if (cache == KGSL_CACHEMODE_WRITEBACK
+		|| cache == KGSL_CACHEMODE_WRITETHROUGH) {
+		struct scatterlist *s;
+		int i;
+		int sglen = entry->memdesc.sglen;
+		unsigned long addr = vma->vm_start;
+
+		/* don't map in the guard page, it should always fault */
+		if (kgsl_memdesc_has_guard_page(&entry->memdesc))
+			sglen--;
+
+		for_each_sg(entry->memdesc.sg, s, sglen, i) {
+			int j;
+			for (j = 0; j < (sg_dma_len(s) >> PAGE_SHIFT); j++) {
+				struct page *page = sg_page(s);
+				page = nth_page(page, j);
+				vm_insert_page(vma, addr, page);
+				addr += PAGE_SIZE;
+			}
+		}
+	}
+
 	vma->vm_file = file;
 
 	entry->memdesc.useraddr = vma->vm_start;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 3eb8831..70a704b 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -149,6 +149,8 @@
 #define KGSL_MEMDESC_GUARD_PAGE BIT(0)
 /* Set if the memdesc is mapped into all pagetables */
 #define KGSL_MEMDESC_GLOBAL BIT(1)
+/* The memdesc is frozen during a snapshot */
+#define KGSL_MEMDESC_FROZEN BIT(2)
 
 /* shared memory allocation */
 struct kgsl_memdesc {
@@ -175,15 +177,10 @@
 #define KGSL_MEM_ENTRY_ION    4
 #define KGSL_MEM_ENTRY_MAX    5
 
-/* List of flags */
-
-#define KGSL_MEM_ENTRY_FROZEN (1 << 0)
-
 struct kgsl_mem_entry {
 	struct kref refcount;
 	struct kgsl_memdesc memdesc;
 	int memtype;
-	int flags;
 	void *priv_data;
 	struct rb_node node;
 	unsigned int id;
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index c24e03b..11d6ffa 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -210,8 +210,7 @@
 				return result;
 			}
 
-			result = kgsl_mmu_map(priv->pagetable, &priv->memdesc,
-					GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+			result = kgsl_mmu_map(priv->pagetable, &priv->memdesc);
 			if (result) {
 				DRM_ERROR(
 				"kgsl_mmu_map failed.  result = %d\n", result);
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index df8e1d0..93b7e5d 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -43,6 +43,8 @@
 	{ 0x820, 0, 0 },			/* RESUME */
 	{ 0x03C, 0, 0 },			/* TLBLKCR */
 	{ 0x818, 0, 0 },			/* V2PUR */
+	{ 0x2C, 0, 0 },                         /* FSYNR0 */
+	{ 0x2C, 0, 0 },                         /* FSYNR0 */
 };
 
 static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = {
@@ -51,7 +53,11 @@
 	{ 0x28, 0x00FFFFFF, 14 },		/* TTBR1 */
 	{ 0x58, 0, 0 },				/* FSR */
 	{ 0x618, 0, 0 },			/* TLBIALL */
-	{ 0x008, 0, 0 }				/* RESUME */
+	{ 0x008, 0, 0 },			/* RESUME */
+	{ 0, 0, 0 },				/* TLBLKCR */
+	{ 0, 0, 0 },				/* V2PUR */
+	{ 0x68, 0, 0 },				/* FSYNR0 */
+	{ 0x6C, 0, 0 }				/* FSYNR1 */
 };
 
 struct remote_iommu_petersons_spinlock kgsl_iommu_sync_lock_vars;
@@ -118,6 +124,7 @@
 	unsigned int gpuaddr;
 	unsigned int size;
 	unsigned int flags;
+	unsigned int priv;
 	pid_t pid;
 };
 
@@ -146,7 +153,8 @@
 		if (entry->memdesc.gpuaddr > ret->gpuaddr) {
 			ret->gpuaddr = entry->memdesc.gpuaddr;
 			ret->size = entry->memdesc.size;
-			ret->flags = entry->flags;
+			ret->flags = entry->memdesc.flags;
+			ret->priv = entry->memdesc.priv;
 			ret->pid = priv->pid;
 		}
 
@@ -179,7 +187,8 @@
 		if (entry->memdesc.gpuaddr < ret->gpuaddr) {
 			ret->gpuaddr = entry->memdesc.gpuaddr;
 			ret->size = entry->memdesc.size;
-			ret->flags = entry->flags;
+			ret->flags = entry->memdesc.flags;
+			ret->priv = entry->memdesc.priv;
 			ret->pid = priv->pid;
 		}
 
@@ -224,9 +233,10 @@
 	kgsl_get_memory_usage(name, sizeof(name) - 1, entry->flags);
 
 	KGSL_LOG_DUMP(device,
-		"[%8.8X - %8.8X] (pid = %d) (%s)\n",
+		"[%8.8X - %8.8X] %s (pid = %d) (%s)\n",
 		entry->gpuaddr,
 		entry->gpuaddr + entry->size,
+		entry->priv & KGSL_MEMDESC_GUARD_PAGE ? "(+guard)" : "",
 		entry->pid, name);
 }
 
@@ -275,6 +285,8 @@
 	unsigned int pid;
 
 	struct _mem_entry prev, next;
+	unsigned int fsynr0, fsynr1;
+	int write;
 
 	ret = get_iommu_unit(dev, &mmu, &iommu_unit);
 	if (ret)
@@ -292,12 +304,25 @@
 
 	fsr = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit,
 		iommu_dev->ctx_id, FSR);
+	fsynr0 = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit,
+		iommu_dev->ctx_id, FSYNR0);
+	fsynr1 = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit,
+		iommu_dev->ctx_id, FSYNR1);
+
+	if (msm_soc_version_supports_iommu_v0())
+		write = ((fsynr1 & (KGSL_IOMMU_FSYNR1_AWRITE_MASK <<
+			KGSL_IOMMU_FSYNR1_AWRITE_SHIFT)) ? 1 : 0);
+	else
+		write = ((fsynr0 & (KGSL_IOMMU_V1_FSYNR0_WNR_MASK <<
+			KGSL_IOMMU_V1_FSYNR0_WNR_SHIFT)) ? 1 : 0);
 
 	pid = kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase);
 	KGSL_MEM_CRIT(iommu_dev->kgsldev,
 		"GPU PAGE FAULT: addr = %lX pid = %d\n", addr, pid);
-	KGSL_MEM_CRIT(iommu_dev->kgsldev, "context = %d FSR = %X\n",
-		iommu_dev->ctx_id, fsr);
+	KGSL_MEM_CRIT(iommu_dev->kgsldev,
+		"context = %d FSR = %X FSYNR0 = %X FSYNR1 = %X(%s fault)\n",
+		iommu_dev->ctx_id, fsr, fsynr0, fsynr1,
+		write ? "write" : "read");
 
 	_check_if_freed(iommu_dev, addr, pid);
 
@@ -321,7 +346,8 @@
 	iommu_dev->fault = 1;
 
 	trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
-			kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase), 0);
+			kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase),
+			write ? "write" : "read");
 
 	/*
 	 * We do not want the h/w to resume fetching data from an iommu unit
@@ -1118,16 +1144,14 @@
 
 	for (i = 0; i < iommu->unit_count; i++) {
 		status = kgsl_mmu_map_global(pt,
-				&(iommu->iommu_units[i].reg_map),
-				GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+				&(iommu->iommu_units[i].reg_map));
 		if (status)
 			goto err;
 	}
 
 	/* Map Lock variables to GPU pagetable */
 	if (iommu->sync_lock_initialized) {
-		status = kgsl_mmu_map_global(pt, &iommu->sync_lock_desc,
-				GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+		status = kgsl_mmu_map_global(pt, &iommu->sync_lock_desc);
 		if (status)
 			goto err;
 	}
@@ -1499,25 +1523,39 @@
 	unsigned int iommu_virt_addr;
 	struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt;
 	int size = kgsl_sg_size(memdesc->sg, memdesc->sglen);
-	unsigned int iommu_flags = IOMMU_READ;
 
 	BUG_ON(NULL == iommu_pt);
 
-	if (protflags & GSL_PT_PAGE_WV)
-		iommu_flags |= IOMMU_WRITE;
+	/* if there's a guard page, we'll map it read only below */
+	if ((protflags & IOMMU_WRITE) && kgsl_memdesc_has_guard_page(memdesc))
+			size -= PAGE_SIZE;
 
 	iommu_virt_addr = memdesc->gpuaddr;
 
 	ret = iommu_map_range(iommu_pt->domain, iommu_virt_addr, memdesc->sg,
-				size, iommu_flags);
+				size, protflags);
 	if (ret) {
-		KGSL_CORE_ERR("iommu_map_range(%p, %x, %p, %d, %d) "
-				"failed with err: %d\n", iommu_pt->domain,
-				iommu_virt_addr, memdesc->sg, size,
-				iommu_flags, ret);
+		KGSL_CORE_ERR("iommu_map_range(%p, %x, %p, %d, %x) err: %d\n",
+			iommu_pt->domain, iommu_virt_addr, memdesc->sg, size,
+			protflags, ret);
 		return ret;
 	}
+	if ((protflags & IOMMU_WRITE) && kgsl_memdesc_has_guard_page(memdesc)) {
+		struct scatterlist *sg = &memdesc->sg[memdesc->sglen - 1];
 
+		ret = iommu_map(iommu_pt->domain, iommu_virt_addr + size,
+				kgsl_get_sg_pa(sg), PAGE_SIZE,
+				protflags & ~IOMMU_WRITE);
+		if (ret) {
+			KGSL_CORE_ERR("iommu_map(%p, %x, %x, %x) err: %d\n",
+				iommu_pt->domain, iommu_virt_addr + size,
+				kgsl_get_sg_pa(sg), protflags & ~IOMMU_WRITE,
+				ret);
+			/* cleanup the partial mapping */
+			iommu_unmap_range(iommu_pt->domain, iommu_virt_addr,
+					  size);
+		}
+	}
 	return ret;
 }
 
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
index bf40113..c09bc4b 100644
--- a/drivers/gpu/msm/kgsl_iommu.h
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -19,7 +19,7 @@
 #define KGSL_IOMMU_CTX_OFFSET_V1	0x8000
 #define KGSL_IOMMU_CTX_SHIFT		12
 
-/* TLBLKCR feilds */
+/* TLBLKCR fields */
 #define KGSL_IOMMU_TLBLKCR_LKE_MASK		0x00000001
 #define KGSL_IOMMU_TLBLKCR_LKE_SHIFT		0
 #define KGSL_IOMMU_TLBLKCR_TLBIALLCFG_MASK	0x00000001
@@ -33,12 +33,19 @@
 #define KGSL_IOMMU_TLBLKCR_VICTIM_MASK		0x000000FF
 #define KGSL_IOMMU_TLBLKCR_VICTIM_SHIFT		16
 
-/* V2PXX feilds */
+/* V2PXX fields */
 #define KGSL_IOMMU_V2PXX_INDEX_MASK		0x000000FF
 #define KGSL_IOMMU_V2PXX_INDEX_SHIFT		0
 #define KGSL_IOMMU_V2PXX_VA_MASK		0x000FFFFF
 #define KGSL_IOMMU_V2PXX_VA_SHIFT		12
 
+/* FSYNR1 V0 fields */
+#define KGSL_IOMMU_FSYNR1_AWRITE_MASK		0x00000001
+#define KGSL_IOMMU_FSYNR1_AWRITE_SHIFT		8
+/* FSYNR0 V1 fields */
+#define KGSL_IOMMU_V1_FSYNR0_WNR_MASK		0x00000001
+#define KGSL_IOMMU_V1_FSYNR0_WNR_SHIFT		4
+
 enum kgsl_iommu_reg_map {
 	KGSL_IOMMU_GLOBAL_BASE = 0,
 	KGSL_IOMMU_CTX_TTBR0,
@@ -48,6 +55,8 @@
 	KGSL_IOMMU_CTX_RESUME,
 	KGSL_IOMMU_CTX_TLBLKCR,
 	KGSL_IOMMU_CTX_V2PUR,
+	KGSL_IOMMU_CTX_FSYNR0,
+	KGSL_IOMMU_CTX_FSYNR1,
 	KGSL_IOMMU_REG_MAX
 };
 
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index f71cf8c..83cf83d 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -580,13 +580,13 @@
 
 int
 kgsl_mmu_map(struct kgsl_pagetable *pagetable,
-				struct kgsl_memdesc *memdesc,
-				unsigned int protflags)
+				struct kgsl_memdesc *memdesc)
 {
 	int ret;
 	struct gen_pool *pool = NULL;
 	int size;
 	int page_align = ilog2(PAGE_SIZE);
+	unsigned int protflags = kgsl_memdesc_protflags(memdesc);
 
 	if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
 		if (memdesc->sglen == 1) {
@@ -738,7 +738,7 @@
 EXPORT_SYMBOL(kgsl_mmu_unmap);
 
 int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable,
-			struct kgsl_memdesc *memdesc, unsigned int protflags)
+			struct kgsl_memdesc *memdesc)
 {
 	int result = -EINVAL;
 	unsigned int gpuaddr = 0;
@@ -750,11 +750,10 @@
 	/* Not all global mappings are needed for all MMU types */
 	if (!memdesc->size)
 		return 0;
-
 	gpuaddr = memdesc->gpuaddr;
 	memdesc->priv |= KGSL_MEMDESC_GLOBAL;
 
-	result = kgsl_mmu_map(pagetable, memdesc, protflags);
+	result = kgsl_mmu_map(pagetable, memdesc);
 	if (result)
 		goto error;
 
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 2b33baf..0458a13 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -201,10 +201,9 @@
 int kgsl_mmu_start(struct kgsl_device *device);
 int kgsl_mmu_close(struct kgsl_device *device);
 int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
-		 struct kgsl_memdesc *memdesc,
-		 unsigned int protflags);
+		 struct kgsl_memdesc *memdesc);
 int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable,
-			struct kgsl_memdesc *memdesc, unsigned int protflags);
+			struct kgsl_memdesc *memdesc);
 int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
 		    struct kgsl_memdesc *memdesc);
 unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index 27b9151..279490f 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -19,6 +19,7 @@
 #include "kgsl_mmu.h"
 #include <linux/slab.h>
 #include <linux/kmemleak.h>
+#include <linux/iommu.h>
 
 #include "kgsl_log.h"
 
@@ -195,15 +196,24 @@
 /*
  * kgsl_memdesc_protflags - get mmu protection flags
  * @memdesc - the memdesc
- * Returns a mask of GSL_PT_PAGE* values based on the
- * memdesc flags.
+ * Returns a mask of GSL_PT_PAGE* or IOMMU* values based
+ * on the memdesc flags.
  */
 static inline unsigned int
 kgsl_memdesc_protflags(const struct kgsl_memdesc *memdesc)
 {
-	unsigned int protflags = GSL_PT_PAGE_RV;
-	if (!(memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY))
-		protflags |= GSL_PT_PAGE_WV;
+	unsigned int protflags = 0;
+	enum kgsl_mmutype mmutype = kgsl_mmu_get_mmutype();
+
+	if (mmutype == KGSL_MMU_TYPE_GPU) {
+		protflags = GSL_PT_PAGE_RV;
+		if (!(memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY))
+			protflags |= GSL_PT_PAGE_WV;
+	} else if (mmutype == KGSL_MMU_TYPE_IOMMU) {
+		protflags = IOMMU_READ;
+		if (!(memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY))
+			protflags |= IOMMU_WRITE;
+	}
 	return protflags;
 }
 
@@ -248,8 +258,7 @@
 	ret = kgsl_sharedmem_page_alloc(memdesc, pagetable, size);
 	if (ret)
 		return ret;
-	ret = kgsl_mmu_map(pagetable, memdesc,
-			   kgsl_memdesc_protflags(memdesc));
+	ret = kgsl_mmu_map(pagetable, memdesc);
 	if (ret)
 		kgsl_sharedmem_free(memdesc);
 	return ret;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 0935f64..c4647a1 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -283,7 +283,7 @@
 {
 	list_del(&obj->node);
 
-	obj->entry->flags &= ~KGSL_MEM_ENTRY_FROZEN;
+	obj->entry->memdesc.priv &= ~KGSL_MEMDESC_FROZEN;
 	kgsl_mem_entry_put(obj->entry);
 
 	kfree(obj);
@@ -416,10 +416,10 @@
 	 * 0 so it doesn't get counted twice
 	 */
 
-	if (entry->flags & KGSL_MEM_ENTRY_FROZEN)
+	if (entry->memdesc.priv & KGSL_MEMDESC_FROZEN)
 		return 0;
 
-	entry->flags |= KGSL_MEM_ENTRY_FROZEN;
+	entry->memdesc.priv |= KGSL_MEMDESC_FROZEN;
 
 	return entry->memdesc.size;
 }
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index e578b0e..f0410d6 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -244,20 +244,17 @@
 	int result = 0;
 	struct z180_device *z180_dev = Z180_DEVICE(device);
 
-	result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory,
-				     GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+	result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory);
 
 	if (result)
 		goto error;
 
-	result = kgsl_mmu_map_global(pagetable, &device->memstore,
-				     GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+	result = kgsl_mmu_map_global(pagetable, &device->memstore);
 	if (result)
 		goto error_unmap_dummy;
 
 	result = kgsl_mmu_map_global(pagetable,
-				     &z180_dev->ringbuffer.cmdbufdesc,
-				     GSL_PT_PAGE_RV);
+				     &z180_dev->ringbuffer.cmdbufdesc);
 	if (result)
 		goto error_unmap_memstore;
 	/*
@@ -498,6 +495,7 @@
 	struct z180_device *z180_dev = Z180_DEVICE(device);
 	memset(&z180_dev->ringbuffer, 0, sizeof(struct z180_ringbuffer));
 	z180_dev->ringbuffer.prevctx = Z180_INVALID_CONTEXT;
+	z180_dev->ringbuffer.cmdbufdesc.flags = KGSL_MEMFLAGS_GPUREADONLY;
 	return kgsl_allocate_contiguous(&z180_dev->ringbuffer.cmdbufdesc,
 		Z180_RB_SIZE);
 }
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 8c30b6c..1b7ecf0 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -164,6 +164,11 @@
 	}
 
 	qinfo =	(struct vidc_iface_q_info *) info;
+	if (!qinfo || !qinfo->q_array.align_virtual_addr) {
+		dprintk(VIDC_WARN, "Queues have already been freed\n");
+		return -EINVAL;
+	}
+
 	venus_hfi_sim_modify_cmd_packet(packet);
 
 	queue = (struct hfi_queue_header *) qinfo->q_hdr;
@@ -282,6 +287,10 @@
 	}
 
 	qinfo =	(struct vidc_iface_q_info *) info;
+	if (!qinfo || !qinfo->q_array.align_virtual_addr) {
+		dprintk(VIDC_WARN, "Queues have already been freed\n");
+		return -EINVAL;
+	}
 	queue = (struct hfi_queue_header *) qinfo->q_hdr;
 
 	if (!queue) {
@@ -634,6 +643,8 @@
 	int num_entries = sizeof(venus_qdss_entries)/(2 * sizeof(u32));
 	int domain, partition;
 
+	mutex_lock(&device->write_lock);
+	mutex_lock(&device->read_lock);
 	if (device->qdss.mem_data) {
 		qdss = (struct hfi_mem_map_table *)
 			device->qdss.align_virtual_addr;
@@ -674,6 +685,8 @@
 
 	msm_smem_delete_client(device->hal_client);
 	device->hal_client = NULL;
+	mutex_unlock(&device->read_lock);
+	mutex_unlock(&device->write_lock);
 }
 static int venus_hfi_get_qdss_iommu_virtual_addr(struct hfi_mem_map *mem_map,
 						int domain, int partition)
@@ -937,7 +950,6 @@
 	}
 
 	dev->intr_status = 0;
-	enable_irq(dev->hal_data->irq);
 	INIT_LIST_HEAD(&dev->sess_head);
 	mutex_init(&dev->read_lock);
 	mutex_init(&dev->write_lock);
@@ -966,6 +978,7 @@
 		rc = -EEXIST;
 		goto err_core_init;
 	}
+	enable_irq(dev->hal_data->irq);
 	venus_hfi_write_register(dev->hal_data->register_base_addr,
 		VIDC_CTRL_INIT, 0x1, 0);
 	rc = venus_hfi_core_start_cpu(dev);
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 46b4651..88e8d43 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -91,6 +91,16 @@
 	  in the kernel log along with the PMIC option status. The PMIC
 	  type is mapped to a Qualcomm chip part number and logged as well.
 
+config QPNP_COINCELL
+	tristate "Qualcomm QPNP coincell charger support"
+	depends on SPMI && OF_SPMI
+	help
+	  This driver supports the QPNP coincell peripheral found inside of
+	  Qualcomm QPNP PMIC devices.  The coincell charger provides a means to
+	  charge a coincell battery or backup capacitor which is used to
+	  maintain PMIC register state when the main battery is removed from the
+	  mobile device.
+
 config IPA
 	tristate "IPA support"
 	depends on SPS
diff --git a/drivers/platform/msm/Makefile b/drivers/platform/msm/Makefile
index 6b9c5ad..efb78e5 100644
--- a/drivers/platform/msm/Makefile
+++ b/drivers/platform/msm/Makefile
@@ -9,6 +9,7 @@
 obj-$(CONFIG_QPNP_POWER_ON) += qpnp-power-on.o
 obj-$(CONFIG_QPNP_VIBRATOR) += qpnp-vibrator.o
 obj-$(CONFIG_QPNP_CLKDIV) += qpnp-clkdiv.o
+obj-$(CONFIG_QPNP_COINCELL) += qpnp-coincell.o
 obj-$(CONFIG_MSM_AVTIMER) += avtimer.o
 obj-$(CONFIG_SSM) += ssm.o
 obj-$(CONFIG_QPNP_REVID) += qpnp-revid.o
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index 1142094..42a0016 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -1919,22 +1919,26 @@
 	ipa_ctx->aggregation_byte_limit = 1;
 	ipa_ctx->aggregation_time_limit = 0;
 
-	/* Initialize IPA RM (resource manager) */
-	result = ipa_rm_initialize();
-	if (result) {
-		IPAERR(":cdev_add err=%d\n", -result);
-		result = -ENODEV;
-		goto fail_ipa_rm_init;
+	if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_PCIE) {
+		/* Initialize IPA RM (resource manager) */
+		result = ipa_rm_initialize();
+		if (result) {
+			IPAERR(":cdev_add err=%d\n", -result);
+			result = -ENODEV;
+			goto fail_ipa_rm_init;
+		}
 	}
 
-	a2_mux_init();
+	if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_NORMAL) {
+		a2_mux_init();
 
-	/* Initialize the tethering bridge driver */
-	result = teth_bridge_driver_init();
-	if (result) {
-		IPAERR(":teth_bridge_driver_init() failed\n");
-		result = -ENODEV;
-		goto fail_cdev_add;
+		/* Initialize the tethering bridge driver */
+		result = teth_bridge_driver_init();
+		if (result) {
+			IPAERR(":teth_bridge_driver_init() failed\n");
+			result = -ENODEV;
+			goto fail_cdev_add;
+		}
 	}
 
 	/* gate IPA clocks */
diff --git a/drivers/platform/msm/ipa/teth_bridge.c b/drivers/platform/msm/ipa/teth_bridge.c
index 76e2eee..29253cd 100644
--- a/drivers/platform/msm/ipa/teth_bridge.c
+++ b/drivers/platform/msm/ipa/teth_bridge.c
@@ -69,6 +69,11 @@
 	bool device_mac_addr_known;
 };
 
+struct stats {
+	u64 a2_to_usb_num_sw_tx_packets;
+	u64 usb_to_a2_num_sw_tx_packets;
+};
+
 struct teth_bridge_ctx {
 	struct class *class;
 	dev_t dev_num;
@@ -90,6 +95,7 @@
 	struct work_struct comp_hw_bridge_work;
 	bool comp_hw_bridge_in_progress;
 	struct teth_aggr_capabilities *aggr_caps;
+	struct stats stats;
 };
 
 static struct teth_bridge_ctx *teth_ctx;
@@ -806,6 +812,7 @@
 				&teth_ctx->mac_addresses.device_mac_addr_known);
 
 		/* Send the packet to A2, using a2_service driver API */
+		teth_ctx->stats.usb_to_a2_num_sw_tx_packets++;
 		res = a2_mux_write(A2_MUX_TETHERED_0, skb);
 		if (res) {
 			TETH_ERR("Packet send failure, dropping packet !\n");
@@ -843,6 +850,7 @@
 				mac_addresses.host_pc_mac_addr_known);
 
 		/* Send the packet to USB */
+		teth_ctx->stats.a2_to_usb_num_sw_tx_packets++;
 		res = ipa_tx_dp(IPA_CLIENT_USB_CONS, skb, NULL);
 		if (res) {
 			TETH_ERR("Packet send failure, dropping packet !\n");
@@ -1216,6 +1224,8 @@
 static struct dentry *dfile_link_protocol;
 static struct dentry *dfile_get_aggr_params;
 static struct dentry *dfile_set_aggr_protocol;
+static struct dentry *dfile_stats;
+static struct dentry *dfile_is_hw_bridge_complete;
 
 static ssize_t teth_debugfs_read_link_protocol(struct file *file,
 					       char __user *ubuf,
@@ -1351,6 +1361,43 @@
 	return count;
 }
 
+static ssize_t teth_debugfs_stats(struct file *file,
+				  char __user *ubuf,
+				  size_t count,
+				  loff_t *ppos)
+{
+	int nbytes = 0;
+
+	nbytes += scnprintf(&dbg_buff[nbytes],
+			    TETH_MAX_MSG_LEN - nbytes,
+			   "USB to A2 SW Tx packets: %lld\n",
+			    teth_ctx->stats.usb_to_a2_num_sw_tx_packets);
+	nbytes += scnprintf(&dbg_buff[nbytes],
+			    TETH_MAX_MSG_LEN - nbytes,
+			   "A2 to USB SW Tx packets: %lld\n",
+			    teth_ctx->stats.a2_to_usb_num_sw_tx_packets);
+	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
+}
+
+static ssize_t teth_debugfs_hw_bridge_status(struct file *file,
+					     char __user *ubuf,
+					     size_t count,
+					     loff_t *ppos)
+{
+	int nbytes = 0;
+
+	if (teth_ctx->is_hw_bridge_complete)
+		nbytes += scnprintf(&dbg_buff[nbytes],
+				    TETH_MAX_MSG_LEN - nbytes,
+				   "HW bridge is in use.\n");
+	else
+		nbytes += scnprintf(&dbg_buff[nbytes],
+				    TETH_MAX_MSG_LEN - nbytes,
+				   "SW bridge is in use. HW bridge not complete yet.\n");
+
+	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
+}
+
 const struct file_operations teth_link_protocol_ops = {
 	.read = teth_debugfs_read_link_protocol,
 	.write = teth_debugfs_write_link_protocol,
@@ -1364,6 +1411,14 @@
 	.write = teth_debugfs_set_aggr_protocol,
 };
 
+const struct file_operations teth_stats_ops = {
+	.read = teth_debugfs_stats,
+};
+
+const struct file_operations teth_hw_bridge_status_ops = {
+	.read = teth_debugfs_hw_bridge_status,
+};
+
 void teth_debugfs_init(void)
 {
 	const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH;
@@ -1400,6 +1455,23 @@
 		goto fail;
 	}
 
+	dfile_stats =
+		debugfs_create_file("stats", read_only_mode, dent,
+				    0, &teth_stats_ops);
+	if (!dfile_stats || IS_ERR(dfile_stats)) {
+		IPAERR("fail to create file stats\n");
+		goto fail;
+	}
+
+	dfile_is_hw_bridge_complete =
+		debugfs_create_file("is_hw_bridge_complete", read_only_mode,
+				    dent, 0, &teth_hw_bridge_status_ops);
+	if (!dfile_is_hw_bridge_complete ||
+	    IS_ERR(dfile_is_hw_bridge_complete)) {
+		IPAERR("fail to create file is_hw_bridge_complete\n");
+		goto fail;
+	}
+
 	return;
 fail:
 	debugfs_remove_recursive(dent);
diff --git a/drivers/platform/msm/qpnp-coincell.c b/drivers/platform/msm/qpnp-coincell.c
new file mode 100644
index 0000000..e08fd7d
--- /dev/null
+++ b/drivers/platform/msm/qpnp-coincell.c
@@ -0,0 +1,266 @@
+/* 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/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/spmi.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#define QPNP_COINCELL_DRIVER_NAME "qcom,qpnp-coincell"
+
+struct qpnp_coincell {
+	struct spmi_device	*spmi_dev;
+	u16			base_addr;
+};
+
+#define QPNP_COINCELL_REG_TYPE		0x04
+#define QPNP_COINCELL_REG_SUBTYPE	0x05
+#define QPNP_COINCELL_REG_RSET		0x44
+#define QPNP_COINCELL_REG_VSET		0x45
+#define QPNP_COINCELL_REG_ENABLE	0x46
+
+#define QPNP_COINCELL_TYPE		0x02
+#define QPNP_COINCELL_SUBTYPE		0x20
+#define QPNP_COINCELL_ENABLE		0x80
+#define QPNP_COINCELL_DISABLE		0x00
+
+static const int qpnp_rset_map[] = {2100, 1700, 1200, 800};
+static const int qpnp_vset_map[] = {2500, 3200, 3100, 3000};
+
+static int qpnp_coincell_set_resistance(struct qpnp_coincell *chip, int rset)
+{
+	int i, rc;
+	u8 reg;
+
+	for (i = 0; i < ARRAY_SIZE(qpnp_rset_map); i++)
+		if (rset == qpnp_rset_map[i])
+			break;
+
+	if (i >= ARRAY_SIZE(qpnp_rset_map)) {
+		pr_err("invalid rset=%d value\n", rset);
+		return -EINVAL;
+	}
+
+	reg = i;
+	rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+		chip->base_addr + QPNP_COINCELL_REG_RSET, &reg, 1);
+	if (rc)
+		dev_err(&chip->spmi_dev->dev, "%s: could not write to RSET register, rc=%d\n",
+			__func__, rc);
+
+	return rc;
+}
+
+static int qpnp_coincell_set_voltage(struct qpnp_coincell *chip, int vset)
+{
+	int i, rc;
+	u8 reg;
+
+	for (i = 0; i < ARRAY_SIZE(qpnp_vset_map); i++)
+		if (vset == qpnp_vset_map[i])
+			break;
+
+	if (i >= ARRAY_SIZE(qpnp_vset_map)) {
+		pr_err("invalid vset=%d value\n", vset);
+		return -EINVAL;
+	}
+
+	reg = i;
+	rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+		chip->base_addr + QPNP_COINCELL_REG_VSET, &reg, 1);
+	if (rc)
+		dev_err(&chip->spmi_dev->dev, "%s: could not write to VSET register, rc=%d\n",
+			__func__, rc);
+
+	return rc;
+}
+
+static int qpnp_coincell_set_charge(struct qpnp_coincell *chip, bool enabled)
+{
+	int rc;
+	u8 reg;
+
+	reg = enabled ? QPNP_COINCELL_ENABLE : QPNP_COINCELL_DISABLE;
+	rc = spmi_ext_register_writel(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+		chip->base_addr + QPNP_COINCELL_REG_ENABLE, &reg, 1);
+	if (rc)
+		dev_err(&chip->spmi_dev->dev, "%s: could not write to ENABLE register, rc=%d\n",
+			__func__, rc);
+
+	return rc;
+}
+
+static void qpnp_coincell_charger_show_state(struct qpnp_coincell *chip)
+{
+	int rc, rset, vset, temp;
+	bool enabled;
+	u8 reg[QPNP_COINCELL_REG_ENABLE - QPNP_COINCELL_REG_RSET + 1];
+
+	rc = spmi_ext_register_readl(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+		chip->base_addr + QPNP_COINCELL_REG_RSET, reg, ARRAY_SIZE(reg));
+	if (rc) {
+		dev_err(&chip->spmi_dev->dev, "%s: could not read RSET register, rc=%d\n",
+			__func__, rc);
+		return;
+	}
+
+	temp = reg[QPNP_COINCELL_REG_RSET - QPNP_COINCELL_REG_RSET];
+	if (temp >= ARRAY_SIZE(qpnp_rset_map)) {
+		dev_err(&chip->spmi_dev->dev, "unknown RSET=0x%02X register value\n",
+			temp);
+		return;
+	}
+	rset = qpnp_rset_map[temp];
+
+	temp = reg[QPNP_COINCELL_REG_VSET - QPNP_COINCELL_REG_RSET];
+	if (temp >= ARRAY_SIZE(qpnp_vset_map)) {
+		dev_err(&chip->spmi_dev->dev, "unknown VSET=0x%02X register value\n",
+			temp);
+		return;
+	}
+	vset = qpnp_vset_map[temp];
+
+	temp = reg[QPNP_COINCELL_REG_ENABLE - QPNP_COINCELL_REG_RSET];
+	enabled = temp & QPNP_COINCELL_ENABLE;
+
+	pr_info("enabled=%c, voltage=%d mV, resistance=%d ohm\n",
+		(enabled ? 'Y' : 'N'), vset, rset);
+}
+
+static int qpnp_coincell_check_type(struct qpnp_coincell *chip)
+{
+	int rc;
+	u8 type[2];
+
+	rc = spmi_ext_register_readl(chip->spmi_dev->ctrl, chip->spmi_dev->sid,
+		chip->base_addr + QPNP_COINCELL_REG_TYPE, type, 2);
+	if (rc) {
+		dev_err(&chip->spmi_dev->dev, "%s: could not read type register, rc=%d\n",
+			__func__, rc);
+		return rc;
+	}
+
+	if (type[0] != QPNP_COINCELL_TYPE || type[1] != QPNP_COINCELL_SUBTYPE) {
+		dev_err(&chip->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_coincell_probe(struct spmi_device *spmi)
+{
+	struct device_node *node = spmi->dev.of_node;
+	struct qpnp_coincell *chip;
+	struct resource *res;
+	u32 temp;
+	int rc = 0;
+
+	if (!node) {
+		dev_err(&spmi->dev, "%s: device node missing\n", __func__);
+		return -ENODEV;
+	}
+
+	chip = devm_kzalloc(&spmi->dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip) {
+		dev_err(&spmi->dev, "%s: cannot allocate qpnp_coincell\n",
+			__func__);
+		return -ENOMEM;
+	}
+	chip->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;
+	}
+	chip->base_addr = res->start;
+
+	rc = qpnp_coincell_check_type(chip);
+	if (rc)
+		return rc;
+
+	rc = of_property_read_u32(node, "qcom,rset-ohms", &temp);
+	if (!rc) {
+		rc = qpnp_coincell_set_resistance(chip, temp);
+		if (rc)
+			return rc;
+	}
+
+	rc = of_property_read_u32(node, "qcom,vset-millivolts", &temp);
+	if (!rc) {
+		rc = qpnp_coincell_set_voltage(chip, temp);
+		if (rc)
+			return rc;
+	}
+
+	rc = of_property_read_u32(node, "qcom,charge-enable", &temp);
+	if (!rc) {
+		rc = qpnp_coincell_set_charge(chip, temp);
+		if (rc)
+			return rc;
+	}
+
+	qpnp_coincell_charger_show_state(chip);
+
+	return 0;
+}
+
+static int __devexit qpnp_coincell_remove(struct spmi_device *spmi)
+{
+	return 0;
+}
+
+static struct of_device_id qpnp_coincell_match_table[] = {
+	{ .compatible = QPNP_COINCELL_DRIVER_NAME, },
+	{}
+};
+
+static const struct spmi_device_id qpnp_coincell_id[] = {
+	{ QPNP_COINCELL_DRIVER_NAME, 0 },
+	{}
+};
+MODULE_DEVICE_TABLE(spmi, qpnp_coincell_id);
+
+static struct spmi_driver qpnp_coincell_driver = {
+	.driver	= {
+		.name		= QPNP_COINCELL_DRIVER_NAME,
+		.of_match_table	= qpnp_coincell_match_table,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= qpnp_coincell_probe,
+	.remove		= __devexit_p(qpnp_coincell_remove),
+	.id_table	= qpnp_coincell_id,
+};
+
+static int __init qpnp_coincell_init(void)
+{
+	return spmi_driver_register(&qpnp_coincell_driver);
+}
+
+static void __exit qpnp_coincell_exit(void)
+{
+	spmi_driver_unregister(&qpnp_coincell_driver);
+}
+
+MODULE_DESCRIPTION("QPNP PMIC coincell charger driver");
+MODULE_LICENSE("GPL v2");
+
+module_init(qpnp_coincell_init);
+module_exit(qpnp_coincell_exit);
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index bc2e2ae..0d161b7 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -432,6 +432,7 @@
 	tristate "QPNP Charger driver"
 	depends on SPMI
 	depends on OF_SPMI
+	depends on THERMAL_QPNP_ADC_TM
 	help
 	  Say Y here to enable the switch mode battery charger
 	  and boost device which supports USB detection and charging. The driver
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 7833afa..8789b19 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -171,17 +171,27 @@
  * @boost_base:			boost peripheral base address
  * @misc_base:			misc peripheral base address
  * @freq_base:			freq peripheral base address
+ * @bat_is_cool:		indicates that battery is cool
+ * @bat_is_warm:		indicates that battery is warm
  * @chg_done:			indicates that charging is completed
  * @usb_present:		present status of usb
  * @dc_present:			present status of dc
+ * @batt_present:		present status of battery
  * @use_default_batt_values:	flag to report default battery properties
  * @max_voltage_mv:		the max volts the batt should be charged up to
  * @min_voltage_mv:		min battery voltage before turning the FET on
- * @resume_voltage_mv:		voltage at which the battery resumes charging
+ * @max_bat_chg_current:	maximum battery charge current in mA
+ * @warm_bat_chg_ma:	warm battery maximum charge current in mA
+ * @cool_bat_chg_ma:	cool battery maximum charge current in mA
+ * @warm_bat_mv:		warm temperature battery target voltage
+ * @cool_bat_mv:		cool temperature battery target voltage
+ * @resume_delta_mv:		voltage delta at which battery resumes charging
  * @term_current:		the charging based term current
  * @safe_current:		battery safety current setting
  * @maxinput_usb_ma:		Maximum Input current USB
  * @maxinput_dc_ma:		Maximum Input current DC
+ * @warm_bat_degc		Warm battery temperature in degree Celsius
+ * @cool_bat_degc		Cool battery temperature in degree Celsius
  * @revision:			PMIC revision
  * @thermal_levels		amount of thermal mitigation levels
  * @thermal_mitigation		thermal mitigation level values
@@ -208,20 +218,32 @@
 	unsigned int			usbin_valid_irq;
 	unsigned int			dcin_valid_irq;
 	unsigned int			chg_done_irq;
+	unsigned int			chg_fastchg_irq;
+	unsigned int			chg_trklchg_irq;
 	unsigned int			chg_failed_irq;
+	unsigned int			batt_pres_irq;
+	bool				bat_is_cool;
+	bool				bat_is_warm;
 	bool				chg_done;
 	bool				usb_present;
 	bool				dc_present;
+	bool				batt_present;
 	bool				charging_disabled;
 	bool				use_default_batt_values;
 	unsigned int			max_bat_chg_current;
+	unsigned int			warm_bat_chg_ma;
+	unsigned int			cool_bat_chg_ma;
 	unsigned int			safe_voltage_mv;
 	unsigned int			max_voltage_mv;
 	unsigned int			min_voltage_mv;
-	unsigned int			resume_voltage_mv;
+	unsigned int			warm_bat_mv;
+	unsigned int			cool_bat_mv;
+	unsigned int			resume_delta_mv;
 	unsigned int			term_current;
 	unsigned int			maxinput_usb_ma;
 	unsigned int			maxinput_dc_ma;
+	unsigned int			warm_bat_degc;
+	unsigned int			cool_bat_degc;
 	unsigned int			safe_current;
 	unsigned int			revision;
 	unsigned int			thermal_levels;
@@ -232,6 +254,7 @@
 	struct power_supply		*bms_psy;
 	struct power_supply		batt_psy;
 	uint32_t			flags;
+	struct qpnp_adc_tm_btm_param	adc_param;
 };
 
 static struct of_device_id qpnp_charger_match_table[] = {
@@ -323,6 +346,23 @@
 	return (usb_otg_en & USB_OTG_EN_BIT) ? 1 : 0;
 }
 
+static int
+qpnp_chg_is_batt_present(struct qpnp_chg_chip *chip)
+{
+	u8 batt_pres_rt_sts;
+	int rc;
+
+	rc = qpnp_chg_read(chip, &batt_pres_rt_sts,
+				 INT_RT_STS(chip->bat_if_base), 1);
+	if (rc) {
+		pr_err("spmi read failed: addr=%03X, rc=%d\n",
+				INT_RT_STS(chip->bat_if_base), rc);
+		return rc;
+	}
+
+	return (batt_pres_rt_sts & BATT_PRES_IRQ) ? 1 : 0;
+}
+
 #define USB_VALID_BIT	BIT(7)
 static int
 qpnp_chg_is_usb_chg_plugged_in(struct qpnp_chg_chip *chip)
@@ -493,6 +533,23 @@
 }
 
 static irqreturn_t
+qpnp_chg_bat_if_batt_pres_irq_handler(int irq, void *_chip)
+{
+	struct qpnp_chg_chip *chip = _chip;
+	int batt_present;
+
+	batt_present = qpnp_chg_is_batt_present(chip);
+	pr_debug("batt-pres triggered: %d\n", batt_present);
+
+	if (chip->batt_present ^ batt_present) {
+		chip->batt_present = batt_present;
+		power_supply_changed(&chip->batt_psy);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
 qpnp_chg_dc_dcin_valid_irq_handler(int irq, void *_chip)
 {
 	struct qpnp_chg_chip *chip = _chip;
@@ -527,12 +584,47 @@
 }
 
 static irqreturn_t
-qpnp_chg_chgr_chg_done_irq_handler(int irq, void *_chip)
+qpnp_chg_chgr_chg_trklchg_irq_handler(int irq, void *_chip)
 {
 	struct qpnp_chg_chip *chip = _chip;
 
+	pr_debug("TRKL IRQ triggered\n");
+
+	chip->chg_done = false;
+	power_supply_changed(&chip->batt_psy);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+qpnp_chg_chgr_chg_fastchg_irq_handler(int irq, void *_chip)
+{
+	struct qpnp_chg_chip *chip = _chip;
+
+	pr_debug("FAST_CHG IRQ triggered\n");
+
+	chip->chg_done = false;
+	power_supply_changed(&chip->batt_psy);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+qpnp_chg_chgr_chg_done_irq_handler(int irq, void *_chip)
+{
+	struct qpnp_chg_chip *chip = _chip;
+	u8 chgr_sts;
+	int rc;
+
 	pr_debug("CHG_DONE IRQ triggered\n");
+
+	rc = qpnp_chg_read(chip, &chgr_sts,
+				INT_RT_STS(chip->chgr_base), 1);
+	if (rc)
+		pr_err("failed to read interrupt sts %d\n", rc);
+
 	chip->chg_done = true;
+	power_supply_changed(&chip->batt_psy);
 
 	return IRQ_HANDLED;
 }
@@ -597,8 +689,8 @@
 	return rc;
 }
 
-static
-int switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
+static int
+switch_usb_to_charge_mode(struct qpnp_chg_chip *chip)
 {
 	int rc;
 
@@ -625,8 +717,8 @@
 	return 0;
 }
 
-static
-int switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
+static int
+switch_usb_to_host_mode(struct qpnp_chg_chip *chip)
 {
 	int rc;
 
@@ -791,19 +883,16 @@
 	int rc;
 	u8 chgr_sts;
 
+	if (chip->chg_done)
+		return POWER_SUPPLY_STATUS_FULL;
+
 	rc = qpnp_chg_read(chip, &chgr_sts,
 				INT_RT_STS(chip->chgr_base), 1);
 	if (rc) {
 		pr_err("failed to read interrupt sts %d\n", rc);
-		return POWER_SUPPLY_STATUS_DISCHARGING;
+		return POWER_SUPPLY_CHARGE_TYPE_NONE;
 	}
 
-	pr_debug("chgr sts 0x%x\n", chgr_sts);
-	if (chgr_sts & CHG_DONE_IRQ || chip->chg_done)
-		return POWER_SUPPLY_STATUS_FULL;
-	else
-		chip->chg_done = false;
-
 	if (chgr_sts & TRKL_CHG_ON_IRQ)
 		return POWER_SUPPLY_STATUS_CHARGING;
 	if (chgr_sts & FAST_CHG_ON_IRQ)
@@ -1147,8 +1236,33 @@
 	temp = (voltage - QPNP_CHG_V_MIN_MV) / QPNP_CHG_V_STEP_MV;
 
 	pr_debug("voltage=%d setting %02x\n", voltage, temp);
-	return qpnp_chg_write(chip, &temp,
-		chip->chgr_base + CHGR_VDD_MAX, 1);
+	return qpnp_chg_write(chip, &temp, chip->chgr_base + CHGR_VDD_MAX, 1);
+}
+
+/* JEITA compliance logic */
+static void
+qpnp_chg_set_appropriate_vddmax(struct qpnp_chg_chip *chip)
+{
+	if (chip->bat_is_cool)
+		qpnp_chg_vddmax_set(chip, chip->cool_bat_mv);
+	else if (chip->bat_is_warm)
+		qpnp_chg_vddmax_set(chip, chip->warm_bat_mv);
+	else
+		qpnp_chg_vddmax_set(chip, chip->max_voltage_mv);
+}
+
+static void
+qpnp_chg_set_appropriate_vbatdet(struct qpnp_chg_chip *chip)
+{
+	if (chip->bat_is_cool)
+		qpnp_chg_vbatdet_set(chip, chip->cool_bat_mv
+			- chip->resume_delta_mv);
+	else if (chip->bat_is_warm)
+		qpnp_chg_vbatdet_set(chip, chip->warm_bat_mv
+			- chip->resume_delta_mv);
+	else
+		qpnp_chg_vbatdet_set(chip, chip->max_voltage_mv
+			- chip->resume_delta_mv);
 }
 
 static void
@@ -1156,6 +1270,12 @@
 {
 	unsigned int chg_current = chip->max_bat_chg_current;
 
+	if (chip->bat_is_cool)
+		chg_current = min(chg_current, chip->cool_bat_chg_ma);
+
+	if (chip->bat_is_warm)
+		chg_current = min(chg_current, chip->warm_bat_chg_ma);
+
 	if (chip->therm_lvl_sel != 0 && chip->thermal_mitigation)
 		chg_current = min(chg_current,
 			chip->thermal_mitigation[chip->therm_lvl_sel]);
@@ -1181,6 +1301,58 @@
 	}
 }
 
+#define TEMP_HYSTERISIS_DEGC 2
+static void
+qpnp_chg_adc_notification(enum qpnp_tm_state state, void *ctx)
+{
+	struct qpnp_chg_chip *chip = ctx;
+	bool bat_warm = 0, bat_cool = 0;
+
+	if (state >= ADC_TM_STATE_NUM) {
+		pr_err("invalid notification %d\n", state);
+		return;
+	}
+
+	pr_debug("state = %s\n", state == ADC_TM_HIGH_STATE ? "high" : "low");
+
+	if (state == ADC_TM_HIGH_STATE) {
+		if (!chip->bat_is_warm) {
+			bat_warm = true;
+			bat_cool = false;
+			chip->adc_param.low_temp =
+				chip->warm_bat_degc - TEMP_HYSTERISIS_DEGC;
+		} else if (chip->bat_is_cool) {
+			bat_warm = false;
+			bat_cool = false;
+			chip->adc_param.high_temp = chip->warm_bat_degc;
+		}
+	} else {
+		if (!chip->bat_is_cool) {
+			bat_cool = true;
+			bat_warm = false;
+			chip->adc_param.high_temp =
+				chip->cool_bat_degc + TEMP_HYSTERISIS_DEGC;
+		} else if (chip->bat_is_warm) {
+			bat_cool = false;
+			bat_warm = false;
+			chip->adc_param.low_temp = chip->cool_bat_degc;
+		}
+	}
+
+	if (chip->bat_is_cool ^ bat_cool || chip->bat_is_warm ^ bat_warm) {
+		/* set appropriate voltages and currents */
+		qpnp_chg_set_appropriate_vddmax(chip);
+		qpnp_chg_set_appropriate_battery_current(chip);
+		qpnp_chg_set_appropriate_vbatdet(chip);
+
+		chip->bat_is_cool = bat_cool;
+		chip->bat_is_warm = bat_warm;
+	}
+
+	/* re-arm ADC interrupt */
+	qpnp_adc_tm_btm_configure(&chip->adc_param);
+}
+
 static int
 qpnp_batt_power_set_property(struct power_supply *psy,
 				  enum power_supply_property psp,
@@ -1231,20 +1403,37 @@
 			return -ENXIO;
 		}
 
+		chip->chg_fastchg_irq = spmi_get_irq_byname(chip->spmi,
+						spmi_resource, "fast-chg-on");
+		if (chip->chg_fastchg_irq < 0) {
+			pr_err("Unable to get fast-chg-on irq\n");
+			return -ENXIO;
+		}
+
+		chip->chg_trklchg_irq = spmi_get_irq_byname(chip->spmi,
+						spmi_resource, "trkl-chg-on");
+		if (chip->chg_trklchg_irq < 0) {
+			pr_err("Unable to get trkl-chg-on irq\n");
+			return -ENXIO;
+		}
+
 		chip->chg_failed_irq = spmi_get_irq_byname(chip->spmi,
 						spmi_resource, "chg-failed");
 		if (chip->chg_failed_irq < 0) {
 			pr_err("Unable to get chg_failed irq\n");
 			return -ENXIO;
 		}
+
 		rc |= devm_request_irq(chip->dev, chip->chg_done_irq,
 				qpnp_chg_chgr_chg_done_irq_handler,
-				IRQF_TRIGGER_RISING, "chg_done", chip);
+				IRQF_TRIGGER_RISING,
+				"chg_done", chip);
 		if (rc < 0) {
 			pr_err("Can't request %d chg_done for chg: %d\n",
 						chip->chg_done_irq, rc);
 			return -ENXIO;
 		}
+
 		rc |= devm_request_irq(chip->dev, chip->chg_failed_irq,
 				qpnp_chg_chgr_chg_failed_irq_handler,
 				IRQF_TRIGGER_RISING, "chg_failed", chip);
@@ -1254,6 +1443,26 @@
 			return -ENXIO;
 		}
 
+		rc |= devm_request_irq(chip->dev, chip->chg_fastchg_irq,
+				qpnp_chg_chgr_chg_fastchg_irq_handler,
+				IRQF_TRIGGER_RISING,
+				"fast-chg-on", chip);
+		if (rc < 0) {
+			pr_err("Can't request %d fast-chg-on for chg: %d\n",
+						chip->chg_fastchg_irq, rc);
+			return -ENXIO;
+		}
+
+		rc |= devm_request_irq(chip->dev, chip->chg_trklchg_irq,
+				qpnp_chg_chgr_chg_trklchg_irq_handler,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				"fast-chg-on", chip);
+		if (rc < 0) {
+			pr_err("Can't request %d trkl-chg-on for chg: %d\n",
+						chip->chg_trklchg_irq, rc);
+			return -ENXIO;
+		}
+
 		rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
 		if (rc) {
 			pr_debug("failed setting  min_voltage rc=%d\n", rc);
@@ -1269,7 +1478,8 @@
 			pr_debug("failed setting safe_voltage rc=%d\n", rc);
 			return rc;
 		}
-		rc = qpnp_chg_vbatdet_set(chip, chip->resume_voltage_mv);
+		rc = qpnp_chg_vbatdet_set(chip,
+				chip->max_voltage_mv - chip->resume_delta_mv);
 		if (rc) {
 			pr_debug("failed setting resume_voltage rc=%d\n", rc);
 			return rc;
@@ -1298,6 +1508,9 @@
 			CHGR_IBAT_TERM_CHGR,
 			0x80, 0x80, 1);
 
+		enable_irq_wake(chip->chg_fastchg_irq);
+		enable_irq_wake(chip->chg_trklchg_irq);
+		enable_irq_wake(chip->chg_failed_irq);
 		enable_irq_wake(chip->chg_done_irq);
 		break;
 	case SMBB_BUCK_SUBTYPE:
@@ -1313,6 +1526,23 @@
 		break;
 	case SMBB_BAT_IF_SUBTYPE:
 	case SMBBP_BAT_IF_SUBTYPE:
+		chip->batt_pres_irq = spmi_get_irq_byname(chip->spmi,
+						spmi_resource, "batt-pres");
+		if (chip->batt_pres_irq < 0) {
+			pr_err("Unable to get batt-pres irq\n");
+			return -ENXIO;
+		}
+		rc = devm_request_irq(chip->dev, chip->batt_pres_irq,
+				qpnp_chg_bat_if_batt_pres_irq_handler,
+				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+				"bat_if_batt_pres", chip);
+		if (rc < 0) {
+			pr_err("Can't request %d batt-pres irq for chg: %d\n",
+						chip->batt_pres_irq, rc);
+			return -ENXIO;
+		}
+
+		enable_irq_wake(chip->batt_pres_irq);
 		break;
 	case SMBB_USB_CHGPTH_SUBTYPE:
 	case SMBBP_USB_CHGPTH_SUBTYPE:
@@ -1427,7 +1657,7 @@
 	/* Get the vddmax property */
 	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vddmax-mv",
 						&chip->max_voltage_mv);
-	if (rc && rc != -EINVAL) {
+	if (rc) {
 		pr_err("Error reading vddmax property %d\n", rc);
 		goto fail_chg_enable;
 	}
@@ -1435,7 +1665,7 @@
 	/* Get the vinmin property */
 	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vinmin-mv",
 						&chip->min_voltage_mv);
-	if (rc && rc != -EINVAL) {
+	if (rc) {
 		pr_err("Error reading vddmax property %d\n", rc);
 		goto fail_chg_enable;
 	}
@@ -1443,17 +1673,17 @@
 	/* Get the vddmax property */
 	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-vddsafe-mv",
 						&chip->safe_voltage_mv);
-	if (rc && rc != -EINVAL) {
+	if (rc) {
 		pr_err("Error reading vddsave property %d\n", rc);
 		goto fail_chg_enable;
 	}
 
-	/* Get the ibatsafe property */
+	/* Get the vbatdet-delta property */
 	rc = of_property_read_u32(spmi->dev.of_node,
-				"qcom,chg-vbatdet-mv",
-				&chip->resume_voltage_mv);
-	if (rc) {
-		pr_err("Error reading vbatdet property %d\n", rc);
+				"qcom,chg-vbatdet-delta-mv",
+				&chip->resume_delta_mv);
+	if (rc && rc != -EINVAL) {
+		pr_err("Error reading vbatdet-delta property %d\n", rc);
 		goto fail_chg_enable;
 	}
 
@@ -1478,17 +1708,8 @@
 	/* Get the ibatmax property */
 	rc = of_property_read_u32(spmi->dev.of_node, "qcom,chg-ibatmax-ma",
 						&chip->max_bat_chg_current);
-	if (rc && rc != -EINVAL) {
-		pr_err("Error reading ibatmax property %d\n", rc);
-		goto fail_chg_enable;
-	}
-
-	/* Get the ibatsafe property */
-	rc = of_property_read_u32(spmi->dev.of_node,
-				"qcom,chg-vbatdet-mv",
-				&chip->resume_voltage_mv);
 	if (rc) {
-		pr_err("Error reading vbatdet property %d\n", rc);
+		pr_err("Error reading ibatmax property %d\n", rc);
 		goto fail_chg_enable;
 	}
 
@@ -1514,6 +1735,67 @@
 	chip->charging_disabled = of_property_read_bool(spmi->dev.of_node,
 					"qcom,chg-charging-disabled");
 
+	/* Get the warm-bat-degc property */
+	rc = of_property_read_u32(spmi->dev.of_node,
+				"qcom,chg-warm-bat-degc",
+				&chip->warm_bat_degc);
+	if (rc && rc != -EINVAL) {
+		pr_err("Error reading warm-bat-degc property %d\n", rc);
+		goto fail_chg_enable;
+	}
+
+	/* Get the cool-bat-degc property */
+	rc = of_property_read_u32(spmi->dev.of_node,
+				"qcom,chg-cool-bat-degc",
+				&chip->cool_bat_degc);
+	if (rc && rc != -EINVAL) {
+		pr_err("Error reading cool-bat-degc property %d\n", rc);
+		goto fail_chg_enable;
+	}
+
+	if (chip->cool_bat_degc && chip->warm_bat_degc) {
+		rc = qpnp_adc_tm_is_ready();
+		if (rc) {
+			pr_err("tm not ready %d\n", rc);
+			goto fail_chg_enable;
+		}
+
+		/* Get the ibatmax-warm property */
+		rc = of_property_read_u32(spmi->dev.of_node,
+					"qcom,chg-ibatmax-warm-ma",
+					&chip->warm_bat_chg_ma);
+		if (rc) {
+			pr_err("Error reading ibatmax-warm-ma %d\n", rc);
+			goto fail_chg_enable;
+		}
+
+		/* Get the ibatmax-cool property */
+		rc = of_property_read_u32(spmi->dev.of_node,
+					"qcom,chg-ibatmax-cool-ma",
+					&chip->cool_bat_chg_ma);
+		if (rc) {
+			pr_err("Error reading ibatmax-cool-ma %d\n", rc);
+			goto fail_chg_enable;
+		}
+		/* Get the cool-bat-mv property */
+		rc = of_property_read_u32(spmi->dev.of_node,
+					"qcom,chg-cool-bat-mv",
+					&chip->cool_bat_mv);
+		if (rc) {
+			pr_err("Error reading cool-bat-mv property %d\n", rc);
+			goto fail_chg_enable;
+		}
+
+		/* Get the warm-bat-mv property */
+		rc = of_property_read_u32(spmi->dev.of_node,
+					"qcom,chg-warm-bat-mv",
+					&chip->warm_bat_mv);
+		if (rc) {
+			pr_err("Error reading warm-bat-mv property %d\n", rc);
+			goto fail_chg_enable;
+		}
+	}
+
 	/* Get the fake-batt-values property */
 	chip->use_default_batt_values = of_property_read_bool(spmi->dev.of_node,
 					"qcom,chg-use-default-batt-values");
@@ -1701,6 +1983,22 @@
 		}
 	}
 
+	if (chip->cool_bat_degc && chip->warm_bat_degc) {
+		chip->adc_param.low_temp = chip->cool_bat_degc;
+		chip->adc_param.high_temp = chip->warm_bat_degc;
+		chip->adc_param.timer_interval = ADC_MEAS2_INTERVAL_1S;
+		chip->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
+		chip->adc_param.btm_ctx = chip;
+		chip->adc_param.threshold_notification =
+						qpnp_chg_adc_notification;
+
+		rc = qpnp_adc_tm_btm_configure(&chip->adc_param);
+		if (rc) {
+			pr_err("request ADC error %d\n", rc);
+			goto fail_chg_enable;
+		}
+	}
+
 	qpnp_chg_charge_en(chip, !chip->charging_disabled);
 	qpnp_chg_force_run_on_batt(chip, chip->charging_disabled);
 
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 9dd9c40..87a0078 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -516,6 +516,82 @@
 /*-------------------------------------------------------------------------*/
 /* Supported functions initialization */
 
+/* ACM */
+static char acm_transports[32];	/*enabled ACM ports - "tty[,sdio]"*/
+static ssize_t acm_transports_store(
+		struct device *device, struct device_attribute *attr,
+		const char *buff, size_t size)
+{
+	strlcpy(acm_transports, buff, sizeof(acm_transports));
+
+	return size;
+}
+
+static DEVICE_ATTR(acm_transports, S_IWUSR, NULL, acm_transports_store);
+static struct device_attribute *acm_function_attributes[] = {
+		&dev_attr_acm_transports,
+		NULL
+};
+
+static void acm_function_cleanup(struct android_usb_function *f)
+{
+	gserial_cleanup();
+}
+
+static int
+acm_function_bind_config(struct android_usb_function *f,
+		struct usb_configuration *c)
+{
+	char *name;
+	char buf[32], *b;
+	int err = -1, i;
+	static int acm_initialized, ports;
+
+	if (acm_initialized)
+		goto bind_config;
+
+	acm_initialized = 1;
+	strlcpy(buf, acm_transports, sizeof(buf));
+	b = strim(buf);
+
+	while (b) {
+		name = strsep(&b, ",");
+
+		if (name) {
+			err = acm_init_port(ports, name);
+			if (err) {
+				pr_err("acm: Cannot open port '%s'", name);
+				goto out;
+			}
+			ports++;
+		}
+	}
+	err = acm_port_setup(c);
+	if (err) {
+		pr_err("acm: Cannot setup transports");
+		goto out;
+	}
+
+bind_config:
+	for (i = 0; i < ports; i++) {
+		err = acm_bind_config(c, i);
+		if (err) {
+			pr_err("acm: bind_config failed for port %d", i);
+			goto out;
+		}
+	}
+
+out:
+	return err;
+}
+
+static struct android_usb_function acm_function = {
+	.name		= "acm",
+	.cleanup	= acm_function_cleanup,
+	.bind_config	= acm_function_bind_config,
+	.attributes	= acm_function_attributes,
+};
+
 /* RMNET_SMD */
 static int rmnet_smd_function_bind_config(struct android_usb_function *f,
 					  struct usb_configuration *c)
@@ -996,78 +1072,6 @@
 	.attributes	= serial_function_attributes,
 };
 
-/* ACM */
-static char acm_transports[32];	/*enabled ACM ports - "tty[,sdio]"*/
-static ssize_t acm_transports_store(
-		struct device *device, struct device_attribute *attr,
-		const char *buff, size_t size)
-{
-	strlcpy(acm_transports, buff, sizeof(acm_transports));
-
-	return size;
-}
-
-static DEVICE_ATTR(acm_transports, S_IWUSR, NULL, acm_transports_store);
-static struct device_attribute *acm_function_attributes[] = {
-		&dev_attr_acm_transports, NULL };
-
-static void acm_function_cleanup(struct android_usb_function *f)
-{
-	gserial_cleanup();
-}
-
-static int acm_function_bind_config(struct android_usb_function *f,
-					struct usb_configuration *c)
-{
-	char *name;
-	char buf[32], *b;
-	int err = -1, i;
-	static int acm_initialized, ports;
-
-	if (acm_initialized)
-		goto bind_config;
-
-	acm_initialized = 1;
-	strlcpy(buf, acm_transports, sizeof(buf));
-	b = strim(buf);
-
-	while (b) {
-		name = strsep(&b, ",");
-
-		if (name) {
-			err = acm_init_port(ports, name);
-			if (err) {
-				pr_err("acm: Cannot open port '%s'", name);
-				goto out;
-			}
-			ports++;
-		}
-	}
-	err = acm_port_setup(c);
-	if (err) {
-		pr_err("acm: Cannot setup transports");
-		goto out;
-	}
-
-bind_config:
-	for (i = 0; i < ports; i++) {
-		err = acm_bind_config(c, i);
-		if (err) {
-			pr_err("acm: bind_config failed for port %d", i);
-			goto out;
-		}
-	}
-
-out:
-	return err;
-}
-static struct android_usb_function acm_function = {
-	.name		= "acm",
-	.cleanup	= acm_function_cleanup,
-	.bind_config	= acm_function_bind_config,
-	.attributes	= acm_function_attributes,
-};
-
 /* CCID */
 static int ccid_function_init(struct android_usb_function *f,
 					struct usb_composite_dev *cdev)
@@ -1093,7 +1097,8 @@
 	.bind_config	= ccid_function_bind_config,
 };
 
-static int mtp_function_init(struct android_usb_function *f,
+static int
+mtp_function_init(struct android_usb_function *f,
 		struct usb_composite_dev *cdev)
 {
 	return mtp_setup();
@@ -1104,13 +1109,16 @@
 	mtp_cleanup();
 }
 
-static int mtp_function_bind_config(struct android_usb_function *f,
+static int
+mtp_function_bind_config(struct android_usb_function *f,
 		struct usb_configuration *c)
 {
 	return mtp_bind_config(c, false);
 }
 
-static int ptp_function_init(struct android_usb_function *f, struct usb_composite_dev *cdev)
+static int
+ptp_function_init(struct android_usb_function *f,
+		struct usb_composite_dev *cdev)
 {
 	/* nothing to do - initialization is handled by mtp_function_init */
 	return 0;
@@ -1121,7 +1129,9 @@
 	/* nothing to do - cleanup is handled by mtp_function_cleanup */
 }
 
-static int ptp_function_bind_config(struct android_usb_function *f, struct usb_configuration *c)
+static int
+ptp_function_bind_config(struct android_usb_function *f,
+		struct usb_configuration *c)
 {
 	return mtp_bind_config(c, true);
 }
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index c02c8e4..81fc1cc 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -1391,9 +1391,6 @@
 		dev_err(dev, "[%s] EINVAL\n", __func__);
 		return 0;
 	}
-	dump = kmalloc(2048, GFP_KERNEL);
-	if (dump == NULL)
-		return -ENOMEM;
 
 	dump = kmalloc(sizeof(u32) * DUMP_ENTRIES, GFP_KERNEL);
 	if (!dump) {
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 0752188..de54714 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -18,7 +18,6 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
-#include <linux/usb/android_composite.h>
 #include <mach/usb_gadget_xport.h>
 
 #include "u_serial.h"
diff --git a/drivers/usb/gadget/f_ccid.c b/drivers/usb/gadget/f_ccid.c
index 4e28d34..6888935 100644
--- a/drivers/usb/gadget/f_ccid.c
+++ b/drivers/usb/gadget/f_ccid.c
@@ -16,7 +16,6 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
-#include <linux/usb/android_composite.h>
 #include <linux/fs.h>
 #include <linux/usb/ccid_desc.h>
 #include <linux/miscdevice.h>
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 0d8fa0f..af68827 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -14,7 +14,6 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/device.h>
-#include <linux/usb/android_composite.h>
 #include <linux/spinlock.h>
 
 #include <mach/usb_gadget_xport.h>
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index bf887a7..8c0894c 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -49,6 +49,7 @@
 #include <linux/spinlock.h>
 #include <linux/cpu.h>
 #include <mach/rpm-regulator.h>
+#include "hbm.c"
 
 #define MSM_USB_BASE (hcd->regs)
 #define USB_REG_START_OFFSET 0x90
@@ -105,6 +106,7 @@
 	int			reset_again;
 
 	struct pm_qos_request pm_qos_req_dma;
+	unsigned		enable_hbm:1;
 };
 
 struct msm_hsic_hcd *__mehci;
@@ -1367,6 +1369,18 @@
 		pm_runtime_set_autosuspend_delay(&dev->dev, 200);
 }
 
+static int ehci_msm_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
+				gfp_t mem_flags)
+{
+	struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
+	struct usb_host_bam_type *usb_host_bam =
+			(struct usb_host_bam_type *)urb->priv_data;
+
+	if (usb_host_bam && mehci && mehci->enable_hbm)
+		return hbm_urb_enqueue(hcd, urb, mem_flags);
+	return ehci_urb_enqueue(hcd, urb, mem_flags);
+}
+
 static struct hc_driver msm_hsic_driver = {
 	.description		= hcd_name,
 	.product_desc		= "Qualcomm EHCI Host Controller using HSIC",
@@ -1387,7 +1401,7 @@
 	/*
 	 * managing i/o requests and associated device resources
 	 */
-	.urb_enqueue		= ehci_urb_enqueue,
+	.urb_enqueue		= ehci_msm_urb_enqueue,
 	.urb_dequeue		= ehci_urb_dequeue,
 	.endpoint_disable	= ehci_endpoint_disable,
 	.endpoint_reset		= ehci_endpoint_reset,
@@ -1778,6 +1792,8 @@
 
 	pdata->pool_64_bit_align = of_property_read_bool(node,
 				"qcom,pool-64-bit-align");
+	pdata->enable_hbm = of_property_read_bool(node,
+				"qcom,enable-hbm");
 
 	return pdata;
 }
@@ -1861,6 +1877,7 @@
 
 	mehci->ehci.resume_sof_bug = 1;
 	mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
+	mehci->enable_hbm = pdata->enable_hbm;
 
 	if (pdata)
 		mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
@@ -2011,6 +2028,9 @@
 	if (pdev->dev.parent)
 		pm_runtime_put_sync(pdev->dev.parent);
 
+	if (mehci->enable_hbm)
+		hbm_init(hcd);
+
 	return 0;
 
 destroy_wq:
@@ -2040,6 +2060,9 @@
 
 	pm_runtime_set_suspended(&pdev->dev);
 
+	if (mehci->enable_hbm)
+		hbm_uninit();
+
 	/* Remove the HCD prior to releasing our resources. */
 	usb_remove_hcd(hcd);
 
diff --git a/drivers/usb/host/hbm.c b/drivers/usb/host/hbm.c
index f516ad8..d48a631 100644
--- a/drivers/usb/host/hbm.c
+++ b/drivers/usb/host/hbm.c
@@ -194,12 +194,6 @@
 		pr_err("%s: hbm_ctx alloc failed\n", __func__);
 		return;
 	}
-	hbm_ctx->base = kzalloc(sizeof(u32), GFP_KERNEL);
-	if (!hbm_ctx->base) {
-		pr_err("%s: hbm_ctx base alloc failed\n", __func__);
-		kfree(hbm_ctx);
-		return;
-	}
 
 	hbm_ctx->base = hcd->regs;
 	hbm_ctx->hcd = hcd;
@@ -214,7 +208,7 @@
 
 void hbm_uninit(void)
 {
-	kfree(hbm_ctx->base);
+	hbm_config(false);
 	kfree(hbm_ctx);
 }
 
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 1c7d928..7760d28 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -151,8 +151,8 @@
 		rc = regulator_set_voltage(hsusb_1p8, USB_PHY_1P8_VOL_MIN,
 				USB_PHY_1P8_VOL_MAX);
 		if (rc) {
-			dev_err(motg->phy.dev, "unable to set voltage level for"
-					"hsusb 1p8\n");
+			dev_err(motg->phy.dev, "unable to set voltage level "
+					"for hsusb 1p8\n");
 			goto put_1p8;
 		}
 
@@ -207,7 +207,7 @@
 		ret = regulator_set_optimum_mode(hsusb_1p8,
 				USB_PHY_1P8_HPM_LOAD);
 		if (ret < 0) {
-			pr_err("%s: Unable to set HPM of the regulator:"
+			pr_err("%s: Unable to set HPM of the regulator "
 				"HSUSB_1p8\n", __func__);
 			return ret;
 		}
@@ -223,7 +223,7 @@
 		ret = regulator_set_optimum_mode(hsusb_3p3,
 				USB_PHY_3P3_HPM_LOAD);
 		if (ret < 0) {
-			pr_err("%s: Unable to set HPM of the regulator:"
+			pr_err("%s: Unable to set HPM of the regulator "
 				"HSUSB_3p3\n", __func__);
 			regulator_set_optimum_mode(hsusb_1p8, 0);
 			regulator_disable(hsusb_1p8);
@@ -252,7 +252,7 @@
 
 		ret = regulator_set_optimum_mode(hsusb_1p8, 0);
 		if (ret < 0)
-			pr_err("%s: Unable to set LPM of the regulator:"
+			pr_err("%s: Unable to set LPM of the regulator "
 				"HSUSB_1p8\n", __func__);
 
 		ret = regulator_disable(hsusb_3p3);
@@ -263,7 +263,7 @@
 		}
 		ret = regulator_set_optimum_mode(hsusb_3p3, 0);
 		if (ret < 0)
-			pr_err("%s: Unable to set LPM of the regulator:"
+			pr_err("%s: Unable to set LPM of the regulator "
 				"HSUSB_3p3\n", __func__);
 
 		break;
@@ -1575,7 +1575,7 @@
 }
 
 static int msm_otg_set_peripheral(struct usb_otg *otg,
-			struct usb_gadget *gadget)
+					struct usb_gadget *gadget)
 {
 	struct msm_otg *motg = container_of(otg->phy, struct msm_otg, phy);
 
@@ -3017,10 +3017,10 @@
 
 	if ((otgsc & OTGSC_IDIS) && (otgsc & OTGSC_IDIE)) {
 		if (otgsc & OTGSC_ID) {
-			pr_debug("Id set\n");
+			dev_dbg(otg->phy->dev, "ID set\n");
 			set_bit(ID, &motg->inputs);
 		} else {
-			pr_debug("Id clear\n");
+			dev_dbg(otg->phy->dev, "ID clear\n");
 			/*
 			 * Assert a_bus_req to supply power on
 			 * VBUS when Micro/Mini-A cable is connected
@@ -3049,10 +3049,10 @@
 			!test_bit(ID_A, &motg->inputs))
 			return IRQ_HANDLED;
 		if (otgsc & OTGSC_BSV) {
-			pr_debug("BSV set\n");
+			dev_dbg(otg->phy->dev, "BSV set\n");
 			set_bit(B_SESS_VLD, &motg->inputs);
 		} else {
-			pr_debug("BSV clear\n");
+			dev_dbg(otg->phy->dev, "BSV clear\n");
 			clear_bit(B_SESS_VLD, &motg->inputs);
 			clear_bit(A_BUS_SUSPEND, &motg->inputs);
 
@@ -3245,9 +3245,9 @@
 static int msm_otg_mode_show(struct seq_file *s, void *unused)
 {
 	struct msm_otg *motg = s->private;
-	struct usb_phy *phy = &motg->phy;
+	struct usb_otg *otg = motg->phy.otg;
 
-	switch (phy->state) {
+	switch (otg->phy->state) {
 	case OTG_STATE_A_HOST:
 		seq_printf(s, "host\n");
 		break;
@@ -4228,10 +4228,10 @@
 static int __devexit msm_otg_remove(struct platform_device *pdev)
 {
 	struct msm_otg *motg = platform_get_drvdata(pdev);
-	struct usb_otg *otg = motg->phy.otg;
+	struct usb_phy *phy = &motg->phy;
 	int cnt = 0;
 
-	if (otg->host || otg->gadget)
+	if (phy->otg->host || phy->otg->gadget)
 		return -EBUSY;
 
 	if (pdev->dev.of_node)
@@ -4264,8 +4264,8 @@
 	/*
 	 * Put PHY in low power mode.
 	 */
-	ulpi_read(otg->phy, 0x14);
-	ulpi_write(otg->phy, 0x08, 0x09);
+	ulpi_read(phy, 0x14);
+	ulpi_write(phy, 0x08, 0x09);
 
 	writel(readl(USB_PORTSC) | PORTSC_PHCD, USB_PORTSC);
 	while (cnt < PHY_SUSPEND_TIMEOUT_USEC) {
@@ -4275,7 +4275,7 @@
 		cnt++;
 	}
 	if (cnt >= PHY_SUSPEND_TIMEOUT_USEC)
-		dev_err(otg->phy->dev, "Unable to suspend PHY\n");
+		dev_err(phy->dev, "Unable to suspend PHY\n");
 
 	clk_disable_unprepare(motg->pclk);
 	clk_disable_unprepare(motg->core_clk);
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index 30dd471..ccddf44 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -1712,18 +1712,18 @@
 		struct input_dev *input = mhl_ctrl->input;
 
 		mhl_ctrl->rcp_key_code_tbl = vmalloc(
-			ARRAY_SIZE(support_rcp_key_code_tbl));
+			sizeof(support_rcp_key_code_tbl));
 		if (!mhl_ctrl->rcp_key_code_tbl) {
 			pr_err("%s: no alloc mem for rcp keycode tbl\n",
 			       __func__);
 			return -ENOMEM;
 		}
 
+		mhl_ctrl->rcp_key_code_tbl_len = sizeof(
+			support_rcp_key_code_tbl);
 		memcpy(mhl_ctrl->rcp_key_code_tbl,
 		       &support_rcp_key_code_tbl[0],
-		       ARRAY_SIZE(support_rcp_key_code_tbl));
-		mhl_ctrl->rcp_key_code_tbl_len = ARRAY_SIZE(
-			support_rcp_key_code_tbl);
+		       mhl_ctrl->rcp_key_code_tbl_len);
 
 		input->phys = "cbus/input0";
 		input->id.bustype = BUS_VIRTUAL;
diff --git a/include/linux/usb/android_composite.h b/include/linux/usb/android_composite.h
deleted file mode 100644
index 438dfa4..0000000
--- a/include/linux/usb/android_composite.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Platform data for Android USB
- *
- * Copyright (C) 2008 Google, Inc.
- * Author: Mike Lockwood <lockwood@android.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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	__LINUX_USB_ANDROID_H
-#define	__LINUX_USB_ANDROID_H
-
-#include <linux/usb/composite.h>
-#include <linux/if_ether.h>
-
-struct android_usb_function {
-	struct list_head	list;
-	char			*name;
-	int 			(*bind_config)(struct usb_configuration *c);
-};
-
-struct android_usb_product {
-	/* Default product ID. */
-	__u16 product_id;
-
-	/* List of function names associated with this product.
-	 * This is used to compute the USB product ID dynamically
-	 * based on which functions are enabled.
-	 */
-	int num_functions;
-	char **functions;
-};
-
-struct android_usb_platform_data {
-	/* USB device descriptor fields */
-	__u16 vendor_id;
-
-	/* Default product ID. */
-	__u16 product_id;
-
-	__u16 version;
-
-	char *product_name;
-	char *manufacturer_name;
-	char *serial_number;
-
-	/* List of available USB products.
-	 * This is used to compute the USB product ID dynamically
-	 * based on which functions are enabled.
-	 * if num_products is zero or no match can be found,
-	 * we use the default product ID
-	 */
-	int num_products;
-	struct android_usb_product *products;
-
-	/* List of all supported USB functions.
-	 * This list is used to define the order in which
-	 * the functions appear in the configuration's list of USB interfaces.
-	 * This is necessary to avoid depending upon the order in which
-	 * the individual function drivers are initialized.
-	 */
-	int num_functions;
-	char **functions;
-};
-
-/* Platform data for "usb_mass_storage" driver. */
-struct usb_mass_storage_platform_data {
-	/* Contains values for the SC_INQUIRY SCSI command. */
-	char *vendor;
-	char *product;
-	int release;
-
-	char can_stall;
-	/* number of LUNS */
-	int nluns;
-};
-
-/* Platform data for USB ethernet driver. */
-struct usb_ether_platform_data {
-	u8	ethaddr[ETH_ALEN];
-	u32	vendorID;
-	const char *vendorDescr;
-};
-
-extern void android_register_function(struct android_usb_function *f);
-
-extern int android_enable_function(struct usb_function *f, int enable);
-
-
-#endif	/* __LINUX_USB_ANDROID_H */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index c7c6b05..c5943c9 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -412,6 +412,7 @@
 	/*standalone latency is required when HSCI is active*/
 	u32 standalone_latency;
 	bool pool_64_bit_align;
+	bool enable_hbm;
 };
 
 struct msm_usb_host_platform_data {
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index af268bd..f4ea679 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -83,6 +83,7 @@
 	AIF2_CAP,
 	AIF3_PB,
 	AIF3_CAP,
+	AIF4_VIFEED,
 	NUM_CODEC_DAIS,
 };
 
@@ -2671,6 +2672,7 @@
 	{"AIF1 CAP", NULL, "AIF1_CAP Mixer"},
 	{"AIF2 CAP", NULL, "AIF2_CAP Mixer"},
 	{"AIF3 CAP", NULL, "AIF3_CAP Mixer"},
+	{"AIF4 VI", NULL, "SPK_OUT"},
 
 	/* SLIM_MIXER("AIF1_CAP Mixer"),*/
 	{"AIF1_CAP Mixer", "SLIM TX1", "SLIM TX1 MUX"},
@@ -3143,6 +3145,7 @@
 	{"MIC BIAS3 Internal2", NULL, "LDO_H"},
 	{"MIC BIAS3 External", NULL, "LDO_H"},
 	{"MIC BIAS4 External", NULL, "LDO_H"},
+
 };
 
 static int taiko_readable(struct snd_soc_codec *ssc, unsigned int reg)
@@ -3367,6 +3370,7 @@
 				unsigned int rx_num, unsigned int *rx_slot)
 
 {
+	struct wcd9xxx_codec_dai_data *dai_data = NULL;
 	struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
 	struct wcd9xxx *core = dev_get_drvdata(dai->codec->dev->parent);
 	if (!tx_slot && !rx_slot) {
@@ -3378,9 +3382,18 @@
 		 __func__, dai->name, dai->id, tx_num, rx_num,
 		 taiko->intf_type);
 
-	if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+	if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
 		wcd9xxx_init_slimslave(core, core->slim->laddr,
-				       tx_num, tx_slot, rx_num, rx_slot);
+					   tx_num, tx_slot, rx_num, rx_slot);
+		/*Reserve tx11 and tx12 for VI feedback path*/
+		dai_data = &taiko->dai[AIF4_VIFEED];
+		if (dai_data) {
+			list_add_tail(&core->tx_chs[TAIKO_TX11].list,
+			&dai_data->wcd9xxx_ch_list);
+			list_add_tail(&core->tx_chs[TAIKO_TX12].list,
+			&dai_data->wcd9xxx_ch_list);
+		}
+	}
 	return 0;
 }
 
@@ -3414,6 +3427,7 @@
 	case AIF1_CAP:
 	case AIF2_CAP:
 	case AIF3_CAP:
+	case AIF4_VIFEED:
 		if (!tx_slot || !tx_num) {
 			pr_err("%s: Invalid tx_slot %d or tx_num %d\n",
 				 __func__, (u32) tx_slot, (u32) tx_num);
@@ -3639,12 +3653,14 @@
 
 	switch (substream->stream) {
 	case SNDRV_PCM_STREAM_CAPTURE:
-		ret = taiko_set_decimator_rate(dai, tx_fs_rate,
-					       params_rate(params));
-		if (ret < 0) {
-			pr_err("%s: set decimator rate failed %d\n", __func__,
-				ret);
-			return ret;
+		if (dai->id != AIF4_VIFEED) {
+			ret = taiko_set_decimator_rate(dai, tx_fs_rate,
+							   params_rate(params));
+			if (ret < 0) {
+				pr_err("%s: set decimator rate failed %d\n",
+					__func__, ret);
+				return ret;
+			}
 		}
 
 		if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
@@ -3828,6 +3844,20 @@
 		},
 		.ops = &taiko_dai_ops,
 	},
+	{
+		.name = "taiko_vifeedback",
+		.id = AIF4_VIFEED,
+		.capture = {
+			.stream_name = "VIfeed",
+			.rates = SNDRV_PCM_RATE_48000,
+			.formats = TAIKO_FORMATS,
+			.rate_max = 48000,
+			.rate_min = 48000,
+			.channels_min = 2,
+			.channels_max = 2,
+	 },
+		.ops = &taiko_dai_ops,
+	},
 };
 
 static struct snd_soc_dai_driver taiko_i2s_dai[] = {
@@ -3967,6 +3997,89 @@
 	return ret;
 }
 
+static int taiko_codec_enable_slimvi_feedback(struct snd_soc_dapm_widget *w,
+				struct snd_kcontrol *kcontrol,
+				int event)
+{
+	struct wcd9xxx *core = NULL;
+	struct snd_soc_codec *codec = NULL;
+	struct taiko_priv *taiko_p = NULL;
+	u32 ret = 0;
+	struct wcd9xxx_codec_dai_data *dai = NULL;
+
+	if (!w || !w->codec) {
+		pr_err("%s invalid params\n", __func__);
+		return -EINVAL;
+	}
+	codec = w->codec;
+	taiko_p = snd_soc_codec_get_drvdata(codec);
+	core = dev_get_drvdata(codec->dev->parent);
+
+	pr_debug("%s: event called! codec name %s num_dai %d stream name %s\n",
+		__func__, w->codec->name, w->codec->num_dai, w->sname);
+
+	/* Execute the callback only if interface type is slimbus */
+	if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
+		pr_err("%s Interface is not correct", __func__);
+		return 0;
+	}
+
+	pr_debug("%s(): w->name %s event %d w->shift %d\n",
+		__func__, w->name, event, w->shift);
+	if (w->shift != AIF4_VIFEED) {
+		pr_err("%s Error in enabling the tx path\n", __func__);
+		ret = -EINVAL;
+		goto out_vi;
+	}
+	dai = &taiko_p->dai[w->shift];
+	switch (event) {
+	case SND_SOC_DAPM_POST_PMU:
+		/*Enable Clip Detection*/
+		snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_CLIP_DET,
+				0x8, 0x8);
+		/*Enable V&I sensing*/
+		snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
+				0x88, 0x88);
+		/*Enable spkr VI clocks*/
+		snd_soc_update_bits(codec,
+		TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0xC, 0xC);
+		/*Enable Voltage Decimator*/
+		snd_soc_update_bits(codec,
+		TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x1F, 0x12);
+		/*Enable Current Decimator*/
+		snd_soc_update_bits(codec,
+		TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x1F, 0x13);
+		ret = wcd9xxx_cfg_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
+					dai->rate, dai->bit_width,
+					&dai->grph);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		ret = wcd9xxx_close_slim_sch_tx(core, &dai->wcd9xxx_ch_list,
+						dai->grph);
+		if (ret)
+			pr_err("%s error in close_slim_sch_tx %d\n",
+				__func__, ret);
+		/*Disable Voltage decimator*/
+		snd_soc_update_bits(codec,
+		TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x1F, 0x0);
+		/*Disable Current decimator*/
+		snd_soc_update_bits(codec,
+		TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x1F, 0x0);
+		/*Disable spkr VI clocks*/
+		snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL,
+				0xC, 0x0);
+		/*Disable V&I sensing*/
+		snd_soc_update_bits(codec, TAIKO_A_SPKR_PROT_EN,
+				0x88, 0x00);
+		/*Disable clip detection*/
+		snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_CLIP_DET,
+				0x8, 0x0);
+		break;
+	}
+out_vi:
+	return ret;
+}
+
 static int taiko_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
 				     struct snd_kcontrol *kcontrol,
 				     int event)
@@ -4440,6 +4553,10 @@
 		AIF3_CAP, 0, taiko_codec_enable_slimtx,
 		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
 
+	SND_SOC_DAPM_AIF_OUT_E("AIF4 VI", "VIfeed", 0, SND_SOC_NOPM,
+		AIF4_VIFEED, 0, taiko_codec_enable_slimvi_feedback,
+		SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
 	SND_SOC_DAPM_MIXER("AIF1_CAP Mixer", SND_SOC_NOPM, AIF1_CAP, 0,
 		aif_cap_mixer, ARRAY_SIZE(aif_cap_mixer)),
 
@@ -4529,7 +4646,6 @@
 
 	SND_SOC_DAPM_MIXER("LINEOUT4_PA_MIXER", SND_SOC_NOPM, 0, 0,
 		lineout4_pa_mix, ARRAY_SIZE(lineout4_pa_mix)),
-
 };
 
 static irqreturn_t taiko_slimbus_irq(int irq, void *data)
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 39afb73..4e6cbaa 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -788,7 +788,7 @@
 	runtime->private_data = compr;
 	atomic_set(&prtd->eos, 0);
 	compressed_audio.prtd =  &compr->prtd;
-	ret = compressed_set_volume(compressed_audio.volume);
+	ret = compressed_set_volume(0);
 	if (ret < 0)
 		pr_err("%s : Set Volume failed : %d", __func__, ret);
 
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index d0b5500..f6e571b8 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -754,7 +754,7 @@
 			prtd->session_id,
 			substream->stream);
 
-		ret = compressed_set_volume(compressed_audio.volume);
+		ret = compressed_set_volume(0);
 		if (ret < 0)
 			pr_err("%s : Set Volume failed : %d", __func__, ret);
 
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index c300a9f..557ec65 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -485,6 +485,7 @@
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
+	case SNDRV_PCM_FMTBIT_SPECIAL:
 		dai_data->port_config.i2s.bit_width = 16;
 		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
@@ -560,6 +561,7 @@
 
 	switch (params_format(params)) {
 	case SNDRV_PCM_FORMAT_S16_LE:
+	case SNDRV_PCM_FMTBIT_SPECIAL:
 		dai_data->port_config.slim_sch.bit_width = 16;
 		break;
 	case SNDRV_PCM_FORMAT_S24_LE:
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index e05e58d..4ca96d7 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -459,19 +459,20 @@
 
 	pr_debug("%s\n", __func__);
 
-	dir = IN;
-	ret = wait_event_timeout(the_locks.eos_wait,
-				prtd->cmd_ack, 5 * HZ);
-	if (ret < 0)
-		pr_err("%s: CMD_EOS failed\n", __func__);
-	q6asm_cmd(prtd->audio_client, CMD_CLOSE);
-	q6asm_audio_client_buf_free_contiguous(dir,
-				prtd->audio_client);
-
+	if (prtd->audio_client) {
+		dir = IN;
+		ret = wait_event_timeout(the_locks.eos_wait,
+					prtd->cmd_ack, 5 * HZ);
+		if (ret < 0)
+			pr_err("%s: CMD_EOS failed\n", __func__);
+		q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+		q6asm_audio_client_buf_free_contiguous(dir,
+					prtd->audio_client);
+		pcm_audio.prtd = NULL;
+		q6asm_audio_client_free(prtd->audio_client);
+	}
 	msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
 						SNDRV_PCM_STREAM_PLAYBACK);
-	pcm_audio.prtd = NULL;
-	q6asm_audio_client_free(prtd->audio_client);
 	kfree(prtd);
 	return 0;
 }
@@ -678,7 +679,7 @@
 		if (ret < 0) {
 			pr_err("%s: q6asm_open_write_v2 failed\n", __func__);
 			q6asm_audio_client_free(prtd->audio_client);
-			kfree(prtd);
+			prtd->audio_client = NULL;
 			return -ENOMEM;
 		}
 
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 4e7455b..0549671 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -2344,7 +2344,7 @@
 	fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) -
 					sizeof(fmt.fmt_blk);
 	fmt.num_channels = channels;
-	fmt.bits_per_sample = 16;
+	fmt.bits_per_sample = bits_per_sample;
 	fmt.sample_rate = rate;
 	fmt.is_signed = 1;
 
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index 99cb6a6..4ed0fb7 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -43,6 +43,7 @@
 	case SLIMBUS_1_TX: return IDX_SLIMBUS_1_TX;
 	case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
 	case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
+	case SLIMBUS_4_TX: return IDX_SLIMBUS_4_TX;
 	case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
 	case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
 	case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
@@ -89,6 +90,7 @@
 	case SLIMBUS_1_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_TX;
 	case SLIMBUS_2_RX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_RX;
 	case SLIMBUS_2_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_2_TX;
+	case SLIMBUS_4_TX: return AFE_PORT_ID_SLIMBUS_MULTI_CHAN_4_TX;
 	case INT_BT_SCO_RX: return AFE_PORT_ID_INTERNAL_BT_SCO_RX;
 	case INT_BT_SCO_TX: return AFE_PORT_ID_INTERNAL_BT_SCO_TX;
 	case INT_BT_A2DP_RX: return AFE_PORT_ID_INTERNAL_BT_A2DP_RX;
@@ -182,6 +184,7 @@
 	case SLIMBUS_1_TX:
 	case SLIMBUS_2_RX:
 	case SLIMBUS_2_TX:
+	case SLIMBUS_4_TX:
 	case INT_BT_SCO_RX:
 	case INT_BT_SCO_TX:
 	case INT_BT_A2DP_RX: