Merge "msm: camera: isp: Add VFE HW driver support" into msm-4.9
diff --git a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
index b043a93..669997c 100644
--- a/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/drm/msm/mdss-dsi-panel.txt
@@ -333,8 +333,13 @@
 					as below:
 					--> Reset GPIO value
 					--> Sleep value (in ms)
-- qcom,partial-update-enabled:		Boolean used to enable partial
+- qcom,partial-update-enabled:		String used to enable partial
 					panel update for command mode panels.
+					"none": partial update is disabled
+					"single_roi": default enable mode, only single roi is sent to panel
+					"dual_roi": two rois are merged into one big roi. Panel ddic should be able
+					to process two roi's along with the DCS command to send two rois.
+					disabled if property is not specified.
 - qcom,mdss-dsi-horizontal-line-idle:	List of width ranges (EC - SC) in pixels indicating
 					additional idle time in dsi clock cycles that is needed
 					to compensate for smaller line width.
@@ -630,7 +635,7 @@
 		qcom,mdss-tear-check-rd-ptr-trigger-intr = <1281>;
 		qcom,mdss-tear-check-frame-rate = <6000>;
 		qcom,mdss-dsi-reset-sequence = <1 2>, <0 10>, <1 10>;
-		qcom,partial-update-enabled;
+		qcom,partial-update-enabled = "single_roi";
 		qcom,dcs-cmd-by-left;
 		qcom,mdss-dsi-lp11-init;
 		qcom,mdss-dsi-init-delay-us = <100>;
diff --git a/Documentation/devicetree/bindings/input/qpnp-power-on.txt b/Documentation/devicetree/bindings/input/qpnp-power-on.txt
index a596aa1..c2550e6 100644
--- a/Documentation/devicetree/bindings/input/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/input/qpnp-power-on.txt
@@ -82,6 +82,8 @@
 - qcom,shutdown-poweroff-type	Same description as qcom,warm-reset-poweroff-
 				type but this applies for the system shutdown
 				case.
+- qcom,kpdpwr-sw-debounce	Boolean property to enable the debounce logic
+				on the KPDPWR_N rising edge.
 
 
 All the below properties are in the sub-node section (properties of the child
diff --git a/Documentation/timers/timer_stats.txt b/Documentation/timers/timer_stats.txt
deleted file mode 100644
index de835ee..0000000
--- a/Documentation/timers/timer_stats.txt
+++ /dev/null
@@ -1,73 +0,0 @@
-timer_stats - timer usage statistics
-------------------------------------
-
-timer_stats is a debugging facility to make the timer (ab)usage in a Linux
-system visible to kernel and userspace developers. If enabled in the config
-but not used it has almost zero runtime overhead, and a relatively small
-data structure overhead. Even if collection is enabled runtime all the
-locking is per-CPU and lookup is hashed.
-
-timer_stats should be used by kernel and userspace developers to verify that
-their code does not make unduly use of timers. This helps to avoid unnecessary
-wakeups, which should be avoided to optimize power consumption.
-
-It can be enabled by CONFIG_TIMER_STATS in the "Kernel hacking" configuration
-section.
-
-timer_stats collects information about the timer events which are fired in a
-Linux system over a sample period:
-
-- the pid of the task(process) which initialized the timer
-- the name of the process which initialized the timer
-- the function where the timer was initialized
-- the callback function which is associated to the timer
-- the number of events (callbacks)
-
-timer_stats adds an entry to /proc: /proc/timer_stats
-
-This entry is used to control the statistics functionality and to read out the
-sampled information.
-
-The timer_stats functionality is inactive on bootup.
-
-To activate a sample period issue:
-# echo 1 >/proc/timer_stats
-
-To stop a sample period issue:
-# echo 0 >/proc/timer_stats
-
-The statistics can be retrieved by:
-# cat /proc/timer_stats
-
-While sampling is enabled, each readout from /proc/timer_stats will see
-newly updated statistics. Once sampling is disabled, the sampled information
-is kept until a new sample period is started. This allows multiple readouts.
-
-Sample output of /proc/timer_stats:
-
-Timerstats sample period: 3.888770 s
-  12,     0 swapper          hrtimer_stop_sched_tick (hrtimer_sched_tick)
-  15,     1 swapper          hcd_submit_urb (rh_timer_func)
-   4,   959 kedac            schedule_timeout (process_timeout)
-   1,     0 swapper          page_writeback_init (wb_timer_fn)
-  28,     0 swapper          hrtimer_stop_sched_tick (hrtimer_sched_tick)
-  22,  2948 IRQ 4            tty_flip_buffer_push (delayed_work_timer_fn)
-   3,  3100 bash             schedule_timeout (process_timeout)
-   1,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
-   1,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
-   1,     1 swapper          neigh_table_init_no_netlink (neigh_periodic_timer)
-   1,  2292 ip               __netdev_watchdog_up (dev_watchdog)
-   1,    23 events/1         do_cache_clean (delayed_work_timer_fn)
-90 total events, 30.0 events/sec
-
-The first column is the number of events, the second column the pid, the third
-column is the name of the process. The forth column shows the function which
-initialized the timer and in parenthesis the callback function which was
-executed on expiry.
-
-    Thomas, Ingo
-
-Added flag to indicate 'deferrable timer' in /proc/timer_stats. A deferrable
-timer will appear as follows
-  10D,     1 swapper          queue_delayed_work_on (delayed_work_timer_fn)
-
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index bcef117..1921325 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -284,7 +284,6 @@
 CONFIG_PANIC_TIMEOUT=5
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_IPC_LOGGING=y
 CONFIG_BLK_DEV_IO_TRACE=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index 5601276..0a875b1 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -135,6 +135,10 @@
 CONFIG_BRIDGE=y
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_PRIO=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+CONFIG_CFG80211_WEXT=y
 CONFIG_RFKILL=y
 CONFIG_IPC_ROUTER=y
 CONFIG_IPC_ROUTER_SECURITY=y
@@ -278,7 +282,6 @@
 CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_PANIC_TIMEOUT=5
 CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_ATOMIC_SLEEP=y
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index ff2cc3e..cd13516 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -14,6 +14,15 @@
 	sdm845-4k-panel-cdp.dtb \
 	sdm845-4k-panel-qrd.dtb
 
+ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y)
+	dtbo-$(CONFIG_ARCH_SDM845) += \
+		sdm845-cdp-overlay.dtbo \
+		sdm845-mtp-overlay.dtbo
+
+sdm845-cdp-overlay.dtbo-base := sdm845.dtb
+sdm845-mtp-overlay.dtbo-base := sdm845.dtb
+endif
+
 dtb-$(CONFIG_ARCH_SDM830) += sdm830-sim.dtb \
 	sdm830-rumi.dtb \
 	sdm830-mtp.dtb \
diff --git a/arch/arm64/boot/dts/qcom/pmi8998.dtsi b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
index b53f7ac..886e792 100644
--- a/arch/arm64/boot/dts/qcom/pmi8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
@@ -76,6 +76,7 @@
 			compatible = "qcom,qpnp-smb2";
 			#address-cells = <1>;
 			#size-cells = <1>;
+			#cooling-cells = <2>;
 
 			qcom,pmic-revid = <&pmi8998_revid>;
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
index 9ead234..e3f7036 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
@@ -373,11 +373,13 @@
 		client-id-based;
 		client-names =
 			"csiphy0", "csiphy1", "csiphy2", "cci0",
+			"csid0", "csid1", "csid2",
 			"ife0", "ife1", "ife2", "ipe0",
 			"ipe1", "cam-cdm-intf0", "cpas-cdm0", "bps0",
 			"icp0", "jpeg-dma0", "jpeg0", "fd0";
 		client-axi-port-names =
 			"cam_hf_1", "cam_hf_2", "cam_hf_2", "cam_sf_1",
+			"cam_hf_1", "cam_hf_2", "cam_hf_2",
 			"cam_hf_1", "cam_hf_2", "cam_hf_2", "cam_sf_1",
 			"cam_sf_1", "cam_sf_1", "cam_sf_1", "cam_sf_1",
 			"cam_sf_1", "cam_sf_1", "cam_sf_1", "cam_sf_1";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-cdp-overlay.dts
new file mode 100644
index 0000000..fff9160
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp-overlay.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2017, 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/;
+/plugin/;
+
+#include "sdm845.dtsi"
+#include "sdm845-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM845 v1 CDP";
+	compatible = "qcom,sdm845-cdp", "qcom,sdm845", "qcom,cdp";
+	qcom,msm-id = <321 0x0>;
+	qcom,board-id = <1 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
index 2c9c012..106d0c6 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
@@ -374,30 +374,110 @@
 		qcom,hw-settle-time = <0>;
 		qcom,btm-channel-number = <0x60>;
 	};
+
+	chan@4c {
+		label = "xo_therm";
+		reg = <0x4c>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <4>;
+		qcom,hw-settle-time = <2>;
+		qcom,btm-channel-number = <0x68>;
+		qcom,thermal-node;
+	};
+
+	chan@4d {
+		label = "msm_therm";
+		reg = <0x4d>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,btm-channel-number = <0x70>;
+		qcom,thermal-node;
+	};
+
+	chan@4f {
+		label = "pa_therm1";
+		reg = <0x4f>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,btm-channel-number = <0x78>;
+		qcom,thermal-node;
+	};
+
+	chan@51 {
+		label = "quiet_therm";
+		reg = <0x51>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,btm-channel-number = <0x80>;
+		qcom,thermal-node;
+	};
 };
 
 &thermal_zones {
 	xo-therm-adc {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
-		thermal-sensors = <&pm8998_vadc 0x4c>;
+		thermal-sensors = <&pm8998_adc_tm 0x4c>;
+		thermal-governor = "user_space";
+
+		trips {
+			active-config0 {
+				temperature = <65000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
 	};
 
 	msm-therm-adc {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
-		thermal-sensors = <&pm8998_vadc 0x4d>;
+		thermal-sensors = <&pm8998_adc_tm 0x4d>;
+		thermal-governor = "user_space";
+
+		trips {
+			active-config0 {
+				temperature = <65000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
 	};
 
 	pa-therm1-adc {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
-		thermal-sensors = <&pm8998_vadc 0x4f>;
+		thermal-sensors = <&pm8998_adc_tm 0x4f>;
+		thermal-governor = "user_space";
+
+		trips {
+			active-config0 {
+				temperature = <65000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
 	};
 
 	quiet-therm-adc {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
-		thermal-sensors = <&pm8998_vadc 0x51>;
+		thermal-sensors = <&pm8998_adc_tm 0x51>;
+		thermal-governor = "user_space";
+
+		trips {
+			active-config0 {
+				temperature = <65000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-mtp-overlay.dts
new file mode 100644
index 0000000..79fa580
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp-overlay.dts
@@ -0,0 +1,24 @@
+/* Copyright (c) 2017, 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/;
+/plugin/;
+
+#include "sdm845.dtsi"
+#include "sdm845-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM845 v1 MTP";
+	compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
+	qcom,msm-id = <321 0x0>;
+	qcom,board-id = <8 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index e4261e2..3dc45ae 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -357,30 +357,110 @@
 		qcom,hw-settle-time = <0>;
 		qcom,btm-channel-number = <0x60>;
 	};
+
+	chan@4c {
+		label = "xo_therm";
+		reg = <0x4c>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <4>;
+		qcom,hw-settle-time = <2>;
+		qcom,btm-channel-number = <0x68>;
+		qcom,thermal-node;
+	};
+
+	chan@4d {
+		label = "msm_therm";
+		reg = <0x4d>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,btm-channel-number = <0x70>;
+		qcom,thermal-node;
+	};
+
+	chan@4f {
+		label = "pa_therm1";
+		reg = <0x4f>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,btm-channel-number = <0x78>;
+		qcom,thermal-node;
+	};
+
+	chan@51 {
+		label = "quiet_therm";
+		reg = <0x51>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,btm-channel-number = <0x80>;
+		qcom,thermal-node;
+	};
 };
 
 &thermal_zones {
 	xo-therm-adc {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
-		thermal-sensors = <&pm8998_vadc 0x4c>;
+		thermal-sensors = <&pm8998_adc_tm 0x4c>;
+		thermal-governor = "user_space";
+
+		trips {
+			active-config0 {
+				temperature = <65000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
 	};
 
 	msm-therm-adc {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
-		thermal-sensors = <&pm8998_vadc 0x4d>;
+		thermal-sensors = <&pm8998_adc_tm 0x4d>;
+		thermal-governor = "user_space";
+
+		trips {
+			active-config0 {
+				temperature = <65000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
 	};
 
 	pa-therm1-adc {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
-		thermal-sensors = <&pm8998_vadc 0x4f>;
+		thermal-sensors = <&pm8998_adc_tm 0x4f>;
+		thermal-governor = "user_space";
+
+		trips {
+			active-config0 {
+				temperature = <65000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
 	};
 
 	quiet-therm-adc {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
-		thermal-sensors = <&pm8998_vadc 0x51>;
+		thermal-sensors = <&pm8998_adc_tm 0x51>;
+		thermal-governor = "user_space";
+
+		trips {
+			active-config0 {
+				temperature = <65000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi b/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
index aac63ee..6fb6fb8 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
@@ -305,7 +305,7 @@
 
 	usb_audio_qmi_dev {
 		compatible = "qcom,usb-audio-qmi-dev";
-		iommus = <&apps_smmu 0x182c>;
+		iommus = <&apps_smmu 0x182c 0x0>;
 		qcom,usb-audio-stream-id = <0xc>;
 		qcom,usb-audio-intr-num = <2>;
 	};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dts b/arch/arm64/boot/dts/qcom/sdm845.dts
new file mode 100644
index 0000000..a3fa3af
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845.dts
@@ -0,0 +1,21 @@
+/* Copyright (c) 2017, 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 "sdm845.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM845 v1 SoC";
+	compatible = "qcom,sdm845";
+	qcom,board-id = <0 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 67e0493..5ae733b 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -741,7 +741,9 @@
 			< 1363200 >,
 			< 1440000 >,
 			< 1516800 >,
-			< 1593600 >;
+			< 1593600 >,
+			< 1651200 >,
+			< 1708800 >;
 
 		qcom,cpufreq-table-4 =
 			<  300000 >,
@@ -765,7 +767,9 @@
 			< 1728000 >,
 			< 1804800 >,
 			< 1881600 >,
-			< 1958400 >;
+			< 1958400 >,
+			< 2035200 >,
+			< 2092800 >;
 	};
 
 	cpubw: qcom,cpubw {
@@ -886,7 +890,9 @@
 			< 729600 >,
 			< 806400 >,
 			< 883200 >,
-			< 960000 >;
+			< 960000 >,
+			< 1036800 >,
+			< 1094400 >;
 	};
 
 	l3_cpu4: qcom,l3-cpu4 {
@@ -904,7 +910,9 @@
 			< 729600 >,
 			< 806400 >,
 			< 883200 >,
-			< 960000 >;
+			< 960000 >,
+			< 1036800 >,
+			< 1094400 >;
 	};
 
 	devfreq_l3lat_0: qcom,cpu0-l3lat-mon {
@@ -1021,11 +1029,14 @@
 			<0x178b0000 0x1000>,
 			<0x17d42400 0x0c00>,
 			<0x17d44400 0x0c00>,
-			<0x17d46c00 0x0c00>;
+			<0x17d46c00 0x0c00>,
+			<0x00784130 0x4>,
+			<0x00784130 0x4>,
+			<0x00784130 0x4>;
 		reg-names = "osm_l3_base", "osm_pwrcl_base", "osm_perfcl_base",
-			"l3_pll", "pwrcl_pll", "perfcl_pll",
-			"l3_sequencer", "pwrcl_sequencer",
-			"perfcl_sequencer";
+			"l3_pll", "pwrcl_pll", "perfcl_pll", "l3_sequencer",
+			"pwrcl_sequencer", "perfcl_sequencer", "l3_efuse",
+			"pwrcl_efuse", "perfcl_efuse";
 
 		vdd-l3-supply = <&apc0_l3_vreg>;
 		vdd-pwrcl-supply = <&apc0_pwrcl_vreg>;
@@ -1038,7 +1049,22 @@
 			<   576000000 0x5014031e 0x00002020 0x1 4 >,
 			<   652800000 0x401c0422 0x00002020 0x1 5 >,
 			<   729600000 0x401c0526 0x00002020 0x1 6 >,
-			<   806400000 0x401c062a 0x00002222 0x1 7 >;
+			<   806400000 0x401c062a 0x00002222 0x1 7 >,
+			<   883200000 0x4024072e 0x00002525 0x2 8 >,
+			<   960000000 0x40240832 0x00002828 0x2 9 >;
+
+		qcom,l3-speedbin1-v0 =
+			<   300000000 0x000c000f 0x00002020 0x1 1 >,
+			<   422400000 0x50140116 0x00002020 0x1 2 >,
+			<   499200000 0x5014021a 0x00002020 0x1 3 >,
+			<   576000000 0x5014031e 0x00002020 0x1 4 >,
+			<   652800000 0x401c0422 0x00002020 0x1 5 >,
+			<   729600000 0x401c0526 0x00002020 0x1 6 >,
+			<   806400000 0x401c062a 0x00002222 0x1 7 >,
+			<   883200000 0x4024072e 0x00002525 0x2 8 >,
+			<   960000000 0x40240832 0x00002828 0x2 9 >,
+			<  1036800000 0x40240936 0x00002b2b 0x3 10 >,
+			<  1094400000 0x402c0a39 0x00002e2e 0x3 11 >;
 
 		qcom,pwrcl-speedbin0-v0 =
 			<   300000000 0x000c000f 0x00002020 0x1 1 >,
@@ -1052,7 +1078,33 @@
 			<   979200000 0x40240833 0x00002929 0x1 9 >,
 			<  1056000000 0x402c0937 0x00002c2c 0x1 10 >,
 			<  1132800000 0x402c0a3b 0x00002f2f 0x1 11 >,
-			<  1209600000 0x402c0b3f 0x00003333 0x1 12 >;
+			<  1209600000 0x402c0b3f 0x00003232 0x1 12 >,
+			<  1286400000 0x40340c43 0x00003636 0x2 13 >,
+			<  1363200000 0x40340d47 0x00003939 0x2 14 >,
+			<  1440000000 0x40340e4b 0x00003c3c 0x2 15 >,
+			<  1516800000 0x403c0f4f 0x00003f3f 0x2 16 >,
+			<  1593600000 0x403c1053 0x00004242 0x2 17 >;
+
+		qcom,pwrcl-speedbin1-v0 =
+			<   300000000 0x000c000f 0x00002020 0x1 1 >,
+			<   422400000 0x50140116 0x00002020 0x1 2 >,
+			<   499200000 0x5014021a 0x00002020 0x1 3 >,
+			<   576000000 0x5014031e 0x00002020 0x1 4 >,
+			<   652800000 0x401c0422 0x00002020 0x1 5 >,
+			<   748800000 0x401c0527 0x00002020 0x1 6 >,
+			<   825600000 0x401c062b 0x00002222 0x1 7 >,
+			<   902400000 0x4024072f 0x00002626 0x1 8 >,
+			<   979200000 0x40240833 0x00002929 0x1 9 >,
+			<  1056000000 0x402c0937 0x00002c2c 0x1 10 >,
+			<  1132800000 0x402c0a3b 0x00002f2f 0x1 11 >,
+			<  1209600000 0x402c0b3f 0x00003232 0x1 12 >,
+			<  1286400000 0x40340c43 0x00003636 0x2 13 >,
+			<  1363200000 0x40340d47 0x00003939 0x2 14 >,
+			<  1440000000 0x40340e4b 0x00003c3c 0x2 15 >,
+			<  1516800000 0x403c0f4f 0x00003f3f 0x2 16 >,
+			<  1593600000 0x403c1053 0x00004242 0x2 17 >,
+			<  1651200000 0x403c1156 0x00004545 0x3 18 >,
+			<  1708800000 0x40441259 0x00004747 0x3 19 >;
 
 		qcom,perfcl-speedbin0-v0 =
 			<   300000000 0x000c000f 0x00002020 0x1 1 >,
@@ -1066,7 +1118,43 @@
 			<   960000000 0x40240832 0x00002828 0x1 9 >,
 			<  1036800000 0x40240936 0x00002b2b 0x1 10 >,
 			<  1113600000 0x402c0a3a 0x00002e2e 0x1 11 >,
-			<  1190400000 0x402c0b3e 0x00003232 0x1 12 >;
+			<  1190400000 0x402c0b3e 0x00003232 0x1 12 >,
+			<  1267200000 0x40340c42 0x00003535 0x2 13 >,
+			<  1344000000 0x40340d46 0x00003838 0x2 14 >,
+			<  1420800000 0x40340e4a 0x00003b3b 0x2 15 >,
+			<  1497600000 0x403c0f4e 0x00003e3e 0x2 16 >,
+			<  1574400000 0x403c1052 0x00004242 0x2 17 >,
+			<  1651200000 0x403c1156 0x00004545 0x2 18 >,
+			<  1728000000 0x4044125a 0x00004848 0x3 19 >,
+			<  1804800000 0x4044135e 0x00004b4b 0x3 20 >,
+			<  1881600000 0x404c1462 0x00004e4e 0x3 21 >,
+			<  1958400000 0x404c1566 0x00005252 0x3 22 >;
+
+		qcom,perfcl-speedbin1-v0 =
+			<   300000000 0x000c000f 0x00002020 0x1 1 >,
+			<   422400000 0x50140116 0x00002020 0x1 2 >,
+			<   499200000 0x5014021a 0x00002020 0x1 3 >,
+			<   576000000 0x5014031e 0x00002020 0x1 4 >,
+			<   652800000 0x401c0422 0x00002020 0x1 5 >,
+			<   729600000 0x401c0526 0x00002020 0x1 6 >,
+			<   806400000 0x401c062a 0x00002222 0x1 7 >,
+			<   883200000 0x4024072e 0x00002525 0x1 8 >,
+			<   960000000 0x40240832 0x00002828 0x1 9 >,
+			<  1036800000 0x40240936 0x00002b2b 0x1 10 >,
+			<  1113600000 0x402c0a3a 0x00002e2e 0x1 11 >,
+			<  1190400000 0x402c0b3e 0x00003232 0x1 12 >,
+			<  1267200000 0x40340c42 0x00003535 0x2 13 >,
+			<  1344000000 0x40340d46 0x00003838 0x2 14 >,
+			<  1420800000 0x40340e4a 0x00003b3b 0x2 15 >,
+			<  1497600000 0x403c0f4e 0x00003e3e 0x2 16 >,
+			<  1574400000 0x403c1052 0x00004242 0x2 17 >,
+			<  1651200000 0x403c1156 0x00004545 0x2 18 >,
+			<  1728000000 0x4044125a 0x00004848 0x3 19 >,
+			<  1804800000 0x4044135e 0x00004b4b 0x3 20 >,
+			<  1881600000 0x404c1462 0x00004e4e 0x3 21 >,
+			<  1958400000 0x404c1566 0x00005252 0x3 22 >,
+			<  2035200000 0x404c166a 0x00005555 0x3 23 >,
+			<  2092800000 0x4054176d 0x00005757 0x3 24 >;
 
 		qcom,l3-min-cpr-vc-bin0 = <7>;
 		qcom,pwrcl-min-cpr-vc-bin0 = <6>;
@@ -2605,10 +2693,17 @@
 			     <0 424 0 /* CE10 */ >,
 			     <0 425 0 /* CE11 */ >;
 		qcom,wlan-msa-memory = <0x100000>;
+
+		vdd-0.8-cx-mx-supply = <&pm8998_l5>;
+		vdd-1.8-xo-supply = <&pm8998_l7>;
+		vdd-1.3-rfa-supply = <&pm8998_l17>;
+		vdd-3.3-ch0-supply = <&pm8998_l25>;
+		qcom,vdd-0.8-cx-mx-config = <800000 800000>;
+		qcom,vdd-3.3-ch0-config = <3104000 3312000>;
 	};
 
 	thermal_zones: thermal-zones {
-		aoss0-ts0-h {
+		aoss0-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "user_space";
@@ -2622,7 +2717,7 @@
 			};
 		};
 
-		cpu0-silver-ts0-h {
+		cpu0-silver-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "user_space";
@@ -2636,7 +2731,7 @@
 			};
 		};
 
-		cpu1-silver-ts0-h {
+		cpu1-silver-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "user_space";
@@ -2650,7 +2745,7 @@
 			};
 		};
 
-		cpu2-silver-ts0-h {
+		cpu2-silver-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "user_space";
@@ -2664,7 +2759,7 @@
 			};
 		};
 
-		cpu3-silver-ts0-h {
+		cpu3-silver-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 4>;
@@ -2678,7 +2773,7 @@
 			};
 		};
 
-		kryo-l3-0-ts0-h {
+		kryo-l3-0-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 5>;
@@ -2692,7 +2787,7 @@
 			};
 		};
 
-		kryo-l3-1-ts0-h {
+		kryo-l3-1-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 6>;
@@ -2706,7 +2801,7 @@
 			};
 		};
 
-		cpu0-gold-ts0-h {
+		cpu0-gold-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 7>;
@@ -2720,7 +2815,7 @@
 			};
 		};
 
-		cpu1-gold-ts0-h {
+		cpu1-gold-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 8>;
@@ -2734,7 +2829,7 @@
 			};
 		};
 
-		cpu2-gold-ts0-h {
+		cpu2-gold-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 9>;
@@ -2748,7 +2843,7 @@
 			};
 		};
 
-		cpu3-gold-ts0-h {
+		cpu3-gold-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 10>;
@@ -2762,7 +2857,7 @@
 			};
 		};
 
-		gpu0-ts0-h {
+		gpu0-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 11>;
@@ -2776,7 +2871,7 @@
 			};
 		};
 
-		gpu1-ts0-h {
+		gpu1-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "user_space";
@@ -2790,7 +2885,7 @@
 			};
 		};
 
-		aoss1-ts1-h {
+		aoss1-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 0>;
@@ -2804,7 +2899,7 @@
 			};
 		};
 
-		mdm-dsp-ts1-h {
+		mdm-dsp-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 1>;
@@ -2820,7 +2915,7 @@
 
 
 
-		ddr-ts1-h {
+		ddr-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 2>;
@@ -2834,7 +2929,7 @@
 			};
 		};
 
-		wlan-ts1-h {
+		wlan-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 3>;
@@ -2848,7 +2943,7 @@
 			};
 		};
 
-		compute-hvx-ts1-h {
+		compute-hvx-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 4>;
@@ -2862,7 +2957,7 @@
 			};
 		};
 
-		camera-ts1-h {
+		camera-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 5>;
@@ -2876,7 +2971,7 @@
 			};
 		};
 
-		mmss-ts1-h {
+		mmss-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 6>;
@@ -2890,7 +2985,7 @@
 			};
 		};
 
-		mdm-core-ts1-h {
+		mdm-core-usr {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 7>;
@@ -2904,7 +2999,7 @@
 			};
 		};
 
-		gpu0 {
+		gpu0-step {
 			polling-delay-passive = <10>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 11>;
@@ -2925,7 +3020,7 @@
 			};
 		};
 
-		gpu1 {
+		gpu1-step {
 			polling-delay-passive = <10>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens0 12>;
@@ -2946,7 +3041,7 @@
 			};
 		};
 
-		pop-mem {
+		pop-mem-step {
 			polling-delay-passive = <10>;
 			polling-delay = <0>;
 			thermal-sensors = <&tsens1 2>;
@@ -2967,7 +3062,7 @@
 			};
 		};
 
-		aoss0-ts0-l {
+		aoss0-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -2996,7 +3091,7 @@
 			};
 		};
 
-		cpu0-silver-ts0-l {
+		cpu0-silver-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3025,7 +3120,7 @@
 			};
 		};
 
-		cpu1-silver-ts0-l {
+		cpu1-silver-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3054,7 +3149,7 @@
 			};
 		};
 
-		cpu2-silver-ts0-l {
+		cpu2-silver-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3083,7 +3178,7 @@
 			};
 		};
 
-		cpu3-silver-ts0-l {
+		cpu3-silver-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3112,7 +3207,7 @@
 			};
 		};
 
-		kryo-l3-0-ts0-l {
+		kryo-l3-0-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3141,7 +3236,7 @@
 			};
 		};
 
-		kryo-l3-1-ts0-l {
+		kryo-l3-1-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3170,7 +3265,7 @@
 			};
 		};
 
-		cpu0-gold-ts0-l {
+		cpu0-gold-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3199,7 +3294,7 @@
 			};
 		};
 
-		cpu1-gold-ts0-l {
+		cpu1-gold-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3228,7 +3323,7 @@
 			};
 		};
 
-		cpu2-gold-ts0-l {
+		cpu2-gold-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3257,11 +3352,11 @@
 			};
 		};
 
-		cpu3-gold-ts0-l {
+		cpu3-gold-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
-			thermal-sensors = <&tsens0 9>;
+			thermal-sensors = <&tsens0 10>;
 			tracks-low;
 			trips {
 				cpug3_trip: cpug3-trip {
@@ -3286,11 +3381,11 @@
 			};
 		};
 
-		gpu0-ts0-l {
+		gpu0-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
-			thermal-sensors = <&tsens0 10>;
+			thermal-sensors = <&tsens0 11>;
 			tracks-low;
 			trips {
 				gpu0_trip_l: gpu0-trip {
@@ -3315,11 +3410,11 @@
 			};
 		};
 
-		gpu1-ts0-l {
+		gpu1-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
-			thermal-sensors = <&tsens0 11>;
+			thermal-sensors = <&tsens0 12>;
 			tracks-low;
 			trips {
 				gpu1_trip_l: gpu1-trip_l {
@@ -3344,7 +3439,7 @@
 			};
 		};
 
-		aoss1-ts1-l {
+		aoss1-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3373,7 +3468,7 @@
 			};
 		};
 
-		mdm-dsp-ts1-l {
+		mdm-dsp-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3402,7 +3497,7 @@
 			};
 		};
 
-		ddr-ts1-l {
+		ddr-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3431,7 +3526,7 @@
 			};
 		};
 
-		wlan-ts1-l {
+		wlan-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3460,7 +3555,7 @@
 			};
 		};
 
-		compute-hvx-ts1-l {
+		compute-hvx-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3489,7 +3584,7 @@
 			};
 		};
 
-		camera-ts1-l {
+		camera-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3518,7 +3613,7 @@
 			};
 		};
 
-		mmss-ts1-l {
+		mmss-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
@@ -3547,7 +3642,7 @@
 			};
 		};
 
-		mdm-core-ts1-l {
+		mdm-core-lowf {
 			polling-delay-passive = <0>;
 			polling-delay = <0>;
 			thermal-governor = "low_limits_floor";
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 9b5de00..86bae12 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -527,7 +527,6 @@
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_PANIC_TIMEOUT=5
 CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_IPC_LOGGING=y
 CONFIG_CPU_FREQ_SWITCH_PROFILER=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 615150a..1436a40 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -576,7 +576,6 @@
 CONFIG_PANIC_ON_RT_THROTTLING=y
 CONFIG_SCHEDSTATS=y
 CONFIG_SCHED_STACK_END_CHECK=y
-CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_SPINLOCK=y
 CONFIG_DEBUG_MUTEXES=y
diff --git a/drivers/clk/qcom/camcc-sdm845.c b/drivers/clk/qcom/camcc-sdm845.c
index 6296c40..adbabea 100644
--- a/drivers/clk/qcom/camcc-sdm845.c
+++ b/drivers/clk/qcom/camcc-sdm845.c
@@ -764,7 +764,8 @@
 };
 
 static const struct freq_tbl ftbl_cam_cc_mclk0_clk_src[] = {
-	F(24000000, P_CAM_CC_PLL3_OUT_EVEN, 16, 0, 0),
+	F(19200000, P_BI_TCXO, 1, 0, 0),
+	F(24000000, P_CAM_CC_PLL2_OUT_EVEN, 10, 1, 2),
 	F(33333333, P_CAM_CC_PLL0_OUT_EVEN, 2, 1, 9),
 	F(34285714, P_CAM_CC_PLL2_OUT_EVEN, 14, 0, 0),
 	{ }
diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c
index 61067ca..5fb870b 100644
--- a/drivers/clk/qcom/clk-cpu-osm.c
+++ b/drivers/clk/qcom/clk-cpu-osm.c
@@ -54,10 +54,10 @@
 
 #define OSM_REG_SIZE			32
 
-#define L3_EFUSE_SHIFT			0
-#define L3_EFUSE_MASK			0
-#define PWRCL_EFUSE_SHIFT		0
-#define PWRCL_EFUSE_MASK		0
+#define L3_EFUSE_SHIFT			29
+#define L3_EFUSE_MASK			0x7
+#define PWRCL_EFUSE_SHIFT		29
+#define PWRCL_EFUSE_MASK		0x7
 #define PERFCL_EFUSE_SHIFT		29
 #define PERFCL_EFUSE_MASK		0x7
 
@@ -2149,6 +2149,20 @@
 
 	/* efuse speed bin fuses are optional */
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+					   "l3_efuse");
+	if (res) {
+		pbase = (unsigned long)res->start;
+		vbase = devm_ioremap(&pdev->dev, res->start,
+				     resource_size(res));
+		if (!vbase) {
+			dev_err(&pdev->dev, "Unable to map in l3_efuse base\n");
+			return -ENOMEM;
+		}
+		l3_clk.pbases[EFUSE_BASE] = pbase;
+		l3_clk.vbases[EFUSE_BASE] = vbase;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
 					   "pwrcl_efuse");
 	if (res) {
 		pbase = (unsigned long)res->start;
@@ -2250,7 +2264,7 @@
 static int clk_cpu_osm_driver_probe(struct platform_device *pdev)
 {
 	int rc = 0, cpu, i;
-	int speedbin = 0, pvs_ver = 0;
+	int pvs_ver = 0;
 	u32 pte_efuse, val;
 	int num_clks = ARRAY_SIZE(osm_qcom_clk_hws);
 	struct clk *ext_xo_clk, *clk;
@@ -2307,11 +2321,11 @@
 		l3_clk.speedbin = ((pte_efuse >> L3_EFUSE_SHIFT) &
 						    L3_EFUSE_MASK);
 		snprintf(l3speedbinstr, ARRAY_SIZE(l3speedbinstr),
-			 "qcom,l3-speedbin%d-v%d", speedbin, pvs_ver);
+			 "qcom,l3-speedbin%d-v%d", l3_clk.speedbin, pvs_ver);
 	}
 
 	dev_info(&pdev->dev, "using L3 speed bin %u and pvs_ver %d\n",
-		 speedbin, pvs_ver);
+		 l3_clk.speedbin, pvs_ver);
 
 	rc = clk_osm_get_lut(pdev, &l3_clk, l3speedbinstr);
 	if (rc) {
@@ -2326,11 +2340,12 @@
 		pwrcl_clk.speedbin = ((pte_efuse >> PWRCL_EFUSE_SHIFT) &
 						    PWRCL_EFUSE_MASK);
 		snprintf(pwrclspeedbinstr, ARRAY_SIZE(pwrclspeedbinstr),
-			 "qcom,pwrcl-speedbin%d-v%d", speedbin, pvs_ver);
+			 "qcom,pwrcl-speedbin%d-v%d", pwrcl_clk.speedbin,
+							pvs_ver);
 	}
 
 	dev_info(&pdev->dev, "using pwrcl speed bin %u and pvs_ver %d\n",
-		 speedbin, pvs_ver);
+		 pwrcl_clk.speedbin, pvs_ver);
 
 	rc = clk_osm_get_lut(pdev, &pwrcl_clk, pwrclspeedbinstr);
 	if (rc) {
@@ -2345,11 +2360,12 @@
 		perfcl_clk.speedbin = ((pte_efuse >> PERFCL_EFUSE_SHIFT) &
 							PERFCL_EFUSE_MASK);
 		snprintf(perfclspeedbinstr, ARRAY_SIZE(perfclspeedbinstr),
-			 "qcom,perfcl-speedbin%d-v%d", speedbin, pvs_ver);
+			 "qcom,perfcl-speedbin%d-v%d", perfcl_clk.speedbin,
+							pvs_ver);
 	}
 
 	dev_info(&pdev->dev, "using perfcl speed bin %u and pvs_ver %d\n",
-		 speedbin, pvs_ver);
+		 perfcl_clk.speedbin, pvs_ver);
 
 	rc = clk_osm_get_lut(pdev, &perfcl_clk, perfclspeedbinstr);
 	if (rc) {
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index c7260f9..f187ad1 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -1556,19 +1556,9 @@
 	return rc;
 }
 
-/**
- * dsi_ctrl_setup() - Setup DSI host hardware while coming out of idle screen.
- * @dsi_ctrl:        DSI controller handle.
- *
- * Initializes DSI controller hardware with host configuration provided by
- * dsi_ctrl_update_host_config(). Initialization can be performed only during
- * DSI_CTRL_POWER_CORE_CLK_ON state and after the PHY SW reset has been
- * performed.
- *
- * Return: error code.
- */
 int dsi_ctrl_setup(struct dsi_ctrl *dsi_ctrl)
 {
+	struct dsi_mode_info video_timing;
 	int rc = 0;
 
 	if (!dsi_ctrl) {
@@ -1578,6 +1568,12 @@
 
 	mutex_lock(&dsi_ctrl->ctrl_lock);
 
+	/* replace video mode width with actual roi width */
+	memcpy(&video_timing, &dsi_ctrl->host_config.video_timing,
+			sizeof(video_timing));
+	video_timing.h_active = dsi_ctrl->roi.w;
+	video_timing.v_active = dsi_ctrl->roi.h;
+
 	dsi_ctrl->hw.ops.setup_lane_map(&dsi_ctrl->hw,
 					&dsi_ctrl->host_config.lane_map);
 
@@ -1590,8 +1586,8 @@
 					&dsi_ctrl->host_config.u.cmd_engine);
 
 		dsi_ctrl->hw.ops.setup_cmd_stream(&dsi_ctrl->hw,
-				&dsi_ctrl->host_config.video_timing,
-				dsi_ctrl->host_config.video_timing.h_active * 3,
+				&video_timing,
+				video_timing.h_active * 3,
 				0x0);
 		dsi_ctrl->hw.ops.cmd_engine_en(&dsi_ctrl->hw, true);
 	} else {
@@ -1611,6 +1607,26 @@
 	return rc;
 }
 
+int dsi_ctrl_set_roi(struct dsi_ctrl *dsi_ctrl, struct dsi_rect *roi,
+		bool *changed)
+{
+	int rc = 0;
+
+	if (!dsi_ctrl || !roi || !changed) {
+		pr_err("Invalid params\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&dsi_ctrl->ctrl_lock);
+	if (!dsi_rect_is_equal(&dsi_ctrl->roi, roi)) {
+		*changed = true;
+		memcpy(&dsi_ctrl->roi, roi, sizeof(dsi_ctrl->roi));
+	} else
+		*changed = false;
+	mutex_unlock(&dsi_ctrl->ctrl_lock);
+	return rc;
+}
+
 /**
  * dsi_ctrl_phy_reset_config() - Mask/unmask propagation of ahb reset signal
  *	to DSI PHY hardware.
@@ -1789,6 +1805,13 @@
 
 	pr_debug("[DSI_%d]Host config updated\n", ctrl->cell_index);
 	memcpy(&ctrl->host_config, config, sizeof(ctrl->host_config));
+	ctrl->mode_bounds.x = ctrl->host_config.video_timing.h_active *
+			ctrl->horiz_index;
+	ctrl->mode_bounds.y = 0;
+	ctrl->mode_bounds.w = ctrl->host_config.video_timing.h_active;
+	ctrl->mode_bounds.h = ctrl->host_config.video_timing.v_active;
+	memcpy(&ctrl->roi, &ctrl->mode_bounds, sizeof(ctrl->mode_bounds));
+	ctrl->roi.x = 0;
 error:
 	mutex_unlock(&ctrl->ctrl_lock);
 	return rc;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
index f8adbea..f89cb68 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
@@ -168,6 +168,7 @@
  * struct dsi_ctrl - DSI controller object
  * @pdev:                Pointer to platform device.
  * @cell_index:          Instance cell id.
+ * @horiz_index:         Index in physical horizontal CTRL layout, 0 = leftmost
  * @name:                Name of the controller instance.
  * @refcount:            ref counter.
  * @ctrl_lock:           Mutex for hardware and object access.
@@ -182,6 +183,10 @@
  * @pwr_info:            Power information.
  * @axi_bus_info:        AXI bus information.
  * @host_config:         Current host configuration.
+ * @mode_bounds:         Boundaries of the default mode ROI.
+ *                       Origin is at top left of all CTRLs.
+ * @roi:                 Partial update region of interest.
+ *                       Origin is top left of this CTRL.
  * @tx_cmd_buf:          Tx command buffer.
  * @cmd_buffer_size:     Size of command buffer.
  * @debugfs_root:        Root for debugfs entries.
@@ -189,6 +194,7 @@
 struct dsi_ctrl {
 	struct platform_device *pdev;
 	u32 cell_index;
+	u32 horiz_index;
 	const char *name;
 	u32 refcount;
 	struct mutex ctrl_lock;
@@ -209,6 +215,9 @@
 	struct dsi_ctrl_bus_scale_info axi_bus_info;
 
 	struct dsi_host_config host_config;
+	struct dsi_rect mode_bounds;
+	struct dsi_rect roi;
+
 	/* Command tx and rx */
 	struct drm_gem_object *tx_cmd_buf;
 	u32 cmd_buffer_size;
@@ -387,11 +396,25 @@
  * DSI_CTRL_POWER_CORE_CLK_ON state and after the PHY SW reset has been
  * performed.
  *
+ * Also used to program the video mode timing values.
+ *
  * Return: error code.
  */
 int dsi_ctrl_setup(struct dsi_ctrl *dsi_ctrl);
 
 /**
+ * dsi_ctrl_set_roi() - Set DSI controller's region of interest
+ * @dsi_ctrl:        DSI controller handle.
+ * @roi:             Region of interest rectangle, must be less than mode bounds
+ * @changed:         Output parameter, set to true of the controller's ROI was
+ *                   dirtied by setting the new ROI, and DCS cmd update needed
+ *
+ * Return: error code.
+ */
+int dsi_ctrl_set_roi(struct dsi_ctrl *dsi_ctrl, struct dsi_rect *roi,
+		bool *changed);
+
+/**
  * dsi_ctrl_set_tpg_state() - enable/disable test pattern on the controller
  * @dsi_ctrl:          DSI controller handle.
  * @on:                enable/disable test pattern.
@@ -401,7 +424,6 @@
  *
  * Return: error code.
  */
-
 int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on);
 
 /**
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
index 563285d..cf36315 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
@@ -411,4 +411,40 @@
 	struct msm_mode_info *mode_info;
 };
 
+/**
+ * struct dsi_rect - dsi rectangle representation
+ * Note: sde_rect is also using u16, this must be maintained for memcpy
+ */
+struct dsi_rect {
+	u16 x;
+	u16 y;
+	u16 w;
+	u16 h;
+};
+
+/**
+ * dsi_rect_intersect - intersect two rectangles
+ * @r1: first rectangle
+ * @r2: scissor rectangle
+ * @result: result rectangle, all 0's on no intersection found
+ */
+void dsi_rect_intersect(const struct dsi_rect *r1,
+		const struct dsi_rect *r2,
+		struct dsi_rect *result);
+
+/**
+ * dsi_rect_is_equal - compares two rects
+ * @r1: rect value to compare
+ * @r2: rect value to compare
+ *
+ * Returns true if the rects are same
+ */
+static inline bool dsi_rect_is_equal(struct dsi_rect *r1,
+		struct dsi_rect *r2)
+{
+	return r1->x == r2->x && r1->y == r2->y && r1->w == r2->w &&
+			r1->h == r2->h;
+}
+
+
 #endif /* _DSI_DEFS_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 231f29b..c2cf2cb 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -38,6 +38,30 @@
 
 static struct dsi_display *main_display;
 
+void dsi_rect_intersect(const struct dsi_rect *r1,
+		const struct dsi_rect *r2,
+		struct dsi_rect *result)
+{
+	int l, t, r, b;
+
+	if (!r1 || !r2 || !result)
+		return;
+
+	l = max(r1->x, r2->x);
+	t = max(r1->y, r2->y);
+	r = min((r1->x + r1->w), (r2->x + r2->w));
+	b = min((r1->y + r1->h), (r2->y + r2->h));
+
+	if (r <= l || b <= t) {
+		memset(result, 0, sizeof(*result));
+	} else {
+		result->x = l;
+		result->y = t;
+		result->w = r - l;
+		result->h = b - t;
+	}
+}
+
 int dsi_display_set_backlight(void *display, u32 bl_lvl)
 {
 	struct dsi_display *dsi_display = display;
@@ -2285,6 +2309,7 @@
 			       display->name, i, rc);
 			goto error_ctrl_deinit;
 		}
+		display_ctrl->ctrl->horiz_index = i;
 
 		rc = dsi_phy_drv_init(display_ctrl->phy);
 		if (rc) {
@@ -2750,6 +2775,10 @@
 				display->panel->mode.panel_mode);
 		break;
 	}
+
+	memcpy(&info->roi_caps, &display->panel->roi_caps,
+			sizeof(info->roi_caps));
+
 error:
 	mutex_unlock(&display->display_lock);
 	return rc;
@@ -3036,10 +3065,110 @@
 	return rc;
 }
 
+static int dsi_display_calc_ctrl_roi(const struct dsi_display *display,
+		const struct dsi_display_ctrl *ctrl,
+		const struct msm_roi_list *req_rois,
+		struct dsi_rect *out_roi)
+{
+	const struct dsi_rect *bounds = &ctrl->ctrl->mode_bounds;
+	struct dsi_rect req_roi = { 0 };
+	int rc = 0;
+
+	if (req_rois->num_rects > display->panel->roi_caps.num_roi) {
+		pr_err("request for %d rois greater than max %d\n",
+				req_rois->num_rects,
+				display->panel->roi_caps.num_roi);
+		rc = -EINVAL;
+		goto exit;
+	}
+
+	/**
+	 * if no rois, user wants to reset back to full resolution
+	 * note: h_active is already divided by ctrl_count
+	 */
+	if (!req_rois->num_rects) {
+		*out_roi = *bounds;
+		goto exit;
+	}
+
+	/* intersect with the bounds */
+	req_roi.x = req_rois->roi[0].x1;
+	req_roi.y = req_rois->roi[0].y1;
+	req_roi.w = req_rois->roi[0].x2 - req_rois->roi[0].x1;
+	req_roi.h = req_rois->roi[0].y2 - req_rois->roi[0].y1;
+	dsi_rect_intersect(&req_roi, bounds, out_roi);
+
+exit:
+	/* adjust the ctrl origin to be top left within the ctrl */
+	out_roi->x = out_roi->x - bounds->x;
+
+	pr_debug("ctrl%d:%d: req (%d,%d,%d,%d) bnd (%d,%d,%d,%d) out (%d,%d,%d,%d)\n",
+			ctrl->dsi_ctrl_idx, ctrl->ctrl->cell_index,
+			req_roi.x, req_roi.y, req_roi.w, req_roi.h,
+			bounds->x, bounds->y, bounds->w, bounds->h,
+			out_roi->x, out_roi->y, out_roi->w, out_roi->h);
+
+	return rc;
+}
+
+static int dsi_display_set_roi(struct dsi_display *display,
+		struct msm_roi_list *rois)
+{
+	int rc = 0;
+	int i;
+
+	if (!display || !rois || !display->panel)
+		return -EINVAL;
+
+	if (!display->panel->roi_caps.enabled)
+		return 0;
+
+	for (i = 0; i < display->ctrl_count; i++) {
+		struct dsi_display_ctrl *ctrl = &display->ctrl[i];
+		struct dsi_rect ctrl_roi;
+		bool changed = false;
+
+		rc = dsi_display_calc_ctrl_roi(display, ctrl, rois, &ctrl_roi);
+		if (rc) {
+			pr_err("dsi_display_calc_ctrl_roi failed rc %d\n", rc);
+			return rc;
+		}
+
+		rc = dsi_ctrl_set_roi(ctrl->ctrl, &ctrl_roi, &changed);
+		if (rc) {
+			pr_err("dsi_ctrl_set_roi failed rc %d\n", rc);
+			return rc;
+		}
+
+		if (!changed)
+			continue;
+
+		/* send the new roi to the panel via dcs commands */
+		rc = dsi_panel_send_roi_dcs(display->panel, i, &ctrl_roi);
+		if (rc) {
+			pr_err("dsi_panel_set_roi failed rc %d\n", rc);
+			return rc;
+		}
+
+		/* re-program the ctrl with the timing based on the new roi */
+		rc = dsi_ctrl_setup(ctrl->ctrl);
+		if (rc) {
+			pr_err("dsi_ctrl_setup failed rc %d\n", rc);
+			return rc;
+		}
+	}
+
+	return rc;
+}
+
 int dsi_display_pre_kickoff(struct dsi_display *display,
 		struct msm_display_kickoff_params *params)
 {
-	return 0;
+	int rc = 0;
+
+	rc = dsi_display_set_roi(display, params->rois);
+
+	return rc;
 }
 
 int dsi_display_enable(struct dsi_display *display)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index 3f4bb5a5..53f0098 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -379,6 +379,25 @@
 		break;
 	}
 
+	if (panel->roi_caps.enabled) {
+		sde_kms_info_add_keyint(info, "partial_update_num_roi",
+				panel->roi_caps.num_roi);
+		sde_kms_info_add_keyint(info, "partial_update_xstart",
+				panel->roi_caps.align.xstart_pix_align);
+		sde_kms_info_add_keyint(info, "partial_update_walign",
+				panel->roi_caps.align.width_pix_align);
+		sde_kms_info_add_keyint(info, "partial_update_wmin",
+				panel->roi_caps.align.min_width);
+		sde_kms_info_add_keyint(info, "partial_update_ystart",
+				panel->roi_caps.align.ystart_pix_align);
+		sde_kms_info_add_keyint(info, "partial_update_halign",
+				panel->roi_caps.align.height_pix_align);
+		sde_kms_info_add_keyint(info, "partial_update_hmin",
+				panel->roi_caps.align.min_height);
+		sde_kms_info_add_keyint(info, "partial_update_roimerge",
+				panel->roi_caps.merge_rois);
+	}
+
 end:
 	return 0;
 }
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index deb718c..dcb787b 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -12,10 +12,12 @@
  *
  */
 
+#define pr_fmt(fmt)	"msm-dsi-panel:[%s:%d] " fmt, __func__, __LINE__
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
+#include <video/mipi_display.h>
 
 #include "dsi_panel.h"
 #include "dsi_ctrl_hw.h"
@@ -1289,6 +1291,8 @@
 	"qcom,video-to-cmd-mode-switch-commands",
 	"qcom,video-to-cmd-mode-post-switch-commands",
 	"qcom,mdss-dsi-panel-status-command",
+	"PPS not parsed from DTSI, generated dynamically",
+	"ROI not parsed from DTSI, generated dynamically",
 };
 
 const char *cmd_set_state_map[DSI_CMD_SET_MAX] = {
@@ -1306,6 +1310,8 @@
 	"qcom,video-to-cmd-mode-switch-commands-state",
 	"qcom,video-to-cmd-mode-post-switch-commands-state",
 	"qcom,mdss-dsi-panel-status-command-state",
+	"PPS not parsed from DTSI, generated dynamically",
+	"ROI not parsed from DTSI, generated dynamically",
 };
 
 static int dsi_panel_get_cmd_pkt_count(const char *data, u32 length, u32 *cnt)
@@ -1348,6 +1354,7 @@
 		cmd[i].last_command = (data[1] == 1 ? true : false);
 		cmd[i].msg.channel = data[2];
 		cmd[i].msg.flags |= (data[3] == 1 ? MIPI_DSI_MSG_REQ_ACK : 0);
+		cmd[i].msg.ctrl = 0;
 		cmd[i].post_wait_ms = data[4];
 		cmd[i].msg.tx_len = ((data[5] << 8) | (data[6]));
 
@@ -1376,7 +1383,7 @@
 	return rc;
 }
 
-static void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set)
+void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set)
 {
 	u32 i = 0;
 	struct dsi_cmd_desc *cmd;
@@ -1471,6 +1478,8 @@
 	for (i = DSI_CMD_SET_PRE_ON; i < DSI_CMD_SET_MAX; i++) {
 		set = &panel->cmd_sets[i];
 		set->type = i;
+		set->count = 0;
+
 		if (i == DSI_CMD_SET_PPS) {
 			rc = dsi_panel_alloc_cmd_packets(set, 1);
 			if (rc)
@@ -2175,6 +2184,87 @@
 	return rc;
 }
 
+static int dsi_panel_parse_roi_alignment(struct device_node *of_node,
+					 struct msm_roi_alignment *align)
+{
+	int len = 0, rc = 0;
+	u32 value[6];
+	struct property *data;
+
+	if (!align || !of_node)
+		return -EINVAL;
+
+	memset(align, 0, sizeof(*align));
+
+	data = of_find_property(of_node, "qcom,panel-roi-alignment", &len);
+	len /= sizeof(u32);
+	if (!data) {
+		pr_err("panel roi alignment not found\n");
+		rc = -EINVAL;
+	} else if (len != 6) {
+		pr_err("incorrect roi alignment len %d\n", len);
+		rc = -EINVAL;
+	} else {
+		rc = of_property_read_u32_array(of_node,
+				"qcom,panel-roi-alignment", value, len);
+		if (rc)
+			pr_debug("error reading panel roi alignment values\n");
+		else {
+			align->xstart_pix_align = value[0];
+			align->ystart_pix_align = value[1];
+			align->width_pix_align = value[2];
+			align->height_pix_align = value[3];
+			align->min_width = value[4];
+			align->min_height = value[5];
+		}
+
+		pr_info("roi alignment: [%d, %d, %d, %d, %d, %d]\n",
+			align->xstart_pix_align,
+			align->width_pix_align,
+			align->ystart_pix_align,
+			align->height_pix_align,
+			align->min_width,
+			align->min_height);
+	}
+
+	return rc;
+}
+
+static int dsi_panel_parse_partial_update_caps(struct dsi_panel *panel,
+					       struct device_node *of_node)
+{
+	struct msm_roi_caps *roi_caps = &panel->roi_caps;
+	const char *data;
+	int rc = 0;
+
+	memset(roi_caps, 0, sizeof(*roi_caps));
+
+	data = of_get_property(of_node, "qcom,partial-update-enabled", NULL);
+	if (data) {
+		if (!strcmp(data, "dual_roi"))
+			roi_caps->num_roi = 2;
+		else
+			roi_caps->num_roi = 1;
+	}
+
+	roi_caps->merge_rois = of_property_read_bool(of_node,
+			"qcom,partial-update-roi-merge");
+
+	roi_caps->enabled = roi_caps->num_roi > 0;
+
+	pr_info("partial update num_rois=%d enabled=%d\n", roi_caps->num_roi,
+			roi_caps->enabled);
+
+	if (roi_caps->enabled)
+		rc = dsi_panel_parse_roi_alignment(of_node,
+				&panel->roi_caps.align);
+
+	if (rc)
+		memset(roi_caps, 0, sizeof(*roi_caps));
+
+	return rc;
+}
+
 struct dsi_panel *dsi_panel_get(struct device *parent,
 				struct device_node *of_node)
 {
@@ -2291,6 +2381,10 @@
 	if (rc)
 		pr_err("failed to parse hdr config, rc=%d\n", rc);
 
+	rc = dsi_panel_parse_partial_update_caps(panel, of_node);
+	if (rc)
+		pr_debug("failed to partial update caps, rc=%d\n", rc);
+
 	panel->panel_of_node = of_node;
 	drm_panel_init(&panel->drm_panel);
 	mutex_init(&panel->panel_lock);
@@ -2624,6 +2718,114 @@
 	return rc;
 }
 
+static int dsi_panel_roi_prepare_dcs_cmds(struct dsi_panel *panel,
+		struct dsi_rect *roi, int ctrl_idx, int unicast)
+{
+	static const int ROI_CMD_LEN = 5;
+	struct dsi_panel_cmd_set *set = &panel->cmd_sets[DSI_CMD_SET_ROI];
+	int rc = 0;
+
+	/* DTYPE_DCS_LWRITE */
+	static char *caset, *paset;
+
+	set->cmds = NULL;
+
+	caset = kzalloc(ROI_CMD_LEN, GFP_KERNEL);
+	if (!caset) {
+		rc = -ENOMEM;
+		goto exit;
+	}
+	caset[0] = 0x2a;
+	caset[1] = (roi->x & 0xFF00) >> 8;
+	caset[2] = roi->x & 0xFF;
+	caset[3] = ((roi->x - 1 + roi->w) & 0xFF00) >> 8;
+	caset[4] = (roi->x - 1 + roi->w) & 0xFF;
+
+	paset = kzalloc(ROI_CMD_LEN, GFP_KERNEL);
+	if (!paset) {
+		rc = -ENOMEM;
+		goto error_free_mem;
+	}
+	paset[0] = 0x2b;
+	paset[1] = (roi->y & 0xFF00) >> 8;
+	paset[2] = roi->y & 0xFF;
+	paset[3] = ((roi->y - 1 + roi->h) & 0xFF00) >> 8;
+	paset[4] = (roi->y - 1 + roi->h) & 0xFF;
+
+	set->type = DSI_CMD_SET_ROI;
+	set->state = DSI_CMD_SET_STATE_LP;
+	set->count = 2; /* send caset + paset together */
+	set->cmds = kcalloc(set->count, sizeof(*set->cmds), GFP_KERNEL);
+	if (!set->cmds) {
+		rc = -ENOMEM;
+		goto error_free_mem;
+	}
+	set->cmds[0].msg.channel = 0;
+	set->cmds[0].msg.type = MIPI_DSI_DCS_LONG_WRITE;
+	set->cmds[0].msg.flags = unicast ? MIPI_DSI_MSG_UNICAST : 0;
+	set->cmds[0].msg.ctrl = unicast ? ctrl_idx : 0;
+	set->cmds[0].msg.tx_len = ROI_CMD_LEN;
+	set->cmds[0].msg.tx_buf = caset;
+	set->cmds[0].msg.rx_len = 0;
+	set->cmds[0].msg.rx_buf = 0;
+	set->cmds[0].last_command = 0;
+	set->cmds[0].post_wait_ms = 1;
+
+	set->cmds[1].msg.channel = 0;
+	set->cmds[1].msg.type = MIPI_DSI_DCS_LONG_WRITE;
+	set->cmds[1].msg.flags = unicast ? MIPI_DSI_MSG_UNICAST : 0;
+	set->cmds[1].msg.ctrl = unicast ? ctrl_idx : 0;
+	set->cmds[1].msg.tx_len = ROI_CMD_LEN;
+	set->cmds[1].msg.tx_buf = paset;
+	set->cmds[1].msg.rx_len = 0;
+	set->cmds[1].msg.rx_buf = 0;
+	set->cmds[1].last_command = 1;
+	set->cmds[1].post_wait_ms = 1;
+
+	goto exit;
+
+error_free_mem:
+	kfree(caset);
+	kfree(paset);
+	kfree(set->cmds);
+
+exit:
+	return rc;
+}
+
+int dsi_panel_send_roi_dcs(struct dsi_panel *panel, int ctrl_idx,
+		struct dsi_rect *roi)
+{
+	int rc = 0;
+
+	if (!panel) {
+		pr_err("Invalid params\n");
+		return -EINVAL;
+	}
+
+	rc = dsi_panel_roi_prepare_dcs_cmds(panel, roi, ctrl_idx, true);
+	if (rc) {
+		pr_err("[%s] failed to prepare DSI_CMD_SET_ROI cmds, rc=%d\n",
+				panel->name, rc);
+		return rc;
+	}
+	pr_debug("[%s] send roi x %d y %d w %d h %d\n", panel->name,
+			roi->x, roi->y, roi->w, roi->h);
+
+	mutex_lock(&panel->panel_lock);
+
+	rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_ROI);
+	if (rc)
+		pr_err("[%s] failed to send DSI_CMD_SET_ROI cmds, rc=%d\n",
+				panel->name, rc);
+
+	mutex_unlock(&panel->panel_lock);
+
+	dsi_panel_destroy_cmd_packets(&panel->cmd_sets[DSI_CMD_SET_ROI]);
+
+	return rc;
+}
+
 int dsi_panel_enable(struct dsi_panel *panel)
 {
 	int rc = 0;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
index de2b5b1..4c9fbbe 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
@@ -28,6 +28,7 @@
 #include "dsi_ctrl_hw.h"
 #include "dsi_clk.h"
 #include "dsi_pwr.h"
+#include "msm_drv.h"
 
 #define MAX_BL_LEVEL 4096
 #define DSI_CMD_PPS_SIZE 135
@@ -55,6 +56,7 @@
 	DSI_CMD_SET_POST_VID_TO_CMD_SWITCH,
 	DSI_CMD_SET_PANEL_STATUS,
 	DSI_CMD_SET_PPS,
+	DSI_CMD_SET_ROI,
 	DSI_CMD_SET_MAX
 };
 
@@ -162,6 +164,7 @@
 	struct dsi_cmd_engine_cfg cmd_config;
 
 	struct dsi_dfps_capabilities dfps_caps;
+	struct msm_roi_caps roi_caps;
 
 	struct dsi_panel_cmd_set cmd_sets[DSI_CMD_SET_MAX];
 	struct dsi_panel_phy_props phy_props;
@@ -242,4 +245,8 @@
 int dsi_panel_set_backlight(struct dsi_panel *panel, u32 bl_lvl);
 
 int dsi_panel_update_pps(struct dsi_panel *panel);
+
+int dsi_panel_send_roi_dcs(struct dsi_panel *panel, int ctrl_idx,
+		struct dsi_rect *roi);
+
 #endif /* _DSI_PANEL_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_dspp.c b/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
index 8df4de2..586d1f1 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_dspp.c
@@ -151,5 +151,7 @@
 
 void sde_hw_dspp_destroy(struct sde_hw_dspp *dspp)
 {
+	if (dspp)
+		reg_dmav1_deinit_dspp_ops(dspp->idx);
 	kfree(dspp);
 }
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
index 49af946..c33e520 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
@@ -553,3 +553,26 @@
 			BIT(0));
 	SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gc.base, reg);
 }
+
+int reg_dmav1_deinit_dspp_ops(enum sde_dspp idx)
+{
+	int i;
+	struct sde_hw_reg_dma_ops *dma_ops;
+
+	dma_ops = sde_reg_dma_get_ops();
+	if (IS_ERR_OR_NULL(dma_ops))
+		return -ENOTSUPP;
+
+	if (idx >= DSPP_MAX) {
+		DRM_ERROR("invalid dspp idx %x max %xd\n", idx, DSPP_MAX);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < REG_DMA_FEATURES_MAX; i++) {
+		if (!dspp_buf[i][idx])
+			continue;
+		dma_ops->dealloc_reg_dma(dspp_buf[i][idx]);
+		dspp_buf[i][idx] = NULL;
+	}
+	return 0;
+}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.h b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.h
index e3bf142..94e1a5c 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.h
@@ -51,4 +51,11 @@
  * @cfg: pointer to struct sde_hw_cp_cfg
  */
 void reg_dmav1_setup_dspp_gcv18(struct sde_hw_dspp *ctx, void *cfg);
+
+/**
+ * reg_dmav1_deinit_dspp_ops() - deinitialize the dspp feature op for sde v4
+ *                               which were initialized.
+ * @idx: dspp idx
+ */
+int reg_dmav1_deinit_dspp_ops(enum sde_dspp idx);
 #endif /* _SDE_HW_REG_DMA_V1_COLOR_PROC_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index b68d736..8cc196a 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -1472,6 +1472,16 @@
 
 	sde_dbg_init_dbg_buses(sde_kms->core_rev);
 
+	/*
+	 * Now we need to read the HW catalog and initialize resources such as
+	 * clocks, regulators, GDSC/MMAGIC, ioremap the register ranges etc
+	 */
+	rc = _sde_kms_mmu_init(sde_kms);
+	if (rc) {
+		SDE_ERROR("sde_kms_mmu_init failed: %d\n", rc);
+		goto power_error;
+	}
+
 	/* Initialize reg dma block which is a singleton */
 	rc = sde_reg_dma_init(sde_kms->reg_dma, sde_kms->catalog,
 			sde_kms->dev);
@@ -1521,15 +1531,6 @@
 		sde_kms->iclient = NULL;
 	}
 
-	/*
-	 * Now we need to read the HW catalog and initialize resources such as
-	 * clocks, regulators, GDSC/MMAGIC, ioremap the register ranges etc
-	 */
-	rc = _sde_kms_mmu_init(sde_kms);
-	if (rc) {
-		SDE_ERROR("sde_kms_mmu_init failed: %d\n", rc);
-		goto power_error;
-	}
 
 	rc = sde_core_perf_init(&sde_kms->perf, dev, sde_kms->catalog,
 			&priv->phandle, priv->pclient, "core_clk");
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 01dc5e1..f9449fe 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -64,6 +64,7 @@
 void tmc_enable_hw(struct tmc_drvdata *drvdata)
 {
 	drvdata->enable = true;
+	drvdata->sticky_enable = true;
 	writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
 }
 
@@ -77,6 +78,9 @@
 {
 	int ret = 0;
 
+	if (!drvdata->sticky_enable)
+		return -EPERM;
+
 	switch (drvdata->config_type) {
 	case TMC_CONFIG_TYPE_ETB:
 	case TMC_CONFIG_TYPE_ETF:
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 3d6e823..a9de0e8 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -183,6 +183,7 @@
 	struct usb_qdss_ch	*usbch;
 	struct tmc_etr_bam_data	*bamdata;
 	bool			enable_to_bam;
+	bool			sticky_enable;
 
 };
 
diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c
index e1c16aa..62e34cc 100644
--- a/drivers/input/misc/qpnp-power-on.c
+++ b/drivers/input/misc/qpnp-power-on.c
@@ -207,7 +207,7 @@
 	int			pon_power_off_reason;
 	int			num_pon_reg;
 	int			num_pon_config;
-	u32			dbc;
+	u32			dbc_time_us;
 	u32			uvlo;
 	int			warm_reset_poff_type;
 	int			hard_reset_poff_type;
@@ -219,6 +219,8 @@
 	u8			warm_reset_reason2;
 	bool			is_spon;
 	bool			store_hard_reset_reason;
+	bool			kpdpwr_dbc_enable;
+	ktime_t			kpdpwr_last_release_time;
 };
 
 static int pon_ship_mode_en;
@@ -381,7 +383,7 @@
 	int rc = 0;
 	u32 val;
 
-	if (delay == pon->dbc)
+	if (delay == pon->dbc_time_us)
 		goto out;
 
 	if (pon->pon_input)
@@ -409,7 +411,7 @@
 		goto unlock;
 	}
 
-	pon->dbc = delay;
+	pon->dbc_time_us = delay;
 
 unlock:
 	if (pon->pon_input)
@@ -418,12 +420,34 @@
 	return rc;
 }
 
+static int qpnp_pon_get_dbc(struct qpnp_pon *pon, u32 *delay)
+{
+	int rc;
+	unsigned int val;
+
+	rc = regmap_read(pon->regmap, QPNP_PON_DBC_CTL(pon), &val);
+	if (rc) {
+		pr_err("Unable to read pon_dbc_ctl rc=%d\n", rc);
+		return rc;
+	}
+	val &= QPNP_PON_DBC_DELAY_MASK(pon);
+
+	if (is_pon_gen2(pon))
+		*delay = USEC_PER_SEC /
+			(1 << (QPNP_PON_GEN2_DELAY_BIT_SHIFT - val));
+	else
+		*delay = USEC_PER_SEC /
+			(1 << (QPNP_PON_DELAY_BIT_SHIFT - val));
+
+	return rc;
+}
+
 static ssize_t qpnp_pon_dbc_show(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
 	struct qpnp_pon *pon = dev_get_drvdata(dev);
 
-	return snprintf(buf, QPNP_PON_BUFFER_SIZE, "%d\n", pon->dbc);
+	return snprintf(buf, QPNP_PON_BUFFER_SIZE, "%d\n", pon->dbc_time_us);
 }
 
 static ssize_t qpnp_pon_dbc_store(struct device *dev,
@@ -777,6 +801,7 @@
 	u8  pon_rt_bit = 0;
 	u32 key_status;
 	uint pon_rt_sts;
+	u64 elapsed_us;
 
 	cfg = qpnp_get_cfg(pon, pon_type);
 	if (!cfg)
@@ -786,6 +811,15 @@
 	if (!cfg->key_code)
 		return 0;
 
+	if (pon->kpdpwr_dbc_enable && cfg->pon_type == PON_KPDPWR) {
+		elapsed_us = ktime_us_delta(ktime_get(),
+				pon->kpdpwr_last_release_time);
+		if (elapsed_us < pon->dbc_time_us) {
+			pr_debug("Ignoring kpdpwr event - within debounce time\n");
+			return 0;
+		}
+	}
+
 	/* check the RT status to get the current status of the line */
 	rc = regmap_read(pon->regmap, QPNP_PON_RT_STS(pon), &pon_rt_sts);
 	if (rc) {
@@ -814,6 +848,11 @@
 					cfg->key_code, pon_rt_sts);
 	key_status = pon_rt_sts & pon_rt_bit;
 
+	if (pon->kpdpwr_dbc_enable && cfg->pon_type == PON_KPDPWR) {
+		if (!key_status)
+			pon->kpdpwr_last_release_time = ktime_get();
+	}
+
 	/*
 	 * simulate press event in case release event occurred
 	 * without a press event
@@ -2230,7 +2269,21 @@
 		}
 	} else {
 		rc = qpnp_pon_set_dbc(pon, delay);
+		if (rc) {
+			dev_err(&pdev->dev,
+				"Unable to set PON debounce delay rc=%d\n", rc);
+			return rc;
+		}
 	}
+	rc = qpnp_pon_get_dbc(pon, &pon->dbc_time_us);
+	if (rc) {
+		dev_err(&pdev->dev,
+			"Unable to get PON debounce delay rc=%d\n", rc);
+		return rc;
+	}
+
+	pon->kpdpwr_dbc_enable = of_property_read_bool(pon->pdev->dev.of_node,
+					"qcom,kpdpwr-sw-debounce");
 
 	rc = of_property_read_u32(pon->pdev->dev.of_node,
 				"qcom,warm-reset-poweroff-type",
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
index bea5f03..0c49a64 100644
--- a/drivers/iommu/iommu-debug.c
+++ b/drivers/iommu/iommu-debug.c
@@ -81,330 +81,58 @@
 
 static DEFINE_MUTEX(iommu_debug_attachments_lock);
 static LIST_HEAD(iommu_debug_attachments);
-static struct dentry *debugfs_attachments_dir;
 
+/*
+ * Each group may have more than one domain; but each domain may
+ * only have one group.
+ * Used by debug tools to display the name of the device(s) associated
+ * with a particular domain.
+ */
 struct iommu_debug_attachment {
 	struct iommu_domain *domain;
-	struct device *dev;
-	struct dentry *dentry;
+	struct iommu_group *group;
 	struct list_head list;
-	unsigned long reg_offset;
 };
 
-static int iommu_debug_attachment_info_show(struct seq_file *s, void *ignored)
-{
-	struct iommu_debug_attachment *attach = s->private;
-	int secure_vmid;
-
-	seq_printf(s, "Domain: 0x%p\n", attach->domain);
-
-	seq_puts(s, "SECURE_VMID: ");
-	if (iommu_domain_get_attr(attach->domain,
-				  DOMAIN_ATTR_SECURE_VMID,
-				  &secure_vmid))
-		seq_puts(s, "(Unknown)\n");
-	else
-		seq_printf(s, "%s (0x%x)\n",
-			   msm_secure_vmid_to_string(secure_vmid), secure_vmid);
-
-	return 0;
-}
-
-static int iommu_debug_attachment_info_open(struct inode *inode,
-					    struct file *file)
-{
-	return single_open(file, iommu_debug_attachment_info_show,
-			   inode->i_private);
-}
-
-static const struct file_operations iommu_debug_attachment_info_fops = {
-	.open	 = iommu_debug_attachment_info_open,
-	.read	 = seq_read,
-	.llseek	 = seq_lseek,
-	.release = single_release,
-};
-
-static ssize_t iommu_debug_attachment_reg_offset_write(
-	struct file *file, const char __user *ubuf, size_t count,
-	loff_t *offset)
-{
-	struct iommu_debug_attachment *attach = file->private_data;
-	unsigned long reg_offset;
-
-	if (kstrtoul_from_user(ubuf, count, 0, &reg_offset)) {
-		pr_err("Invalid reg_offset format\n");
-		return -EFAULT;
-	}
-
-	attach->reg_offset = reg_offset;
-
-	return count;
-}
-
-static const struct file_operations iommu_debug_attachment_reg_offset_fops = {
-	.open	= simple_open,
-	.write	= iommu_debug_attachment_reg_offset_write,
-};
-
-static ssize_t iommu_debug_attachment_reg_read_read(
-	struct file *file, char __user *ubuf, size_t count, loff_t *offset)
-{
-	struct iommu_debug_attachment *attach = file->private_data;
-	unsigned long val;
-	char *val_str;
-	ssize_t val_str_len;
-
-	if (*offset)
-		return 0;
-
-	val = iommu_reg_read(attach->domain, attach->reg_offset);
-	val_str = kasprintf(GFP_KERNEL, "0x%lx\n", val);
-	if (!val_str)
-		return -ENOMEM;
-	val_str_len = strlen(val_str);
-
-	if (copy_to_user(ubuf, val_str, val_str_len)) {
-		pr_err("copy_to_user failed\n");
-		val_str_len = -EFAULT;
-		goto out;
-	}
-	*offset = 1;		/* non-zero means we're done */
-
-out:
-	kfree(val_str);
-	return val_str_len;
-}
-
-static const struct file_operations iommu_debug_attachment_reg_read_fops = {
-	.open	= simple_open,
-	.read	= iommu_debug_attachment_reg_read_read,
-};
-
-static ssize_t iommu_debug_attachment_reg_write_write(
-	struct file *file, const char __user *ubuf, size_t count,
-	loff_t *offset)
-{
-	struct iommu_debug_attachment *attach = file->private_data;
-	unsigned long val;
-
-	if (kstrtoul_from_user(ubuf, count, 0, &val)) {
-		pr_err("Invalid val format\n");
-		return -EFAULT;
-	}
-
-	iommu_reg_write(attach->domain, attach->reg_offset, val);
-
-	return count;
-}
-
-static const struct file_operations iommu_debug_attachment_reg_write_fops = {
-	.open	= simple_open,
-	.write	= iommu_debug_attachment_reg_write_write,
-};
-
-/* should be called with iommu_debug_attachments_lock locked */
-static int iommu_debug_attach_add_debugfs(
-	struct iommu_debug_attachment *attach)
-{
-	const char *attach_name;
-	struct device *dev = attach->dev;
-	struct iommu_domain *domain = attach->domain;
-	int is_dynamic;
-
-	if (iommu_domain_get_attr(domain, DOMAIN_ATTR_DYNAMIC, &is_dynamic))
-		is_dynamic = 0;
-
-	if (is_dynamic) {
-		uuid_le uuid;
-
-		uuid_le_gen(&uuid);
-		attach_name = kasprintf(GFP_KERNEL, "%s-%pUl", dev_name(dev),
-					uuid.b);
-		if (!attach_name)
-			return -ENOMEM;
-	} else {
-		attach_name = dev_name(dev);
-	}
-
-	attach->dentry = debugfs_create_dir(attach_name,
-					    debugfs_attachments_dir);
-	if (!attach->dentry) {
-		pr_err("Couldn't create iommu/attachments/%s debugfs directory for domain 0x%p\n",
-		       attach_name, domain);
-		if (is_dynamic)
-			kfree(attach_name);
-		return -EIO;
-	}
-
-	if (is_dynamic)
-		kfree(attach_name);
-
-	if (!debugfs_create_file(
-		    "info", S_IRUSR, attach->dentry, attach,
-		    &iommu_debug_attachment_info_fops)) {
-		pr_err("Couldn't create iommu/attachments/%s/info debugfs file for domain 0x%p\n",
-		       dev_name(dev), domain);
-		goto err_rmdir;
-	}
-
-	if (!debugfs_create_file(
-		    "reg_offset", S_IRUSR, attach->dentry, attach,
-		    &iommu_debug_attachment_reg_offset_fops)) {
-		pr_err("Couldn't create iommu/attachments/%s/reg_offset debugfs file for domain 0x%p\n",
-		       dev_name(dev), domain);
-		goto err_rmdir;
-	}
-
-	if (!debugfs_create_file(
-		    "reg_read", S_IRUSR, attach->dentry, attach,
-		    &iommu_debug_attachment_reg_read_fops)) {
-		pr_err("Couldn't create iommu/attachments/%s/reg_read debugfs file for domain 0x%p\n",
-		       dev_name(dev), domain);
-		goto err_rmdir;
-	}
-
-	if (!debugfs_create_file(
-		    "reg_write", S_IRUSR, attach->dentry, attach,
-		    &iommu_debug_attachment_reg_write_fops)) {
-		pr_err("Couldn't create iommu/attachments/%s/reg_write debugfs file for domain 0x%p\n",
-		       dev_name(dev), domain);
-		goto err_rmdir;
-	}
-
-	return 0;
-
-err_rmdir:
-	debugfs_remove_recursive(attach->dentry);
-	return -EIO;
-}
-
-void iommu_debug_domain_add(struct iommu_domain *domain)
-{
-	struct iommu_debug_attachment *attach;
-
-	mutex_lock(&iommu_debug_attachments_lock);
-
-	attach = kmalloc(sizeof(*attach), GFP_KERNEL);
-	if (!attach)
-		goto out_unlock;
-
-	attach->domain = domain;
-	attach->dev = NULL;
-	list_add(&attach->list, &iommu_debug_attachments);
-
-out_unlock:
-	mutex_unlock(&iommu_debug_attachments_lock);
-}
-
-void iommu_debug_domain_remove(struct iommu_domain *domain)
-{
-	struct iommu_debug_attachment *it;
-
-	mutex_lock(&iommu_debug_attachments_lock);
-	list_for_each_entry(it, &iommu_debug_attachments, list)
-		if (it->domain == domain && it->dev == NULL)
-			break;
-
-	if (&it->list == &iommu_debug_attachments) {
-		WARN(1, "Couldn't find debug attachment for domain=0x%p",
-				domain);
-	} else {
-		list_del(&it->list);
-		kfree(it);
-	}
-	mutex_unlock(&iommu_debug_attachments_lock);
-}
-
 void iommu_debug_attach_device(struct iommu_domain *domain,
 			       struct device *dev)
 {
 	struct iommu_debug_attachment *attach;
+	struct iommu_group *group;
+
+	group = iommu_group_get(dev);
+	if (!group)
+		return;
+
+	attach = kzalloc(sizeof(*attach), GFP_KERNEL);
+	if (!attach)
+		return;
+
+	attach->domain = domain;
+	attach->group = group;
+	INIT_LIST_HEAD(&attach->list);
 
 	mutex_lock(&iommu_debug_attachments_lock);
+	list_add(&attach->list, &iommu_debug_attachments);
+	mutex_unlock(&iommu_debug_attachments_lock);
+}
 
-	list_for_each_entry(attach, &iommu_debug_attachments, list)
-		if (attach->domain == domain && attach->dev == NULL)
-			break;
+void iommu_debug_domain_remove(struct iommu_domain *domain)
+{
+	struct iommu_debug_attachment *it, *tmp;
 
-	if (&attach->list == &iommu_debug_attachments) {
-		WARN(1, "Couldn't find debug attachment for domain=0x%p dev=%s",
-		     domain, dev_name(dev));
-	} else {
-		attach->dev = dev;
-
-		/*
-		 * we might not init until after other drivers start calling
-		 * iommu_attach_device. Only set up the debugfs nodes if we've
-		 * already init'd to avoid polluting the top-level debugfs
-		 * directory (by calling debugfs_create_dir with a NULL
-		 * parent). These will be flushed out later once we init.
-		 */
-
-		if (debugfs_attachments_dir)
-			iommu_debug_attach_add_debugfs(attach);
+	mutex_lock(&iommu_debug_attachments_lock);
+	list_for_each_entry_safe(it, tmp, &iommu_debug_attachments, list) {
+		if (it->domain != domain)
+			continue;
+		list_del(&it->list);
+		iommu_group_put(it->group);
+		kfree(it);
 	}
 
 	mutex_unlock(&iommu_debug_attachments_lock);
 }
 
-void iommu_debug_detach_device(struct iommu_domain *domain,
-			       struct device *dev)
-{
-	struct iommu_debug_attachment *it;
-
-	mutex_lock(&iommu_debug_attachments_lock);
-	list_for_each_entry(it, &iommu_debug_attachments, list)
-		if (it->domain == domain && it->dev == dev)
-			break;
-
-	if (&it->list == &iommu_debug_attachments) {
-		WARN(1, "Couldn't find debug attachment for domain=0x%p dev=%s",
-		     domain, dev_name(dev));
-	} else {
-		/*
-		 * Just remove debugfs entry and mark dev as NULL on
-		 * iommu_detach call. We would remove the actual
-		 * attachment entry from the list only on domain_free call.
-		 * This is to ensure we keep track of unattached domains too.
-		 */
-
-		debugfs_remove_recursive(it->dentry);
-		it->dev = NULL;
-	}
-	mutex_unlock(&iommu_debug_attachments_lock);
-}
-
-static int iommu_debug_init_tracking(void)
-{
-	int ret = 0;
-	struct iommu_debug_attachment *attach;
-
-	mutex_lock(&iommu_debug_attachments_lock);
-	debugfs_attachments_dir = debugfs_create_dir("attachments",
-						     iommu_debugfs_top);
-	if (!debugfs_attachments_dir) {
-		pr_err("Couldn't create iommu/attachments debugfs directory\n");
-		ret = -ENODEV;
-		goto out_unlock;
-	}
-
-	/* set up debugfs entries for attachments made during early boot */
-	list_for_each_entry(attach, &iommu_debug_attachments, list)
-		if (attach->dev)
-			iommu_debug_attach_add_debugfs(attach);
-
-out_unlock:
-	mutex_unlock(&iommu_debug_attachments_lock);
-	return ret;
-}
-
-static void iommu_debug_destroy_tracking(void)
-{
-	debugfs_remove_recursive(debugfs_attachments_dir);
-}
-#else
-static inline int iommu_debug_init_tracking(void) { return 0; }
-static inline void iommu_debug_destroy_tracking(void) { }
 #endif
 
 #ifdef CONFIG_IOMMU_TESTS
@@ -2045,9 +1773,6 @@
 
 static int iommu_debug_init(void)
 {
-	if (iommu_debug_init_tracking())
-		return -ENODEV;
-
 	if (iommu_debug_init_tests())
 		return -ENODEV;
 
@@ -2057,7 +1782,6 @@
 static void iommu_debug_exit(void)
 {
 	platform_driver_unregister(&iommu_debug_driver);
-	iommu_debug_destroy_tracking();
 	iommu_debug_destroy_tests();
 }
 
diff --git a/drivers/iommu/iommu-debug.h b/drivers/iommu/iommu-debug.h
index 94a97bf..91c418d 100644
--- a/drivers/iommu/iommu-debug.h
+++ b/drivers/iommu/iommu-debug.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, 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
@@ -16,8 +16,6 @@
 #ifdef CONFIG_IOMMU_DEBUG_TRACKING
 
 void iommu_debug_attach_device(struct iommu_domain *domain, struct device *dev);
-void iommu_debug_detach_device(struct iommu_domain *domain, struct device *dev);
-void iommu_debug_domain_add(struct iommu_domain *domain);
 void iommu_debug_domain_remove(struct iommu_domain *domain);
 
 #else  /* !CONFIG_IOMMU_DEBUG_TRACKING */
@@ -27,15 +25,6 @@
 {
 }
 
-static inline void iommu_debug_detach_device(struct iommu_domain *domain,
-					     struct device *dev)
-{
-}
-
-static inline void iommu_debug_domain_add(struct iommu_domain *domain)
-{
-}
-
 static inline void iommu_debug_domain_remove(struct iommu_domain *domain)
 {
 }
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 7f9d9e1..e81bb48 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1067,8 +1067,6 @@
 	/* Assume all sizes by default; the driver may override this later */
 	domain->pgsize_bitmap  = bus->iommu_ops->pgsize_bitmap;
 
-	iommu_debug_domain_add(domain);
-
 	return domain;
 }
 
@@ -1132,8 +1130,6 @@
 static void __iommu_detach_device(struct iommu_domain *domain,
 				  struct device *dev)
 {
-	iommu_debug_detach_device(domain, dev);
-
 	if (unlikely(domain->ops->detach_dev == NULL))
 		return;
 
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop100.h b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop100.h
index 8686bd5..12c8e66 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop100.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop100.h
@@ -39,7 +39,7 @@
 		.access_type = CAM_REG_TYPE_WRITE,
 		.enable = true,
 		.offset = 0x2080, /* SBM_FLAGOUTCLR0_LOW */
-		.value = TEST_IRQ_ENABLE ? 0x7 : 0x3,
+		.value = TEST_IRQ_ENABLE ? 0x6 : 0x2,
 	}
 };
 
@@ -164,7 +164,7 @@
 			.access_type = CAM_REG_TYPE_READ_WRITE,
 			.enable = true,
 			.offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */
-			.value = 0x7,
+			.value = 0x1,
 		},
 		.err_status = {
 			.access_type = CAM_REG_TYPE_READ,
@@ -191,7 +191,7 @@
 			.access_type = CAM_REG_TYPE_READ_WRITE,
 			.enable = true,
 			.offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */
-			.value = 0x7,
+			.value = 0x5,
 		},
 		.err_status = {
 			.access_type = CAM_REG_TYPE_READ,
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
index b16e37e..2dfb90a 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
@@ -267,7 +267,7 @@
 
 	of_node = pdev->dev.of_node;
 
-	rc = of_property_read_u32(of_node, "cell-index", &pdev->id);
+	rc = of_property_read_u32(of_node, "cell-index", &soc_info->index);
 	if (rc) {
 		pr_err("device %s failed to read cell-index\n", pdev->name);
 		return rc;
@@ -317,11 +317,13 @@
 		}
 	}
 
-	rc = of_property_read_u32_array(of_node, "reg-cam-base",
-		soc_info->mem_block_cam_base, soc_info->num_mem_block);
-	if (rc) {
-		pr_err("Error reading register offsets\n");
-		return rc;
+	if (soc_info->num_mem_block > 0) {
+		rc = of_property_read_u32_array(of_node, "reg-cam-base",
+			soc_info->mem_block_cam_base, soc_info->num_mem_block);
+		if (rc) {
+			pr_err("Error reading register offsets\n");
+			return rc;
+		}
 	}
 
 	rc = of_property_read_string_index(of_node, "interrupt-names", 0,
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
index 3e8226f..e556bba 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
@@ -18,6 +18,7 @@
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
+
 #include "cam_io_util.h"
 
 #define NO_SET_RATE  -1
@@ -54,7 +55,7 @@
  *                          Camera hardware driver module
  *
  * @pdev:                   Platform device pointer
- * @hw_version;             Camera device version
+ * @hw_version:             Camera device version
  * @index:                  Instance id for the camera device
  * @irq_name:               Name of the irq associated with the device
  * @irq_line:               Irq resource
@@ -76,7 +77,7 @@
  * @clk:                    Array of associated clock resources
  * @clk_rate:               Array of default clock rates
  * @src_clk_idx:            Source clock index that is rate-controllable
- * @soc_private;            Soc private data
+ * @soc_private:            Soc private data
  *
  */
 struct cam_hw_soc_info {
@@ -172,7 +173,6 @@
  */
 int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info);
 
-
 /**
  * cam_soc_util_request_platform_resource()
  *
@@ -208,7 +208,7 @@
  *                          TRUE: Enable all clocks in soc_info Now.
  *                          False: Don't enable clocks Now. Driver will
  *                                 enable independently.
- @enable_irq:           Boolean flag:
+ * @enable_irq:         Boolean flag:
  *                          TRUE: Enable IRQ in soc_info Now.
  *                          False: Don't enable IRQ Now. Driver will
  *                                 enable independently.
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 4f53850..9dda0d2 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -476,7 +476,7 @@
 	for (; idx < num_ctrls; idx++) {
 		struct v4l2_ctrl *ctrl = NULL;
 
-		if (1) {
+		if (IS_PRIV_CTRL(drv_ctrls[idx].id)) {
 			/*add private control*/
 			ctrl_cfg.def = drv_ctrls[idx].default_value;
 			ctrl_cfg.flags = 0;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 098063d..61df652 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -61,7 +61,7 @@
 struct hal_buffer_requirements *get_buff_req_buffer(
 			struct msm_vidc_inst *inst, u32 buffer_type);
 #define IS_PRIV_CTRL(idx) (\
-		(V4L2_CTRL_ID2CLASS(idx) == V4L2_CTRL_CLASS_MPEG) && \
+		(V4L2_CTRL_ID2WHICH(idx) == V4L2_CTRL_CLASS_MPEG) && \
 		V4L2_CTRL_DRIVER_PRIV(idx))
 void msm_comm_session_clean(struct msm_vidc_inst *inst);
 int msm_comm_kill_session(struct msm_vidc_inst *inst);
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index d16e3e8..077d237 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -123,6 +123,7 @@
 }
 EXPORT_SYMBOL_GPL(power_supply_changed);
 
+static int psy_register_cooler(struct device *dev, struct power_supply *psy);
 /*
  * Notify that power supply was registered after parent finished the probing.
  *
@@ -130,6 +131,8 @@
  * calling power_supply_changed() directly from power_supply_register()
  * would lead to execution of get_property() function provided by the driver
  * too early - before the probe ends.
+ * Also, registering cooling device from the probe will execute the
+ * get_property() function. So register the cooling device after the probe.
  *
  * Avoid that by waiting on parent's mutex.
  */
@@ -141,6 +144,7 @@
 	if (psy->dev.parent)
 		mutex_lock(&psy->dev.parent->mutex);
 
+	psy_register_cooler(psy->dev.parent, psy);
 	power_supply_changed(psy);
 
 	if (psy->dev.parent)
@@ -776,10 +780,6 @@
 	if (rc)
 		goto register_thermal_failed;
 
-	rc = psy_register_cooler(parent, psy);
-	if (rc)
-		goto register_cooler_failed;
-
 	rc = power_supply_create_triggers(psy);
 	if (rc)
 		goto create_triggers_failed;
@@ -803,8 +803,6 @@
 	return psy;
 
 create_triggers_failed:
-	psy_unregister_cooler(psy);
-register_cooler_failed:
 	psy_unregister_thermal(psy);
 register_thermal_failed:
 	device_del(dev);
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 217b7ca..25b2cdd 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -180,6 +180,15 @@
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
 };
 
+static struct usb_ss_ep_comp_descriptor ss_bulk_comp_desc = {
+	.bLength =		sizeof(ss_bulk_comp_desc),
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
+	/* the following 2 values can be tweaked if necessary */
+	/* .bMaxBurst =		0, */
+	/* .bmAttributes =	0, */
+};
+
 /* B.6.2  Class-specific MS Bulk IN Endpoint Descriptor */
 static struct usb_ms_endpoint_descriptor_16 ms_in_desc = {
 	/* .bLength =		DYNAMIC */
@@ -846,6 +855,7 @@
 static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct usb_descriptor_header **midi_function;
+	struct usb_descriptor_header **midi_ss_function;
 	struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS];
 	struct usb_midi_in_jack_descriptor jack_in_emb_desc[MAX_PORTS];
 	struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc[MAX_PORTS];
@@ -853,7 +863,7 @@
 	struct usb_composite_dev *cdev = c->cdev;
 	struct f_midi *midi = func_to_midi(f);
 	struct usb_string *us;
-	int status, n, jack = 1, i = 0;
+	int status, n, jack = 1, i = 0, j = 0;
 
 	midi->gadget = cdev->gadget;
 	tasklet_init(&midi->tasklet, f_midi_in_tasklet, (unsigned long) midi);
@@ -894,11 +904,20 @@
 	if (!midi->out_ep)
 		goto fail;
 
+	/* allocate temporary function list for ss */
+	midi_ss_function = kcalloc((MAX_PORTS * 4) + 11,
+				sizeof(*midi_ss_function), GFP_KERNEL);
+	if (!midi_ss_function) {
+		status = -ENOMEM;
+		goto fail;
+	}
+
 	/* allocate temporary function list */
 	midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(*midi_function),
 				GFP_KERNEL);
 	if (!midi_function) {
 		status = -ENOMEM;
+		kfree(midi_ss_function);
 		goto fail;
 	}
 
@@ -912,6 +931,12 @@
 	midi_function[i++] = (struct usb_descriptor_header *) &ac_interface_desc;
 	midi_function[i++] = (struct usb_descriptor_header *) &ac_header_desc;
 	midi_function[i++] = (struct usb_descriptor_header *) &ms_interface_desc;
+	midi_ss_function[j++] =
+			(struct usb_descriptor_header *) &ac_interface_desc;
+	midi_ss_function[j++] =
+			(struct usb_descriptor_header *) &ac_header_desc;
+	midi_ss_function[j++] =
+			(struct usb_descriptor_header *) &ms_interface_desc;
 
 	/* calculate the header's wTotalLength */
 	n = USB_DT_MS_HEADER_SIZE
@@ -920,6 +945,8 @@
 	ms_header_desc.wTotalLength = cpu_to_le16(n);
 
 	midi_function[i++] = (struct usb_descriptor_header *) &ms_header_desc;
+	midi_ss_function[j++] =
+			(struct usb_descriptor_header *) &ms_header_desc;
 
 	/* configure the external IN jacks, each linked to an embedded OUT jack */
 	for (n = 0; n < midi->in_ports; n++) {
@@ -933,6 +960,7 @@
 		in_ext->bJackID			= jack++;
 		in_ext->iJack			= 0;
 		midi_function[i++] = (struct usb_descriptor_header *) in_ext;
+		midi_ss_function[j++] = (struct usb_descriptor_header *) in_ext;
 
 		out_emb->bLength		= USB_DT_MIDI_OUT_SIZE(1);
 		out_emb->bDescriptorType	= USB_DT_CS_INTERFACE;
@@ -944,6 +972,8 @@
 		out_emb->pins[0].baSourceID	= in_ext->bJackID;
 		out_emb->iJack			= 0;
 		midi_function[i++] = (struct usb_descriptor_header *) out_emb;
+		midi_ss_function[j++] =
+				(struct usb_descriptor_header *) out_emb;
 
 		/* link it to the endpoint */
 		ms_in_desc.baAssocJackID[n] = out_emb->bJackID;
@@ -961,6 +991,7 @@
 		in_emb->bJackID			= jack++;
 		in_emb->iJack			= 0;
 		midi_function[i++] = (struct usb_descriptor_header *) in_emb;
+		midi_ss_function[j++] = (struct usb_descriptor_header *) in_emb;
 
 		out_ext->bLength =		USB_DT_MIDI_OUT_SIZE(1);
 		out_ext->bDescriptorType =	USB_DT_CS_INTERFACE;
@@ -972,6 +1003,8 @@
 		out_ext->pins[0].baSourceID =	in_emb->bJackID;
 		out_ext->pins[0].baSourcePin =	1;
 		midi_function[i++] = (struct usb_descriptor_header *) out_ext;
+		midi_ss_function[j++] =
+				(struct usb_descriptor_header *) out_ext;
 
 		/* link it to the endpoint */
 		ms_out_desc.baAssocJackID[n] = in_emb->bJackID;
@@ -991,6 +1024,16 @@
 	midi_function[i++] = (struct usb_descriptor_header *) &ms_in_desc;
 	midi_function[i++] = NULL;
 
+	midi_ss_function[j++] = (struct usb_descriptor_header *) &bulk_out_desc;
+	midi_ss_function[j++] =
+			(struct usb_descriptor_header *) &ss_bulk_comp_desc;
+	midi_ss_function[j++] = (struct usb_descriptor_header *) &ms_out_desc;
+	midi_ss_function[j++] = (struct usb_descriptor_header *) &bulk_in_desc;
+	midi_ss_function[j++] =
+			(struct usb_descriptor_header *) &ss_bulk_comp_desc;
+	midi_ss_function[j++] = (struct usb_descriptor_header *) &ms_in_desc;
+	midi_ss_function[j++] = NULL;
+
 	/*
 	 * support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
@@ -1009,13 +1052,23 @@
 			goto fail_f_midi;
 	}
 
+	if (gadget_is_superspeed(c->cdev->gadget)) {
+		bulk_in_desc.wMaxPacketSize = cpu_to_le16(1024);
+		bulk_out_desc.wMaxPacketSize = cpu_to_le16(1024);
+		f->ss_descriptors = usb_copy_descriptors(midi_ss_function);
+		if (!f->ss_descriptors)
+			goto fail_f_midi;
+	}
+
 	kfree(midi_function);
+	kfree(midi_ss_function);
 
 	return 0;
 
 fail_f_midi:
 	kfree(midi_function);
 	usb_free_descriptors(f->hs_descriptors);
+	kfree(midi_ss_function);
 fail:
 	f_midi_unregister_card(midi);
 fail_register:
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 6012da3..918f659 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -435,8 +435,8 @@
 #define PORT_L1_TIMEOUT(p)(((p) & 0xff) << 2)
 #define PORT_BESLD(p)(((p) & 0xf) << 10)
 
-/* use 512 microseconds as USB2 LPM L1 default timeout. */
-#define XHCI_L1_TIMEOUT		512
+/* use 128 microseconds as USB2 LPM L1 default timeout. */
+#define XHCI_L1_TIMEOUT		128
 
 /* Set default HIRD/BESL value to 4 (350/400us) for USB2 L1 LPM resume latency.
  * Safe to use with mixed HIRD and BESL systems (host and device) and is used
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index d3b4cf4..9523c60 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -91,12 +91,6 @@
  * @base:	pointer to the timer base (per cpu and per clock)
  * @state:	state information (See bit values above)
  * @is_rel:	Set if the timer was armed relative
- * @start_pid:  timer statistics field to store the pid of the task which
- *		started the timer
- * @start_site:	timer statistics field to store the site where the timer
- *		was started
- * @start_comm: timer statistics field to store the name of the process which
- *		started the timer
  *
  * The hrtimer structure must be initialized by hrtimer_init()
  */
@@ -107,11 +101,6 @@
 	struct hrtimer_clock_base	*base;
 	u8				state;
 	u8				is_rel;
-#ifdef CONFIG_TIMER_STATS
-	int				start_pid;
-	void				*start_site;
-	char				start_comm[16];
-#endif
 };
 
 /**
diff --git a/include/linux/timer.h b/include/linux/timer.h
index 3e354fd..56dde53 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -20,11 +20,6 @@
 	unsigned long		data;
 	u32			flags;
 
-#ifdef CONFIG_TIMER_STATS
-	int			start_pid;
-	void			*start_site;
-	char			start_comm[16];
-#endif
 #ifdef CONFIG_LOCKDEP
 	struct lockdep_map	lockdep_map;
 #endif
@@ -200,46 +195,6 @@
 /* To be used from cpusets, only */
 extern void timer_quiesce_cpu(void *cpup);
 
-/*
- * Timer-statistics info:
- */
-#ifdef CONFIG_TIMER_STATS
-
-extern int timer_stats_active;
-
-extern void init_timer_stats(void);
-
-extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
-				     void *timerf, char *comm, u32 flags);
-
-extern void __timer_stats_timer_set_start_info(struct timer_list *timer,
-					       void *addr);
-
-static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
-{
-	if (likely(!timer_stats_active))
-		return;
-	__timer_stats_timer_set_start_info(timer, __builtin_return_address(0));
-}
-
-static inline void timer_stats_timer_clear_start_info(struct timer_list *timer)
-{
-	timer->start_site = NULL;
-}
-#else
-static inline void init_timer_stats(void)
-{
-}
-
-static inline void timer_stats_timer_set_start_info(struct timer_list *timer)
-{
-}
-
-static inline void timer_stats_timer_clear_start_info(struct timer_list *timer)
-{
-}
-#endif
-
 extern void add_timer(struct timer_list *timer);
 
 extern int try_to_del_timer_sync(struct timer_list *timer);
diff --git a/include/uapi/media/Kbuild b/include/uapi/media/Kbuild
index 478f7fe..98844ac 100644
--- a/include/uapi/media/Kbuild
+++ b/include/uapi/media/Kbuild
@@ -1,5 +1,6 @@
 header-y += cam_cpas.h
 header-y += cam_defs.h
+header-y += cam_icp.h
 header-y += cam_isp.h
 header-y += cam_isp_vfe.h
 header-y += cam_isp_ife.h
diff --git a/include/uapi/media/cam_defs.h b/include/uapi/media/cam_defs.h
index cf56211..a4557d1 100644
--- a/include/uapi/media/cam_defs.h
+++ b/include/uapi/media/cam_defs.h
@@ -121,9 +121,6 @@
 #define CAM_FORMAT_Y_ONLY                       45
 #define CAM_FORMAT_MAX                          46
 
-
-/* camera packet */
-
 /* camera rotaion */
 #define CAM_ROTATE_CW_0_DEGREE                  0
 #define CAM_ROTATE_CW_90_DEGREE                 1
@@ -343,7 +340,6 @@
 
 };
 
-/* Release Device */
 /**
  * struct cam_release_dev_cmd - Control payload for release devices
  *
@@ -355,7 +351,6 @@
 	int32_t                 dev_handle;
 };
 
-/* Start/Stop device */
 /**
  * struct cam_start_stop_dev_cmd - Control payload for start/stop device
  *
@@ -368,7 +363,6 @@
 	int32_t                 dev_handle;
 };
 
-/* Configure Device */
 /**
  * struct cam_config_dev_cmd - Command payload for configure device
  *
@@ -386,7 +380,6 @@
 	uint64_t                packet_handle;
 };
 
-/* Query Device Caps */
 /**
  * struct cam_query_cap_cmd - Payload for query device capability
  *
@@ -401,7 +394,6 @@
 	uint64_t        caps_handle;
 };
 
-/* Acquire Device */
 /**
  * struct cam_acquire_dev_cmd - Control payload for acquire devices
  *
diff --git a/include/uapi/media/cam_icp.h b/include/uapi/media/cam_icp.h
new file mode 100644
index 0000000..9351d2d
--- /dev/null
+++ b/include/uapi/media/cam_icp.h
@@ -0,0 +1,155 @@
+#ifndef __UAPI_CAM_ICP_H__
+#define __UAPI_CAM_ICP_H__
+
+#include "cam_defs.h"
+
+/* icp, ipe, bps, cdm(ipe/bps) are used in querycap */
+#define CAM_ICP_DEV_TYPE_A5      1
+#define CAM_ICP_DEV_TYPE_IPE     2
+#define CAM_ICP_DEV_TYPE_BPS     3
+#define CAM_ICP_DEV_TYPE_IPE_CDM 4
+#define CAM_ICP_DEV_TYPE_BPS_CDM 5
+#define CAM_ICP_DEV_TYPE_MAX     5
+
+/* definitions needed for icp aquire device */
+#define CAM_ICP_RES_TYPE_BPS        1
+#define CAM_ICP_RES_TYPE_IPE_RT     2
+#define CAM_ICP_RES_TYPE_IPE        3
+#define CAM_ICP_RES_TYPE_MAX        4
+
+/* packet opcode types */
+#define CAM_ICP_OPCODE_IPE_UPDATE 0
+#define CAM_ICP_OPCODE_BPS_UPDATE 1
+
+/* IPE input port resource type */
+#define CAM_ICP_IPE_INPUT_IMAGE_FULL            0x0
+#define CAM_ICP_IPE_INPUT_IMAGE_DS4             0x1
+#define CAM_ICP_IPE_INPUT_IMAGE_DS16            0x2
+#define CAM_ICP_IPE_INPUT_IMAGE_DS64            0x3
+#define CAM_ICP_IPE_INPUT_IMAGE_FULL_REF        0x4
+#define CAM_ICP_IPE_INPUT_IMAGE_DS4_REF         0x5
+#define CAM_ICP_IPE_INPUT_IMAGE_DS16_REF        0x6
+#define CAM_ICP_IPE_INPUT_IMAGE_DS64_REF        0x7
+
+/* IPE output port resource type */
+#define CAM_ICP_IPE_OUTPUT_IMAGE_DISPLAY        0x8
+#define CAM_ICP_IPE_OUTPUT_IMAGE_VIDEO          0x9
+#define CAM_ICP_IPE_OUTPUT_IMAGE_FULL_REF       0xA
+#define CAM_ICP_IPE_OUTPUT_IMAGE_DS4_REF        0xB
+#define CAM_ICP_IPE_OUTPUT_IMAGE_DS16_REF       0xC
+#define CAM_ICP_IPE_OUTPUT_IMAGE_DS64_REF       0xD
+
+#define CAM_ICP_IPE_IMAGE_MAX                   0xE
+
+/* BPS input port resource type */
+#define CAM_ICP_BPS_INPUT_IMAGE                 0x0
+
+/* BPS output port resource type */
+#define CAM_ICP_BPS_OUTPUT_IMAGE_FULL           0x1
+#define CAM_ICP_BPS_OUTPUT_IMAGE_DS4            0x2
+#define CAM_ICP_BPS_OUTPUT_IMAGE_DS16           0x3
+#define CAM_ICP_BPS_OUTPUT_IMAGE_DS64           0x4
+#define CAM_ICP_BPS_OUTPUT_IMAGE_STATS_BG       0x5
+#define CAM_ICP_BPS_OUTPUT_IMAGE_STATS_BHIST    0x6
+#define CAM_ICP_BPS_OUTPUT_IMAGE_REG1           0x7
+#define CAM_ICP_BPS_OUTPUT_IMAGE_REG2           0x8
+
+#define CAM_ICP_BPS_IO_IMAGES_MAX               0x9
+
+/**
+ * struct cam_icp_dev_ver - Device information for particular hw type
+ *
+ * This is used to get device version info of
+ * ICP, IPE, BPS and CDM related IPE and BPS from firmware
+ * and use this info in CAM_QUERY_CAP IOCTL
+ *
+ * @dev_type: hardware type for the cap info(icp, ipe, bps, cdm(ipe/bps))
+ * @reserved: reserved field
+ * @hw_ver: major, minor and incr values of a device version
+ */
+struct cam_icp_dev_ver {
+	uint32_t dev_type;
+	uint32_t reserved;
+	struct cam_hw_version hw_ver;
+};
+
+/**
+ * struct cam_icp_ver - ICP version info
+ *
+ * This strcuture is used for fw and api version
+ * this is used to get firmware version and api version from firmware
+ * and use this info in CAM_QUERY_CAP IOCTL
+ *
+ * @major: FW version major
+ * @minor: FW version minor
+ * @revision: FW version increment
+ */
+struct cam_icp_ver {
+	uint32_t major;
+	uint32_t minor;
+	uint32_t revision;
+	uint32_t reserved;
+};
+
+/**
+ * struct cam_icp_query_cap_cmd - ICP query device capability payload
+ *
+ * @dev_iommu_handle: icp iommu handles for secure/non secure modes
+ * @cdm_iommu_handle: iommu handles for secure/non secure modes
+ * @fw_version: firmware version info
+ * @api_version: api version info
+ * @num_ipe: number of ipes
+ * @num_bps: number of bps
+ * @dev_ver: returned device capability array
+ */
+struct cam_icp_query_cap_cmd {
+	struct cam_iommu_handle dev_iommu_handle;
+	struct cam_iommu_handle cdm_iommu_handle;
+	struct cam_icp_ver fw_version;
+	struct cam_icp_ver api_version;
+	uint32_t num_ipe;
+	uint32_t num_bps;
+	struct cam_icp_dev_ver dev_ver[CAM_ICP_DEV_TYPE_MAX];
+};
+
+/**
+ * struct cam_icp_res_info - ICP output resource info
+ *
+ * @format: format of the resource
+ * @width:  width in pixels
+ * @height: height in lines
+ * @fps:  fps
+ */
+struct cam_icp_res_info {
+	uint32_t format;
+	uint32_t width;
+	uint32_t height;
+	uint32_t fps;
+};
+
+/**
+ * struct cam_icp_acquire_dev_info - An ICP device info
+ *
+ * @scratch_mem_size: Output param - size of scratch memory
+ * @dev_type: device type (IPE_RT/IPE_NON_RT/BPS)
+ * @io_config_cmd_size: size of IO config command
+ * @io_config_cmd_handle: IO config command for each acquire
+ * @secure_mode: camera mode (secure/non secure)
+ * @chain_info: chaining info of FW device handles
+ * @in_res: resource info used for clock and bandwidth calculation
+ * @num_out_res: number of output resources
+ * @out_res: output resource
+ */
+struct cam_icp_acquire_dev_info {
+	uint32_t scratch_mem_size;
+	uint32_t dev_type;
+	uint32_t io_config_cmd_size;
+	int32_t  io_config_cmd_handle;
+	uint32_t secure_mode;
+	int32_t chain_info;
+	struct cam_icp_res_info in_res;
+	uint32_t num_out_res;
+	struct cam_icp_res_info out_res[1];
+} __attribute__((__packed__));
+
+#endif /* __UAPI_CAM_ICP_H__ */
diff --git a/include/uapi/media/cam_sensor.h b/include/uapi/media/cam_sensor.h
index bb4805c..83f1a02 100644
--- a/include/uapi/media/cam_sensor.h
+++ b/include/uapi/media/cam_sensor.h
@@ -6,7 +6,7 @@
 #include <media/cam_defs.h>
 
 #define CAM_SENSOR_PROBE_CMD   (CAM_COMMON_OPCODE_MAX + 1)
-
+#define CAM_SENSOR_MAX_LED_TRIGGERS 3
 /**
  * struct cam_sensor_query_cap - capabilities info for sensor
  *
@@ -42,6 +42,7 @@
  * @version          :  CSIphy version
  * @clk lane         :  Of the 5 lanes, informs lane configured
  *                      as clock lane
+ * @reserved
  */
 struct cam_csiphy_query_cap {
 	uint32_t            slot_info;
@@ -54,6 +55,7 @@
  * struct cam_actuator_query_cap - capabilities info for actuator
  *
  * @slot_info        :  Indicates about the slotId or cell Index
+ * @reserved
  */
 struct cam_actuator_query_cap {
 	uint32_t            slot_info;
@@ -85,6 +87,7 @@
  * @data_mask       :   Data mask if only few bits are valid
  * @camera_id       :   Indicates the slot to which camera
  *                      needs to be probed
+ * @reserved
  */
 struct cam_cmd_probe {
 	uint8_t     data_type;
@@ -99,9 +102,10 @@
 } __attribute__((packed));
 
 /**
- * struct cam_power_settings - Contains sensor slave info
+ * struct cam_power_settings - Contains sensor power setting info
  *
  * @power_seq_type  :   Type of power sequence
+ * @reserved
  * @config_val_low  :   Lower 32 bit value configuration value
  * @config_val_high :   Higher 32 bit value configuration value
  *
@@ -117,8 +121,9 @@
  * struct cam_cmd_power - Explains about the power settings
  *
  * @count           :    Number of power settings follows
+ * @reserved
  * @cmd_type        :    Explains type of command
- *
+ * @power_settings  :    Contains power setting info
  */
 struct cam_cmd_power {
 	uint16_t                    count;
@@ -135,7 +140,7 @@
  * @ cmd_type        :   Command buffer type
  * @ data_type       :   I2C data type
  * @ addr_type       :   I2C address type
- *
+ * @ reserved
  */
 struct i2c_rdwr_header {
 	uint16_t    count;
@@ -160,7 +165,8 @@
 
 /**
  * struct cam_cmd_i2c_random_wr - I2C random write command
- *
+ * @ header            :   header of READ/WRITE I2C command
+ * @ random_wr_payload :   payload for I2C random write
  */
 struct cam_cmd_i2c_random_wr {
 	struct i2c_rdwr_header       header;
@@ -170,7 +176,7 @@
 /**
  * struct cam_cmd_read - I2C read command
  * @ reg_data        :   Register data
- *
+ * @ reserved
  */
 struct cam_cmd_read {
 	uint32_t                reg_data;
@@ -179,8 +185,9 @@
 
 /**
  * struct cam_cmd_i2c_continuous_wr - I2C continuous write command
+ * @ header          :   header of READ/WRITE I2C command
  * @ reg_addr        :   Register address
- *
+ * @ data_read       :   I2C read command
  */
 struct cam_cmd_i2c_continuous_wr {
 	struct i2c_rdwr_header  header;
@@ -190,7 +197,8 @@
 
 /**
  * struct cam_cmd_i2c_random_rd - I2C random read command
- *
+ * @ header          :   header of READ/WRITE I2C command
+ * @ data_read       :   I2C read command
  */
 struct cam_cmd_i2c_random_rd {
 	struct i2c_rdwr_header  header;
@@ -199,6 +207,7 @@
 
 /**
  * struct cam_cmd_i2c_continuous_rd - I2C continuous continuous read command
+ * @ header          :   header of READ/WRITE I2C command
  * @ reg_addr        :   Register address
  *
  */
@@ -214,6 +223,7 @@
  * @op_code         :   Opcode
  * @cmd_type        :   Explains type of command
  * @timeout         :   Timeout for retries
+ * @reserved
  * @reg_addr        :   Register Address
  * @reg_data        :   Register data
  * @data_mask       :   Data mask if only few bits are valid
@@ -237,7 +247,7 @@
  * struct cam_cmd_unconditional_wait - Un-conditional wait command
  * @delay           :   Delay
  * @op_code         :   Opcode
- *
+ * @cmd_type        :   Explains type of command
  */
 struct cam_cmd_unconditional_wait {
 	int16_t     delay;
@@ -252,6 +262,7 @@
  * @csiphy_3phase :  Total number of lanes
  * @combo_mode    :  Info regarding combo_mode is enable / disable
  * @lane_cnt      :  Total number of lanes
+ * @reserved
  * @3phase        :  Details whether 3Phase / 2Phase operation
  * @settle_time   :  Settling time in ms
  * @data_rate     :  Data rate
@@ -272,6 +283,7 @@
  * cam_csiphy_acquire_dev_info : Information needed for
  *                        csiphy at the time of acquire
  * @combo_mode     :    Indicates the device mode of operation
+ * @reserved
  *
  */
 struct cam_csiphy_acquire_dev_info {
@@ -284,6 +296,7 @@
  * @device_handle  :    Updates device handle
  * @session_handle :    Session handle for acquiring device
  * @handle_type    :    Resource handle type
+ * @reserved
  * @info_handle    :    Handle to additional info
  *                      needed for sensor sub modules
  *
@@ -301,6 +314,7 @@
  * @session_handle :    Session handle for acquiring device
  * @device_handle  :    Updates device handle
  * @handle_type    :    Resource handle type
+ * @reserved
  * @info_handle    :    Information Needed at the time of streamOn
  *
  */
@@ -312,4 +326,92 @@
 	uint64_t    info_handle;
 } __attribute__((packed));
 
+/**
+ * struct cam_flash_init : Init command for the flash
+ * @flash_type  :    flash hw type
+ * @reserved
+ * @cmd_type    :    command buffer type
+ */
+struct cam_flash_init {
+	uint8_t     flash_type;
+	uint16_t    reserved;
+	uint8_t     cmd_type;
+} __attribute__((packed));
+
+/**
+ * struct cam_flash_set_rer : RedEyeReduction command buffer
+ *
+ * @count             :   Number of flash leds
+ * @opcode            :   Command buffer opcode
+ *			CAM_FLASH_FIRE_RER
+ * @cmd_type          :   command buffer operation type
+ * @num_iteration     :   Number of led turn on/off sequence
+ * @reserved
+ * @led_on_delay_ms   :   flash led turn on time in ms
+ * @led_off_delay_ms  :   flash led turn off time in ms
+ * @led_current_ma    :   flash led current in ma
+ *
+ */
+struct cam_flash_set_rer {
+	uint16_t    count;
+	uint8_t     opcode;
+	uint8_t     cmd_type;
+	uint16_t    num_iteration;
+	uint16_t    reserved;
+	uint32_t    led_on_delay_ms;
+	uint32_t    led_off_delay_ms;
+	uint32_t    led_current_ma[CAM_SENSOR_MAX_LED_TRIGGERS];
+} __attribute__((packed));
+
+/**
+ * struct cam_flash_set_on_off : led turn on/off command buffer
+ *
+ * @count              :   Number of Flash leds
+ * @opcode             :   command buffer opcodes
+ *			CAM_FLASH_FIRE_LOW
+ *			CAM_FLASH_FIRE_HIGH
+ *			CAM_FLASH_OFF
+ * @cmd_type           :   command buffer operation type
+ * @led_current_ma     :   flash led current in ma
+ *
+ */
+struct cam_flash_set_on_off {
+	uint16_t    count;
+	uint8_t     opcode;
+	uint8_t     cmd_type;
+	uint32_t    led_current_ma[CAM_SENSOR_MAX_LED_TRIGGERS];
+} __attribute__((packed));
+
+/**
+ * struct cam_flash_query_curr : query current command buffer
+ *
+ * @reserved
+ * @opcode            :   command buffer opcode
+ * @cmd_type          :   command buffer operation type
+ * @query_current_ma  :   battery current in ma
+ *
+ */
+struct cam_flash_query_curr {
+	uint16_t    reserved;
+	uint8_t     opcode;
+	uint8_t     cmd_type;
+	uint32_t    query_current_ma;
+} __attribute__ ((packed));
+
+/**
+ * struct cam_flash_query_cap  :  capabilities info for flash
+ *
+ * @slot_info           :  Indicates about the slotId or cell Index
+ * @max_current_flash   :  max supported current for flash
+ * @max_duration_flash  :  max flash turn on duration
+ * @max_current_torch   :  max supported current for torch
+ *
+ */
+struct cam_flash_query_cap_info {
+	uint32_t    slot_info;
+	uint32_t    max_current_flash[CAM_SENSOR_MAX_LED_TRIGGERS];
+	uint32_t    max_duration_flash[CAM_SENSOR_MAX_LED_TRIGGERS];
+	uint32_t    max_current_torch[CAM_SENSOR_MAX_LED_TRIGGERS];
+} __attribute__ ((packed));
+
 #endif
diff --git a/kernel/kthread.c b/kernel/kthread.c
index c2c911a..b65854c 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -854,7 +854,6 @@
 
 	list_add(&work->node, &worker->delayed_work_list);
 	work->worker = worker;
-	timer_stats_timer_set_start_info(&dwork->timer);
 	timer->expires = jiffies + delay;
 	add_timer(timer);
 }
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index 5819ca0..b9b881eb 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -9,7 +9,6 @@
 endif
 obj-$(CONFIG_GENERIC_SCHED_CLOCK)		+= sched_clock.o
 obj-$(CONFIG_TICK_ONESHOT)			+= tick-oneshot.o tick-sched.o
-obj-$(CONFIG_TIMER_STATS)			+= timer_stats.o
 obj-$(CONFIG_DEBUG_FS)				+= timekeeping_debug.o
 obj-$(CONFIG_TEST_UDELAY)			+= test_udelay.o
 
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index b1c7852..9792763 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -767,34 +767,6 @@
 	clock_was_set_delayed();
 }
 
-static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer)
-{
-#ifdef CONFIG_TIMER_STATS
-	if (timer->start_site)
-		return;
-	timer->start_site = __builtin_return_address(0);
-	memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
-	timer->start_pid = current->pid;
-#endif
-}
-
-static inline void timer_stats_hrtimer_clear_start_info(struct hrtimer *timer)
-{
-#ifdef CONFIG_TIMER_STATS
-	timer->start_site = NULL;
-#endif
-}
-
-static inline void timer_stats_account_hrtimer(struct hrtimer *timer)
-{
-#ifdef CONFIG_TIMER_STATS
-	if (likely(!timer_stats_active))
-		return;
-	timer_stats_update_stats(timer, timer->start_pid, timer->start_site,
-				 timer->function, timer->start_comm, 0);
-#endif
-}
-
 /*
  * Counterpart to lock_hrtimer_base above:
  */
@@ -938,7 +910,6 @@
 		 * rare case and less expensive than a smp call.
 		 */
 		debug_deactivate(timer);
-		timer_stats_hrtimer_clear_start_info(timer);
 		reprogram = base->cpu_base == this_cpu_ptr(&hrtimer_bases);
 
 		if (!restart)
@@ -997,8 +968,6 @@
 	/* Switch the timer base, if necessary: */
 	new_base = switch_hrtimer_base(timer, base, mode & HRTIMER_MODE_PINNED);
 
-	timer_stats_hrtimer_set_start_info(timer);
-
 	/* Update pinned state */
 	timer->state &= ~HRTIMER_STATE_PINNED;
 	timer->state |= (!!(mode & HRTIMER_MODE_PINNED)) << HRTIMER_PINNED_SHIFT;
@@ -1139,12 +1108,6 @@
 	base = hrtimer_clockid_to_base(clock_id);
 	timer->base = &cpu_base->clock_base[base];
 	timerqueue_init(&timer->node);
-
-#ifdef CONFIG_TIMER_STATS
-	timer->start_site = NULL;
-	timer->start_pid = -1;
-	memset(timer->start_comm, 0, TASK_COMM_LEN);
-#endif
 }
 
 /**
@@ -1228,7 +1191,6 @@
 	raw_write_seqcount_barrier(&cpu_base->seq);
 
 	__remove_hrtimer(timer, base, HRTIMER_STATE_INACTIVE, 0);
-	timer_stats_account_hrtimer(timer);
 	fn = timer->function;
 
 	/*
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 5463c3b..adede73 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -575,38 +575,6 @@
 	trigger_dyntick_cpu(base, timer);
 }
 
-#ifdef CONFIG_TIMER_STATS
-void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr)
-{
-	if (timer->start_site)
-		return;
-
-	timer->start_site = addr;
-	memcpy(timer->start_comm, current->comm, TASK_COMM_LEN);
-	timer->start_pid = current->pid;
-}
-
-static void timer_stats_account_timer(struct timer_list *timer)
-{
-	void *site;
-
-	/*
-	 * start_site can be concurrently reset by
-	 * timer_stats_timer_clear_start_info()
-	 */
-	site = READ_ONCE(timer->start_site);
-	if (likely(!site))
-		return;
-
-	timer_stats_update_stats(timer, timer->start_pid, site,
-				 timer->function, timer->start_comm,
-				 timer->flags);
-}
-
-#else
-static void timer_stats_account_timer(struct timer_list *timer) {}
-#endif
-
 #ifdef CONFIG_DEBUG_OBJECTS_TIMERS
 
 static struct debug_obj_descr timer_debug_descr;
@@ -793,11 +761,6 @@
 {
 	timer->entry.pprev = NULL;
 	timer->flags = flags | raw_smp_processor_id();
-#ifdef CONFIG_TIMER_STATS
-	timer->start_site = NULL;
-	timer->start_pid = -1;
-	memset(timer->start_comm, 0, TASK_COMM_LEN);
-#endif
 	lockdep_init_map(&timer->lockdep_map, name, key, 0);
 }
 
@@ -1011,8 +974,6 @@
 		base = lock_timer_base(timer, &flags);
 	}
 
-	timer_stats_timer_set_start_info(timer);
-
 	ret = detach_if_pending(timer, base, false);
 	if (!ret && pending_only)
 		goto out_unlock;
@@ -1140,7 +1101,6 @@
 	struct timer_base *new_base, *base;
 	unsigned long flags;
 
-	timer_stats_timer_set_start_info(timer);
 	BUG_ON(timer_pending(timer) || !timer->function);
 
 	new_base = get_timer_cpu_base(timer->flags, cpu);
@@ -1186,7 +1146,6 @@
 
 	debug_assert_init(timer);
 
-	timer_stats_timer_clear_start_info(timer);
 	if (timer_pending(timer)) {
 		base = lock_timer_base(timer, &flags);
 		ret = detach_if_pending(timer, base, true);
@@ -1214,10 +1173,9 @@
 
 	base = lock_timer_base(timer, &flags);
 
-	if (base->running_timer != timer) {
-		timer_stats_timer_clear_start_info(timer);
+	if (base->running_timer != timer)
 		ret = detach_if_pending(timer, base, true);
-	}
+
 	spin_unlock_irqrestore(&base->lock, flags);
 
 	return ret;
@@ -1341,7 +1299,6 @@
 		unsigned long data;
 
 		timer = hlist_entry(head->first, struct timer_list, entry);
-		timer_stats_account_timer(timer);
 
 		base->running_timer = timer;
 		detach_timer(timer, true);
@@ -1916,7 +1873,6 @@
 void __init init_timers(void)
 {
 	init_timer_cpus();
-	init_timer_stats();
 	open_softirq(TIMER_SOFTIRQ, run_timer_softirq);
 }
 
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index ba7d8b2..83aa1f8 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -62,21 +62,11 @@
 print_timer(struct seq_file *m, struct hrtimer *taddr, struct hrtimer *timer,
 	    int idx, u64 now)
 {
-#ifdef CONFIG_TIMER_STATS
-	char tmp[TASK_COMM_LEN + 1];
-#endif
 	SEQ_printf(m, " #%d: ", idx);
 	print_name_offset(m, taddr);
 	SEQ_printf(m, ", ");
 	print_name_offset(m, timer->function);
 	SEQ_printf(m, ", S:%02x", timer->state);
-#ifdef CONFIG_TIMER_STATS
-	SEQ_printf(m, ", ");
-	print_name_offset(m, timer->start_site);
-	memcpy(tmp, timer->start_comm, TASK_COMM_LEN);
-	tmp[TASK_COMM_LEN] = 0;
-	SEQ_printf(m, ", %s/%d", tmp, timer->start_pid);
-#endif
 	SEQ_printf(m, "\n");
 	SEQ_printf(m, " # expires at %Lu-%Lu nsecs [in %Ld to %Ld nsecs]\n",
 		(unsigned long long)ktime_to_ns(hrtimer_get_softexpires(timer)),
diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c
deleted file mode 100644
index 087204c..0000000
--- a/kernel/time/timer_stats.c
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- * kernel/time/timer_stats.c
- *
- * Collect timer usage statistics.
- *
- * Copyright(C) 2006, Red Hat, Inc., Ingo Molnar
- * Copyright(C) 2006 Timesys Corp., Thomas Gleixner <tglx@timesys.com>
- *
- * timer_stats is based on timer_top, a similar functionality which was part of
- * Con Kolivas dyntick patch set. It was developed by Daniel Petrini at the
- * Instituto Nokia de Tecnologia - INdT - Manaus. timer_top's design was based
- * on dynamic allocation of the statistics entries and linear search based
- * lookup combined with a global lock, rather than the static array, hash
- * and per-CPU locking which is used by timer_stats. It was written for the
- * pre hrtimer kernel code and therefore did not take hrtimers into account.
- * Nevertheless it provided the base for the timer_stats implementation and
- * was a helpful source of inspiration. Kudos to Daniel and the Nokia folks
- * for this effort.
- *
- * timer_top.c is
- *	Copyright (C) 2005 Instituto Nokia de Tecnologia - INdT - Manaus
- *	Written by Daniel Petrini <d.pensator@gmail.com>
- *	timer_top.c was released under the GNU General Public License version 2
- *
- * We export the addresses and counting of timer functions being called,
- * the pid and cmdline from the owner process if applicable.
- *
- * Start/stop data collection:
- * # echo [1|0] >/proc/timer_stats
- *
- * Display the information collected so far:
- * # cat /proc/timer_stats
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/proc_fs.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/sched.h>
-#include <linux/seq_file.h>
-#include <linux/kallsyms.h>
-
-#include <asm/uaccess.h>
-
-/*
- * This is our basic unit of interest: a timer expiry event identified
- * by the timer, its start/expire functions and the PID of the task that
- * started the timer. We count the number of times an event happens:
- */
-struct entry {
-	/*
-	 * Hash list:
-	 */
-	struct entry		*next;
-
-	/*
-	 * Hash keys:
-	 */
-	void			*timer;
-	void			*start_func;
-	void			*expire_func;
-	pid_t			pid;
-
-	/*
-	 * Number of timeout events:
-	 */
-	unsigned long		count;
-	u32			flags;
-
-	/*
-	 * We save the command-line string to preserve
-	 * this information past task exit:
-	 */
-	char			comm[TASK_COMM_LEN + 1];
-
-} ____cacheline_aligned_in_smp;
-
-/*
- * Spinlock protecting the tables - not taken during lookup:
- */
-static DEFINE_RAW_SPINLOCK(table_lock);
-
-/*
- * Per-CPU lookup locks for fast hash lookup:
- */
-static DEFINE_PER_CPU(raw_spinlock_t, tstats_lookup_lock);
-
-/*
- * Mutex to serialize state changes with show-stats activities:
- */
-static DEFINE_MUTEX(show_mutex);
-
-/*
- * Collection status, active/inactive:
- */
-int __read_mostly timer_stats_active;
-
-/*
- * Beginning/end timestamps of measurement:
- */
-static ktime_t time_start, time_stop;
-
-/*
- * tstat entry structs only get allocated while collection is
- * active and never freed during that time - this simplifies
- * things quite a bit.
- *
- * They get freed when a new collection period is started.
- */
-#define MAX_ENTRIES_BITS	10
-#define MAX_ENTRIES		(1UL << MAX_ENTRIES_BITS)
-
-static unsigned long nr_entries;
-static struct entry entries[MAX_ENTRIES];
-
-static atomic_t overflow_count;
-
-/*
- * The entries are in a hash-table, for fast lookup:
- */
-#define TSTAT_HASH_BITS		(MAX_ENTRIES_BITS - 1)
-#define TSTAT_HASH_SIZE		(1UL << TSTAT_HASH_BITS)
-#define TSTAT_HASH_MASK		(TSTAT_HASH_SIZE - 1)
-
-#define __tstat_hashfn(entry)						\
-	(((unsigned long)(entry)->timer       ^				\
-	  (unsigned long)(entry)->start_func  ^				\
-	  (unsigned long)(entry)->expire_func ^				\
-	  (unsigned long)(entry)->pid		) & TSTAT_HASH_MASK)
-
-#define tstat_hashentry(entry)	(tstat_hash_table + __tstat_hashfn(entry))
-
-static struct entry *tstat_hash_table[TSTAT_HASH_SIZE] __read_mostly;
-
-static void reset_entries(void)
-{
-	nr_entries = 0;
-	memset(entries, 0, sizeof(entries));
-	memset(tstat_hash_table, 0, sizeof(tstat_hash_table));
-	atomic_set(&overflow_count, 0);
-}
-
-static struct entry *alloc_entry(void)
-{
-	if (nr_entries >= MAX_ENTRIES)
-		return NULL;
-
-	return entries + nr_entries++;
-}
-
-static int match_entries(struct entry *entry1, struct entry *entry2)
-{
-	return entry1->timer       == entry2->timer	  &&
-	       entry1->start_func  == entry2->start_func  &&
-	       entry1->expire_func == entry2->expire_func &&
-	       entry1->pid	   == entry2->pid;
-}
-
-/*
- * Look up whether an entry matching this item is present
- * in the hash already. Must be called with irqs off and the
- * lookup lock held:
- */
-static struct entry *tstat_lookup(struct entry *entry, char *comm)
-{
-	struct entry **head, *curr, *prev;
-
-	head = tstat_hashentry(entry);
-	curr = *head;
-
-	/*
-	 * The fastpath is when the entry is already hashed,
-	 * we do this with the lookup lock held, but with the
-	 * table lock not held:
-	 */
-	while (curr) {
-		if (match_entries(curr, entry))
-			return curr;
-
-		curr = curr->next;
-	}
-	/*
-	 * Slowpath: allocate, set up and link a new hash entry:
-	 */
-	prev = NULL;
-	curr = *head;
-
-	raw_spin_lock(&table_lock);
-	/*
-	 * Make sure we have not raced with another CPU:
-	 */
-	while (curr) {
-		if (match_entries(curr, entry))
-			goto out_unlock;
-
-		prev = curr;
-		curr = curr->next;
-	}
-
-	curr = alloc_entry();
-	if (curr) {
-		*curr = *entry;
-		curr->count = 0;
-		curr->next = NULL;
-		memcpy(curr->comm, comm, TASK_COMM_LEN);
-
-		smp_mb(); /* Ensure that curr is initialized before insert */
-
-		if (prev)
-			prev->next = curr;
-		else
-			*head = curr;
-	}
- out_unlock:
-	raw_spin_unlock(&table_lock);
-
-	return curr;
-}
-
-/**
- * timer_stats_update_stats - Update the statistics for a timer.
- * @timer:	pointer to either a timer_list or a hrtimer
- * @pid:	the pid of the task which set up the timer
- * @startf:	pointer to the function which did the timer setup
- * @timerf:	pointer to the timer callback function of the timer
- * @comm:	name of the process which set up the timer
- * @tflags:	The flags field of the timer
- *
- * When the timer is already registered, then the event counter is
- * incremented. Otherwise the timer is registered in a free slot.
- */
-void timer_stats_update_stats(void *timer, pid_t pid, void *startf,
-			      void *timerf, char *comm, u32 tflags)
-{
-	/*
-	 * It doesn't matter which lock we take:
-	 */
-	raw_spinlock_t *lock;
-	struct entry *entry, input;
-	unsigned long flags;
-
-	if (likely(!timer_stats_active))
-		return;
-
-	lock = &per_cpu(tstats_lookup_lock, raw_smp_processor_id());
-
-	input.timer = timer;
-	input.start_func = startf;
-	input.expire_func = timerf;
-	input.pid = pid;
-	input.flags = tflags;
-
-	raw_spin_lock_irqsave(lock, flags);
-	if (!timer_stats_active)
-		goto out_unlock;
-
-	entry = tstat_lookup(&input, comm);
-	if (likely(entry))
-		entry->count++;
-	else
-		atomic_inc(&overflow_count);
-
- out_unlock:
-	raw_spin_unlock_irqrestore(lock, flags);
-}
-
-static void print_name_offset(struct seq_file *m, unsigned long addr)
-{
-	char symname[KSYM_NAME_LEN];
-
-	if (lookup_symbol_name(addr, symname) < 0)
-		seq_printf(m, "<%p>", (void *)addr);
-	else
-		seq_printf(m, "%s", symname);
-}
-
-static int tstats_show(struct seq_file *m, void *v)
-{
-	struct timespec64 period;
-	struct entry *entry;
-	unsigned long ms;
-	long events = 0;
-	ktime_t time;
-	int i;
-
-	mutex_lock(&show_mutex);
-	/*
-	 * If still active then calculate up to now:
-	 */
-	if (timer_stats_active)
-		time_stop = ktime_get();
-
-	time = ktime_sub(time_stop, time_start);
-
-	period = ktime_to_timespec64(time);
-	ms = period.tv_nsec / 1000000;
-
-	seq_puts(m, "Timer Stats Version: v0.3\n");
-	seq_printf(m, "Sample period: %ld.%03ld s\n", (long)period.tv_sec, ms);
-	if (atomic_read(&overflow_count))
-		seq_printf(m, "Overflow: %d entries\n", atomic_read(&overflow_count));
-	seq_printf(m, "Collection: %s\n", timer_stats_active ? "active" : "inactive");
-
-	for (i = 0; i < nr_entries; i++) {
-		entry = entries + i;
-		if (entry->flags & TIMER_DEFERRABLE) {
-			seq_printf(m, "%4luD, %5d %-16s ",
-				entry->count, entry->pid, entry->comm);
-		} else {
-			seq_printf(m, " %4lu, %5d %-16s ",
-				entry->count, entry->pid, entry->comm);
-		}
-
-		print_name_offset(m, (unsigned long)entry->start_func);
-		seq_puts(m, " (");
-		print_name_offset(m, (unsigned long)entry->expire_func);
-		seq_puts(m, ")\n");
-
-		events += entry->count;
-	}
-
-	ms += period.tv_sec * 1000;
-	if (!ms)
-		ms = 1;
-
-	if (events && period.tv_sec)
-		seq_printf(m, "%ld total events, %ld.%03ld events/sec\n",
-			   events, events * 1000 / ms,
-			   (events * 1000000 / ms) % 1000);
-	else
-		seq_printf(m, "%ld total events\n", events);
-
-	mutex_unlock(&show_mutex);
-
-	return 0;
-}
-
-/*
- * After a state change, make sure all concurrent lookup/update
- * activities have stopped:
- */
-static void sync_access(void)
-{
-	unsigned long flags;
-	int cpu;
-
-	for_each_online_cpu(cpu) {
-		raw_spinlock_t *lock = &per_cpu(tstats_lookup_lock, cpu);
-
-		raw_spin_lock_irqsave(lock, flags);
-		/* nothing */
-		raw_spin_unlock_irqrestore(lock, flags);
-	}
-}
-
-static ssize_t tstats_write(struct file *file, const char __user *buf,
-			    size_t count, loff_t *offs)
-{
-	char ctl[2];
-
-	if (count != 2 || *offs)
-		return -EINVAL;
-
-	if (copy_from_user(ctl, buf, count))
-		return -EFAULT;
-
-	mutex_lock(&show_mutex);
-	switch (ctl[0]) {
-	case '0':
-		if (timer_stats_active) {
-			timer_stats_active = 0;
-			time_stop = ktime_get();
-			sync_access();
-		}
-		break;
-	case '1':
-		if (!timer_stats_active) {
-			reset_entries();
-			time_start = ktime_get();
-			smp_mb();
-			timer_stats_active = 1;
-		}
-		break;
-	default:
-		count = -EINVAL;
-	}
-	mutex_unlock(&show_mutex);
-
-	return count;
-}
-
-static int tstats_open(struct inode *inode, struct file *filp)
-{
-	return single_open(filp, tstats_show, NULL);
-}
-
-static const struct file_operations tstats_fops = {
-	.open		= tstats_open,
-	.read		= seq_read,
-	.write		= tstats_write,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-void __init init_timer_stats(void)
-{
-	int cpu;
-
-	for_each_possible_cpu(cpu)
-		raw_spin_lock_init(&per_cpu(tstats_lookup_lock, cpu));
-}
-
-static int __init init_tstats_procfs(void)
-{
-	struct proc_dir_entry *pe;
-
-	pe = proc_create("timer_stats", 0644, NULL, &tstats_fops);
-	if (!pe)
-		return -ENOMEM;
-	return 0;
-}
-__initcall(init_tstats_procfs);
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 7ae9b24..812b8f8 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -1529,8 +1529,6 @@
 		return;
 	}
 
-	timer_stats_timer_set_start_info(&dwork->timer);
-
 	dwork->wq = wq;
 	dwork->cpu = cpu;
 	timer->expires = jiffies + delay;
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 64ec3fd..22eff06 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1003,20 +1003,6 @@
 
 	  If unsure, say N.
 
-config TIMER_STATS
-	bool "Collect kernel timers statistics"
-	depends on DEBUG_KERNEL && PROC_FS
-	help
-	  If you say Y here, additional code will be inserted into the
-	  timer routines to collect statistics about kernel timers being
-	  reprogrammed. The statistics can be read from /proc/timer_stats.
-	  The statistics collection is started by writing 1 to /proc/timer_stats,
-	  writing 0 stops it. This feature is useful to collect information
-	  about timer usage patterns in kernel and userspace. This feature
-	  is lightweight if enabled in the kernel config but not activated
-	  (it defaults to deactivated on bootup and will only be activated
-	  if some application like powertop activates it explicitly).
-
 config DEBUG_TASK_STACK_SCAN_OFF
 	bool "Disable kmemleak task stack scan by default"
 	depends on DEBUG_KMEMLEAK