Merge "ARM: dts: msm: Add oem in vbmeta parts for apq8053 lite"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index 931ef7a..a55ef6c 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -110,6 +110,9 @@
 - SDM450
   compatible = "qcom,sdm450"
 
+- SDA450
+  compatible = "qcom,sda450"
+
 - SDM632
   compatible = "qcom,sdm632"
 
@@ -357,6 +360,8 @@
 compatible = "qcom,sdm450-mtp"
 compatible = "qcom,sdm450-cdp"
 compatible = "qcom,sdm450-qrd"
+compatible = "qcom,sda450-mtp"
+compatible = "qcom,sda450-cdp"
 compatible = "qcom,sdm632-rumi"
 compatible = "qcom,sdm632-cdp"
 compatible = "qcom,sdm632-mtp"
diff --git a/Documentation/devicetree/bindings/input/qpnp-power-on.txt b/Documentation/devicetree/bindings/input/qpnp-power-on.txt
index 0f1d9e1..9addf15 100644
--- a/Documentation/devicetree/bindings/input/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/input/qpnp-power-on.txt
@@ -115,6 +115,10 @@
 - qcom,use-legacy-hard-reset-offset	Boolean property to support legacy
 				hard-reset offset of the PON_RB_SPARE register for
 				some (PON gen2) platforms.
+- qcom,support-twm-config       Boolean property to allow the PON module to be
+                                configured to support TWM modes.
+- qcom,pbs-client               Phandle of the PBS client node. Should be
+                                defined if 'qcom,support-twm-config' is present.
 
 All the below properties are in the sub-node section (properties of the child
 node).
diff --git a/Documentation/devicetree/bindings/misc/qpnp-misc.txt b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
index a34cbde..ada8da9 100644
--- a/Documentation/devicetree/bindings/misc/qpnp-misc.txt
+++ b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
@@ -16,6 +16,12 @@
 				if a non-zero PWM source is specified under
 				"qcom,pwm-sel" property.
 
+- qcom,support-twm-config	Enable configuration for TWM mode.
+
+- qcom,twm-mode			The TWM mode which PMIC enters post power-off.
+				Valid only if 'qcom,support-twm-config' is
+				defined. If not specified, the default mode
+				is 3.
 Example:
 	qcom,misc@900 {
 		compatible = "qcom,qpnp-misc";
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index 51df1d7..38ba7fc 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -826,8 +826,6 @@
 	qcom,rmnet-ipa {
 		compatible = "qcom,rmnet-ipa3";
 		qcom,rmnet-ipa-ssr;
-		qcom,ipa-loaduC;
-		qcom,ipa-advertise-sg-support;
 	};
 
 	dcc: dcc_v2@10a2000 {
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index cdfe536..75372aa 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -33,6 +33,7 @@
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
diff --git a/arch/arm/configs/msm8909w_defconfig b/arch/arm/configs/msm8909w_defconfig
index 46052bd..086b127 100644
--- a/arch/arm/configs/msm8909w_defconfig
+++ b/arch/arm/configs/msm8909w_defconfig
@@ -33,6 +33,7 @@
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
diff --git a/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi b/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
index 2a3468d..3947406 100644
--- a/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
@@ -469,6 +469,15 @@
 	qcom,support-twm-config;
 };
 
+&pm660_pbs {
+	status = "okay";
+};
+
+&pm660_pon {
+	qcom,support-twm-config;
+	qcom,pbs-client = <&pm660_pbs>;
+};
+
 / {
 	/delete-node/ qcom,battery-data;
 	mtp_batterydata: qcom,battery-data {
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 7457bbb..85c4df1 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -317,6 +317,7 @@
 msm8953-mtp-overlay.dtbo-base := sdm450.dtb \
 	msm8953.dtb \
 	apq8053.dtb \
+	sda450.dtb \
 	msm8953-pmi8940.dtb \
 	msm8953-pmi8937.dtb \
 	sdm450-pmi8940.dtb \
@@ -324,6 +325,7 @@
 msm8953-cdp-overlay.dtbo-base := sdm450.dtb \
 	msm8953.dtb \
 	apq8053.dtb \
+	sda450.dtb \
 	msm8953-pmi8940.dtb \
 	msm8953-pmi8937.dtb
 msm8953-rcm-overlay.dtbo-base := sdm450.dtb \
@@ -346,10 +348,12 @@
 sdm450-cdp-s2-overlay.dtbo-base := sdm450-pmi632.dtb \
 	sdm632.dtb \
 	sdm632-pm8004.dtb \
-	msm8953-pmi632.dtb
+	msm8953-pmi632.dtb \
+	sda450-pmi632.dtb
 sdm450-mtp-s3-overlay.dtbo-base := sdm450-pmi632.dtb \
 	sdm632.dtb \
-	sdm632-pm8004.dtb
+	sdm632-pm8004.dtb \
+	sda450-pmi632.dtb
 sdm450-qrd-sku4-overlay.dtbo-base := sdm450-pmi632.dtb \
 	sdm632.dtb \
 	sdm632-pm8004.dtb
@@ -422,13 +426,17 @@
 dtb-$(CONFIG_ARCH_SDM450) += sdm450-rcm.dtb \
 	sdm450-cdp.dtb \
 	sdm450-mtp.dtb \
+	sda450-cdp.dtb \
+	sda450-mtp.dtb \
 	sdm450-qrd.dtb \
 	sdm450-pmi8940-mtp.dtb \
 	sdm450-pmi8937-mtp.dtb \
 	sdm450-iot-mtp.dtb \
 	sdm450-qrd-sku4.dtb \
 	sdm450-pmi632-cdp-s2.dtb \
-	sdm450-pmi632-mtp-s3.dtb
+	sdm450-pmi632-mtp-s3.dtb \
+	sda450-pmi632-cdp-s2.dtb \
+	sda450-pmi632-mtp-s3.dtb
 
 dtb-$(CONFIG_ARCH_SDM632) += sdm632-rumi.dtb \
 	sdm632-cdp-s2.dtb \
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts
index d857c82..ab86021 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts
@@ -61,3 +61,46 @@
 	qcom,esd-check-enabled;
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
 };
+
+&soc {
+	i2c@78b7000 {
+		status = "ok";
+		focaltech@38 {
+			compatible = "focaltech,5x06";
+			reg = <0x38>;
+			interrupt-parent = <&tlmm>;
+			interrupts = <65 0x2>;
+			vdd-supply = <&pm8937_l10>;
+			vcc_i2c-supply = <&pm8937_l5>;
+			/* pins used by touchscreen */
+			pinctrl-names = "pmx_ts_active",
+						"pmx_ts_suspend",
+						"pmx_ts_release";
+			pinctrl-0 = <&ts_int_active &ts_reset_active>;
+			pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+			pinctrl-2 = <&ts_release>;
+			focaltech,name = "ft5436";
+			focaltech,family-id = <0x06>;
+			focaltech,reset-gpio = <&tlmm 64 0x0>;
+			focaltech,irq-gpio = <&tlmm 65 0x2008>;
+			focaltech,display-coords = <0 0 720 1280>;
+			focaltech,panel-coords = <0 0 720 1400>;
+			focaltech,button-map= <139 102 158>;
+			focaltech,no-force-update;
+			focaltech,i2c-pull-up;
+			focaltech,group-id = <1>;
+			focaltech,hard-reset-delay-ms = <20>;
+			focaltech,soft-reset-delay-ms = <200>;
+			focaltech,num-max-touches = <5>;
+			focaltech,fw-delay-aa-ms = <30>;
+			focaltech,fw-delay-55-ms = <30>;
+			focaltech,fw-upgrade-id1 = <0x79>;
+			focaltech,fw-upgrade-id2 = <0x08>;
+			focaltech,fw-delay-readid-ms = <10>;
+			focaltech,fw-delay-era-flsh-ms = <2000>;
+			focaltech,fw-auto-cal;
+			focaltech,ignore-id-check;
+			focaltech,resume-in-workqueue;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937.dtsi b/arch/arm64/boot/dts/qcom/msm8937.dtsi
index 632c924..7b9f74b 100644
--- a/arch/arm64/boot/dts/qcom/msm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937.dtsi
@@ -191,6 +191,17 @@
 		      <0x0b002000 0x1000>;
 	};
 
+	dcc: dcc@b3000 {
+		compatible = "qcom,dcc";
+		reg = <0xb3000 0x1000>,
+		      <0xb4000 0x2000>;
+		reg-names = "dcc-base", "dcc-ram-base";
+
+		clocks = <&clock_gcc clk_gcc_dcc_clk>;
+		clock-names = "apb_pclk";
+		qcom,save-reg;
+	};
+
 	wakegic: wake-gic {
 		compatible = "qcom,mpm-gic-msm8937", "qcom,mpm-gic";
 		interrupts = <GIC_SPI 171 IRQ_TYPE_EDGE_RISING>;
diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi
index fa10500..e8a82aa 100644
--- a/arch/arm64/boot/dts/qcom/pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660.dtsi
@@ -32,7 +32,7 @@
 			reg = <0x900 0x100>;
 		};
 
-		qcom,power-on@800 {
+		pm660_pon: qcom,power-on@800 {
 			compatible = "qcom,qpnp-power-on";
 			reg = <0x800 0x100>;
 			interrupts = <0x0 0x8 0x0 IRQ_TYPE_NONE>,
@@ -349,6 +349,12 @@
 			};
 		};
 
+		pm660_pbs: qcom,pbs@7400 {
+			compatible = "qcom,qpnp-pbs";
+			reg = <0x7400 0x100>;
+			status = "disabled";
+		};
+
 		bcl_sensor: bcl@4200 {
 			compatible = "qcom,msm-bcl-lmh";
 			reg = <0x4200 0xff>,
diff --git a/arch/arm64/boot/dts/qcom/qg-batterydata-ascent-3450mah.dtsi b/arch/arm64/boot/dts/qcom/qg-batterydata-ascent-3450mah.dtsi
index 8af4254..f28f19e2 100644
--- a/arch/arm64/boot/dts/qcom/qg-batterydata-ascent-3450mah.dtsi
+++ b/arch/arm64/boot/dts/qcom/qg-batterydata-ascent-3450mah.dtsi
@@ -32,6 +32,11 @@
 				4201000  4300000  2760000
 				4301000  4350000  2070000>;
 
+	/* COOL = 5 DegC, WARM = 40 DegC */
+	qcom,jeita-soft-thresholds = <0x44bd 0x1fc4>;
+	/* COLD = 0 DegC, HOT = 45 DegC */
+	qcom,jeita-hard-thresholds = <0x4aa5 0x1bfb>;
+
 	qcom,fcc1-temp-lut {
 		qcom,lut-col-legend = <0 10 25 40 50>;
 		qcom,lut-data = <3377 3428 3481 3496 3500>;
diff --git a/arch/arm64/boot/dts/qcom/qg-batterydata-mlp356477-2800mah.dtsi b/arch/arm64/boot/dts/qcom/qg-batterydata-mlp356477-2800mah.dtsi
index 6bcfd37..3b18010 100644
--- a/arch/arm64/boot/dts/qcom/qg-batterydata-mlp356477-2800mah.dtsi
+++ b/arch/arm64/boot/dts/qcom/qg-batterydata-mlp356477-2800mah.dtsi
@@ -29,6 +29,11 @@
 				 151 450  4400000
 				 451 550  4150000>;
 
+	/* COOL = 15 DegC, WARM = 45 DegC */
+	qcom,jeita-soft-thresholds = <0x4621 0x20b8>;
+	/* COLD = 0 DegC, HOT = 55 DegC */
+	qcom,jeita-hard-thresholds = <0x58cd 0x181d>;
+
 	qcom,fcc1-temp-lut {
 		qcom,lut-col-legend = <0 10 25 40 50>;
 		qcom,lut-data = <2715 2788 2861 2898 2908>;
diff --git a/arch/arm64/boot/dts/qcom/sda450-cdp.dts b/arch/arm64/boot/dts/qcom/sda450-cdp.dts
new file mode 100644
index 0000000..e8f22b8
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450-cdp.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sda450.dtsi"
+#include "pmi8950.dtsi"
+#include "msm8953-cdp.dtsi"
+#include "msm8953-pmi8950.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450 + PMI8950 CDP";
+	compatible = "qcom,sda450-cdp", "qcom,sda450", "qcom,cdp";
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda450-mtp.dts b/arch/arm64/boot/dts/qcom/sda450-mtp.dts
new file mode 100644
index 0000000..06002e0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450-mtp.dts
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sda450.dtsi"
+#include "pmi8950.dtsi"
+#include "msm8953-mtp.dtsi"
+#include "msm8953-pmi8950.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450 + PMI8950 MTP";
+	compatible = "qcom,sda450-mtp", "qcom,sda450", "qcom,mtp";
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
+};
+
+/{
+	mtp_batterydata: qcom,battery-data {
+		qcom,batt-id-range-pct = <15>;
+		#include "batterydata-itech-3000mah.dtsi"
+		#include "batterydata-ascent-3450mAh.dtsi"
+	};
+};
+
+&qpnp_fg {
+	qcom,battery-data = <&mtp_batterydata>;
+};
+
+&qpnp_smbcharger {
+	qcom,battery-data = <&mtp_batterydata>;
+	qcom,chg-led-sw-controls;
+	qcom,chg-led-support;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda450-pmi632-cdp-s2.dts b/arch/arm64/boot/dts/qcom/sda450-pmi632-cdp-s2.dts
new file mode 100644
index 0000000..14c5e22
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450-pmi632-cdp-s2.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sda450.dtsi"
+#include "sdm450-pmi632-cdp-s2.dtsi"
+#include "sdm450-pmi632.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450 + PMI632 CDP S2";
+	compatible = "qcom,sda450-cdp", "qcom,sda450", "qcom,cdp";
+	qcom,board-id = <1 2>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sda450-pmi632-mtp-s3.dts b/arch/arm64/boot/dts/qcom/sda450-pmi632-mtp-s3.dts
new file mode 100644
index 0000000..c907977
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450-pmi632-mtp-s3.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sda450.dtsi"
+#include "sdm450-pmi632-mtp-s3.dtsi"
+#include "sdm450-pmi632.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450 + PMI632 MTP S3";
+	compatible = "qcom,sda450-mtp", "qcom,sda450", "qcom,mtp";
+	qcom,board-id = <8 3>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sda450-pmi632.dts b/arch/arm64/boot/dts/qcom/sda450-pmi632.dts
new file mode 100644
index 0000000..1bb0b47
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450-pmi632.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sda450.dtsi"
+#include "sdm450-pmi632.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450 + PMI632 SOC";
+	compatible = "qcom,sda450";
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+	qcom,pmic-name = "PMI632";
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sda450.dts b/arch/arm64/boot/dts/qcom/sda450.dts
new file mode 100644
index 0000000..13b1622
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sda450.dtsi"
+#include "pmi8950.dtsi"
+#include "msm8953-pmi8950.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450 + PMI8950 SOC";
+	compatible = "qcom,sda450";
+	qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
+	qcom,pmic-name = "PMI8950";
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sda450.dtsi b/arch/arm64/boot/dts/qcom/sda450.dtsi
new file mode 100644
index 0000000..ba99fe9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450.dtsi
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, 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 "sdm450.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450";
+	compatible = "qcom,sda450";
+	qcom,msm-id = <351 0x0>;
+	qcom,msm-name = "SDA450";
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi b/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi
index 5075862..300c83a 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi
@@ -39,6 +39,10 @@
 	qcom,battery-data = <&mtp_batterydata>;
 };
 
+&pmi632_charger {
+	qcom,battery-data = <&mtp_batterydata>;
+};
+
 &pm8953_typec {
 	status = "disabled";
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632.dtsi b/arch/arm64/boot/dts/qcom/sdm450-pmi632.dtsi
index a4b6054..5c127bc 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632.dtsi
@@ -45,6 +45,10 @@
 	qcom,battery-data = <&mtp_batterydata>;
 };
 
+&pmi632_charger {
+	qcom,battery-data = <&mtp_batterydata>;
+};
+
 &pm8953_gpios {
 	bklt_en {
 		bklt_en_default: bklt_en_default {
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 8f213f4..f5dc2a8 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -545,7 +545,6 @@
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_QMP_DEBUGFS_CLIENT=y
-CONFIG_MEM_SHARE_QMI_SERVICE=y
 CONFIG_QSEE_IPC_IRQ_BRIDGE=y
 CONFIG_QCOM_BIMC_BWMON=y
 CONFIG_ARM_MEMLAT_MON=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index ac25fb9..8a84a2d 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -564,7 +564,6 @@
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_QMP_DEBUGFS_CLIENT=y
-CONFIG_MEM_SHARE_QMI_SERVICE=y
 CONFIG_MSM_REMOTEQDSS=y
 CONFIG_QSEE_IPC_IRQ_BRIDGE=y
 CONFIG_QCOM_BIMC_BWMON=y
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index a469eb9..6861cd5 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -26,6 +26,7 @@
 #include <linux/reboot.h>
 #include <asm/current.h>
 #include <soc/qcom/restart.h>
+#include <linux/vmalloc.h>
 #ifdef CONFIG_DIAG_OVER_USB
 #include <linux/usb/usbdiag.h>
 #endif
@@ -259,7 +260,7 @@
 	switch (type) {
 	case DCI_BUF_PRIMARY:
 		buffer->capacity = IN_BUF_SIZE;
-		buffer->data = kzalloc(buffer->capacity, GFP_KERNEL);
+		buffer->data = vzalloc(buffer->capacity);
 		if (!buffer->data)
 			return -ENOMEM;
 		break;
@@ -269,7 +270,7 @@
 		break;
 	case DCI_BUF_CMD:
 		buffer->capacity = DIAG_MAX_REQ_SIZE + DCI_BUF_SIZE;
-		buffer->data = kzalloc(buffer->capacity, GFP_KERNEL);
+		buffer->data = vzalloc(buffer->capacity);
 		if (!buffer->data)
 			return -ENOMEM;
 		break;
@@ -2726,7 +2727,7 @@
 		create_dci_event_mask_tbl(temp->event_mask_composite);
 	}
 
-	partial_pkt.data = kzalloc(MAX_DCI_PACKET_SZ, GFP_KERNEL);
+	partial_pkt.data = vzalloc(MAX_DCI_PACKET_SZ);
 	if (!partial_pkt.data)
 		return -ENOMEM;
 
@@ -2780,7 +2781,7 @@
 		goto err;
 
 	if (driver->apps_dci_buf == NULL) {
-		driver->apps_dci_buf = kzalloc(DCI_BUF_SIZE, GFP_KERNEL);
+		driver->apps_dci_buf = vzalloc(DCI_BUF_SIZE);
 		if (driver->apps_dci_buf == NULL)
 			goto err;
 	}
@@ -2797,12 +2798,12 @@
 	return DIAG_DCI_NO_ERROR;
 err:
 	pr_err("diag: Could not initialize diag DCI buffers");
-	kfree(driver->apps_dci_buf);
+	vfree(driver->apps_dci_buf);
 	driver->apps_dci_buf = NULL;
 
 	if (driver->diag_dci_wq)
 		destroy_workqueue(driver->diag_dci_wq);
-	kfree(partial_pkt.data);
+	vfree(partial_pkt.data);
 	partial_pkt.data = NULL;
 	mutex_destroy(&driver->dci_mutex);
 	mutex_destroy(&dci_log_mask_mutex);
@@ -2822,9 +2823,9 @@
 
 void diag_dci_exit(void)
 {
-	kfree(partial_pkt.data);
+	vfree(partial_pkt.data);
 	partial_pkt.data = NULL;
-	kfree(driver->apps_dci_buf);
+	vfree(driver->apps_dci_buf);
 	driver->apps_dci_buf = NULL;
 	mutex_destroy(&driver->dci_mutex);
 	mutex_destroy(&dci_log_mask_mutex);
@@ -2962,7 +2963,7 @@
 	new_entry->in_service = 0;
 	INIT_LIST_HEAD(&new_entry->list_write_buf);
 	mutex_init(&new_entry->write_buf_mutex);
-	new_entry->dci_log_mask =  kzalloc(DCI_LOG_MASK_SIZE, GFP_KERNEL);
+	new_entry->dci_log_mask =  vzalloc(DCI_LOG_MASK_SIZE);
 	if (!new_entry->dci_log_mask) {
 		pr_err("diag: Unable to create log mask for client, %d",
 							driver->dci_client_id);
@@ -2970,14 +2971,14 @@
 	}
 	create_dci_log_mask_tbl(new_entry->dci_log_mask, DCI_LOG_MASK_CLEAN);
 
-	new_entry->dci_event_mask =  kzalloc(DCI_EVENT_MASK_SIZE, GFP_KERNEL);
+	new_entry->dci_event_mask =  vzalloc(DCI_EVENT_MASK_SIZE);
 	if (!new_entry->dci_event_mask)
 		goto fail_alloc;
 	create_dci_event_mask_tbl(new_entry->dci_event_mask);
 
 	new_entry->buffers = kzalloc(new_entry->num_buffers *
 				     sizeof(struct diag_dci_buf_peripheral_t),
-				     GFP_KERNEL);
+					GFP_KERNEL);
 	if (!new_entry->buffers) {
 		pr_err("diag: Unable to allocate buffers for peripherals in %s\n",
 								__func__);
@@ -3001,7 +3002,7 @@
 		if (!proc_buf->buf_primary)
 			goto fail_alloc;
 		proc_buf->buf_cmd = kzalloc(sizeof(struct diag_dci_buffer_t),
-					    GFP_KERNEL);
+					GFP_KERNEL);
 		if (!proc_buf->buf_cmd)
 			goto fail_alloc;
 		err = diag_dci_init_buffer(proc_buf->buf_primary,
@@ -3034,7 +3035,7 @@
 			if (proc_buf) {
 				mutex_destroy(&proc_buf->health_mutex);
 				if (proc_buf->buf_primary) {
-					kfree(proc_buf->buf_primary->data);
+					vfree(proc_buf->buf_primary->data);
 					proc_buf->buf_primary->data = NULL;
 					mutex_destroy(
 					   &proc_buf->buf_primary->data_mutex);
@@ -3042,7 +3043,7 @@
 				kfree(proc_buf->buf_primary);
 				proc_buf->buf_primary = NULL;
 				if (proc_buf->buf_cmd) {
-					kfree(proc_buf->buf_cmd->data);
+					vfree(proc_buf->buf_cmd->data);
 					proc_buf->buf_cmd->data = NULL;
 					mutex_destroy(
 					   &proc_buf->buf_cmd->data_mutex);
@@ -3051,9 +3052,9 @@
 				proc_buf->buf_cmd = NULL;
 			}
 		}
-		kfree(new_entry->dci_event_mask);
+		vfree(new_entry->dci_event_mask);
 		new_entry->dci_event_mask = NULL;
-		kfree(new_entry->dci_log_mask);
+		vfree(new_entry->dci_log_mask);
 		new_entry->dci_log_mask = NULL;
 		kfree(new_entry->buffers);
 		new_entry->buffers = NULL;
@@ -3088,7 +3089,7 @@
 	 * Clear the client's log and event masks, update the cumulative
 	 * masks and send the masks to peripherals
 	 */
-	kfree(entry->dci_log_mask);
+	vfree(entry->dci_log_mask);
 	entry->dci_log_mask = NULL;
 	diag_dci_invalidate_cumulative_log_mask(token);
 	if (token == DCI_LOCAL_PROC)
@@ -3096,7 +3097,7 @@
 	ret = dci_ops_tbl[token].send_log_mask(token);
 	if (ret != DIAG_DCI_NO_ERROR)
 		return ret;
-	kfree(entry->dci_event_mask);
+	vfree(entry->dci_event_mask);
 	entry->dci_event_mask = NULL;
 	diag_dci_invalidate_cumulative_event_mask(token);
 	if (token == DCI_LOCAL_PROC)
@@ -3159,12 +3160,12 @@
 		}
 
 		mutex_lock(&proc_buf->buf_primary->data_mutex);
-		kfree(proc_buf->buf_primary->data);
+		vfree(proc_buf->buf_primary->data);
 		proc_buf->buf_primary->data = NULL;
 		mutex_unlock(&proc_buf->buf_primary->data_mutex);
 
 		mutex_lock(&proc_buf->buf_cmd->data_mutex);
-		kfree(proc_buf->buf_cmd->data);
+		vfree(proc_buf->buf_cmd->data);
 		proc_buf->buf_cmd->data = NULL;
 		mutex_unlock(&proc_buf->buf_cmd->data_mutex);
 
diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c
index 97b0cb2..6c8e664 100644
--- a/drivers/gpu/msm/adreno_a6xx_preempt.c
+++ b/drivers/gpu/msm/adreno_a6xx_preempt.c
@@ -749,6 +749,9 @@
 	if (context->flags & KGSL_CONTEXT_SECURE)
 		flags |= KGSL_MEMFLAGS_SECURE;
 
+	if (kgsl_is_compat_task())
+		flags |= KGSL_MEMFLAGS_FORCE_32BIT;
+
 	/*
 	 * gpumem_alloc_entry takes an extra refcount. Put it only when
 	 * destroying the context to keep the context record valid
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 2e617429..bb9f9ff 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2402,6 +2402,9 @@
 	if (!MMU_FEATURE(mmu, KGSL_MMU_IO_COHERENT))
 		param->flags &= ~((uint64_t)KGSL_MEMFLAGS_IOCOHERENT);
 
+	if (kgsl_is_compat_task())
+		param->flags |= KGSL_MEMFLAGS_FORCE_32BIT;
+
 	entry->memdesc.flags = param->flags;
 
 	if (MMU_FEATURE(mmu, KGSL_MMU_NEED_GUARD_PAGE))
@@ -2692,8 +2695,10 @@
 	if (!MMU_FEATURE(mmu, KGSL_MMU_IO_COHERENT))
 		param->flags &= ~((uint64_t)KGSL_MEMFLAGS_IOCOHERENT);
 
-	entry->memdesc.flags = ((uint64_t) param->flags)
-		| KGSL_MEMFLAGS_FORCE_32BIT;
+	entry->memdesc.flags = (uint64_t) param->flags;
+
+	if (kgsl_is_compat_task())
+		entry->memdesc.flags |= KGSL_MEMFLAGS_FORCE_32BIT;
 
 	if (!kgsl_mmu_use_cpu_map(mmu))
 		entry->memdesc.flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP);
@@ -3197,6 +3202,9 @@
 	struct kgsl_gpuobj_alloc *param = data;
 	struct kgsl_mem_entry *entry;
 
+	if (kgsl_is_compat_task())
+		param->flags |= KGSL_MEMFLAGS_FORCE_32BIT;
+
 	entry = gpumem_alloc_entry(dev_priv, param->size, param->flags);
 
 	if (IS_ERR(entry))
@@ -3224,7 +3232,9 @@
 
 	/* Legacy functions doesn't support these advanced features */
 	flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP);
-	flags |= KGSL_MEMFLAGS_FORCE_32BIT;
+
+	if (kgsl_is_compat_task())
+		flags |= KGSL_MEMFLAGS_FORCE_32BIT;
 
 	entry = gpumem_alloc_entry(dev_priv, (uint64_t) param->size, flags);
 
@@ -3248,7 +3258,8 @@
 	struct kgsl_mem_entry *entry;
 	uint64_t flags = param->flags;
 
-	flags |= KGSL_MEMFLAGS_FORCE_32BIT;
+	if (kgsl_is_compat_task())
+		flags |= KGSL_MEMFLAGS_FORCE_32BIT;
 
 	entry = gpumem_alloc_entry(dev_priv, (uint64_t) param->size, flags);
 
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index f4a2de5..1fa2717 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,6 +27,7 @@
 #include <linux/uaccess.h>
 #include <linux/kthread.h>
 #include <asm/cacheflush.h>
+#include <linux/compat.h>
 
 /*
  * --- kgsl drawobj flags ---
@@ -628,4 +629,9 @@
 
 	kernfs_create_link(dst->sd, dst_name, old);
 }
+
+static inline bool kgsl_is_compat_task(void)
+{
+	return (BITS_PER_LONG == 32) || is_compat_task();
+}
 #endif /* __KGSL_H */
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index c4296c8..0ce72f6 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1052,7 +1052,7 @@
 
 	if (pagetable->name != KGSL_MMU_GLOBAL_PT &&
 		pagetable->name != KGSL_MMU_SECURE_PT) {
-		if ((BITS_PER_LONG == 32) || is_compat_task()) {
+		if (kgsl_is_compat_task()) {
 			pt->svm_start = KGSL_IOMMU_SVM_BASE32;
 			pt->svm_end = KGSL_IOMMU_SECURE_BASE(mmu);
 		} else {
diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c
index 36d07c5..93c28ef 100644
--- a/drivers/input/misc/qpnp-power-on.c
+++ b/drivers/input/misc/qpnp-power-on.c
@@ -31,6 +31,8 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/input/qpnp-power-on.h>
+#include <linux/qpnp/qpnp-pbs.h>
+#include <linux/qpnp/qpnp-misc.h>
 #include <linux/power_supply.h>
 
 #define PMIC_VER_8941           0x01
@@ -203,6 +205,7 @@
 	struct list_head	list;
 	struct delayed_work	bark_work;
 	struct dentry		*debugfs;
+	struct device_node      *pbs_dev_node;
 	int			pon_trigger_reason;
 	int			pon_power_off_reason;
 	int			num_pon_reg;
@@ -220,6 +223,7 @@
 	u8			pon_ver;
 	u8			warm_reset_reason1;
 	u8			warm_reset_reason2;
+	u8                      twm_state;
 	bool			is_spon;
 	bool			store_hard_reset_reason;
 	bool			resin_hard_reset_disable;
@@ -227,8 +231,10 @@
 	bool			ps_hold_hard_reset_disable;
 	bool			ps_hold_shutdown_disable;
 	bool			kpdpwr_dbc_enable;
+	bool                    support_twm_config;
 	bool			resin_pon_reset;
 	ktime_t			kpdpwr_last_release_time;
+	struct notifier_block   pon_nb;
 	bool			legacy_hard_reset_offset;
 };
 
@@ -483,6 +489,7 @@
 
 static DEVICE_ATTR(debounce_us, 0664, qpnp_pon_dbc_show, qpnp_pon_dbc_store);
 
+#define PON_TWM_ENTRY_PBS_BIT           BIT(0)
 static int qpnp_pon_reset_config(struct qpnp_pon *pon,
 		enum pon_power_off_type type)
 {
@@ -490,6 +497,19 @@
 	bool disable = false;
 	u16 rst_en_reg;
 
+	/* Ignore the PS_HOLD reset config if TWM ENTRY is enabled */
+	if (pon->support_twm_config && pon->twm_state == PMIC_TWM_ENABLE) {
+		rc = qpnp_pbs_trigger_event(pon->pbs_dev_node,
+					PON_TWM_ENTRY_PBS_BIT);
+		if (rc < 0) {
+			pr_err("Unable to trigger PBS trigger for TWM entry rc=%d\n",
+							rc);
+			return rc;
+		}
+		pr_crit("PMIC configured for TWM entry\n");
+		return 0;
+	}
+
 	if (pon->pon_ver == QPNP_PON_GEN1_V1)
 		rst_en_reg = QPNP_PON_PS_HOLD_RST_CTL(pon);
 	else
@@ -2087,6 +2107,35 @@
 	return 0;
 }
 
+static int pon_twm_notifier_cb(struct notifier_block *nb,
+				unsigned long action, void *data)
+{
+	struct qpnp_pon *pon = container_of(nb, struct qpnp_pon, pon_nb);
+
+	if (action != PMIC_TWM_CLEAR &&
+			action != PMIC_TWM_ENABLE) {
+		pr_debug("Unsupported option %lu\n", action);
+		return NOTIFY_OK;
+	}
+
+	pon->twm_state = (u8)action;
+	pr_debug("TWM state = %d\n", pon->twm_state);
+
+	return NOTIFY_OK;
+}
+
+static int pon_register_twm_notifier(struct qpnp_pon *pon)
+{
+	int rc;
+
+	pon->pon_nb.notifier_call = pon_twm_notifier_cb;
+	rc = qpnp_misc_twm_notifier_register(&pon->pon_nb);
+	if (rc < 0)
+		pr_err("Failed to register pon_twm_notifier_cb rc=%d\n", rc);
+
+	return rc;
+}
+
 static int qpnp_pon_probe(struct platform_device *pdev)
 {
 	struct qpnp_pon *pon;
@@ -2364,6 +2413,22 @@
 		goto err_out;
 	}
 
+	if (of_property_read_bool(pon->pdev->dev.of_node,
+					"qcom,support-twm-config")) {
+		pon->support_twm_config = true;
+		rc = pon_register_twm_notifier(pon);
+		if (rc < 0) {
+			pr_err("Failed to register TWM notifier rc=%d\n", rc);
+			return rc;
+		}
+		pon->pbs_dev_node = of_parse_phandle(pon->pdev->dev.of_node,
+						"qcom,pbs-client", 0);
+		if (!pon->pbs_dev_node) {
+			pr_err("Missing qcom,pbs-client property\n");
+			return -EINVAL;
+		}
+	}
+
 	rc = of_property_read_u32(pon->pdev->dev.of_node,
 				"qcom,pon-dbc-delay", &delay);
 	if (rc) {
diff --git a/drivers/misc/qpnp-misc.c b/drivers/misc/qpnp-misc.c
index 690b28b..eec0875 100644
--- a/drivers/misc/qpnp-misc.c
+++ b/drivers/misc/qpnp-misc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014,2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014,2016-2018, 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
@@ -17,6 +17,7 @@
 #include <linux/regmap.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/notifier.h>
 #include <linux/qpnp/qpnp-misc.h>
 
 #define QPNP_MISC_DEV_NAME "qcom,qpnp-misc"
@@ -29,8 +30,20 @@
 #define PWM_SEL_MAX		0x03
 #define GP_DRIVER_EN_BIT	BIT(0)
 
+enum twm {
+	TWM_MODE_1 = 1,
+	TWM_MODE_2,
+	TWM_MODE_3,
+};
+
+enum twm_attrib {
+	TWM_ENABLE,
+	TWM_EXIT,
+};
+
 static DEFINE_MUTEX(qpnp_misc_dev_list_mutex);
 static LIST_HEAD(qpnp_misc_dev_list);
+static RAW_NOTIFIER_HEAD(twm_notifier);
 
 struct qpnp_misc_version {
 	u8	subtype;
@@ -55,10 +68,14 @@
 	struct device			*dev;
 	struct regmap			*regmap;
 	struct qpnp_misc_version	version;
+	struct class			twm_class;
 
+	u8				twm_mode;
 	u32				base;
 	u8				pwm_sel;
 	bool				enable_gp_driver;
+	bool				support_twm_config;
+	bool				twm_enable;
 };
 
 static const struct of_device_id qpnp_misc_match_table[] = {
@@ -211,12 +228,100 @@
 	return __misc_irqs_available(mdev_found);
 }
 
+#define MISC_SPARE_1		0x50
+#define MISC_SPARE_2		0x51
+#define ENABLE_TWM_MODE		0x80
+#define DISABLE_TWM_MODE	0x0
+#define TWM_EXIT_BIT		BIT(0)
+static ssize_t twm_enable_store(struct class *c,
+			struct class_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct qpnp_misc_dev *mdev = container_of(c,
+			struct qpnp_misc_dev, twm_class);
+	u8 val = 0;
+	ssize_t rc = 0;
+
+	rc = kstrtou8(buf, 10, &val);
+	if (rc < 0)
+		return rc;
+
+	mdev->twm_enable = val ? true : false;
+
+	/* Notify the TWM state */
+	raw_notifier_call_chain(&twm_notifier,
+		mdev->twm_enable ? PMIC_TWM_ENABLE : PMIC_TWM_CLEAR, NULL);
+
+	return count;
+}
+
+static ssize_t twm_enable_show(struct class *c,
+			struct class_attribute *attr, char *buf)
+{
+	struct qpnp_misc_dev *mdev = container_of(c,
+			struct qpnp_misc_dev, twm_class);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", mdev->twm_enable);
+}
+
+static ssize_t twm_exit_show(struct class *c,
+			struct class_attribute *attr, char *buf)
+{
+	struct qpnp_misc_dev *mdev = container_of(c,
+			struct qpnp_misc_dev, twm_class);
+	int rc = 0;
+	u8 val = 0;
+
+	rc = qpnp_read_byte(mdev, MISC_SPARE_1, &val);
+	if (rc < 0) {
+		pr_err("Failed to read TWM enable (misc_spare_1) rc=%d\n", rc);
+		return rc;
+	}
+
+	pr_debug("TWM_EXIT (misc_spare_1) register = 0x%02x\n", val);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", !!(val & TWM_EXIT_BIT));
+}
+
+static struct class_attribute twm_attributes[] = {
+	[TWM_ENABLE]		= __ATTR(twm_enable, 0644,
+					twm_enable_show, twm_enable_store),
+	[TWM_EXIT]		= __ATTR(twm_exit, 0644,
+					twm_exit_show, NULL),
+	__ATTR_NULL,
+};
+
+int qpnp_misc_twm_notifier_register(struct notifier_block *nb)
+{
+	return raw_notifier_chain_register(&twm_notifier, nb);
+}
+EXPORT_SYMBOL(qpnp_misc_twm_notifier_register);
+
+int qpnp_misc_twm_notifier_unregister(struct notifier_block *nb)
+{
+	return raw_notifier_chain_unregister(&twm_notifier, nb);
+}
+EXPORT_SYMBOL(qpnp_misc_twm_notifier_unregister);
+
 static int qpnp_misc_dt_init(struct qpnp_misc_dev *mdev)
 {
 	struct device_node *node = mdev->dev->of_node;
 	u32 val;
 	int rc;
 
+	if (of_property_read_bool(mdev->dev->of_node,
+				"qcom,support-twm-config")) {
+		mdev->support_twm_config = true;
+		mdev->twm_mode = TWM_MODE_3;
+		rc = of_property_read_u8(mdev->dev->of_node, "qcom,twm-mode",
+							&mdev->twm_mode);
+		if (!rc && (mdev->twm_mode < TWM_MODE_1 ||
+				mdev->twm_mode > TWM_MODE_3)) {
+			pr_err("Invalid TWM mode %d\n", mdev->twm_mode);
+			return -EINVAL;
+		}
+	}
+
 	rc = of_property_read_u32(node, "reg", &mdev->base);
 	if (rc < 0 || !mdev->base) {
 		dev_err(mdev->dev, "Base address not defined or invalid\n");
@@ -270,6 +375,18 @@
 		break;
 	}
 
+	if (mdev->support_twm_config) {
+		mdev->twm_class.name = "pmic_twm",
+		mdev->twm_class.owner = THIS_MODULE,
+		mdev->twm_class.class_attrs = twm_attributes;
+
+		rc = class_register(&mdev->twm_class);
+		if (rc < 0) {
+			pr_err("Failed to register pmic_twm class rc=%d\n", rc);
+			return rc;
+		}
+	}
+
 	return 0;
 }
 
@@ -283,6 +400,7 @@
 		return -ENOMEM;
 
 	mdev->dev = &pdev->dev;
+	dev_set_drvdata(&pdev->dev, mdev);
 	mdev->regmap = dev_get_regmap(mdev->dev->parent, NULL);
 	if (!mdev->regmap) {
 		dev_err(mdev->dev, "Parent regmap is unavailable\n");
@@ -325,8 +443,33 @@
 	return 0;
 }
 
+static void qpnp_misc_shutdown(struct platform_device *pdev)
+{
+	struct qpnp_misc_dev *mdev = dev_get_drvdata(&pdev->dev);
+	int rc;
+
+	if (mdev->support_twm_config) {
+		rc = qpnp_write_byte(mdev, MISC_SPARE_2,
+				mdev->twm_enable ? mdev->twm_mode : 0x0);
+		if (rc < 0)
+			pr_err("Failed to write MISC_SPARE_2 (twm_mode) val=%d rc=%d\n",
+				mdev->twm_enable ? mdev->twm_mode : 0x0, rc);
+
+		rc = qpnp_write_byte(mdev, MISC_SPARE_1,
+				mdev->twm_enable ? ENABLE_TWM_MODE : 0x0);
+		if (rc < 0)
+			pr_err("Failed to write MISC_SPARE_1 (twm_state) val=%d rc=%d\n",
+				mdev->twm_enable ? ENABLE_TWM_MODE : 0x0, rc);
+
+		pr_debug("PMIC configured for TWM-%s MODE=%d\n",
+				mdev->twm_enable ? "enabled" : "disabled",
+				mdev->twm_mode);
+	}
+}
+
 static struct platform_driver qpnp_misc_driver = {
 	.probe	= qpnp_misc_probe,
+	.shutdown = qpnp_misc_shutdown,
 	.driver	= {
 		.name		= QPNP_MISC_DEV_NAME,
 		.owner		= THIS_MODULE,
diff --git a/drivers/net/wireless/cnss2/debug.c b/drivers/net/wireless/cnss2/debug.c
index a3cf6c2..b1fbbd8 100644
--- a/drivers/net/wireless/cnss2/debug.c
+++ b/drivers/net/wireless/cnss2/debug.c
@@ -137,11 +137,17 @@
 {
 	struct cnss_plat_data *plat_priv =
 		((struct seq_file *)fp->private_data)->private;
+	struct cnss_pci_data *pci_priv;
 	char buf[64];
 	char *cmd;
 	unsigned int len = 0;
 	int ret = 0;
 
+	if (!plat_priv)
+		return -ENODEV;
+
+	pci_priv = plat_priv->bus_priv;
+
 	len = min(count, sizeof(buf) - 1);
 	if (copy_from_user(buf, user_buf, len))
 		return -EFAULT;
@@ -157,11 +163,11 @@
 		ret = cnss_pci_init(plat_priv);
 	} else if (sysfs_streq(cmd, "download")) {
 		set_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
-		ret = cnss_pci_start_mhi(plat_priv->bus_priv);
+		ret = cnss_pci_start_mhi(pci_priv);
 	} else if (sysfs_streq(cmd, "linkup")) {
-		ret = cnss_resume_pci_link(plat_priv->bus_priv);
+		ret = cnss_resume_pci_link(pci_priv);
 	} else if (sysfs_streq(cmd, "linkdown")) {
-		ret = cnss_suspend_pci_link(plat_priv->bus_priv);
+		ret = cnss_suspend_pci_link(pci_priv);
 	} else if (sysfs_streq(cmd, "powerup")) {
 		set_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
 		ret = cnss_driver_event_post(plat_priv,
@@ -172,6 +178,8 @@
 					     CNSS_DRIVER_EVENT_POWER_DOWN,
 					     0, NULL);
 		clear_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
+	} else if (sysfs_streq(cmd, "assert")) {
+		ret = cnss_force_fw_assert(&pci_priv->pci_dev->dev);
 	} else {
 		cnss_pr_err("Device boot debugfs command is invalid\n");
 		ret = -EINVAL;
@@ -195,6 +203,7 @@
 	seq_puts(s, "linkdown: bring down PCIe link\n");
 	seq_puts(s, "powerup: full power on sequence to boot device, download FW and do QMI handshake with FW\n");
 	seq_puts(s, "shutdown: full power off sequence to shutdown device\n");
+	seq_puts(s, "assert: trigger firmware assert\n");
 
 	return 0;
 }
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index 098631e..9d1fbf9 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -1458,8 +1458,7 @@
 		ret = mhi_pm_resume(pci_priv->mhi_ctrl);
 		break;
 	case CNSS_MHI_TRIGGER_RDDM:
-		cnss_pr_dbg("Bypass MHI state: %s(%d)\n",
-			    cnss_mhi_state_to_str(mhi_state), mhi_state);
+		ret = mhi_force_rddm_mode(pci_priv->mhi_ctrl);
 		break;
 	default:
 		cnss_pr_err("Unhandled MHI state (%d)\n", mhi_state);
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index d675e46..4d4b4cf 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -337,6 +337,7 @@
 	POWER_SUPPLY_ATTR(manufacturer),
 	POWER_SUPPLY_ATTR(serial_number),
 	POWER_SUPPLY_ATTR(battery_type),
+	POWER_SUPPLY_ATTR(cycle_counts),
 };
 
 static struct attribute *
diff --git a/drivers/power/supply/qcom/fg-alg.c b/drivers/power/supply/qcom/fg-alg.c
new file mode 100644
index 0000000..3d74f7e
--- /dev/null
+++ b/drivers/power/supply/qcom/fg-alg.c
@@ -0,0 +1,606 @@
+/* Copyright (c) 2018, 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)	"ALG: %s: " fmt, __func__
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/power_supply.h>
+#include "fg-alg.h"
+
+#define FULL_SOC_RAW		255
+#define CAPACITY_DELTA_DECIPCT	500
+
+/* Cycle counter APIs */
+
+/**
+ * restore_cycle_count -
+ * @counter: Cycle counter object
+ *
+ * Restores all the counters back from FG/QG during boot
+ *
+ */
+int restore_cycle_count(struct cycle_counter *counter)
+{
+	int rc = 0;
+
+	if (!counter)
+		return -ENODEV;
+
+	mutex_lock(&counter->lock);
+	rc = counter->restore_count(counter->data, counter->count,
+			BUCKET_COUNT);
+	if (rc < 0)
+		pr_err("failed to restore cycle counter rc=%d\n", rc);
+	mutex_unlock(&counter->lock);
+
+	return rc;
+}
+
+/**
+ * clear_cycle_count -
+ * @counter: Cycle counter object
+ *
+ * Clears all the counters stored by FG/QG when a battery is inserted
+ * or the profile is re-loaded.
+ *
+ */
+void clear_cycle_count(struct cycle_counter *counter)
+{
+	int rc = 0, i;
+
+	if (!counter)
+		return;
+
+	mutex_lock(&counter->lock);
+	memset(counter->count, 0, sizeof(counter->count));
+	for (i = 0; i < BUCKET_COUNT; i++) {
+		counter->started[i] = false;
+		counter->last_soc[i] = 0;
+	}
+
+	rc = counter->store_count(counter->data, counter->count, 0,
+			BUCKET_COUNT * 2);
+	if (rc < 0)
+		pr_err("failed to clear cycle counter rc=%d\n", rc);
+
+	mutex_unlock(&counter->lock);
+}
+
+/**
+ * store_cycle_count -
+ * @counter: Cycle counter object
+ * @id: Cycle counter bucket id
+ *
+ * Stores the cycle counter for a bucket in FG/QG.
+ *
+ */
+static int store_cycle_count(struct cycle_counter *counter, int id)
+{
+	int rc = 0;
+	u16 cyc_count;
+
+	if (!counter)
+		return -ENODEV;
+
+	if (id < 0 || (id > BUCKET_COUNT - 1)) {
+		pr_err("Invalid id %d\n", id);
+		return -EINVAL;
+	}
+
+	cyc_count = counter->count[id];
+	cyc_count++;
+
+	rc = counter->store_count(counter->data, &cyc_count, id, 2);
+	if (rc < 0) {
+		pr_err("failed to write cycle_count[%d] rc=%d\n",
+			id, rc);
+		return rc;
+	}
+
+	counter->count[id] = cyc_count;
+	pr_debug("Stored count %d in id %d\n", cyc_count, id);
+
+	return rc;
+}
+
+/**
+ * cycle_count_update -
+ * @counter: Cycle counter object
+ * @batt_soc: Battery State of Charge (SOC)
+ * @charge_status: Charging status from power supply
+ * @charge_done: Indicator for charge termination
+ * @input_present: Indicator for input presence
+ *
+ * Called by FG/QG whenever there is a state change (Charging status, SOC)
+ *
+ */
+void cycle_count_update(struct cycle_counter *counter, int batt_soc,
+			int charge_status, bool charge_done, bool input_present)
+{
+	int rc = 0, id, i, soc_thresh;
+
+	if (!counter)
+		return;
+
+	mutex_lock(&counter->lock);
+
+	/* Find out which id the SOC falls in */
+	id = batt_soc / BUCKET_SOC_PCT;
+
+	if (charge_status == POWER_SUPPLY_STATUS_CHARGING) {
+		if (!counter->started[id] && id != counter->last_bucket) {
+			counter->started[id] = true;
+			counter->last_soc[id] = batt_soc;
+		}
+	} else if (charge_done || !input_present) {
+		for (i = 0; i < BUCKET_COUNT; i++) {
+			soc_thresh = counter->last_soc[i] + BUCKET_SOC_PCT / 2;
+			if (counter->started[i] && batt_soc > soc_thresh) {
+				rc = store_cycle_count(counter, i);
+				if (rc < 0)
+					pr_err("Error in storing cycle_ctr rc: %d\n",
+						rc);
+				counter->last_soc[i] = 0;
+				counter->started[i] = false;
+				counter->last_bucket = i;
+			}
+		}
+	}
+
+	pr_debug("batt_soc: %d id: %d chg_status: %d\n", batt_soc, id,
+		charge_status);
+	mutex_unlock(&counter->lock);
+}
+
+/**
+ * get_cycle_count -
+ * @counter: Cycle counter object
+ *
+ * Returns the cycle counter for a SOC bucket.
+ *
+ */
+int get_cycle_count(struct cycle_counter *counter)
+{
+	int count;
+
+	if (!counter)
+		return 0;
+
+	if ((counter->id <= 0) || (counter->id > BUCKET_COUNT))
+		return -EINVAL;
+
+	mutex_lock(&counter->lock);
+	count = counter->count[counter->id - 1];
+	mutex_unlock(&counter->lock);
+	return count;
+}
+
+/**
+ * cycle_count_init -
+ * @counter: Cycle counter object
+ *
+ * FG/QG have to call this during driver probe to validate the required
+ * parameters after allocating cycle_counter object.
+ *
+ */
+int cycle_count_init(struct cycle_counter *counter)
+{
+	if (!counter)
+		return -ENODEV;
+
+	if (!counter->data || !counter->restore_count ||
+		!counter->store_count) {
+		pr_err("Invalid parameters for using cycle counter\n");
+		return -EINVAL;
+	}
+
+	mutex_init(&counter->lock);
+	counter->last_bucket = -1;
+	return 0;
+}
+
+/* Capacity learning algorithm APIs */
+
+/**
+ * cap_learning_post_process -
+ * @cl: Capacity learning object
+ *
+ * Does post processing on the learnt capacity based on the user specified
+ * or default parameters for the capacity learning algorithm.
+ *
+ */
+static void cap_learning_post_process(struct cap_learning *cl)
+{
+	int64_t max_inc_val, min_dec_val, old_cap;
+	int rc;
+
+	if (cl->dt.skew_decipct) {
+		pr_debug("applying skew %d on current learnt capacity %lld\n",
+			cl->dt.skew_decipct, cl->final_cap_uah);
+		cl->final_cap_uah = cl->final_cap_uah *
+					(1000 + cl->dt.skew_decipct);
+		cl->final_cap_uah = div64_u64(cl->final_cap_uah, 1000);
+	}
+
+	max_inc_val = cl->learned_cap_uah * (1000 + cl->dt.max_cap_inc);
+	max_inc_val = div64_u64(max_inc_val, 1000);
+
+	min_dec_val = cl->learned_cap_uah * (1000 - cl->dt.max_cap_dec);
+	min_dec_val = div64_u64(min_dec_val, 1000);
+
+	old_cap = cl->learned_cap_uah;
+	if (cl->final_cap_uah > max_inc_val)
+		cl->learned_cap_uah = max_inc_val;
+	else if (cl->final_cap_uah < min_dec_val)
+		cl->learned_cap_uah = min_dec_val;
+	else
+		cl->learned_cap_uah = cl->final_cap_uah;
+
+	if (cl->dt.max_cap_limit) {
+		max_inc_val = (int64_t)cl->nom_cap_uah * (1000 +
+				cl->dt.max_cap_limit);
+		max_inc_val = div64_u64(max_inc_val, 1000);
+		if (cl->final_cap_uah > max_inc_val) {
+			pr_debug("learning capacity %lld goes above max limit %lld\n",
+				cl->final_cap_uah, max_inc_val);
+			cl->learned_cap_uah = max_inc_val;
+		}
+	}
+
+	if (cl->dt.min_cap_limit) {
+		min_dec_val = (int64_t)cl->nom_cap_uah * (1000 -
+				cl->dt.min_cap_limit);
+		min_dec_val = div64_u64(min_dec_val, 1000);
+		if (cl->final_cap_uah < min_dec_val) {
+			pr_debug("learning capacity %lld goes below min limit %lld\n",
+				cl->final_cap_uah, min_dec_val);
+			cl->learned_cap_uah = min_dec_val;
+		}
+	}
+
+	if (cl->store_learned_capacity) {
+		rc = cl->store_learned_capacity(cl->data, cl->learned_cap_uah);
+		if (rc < 0)
+			pr_err("Error in storing learned_cap_uah, rc=%d\n", rc);
+	}
+
+	pr_debug("final cap_uah = %lld, learned capacity %lld -> %lld uah\n",
+		cl->final_cap_uah, old_cap, cl->learned_cap_uah);
+}
+
+/**
+ * cap_learning_process_full_data -
+ * @cl: Capacity learning object
+ *
+ * Processes the coulomb counter during charge termination and calculates the
+ * delta w.r.to the coulomb counter obtained earlier when the learning begun.
+ *
+ */
+static int cap_learning_process_full_data(struct cap_learning *cl)
+{
+	int rc, cc_soc_sw, cc_soc_delta_pct;
+	int64_t delta_cap_uah;
+
+	rc = cl->get_cc_soc(cl->data, &cc_soc_sw);
+	if (rc < 0) {
+		pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
+		return rc;
+	}
+
+	cc_soc_delta_pct =
+		div64_s64((int64_t)(cc_soc_sw - cl->init_cc_soc_sw) * 100,
+			cl->cc_soc_max);
+
+	/* If the delta is < 50%, then skip processing full data */
+	if (cc_soc_delta_pct < 50) {
+		pr_err("cc_soc_delta_pct: %d\n", cc_soc_delta_pct);
+		return -ERANGE;
+	}
+
+	delta_cap_uah = div64_s64(cl->learned_cap_uah * cc_soc_delta_pct, 100);
+	cl->final_cap_uah = cl->init_cap_uah + delta_cap_uah;
+	pr_debug("Current cc_soc=%d cc_soc_delta_pct=%d total_cap_uah=%lld\n",
+		cc_soc_sw, cc_soc_delta_pct, cl->final_cap_uah);
+	return 0;
+}
+
+/**
+ * cap_learning_begin -
+ * @cl: Capacity learning object
+ * @batt_soc: Battery State of Charge (SOC)
+ *
+ * Gets the coulomb counter from FG/QG when the conditions are suitable for
+ * beginning capacity learning. Also, primes the coulomb counter based on
+ * battery SOC if required.
+ *
+ */
+static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc)
+{
+	int rc, cc_soc_sw, batt_soc_msb;
+
+	batt_soc_msb = batt_soc >> 24;
+	if (DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW) >
+		cl->dt.start_soc) {
+		pr_debug("Battery SOC %d is high!, not starting\n",
+			batt_soc_msb);
+		return -EINVAL;
+	}
+
+	cl->init_cap_uah = div64_s64(cl->learned_cap_uah * batt_soc_msb,
+					FULL_SOC_RAW);
+
+	if (cl->prime_cc_soc) {
+		/*
+		 * Prime cc_soc_sw with battery SOC when capacity learning
+		 * begins.
+		 */
+		rc = cl->prime_cc_soc(cl->data, batt_soc);
+		if (rc < 0) {
+			pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
+			goto out;
+		}
+	}
+
+	rc = cl->get_cc_soc(cl->data, &cc_soc_sw);
+	if (rc < 0) {
+		pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
+		goto out;
+	}
+
+	cl->init_cc_soc_sw = cc_soc_sw;
+	pr_debug("Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n",
+		batt_soc_msb, cl->init_cc_soc_sw);
+out:
+	return rc;
+}
+
+/**
+ * cap_learning_done -
+ * @cl: Capacity learning object
+ *
+ * Top level function for getting coulomb counter and post processing the
+ * data once the capacity learning is complete after charge termination.
+ *
+ */
+static int cap_learning_done(struct cap_learning *cl)
+{
+	int rc;
+
+	rc = cap_learning_process_full_data(cl);
+	if (rc < 0) {
+		pr_err("Error in processing cap learning full data, rc=%d\n",
+			rc);
+		goto out;
+	}
+
+	if (cl->prime_cc_soc) {
+		/* Write a FULL value to cc_soc_sw */
+		rc = cl->prime_cc_soc(cl->data, cl->cc_soc_max);
+		if (rc < 0) {
+			pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
+			goto out;
+		}
+	}
+
+	cap_learning_post_process(cl);
+out:
+	return rc;
+}
+
+/**
+ * cap_learning_update -
+ * @cl: Capacity learning object
+ * @batt_temp - Battery temperature
+ * @batt_soc: Battery State of Charge (SOC)
+ * @charge_status: Charging status from power supply
+ * @charge_done: Indicator for charge termination
+ * @input_present: Indicator for input presence
+ * @qnovo_en: Indicator for Qnovo enable status
+ *
+ * Called by FG/QG driver when there is a state change (Charging status, SOC)
+ *
+ */
+void cap_learning_update(struct cap_learning *cl, int batt_temp,
+			int batt_soc, int charge_status, bool charge_done,
+			bool input_present, bool qnovo_en)
+{
+	int rc, batt_soc_msb, batt_soc_prime;
+	bool prime_cc = false;
+
+	if (!cl)
+		return;
+
+	mutex_lock(&cl->lock);
+
+	if (batt_temp > cl->dt.max_temp || batt_temp < cl->dt.min_temp ||
+		!cl->learned_cap_uah) {
+		cl->active = false;
+		cl->init_cap_uah = 0;
+		goto out;
+	}
+
+	batt_soc_msb = (u32)batt_soc >> 24;
+	pr_debug("Charge_status: %d active: %d batt_soc: %d\n",
+		charge_status, cl->active, batt_soc_msb);
+
+	/* Initialize the starting point of learning capacity */
+	if (!cl->active) {
+		if (charge_status == POWER_SUPPLY_STATUS_CHARGING) {
+			rc = cap_learning_begin(cl, batt_soc);
+			cl->active = (rc == 0);
+		} else {
+			if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING ||
+				charge_done)
+				prime_cc = true;
+		}
+	} else {
+		if (charge_done) {
+			rc = cap_learning_done(cl);
+			if (rc < 0)
+				pr_err("Error in completing capacity learning, rc=%d\n",
+					rc);
+
+			cl->active = false;
+			cl->init_cap_uah = 0;
+		}
+
+		if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING) {
+			if (!input_present) {
+				pr_debug("Capacity learning aborted @ battery SOC %d\n",
+					 batt_soc_msb);
+				cl->active = false;
+				cl->init_cap_uah = 0;
+				prime_cc = true;
+			}
+		}
+
+		if (charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
+			if (qnovo_en && input_present) {
+				/*
+				 * Don't abort the capacity learning when qnovo
+				 * is enabled and input is present where the
+				 * charging status can go to "not charging"
+				 * intermittently.
+				 */
+			} else {
+				pr_debug("Capacity learning aborted @ battery SOC %d\n",
+					batt_soc_msb);
+				cl->active = false;
+				cl->init_cap_uah = 0;
+				prime_cc = true;
+			}
+		}
+	}
+
+	/*
+	 * Prime CC_SOC_SW when the device is not charging or during charge
+	 * termination when the capacity learning is not active.
+	 */
+
+	if (prime_cc && cl->prime_cc_soc) {
+		if (charge_done)
+			batt_soc_prime = cl->cc_soc_max;
+		else
+			batt_soc_prime = batt_soc;
+
+		rc = cl->prime_cc_soc(cl->data, batt_soc_prime);
+		if (rc < 0)
+			pr_err("Error in writing cc_soc_sw, rc=%d\n",
+				rc);
+	}
+
+out:
+	mutex_unlock(&cl->lock);
+}
+
+/**
+ * cap_learning_abort -
+ * @cl: Capacity learning object
+ *
+ * Aborts the capacity learning and initializes variables
+ *
+ */
+void cap_learning_abort(struct cap_learning *cl)
+{
+	if (!cl)
+		return;
+
+	mutex_lock(&cl->lock);
+	pr_debug("Aborting cap_learning\n");
+	cl->active = false;
+	cl->init_cap_uah = 0;
+	mutex_lock(&cl->lock);
+}
+
+/**
+ * cap_learning_post_profile_init -
+ * @cl: Capacity learning object
+ * @nom_cap_uah: Nominal capacity of battery in uAh
+ *
+ * Called by FG/QG once the profile load is complete and nominal capacity
+ * of battery is known. This also gets the last learned capacity back from
+ * FG/QG to feed back to the algorithm.
+ *
+ */
+int cap_learning_post_profile_init(struct cap_learning *cl, int64_t nom_cap_uah)
+{
+	int64_t delta_cap_uah, pct_nom_cap_uah;
+	int rc;
+
+	if (!cl || !cl->data)
+		return -EINVAL;
+
+	mutex_lock(&cl->lock);
+	cl->nom_cap_uah = nom_cap_uah;
+	rc = cl->get_learned_capacity(cl->data, &cl->learned_cap_uah);
+	if (rc < 0) {
+		pr_err("Couldn't get learned capacity, rc=%d\n", rc);
+		goto out;
+	}
+
+	if (cl->learned_cap_uah != cl->nom_cap_uah) {
+		if (cl->learned_cap_uah == 0)
+			cl->learned_cap_uah = cl->nom_cap_uah;
+
+		delta_cap_uah = abs(cl->learned_cap_uah - cl->nom_cap_uah);
+		pct_nom_cap_uah = div64_s64((int64_t)cl->nom_cap_uah *
+				CAPACITY_DELTA_DECIPCT, 1000);
+		/*
+		 * If the learned capacity is out of range by 50% from the
+		 * nominal capacity, then overwrite the learned capacity with
+		 * the nominal capacity.
+		 */
+		if (cl->nom_cap_uah && delta_cap_uah > pct_nom_cap_uah) {
+			pr_debug("learned_cap_uah: %lld is higher than expected, capping it to nominal: %lld\n",
+				cl->learned_cap_uah, cl->nom_cap_uah);
+			cl->learned_cap_uah = cl->nom_cap_uah;
+		}
+
+		rc = cl->store_learned_capacity(cl->data, cl->learned_cap_uah);
+		if (rc < 0)
+			pr_err("Error in storing learned_cap_uah, rc=%d\n", rc);
+	}
+
+out:
+	mutex_unlock(&cl->lock);
+	return rc;
+}
+
+/**
+ * cap_learning_init -
+ * @cl: Capacity learning object
+ *
+ * FG/QG have to call this during driver probe to validate the required
+ * parameters after allocating cap_learning object.
+ *
+ */
+int cap_learning_init(struct cap_learning *cl)
+{
+	if (!cl)
+		return -ENODEV;
+
+	if (!cl->get_learned_capacity || !cl->store_learned_capacity ||
+		!cl->get_cc_soc) {
+		pr_err("Insufficient functions for supporting capacity learning\n");
+		return -EINVAL;
+	}
+
+	if (!cl->cc_soc_max) {
+		pr_err("Insufficient parameters for supporting capacity learning\n");
+		return -EINVAL;
+	}
+
+	mutex_init(&cl->lock);
+	return 0;
+}
diff --git a/drivers/power/supply/qcom/fg-alg.h b/drivers/power/supply/qcom/fg-alg.h
new file mode 100644
index 0000000..ff5bece
--- /dev/null
+++ b/drivers/power/supply/qcom/fg-alg.h
@@ -0,0 +1,73 @@
+/* Copyright (c) 2018, 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 __FG_ALG_H__
+#define __FG_ALG_H__
+
+#define BUCKET_COUNT		8
+#define BUCKET_SOC_PCT		(256 / BUCKET_COUNT)
+
+struct cycle_counter {
+	void		*data;
+	bool		started[BUCKET_COUNT];
+	u16		count[BUCKET_COUNT];
+	u8		last_soc[BUCKET_COUNT];
+	int		id;
+	int		last_bucket;
+	struct mutex	lock;
+	int (*restore_count)(void *data, u16 *buf, int num_bytes);
+	int (*store_count)(void *data, u16 *buf, int id, int num_bytes);
+};
+
+struct cl_params {
+	int	start_soc;
+	int	max_temp;
+	int	min_temp;
+	int	max_cap_inc;
+	int	max_cap_dec;
+	int	max_cap_limit;
+	int	min_cap_limit;
+	int	skew_decipct;
+};
+
+struct cap_learning {
+	void			*data;
+	int			init_cc_soc_sw;
+	int			cc_soc_max;
+	int64_t			nom_cap_uah;
+	int64_t			init_cap_uah;
+	int64_t			final_cap_uah;
+	int64_t			learned_cap_uah;
+	bool			active;
+	struct mutex		lock;
+	struct cl_params	dt;
+	int (*get_learned_capacity)(void *data, int64_t *learned_cap_uah);
+	int (*store_learned_capacity)(void *data, int64_t learned_cap_uah);
+	int (*get_cc_soc)(void *data, int *cc_soc_sw);
+	int (*prime_cc_soc)(void *data, u32 cc_soc_sw);
+};
+
+int restore_cycle_count(struct cycle_counter *counter);
+void clear_cycle_count(struct cycle_counter *counter);
+void cycle_count_update(struct cycle_counter *counter, int batt_soc,
+		int charge_status, bool charge_done, bool input_present);
+int get_cycle_count(struct cycle_counter *counter);
+int cycle_count_init(struct cycle_counter *counter);
+void cap_learning_abort(struct cap_learning *cl);
+void cap_learning_update(struct cap_learning *cl, int batt_temp,
+		int batt_soc, int charge_status, bool charge_done,
+		bool input_present, bool qnovo_en);
+int cap_learning_init(struct cap_learning *cl);
+int cap_learning_post_profile_init(struct cap_learning *cl,
+		int64_t nom_cap_uah);
+
+#endif
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index a82cb43..e02bf84 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -605,6 +605,7 @@
 
 	/* SDM450 ID */
 	[338] = {MSM_CPU_SDM450, "SDM450"},
+	[351] = {MSM_CPU_SDM450, "SDA450"},
 
 	/* SDM632 ID */
 	[349] = {MSM_CPU_SDM632, "SDM632"},
diff --git a/drivers/thermal/tsens-dbg.c b/drivers/thermal/tsens-dbg.c
index e1fc6b9..9f128fe 100644
--- a/drivers/thermal/tsens-dbg.c
+++ b/drivers/thermal/tsens-dbg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -190,17 +190,34 @@
 	__ATTR(zonehist, 0644, zonehist_show, zonehist_store),
 };
 
+static struct device_attribute tsens_mtc_dev_attr_V14[] = {
+	__ATTR(zonemask, 0644, zonemask_show, zonemask_store),
+	__ATTR(zonelog, 0644, zonelog_show, zonelog_store),
+};
+
 static int tsens_dbg_mtc_data(struct tsens_device *data,
 					u32 id, u32 dbg_type, int *val)
 {
 	int result = 0, i;
 	struct tsens_device *tmdev = NULL;
 	struct device_attribute *attr_ptr = NULL;
+	u32 ver_major;
+	u32 ver_minor;
+	u32 num_elem;
 
-	attr_ptr = tsens_mtc_dev_attr;
 	tmdev = data;
+	ver_major = tmdev->ctrl_data->ver_major;
+	ver_minor = tmdev->ctrl_data->ver_minor;
 
-	for (i = 0; i < ARRAY_SIZE(tsens_mtc_dev_attr); i++) {
+	if (ver_major == 1 && ver_minor == 4) {
+		attr_ptr = tsens_mtc_dev_attr_V14;
+		num_elem = ARRAY_SIZE(tsens_mtc_dev_attr_V14);
+	} else {
+		attr_ptr = tsens_mtc_dev_attr;
+		num_elem = ARRAY_SIZE(tsens_mtc_dev_attr);
+	}
+
+	for (i = 0; i < num_elem; i++) {
 		result = device_create_file(&tmdev->pdev->dev, &attr_ptr[i]);
 		if (result < 0)
 			goto error;
diff --git a/drivers/thermal/tsens-mtc.c b/drivers/thermal/tsens-mtc.c
index 451c6c7..6e43533 100644
--- a/drivers/thermal/tsens-mtc.c
+++ b/drivers/thermal/tsens-mtc.c
@@ -76,6 +76,8 @@
 	unsigned int reg_cntl;
 	void __iomem *sensor_addr;
 	struct tsens_device *tmdev = NULL;
+	u32 ver_major;
+	u32 ver_minor;
 
 	if (zone > TSENS_NUM_MTC_ZONES_SUPPORT)
 		return -EINVAL;
@@ -86,8 +88,16 @@
 		return -EPROBE_DEFER;
 	}
 
-	sensor_addr = TSENS_TM_MTC_ZONE0_SW_MASK_ADDR
-					(tmdev->tsens_tm_addr);
+	ver_major = tmdev->ctrl_data->ver_major;
+	ver_minor = tmdev->ctrl_data->ver_minor;
+
+	if (ver_major == 1 && ver_minor == 4) {
+		sensor_addr = TSENS_TM_MTC_ZONE0_SW_MASK_ADDR_V14
+			(tmdev->tsens_tm_addr);
+	} else {
+		sensor_addr = TSENS_TM_MTC_ZONE0_SW_MASK_ADDR
+			(tmdev->tsens_tm_addr);
+	}
 
 	if (th1_enable && th2_enable)
 		writel_relaxed(TSENS_MTC_IN_EFFECT,
@@ -120,6 +130,8 @@
 	int *zlog = (int *)zone_log;
 	void __iomem *sensor_addr;
 	struct tsens_device *tmdev = NULL;
+	u32 ver_major;
+	u32 ver_minor;
 
 	if (zone > TSENS_NUM_MTC_ZONES_SUPPORT)
 		return -EINVAL;
@@ -130,8 +142,13 @@
 		return -EPROBE_DEFER;
 	}
 
-	sensor_addr = TSENS_TM_MTC_ZONE0_LOG(tmdev->tsens_tm_addr);
+	ver_major = tmdev->ctrl_data->ver_major;
+	ver_minor = tmdev->ctrl_data->ver_minor;
 
+	if (ver_major == 1 && ver_minor == 4)
+		sensor_addr = TSENS_TM_MTC_ZONE0_LOG_V14(tmdev->tsens_tm_addr);
+	else
+		sensor_addr = TSENS_TM_MTC_ZONE0_LOG(tmdev->tsens_tm_addr);
 	reg_cntl = readl_relaxed((sensor_addr +
 				(zone * TSENS_SN_ADDR_OFFSET)));
 	is_valid = (reg_cntl & TSENS_LOGS_VALID_MASK)
diff --git a/drivers/thermal/tsens-mtc.h b/drivers/thermal/tsens-mtc.h
index 8782728..b3a2c8e 100644
--- a/drivers/thermal/tsens-mtc.h
+++ b/drivers/thermal/tsens-mtc.h
@@ -15,6 +15,9 @@
 #define TSENS_TM_MTC_ZONE0_SW_MASK_ADDR(n)      ((n) + 0x140)
 #define TSENS_TM_MTC_ZONE0_LOG(n)               ((n) + 0x150)
 #define TSENS_TM_MTC_ZONE0_HISTORY(n)           ((n) + 0x160)
+#define TSENS_TM_MTC_ZONE0_SW_MASK_ADDR_V14(n)  ((n) + 0xC0)
+#define TSENS_TM_MTC_ZONE0_LOG_V14(n)           ((n) + 0xD0)
+
 #define TSENS_SN_ADDR_OFFSET             0x4
 #define TSENS_RESET_HISTORY_MASK        0x4
 #define TSENS_ZONEMASK_PARAMS           3
diff --git a/drivers/thermal/tsens.h b/drivers/thermal/tsens.h
index 885b15c..730d124 100644
--- a/drivers/thermal/tsens.h
+++ b/drivers/thermal/tsens.h
@@ -127,6 +127,8 @@
 	u32				wd_bark_mask;
 	bool				mtc;
 	bool				valid_status_check;
+	u32				ver_major;
+	u32				ver_minor;
 };
 
 struct tsens_mtc_sysfs {
diff --git a/drivers/thermal/tsens1xxx.c b/drivers/thermal/tsens1xxx.c
index 0ea4a46..d63fcd1 100644
--- a/drivers/thermal/tsens1xxx.c
+++ b/drivers/thermal/tsens1xxx.c
@@ -306,6 +306,10 @@
 	*temp = code_to_degc(last_temp, sensor);
 	*temp = *temp * TSENS_SCALE_MILLIDEG;
 
+	if (tmdev->ops->dbg)
+		tmdev->ops->dbg(tmdev, (u32)sensor->hw_id,
+				TSENS_DBG_LOG_TEMP_READS, temp);
+
 	return 0;
 }
 
@@ -565,6 +569,9 @@
 	/* Disable monitoring sensor trip threshold for triggered sensor */
 	mb();
 
+	if (tm->ops->dbg)
+		tm->ops->dbg(tm, 0, TSENS_DBG_LOG_INTERRUPT_TIMESTAMP, NULL);
+
 	return IRQ_HANDLED;
 }
 
@@ -600,6 +607,11 @@
 
 	spin_lock_init(&tmdev->tsens_upp_low_lock);
 
+	if (tmdev->ctrl_data->mtc) {
+		if (tmdev->ops->dbg)
+			tmdev->ops->dbg(tmdev, 0, TSENS_DBG_MTC_DATA, NULL);
+	}
+
 	return 0;
 }
 
@@ -646,13 +658,16 @@
 	.hw_init		= tsens1xxx_hw_init,
 	.get_temp		= tsens1xxx_get_temp,
 	.set_trips		= tsens1xxx_set_trip_temp,
-	.interrupts_reg		= tsens1xxx_register_interrupts,
+	.interrupts_reg	= tsens1xxx_register_interrupts,
 	.sensor_en		= tsens1xxx_hw_sensor_en,
 	.calibrate		= calibrate_8937,
+	.dbg            = tsens2xxx_dbg,
 };
 
 const struct tsens_data data_tsens14xx = {
-	.ops			= &ops_tsens1xxx,
-	.valid_status_check	= true,
-	.mtc			= true,
+	.ops = &ops_tsens1xxx,
+	.valid_status_check = true,
+	.mtc = true,
+	.ver_major = 1,
+	.ver_minor = 4,
 };
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index b59d548..4331b83 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -288,6 +288,7 @@
 	POWER_SUPPLY_PROP_MANUFACTURER,
 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
 	POWER_SUPPLY_PROP_BATTERY_TYPE,
+	POWER_SUPPLY_PROP_CYCLE_COUNTS,
 };
 
 enum power_supply_type {
diff --git a/include/linux/qpnp/qpnp-misc.h b/include/linux/qpnp/qpnp-misc.h
index 7d95bf2..a7a5616 100644
--- a/include/linux/qpnp/qpnp-misc.h
+++ b/include/linux/qpnp/qpnp-misc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 2017-2018, 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,6 +15,11 @@
 
 #include <linux/errno.h>
 
+enum twm_state {
+	PMIC_TWM_CLEAR,
+	PMIC_TWM_ENABLE,
+};
+
 #ifdef CONFIG_QPNP_MISC
 /**
  * qpnp_misc_irqs_available - check if IRQs are available
@@ -42,6 +47,25 @@
  */
 
 int qpnp_misc_read_reg(struct device_node *node, u16 addr, u8 *val);
+/**
+ * qpnp_misc_twm_notifier_register - register to the twm mode notifier
+ *
+ * @nb: pointer to the client's notifier handle
+ *
+ * This function returns 0 if the client is successfuly added to the
+ * notifer list.
+ */
+int qpnp_misc_twm_notifier_register(struct notifier_block *nb);
+
+/**
+ * qpnp_misc_twm_notifier_unregister - unregister to the twm mode notifier
+ *
+ * @nb: pointer to the client's notifier handle
+ *
+ * This function returns 0 if the client is successfuly removed from the
+ * notifer list.
+ */
+int qpnp_misc_twm_notifier_unregister(struct notifier_block *nb);
 #else
 static inline int qpnp_misc_irqs_available(struct device *consumer_dev)
 {
@@ -52,5 +76,13 @@
 {
 	return 0;
 }
+static inline int qpnp_misc_twm_notifier_register(struct notifier_block *nb)
+{
+	return 0;
+}
+static inline int qpnp_misc_twm_notifier_unregister(struct notifier_block *nb)
+{
+	return 0;
+}
 #endif
 #endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index bae4f35..4b2a1bc 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1768,6 +1768,7 @@
 	struct sched_entity se;
 	struct sched_rt_entity rt;
 	u64 last_sleep_ts;
+	u64 last_cpu_selected_ts;
 #ifdef CONFIG_SCHED_WALT
 	struct ravg ravg;
 	/*
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 23a7f9c..0ca1647 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2330,6 +2330,7 @@
 	p->se.nr_migrations		= 0;
 	p->se.vruntime			= 0;
 	p->last_sleep_ts		= 0;
+	p->last_cpu_selected_ts		= 0;
 
 	INIT_LIST_HEAD(&p->se.group_node);
 
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index c00e731..04ba6d0 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -7296,6 +7296,39 @@
 	       task_fits_max(p, cpu);
 }
 
+#define SCHED_SELECT_PREV_CPU_NSEC	2000000
+#define SCHED_FORCE_CPU_SELECTION_NSEC	20000000
+
+static inline bool
+bias_to_prev_cpu(struct task_struct *p, struct cpumask *rtg_target)
+{
+	int prev_cpu = task_cpu(p);
+#ifdef CONFIG_SCHED_WALT
+	u64 ms = p->ravg.mark_start;
+#else
+	u64 ms = sched_clock();
+#endif
+
+	if (cpu_isolated(prev_cpu) || !idle_cpu(prev_cpu))
+		return false;
+
+	if (!ms)
+		return false;
+
+	if (ms - p->last_cpu_selected_ts >= SCHED_SELECT_PREV_CPU_NSEC) {
+		p->last_cpu_selected_ts = ms;
+		return false;
+	}
+
+	if (ms - p->last_sleep_ts >= SCHED_SELECT_PREV_CPU_NSEC)
+		return false;
+
+	if (rtg_target && !cpumask_test_cpu(prev_cpu, rtg_target))
+		return false;
+
+	return true;
+}
+
 #ifdef CONFIG_SCHED_WALT
 static inline struct cpumask *find_rtg_target(struct task_struct *p)
 {
@@ -7374,6 +7407,9 @@
 		}
 	}
 
+	if (bias_to_prev_cpu(p, rtg_target))
+		return prev_cpu;
+
 	rcu_read_lock();
 
 	sd = rcu_dereference(per_cpu(sd_ea, prev_cpu));
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 3637d96..f27ab13 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -823,6 +823,8 @@
 	int prev_top;
 	int curr_top;
 	bool notif_pending;
+	u64 last_cc_update;
+	u64 cycles;
 #endif
 
 #ifdef CONFIG_IRQ_TIME_ACCOUNTING
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
index e6a11c1..a9fb367 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -301,10 +301,27 @@
 	return 0;
 }
 
-static void update_task_cpu_cycles(struct task_struct *p, int cpu)
+/*
+ * Assumes rq_lock is held and wallclock was recorded in the same critical
+ * section as this function's invocation.
+ */
+static inline u64 read_cycle_counter(int cpu, u64 wallclock)
+{
+	struct rq *rq = cpu_rq(cpu);
+
+	if (rq->last_cc_update != wallclock) {
+		rq->cycles = cpu_cycle_counter_cb.get_cpu_cycle_counter(cpu);
+		rq->last_cc_update = wallclock;
+	}
+
+	return rq->cycles;
+}
+
+static void update_task_cpu_cycles(struct task_struct *p, int cpu,
+				   u64 wallclock)
 {
 	if (use_cycle_counter)
-		p->cpu_cycles = cpu_cycle_counter_cb.get_cpu_cycle_counter(cpu);
+		p->cpu_cycles = read_cycle_counter(cpu, wallclock);
 }
 
 void clear_ed_task(struct task_struct *p, struct rq *rq)
@@ -348,7 +365,7 @@
 	if (is_idle_task(curr)) {
 		/* We're here without rq->lock held, IRQ disabled */
 		raw_spin_lock(&rq->lock);
-		update_task_cpu_cycles(curr, cpu);
+		update_task_cpu_cycles(curr, cpu, ktime_get_ns());
 		raw_spin_unlock(&rq->lock);
 	}
 }
@@ -757,7 +774,7 @@
 	update_task_ravg(p, task_rq(p), TASK_MIGRATE,
 			 wallclock, 0);
 
-	update_task_cpu_cycles(p, new_cpu);
+	update_task_cpu_cycles(p, new_cpu, wallclock);
 
 	/*
 	 * When a task is migrating during the wakeup, adjust
@@ -1839,7 +1856,7 @@
 		return;
 	}
 
-	cur_cycles = cpu_cycle_counter_cb.get_cpu_cycle_counter(cpu);
+	cur_cycles = read_cycle_counter(cpu, wallclock);
 
 	/*
 	 * If current task is idle task and irqtime == 0 CPU was
@@ -1904,7 +1921,7 @@
 	old_window_start = update_window_start(rq, wallclock, event);
 
 	if (!p->ravg.mark_start) {
-		update_task_cpu_cycles(p, cpu_of(rq));
+		update_task_cpu_cycles(p, cpu_of(rq), wallclock);
 		goto done;
 	}
 
@@ -2035,7 +2052,7 @@
 	p->ravg.mark_start = p->last_wake_ts = wallclock;
 	p->last_enqueued_ts = wallclock;
 	p->last_switch_out_ts = 0;
-	update_task_cpu_cycles(p, cpu_of(rq));
+	update_task_cpu_cycles(p, cpu_of(rq), wallclock);
 }
 
 static cpumask_t all_cluster_cpus = CPU_MASK_NONE;
@@ -3255,6 +3272,8 @@
 	rq->curr_table = 0;
 	rq->prev_top = 0;
 	rq->curr_top = 0;
+	rq->last_cc_update = 0;
+	rq->cycles = 0;
 	for (j = 0; j < NUM_TRACKED_WINDOWS; j++) {
 		memset(&rq->load_subs[j], 0,
 				sizeof(struct load_subtractions));