Merge "mmc: core: fix the pointer cast of freq_table" into msm-4.9
diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
index 53e4295..fe53218 100644
--- a/Documentation/devicetree/bindings/arm/coresight.txt
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -73,9 +73,6 @@
 	  AMBA markee):
 		- "arm,coresight-replicator"
 		- "qcom,coresight-csr"
-		- "arm,coresight-cti"
-		- "qcom,coresight-tpda"
-		- "qcom,coresight-tpdm"
 		- "qcom,coresight-remote-etm"
 		- "qcom,coresight-hwevent"
 		- "qcom,coresight-dummy"
@@ -264,7 +261,7 @@
 	};
 
 	tpda_mss: tpda@7043000 {
-		compatible = "qcom,coresight-tpda";
+		compatible = "qcom,coresight-tpda", "arm,primecell";
 		reg = <0x7043000 0x1000>;
 		reg-names = "tpda-base";
 
@@ -274,9 +271,8 @@
 		qcom,dsb-elem-size = <0 32>;
 		qcom,cmb-elem-size = <0 32>;
 
-		clocks = <&clock_gcc clk_qdss_clk>,
-			 <&clock_gcc clk_qdss_a_clk>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop clk_qdss_clk>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -345,15 +341,14 @@
 	};
 
 	tpdm_mss: tpdm@7042000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "qcom,coresight-tpdm", "arm,primecell";
 		reg = <0x7042000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-mss";
 
-		clocks = <&clock_gcc clk_qdss_clk>,
-			 <&clock_gcc clk_qdss_a_clk>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop qdss_clk>;
+		clock-names = "apb_pclk";
 
 		port{
 			tpdm_mss_out_tpda_mss: endpoint {
@@ -364,15 +359,14 @@
 
 4. CTIs
 	cti0: cti@6010000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,coresight-cti", "arm,primecell";
 		reg = <0x6010000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti0";
 
-		clocks = <&clock_gcc clk_qdss_clk>,
-			 <&clock_gcc clk_qdss_a_clk>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop qdss_clk>;
+		clock-names = "apb_pclk";
 	};
 
 [1]. There is currently two version of STM: STM32 and STM500.  Both
diff --git a/Documentation/devicetree/bindings/arm/msm/imem.txt b/Documentation/devicetree/bindings/arm/msm/imem.txt
index d1f8ce1..eaa7146b 100644
--- a/Documentation/devicetree/bindings/arm/msm/imem.txt
+++ b/Documentation/devicetree/bindings/arm/msm/imem.txt
@@ -57,6 +57,11 @@
 -compatible: "qcom,msm-imem-emergency_download_mode"
 -reg: start address and size of emergency_download_mode region in imem
 
+Kaslr Offset:
+------------------------
+-compatible: "qcom,msm-imem-kaslr_offset"
+-reg: start address and size of kaslr_offset region in imem
+
 USB Diag Cookies:
 -----------------
 Memory region used to store USB PID and serial numbers to be used by
@@ -95,6 +100,12 @@
 			reg = <0x6b0 32>;
 		};
 
+		kaslr_offset@6d0 {
+			compatible = "qcom,msm-imem-kaslr_offset";
+			reg = <0x6d0 12>;
+		};
+
+
 		pil@94c {
 			compatible = "qcom,msm-imem-pil";
 			reg = <0x94c 200>;
diff --git a/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt b/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
index c6626d1..3ad0986 100644
--- a/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/sde-dsi.txt
@@ -6,8 +6,9 @@
 DSI Controller:
 Required properties:
 - compatible:           Should be "qcom,dsi-ctrl-hw-v<version>". Supported
-			versions include 1.4 and 2.0.
-			eg: qcom,dsi-ctrl-hw-v1.4, qcom,dsi-ctrl-hw-v2.0
+			versions include 1.4, 2.0 and 2.2.
+			eg: qcom,dsi-ctrl-hw-v1.4, qcom,dsi-ctrl-hw-v2.0,
+			qcom,dsi-ctrl-hw-v2.2
 			And for dsi phy driver:
 			qcom,dsi-phy-v0.0-hpm, qcom,dsi-phy-v0.0-lpm,
 			qcom,dsi-phy-v1.0, qcom,dsi-phy-v2.0,
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
index f4a22e0..e1f194f3 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
@@ -169,6 +169,18 @@
   Definition: Boolean flag which when present enables input suspend for
 		debug battery.
 
+- qcom,min-freq-khz
+  Usage:      optional
+  Value type: <u32>
+  Definition: Specifies the minimum charger buck/boost switching frequency
+		in KHz. It overrides the min frequency defined for the charger.
+
+- qcom,max-freq-khz
+  Usage:      optional
+  Value type: <u32>
+  Definition: Specifies the maximum charger buck/boost switching frequency in
+		 KHz. It overrides the max frequency defined for the charger.
+
 =============================================
 Second Level Nodes - SMB2 Charger Peripherals
 =============================================
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt
index 92ef23c..5529e308 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/smb138x-charger.txt
@@ -22,7 +22,8 @@
   Definition: String which indicates the charging mode. Can be one of the
 	      following:
               Standalone/Parallel Master	- "qcom,smb138x-charger"
-	      Parallel Slave			- "qcom,smb138x-parallel-slave"
+	      smb138x Parallel Slave		- "qcom,smb138x-parallel-slave"
+	      smb1355 Parallel Slave		- "qcom,smb1355-parallel-slave",
 
 - qcom,pmic-revid
   Usage:      required
@@ -35,7 +36,8 @@
   Usage:      optional
   Value type: <u32>
   Definition: Specifies parallel charging mode. If not specified, MID-MID
-	      option is selected by default.
+	      option is selected by default. Note that smb1355 can only
+	      run in MID-MID configuration.
 
 - qcom,suspend-input
   Usage:      optional
@@ -125,7 +127,7 @@
 =======
 
 smb138x_charger: qcom,smb138x-charger {
-	compatible = "qcom,qpnp-smb138x-charger";
+	compatible = "qcom,smb138x-charger";
 	#address-cells = <1>;
 	#size-cells = <1>;
 
diff --git a/Documentation/devicetree/bindings/prng/msm-rng.txt b/Documentation/devicetree/bindings/prng/msm-rng.txt
new file mode 100644
index 0000000..917c2fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/prng/msm-rng.txt
@@ -0,0 +1,18 @@
+* RNG (Random Number Generator)
+
+Required properties:
+- compatible : Should be "qcom,msm-rng"
+- reg        : Offset and length of the register set for the device
+
+Optional property:
+- qcom,msm-rng-iface-clk : If the device uses iface-clk.
+- qcom,no-qrng-config    : Flag to decide whether the driver do the hardware configuration or not.
+
+Example:
+
+	qcom,msm-rng@f9bff000 {
+		compatible = "qcom,msm-rng";
+		reg = <0xf9bff000 0x200>;
+		qcom,msm-rng-iface-clk;
+		qcom,no-qrng-config;
+	};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index cb7ab27..0afa5a8 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -12,6 +12,7 @@
 
 
 #include "skeleton.dtsi"
+#include <dt-bindings/clock/qcom,gcc-sdxpoorwills.h>
 
 / {
 	model = "Qualcomm Technologies, Inc. SDX POORWILLS";
@@ -135,6 +136,18 @@
 		};
 	};
 
+	clock_gcc: qcom,gcc@100000 {
+		compatible = "qcom,dummycc";
+		clock-output-names = "gcc_clocks";
+		#clock-cells = <1>;
+	};
+
+	clock_cpu: qcom,clock-a7@17810008 {
+		compatible = "qcom,dummycc";
+		clock-output-names = "cpu_clocks";
+		#clock-cells = <1>;
+	};
+
 	blsp1_uart2: serial@831000 {
 		compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
 		reg = <0x831000 0x200>;
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index dc44f9d..facbb15 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -264,6 +264,7 @@
 CONFIG_MSM_SMP2P_TEST=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_PWM=y
+CONFIG_QCOM_SHOW_RESUME_IRQ=y
 CONFIG_ANDROID=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS_SECURITY=y
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index ef75d2f..f4d7965 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -49,5 +49,7 @@
 	select MSM_JTAG_MM if CORESIGHT_ETM
 	select PM_DEVFREQ
 	select COMMON_CLK
+	select COMMON_CLK_QCOM
+	select QCOM_GDSC
 endmenu
 endif
diff --git a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
index 1a0ec0b..434de76 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
@@ -21,9 +21,8 @@
 
 		coresight-name = "coresight-replicator";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -57,9 +56,8 @@
 
 		coresight-name = "coresight-replicator-swao";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -106,9 +104,8 @@
 
 		coresight-name = "coresight-tmc-etf-swao";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -143,9 +140,8 @@
 
 		coresight-name = "coresight-funnel-swao";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -171,7 +167,8 @@
 	};
 
 	tpda_swao: tpda@6b01000 {
-		compatible = "qcom,coresight-tpda";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
 		reg = <0x6b01000 0x1000>;
 		reg-names = "tpda-base";
 
@@ -181,9 +178,8 @@
 		qcom,dsb-elem-size = <1 32>;
 		qcom,cmb-elem-size = <0 64>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -220,16 +216,16 @@
 	};
 
 	tpdm_swao0: tpdm@6b02000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 
 		reg = <0x6b02000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-swao-0";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			tpdm_swao0_out_tpda_swao: endpoint {
@@ -239,15 +235,15 @@
 	};
 
 	tpdm_swao1: tpdm@6b03000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x6b03000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name="coresight-tpdm-swao-1";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			tpdm_swao1_out_tpda_swao: endpoint {
@@ -265,13 +261,13 @@
 		reg-names = "tmc-base", "bam-base";
 
 		arm,buffer-size = <0x400000>;
+		arm,sg-enable;
 
 		coresight-name = "coresight-tmc-etr";
 		coresight-ctis = <&cti0 &cti8>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			tmc_etr_in_replicator: endpoint {
@@ -292,9 +288,8 @@
 		coresight-ctis = <&cti0 &cti8>;
 		arm,default-sink;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -329,9 +324,8 @@
 
 		coresight-name = "coresight-funnel-merg";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -375,9 +369,8 @@
 
 		coresight-name = "coresight-stm";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			stm_out_funnel_in0: endpoint {
@@ -396,9 +389,8 @@
 
 		coresight-name = "coresight-funnel-in0";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -449,9 +441,8 @@
 
 		coresight-name = "coresight-funnel-in2";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -498,7 +489,8 @@
 	};
 
 	tpda: tpda@6004000 {
-		compatible = "qcom,coresight-tpda";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
 		reg = <0x6004000 0x1000>;
 		reg-names = "tpda-base";
 
@@ -519,9 +511,8 @@
 				     <7 64>,
 				     <13 64>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -618,9 +609,8 @@
 
 		coresight-name = "coresight-funnel-modem";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -646,7 +636,8 @@
 	};
 
 	tpda_modem: tpda@6831000 {
-		compatible = "qcom,coresight-tpda";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
 		reg = <0x6831000 0x1000>;
 		reg-names = "tpda-base";
 
@@ -656,9 +647,8 @@
 		qcom,dsb-elem-size = <0 32>;
 		qcom,cmb-elem-size = <0 64>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -683,15 +673,15 @@
 	};
 
 	tpdm_modem: tpdm@6830000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x6830000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-modem";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			tpdm_modem_out_tpda_modem: endpoint {
@@ -709,9 +699,8 @@
 
 		coresight-name = "coresight-funnel-lpass";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -743,9 +732,8 @@
 
 		coresight-name = "coresight-tpdm-lpass";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "core_clk";
 
 		port {
 			tpdm_lpass_out_funnel_lpass: endpoint {
@@ -755,15 +743,15 @@
 	};
 
 	tpdm_center: tpdm@6c28000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x6c28000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-center";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			tpdm_center_out_tpda: endpoint {
@@ -773,15 +761,15 @@
 	};
 
 	tpdm_north: tpdm@6a24000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x6a24000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-north";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			tpdm_north_out_tpda: endpoint {
@@ -791,15 +779,15 @@
 	};
 
 	tpdm_qm: tpdm@69d0000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x69d0000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-qm";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			tpdm_qm_out_tpda: endpoint {
@@ -809,7 +797,8 @@
 	};
 
 	tpda_apss: tpda@7862000 {
-		compatible = "qcom,coresight-tpda";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
 		reg = <0x7862000 0x1000>;
 		reg-names = "tpda-base";
 
@@ -818,9 +807,8 @@
 		qcom,tpda-atid = <66>;
 		qcom,dsb-elem-size = <0 32>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -845,15 +833,15 @@
 	};
 
 	tpdm_apss: tpdm@7860000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x7860000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-apss";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			tpdm_apss_out_tpda_apss: endpoint {
@@ -863,7 +851,8 @@
 	};
 
 	tpda_llm_silver: tpda@78c0000 {
-		compatible = "qcom,coresight-tpda";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
 		reg = <0x78c0000 0x1000>;
 		reg-names = "tpda-base";
 
@@ -872,9 +861,8 @@
 		qcom,tpda-atid = <72>;
 		qcom,cmb-elem-size = <0 64>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -899,15 +887,15 @@
 	};
 
 	tpdm_llm_silver: tpdm@78a0000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x78a0000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-llm-silver";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			tpdm_llm_silver_out_tpda_llm_silver: endpoint {
@@ -918,7 +906,8 @@
 	};
 
 	tpda_llm_gold: tpda@78d0000 {
-		compatible = "qcom,coresight-tpda";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
 		reg = <0x78d0000 0x1000>;
 		reg-names = "tpda-base";
 
@@ -927,9 +916,8 @@
 		qcom,tpda-atid = <73>;
 		qcom,cmb-elem-size = <0 64>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -954,15 +942,15 @@
 	};
 
 	tpdm_llm_gold: tpdm@78b0000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x78b0000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-llm-gold";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			tpdm_llm_gold_out_tpda_llm_gold: endpoint {
@@ -981,9 +969,8 @@
 
 		coresight-name = "coresight-funnel-dl-mm";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -1009,15 +996,15 @@
 	};
 
 	tpdm_mm: tpdm@6c08000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x6c08000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-mm";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			tpdm_mm_out_funnel_dl_mm: endpoint {
@@ -1035,9 +1022,8 @@
 
 		coresight-name = "coresight-funnel-ddr-0";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -1063,15 +1049,15 @@
 	};
 
 	tpdm_ddr: tpdm@69e0000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x69e0000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-ddr";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			tpdm_ddr_out_funnel_ddr_0: endpoint {
@@ -1081,15 +1067,15 @@
 	};
 
 	tpdm_pimem: tpdm@6850000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x6850000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-pimem";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			tpdm_pimem_out_tpda: endpoint {
@@ -1099,15 +1085,15 @@
 	};
 
 	tpdm_vsense: tpdm@6840000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x6840000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-vsense";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port{
 			tpdm_vsense_out_tpda: endpoint {
@@ -1117,7 +1103,8 @@
 	};
 
 	tpda_olc: tpda@7832000 {
-		compatible = "qcom,coresight-tpda";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
 		reg = <0x7832000 0x1000>;
 		reg-names = "tpda-base";
 
@@ -1126,9 +1113,8 @@
 		qcom,tpda-atid = <69>;
 		qcom,cmb-elem-size = <0 64>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -1152,15 +1138,15 @@
 	};
 
 	tpdm_olc: tpdm@7830000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x7830000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-olc";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port{
 			tpdm_olc_out_tpda_olc: endpoint {
@@ -1170,7 +1156,8 @@
 	};
 
 	tpda_spss: tpda@6882000 {
-		compatible = "qcom,coresight-tpda";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
 		reg = <0x6882000 0x1000>;
 		reg-names = "tpda-base";
 
@@ -1179,9 +1166,8 @@
 		qcom,tpda-atid = <70>;
 		qcom,dsb-elem-size = <0 32>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -1205,16 +1191,15 @@
 	};
 
 	tpdm_spss: tpdm@6880000 {
-		compatible = "qcom,coresight-tpdm";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
 		reg = <0x6880000 0x1000>;
 		reg-names = "tpdm-base";
 
 		coresight-name = "coresight-tpdm-spss";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
-
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 		qcom,msr-fix-req;
 
 		port{
@@ -1233,9 +1218,8 @@
 
 		coresight-name = "coresight-funnel-spss";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -1269,9 +1253,8 @@
 
 		coresight-name = "coresight-funnel-qatb";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -1297,299 +1280,315 @@
 	};
 
 	cti0: cti@6010000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x6010000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti0";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti1: cti@6011000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x6011000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti1";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti2: cti@6012000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x6012000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti2";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 	};
 
 	cti3: cti@6013000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x6013000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti3";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti4: cti@6014000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x6014000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti4";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti5: cti@6015000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x6015000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti5";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti6: cti@6016000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x6016000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti6";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti7: cti@6017000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x6017000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti7";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti8: cti@6018000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x6018000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti8";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti9: cti@6019000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x6019000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti9";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti10: cti@601a000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x601a000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti10";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti11: cti@601b000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x601b000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti11";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti12: cti@601c000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x601c000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti12";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti13: cti@601d000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x601d000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti13";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti14: cti@601e000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x601e000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti14";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti15: cti@601f000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x601f000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti15";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti_cpu0: cti@7020000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x7020000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu0";
 		cpu = <&CPU0>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
 	};
 
 	cti_cpu1: cti@7120000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x7120000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu1";
 		cpu = <&CPU1>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 	};
 
 	cti_cpu2: cti@7220000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x7220000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu2";
 		cpu = <&CPU2>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 	};
 
 	cti_cpu3: cti@7320000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x7320000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu3";
 		cpu = <&CPU3>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 	};
 
 	cti_cpu4: cti@7420000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x7420000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu4";
 		cpu = <&CPU4>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 	};
 
 	cti_cpu5: cti@7520000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x7520000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu5";
 		cpu = <&CPU5>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 	};
 
 	cti_cpu6: cti@7620000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x7620000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu6";
 		cpu = <&CPU6>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 	};
 
 	cti_cpu7: cti@7720000 {
-		compatible = "arm,coresight-cti";
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
 		reg = <0x7720000 0x1000>;
 		reg-names = "cti-base";
 
 		coresight-name = "coresight-cti-cpu7";
 		cpu = <&CPU7>;
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 	};
 
 	dummy_eud: dummy_sink {
@@ -1616,9 +1615,8 @@
 
 		coresight-name = "coresight-funnel-apss-merg";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
@@ -1688,9 +1686,8 @@
 
 		coresight-name = "coresight-etm0";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			etm0_out_funnel_apss: endpoint {
@@ -1708,9 +1705,8 @@
 
 		coresight-name = "coresight-etm1";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			etm1_out_funnel_apss: endpoint {
@@ -1728,9 +1724,8 @@
 
 		coresight-name = "coresight-etm2";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			etm2_out_funnel_apss: endpoint {
@@ -1748,9 +1743,8 @@
 
 		coresight-name = "coresight-etm3";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			etm3_out_funnel_apss: endpoint {
@@ -1768,9 +1762,8 @@
 
 		coresight-name = "coresight-etm4";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			etm4_out_funnel_apss: endpoint {
@@ -1788,9 +1781,8 @@
 
 		coresight-name = "coresight-etm5";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			etm5_out_funnel_apss: endpoint {
@@ -1808,9 +1800,8 @@
 
 		coresight-name = "coresight-etm6";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			etm6_out_funnel_apss: endpoint {
@@ -1828,9 +1819,8 @@
 
 		coresight-name = "coresight-etm7";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		port {
 			etm7_out_funnel_apss: endpoint {
@@ -1848,9 +1838,8 @@
 
 		coresight-name = "coresight-funnel-apss";
 
-		clocks = <&clock_gcc RPMH_QDSS_CLK>,
-			 <&clock_gcc RPMH_QDSS_A_CLK>;
-		clock-names = "apb_pclk", "core_a_clk";
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
 
 		ports {
 			#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde-pll.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde-pll.dtsi
new file mode 100644
index 0000000..168f2a9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde-pll.dtsi
@@ -0,0 +1,67 @@
+/* Copyright (c) 2016-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.
+ */
+
+&soc {
+	mdss_dsi0_pll: qcom,mdss_dsi_pll@ae94a00 {
+		compatible = "qcom,mdss_dsi_pll_10nm";
+		label = "MDSS DSI 0 PLL";
+		cell-index = <0>;
+		#clock-cells = <1>;
+		reg = <0xae94a00 0x1e0>,
+		      <0xae94400 0x800>,
+		      <0xaf03000 0x8>;
+		reg-names = "pll_base", "phy_base", "gdsc_base";
+		clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>;
+		clock-names = "iface_clk";
+		clock-rate = <0>;
+		gdsc-supply = <&mdss_core_gdsc>;
+		qcom,platform-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			qcom,platform-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "gdsc";
+				qcom,supply-min-voltage = <0>;
+				qcom,supply-max-voltage = <0>;
+				qcom,supply-enable-load = <0>;
+				qcom,supply-disable-load = <0>;
+			};
+		};
+	};
+
+	mdss_dsi1_pll: qcom,mdss_dsi_pll@ae96a00 {
+		compatible = "qcom,mdss_dsi_pll_10nm";
+		label = "MDSS DSI 1 PLL";
+		cell-index = <1>;
+		#clock-cells = <1>;
+		reg = <0xae96a00 0x1e0>,
+		      <0xae96400 0x800>,
+		      <0xaf03000 0x8>;
+		reg-names = "pll_base", "phy_base", "gdsc_base";
+		clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>;
+		clock-names = "iface_clk";
+		clock-rate = <0>;
+		gdsc-supply = <&mdss_core_gdsc>;
+		qcom,platform-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			qcom,platform-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "gdsc";
+				qcom,supply-min-voltage = <0>;
+				qcom,supply-max-voltage = <0>;
+				qcom,supply-enable-load = <0>;
+				qcom,supply-disable-load = <0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
index 2f45c41..cb5d924 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
@@ -273,98 +273,81 @@
 	};
 
 	mdss_dsi0: qcom,mdss_dsi_ctrl0@ae94000 {
-		compatible = "qcom,dsi-ctrl-hw-v2.0";
+		compatible = "qcom,dsi-ctrl-hw-v2.2";
 		label = "dsi-ctrl-0";
-		status = "disabled";
 		cell-index = <0>;
-		reg =   <0xae94000 0x400>;
-		reg-names = "dsi_ctrl";
+		reg =   <0xae94000 0x400>,
+			<0xaf08000 0x4>;
+		reg-names = "dsi_ctrl", "disp_cc_base";
 		interrupt-parent = <&mdss_mdp>;
 		interrupts = <4 0>;
 		vdda-1p2-supply = <&pm8998_l26>;
-		vdda-0p9-supply = <&pm8998_l1>;
 		clocks = <&clock_dispcc DISP_CC_MDSS_BYTE0_CLK>,
 		<&clock_dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
 		<&clock_dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
 		<&clock_dispcc DISP_CC_MDSS_PCLK0_CLK>,
-		<&clock_dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+		<&clock_dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>,
+		<&clock_dispcc DISP_CC_MDSS_ESC0_CLK>;
 		clock-names = "byte_clk", "byte_clk_rcg", "byte_intf_clk",
-					"pixel_clk", "pixel_clk_rcg";
+					"pixel_clk", "pixel_clk_rcg",
+					"esc_clk";
 
 		qcom,ctrl-supply-entries {
 			#address-cells = <1>;
 			#size-cells = <0>;
+
 			qcom,ctrl-supply-entry@0 {
 				reg = <0>;
-				qcom,supply-name = "vdda-0p9";
-				qcom,supply-min-voltage = <925000>;
-				qcom,supply-max-voltage = <925000>;
-				qcom,supply-enable-load = <17000>;
-				qcom,supply-disable-load = <32>;
-			};
-
-			qcom,ctrl-supply-entry@1 {
-				reg = <0>;
 				qcom,supply-name = "vdda-1p2";
-				qcom,supply-min-voltage = <1250000>;
-				qcom,supply-max-voltage = <1250000>;
-				qcom,supply-enable-load = <18160>;
-				qcom,supply-disable-load = <1>;
+				qcom,supply-min-voltage = <1200000>;
+				qcom,supply-max-voltage = <1200000>;
+				qcom,supply-enable-load = <21800>;
+				qcom,supply-disable-load = <4>;
 			};
 		};
 	};
 
 	mdss_dsi1: qcom,mdss_dsi_ctrl1@ae96000 {
-		compatible = "qcom,dsi-ctrl-hw-v2.0";
+		compatible = "qcom,dsi-ctrl-hw-v2.2";
 		label = "dsi-ctrl-1";
-		status = "disabled";
 		cell-index = <1>;
-		reg =   <0xae96000 0x400>;
-		reg-names = "dsi_ctrl";
+		reg =   <0xae96000 0x400>,
+			<0xaf08000 0x4>;
+		reg-names = "dsi_ctrl", "disp_cc_base";
 		interrupt-parent = <&mdss_mdp>;
 		interrupts = <5 0>;
 		vdda-1p2-supply = <&pm8998_l26>;
-		vdda-0p9-supply = <&pm8998_l1>;
-		clocks = <&clock_dispcc DISP_CC_MDSS_BYTE0_CLK>,
-		<&clock_dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
-		<&clock_dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
-		<&clock_dispcc DISP_CC_MDSS_PCLK0_CLK>,
-		<&clock_dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+		clocks = <&clock_dispcc DISP_CC_MDSS_BYTE1_CLK>,
+		<&clock_dispcc DISP_CC_MDSS_BYTE1_CLK_SRC>,
+		<&clock_dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>,
+		<&clock_dispcc DISP_CC_MDSS_PCLK1_CLK>,
+		<&clock_dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>,
+		<&clock_dispcc DISP_CC_MDSS_ESC1_CLK>;
 		clock-names = "byte_clk", "byte_clk_rcg", "byte_intf_clk",
-				"pixel_clk", "pixel_clk_rcg";
+				"pixel_clk", "pixel_clk_rcg", "esc_clk";
 		qcom,ctrl-supply-entries {
 			#address-cells = <1>;
 			#size-cells = <0>;
 
 			qcom,ctrl-supply-entry@0 {
 				reg = <0>;
-				qcom,supply-name = "vdda-0p9";
-				qcom,supply-min-voltage = <925000>;
-				qcom,supply-max-voltage = <925000>;
-				qcom,supply-enable-load = <17000>;
-				qcom,supply-disable-load = <32>;
-			};
-
-			qcom,ctrl-supply-entry@1 {
-				reg = <0>;
 				qcom,supply-name = "vdda-1p2";
-				qcom,supply-min-voltage = <1250000>;
-				qcom,supply-max-voltage = <1250000>;
-				qcom,supply-enable-load = <18160>;
-				qcom,supply-disable-load = <1>;
+				qcom,supply-min-voltage = <1200000>;
+				qcom,supply-max-voltage = <1200000>;
+				qcom,supply-enable-load = <21800>;
+				qcom,supply-disable-load = <4>;
 			};
 		};
 	};
 
 	mdss_dsi_phy0: qcom,mdss_dsi_phy0@ae94400 {
 		compatible = "qcom,dsi-phy-v3.0";
-		status = "disabled";
 		label = "dsi-phy-0";
 		cell-index = <0>;
 		reg = <0xae94400 0x7c0>;
 		reg-names = "dsi_phy";
 		gdsc-supply = <&mdss_core_gdsc>;
-		vdda-1p2-supply = <&pm8998_l26>;
+		vdda-0p9-supply = <&pm8998_l1>;
 		qcom,platform-strength-ctrl = [55 03
 						55 03
 						55 03
@@ -381,24 +364,23 @@
 			#size-cells = <0>;
 			qcom,phy-supply-entry@0 {
 				reg = <0>;
-				qcom,supply-name = "vdda-1p2";
-				qcom,supply-min-voltage = <1250000>;
-				qcom,supply-max-voltage = <1250000>;
-				qcom,supply-enable-load = <2500>;
-				qcom,supply-disable-load = <1>;
+				qcom,supply-name = "vdda-0p9";
+				qcom,supply-min-voltage = <880000>;
+				qcom,supply-max-voltage = <880000>;
+				qcom,supply-enable-load = <36000>;
+				qcom,supply-disable-load = <32>;
 			};
 		};
 	};
 
 	mdss_dsi_phy1: qcom,mdss_dsi_phy0@ae96400 {
 		compatible = "qcom,dsi-phy-v3.0";
-		status = "disabled";
 		label = "dsi-phy-1";
 		cell-index = <1>;
 		reg = <0xae96400 0x7c0>;
 		reg-names = "dsi_phy";
 		gdsc-supply = <&mdss_core_gdsc>;
-		vdda-1p2-supply = <&pm8998_l26>;
+		vdda-0p9-supply = <&pm8998_l1>;
 		qcom,platform-strength-ctrl = [55 03
 						55 03
 						55 03
@@ -415,11 +397,11 @@
 			#size-cells = <0>;
 			qcom,phy-supply-entry@0 {
 				reg = <0>;
-				qcom,supply-name = "vdda-1p2";
-				qcom,supply-min-voltage = <1250000>;
-				qcom,supply-max-voltage = <1250000>;
-				qcom,supply-enable-load = <2500>;
-				qcom,supply-disable-load = <1>;
+				qcom,supply-name = "vdda-0p9";
+				qcom,supply-min-voltage = <880000>;
+				qcom,supply-max-voltage = <880000>;
+				qcom,supply-enable-load = <36000>;
+				qcom,supply-disable-load = <32>;
 			};
 		};
 	};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 39c90c7..3100fe4 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -18,6 +18,7 @@
 #include <dt-bindings/clock/qcom,videocc-sdm845.h>
 #include <dt-bindings/clock/qcom,cpucc-sdm845.h>
 #include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/clock/qcom,aop-qmp.h>
 #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/soc/qcom,tcs-mbox.h>
@@ -429,6 +430,7 @@
 };
 
 #include "msm-gdsc-sdm845.dtsi"
+#include "sdm845-sde-pll.dtsi"
 #include "sdm845-sde.dtsi"
 #include "sdm845-sde-display.dtsi"
 #include "sdm845-qupv3.dtsi"
@@ -1011,6 +1013,13 @@
 		#clock-cells = <1>;
 	};
 
+	clock_aop: qcom,aopclk {
+		compatible = "qcom,aop-qmp-clk";
+		#clock-cells = <1>;
+		mboxes = <&qmp_aop 0>;
+		mbox-names = "qdss_clk";
+	};
+
 	ufsphy_mem: ufsphy_mem@1d87000 {
 		reg = <0x1d87000 0xda8>; /* PHY regs */
 		reg-names = "phy_mem";
@@ -1495,11 +1504,22 @@
 		qcom,rtb-size = <0x100000>;
 	};
 
+	qcom,mpm2-sleep-counter@0x0c221000 {
+		compatible = "qcom,mpm2-sleep-counter";
+		reg = <0x0c221000 0x1000>;
+		clock-frequency = <32768>;
+	};
+
 	qcom,msm-cdsp-loader {
 		compatible = "qcom,cdsp-loader";
 		qcom,proc-img-to-load = "cdsp";
 	};
 
+	qcom,msm-adsprpc-mem {
+		compatible = "qcom,msm-adsprpc-mem-region";
+		memory-region = <&adsp_mem>;
+	};
+
 	qcom,msm_fastrpc {
 		compatible = "qcom,msm-fastrpc-compute";
 
@@ -1551,6 +1571,32 @@
 			iommus = <&apps_smmu 0x1408>,
 				 <&apps_smmu 0x1428>;
 		};
+		qcom,msm_fastrpc_compute_cb9 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "cdsprpc-smd";
+			qcom,secure-context-bank;
+			iommus = <&apps_smmu 0x1409>,
+				 <&apps_smmu 0x1419>,
+				 <&apps_smmu 0x1429>;
+		};
+		qcom,msm_fastrpc_compute_cb10 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "cdsprpc-smd";
+			qcom,secure-context-bank;
+			iommus = <&apps_smmu 0x140A>,
+				 <&apps_smmu 0x141A>,
+				 <&apps_smmu 0x142A>;
+		};
+		qcom,msm_fastrpc_compute_cb11 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "adsprpc-smd";
+			iommus = <&apps_smmu 0x1823>;
+		};
+		qcom,msm_fastrpc_compute_cb12 {
+			compatible = "qcom,msm-fastrpc-compute-cb";
+			label = "adsprpc-smd";
+			iommus = <&apps_smmu 0x1824>;
+		};
 	};
 
 	qcom,msm-imem@146bf000 {
@@ -1570,10 +1616,20 @@
 			reg = <0x65c 4>;
 		};
 
+		boot_stats@6b0 {
+			compatible = "qcom,msm-imem-boot_stats";
+			reg = <0x6b0 32>;
+		};
+
 		pil@94c {
 			compatible = "qcom,msm-imem-pil";
 			reg = <0x94c 200>;
 		};
+
+		kaslr_offset@6d0 {
+			compatible = "qcom,msm-imem-kaslr_offset";
+			reg = <0x6d0 12>;
+		};
 	};
 
 	qcom,venus@aae0000 {
@@ -2058,6 +2114,29 @@
 		qcom,qsee-reentrancy-support = <2>;
 	};
 
+	qcom_rng: qrng@793000 {
+		compatible = "qcom,msm-rng";
+		reg = <0x793000 0x1000>;
+		qcom,msm-rng-iface-clk;
+		qcom,no-qrng-config;
+		qcom,msm-bus,name = "msm-rng-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<1 618 0 0>,    /* No vote */
+			<1 618 0 800>;  /* 100 KHz */
+		clocks = <&clock_gcc GCC_PRNG_AHB_CLK>;
+		clock-names = "iface_clk";
+	};
+
+	qcom_tzlog: tz-log@146bf720 {
+		compatible = "qcom,tz-log";
+		reg = <0x146bf720 0x3000>;
+		qcom,hyplog-enabled;
+		hyplog-address-offset = <0x410>;
+		hyplog-size-offset = <0x414>;
+	};
+
 	qcom,msm_gsi {
 		compatible = "qcom,msm_gsi";
 	};
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 926b10f..9a2ab8c 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -55,6 +55,7 @@
 CONFIG_HZ_100=y
 CONFIG_CMA=y
 CONFIG_ZSMALLOC=y
+CONFIG_BALANCE_ANON_FILE_RECLAIM=y
 CONFIG_SECCOMP=y
 CONFIG_ARMV8_DEPRECATED=y
 CONFIG_SWP_EMULATION=y
@@ -275,6 +276,7 @@
 CONFIG_SERIAL_MSM_GENI=y
 CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
 CONFIG_MSM_ADSPRPC=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QCOM_GENI=y
@@ -442,6 +444,7 @@
 CONFIG_IOMMU_TESTS=y
 CONFIG_QCOM_LLCC=y
 CONFIG_QCOM_SDM845_LLCC=y
+CONFIG_MSM_BOOT_STATS=y
 CONFIG_QCOM_EUD=y
 CONFIG_QCOM_WATCHDOG_V2=y
 CONFIG_QCOM_MEMORY_DUMP_V2=y
@@ -491,6 +494,7 @@
 CONFIG_ARM_GIC_V3_ACL=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_MSM_TZ_LOG=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 5d6246b..31f8703 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -61,6 +61,7 @@
 CONFIG_CLEANCACHE=y
 CONFIG_CMA=y
 CONFIG_ZSMALLOC=y
+CONFIG_BALANCE_ANON_FILE_RECLAIM=y
 CONFIG_SECCOMP=y
 CONFIG_ARMV8_DEPRECATED=y
 CONFIG_SWP_EMULATION=y
@@ -282,9 +283,8 @@
 CONFIG_SERIAL_MSM_GENI=y
 CONFIG_SERIAL_MSM_GENI_CONSOLE=y
 CONFIG_DIAG_CHAR=y
-CONFIG_HVC_DCC=y
-CONFIG_HVC_DCC_SERIALIZE_SMP=y
 CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
 CONFIG_MSM_ADSPRPC=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_QCOM_GENI=y
@@ -338,6 +338,7 @@
 CONFIG_VIDEO_ADV_DEBUG=y
 CONFIG_VIDEO_FIXED_MINOR_RANGES=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_SPECTRA_CAMERA=y
 CONFIG_MSM_VIDC_V4L2=y
 CONFIG_MSM_VIDC_VMEM=y
 CONFIG_MSM_VIDC_GOVERNORS=y
@@ -460,6 +461,7 @@
 CONFIG_QCOM_CPUSS_DUMP=y
 CONFIG_QCOM_LLCC=y
 CONFIG_QCOM_SDM845_LLCC=y
+CONFIG_MSM_BOOT_STATS=y
 CONFIG_MSM_CORE_HANG_DETECT=y
 CONFIG_MSM_GLADIATOR_HANG_DETECT=y
 CONFIG_QCOM_EUD=y
@@ -514,6 +516,7 @@
 CONFIG_PHY_XGENE=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_MSM_TZ_LOG=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 296e139..0a34644 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -335,7 +335,8 @@
 
 	if (is_el0_instruction_abort(esr)) {
 		vm_flags = VM_EXEC;
-	} else if ((esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM)) {
+	} else if (((esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM)) ||
+			((esr & ESR_ELx_CM) && !(mm_flags & FAULT_FLAG_USER))) {
 		vm_flags = VM_WRITE;
 		mm_flags |= FAULT_FLAG_WRITE;
 	}
diff --git a/drivers/base/dma-removed.c b/drivers/base/dma-removed.c
index 4281801..09e77d5 100644
--- a/drivers/base/dma-removed.c
+++ b/drivers/base/dma-removed.c
@@ -1,6 +1,6 @@
 /*
  *
- *  Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ *  Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
  *  Copyright (C) 2000-2004 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
@@ -294,6 +294,7 @@
 	bool no_kernel_mapping = attrs & DMA_ATTR_NO_KERNEL_MAPPING;
 	struct removed_region *dma_mem = dev->removed_mem;
 
+	size = PAGE_ALIGN(size);
 	if (!no_kernel_mapping)
 		iounmap(cpu_addr);
 	mutex_lock(&dma_mem->lock);
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 200dab5..18849f4 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -337,7 +337,6 @@
 config HW_RANDOM_MSM
 	tristate "Qualcomm SoCs Random Number Generator support"
 	depends on HW_RANDOM && ARCH_QCOM
-	default HW_RANDOM
 	---help---
 	  This driver provides kernel-side support for the Random Number
 	  Generator hardware found on Qualcomm SoCs.
@@ -347,6 +346,20 @@
 
 	  If unsure, say Y.
 
+config HW_RANDOM_MSM_LEGACY
+	tristate "QTI MSM Random Number Generator support (LEGACY)"
+	depends on HW_RANDOM && ARCH_QCOM
+	select CRYPTO_AES
+	select CRYPTO_ECB
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on QTI MSM SoCs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called msm_rng.
+
+	  If unsure, say Y.
+
 config HW_RANDOM_ST
 	tristate "ST Microelectronics HW Random Number Generator support"
 	depends on HW_RANDOM && ARCH_STI
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 5f52b1e..637adb5 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -30,6 +30,7 @@
 obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
 obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
 obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o
+obj-$(CONFIG_HW_RANDOM_MSM_LEGACY) += msm_rng.o
 obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o
 obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o
 obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
new file mode 100644
index 0000000..7641a6a
--- /dev/null
+++ b/drivers/char/hw_random/msm_rng.c
@@ -0,0 +1,481 @@
+/*
+ * Copyright (c) 2011-2013, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/hw_random.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/types.h>
+#include <soc/qcom/socinfo.h>
+#include <linux/msm-bus.h>
+#include <linux/qrng.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/delay.h>
+#include <linux/crypto.h>
+#include <crypto/internal/rng.h>
+
+#include <linux/platform_data/qcom_crypto_device.h>
+
+
+
+#define DRIVER_NAME "msm_rng"
+
+/* Device specific register offsets */
+#define PRNG_DATA_OUT_OFFSET    0x0000
+#define PRNG_STATUS_OFFSET	0x0004
+#define PRNG_LFSR_CFG_OFFSET	0x0100
+#define PRNG_CONFIG_OFFSET	0x0104
+
+/* Device specific register masks and config values */
+#define PRNG_LFSR_CFG_MASK	0xFFFF0000
+#define PRNG_LFSR_CFG_CLOCKS	0x0000DDDD
+#define PRNG_CONFIG_MASK	0xFFFFFFFD
+#define PRNG_HW_ENABLE		0x00000002
+
+#define MAX_HW_FIFO_DEPTH 16                     /* FIFO is 16 words deep */
+#define MAX_HW_FIFO_SIZE (MAX_HW_FIFO_DEPTH * 4) /* FIFO is 32 bits wide  */
+
+struct msm_rng_device {
+	struct platform_device *pdev;
+	void __iomem *base;
+	struct clk *prng_clk;
+	uint32_t qrng_perf_client;
+	struct mutex rng_lock;
+};
+
+struct msm_rng_device msm_rng_device_info;
+static struct msm_rng_device *msm_rng_dev_cached;
+struct mutex cached_rng_lock;
+static long msm_rng_ioctl(struct file *filp, unsigned int cmd,
+				unsigned long arg)
+{
+	long ret = 0;
+
+	switch (cmd) {
+	case QRNG_IOCTL_RESET_BUS_BANDWIDTH:
+		pr_info("calling msm_rng_bus_scale(LOW)\n");
+		ret = msm_bus_scale_client_update_request(
+				msm_rng_device_info.qrng_perf_client, 0);
+		if (ret)
+			pr_err("failed qrng_reset_bus_bw, ret = %ld\n", ret);
+		break;
+	default:
+		pr_err("Unsupported IOCTL call");
+		break;
+	}
+	return ret;
+}
+
+/*
+ *
+ *  This function calls hardware random bit generator directory and retuns it
+ *  back to caller
+ *
+ */
+static int msm_rng_direct_read(struct msm_rng_device *msm_rng_dev,
+					void *data, size_t max)
+{
+	struct platform_device *pdev;
+	void __iomem *base;
+	size_t currsize = 0;
+	u32 val;
+	u32 *retdata = data;
+	int ret;
+	int failed = 0;
+
+	pdev = msm_rng_dev->pdev;
+	base = msm_rng_dev->base;
+
+	/* no room for word data */
+	if (max < 4)
+		return 0;
+
+	mutex_lock(&msm_rng_dev->rng_lock);
+
+	if (msm_rng_dev->qrng_perf_client) {
+		ret = msm_bus_scale_client_update_request(
+				msm_rng_dev->qrng_perf_client, 1);
+		if (ret)
+			pr_err("bus_scale_client_update_req failed!\n");
+	}
+	/* enable PRNG clock */
+	ret = clk_prepare_enable(msm_rng_dev->prng_clk);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to enable clock in callback\n");
+		goto err;
+	}
+	/* read random data from h/w */
+	do {
+		/* check status bit if data is available */
+		while (!(readl_relaxed(base + PRNG_STATUS_OFFSET)
+				& 0x00000001)) {
+			if (failed == 10) {
+				pr_err("Data not available after retry\n");
+				break;
+			}
+			pr_err("msm_rng:Data not available!\n");
+			msleep_interruptible(10);
+			failed++;
+		}
+
+		/* read FIFO */
+		val = readl_relaxed(base + PRNG_DATA_OUT_OFFSET);
+		if (!val)
+			break;	/* no data to read so just bail */
+
+		/* write data back to callers pointer */
+		*(retdata++) = val;
+		currsize += 4;
+		/* make sure we stay on 32bit boundary */
+		if ((max - currsize) < 4)
+			break;
+
+	} while (currsize < max);
+
+	/* vote to turn off clock */
+	clk_disable_unprepare(msm_rng_dev->prng_clk);
+err:
+	if (msm_rng_dev->qrng_perf_client) {
+		ret = msm_bus_scale_client_update_request(
+				msm_rng_dev->qrng_perf_client, 0);
+		if (ret)
+			pr_err("bus_scale_client_update_req failed!\n");
+	}
+	mutex_unlock(&msm_rng_dev->rng_lock);
+
+	val = 0L;
+	return currsize;
+}
+static int msm_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+{
+	struct msm_rng_device *msm_rng_dev;
+	int rv = 0;
+
+	msm_rng_dev = (struct msm_rng_device *)rng->priv;
+	rv = msm_rng_direct_read(msm_rng_dev, data, max);
+
+	return rv;
+}
+
+
+static struct hwrng msm_rng = {
+	.name = DRIVER_NAME,
+	.read = msm_rng_read,
+	.quality = 700,
+};
+
+static int msm_rng_enable_hw(struct msm_rng_device *msm_rng_dev)
+{
+	unsigned long val = 0;
+	unsigned long reg_val = 0;
+	int ret = 0;
+
+	if (msm_rng_dev->qrng_perf_client) {
+		ret = msm_bus_scale_client_update_request(
+				msm_rng_dev->qrng_perf_client, 1);
+		if (ret)
+			pr_err("bus_scale_client_update_req failed!\n");
+	}
+	/* Enable the PRNG CLK */
+	ret = clk_prepare_enable(msm_rng_dev->prng_clk);
+	if (ret) {
+		dev_err(&(msm_rng_dev->pdev)->dev,
+				"failed to enable clock in probe\n");
+		return -EPERM;
+	}
+
+	/* Enable PRNG h/w only if it is NOT ON */
+	val = readl_relaxed(msm_rng_dev->base + PRNG_CONFIG_OFFSET) &
+					PRNG_HW_ENABLE;
+	/* PRNG H/W is not ON */
+	if (val != PRNG_HW_ENABLE) {
+		val = readl_relaxed(msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET);
+		val &= PRNG_LFSR_CFG_MASK;
+		val |= PRNG_LFSR_CFG_CLOCKS;
+		writel_relaxed(val, msm_rng_dev->base + PRNG_LFSR_CFG_OFFSET);
+
+		/* The PRNG CONFIG register should be first written */
+		mb();
+
+		reg_val = readl_relaxed(msm_rng_dev->base + PRNG_CONFIG_OFFSET)
+						& PRNG_CONFIG_MASK;
+		reg_val |= PRNG_HW_ENABLE;
+		writel_relaxed(reg_val, msm_rng_dev->base + PRNG_CONFIG_OFFSET);
+
+		/* The PRNG clk should be disabled only after we enable the
+		 * PRNG h/w by writing to the PRNG CONFIG register.
+		 */
+		mb();
+	}
+	clk_disable_unprepare(msm_rng_dev->prng_clk);
+
+	if (msm_rng_dev->qrng_perf_client) {
+		ret = msm_bus_scale_client_update_request(
+				msm_rng_dev->qrng_perf_client, 0);
+		if (ret)
+			pr_err("bus_scale_client_update_req failed!\n");
+	}
+
+	return 0;
+}
+
+static const struct file_operations msm_rng_fops = {
+	.unlocked_ioctl = msm_rng_ioctl,
+};
+static struct class *msm_rng_class;
+static struct cdev msm_rng_cdev;
+
+static int msm_rng_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct msm_rng_device *msm_rng_dev = NULL;
+	void __iomem *base = NULL;
+	bool configure_qrng = true;
+	int error = 0;
+	int ret = 0;
+	struct device *dev;
+
+	struct msm_bus_scale_pdata *qrng_platform_support = NULL;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "invalid address\n");
+		error = -EFAULT;
+		goto err_exit;
+	}
+
+	msm_rng_dev = kzalloc(sizeof(struct msm_rng_device), GFP_KERNEL);
+	if (!msm_rng_dev) {
+		error = -ENOMEM;
+		goto err_exit;
+	}
+
+	base = ioremap(res->start, resource_size(res));
+	if (!base) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		error = -ENOMEM;
+		goto err_iomap;
+	}
+	msm_rng_dev->base = base;
+
+	/* create a handle for clock control */
+	if ((pdev->dev.of_node) && (of_property_read_bool(pdev->dev.of_node,
+					"qcom,msm-rng-iface-clk")))
+		msm_rng_dev->prng_clk = clk_get(&pdev->dev,
+							"iface_clk");
+	else
+		msm_rng_dev->prng_clk = clk_get(&pdev->dev, "core_clk");
+	if (IS_ERR(msm_rng_dev->prng_clk)) {
+		dev_err(&pdev->dev, "failed to register clock source\n");
+		error = -EPERM;
+		goto err_clk_get;
+	}
+
+	/* save away pdev and register driver data */
+	msm_rng_dev->pdev = pdev;
+	platform_set_drvdata(pdev, msm_rng_dev);
+
+	if (pdev->dev.of_node) {
+		/* Register bus client */
+		qrng_platform_support = msm_bus_cl_get_pdata(pdev);
+		msm_rng_dev->qrng_perf_client = msm_bus_scale_register_client(
+						qrng_platform_support);
+		msm_rng_device_info.qrng_perf_client =
+					msm_rng_dev->qrng_perf_client;
+		if (!msm_rng_dev->qrng_perf_client)
+			pr_err("Unable to register bus client\n");
+	}
+
+	/* Enable rng h/w for the targets which can access the entire
+	 * address space of PRNG.
+	 */
+	if ((pdev->dev.of_node) && (of_property_read_bool(pdev->dev.of_node,
+					"qcom,no-qrng-config")))
+		configure_qrng = false;
+	if (configure_qrng) {
+		error = msm_rng_enable_hw(msm_rng_dev);
+		if (error)
+			goto rollback_clk;
+	}
+
+	mutex_init(&msm_rng_dev->rng_lock);
+	mutex_init(&cached_rng_lock);
+
+	/* register with hwrng framework */
+	msm_rng.priv = (unsigned long) msm_rng_dev;
+	error = hwrng_register(&msm_rng);
+	if (error) {
+		dev_err(&pdev->dev, "failed to register hwrng\n");
+		error = -EPERM;
+		goto rollback_clk;
+	}
+	ret = register_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME, &msm_rng_fops);
+
+	msm_rng_class = class_create(THIS_MODULE, "msm-rng");
+	if (IS_ERR(msm_rng_class)) {
+		pr_err("class_create failed\n");
+		return PTR_ERR(msm_rng_class);
+	}
+
+	dev = device_create(msm_rng_class, NULL, MKDEV(QRNG_IOC_MAGIC, 0),
+				NULL, "msm-rng");
+	if (IS_ERR(dev)) {
+		pr_err("Device create failed\n");
+		error = PTR_ERR(dev);
+		goto unregister_chrdev;
+	}
+	cdev_init(&msm_rng_cdev, &msm_rng_fops);
+	msm_rng_dev_cached = msm_rng_dev;
+	return error;
+
+unregister_chrdev:
+	unregister_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME);
+rollback_clk:
+	clk_put(msm_rng_dev->prng_clk);
+err_clk_get:
+	iounmap(msm_rng_dev->base);
+err_iomap:
+	kzfree(msm_rng_dev);
+err_exit:
+	return error;
+}
+
+static int msm_rng_remove(struct platform_device *pdev)
+{
+	struct msm_rng_device *msm_rng_dev = platform_get_drvdata(pdev);
+
+	unregister_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME);
+	hwrng_unregister(&msm_rng);
+	clk_put(msm_rng_dev->prng_clk);
+	iounmap(msm_rng_dev->base);
+	platform_set_drvdata(pdev, NULL);
+	if (msm_rng_dev->qrng_perf_client)
+		msm_bus_scale_unregister_client(msm_rng_dev->qrng_perf_client);
+
+	kzfree(msm_rng_dev);
+	msm_rng_dev_cached = NULL;
+	return 0;
+}
+
+static int qrng_get_random(struct crypto_rng *tfm, const u8 *src,
+				unsigned int slen, u8 *rdata,
+				unsigned int dlen)
+{
+	int sizeread = 0;
+	int rv = -EFAULT;
+
+	if (!msm_rng_dev_cached) {
+		pr_err("%s: msm_rng_dev is not initialized.\n", __func__);
+		rv = -ENODEV;
+		goto err_exit;
+	}
+
+	if (!rdata) {
+		pr_err("%s: data buffer is null!\n", __func__);
+		rv = -EINVAL;
+		goto err_exit;
+	}
+
+	if (signal_pending(current) ||
+		mutex_lock_interruptible(&cached_rng_lock)) {
+		pr_err("%s: mutex lock interrupted!\n", __func__);
+		rv = -ERESTARTSYS;
+		goto err_exit;
+	}
+	sizeread = msm_rng_direct_read(msm_rng_dev_cached, rdata, dlen);
+
+	if (sizeread == dlen)
+		rv = 0;
+
+	mutex_unlock(&cached_rng_lock);
+err_exit:
+	return rv;
+
+}
+
+static int qrng_reset(struct crypto_rng *tfm, const u8 *seed, unsigned int slen)
+{
+	return 0;
+}
+
+static struct rng_alg rng_algs[] = { {
+	.generate	= qrng_get_random,
+	.seed		= qrng_reset,
+	.seedsize	= 0,
+	.base		= {
+		.cra_name		= "qrng",
+		.cra_driver_name	= "fips_hw_qrng",
+		.cra_priority		= 300,
+		.cra_ctxsize		= 0,
+		.cra_module		= THIS_MODULE,
+	}
+} };
+
+static const struct of_device_id qrng_match[] = {
+	{	.compatible = "qcom,msm-rng",
+	},
+	{}
+};
+
+static struct platform_driver rng_driver = {
+	.probe      = msm_rng_probe,
+	.remove     = msm_rng_remove,
+	.driver     = {
+		.name   = DRIVER_NAME,
+		.owner  = THIS_MODULE,
+		.of_match_table = qrng_match,
+	}
+};
+
+static int __init msm_rng_init(void)
+{
+	int ret;
+
+	msm_rng_dev_cached = NULL;
+	ret = platform_driver_register(&rng_driver);
+	if (ret) {
+		pr_err("%s: platform_driver_register error:%d\n",
+			__func__, ret);
+		goto err_exit;
+	}
+	ret = crypto_register_rngs(rng_algs, ARRAY_SIZE(rng_algs));
+	if (ret) {
+		pr_err("%s: crypto_register_algs error:%d\n",
+			__func__, ret);
+		goto err_exit;
+	}
+
+err_exit:
+	return ret;
+}
+
+module_init(msm_rng_init);
+
+static void __exit msm_rng_exit(void)
+{
+	crypto_unregister_rngs(rng_algs, ARRAY_SIZE(rng_algs));
+	platform_driver_unregister(&rng_driver);
+}
+
+module_exit(msm_rng_exit);
+
+MODULE_DESCRIPTION("QTI MSM Random Number Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/qcom/camcc-sdm845.c b/drivers/clk/qcom/camcc-sdm845.c
index 84e9698..6296c40 100644
--- a/drivers/clk/qcom/camcc-sdm845.c
+++ b/drivers/clk/qcom/camcc-sdm845.c
@@ -1115,19 +1115,6 @@
 	},
 };
 
-static struct clk_branch cam_cc_debug_clk = {
-	.halt_reg = 0xc008,
-	.halt_check = BRANCH_HALT,
-	.clkr = {
-		.enable_reg = 0xc008,
-		.enable_mask = BIT(0),
-		.hw.init = &(struct clk_init_data){
-			.name = "cam_cc_debug_clk",
-			.ops = &clk_branch2_ops,
-		},
-	},
-};
-
 static struct clk_branch cam_cc_fd_core_clk = {
 	.halt_reg = 0xb0c8,
 	.halt_check = BRANCH_HALT,
@@ -1764,7 +1751,6 @@
 	[CAM_CC_CSIPHY0_CLK] = &cam_cc_csiphy0_clk.clkr,
 	[CAM_CC_CSIPHY1_CLK] = &cam_cc_csiphy1_clk.clkr,
 	[CAM_CC_CSIPHY2_CLK] = &cam_cc_csiphy2_clk.clkr,
-	[CAM_CC_DEBUG_CLK] = &cam_cc_debug_clk.clkr,
 	[CAM_CC_FAST_AHB_CLK_SRC] = &cam_cc_fast_ahb_clk_src.clkr,
 	[CAM_CC_FD_CORE_CLK] = &cam_cc_fd_core_clk.clkr,
 	[CAM_CC_FD_CORE_CLK_SRC] = &cam_cc_fd_core_clk_src.clkr,
diff --git a/drivers/clk/qcom/dispcc-sdm845.c b/drivers/clk/qcom/dispcc-sdm845.c
index 20ce78b..3b56fa1 100644
--- a/drivers/clk/qcom/dispcc-sdm845.c
+++ b/drivers/clk/qcom/dispcc-sdm845.c
@@ -478,19 +478,6 @@
 	},
 };
 
-static struct clk_branch disp_cc_debug_clk = {
-	.halt_reg = 0x600c,
-	.halt_check = BRANCH_HALT,
-	.clkr = {
-		.enable_reg = 0x600c,
-		.enable_mask = BIT(0),
-		.hw.init = &(struct clk_init_data){
-			.name = "disp_cc_debug_clk",
-			.ops = &clk_branch2_ops,
-		},
-	},
-};
-
 static struct clk_branch disp_cc_mdss_ahb_clk = {
 	.halt_reg = 0x4004,
 	.halt_check = BRANCH_HALT,
@@ -949,7 +936,6 @@
 };
 
 static struct clk_regmap *disp_cc_sdm845_clocks[] = {
-	[DISP_CC_DEBUG_CLK] = &disp_cc_debug_clk.clkr,
 	[DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr,
 	[DISP_CC_MDSS_AXI_CLK] = &disp_cc_mdss_axi_clk.clkr,
 	[DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr,
diff --git a/drivers/clk/qcom/gcc-sdm845.c b/drivers/clk/qcom/gcc-sdm845.c
index 5fcb1f5..4824546 100644
--- a/drivers/clk/qcom/gcc-sdm845.c
+++ b/drivers/clk/qcom/gcc-sdm845.c
@@ -1468,19 +1468,6 @@
 	},
 };
 
-static struct clk_branch gcc_cxo_tx1_clkref_clk = {
-	.halt_reg = 0x8c020,
-	.halt_check = BRANCH_HALT,
-	.clkr = {
-		.enable_reg = 0x8c020,
-		.enable_mask = BIT(0),
-		.hw.init = &(struct clk_init_data){
-			.name = "gcc_cxo_tx1_clkref_clk",
-			.ops = &clk_branch2_ops,
-		},
-	},
-};
-
 static struct clk_branch gcc_ddrss_gpu_axi_clk = {
 	.halt_reg = 0x44038,
 	.halt_check = BRANCH_VOTED,
@@ -2433,32 +2420,6 @@
 	},
 };
 
-static struct clk_branch gcc_rx1_usb2_clkref_clk = {
-	.halt_reg = 0x8c014,
-	.halt_check = BRANCH_HALT,
-	.clkr = {
-		.enable_reg = 0x8c014,
-		.enable_mask = BIT(0),
-		.hw.init = &(struct clk_init_data){
-			.name = "gcc_rx1_usb2_clkref_clk",
-			.ops = &clk_branch2_ops,
-		},
-	},
-};
-
-static struct clk_branch gcc_rx2_qlink_clkref_clk = {
-	.halt_reg = 0x8c018,
-	.halt_check = BRANCH_HALT,
-	.clkr = {
-		.enable_reg = 0x8c018,
-		.enable_mask = BIT(0),
-		.hw.init = &(struct clk_init_data){
-			.name = "gcc_rx2_qlink_clkref_clk",
-			.ops = &clk_branch2_ops,
-		},
-	},
-};
-
 static struct clk_branch gcc_sdcc2_ahb_clk = {
 	.halt_reg = 0x14008,
 	.halt_check = BRANCH_HALT,
@@ -3151,7 +3112,6 @@
 	[GCC_CPUSS_GNOC_CLK] = &gcc_cpuss_gnoc_clk.clkr,
 	[GCC_CPUSS_RBCPR_CLK] = &gcc_cpuss_rbcpr_clk.clkr,
 	[GCC_CPUSS_RBCPR_CLK_SRC] = &gcc_cpuss_rbcpr_clk_src.clkr,
-	[GCC_CXO_TX1_CLKREF_CLK] = &gcc_cxo_tx1_clkref_clk.clkr,
 	[GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr,
 	[GCC_DISP_AHB_CLK] = &gcc_disp_ahb_clk.clkr,
 	[GCC_DISP_AXI_CLK] = &gcc_disp_axi_clk.clkr,
@@ -3238,8 +3198,6 @@
 	[GCC_QUPV3_WRAP_0_S_AHB_CLK] = &gcc_qupv3_wrap_0_s_ahb_clk.clkr,
 	[GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.clkr,
 	[GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.clkr,
-	[GCC_RX1_USB2_CLKREF_CLK] = &gcc_rx1_usb2_clkref_clk.clkr,
-	[GCC_RX2_QLINK_CLKREF_CLK] = &gcc_rx2_qlink_clkref_clk.clkr,
 	[GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr,
 	[GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr,
 	[GCC_SDCC2_APPS_CLK_SRC] = &gcc_sdcc2_apps_clk_src.clkr,
diff --git a/drivers/clk/qcom/gpucc-sdm845.c b/drivers/clk/qcom/gpucc-sdm845.c
index d9a626e..0115bb1 100644
--- a/drivers/clk/qcom/gpucc-sdm845.c
+++ b/drivers/clk/qcom/gpucc-sdm845.c
@@ -413,19 +413,6 @@
 	},
 };
 
-static struct clk_branch gpu_cc_debug_clk = {
-	.halt_reg = 0x1100,
-	.halt_check = BRANCH_HALT,
-	.clkr = {
-		.enable_reg = 0x1100,
-		.enable_mask = BIT(0),
-		.hw.init = &(struct clk_init_data){
-			.name = "gpu_cc_debug_clk",
-			.ops = &clk_branch2_ops,
-		},
-	},
-};
-
 static struct clk_branch gpu_cc_gx_cxo_clk = {
 	.halt_reg = 0x1060,
 	.halt_check = BRANCH_HALT,
@@ -544,7 +531,6 @@
 	[GPU_CC_CX_SNOC_DVM_CLK] = &gpu_cc_cx_snoc_dvm_clk.clkr,
 	[GPU_CC_CXO_AON_CLK] = &gpu_cc_cxo_aon_clk.clkr,
 	[GPU_CC_CXO_CLK] = &gpu_cc_cxo_clk.clkr,
-	[GPU_CC_DEBUG_CLK] = &gpu_cc_debug_clk.clkr,
 	[GPU_CC_GMU_CLK_SRC] = &gpu_cc_gmu_clk_src.clkr,
 	[GPU_CC_GX_CXO_CLK] = &gpu_cc_gx_cxo_clk.clkr,
 	[GPU_CC_GX_GMU_CLK] = &gpu_cc_gx_gmu_clk.clkr,
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
index 6ce0d76..3daefbc 100644
--- a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
@@ -40,6 +40,8 @@
 #define PLL_CALIBRATION_SETTINGS		0x030
 #define PLL_BAND_SEL_CAL_SETTINGS_THREE		0x054
 #define PLL_FREQ_DETECT_SETTINGS_ONE		0x064
+#define PLL_PFILT				0x07c
+#define PLL_IFILT				0x080
 #define PLL_OUTDIV				0x094
 #define PLL_CORE_OVERRIDE			0x0a4
 #define PLL_CORE_INPUT_OVERRIDE			0x0a8
@@ -63,6 +65,7 @@
 #define PLL_PLL_FL_INT_GAIN_PFILT_BAND_1	0x164
 #define PLL_PLL_LOCK_OVERRIDE			0x180
 #define PLL_PLL_LOCK_DELAY			0x184
+#define PLL_CLOCK_INVERTERS			0x18c
 #define PLL_COMMON_STATUS_ONE			0x1a0
 
 /* Register Offsets from PHY base address */
@@ -338,7 +341,6 @@
 	MDSS_PLL_REG_W(pll_base, PLL_ANALOG_CONTROLS_THREE, 0x00);
 	MDSS_PLL_REG_W(pll_base, PLL_DSM_DIVIDER, 0x00);
 	MDSS_PLL_REG_W(pll_base, PLL_FEEDBACK_DIVIDER, 0x4e);
-	MDSS_PLL_REG_W(pll_base, PLL_CMODE, 0x00);
 	MDSS_PLL_REG_W(pll_base, PLL_CALIBRATION_SETTINGS, 0x40);
 	MDSS_PLL_REG_W(pll_base, PLL_BAND_SEL_CAL_SETTINGS_THREE, 0xba);
 	MDSS_PLL_REG_W(pll_base, PLL_FREQ_DETECT_SETTINGS_ONE, 0x0c);
@@ -347,9 +349,11 @@
 	MDSS_PLL_REG_W(pll_base, PLL_PLL_DIGITAL_TIMERS_TWO, 0x08);
 	MDSS_PLL_REG_W(pll_base, PLL_PLL_PROP_GAIN_RATE_1, 0x08);
 	MDSS_PLL_REG_W(pll_base, PLL_PLL_BAND_SET_RATE_1, 0xc0);
-	MDSS_PLL_REG_W(pll_base, PLL_PLL_INT_GAIN_IFILT_BAND_1, 0x82);
+	MDSS_PLL_REG_W(pll_base, PLL_PLL_INT_GAIN_IFILT_BAND_1, 0xfa);
 	MDSS_PLL_REG_W(pll_base, PLL_PLL_FL_INT_GAIN_PFILT_BAND_1, 0x4c);
 	MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_OVERRIDE, 0x80);
+	MDSS_PLL_REG_W(pll_base, PLL_PFILT, 0x29);
+	MDSS_PLL_REG_W(pll_base, PLL_IFILT, 0x3f);
 }
 
 static void dsi_pll_commit(struct dsi_pll_10nm *pll,
@@ -367,9 +371,11 @@
 		       reg->frac_div_start_mid);
 	MDSS_PLL_REG_W(pll_base, PLL_FRAC_DIV_START_HIGH_1,
 		       reg->frac_div_start_high);
-	MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCKDET_RATE_1, 0xc8);
+	MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCKDET_RATE_1, 0x40);
 	MDSS_PLL_REG_W(pll_base, PLL_PLL_OUTDIV_RATE, reg->pll_outdiv_rate);
-	MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_DELAY, 0x0a);
+	MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_DELAY, 0x06);
+	MDSS_PLL_REG_W(pll_base, PLL_CMODE, 0x10);
+	MDSS_PLL_REG_W(pll_base, PLL_CLOCK_INVERTERS, 0x0);
 
 }
 
@@ -450,8 +456,8 @@
 {
 	u32 data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CTRL_0);
 
-	MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data & ~BIT(5));
 	MDSS_PLL_REG_W(rsc->pll_base, PLL_SYSTEM_MUXES, 0);
+	MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CTRL_0, data & ~BIT(5));
 	ndelay(250);
 }
 
@@ -464,6 +470,22 @@
 	ndelay(250);
 }
 
+static void dsi_pll_disable_global_clk(struct mdss_pll_resources *rsc)
+{
+	u32 data;
+
+	data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1);
+	MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data & ~BIT(5)));
+}
+
+static void dsi_pll_enable_global_clk(struct mdss_pll_resources *rsc)
+{
+	u32 data;
+
+	data = MDSS_PLL_REG_R(rsc->phy_base, PHY_CMN_CLK_CFG1);
+	MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_CLK_CFG1, (data | BIT(5)));
+}
+
 static int dsi_pll_enable(struct dsi_pll_vco_clk *vco)
 {
 	int rc;
@@ -490,6 +512,11 @@
 	}
 
 	rsc->pll_on = true;
+
+	dsi_pll_enable_global_clk(rsc);
+	if (rsc->slave)
+		dsi_pll_enable_global_clk(rsc->slave);
+
 	MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_RBUF_CTRL, 0x01);
 	if (rsc->slave)
 		MDSS_PLL_REG_W(rsc->slave->phy_base, PHY_CMN_RBUF_CTRL, 0x01);
@@ -500,8 +527,9 @@
 
 static void dsi_pll_disable_sub(struct mdss_pll_resources *rsc)
 {
-	dsi_pll_disable_pll_bias(rsc);
+	dsi_pll_disable_global_clk(rsc);
 	MDSS_PLL_REG_W(rsc->phy_base, PHY_CMN_RBUF_CTRL, 0);
+	dsi_pll_disable_pll_bias(rsc);
 }
 
 static void dsi_pll_disable(struct dsi_pll_vco_clk *vco)
@@ -613,6 +641,9 @@
 	u32 outdiv;
 	u64 pll_freq, tmp64;
 
+	if (!vco->priv)
+		pr_err("vco priv is null\n");
+
 	rc = mdss_pll_resource_enable(pll, true);
 	if (rc) {
 		pr_err("failed to enable pll(%d) resource, rc=%d\n",
@@ -671,9 +702,11 @@
 	reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0);
 	*div = (reg_val & 0xF0) >> 4;
 
-	if (*div == 0)
-		*div = 1;
-	else
+	/**
+	 * Common clock framework the divider value is interpreted as one less
+	 * hence we return one less for all dividers except when zero
+	 */
+	if (*div != 0)
 		*div -= 1;
 
 	(void)mdss_pll_resource_enable(pll, false);
@@ -701,13 +734,15 @@
 		pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
 		return rc;
 	}
-	/* In common clock framework the divider value provided is one less */
+	/**
+	 * In common clock framework the divider value provided is one less and
+	 * and hence adjusting the divider value by one prior to writing it to
+	 * hardware
+	 */
 	div++;
-
 	pixel_clk_set_div_sub(pll, div);
 	if (pll->slave)
 		pixel_clk_set_div_sub(pll->slave, div);
-
 	(void)mdss_pll_resource_enable(pll, false);
 
 	return 0;
@@ -728,12 +763,12 @@
 	reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0);
 	*div = (reg_val & 0x0F);
 
-	/* Common clock framework will add one to divider value sent */
-	if (*div == 0)
-		*div = 1;
-	else
+	/**
+	 *Common clock framework the divider value is interpreted as one less
+	 * hence we return one less for all dividers except when zero
+	 */
+	if (*div != 0)
 		*div -= 1;
-
 	(void)mdss_pll_resource_enable(pll, false);
 
 	return rc;
@@ -771,6 +806,12 @@
 		pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
 		return rc;
 	}
+
+	/**
+	 * In common clock framework the divider value provided is one less and
+	 * and hence adjusting the divider value by one prior to writing it to
+	 * hardware
+	 */
 	div++;
 
 	bit_clk_set_div_sub(rsc, div);
@@ -806,9 +847,11 @@
 	else
 		*div = 1;
 
-	if (*div == 0)
-		*div = 1;
-	else
+	/**
+	 *Common clock framework the divider value is interpreted as one less
+	 * hence we return one less for all dividers except when zero
+	 */
+	if (*div != 0)
 		*div -= 1;
 
 	(void)mdss_pll_resource_enable(pll, false);
@@ -851,8 +894,12 @@
 		return rc;
 	}
 
+	/**
+	 * In common clock framework the divider value provided is one less and
+	 * and hence adjusting the divider value by one prior to writing it to
+	 * hardware
+	 */
 	div++;
-
 	rc = post_vco_clk_set_div_sub(pll, div);
 	if (!rc && pll->slave)
 		rc = post_vco_clk_set_div_sub(pll->slave, div);
@@ -885,9 +932,11 @@
 	else
 		*div = 1;
 
-	if (*div == 0)
-		*div = 1;
-	else
+	/**
+	 *Common clock framework the divider value is interpreted as one less
+	 * hence we return one less for all dividers except when zero
+	 */
+	if (*div != 0)
 		*div -= 1;
 
 	(void)mdss_pll_resource_enable(pll, false);
@@ -930,8 +979,12 @@
 		return rc;
 	}
 
+	/**
+	 * In common clock framework the divider value provided is one less and
+	 * and hence adjusting the divider value by one prior to writing it to
+	 * hardware
+	 */
 	div++;
-
 	rc = post_bit_clk_set_div_sub(pll, div);
 	if (!rc && pll->slave)
 		rc = post_bit_clk_set_div_sub(pll->slave, div);
@@ -1057,7 +1110,6 @@
 };
 
 static struct clk_regmap_div dsi0pll_bitclk_src = {
-	.reg = 0x48,
 	.shift = 0,
 	.width = 4,
 	.clkr = {
@@ -1072,7 +1124,6 @@
 };
 
 static struct clk_regmap_div dsi1pll_bitclk_src = {
-	.reg = 0x48,
 	.shift = 0,
 	.width = 4,
 	.clkr = {
@@ -1087,9 +1138,8 @@
 };
 
 static struct clk_regmap_div dsi0pll_post_vco_div = {
-	.reg = 0x48,
 	.shift = 0,
-	.width = 4,
+	.width = 2,
 	.clkr = {
 		.hw.init = &(struct clk_init_data){
 			.name = "dsi0pll_post_vco_div",
@@ -1102,9 +1152,8 @@
 };
 
 static struct clk_regmap_div dsi1pll_post_vco_div = {
-	.reg = 0x48,
 	.shift = 0,
-	.width = 4,
+	.width = 2,
 	.clkr = {
 		.hw.init = &(struct clk_init_data){
 			.name = "dsi1pll_post_vco_div",
@@ -1141,9 +1190,8 @@
 };
 
 static struct clk_regmap_div dsi0pll_post_bit_div = {
-	.reg = 0x48,
 	.shift = 0,
-	.width = 4,
+	.width = 1,
 	.clkr = {
 		.hw.init = &(struct clk_init_data){
 			.name = "dsi0pll_post_bit_div",
@@ -1156,9 +1204,8 @@
 };
 
 static struct clk_regmap_div dsi1pll_post_bit_div = {
-	.reg = 0x48,
 	.shift = 0,
-	.width = 4,
+	.width = 1,
 	.clkr = {
 		.hw.init = &(struct clk_init_data){
 			.name = "dsi1pll_post_bit_div",
@@ -1171,12 +1218,11 @@
 };
 
 static struct clk_regmap_mux dsi0pll_byteclk_mux = {
-	.reg = 0x48,
 	.shift = 0,
-	.width = 4,
+	.width = 0,
 	.clkr = {
 		.hw.init = &(struct clk_init_data){
-			.name = "dsi0pll_byteclk_mux",
+			.name = "dsi0_phy_pll_out_byteclk",
 			.parent_names = (const char *[]){"dsi0pll_byteclk_src"},
 			.num_parents = 1,
 			.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
@@ -1186,12 +1232,11 @@
 };
 
 static struct clk_regmap_mux dsi1pll_byteclk_mux = {
-	.reg = 0x48,
 	.shift = 0,
-	.width = 4,
+	.width = 0,
 	.clkr = {
 		.hw.init = &(struct clk_init_data){
-			.name = "dsi1pll_byteclk_mux",
+			.name = "dsi1_phy_pll_out_byteclk",
 			.parent_names = (const char *[]){"dsi1pll_byteclk_src"},
 			.num_parents = 1,
 			.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
@@ -1201,15 +1246,14 @@
 };
 
 static struct clk_regmap_mux dsi0pll_pclk_src_mux = {
-	.reg = 0x48,
 	.shift = 0,
-	.width = 4,
+	.width = 0,
 	.clkr = {
 		.hw.init = &(struct clk_init_data){
 			.name = "dsi0pll_pclk_src_mux",
 			.parent_names = (const char *[]){"dsi0pll_post_bit_div",
-						"dsi0pll_post_bit_div"},
-			.num_parents = 1,
+						"dsi0pll_post_vco_div"},
+			.num_parents = 2,
 			.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
 			.ops = &clk_regmap_mux_closest_ops,
 		},
@@ -1217,15 +1261,14 @@
 };
 
 static struct clk_regmap_mux dsi1pll_pclk_src_mux = {
-	.reg = 0x48,
 	.shift = 0,
-	.width = 4,
+	.width = 0,
 	.clkr = {
 		.hw.init = &(struct clk_init_data){
 			.name = "dsi1pll_pclk_src_mux",
 			.parent_names = (const char *[]){"dsi1pll_post_bit_div",
-						"dsi1pll_post_bit_div"},
-			.num_parents = 1,
+						"dsi1pll_post_vco_div"},
+			.num_parents = 2,
 			.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
 			.ops = &clk_regmap_mux_closest_ops,
 		},
@@ -1233,7 +1276,6 @@
 };
 
 static struct clk_regmap_div dsi0pll_pclk_src = {
-	.reg = 0x48,
 	.shift = 0,
 	.width = 4,
 	.clkr = {
@@ -1249,7 +1291,6 @@
 };
 
 static struct clk_regmap_div dsi1pll_pclk_src = {
-	.reg = 0x48,
 	.shift = 0,
 	.width = 4,
 	.clkr = {
@@ -1265,12 +1306,11 @@
 };
 
 static struct clk_regmap_mux dsi0pll_pclk_mux = {
-	.reg = 0x48,
 	.shift = 0,
-	.width = 4,
+	.width = 0,
 	.clkr = {
 		.hw.init = &(struct clk_init_data){
-			.name = "dsi0pll_pclk_mux",
+			.name = "dsi0_phy_pll_out_dsiclk",
 			.parent_names = (const char *[]){"dsi0pll_pclk_src"},
 			.num_parents = 1,
 			.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
@@ -1280,12 +1320,11 @@
 };
 
 static struct clk_regmap_mux dsi1pll_pclk_mux = {
-	.reg = 0x48,
 	.shift = 0,
-	.width = 4,
+	.width = 0,
 	.clkr = {
 		.hw.init = &(struct clk_init_data){
-			.name = "dsi1pll_pclk_mux",
+			.name = "dsi1_phy_pll_out_dsiclk",
 			.parent_names = (const char *[]){"dsi1pll_pclk_src"},
 			.num_parents = 1,
 			.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
@@ -1339,8 +1378,8 @@
 	}
 
 	pll_rsc_db[ndx] = pll_res;
-	pll_res->priv = &plls[ndx];
 	plls[ndx].rsc = pll_res;
+	pll_res->priv = &plls[ndx];
 	pll_res->vco_delay = VCO_DELAY_USEC;
 
 	clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data),
@@ -1386,6 +1425,7 @@
 				pll_res, &dsi_pll_10nm_config);
 		dsi0pll_byteclk_mux.clkr.regmap = rmap;
 
+		dsi0pll_vco_clk.priv = pll_res;
 		for (i = VCO_CLK_0; i <= PCLK_MUX_0_CLK; i++) {
 			clk = devm_clk_register(&pdev->dev,
 						mdss_dsi_pllcc_10nm[i]);
@@ -1431,6 +1471,7 @@
 		rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
 				pll_res, &dsi_pll_10nm_config);
 		dsi1pll_byteclk_mux.clkr.regmap = rmap;
+		dsi1pll_vco_clk.priv = pll_res;
 
 		for (i = VCO_CLK_1; i <= PCLK_MUX_1_CLK; i++) {
 			clk = devm_clk_register(&pdev->dev,
diff --git a/drivers/clk/qcom/mdss/mdss-pll.c b/drivers/clk/qcom/mdss/mdss-pll.c
index 0a0d303..7f82fda 100644
--- a/drivers/clk/qcom/mdss/mdss-pll.c
+++ b/drivers/clk/qcom/mdss/mdss-pll.c
@@ -150,6 +150,7 @@
 	switch (pll_res->pll_interface_type) {
 	case MDSS_DSI_PLL_10NM:
 		rc = dsi_pll_clock_register_10nm(pdev, pll_res);
+		break;
 	case MDSS_UNKNOWN_PLL:
 	default:
 		rc = -EINVAL;
@@ -370,7 +371,7 @@
 
 	return rc;
 }
-subsys_initcall(mdss_pll_driver_init);
+fs_initcall(mdss_pll_driver_init);
 
 static void __exit mdss_pll_driver_deinit(void)
 {
diff --git a/drivers/clk/qcom/mdss/mdss-pll.h b/drivers/clk/qcom/mdss/mdss-pll.h
index 28b7ca6..eccfcea 100644
--- a/drivers/clk/qcom/mdss/mdss-pll.h
+++ b/drivers/clk/qcom/mdss/mdss-pll.h
@@ -194,9 +194,7 @@
 		WARN(1, "gdsc_base register is not defined\n");
 		return true;
 	}
-
-	return ((readl_relaxed(pll_res->gdsc_base + 0x4) & BIT(31)) &&
-		(!(readl_relaxed(pll_res->gdsc_base) & BIT(0)))) ? false : true;
+	return readl_relaxed(pll_res->gdsc_base) & BIT(31) ? false : true;
 }
 
 static inline int mdss_pll_div_prepare(struct clk_hw *hw)
diff --git a/drivers/clk/qcom/videocc-sdm845.c b/drivers/clk/qcom/videocc-sdm845.c
index 8b63979..4eb8a04 100644
--- a/drivers/clk/qcom/videocc-sdm845.c
+++ b/drivers/clk/qcom/videocc-sdm845.c
@@ -151,19 +151,6 @@
 	},
 };
 
-static struct clk_branch video_cc_debug_clk = {
-	.halt_reg = 0xa58,
-	.halt_check = BRANCH_HALT,
-	.clkr = {
-		.enable_reg = 0xa58,
-		.enable_mask = BIT(0),
-		.hw.init = &(struct clk_init_data){
-			.name = "video_cc_debug_clk",
-			.ops = &clk_branch2_ops,
-		},
-	},
-};
-
 static struct clk_branch video_cc_qdss_trig_clk = {
 	.halt_reg = 0x970,
 	.halt_check = BRANCH_HALT,
@@ -299,7 +286,6 @@
 static struct clk_regmap *video_cc_sdm845_clocks[] = {
 	[VIDEO_CC_APB_CLK] = &video_cc_apb_clk.clkr,
 	[VIDEO_CC_AT_CLK] = &video_cc_at_clk.clkr,
-	[VIDEO_CC_DEBUG_CLK] = &video_cc_debug_clk.clkr,
 	[VIDEO_CC_QDSS_TRIG_CLK] = &video_cc_qdss_trig_clk.clkr,
 	[VIDEO_CC_QDSS_TSCTR_DIV8_CLK] = &video_cc_qdss_tsctr_div8_clk.clkr,
 	[VIDEO_CC_VCODEC0_AXI_CLK] = &video_cc_vcodec0_axi_clk.clkr,
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 5b85b8d..8f582f6 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -70,6 +70,29 @@
 }
 
 /**
+ * devfreq_set_freq_limits() - Set min and max frequency from freq_table
+ * @devfreq:	the devfreq instance
+ */
+static void devfreq_set_freq_limits(struct devfreq *devfreq)
+{
+	int idx;
+	unsigned long min = ~0, max = 0;
+
+	if (!devfreq->profile->freq_table)
+		return;
+
+	for (idx = 0; idx < devfreq->profile->max_state; idx++) {
+		if (min > devfreq->profile->freq_table[idx])
+			min = devfreq->profile->freq_table[idx];
+		if (max < devfreq->profile->freq_table[idx])
+			max = devfreq->profile->freq_table[idx];
+	}
+
+	devfreq->min_freq = min;
+	devfreq->max_freq = max;
+}
+
+/**
  * devfreq_get_freq_level() - Lookup freq_table for the frequency
  * @devfreq:	the devfreq instance
  * @freq:	the target frequency
@@ -569,6 +592,7 @@
 		devfreq_set_freq_table(devfreq);
 		mutex_lock(&devfreq->lock);
 	}
+	devfreq_set_freq_limits(devfreq);
 
 	dev_set_name(&devfreq->dev, "%s", dev_name(dev));
 	err = device_register(&devfreq->dev);
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index b5d78b1..4112bef 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -109,6 +109,7 @@
 				dsi-staging/dsi_ctrl_hw_cmn.o \
 				dsi-staging/dsi_ctrl_hw_1_4.o \
 				dsi-staging/dsi_ctrl_hw_2_0.o \
+				dsi-staging/dsi_ctrl_hw_2_2.o \
 				dsi-staging/dsi_ctrl.o \
 				dsi-staging/dsi_catalog.o \
 				dsi-staging/dsi_drm.o \
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
index 976be99..3625ed0 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
@@ -83,6 +83,19 @@
 		ctrl->ops.clamp_enable = NULL;
 		ctrl->ops.clamp_disable = NULL;
 		break;
+	case DSI_CTRL_VERSION_2_2:
+		ctrl->ops.phy_reset_config = dsi_ctrl_hw_22_phy_reset_config;
+		ctrl->ops.setup_lane_map = dsi_ctrl_hw_20_setup_lane_map;
+		ctrl->ops.wait_for_lane_idle =
+			dsi_ctrl_hw_20_wait_for_lane_idle;
+		ctrl->ops.reg_dump_to_buffer =
+			dsi_ctrl_hw_20_reg_dump_to_buffer;
+		ctrl->ops.ulps_ops.ulps_request = NULL;
+		ctrl->ops.ulps_ops.ulps_exit = NULL;
+		ctrl->ops.ulps_ops.get_lanes_in_ulps = NULL;
+		ctrl->ops.clamp_enable = NULL;
+		ctrl->ops.clamp_disable = NULL;
+		break;
 	default:
 		break;
 	}
@@ -121,6 +134,7 @@
 	switch (version) {
 	case DSI_CTRL_VERSION_1_4:
 	case DSI_CTRL_VERSION_2_0:
+	case DSI_CTRL_VERSION_2_2:
 		dsi_catalog_cmn_init(ctrl, version);
 		break;
 	default:
@@ -167,6 +181,8 @@
 		dsi_phy_hw_v3_0_ulps_exit;
 	phy->ops.ulps_ops.get_lanes_in_ulps =
 		dsi_phy_hw_v3_0_get_lanes_in_ulps;
+	phy->ops.ulps_ops.is_lanes_in_ulps =
+		dsi_phy_hw_v3_0_is_lanes_in_ulps;
 	phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v3_0;
 }
 
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
index 4a6a934..5dcdf46 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
@@ -97,6 +97,7 @@
 void dsi_phy_hw_v3_0_ulps_exit(struct dsi_phy_hw *phy,
 			struct dsi_phy_cfg *cfg, u32 lanes);
 u32 dsi_phy_hw_v3_0_get_lanes_in_ulps(struct dsi_phy_hw *phy);
+bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes);
 int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg,
 		u32 *timing_val, u32 size);
 
@@ -157,6 +158,8 @@
 void dsi_ctrl_hw_dln0_phy_err(struct dsi_ctrl_hw *ctrl);
 void dsi_ctrl_hw_cmn_phy_reset_config(struct dsi_ctrl_hw *ctrl,
 			bool enable);
+void dsi_ctrl_hw_22_phy_reset_config(struct dsi_ctrl_hw *ctrl,
+			bool enable);
 
 /* Definitions specific to 1.4 DSI controller hardware */
 int dsi_ctrl_hw_14_wait_for_lane_idle(struct dsi_ctrl_hw *ctrl, u32 lanes);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
index cc87775..560964e 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
@@ -236,32 +236,52 @@
 	return rc;
 
 error_disable_mmss_clk:
-	clk_disable_unprepare(c_clks->clks.core_mmss_clk);
+	if (c_clks->clks.core_mmss_clk)
+		clk_disable_unprepare(c_clks->clks.core_mmss_clk);
 error_disable_bus_clk:
-	clk_disable_unprepare(c_clks->clks.bus_clk);
+	if (c_clks->clks.bus_clk)
+		clk_disable_unprepare(c_clks->clks.bus_clk);
 error_disable_iface_clk:
-	clk_disable_unprepare(c_clks->clks.iface_clk);
+	if (c_clks->clks.iface_clk)
+		clk_disable_unprepare(c_clks->clks.iface_clk);
 error_disable_mnoc_clk:
 	if (c_clks->clks.mnoc_clk)
 		clk_disable_unprepare(c_clks->clks.mnoc_clk);
 error_disable_core_clk:
-	clk_disable_unprepare(c_clks->clks.mdp_core_clk);
+	if (c_clks->clks.mdp_core_clk)
+		clk_disable_unprepare(c_clks->clks.mdp_core_clk);
 error:
 	return rc;
 }
 
 int dsi_core_clk_stop(struct dsi_core_clks *c_clks)
 {
-	if (msm_bus_scale_client_update_request(c_clks->bus_handle, 0))
-		pr_err("bus scale client disable failed\n");
-	clk_disable_unprepare(c_clks->clks.core_mmss_clk);
-	clk_disable_unprepare(c_clks->clks.bus_clk);
-	clk_disable_unprepare(c_clks->clks.iface_clk);
+	int rc = 0;
+
+	if (c_clks->bus_handle) {
+		rc = msm_bus_scale_client_update_request(c_clks->bus_handle, 0);
+		if (rc) {
+			pr_err("bus scale client disable failed, rc=%d\n", rc);
+			return rc;
+		}
+	}
+
+	if (c_clks->clks.core_mmss_clk)
+		clk_disable_unprepare(c_clks->clks.core_mmss_clk);
+
+	if (c_clks->clks.bus_clk)
+		clk_disable_unprepare(c_clks->clks.bus_clk);
+
+	if (c_clks->clks.iface_clk)
+		clk_disable_unprepare(c_clks->clks.iface_clk);
+
 	if (c_clks->clks.mnoc_clk)
 		clk_disable_unprepare(c_clks->clks.mnoc_clk);
-	clk_disable_unprepare(c_clks->clks.mdp_core_clk);
 
-	return 0;
+	if (c_clks->clks.mdp_core_clk)
+		clk_disable_unprepare(c_clks->clks.mdp_core_clk);
+
+	return rc;
 }
 
 static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 5df48c3..9a71ea0 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -62,6 +62,7 @@
 
 static const enum dsi_ctrl_version dsi_ctrl_v1_4 = DSI_CTRL_VERSION_1_4;
 static const enum dsi_ctrl_version dsi_ctrl_v2_0 = DSI_CTRL_VERSION_2_0;
+static const enum dsi_ctrl_version dsi_ctrl_v2_2 = DSI_CTRL_VERSION_2_2;
 
 static const struct of_device_id msm_dsi_of_match[] = {
 	{
@@ -72,6 +73,10 @@
 		.compatible = "qcom,dsi-ctrl-hw-v2.0",
 		.data = &dsi_ctrl_v2_0,
 	},
+	{
+		.compatible = "qcom,dsi-ctrl-hw-v2.2",
+		.data = &dsi_ctrl_v2_2,
+	},
 	{}
 };
 
@@ -428,15 +433,34 @@
 	pr_debug("[%s] map dsi_ctrl registers to %p\n", ctrl->name,
 		 ctrl->hw.base);
 
-	ptr = msm_ioremap(pdev, "mmss_misc", ctrl->name);
-	if (IS_ERR(ptr)) {
-		rc = PTR_ERR(ptr);
-		return rc;
+	switch (ctrl->version) {
+	case DSI_CTRL_VERSION_1_4:
+	case DSI_CTRL_VERSION_2_0:
+		ptr = msm_ioremap(pdev, "mmss_misc", ctrl->name);
+		if (IS_ERR(ptr)) {
+			pr_err("mmss_misc base address not found for [%s]\n",
+					ctrl->name);
+			rc = PTR_ERR(ptr);
+			return rc;
+		}
+		ctrl->hw.mmss_misc_base = ptr;
+		ctrl->hw.disp_cc_base = NULL;
+		break;
+	case DSI_CTRL_VERSION_2_2:
+		ptr = msm_ioremap(pdev, "disp_cc_base", ctrl->name);
+		if (IS_ERR(ptr)) {
+			pr_err("disp_cc base address not found for [%s]\n",
+					ctrl->name);
+			rc = PTR_ERR(ptr);
+			return rc;
+		}
+		ctrl->hw.disp_cc_base = ptr;
+		ctrl->hw.mmss_misc_base = NULL;
+		break;
+	default:
+		break;
 	}
 
-	ctrl->hw.mmss_misc_base = ptr;
-	pr_debug("[%s] map mmss_misc registers to %p\n", ctrl->name,
-		 ctrl->hw.mmss_misc_base);
 	return rc;
 }
 
@@ -532,7 +556,7 @@
 		goto fail;
 	}
 
-	link->esc_clk = devm_clk_get(&pdev->dev, "core_clk");
+	link->esc_clk = devm_clk_get(&pdev->dev, "esc_clk");
 	if (IS_ERR(link->esc_clk)) {
 		rc = PTR_ERR(link->esc_clk);
 		pr_err("failed to get esc_clk, rc=%d\n", rc);
@@ -613,10 +637,8 @@
 	rc = dsi_pwr_get_dt_vreg_data(&pdev->dev,
 					  &ctrl->pwr_info.digital,
 					  "qcom,core-supply-entries");
-	if (rc) {
-		pr_err("failed to get digital supply, rc = %d\n", rc);
-		goto error;
-	}
+	if (rc)
+		pr_debug("failed to get digital supply, rc = %d\n", rc);
 
 	rc = dsi_pwr_get_dt_vreg_data(&pdev->dev,
 					  &ctrl->pwr_info.host_pwr,
@@ -663,10 +685,10 @@
 	ctrl->pwr_info.host_pwr.vregs = NULL;
 	ctrl->pwr_info.host_pwr.count = 0;
 error_digital:
-	devm_kfree(&pdev->dev, ctrl->pwr_info.digital.vregs);
+	if (ctrl->pwr_info.digital.vregs)
+		devm_kfree(&pdev->dev, ctrl->pwr_info.digital.vregs);
 	ctrl->pwr_info.digital.vregs = NULL;
 	ctrl->pwr_info.digital.count = 0;
-error:
 	return rc;
 }
 
@@ -1204,6 +1226,7 @@
 	}
 
 	dsi_ctrl->cell_index = index;
+	dsi_ctrl->version = version;
 
 	dsi_ctrl->name = of_get_property(pdev->dev.of_node, "label", NULL);
 	if (!dsi_ctrl->name)
@@ -1227,7 +1250,6 @@
 		goto fail_clks;
 	}
 
-	dsi_ctrl->version = version;
 	rc = dsi_catalog_ctrl_setup(&dsi_ctrl->hw, dsi_ctrl->version,
 				    dsi_ctrl->cell_index);
 	if (rc) {
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
index 161024a..859d707 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
@@ -41,6 +41,7 @@
 	DSI_CTRL_VERSION_UNKNOWN,
 	DSI_CTRL_VERSION_1_4,
 	DSI_CTRL_VERSION_2_0,
+	DSI_CTRL_VERSION_2_2,
 	DSI_CTRL_VERSION_MAX
 };
 
@@ -575,18 +576,26 @@
 
 /*
  * struct dsi_ctrl_hw - DSI controller hardware object specific to an instance
- * @base:           VA for the DSI controller base address.
- * @length:         Length of the DSI controller register map.
- * @index:          Instance ID of the controller.
- * @feature_map:    Features supported by the DSI controller.
- * @ops:            Function pointers to the operations supported by the
- *                  controller.
+ * @base:                   VA for the DSI controller base address.
+ * @length:                 Length of the DSI controller register map.
+ * @mmss_misc_base:         Base address of mmss_misc register map.
+ * @mmss_misc_length:       Length of mmss_misc register map.
+ * @disp_cc_base:           Base address of disp_cc register map.
+ * @disp_cc_length:         Length of disp_cc register map.
+ * @index:                  Instance ID of the controller.
+ * @feature_map:            Features supported by the DSI controller.
+ * @ops:                    Function pointers to the operations supported by the
+ *                          controller.
+ * @supported_interrupts:   Number of supported interrupts.
+ * @supported_errors:       Number of supported errors.
  */
 struct dsi_ctrl_hw {
 	void __iomem *base;
 	u32 length;
 	void __iomem *mmss_misc_base;
 	u32 mmss_misc_length;
+	void __iomem *disp_cc_base;
+	u32 disp_cc_length;
 	u32 index;
 
 	/* features */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_2.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_2.c
new file mode 100644
index 0000000..1b1e811
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_2.c
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ *
+ */
+
+#define pr_fmt(fmt) "dsi-hw:" fmt
+
+#include "dsi_ctrl_hw.h"
+#include "dsi_ctrl_reg.h"
+#include "dsi_hw.h"
+
+/* Equivalent to register DISP_CC_MISC_CMD */
+#define DISP_CC_CLAMP_REG_OFF 0x00
+
+/**
+ * dsi_ctrl_hw_22_phy_reset_config() - to configure clamp control during ulps
+ * @ctrl:          Pointer to the controller host hardware.
+ * @enable:      boolean to specify enable/disable.
+ */
+void dsi_ctrl_hw_22_phy_reset_config(struct dsi_ctrl_hw *ctrl,
+		bool enable)
+{
+	u32 reg = 0;
+
+	reg = DSI_DISP_CC_R32(ctrl, DISP_CC_CLAMP_REG_OFF);
+
+	/* Mask/unmask disable PHY reset bit */
+	if (enable)
+		reg &= ~BIT(ctrl->index);
+	else
+		reg |= BIT(ctrl->index);
+	DSI_DISP_CC_W32(ctrl, DISP_CC_CLAMP_REG_OFF, reg);
+}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
index 8605338..122a63d 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
@@ -320,8 +320,8 @@
 	reg |= (common_cfg->bit_swap_green ? BIT(4) : 0);
 	reg |= (common_cfg->bit_swap_blue ? BIT(8) : 0);
 	DSI_W32(ctrl, DSI_VIDEO_MODE_DATA_CTRL, reg);
-	/* Enable Timing double buffering */
-	DSI_W32(ctrl, DSI_DSI_TIMING_DB_MODE, 0x1);
+	/* Disable Timing double buffering */
+	DSI_W32(ctrl, DSI_DSI_TIMING_DB_MODE, 0x0);
 
 
 	pr_debug("[DSI_%d] Video engine setup done\n", ctrl->index);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 2c5bd76..106511c 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -260,7 +260,8 @@
 		return rc;
 	}
 
-	rc = dsi_phy_set_ulps(m_ctrl->phy, &display->config, enable);
+	rc = dsi_phy_set_ulps(m_ctrl->phy, &display->config, enable,
+				display->clamp_enabled);
 	if (rc) {
 		pr_err("Ulps PHY state change(%d) failed\n", enable);
 		return rc;
@@ -278,7 +279,8 @@
 			return rc;
 		}
 
-		rc = dsi_phy_set_ulps(ctrl->phy, &display->config, enable);
+		rc = dsi_phy_set_ulps(ctrl->phy, &display->config, enable,
+					display->clamp_enabled);
 		if (rc) {
 			pr_err("Ulps PHY state change(%d) failed\n", enable);
 			return rc;
@@ -1365,8 +1367,7 @@
 		/*
 		 * Enable DSI clamps only if entering idle power collapse.
 		 */
-		if (dsi_panel_initialized(display->panel) &&
-			dsi_panel_ulps_feature_enabled(display->panel)) {
+		if (dsi_panel_initialized(display->panel)) {
 			dsi_display_phy_idle_off(display);
 			rc = dsi_display_set_clamp(display, true);
 			if (rc)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h
index 447f613..8250da3 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_hw.h
@@ -33,6 +33,15 @@
 		writel_relaxed((val), (dsi_hw)->mmss_misc_base + (off)); \
 	} while (0)
 
+#define DSI_DISP_CC_R32(dsi_hw, off) \
+	readl_relaxed((dsi_hw)->disp_cc_base + (off))
+#define DSI_DISP_CC_W32(dsi_hw, off, val) \
+	do {\
+		pr_err("[DSI_%d][%s] - [0x%08x]\n", \
+			(dsi_hw)->index, #off, val); \
+		writel_relaxed((val), (dsi_hw)->disp_cc_base + (off)); \
+	} while (0)
+
 #define DSI_R64(dsi_hw, off) readq_relaxed((dsi_hw)->base + (off))
 #define DSI_W64(dsi_hw, off, val) writeq_relaxed((val), (dsi_hw)->base + (off))
 
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index bda9c2d..8b759f4 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -2490,7 +2490,6 @@
 		       panel->name, rc);
 		goto error;
 	}
-	panel->panel_initialized = false;
 error:
 	mutex_unlock(&panel->panel_lock);
 	return rc;
@@ -2536,6 +2535,8 @@
 		       panel->name, rc);
 		goto error;
 	}
+	panel->panel_initialized = false;
+
 error:
 	mutex_unlock(&panel->panel_lock);
 	return rc;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
index 96a98bd..ebfb40b8 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c
@@ -388,7 +388,7 @@
 	/** TODO: initialize debugfs */
 	dsi_phy->pdev = pdev;
 	platform_set_drvdata(pdev, dsi_phy);
-	pr_debug("Probe successful for %s\n", dsi_phy->name);
+	pr_info("Probe successful for %s\n", dsi_phy->name);
 	return 0;
 
 fail_supplies:
@@ -669,7 +669,7 @@
 }
 
 static int dsi_phy_enable_ulps(struct msm_dsi_phy *phy,
-		struct dsi_host_config *config)
+		struct dsi_host_config *config, bool clamp_enabled)
 {
 	int rc = 0;
 	u32 lanes = 0;
@@ -679,17 +679,25 @@
 		lanes = config->common_config.data_lanes;
 	lanes |= DSI_CLOCK_LANE;
 
-	rc = phy->hw.ops.ulps_ops.wait_for_lane_idle(&phy->hw, lanes);
-	if (rc) {
-		pr_err("lanes not entering idle, skip ULPS\n");
-		return rc;
+	/*
+	 * If DSI clamps are enabled, it means that the DSI lanes are
+	 * already in idle state. Checking for lanes to be in idle state
+	 * should be skipped during ULPS entry programming while coming
+	 * out of idle screen.
+	 */
+	if (!clamp_enabled) {
+		rc = phy->hw.ops.ulps_ops.wait_for_lane_idle(&phy->hw, lanes);
+		if (rc) {
+			pr_err("lanes not entering idle, skip ULPS\n");
+			return rc;
+		}
 	}
 
 	phy->hw.ops.ulps_ops.ulps_request(&phy->hw, &phy->cfg, lanes);
 
 	ulps_lanes = phy->hw.ops.ulps_ops.get_lanes_in_ulps(&phy->hw);
 
-	if ((lanes & ulps_lanes) != lanes) {
+	if (!phy->hw.ops.ulps_ops.is_lanes_in_ulps(lanes, ulps_lanes)) {
 		pr_err("Failed to enter ULPS, request=0x%x, actual=0x%x\n",
 		       lanes, ulps_lanes);
 		rc = -EIO;
@@ -701,7 +709,6 @@
 static int dsi_phy_disable_ulps(struct msm_dsi_phy *phy,
 		 struct dsi_host_config *config)
 {
-	int rc = 0;
 	u32 ulps_lanes, lanes = 0;
 
 	if (config->panel_mode == DSI_OP_CMD_MODE)
@@ -710,25 +717,27 @@
 
 	ulps_lanes = phy->hw.ops.ulps_ops.get_lanes_in_ulps(&phy->hw);
 
-	if ((lanes & ulps_lanes) != lanes)
-		pr_err("Mismatch between lanes in ULPS\n");
-
-	lanes &= ulps_lanes;
+	if (!phy->hw.ops.ulps_ops.is_lanes_in_ulps(lanes, ulps_lanes)) {
+		pr_err("Mismatch in ULPS: lanes:%d, ulps_lanes:%d\n",
+				lanes, ulps_lanes);
+		return -EIO;
+	}
 
 	phy->hw.ops.ulps_ops.ulps_exit(&phy->hw, &phy->cfg, lanes);
 
 	ulps_lanes = phy->hw.ops.ulps_ops.get_lanes_in_ulps(&phy->hw);
-	if (ulps_lanes & lanes) {
+
+	if (phy->hw.ops.ulps_ops.is_lanes_in_ulps(lanes, ulps_lanes)) {
 		pr_err("Lanes (0x%x) stuck in ULPS\n", ulps_lanes);
-		rc = -EIO;
+		return -EIO;
 	}
 
-	return rc;
+	return 0;
 }
 
 
 int dsi_phy_set_ulps(struct msm_dsi_phy *phy, struct dsi_host_config *config,
-		bool enable)
+		bool enable, bool clamp_enabled)
 {
 	int rc = 0;
 
@@ -738,7 +747,10 @@
 	}
 
 	if (!phy->hw.ops.ulps_ops.ulps_request ||
-			!phy->hw.ops.ulps_ops.ulps_exit) {
+			!phy->hw.ops.ulps_ops.ulps_exit ||
+			!phy->hw.ops.ulps_ops.get_lanes_in_ulps ||
+			!phy->hw.ops.ulps_ops.is_lanes_in_ulps ||
+			!phy->hw.ops.ulps_ops.wait_for_lane_idle) {
 		pr_debug("DSI PHY ULPS ops not present\n");
 		return 0;
 	}
@@ -746,7 +758,7 @@
 	mutex_lock(&phy->phy_lock);
 
 	if (enable)
-		rc = dsi_phy_enable_ulps(phy, config);
+		rc = dsi_phy_enable_ulps(phy, config, clamp_enabled);
 	else
 		rc = dsi_phy_disable_ulps(phy, config);
 
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h
index 4a64855..e721486 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.h
@@ -182,11 +182,12 @@
  * @phy:          DSI PHY handle
  * @config:	  DSi host configuration information.
  * @enable:	  Enable/Disable
+ * @clamp_enabled: mmss_clamp enabled/disabled
  *
  * Return: error code.
  */
 int dsi_phy_set_ulps(struct msm_dsi_phy *phy,  struct dsi_host_config *config,
-		bool enable);
+		bool enable, bool clamp_enabled);
 
 /**
  * dsi_phy_clk_cb_register() - Register PHY clock control callback
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
index daaa78a..51c2f46 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw.h
@@ -143,15 +143,22 @@
 	 * @phy:           Pointer to DSI PHY hardware instance.
 	 *
 	 * Returns an ORed list of lanes (enum dsi_data_lanes) that are in ULPS
-	 * state. If 0 is returned, all the lanes are active.
+	 * state.
 	 *
 	 * Return: List of lanes in ULPS state.
 	 */
 	u32 (*get_lanes_in_ulps)(struct dsi_phy_hw *phy);
+
+	/**
+	 * is_lanes_in_ulps() - checks if the given lanes are in ulps
+	 * @lanes:           lanes to be checked.
+	 * @ulps_lanes:	   lanes in ulps currenly.
+	 *
+	 * Return: true if all the given lanes are in ulps; false otherwise.
+	 */
+	bool (*is_lanes_in_ulps)(u32 ulps, u32 ulps_lanes);
 };
 
-
-
 /**
  * struct dsi_phy_hw_ops - Operations for DSI PHY hardware.
  * @regulator_enable:          Enable PHY regulators.
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c
index 96f5c19..371239d 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_hw_v3_0.c
@@ -159,7 +159,7 @@
 			    struct dsi_phy_cfg *cfg)
 {
 	int i;
-	u8 tx_dctrl[] = {0x00, 0x00, 0x00, 0x02, 0x01};
+	u8 tx_dctrl[] = {0x00, 0x00, 0x00, 0x04, 0x01};
 
 	/* Strength ctrl settings */
 	for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) {
@@ -186,6 +186,10 @@
 		DSI_W32(phy, DSIPHY_LNX_OFFSET_BOT_CTRL(i), 0x0);
 		DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(i), tx_dctrl[i]);
 	}
+
+	/* Toggle BIT 0 to release freeze I/0 */
+	DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(3), 0x05);
+	DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(3), 0x04);
 }
 
 /**
@@ -419,6 +423,14 @@
 	return lanes;
 }
 
+bool dsi_phy_hw_v3_0_is_lanes_in_ulps(u32 lanes, u32 ulps_lanes)
+{
+	if (lanes & ulps_lanes)
+		return false;
+
+	return true;
+}
+
 int dsi_phy_hw_timing_val_v3_0(struct dsi_phy_per_lane_cfgs *timing_cfg,
 		u32 *timing_val, u32 size)
 {
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 4b263d3..4471d0b 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -138,6 +138,7 @@
 	CRTC_PROP_MEM_IB,
 	CRTC_PROP_ROT_PREFILL_BW,
 	CRTC_PROP_ROT_CLK,
+	CRTC_PROP_ROI_V1,
 
 	/* total # of properties */
 	CRTC_PROP_COUNT
@@ -158,6 +159,7 @@
 	CONNECTOR_PROP_DST_Y,
 	CONNECTOR_PROP_DST_W,
 	CONNECTOR_PROP_DST_H,
+	CONNECTOR_PROP_ROI_V1,
 
 	/* enum/bitmask properties */
 	CONNECTOR_PROP_TOPOLOGY_NAME,
@@ -200,6 +202,38 @@
 };
 
 /**
+ * struct msm_roi_alignment - region of interest alignment restrictions
+ * @xstart_pix_align: left x offset alignment restriction
+ * @width_pix_align: width alignment restriction
+ * @ystart_pix_align: top y offset alignment restriction
+ * @height_pix_align: height alignment restriction
+ * @min_width: minimum width restriction
+ * @min_height: minimum height restriction
+ */
+struct msm_roi_alignment {
+	uint32_t xstart_pix_align;
+	uint32_t width_pix_align;
+	uint32_t ystart_pix_align;
+	uint32_t height_pix_align;
+	uint32_t min_width;
+	uint32_t min_height;
+};
+
+/**
+ * struct msm_roi_caps - display's region of interest capabilities
+ * @enabled: true if some region of interest is supported
+ * @merge_rois: merge rois before sending to display
+ * @num_roi: maximum number of rois supported
+ * @align: roi alignment restrictions
+ */
+struct msm_roi_caps {
+	bool enabled;
+	bool merge_rois;
+	uint32_t num_roi;
+	struct msm_roi_alignment align;
+};
+
+/**
  * struct msm_display_dsc_info - defines dsc configuration
  * @version:                 DSC version.
  * @scr_rev:                 DSC revision.
@@ -338,6 +372,7 @@
  * @vtotal:		display vertical total
  * @jitter:		display jitter configuration
  * @comp_info:          Compression supported by the display
+ * @roi_caps:           Region of interest capability info
  */
 struct msm_display_info {
 	int intf_type;
@@ -361,21 +396,19 @@
 	uint32_t jitter;
 
 	struct msm_compression_info comp_info;
+	struct msm_roi_caps roi_caps;
 };
 
 #define MSM_MAX_ROI	4
 
 /**
- * struct msm_roi_mapping - Regions of interest structure for mapping CRTC to
- *	Connector output
- * @num_rects: number of valid rectangles in src and dst arrays
- * @src: source roi rectangle
- * @dst: destination roi rectangle
+ * struct msm_roi_list - list of regions of interest for a drm object
+ * @num_rects: number of valid rectangles in the roi array
+ * @roi: list of roi rectangles
  */
-struct msm_roi_mapping {
+struct msm_roi_list {
 	uint32_t num_rects;
-	struct drm_clip_rect src[MSM_MAX_ROI];
-	struct drm_clip_rect dst[MSM_MAX_ROI];
+	struct drm_clip_rect roi[MSM_MAX_ROI];
 };
 
 /**
@@ -383,7 +416,7 @@
  * @rois: Regions of interest structure for mapping CRTC to Connector output
  */
 struct msm_display_kickoff_params {
-	struct msm_roi_mapping *rois;
+	struct msm_roi_list *rois;
 };
 
 /**
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index 6c2d643..e3f8261 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -21,6 +21,12 @@
 
 #define BL_NODE_NAME_SIZE 32
 
+#define SDE_DEBUG_CONN(c, fmt, ...) SDE_DEBUG("conn%d " fmt,\
+		(c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
+
+#define SDE_ERROR_CONN(c, fmt, ...) SDE_ERROR("conn%d " fmt,\
+		(c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
+
 static const struct drm_prop_enum_list e_topology_name[] = {
 	{SDE_RM_TOPOLOGY_UNKNOWN,	"sde_unknown"},
 	{SDE_RM_TOPOLOGY_SINGLEPIPE,	"sde_singlepipe"},
@@ -248,6 +254,25 @@
 	return rc;
 }
 
+void sde_connector_clk_ctrl(struct drm_connector *connector, bool enable)
+{
+	struct sde_connector *c_conn;
+	struct dsi_display *display;
+	u32 state = enable ? DSI_CLK_ON : DSI_CLK_OFF;
+
+	if (!connector) {
+		SDE_ERROR("invalid connector\n");
+		return;
+	}
+
+	c_conn = to_sde_connector(connector);
+	display = (struct dsi_display *) c_conn->display;
+
+	if (display && c_conn->ops.clk_ctrl)
+		c_conn->ops.clk_ctrl(display->mdp_clk_handle,
+				DSI_ALL_CLKS, state);
+}
+
 static void sde_connector_destroy(struct drm_connector *connector)
 {
 	struct sde_connector *c_conn;
@@ -397,6 +422,122 @@
 	return &c_state->base;
 }
 
+static int _sde_connector_roi_v1_check_roi(
+		struct sde_connector *c_conn,
+		struct drm_clip_rect *roi_conn,
+		const struct msm_roi_caps *caps)
+{
+	const struct msm_roi_alignment *align = &caps->align;
+	int w = roi_conn->x2 - roi_conn->x1;
+	int h = roi_conn->y2 - roi_conn->y1;
+
+	if (w <= 0 || h <= 0) {
+		SDE_ERROR_CONN(c_conn, "invalid conn roi w %d h %d\n", w, h);
+		return -EINVAL;
+	}
+
+	if (w < align->min_width || w % align->width_pix_align) {
+		SDE_ERROR_CONN(c_conn,
+				"invalid conn roi width %d min %d align %d\n",
+				w, align->min_width, align->width_pix_align);
+		return -EINVAL;
+	}
+
+	if (h < align->min_height || h % align->height_pix_align) {
+		SDE_ERROR_CONN(c_conn,
+				"invalid conn roi height %d min %d align %d\n",
+				h, align->min_height, align->height_pix_align);
+		return -EINVAL;
+	}
+
+	if (roi_conn->x1 % align->xstart_pix_align) {
+		SDE_ERROR_CONN(c_conn, "invalid conn roi x1 %d align %d\n",
+				roi_conn->x1, align->xstart_pix_align);
+		return -EINVAL;
+	}
+
+	if (roi_conn->y1 % align->ystart_pix_align) {
+		SDE_ERROR_CONN(c_conn, "invalid conn roi y1 %d align %d\n",
+				roi_conn->y1, align->ystart_pix_align);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int _sde_connector_set_roi_v1(
+		struct sde_connector *c_conn,
+		struct sde_connector_state *c_state,
+		void *usr_ptr)
+{
+	struct sde_drm_roi_v1 roi_v1;
+	struct msm_display_info display_info;
+	struct msm_roi_caps *caps;
+	int i, rc;
+
+	if (!c_conn || !c_state) {
+		SDE_ERROR("invalid args\n");
+		return -EINVAL;
+	}
+
+	rc = sde_connector_get_info(&c_conn->base, &display_info);
+	if (rc) {
+		SDE_ERROR_CONN(c_conn, "display get info error: %d\n", rc);
+		return rc;
+	}
+
+	caps = &display_info.roi_caps;
+	if (!caps->enabled) {
+		SDE_ERROR_CONN(c_conn, "display roi capability is disabled\n");
+		return -ENOTSUPP;
+	}
+
+	memset(&c_state->rois, 0, sizeof(c_state->rois));
+
+	if (!usr_ptr) {
+		SDE_DEBUG_CONN(c_conn, "rois cleared\n");
+		return 0;
+	}
+
+	if (copy_from_user(&roi_v1, usr_ptr, sizeof(roi_v1))) {
+		SDE_ERROR_CONN(c_conn, "failed to copy roi_v1 data\n");
+		return -EINVAL;
+	}
+
+	SDE_DEBUG_CONN(c_conn, "num_rects %d\n", roi_v1.num_rects);
+
+	if (roi_v1.num_rects == 0) {
+		SDE_DEBUG_CONN(c_conn, "rois cleared\n");
+		return 0;
+	}
+
+	if (roi_v1.num_rects > SDE_MAX_ROI_V1 ||
+			roi_v1.num_rects > caps->num_roi) {
+		SDE_ERROR_CONN(c_conn, "too many rects specified: %d\n",
+				roi_v1.num_rects);
+		return -EINVAL;
+	}
+
+	c_state->rois.num_rects = roi_v1.num_rects;
+	for (i = 0; i < roi_v1.num_rects; ++i) {
+		int rc;
+
+		rc = _sde_connector_roi_v1_check_roi(c_conn, &roi_v1.roi[i],
+				caps);
+		if (rc)
+			return rc;
+
+		c_state->rois.roi[i] = roi_v1.roi[i];
+		SDE_DEBUG_CONN(c_conn, "roi%d: roi 0x%x 0x%x 0x%x 0x%x\n", i,
+				c_state->rois.roi[i].x1,
+				c_state->rois.roi[i].y1,
+				c_state->rois.roi[i].x2,
+				c_state->rois.roi[i].y2);
+	}
+
+	return 0;
+}
+
 static int sde_connector_atomic_set_property(struct drm_connector *connector,
 		struct drm_connector_state *state,
 		struct drm_property *property,
@@ -462,6 +603,12 @@
 			SDE_ERROR("invalid topology_control: 0x%llX\n", val);
 	}
 
+	if (idx == CONNECTOR_PROP_ROI_V1) {
+		rc = _sde_connector_set_roi_v1(c_conn, c_state, (void *)val);
+		if (rc)
+			SDE_ERROR_CONN(c_conn, "invalid roi_v1, rc: %d\n", rc);
+	}
+
 	/* check for custom property handling */
 	if (!rc && c_conn->ops.set_property) {
 		rc = c_conn->ops.set_property(connector,
@@ -511,13 +658,7 @@
 
 	idx = msm_property_index(&c_conn->property_info, property);
 	if (idx == CONNECTOR_PROP_RETIRE_FENCE)
-		/*
-		 * Set a fence offset if not a virtual connector, so that the
-		 * fence signals after one additional commit rather than at the
-		 * end of the current one.
-		 */
-		rc = sde_fence_create(&c_conn->retire_fence, val,
-			c_conn->connector_type != DRM_MODE_CONNECTOR_VIRTUAL);
+		rc = sde_fence_create(&c_conn->retire_fence, val, 0);
 	else
 		/* get cached property value */
 		rc = msm_property_atomic_get(&c_conn->property_info,
@@ -706,6 +847,7 @@
 	struct sde_kms_info *info;
 	struct sde_connector *c_conn = NULL;
 	struct dsi_display *dsi_display;
+	struct msm_display_info display_info;
 	int rc;
 
 	if (!dev || !dev->dev_private || !encoder) {
@@ -838,6 +980,13 @@
 		}
 	}
 
+	rc = sde_connector_get_info(&c_conn->base, &display_info);
+	if (!rc && display_info.roi_caps.enabled) {
+		msm_property_install_volatile_range(
+				&c_conn->property_info, "sde_drm_roi_v1", 0x0,
+				0, ~0, 0, CONNECTOR_PROP_ROI_V1);
+	}
+
 	msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
 			0x0, 0, INR_OPEN_MAX, 0, CONNECTOR_PROP_RETIRE_FENCE);
 
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index 70d4952..601299e 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -150,6 +150,14 @@
 	int (*pre_kickoff)(struct drm_connector *connector,
 			void *display,
 			struct msm_display_kickoff_params *params);
+
+	/**
+	 * clk_ctrl - perform clk enable/disable on the connector
+	 * @handle: Pointer to clk handle
+	 * @type: Type of clks
+	 * @enable: State of clks
+	 */
+	int (*clk_ctrl)(void *handle, u32 type, u32 state);
 };
 
 /**
@@ -273,7 +281,7 @@
 	int mmu_id;
 	uint64_t property_values[CONNECTOR_PROP_COUNT];
 
-	struct msm_roi_mapping rois;
+	struct msm_roi_list rois;
 };
 
 /**
@@ -366,6 +374,13 @@
 		struct msm_display_info *info);
 
 /**
+ * sde_connector_clk_ctrl - enables/disables the connector clks
+ * @connector: Pointer to drm connector object
+ * @enable: true/false to enable/disable
+ */
+void sde_connector_clk_ctrl(struct drm_connector *connector, bool enable);
+
+/**
  * sde_connector_trigger_event - indicate that an event has occurred
  *	Any callbacks that have been registered against this event will
  *	be called from the same thread context.
@@ -425,5 +440,22 @@
  */
 int sde_connector_pre_kickoff(struct drm_connector *connector);
 
+/**
+ * sde_connector_needs_offset - adjust the output fence offset based on
+ *                              display type
+ * @connector: Pointer to drm connector object
+ * Returns: true if offset is required, false for all other cases.
+ */
+static inline bool sde_connector_needs_offset(struct drm_connector *connector)
+{
+	struct sde_connector *c_conn;
+
+	if (!connector)
+		return false;
+
+	c_conn = to_sde_connector(connector);
+	return (c_conn->connector_type != DRM_MODE_CONNECTOR_VIRTUAL);
+}
+
 #endif /* _SDE_CONNECTOR_H_ */
 
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index a44dd68..6bae083 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -656,21 +656,344 @@
 	}
 }
 
+void sde_crtc_get_crtc_roi(struct drm_crtc_state *state,
+		const struct sde_rect **crtc_roi)
+{
+	struct sde_crtc_state *crtc_state;
+
+	if (!state || !crtc_roi)
+		return;
+
+	crtc_state = to_sde_crtc_state(state);
+	*crtc_roi = &crtc_state->crtc_roi;
+}
+
+static int _sde_crtc_set_roi_v1(struct drm_crtc_state *state,
+		void *usr_ptr)
+{
+	struct drm_crtc *crtc;
+	struct sde_crtc_state *cstate;
+	struct sde_drm_roi_v1 roi_v1;
+	int i;
+
+	if (!state) {
+		SDE_ERROR("invalid args\n");
+		return -EINVAL;
+	}
+
+	cstate = to_sde_crtc_state(state);
+	crtc = cstate->base.crtc;
+
+	memset(&cstate->user_roi_list, 0, sizeof(cstate->user_roi_list));
+
+	if (!usr_ptr) {
+		SDE_DEBUG("crtc%d: rois cleared\n", DRMID(crtc));
+		return 0;
+	}
+
+	if (copy_from_user(&roi_v1, usr_ptr, sizeof(roi_v1))) {
+		SDE_ERROR("crtc%d: failed to copy roi_v1 data\n", DRMID(crtc));
+		return -EINVAL;
+	}
+
+	SDE_DEBUG("crtc%d: num_rects %d\n", DRMID(crtc), roi_v1.num_rects);
+
+	if (roi_v1.num_rects == 0) {
+		SDE_DEBUG("crtc%d: rois cleared\n", DRMID(crtc));
+		return 0;
+	}
+
+	if (roi_v1.num_rects > SDE_MAX_ROI_V1) {
+		SDE_ERROR("crtc%d: too many rects specified: %d\n", DRMID(crtc),
+				roi_v1.num_rects);
+		return -EINVAL;
+	}
+
+	cstate->user_roi_list.num_rects = roi_v1.num_rects;
+	for (i = 0; i < roi_v1.num_rects; ++i) {
+		cstate->user_roi_list.roi[i] = roi_v1.roi[i];
+		SDE_DEBUG("crtc%d: roi%d: roi (%d,%d) (%d,%d)\n",
+				DRMID(crtc), i,
+				cstate->user_roi_list.roi[i].x1,
+				cstate->user_roi_list.roi[i].y1,
+				cstate->user_roi_list.roi[i].x2,
+				cstate->user_roi_list.roi[i].y2);
+	}
+
+	return 0;
+}
+
+static int _sde_crtc_set_crtc_roi(struct drm_crtc *crtc,
+		struct drm_crtc_state *state)
+{
+	struct drm_connector *conn;
+	struct drm_connector_state *conn_state;
+	struct sde_crtc *sde_crtc;
+	struct sde_crtc_state *crtc_state;
+	struct sde_rect *crtc_roi;
+	struct drm_clip_rect crtc_clip, *user_rect;
+	int i, num_attached_conns = 0;
+
+	if (!crtc || !state)
+		return -EINVAL;
+
+	sde_crtc = to_sde_crtc(crtc);
+	crtc_state = to_sde_crtc_state(state);
+	crtc_roi = &crtc_state->crtc_roi;
+
+	/* init to invalid range maxes */
+	crtc_clip.x1 = ~0;
+	crtc_clip.y1 = ~0;
+	crtc_clip.x2 = 0;
+	crtc_clip.y2 = 0;
+
+	for_each_connector_in_state(state->state, conn, conn_state, i) {
+		struct sde_connector_state *sde_conn_state;
+
+		if (!conn_state || conn_state->crtc != crtc)
+			continue;
+
+		if (num_attached_conns) {
+			SDE_ERROR(
+				"crtc%d: unsupported: roi on crtc w/ >1 connectors\n",
+					DRMID(crtc));
+			return -EINVAL;
+		}
+		++num_attached_conns;
+
+		sde_conn_state = to_sde_connector_state(conn_state);
+
+		if (memcmp(&sde_conn_state->rois, &crtc_state->user_roi_list,
+				sizeof(crtc_state->user_roi_list))) {
+			SDE_ERROR("%s: crtc -> conn roi scaling unsupported\n",
+					sde_crtc->name);
+			return -EINVAL;
+		}
+	}
+
+	/* aggregate all clipping rectangles together for overall crtc roi */
+	for (i = 0; i < crtc_state->user_roi_list.num_rects; i++) {
+		user_rect = &crtc_state->user_roi_list.roi[i];
+
+		crtc_clip.x1 = min(crtc_clip.x1, user_rect->x1);
+		crtc_clip.y1 = min(crtc_clip.y1, user_rect->y1);
+		crtc_clip.x2 = max(crtc_clip.x2, user_rect->x2);
+		crtc_clip.y2 = max(crtc_clip.y2, user_rect->y2);
+
+		SDE_DEBUG(
+			"%s: conn%d roi%d (%d,%d),(%d,%d) -> crtc (%d,%d),(%d,%d)\n",
+				sde_crtc->name, DRMID(crtc), i,
+				user_rect->x1, user_rect->y1,
+				user_rect->x2, user_rect->y2,
+				crtc_clip.x1, crtc_clip.y1,
+				crtc_clip.x2, crtc_clip.y2);
+
+	}
+
+	if (crtc_clip.x2  && crtc_clip.y2) {
+		crtc_roi->x = crtc_clip.x1;
+		crtc_roi->y = crtc_clip.y1;
+		crtc_roi->w = crtc_clip.x2 - crtc_clip.x1;
+		crtc_roi->h = crtc_clip.y2 - crtc_clip.y1;
+	} else {
+		crtc_roi->x = 0;
+		crtc_roi->y = 0;
+		crtc_roi->w = 0;
+		crtc_roi->h = 0;
+	}
+
+	SDE_DEBUG("%s: crtc roi (%d,%d,%d,%d)\n", sde_crtc->name,
+			crtc_roi->x, crtc_roi->y, crtc_roi->w, crtc_roi->h);
+
+	return 0;
+}
+
+static int _sde_crtc_set_lm_roi(struct drm_crtc *crtc,
+		struct drm_crtc_state *state, int lm_idx)
+{
+	struct sde_crtc *sde_crtc;
+	struct sde_crtc_state *crtc_state;
+	const struct sde_rect *crtc_roi;
+	const struct sde_rect *lm_bounds;
+	struct sde_rect *lm_roi;
+
+	if (!crtc || !state || lm_idx >= ARRAY_SIZE(crtc_state->lm_bounds))
+		return -EINVAL;
+
+	sde_crtc = to_sde_crtc(crtc);
+	crtc_state = to_sde_crtc_state(state);
+	crtc_roi = &crtc_state->crtc_roi;
+	lm_bounds = &crtc_state->lm_bounds[lm_idx];
+	lm_roi = &crtc_state->lm_roi[lm_idx];
+
+	if (!sde_kms_rect_is_null(crtc_roi)) {
+		sde_kms_rect_intersect(crtc_roi, lm_bounds, lm_roi);
+		if (sde_kms_rect_is_null(lm_roi)) {
+			SDE_ERROR("unsupported R/L only partial update\n");
+			return -EINVAL;
+		}
+	} else {
+		memcpy(lm_roi, lm_bounds, sizeof(*lm_roi));
+	}
+
+	SDE_DEBUG("%s: lm%d roi (%d,%d,%d,%d)\n", sde_crtc->name, lm_idx,
+			lm_roi->x, lm_roi->y, lm_roi->w, lm_roi->h);
+
+	return 0;
+}
+
+static int _sde_crtc_check_rois_centered_and_symmetric(struct drm_crtc *crtc,
+		struct drm_crtc_state *state)
+{
+	struct sde_crtc *sde_crtc;
+	struct sde_crtc_state *crtc_state;
+	const struct sde_rect *roi_prv, *roi_cur;
+	int lm_idx;
+
+	if (!crtc || !state)
+		return -EINVAL;
+
+	/*
+	 * On certain HW, ROIs must be centered on the split between LMs,
+	 * and be of equal width.
+	 */
+
+	sde_crtc = to_sde_crtc(crtc);
+	crtc_state = to_sde_crtc_state(state);
+
+	roi_prv = &crtc_state->lm_roi[0];
+	for (lm_idx = 1; lm_idx < sde_crtc->num_mixers; lm_idx++) {
+		roi_cur = &crtc_state->lm_roi[lm_idx];
+
+		/* check lm rois are equal width & first roi ends at 2nd roi */
+		if (((roi_prv->x + roi_prv->w) != roi_cur->x) ||
+				(roi_prv->w != roi_cur->w)) {
+			SDE_ERROR("%s: roi lm%d x %d w %d lm%d x %d w %d\n",
+					sde_crtc->name,
+					lm_idx-1, roi_prv->x, roi_prv->w,
+					lm_idx, roi_cur->x, roi_cur->w);
+			return -EINVAL;
+		}
+		roi_prv = roi_cur;
+	}
+
+	return 0;
+}
+
+static int _sde_crtc_check_planes_within_crtc_roi(struct drm_crtc *crtc,
+		struct drm_crtc_state *state)
+{
+	struct sde_crtc *sde_crtc;
+	struct sde_crtc_state *crtc_state;
+	const struct sde_rect *crtc_roi;
+	struct drm_plane_state *pstate;
+	struct drm_plane *plane;
+
+	if (!crtc || !state)
+		return -EINVAL;
+
+	/*
+	 * Reject commit if a Plane CRTC destination coordinates fall outside
+	 * the partial CRTC ROI. LM output is determined via connector ROIs,
+	 * if they are specified, not Plane CRTC ROIs.
+	 */
+
+	sde_crtc = to_sde_crtc(crtc);
+	crtc_state = to_sde_crtc_state(state);
+	crtc_roi = &crtc_state->crtc_roi;
+
+	if (sde_kms_rect_is_null(crtc_roi))
+		return 0;
+
+	drm_atomic_crtc_state_for_each_plane(plane, state) {
+		struct sde_rect plane_roi, intersection;
+
+		pstate = drm_atomic_get_plane_state(state->state, plane);
+		if (IS_ERR_OR_NULL(pstate)) {
+			int rc = PTR_ERR(pstate);
+
+			SDE_ERROR("%s: failed to get plane%d state, %d\n",
+					sde_crtc->name, plane->base.id, rc);
+			return rc;
+		}
+
+		plane_roi.x = pstate->crtc_x;
+		plane_roi.y = pstate->crtc_y;
+		plane_roi.w = pstate->crtc_w;
+		plane_roi.h = pstate->crtc_h;
+		sde_kms_rect_intersect(crtc_roi, &plane_roi, &intersection);
+		if (!sde_kms_rect_is_equal(&plane_roi, &intersection)) {
+			SDE_ERROR(
+				"%s: plane%d crtc roi (%d,%d,%d,%d) outside crtc roi (%d,%d,%d,%d)\n",
+					sde_crtc->name, plane->base.id,
+					plane_roi.x, plane_roi.y,
+					plane_roi.w, plane_roi.h,
+					crtc_roi->x, crtc_roi->y,
+					crtc_roi->w, crtc_roi->h);
+			return -E2BIG;
+		}
+	}
+
+	return 0;
+}
+
+static int _sde_crtc_check_rois(struct drm_crtc *crtc,
+		struct drm_crtc_state *state)
+{
+	struct sde_crtc *sde_crtc;
+	int lm_idx;
+	int rc;
+
+	if (!crtc || !state)
+		return -EINVAL;
+
+	sde_crtc = to_sde_crtc(crtc);
+
+	rc = _sde_crtc_set_crtc_roi(crtc, state);
+	if (rc)
+		return rc;
+
+	for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) {
+		rc = _sde_crtc_set_lm_roi(crtc, state, lm_idx);
+		if (rc)
+			return rc;
+	}
+
+	rc = _sde_crtc_check_rois_centered_and_symmetric(crtc, state);
+	if (rc)
+		return rc;
+
+	rc = _sde_crtc_check_planes_within_crtc_roi(crtc, state);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
 static void _sde_crtc_program_lm_output_roi(struct drm_crtc *crtc)
 {
 	struct sde_crtc *sde_crtc;
 	struct sde_crtc_state *crtc_state;
+	const struct sde_rect *lm_roi;
+	struct sde_hw_mixer *hw_lm;
 	int lm_idx, lm_horiz_position;
 
+	if (!crtc)
+		return;
+
 	sde_crtc = to_sde_crtc(crtc);
 	crtc_state = to_sde_crtc_state(crtc->state);
 
 	lm_horiz_position = 0;
 	for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) {
-		const struct sde_rect *lm_roi = &crtc_state->lm_bounds[lm_idx];
-		struct sde_hw_mixer *hw_lm = sde_crtc->mixers[lm_idx].hw_lm;
 		struct sde_hw_mixer_cfg cfg;
 
+		lm_roi = &crtc_state->lm_roi[lm_idx];
+		hw_lm = sde_crtc->mixers[lm_idx].hw_lm;
+
+		SDE_EVT32(DRMID(crtc_state->base.crtc), lm_idx,
+			lm_roi->x, lm_roi->y, lm_roi->w, lm_roi->h);
+
 		if (sde_kms_rect_is_null(lm_roi))
 			continue;
 
@@ -742,9 +1065,12 @@
 
 		format = to_sde_format(msm_framebuffer_format(pstate->base.fb));
 
-		SDE_EVT32(DRMID(plane), state->src_x, state->src_y,
-			state->src_w >> 16, state->src_h >> 16, state->crtc_x,
-			state->crtc_y, state->crtc_w, state->crtc_h);
+		SDE_EVT32(DRMID(crtc), DRMID(plane),
+				state->fb ? state->fb->base.id : -1,
+				state->src_x >> 16, state->src_y >> 16,
+				state->src_w >> 16, state->src_h >> 16,
+				state->crtc_x, state->crtc_y,
+				state->crtc_w, state->crtc_h);
 
 		for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) {
 			struct sde_rect intersect;
@@ -877,6 +1203,8 @@
 		ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx,
 			&sde_crtc->stage_cfg, i);
 	}
+
+	_sde_crtc_program_lm_output_roi(crtc);
 }
 
 void sde_crtc_prepare_commit(struct drm_crtc *crtc,
@@ -1329,14 +1657,18 @@
 	crtc_split_width = sde_crtc_mixer_width(sde_crtc, adj_mode);
 
 	for (i = 0; i < sde_crtc->num_mixers; i++) {
-		struct sde_rect *lm_bound = &cstate->lm_bounds[i];
-
-		lm_bound->x = crtc_split_width * i;
-		lm_bound->y = 0;
-		lm_bound->w = crtc_split_width;
-		lm_bound->h = adj_mode->vdisplay;
-		SDE_EVT32(DRMID(crtc), i, lm_bound->x, lm_bound->y,
-				lm_bound->w, lm_bound->h);
+		cstate->lm_bounds[i].x = crtc_split_width * i;
+		cstate->lm_bounds[i].y = 0;
+		cstate->lm_bounds[i].w = crtc_split_width;
+		cstate->lm_bounds[i].h = adj_mode->vdisplay;
+		memcpy(&cstate->lm_roi[i], &cstate->lm_bounds[i],
+				sizeof(cstate->lm_roi[i]));
+		SDE_EVT32(DRMID(crtc), i,
+				cstate->lm_bounds[i].x, cstate->lm_bounds[i].y,
+				cstate->lm_bounds[i].w, cstate->lm_bounds[i].h);
+		SDE_DEBUG("%s: lm%d bnd&roi (%d,%d,%d,%d)\n", sde_crtc->name, i,
+				cstate->lm_roi[i].x, cstate->lm_roi[i].y,
+				cstate->lm_roi[i].w, cstate->lm_roi[i].h);
 	}
 
 	drm_mode_debug_printmodeline(adj_mode);
@@ -1366,10 +1698,10 @@
 	sde_crtc = to_sde_crtc(crtc);
 	dev = crtc->dev;
 
-	if (!sde_crtc->num_mixers)
+	if (!sde_crtc->num_mixers) {
 		_sde_crtc_setup_mixers(crtc);
-
-	_sde_crtc_setup_lm_bounds(crtc, crtc->state);
+		_sde_crtc_setup_lm_bounds(crtc, crtc->state);
+	}
 
 	if (sde_crtc->event) {
 		WARN_ON(sde_crtc->event);
@@ -2117,6 +2449,11 @@
 		}
 	}
 
+	rc = _sde_crtc_check_rois(crtc, state);
+	if (rc) {
+		SDE_ERROR("crtc%d failed roi check %d\n", crtc->base.id, rc);
+		goto end;
+	}
 
 end:
 	_sde_crtc_rp_free_unused(&cstate->rp);
@@ -2243,6 +2580,9 @@
 			"dim_layer_v1", 0x0, 0, ~0, 0, CRTC_PROP_DIM_LAYER_V1);
 	}
 
+	msm_property_install_volatile_range(&sde_crtc->property_info,
+		"sde_drm_roi_v1", 0x0, 0, ~0, 0, CRTC_PROP_ROI_V1);
+
 	sde_kms_info_reset(info);
 
 	sde_kms_info_add_keyint(info, "hw_version", catalog->hwversion);
@@ -2315,6 +2655,9 @@
 			case CRTC_PROP_DIM_LAYER_V1:
 				_sde_crtc_set_dim_layer_v1(cstate, (void *)val);
 				break;
+			case CRTC_PROP_ROI_V1:
+				ret = _sde_crtc_set_roi_v1(state, (void *)val);
+				break;
 			default:
 				/* nothing to do */
 				break;
@@ -2364,19 +2707,28 @@
 	struct sde_crtc *sde_crtc;
 	struct sde_crtc_state *cstate;
 	int i, ret = -EINVAL;
+	bool conn_offset = 0;
 
 	if (!crtc || !state) {
 		SDE_ERROR("invalid argument(s)\n");
 	} else {
 		sde_crtc = to_sde_crtc(crtc);
 		cstate = to_sde_crtc_state(state);
+
+		for (i = 0; i < cstate->num_connectors; ++i) {
+			conn_offset = sde_connector_needs_offset(
+						cstate->connectors[i]);
+			if (conn_offset)
+				break;
+		}
+
 		i = msm_property_index(&sde_crtc->property_info, property);
 		if (i == CRTC_PROP_OUTPUT_FENCE) {
 			uint32_t offset = sde_crtc_get_property(cstate,
 					CRTC_PROP_OUTPUT_FENCE_OFFSET);
 
-			ret = sde_fence_create(
-					&sde_crtc->output_fence, val, offset);
+			ret = sde_fence_create(&sde_crtc->output_fence, val,
+							offset + conn_offset);
 			if (ret)
 				SDE_ERROR("fence create failed\n");
 		} else {
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 36231d4..7ad0955 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -250,6 +250,11 @@
  * @rsc_client    : sde rsc client when mode is valid
  * @lm_bounds     : LM boundaries based on current mode full resolution, no ROI.
  *                  Origin top left of CRTC.
+ * @crtc_roi      : Current CRTC ROI. Possibly sub-rectangle of mode.
+ *                  Origin top left of CRTC.
+ * @lm_roi        : Current LM ROI, possibly sub-rectangle of mode.
+ *                  Origin top left of CRTC.
+ * @user_roi_list : List of user's requested ROIs as from set property
  * @property_values: Current crtc property values
  * @input_fence_timeout_ns : Cached input fence timeout, in ns
  * @property_blobs: Reference pointers for blob properties
@@ -270,6 +275,9 @@
 	bool rsc_update;
 
 	struct sde_rect lm_bounds[CRTC_DUAL_MIXERS];
+	struct sde_rect crtc_roi;
+	struct sde_rect lm_roi[CRTC_DUAL_MIXERS];
+	struct msm_roi_list user_roi_list;
 
 	uint64_t property_values[CRTC_PROP_COUNT];
 	uint64_t input_fence_timeout_ns;
@@ -433,4 +441,14 @@
  */
 void sde_crtc_res_put(struct drm_crtc_state *state, u32 type, u64 tag);
 
+/**
+ * sde_crtc_get_crtc_roi - retrieve the crtc_roi from the given state object
+ *	used to allow the planes to adjust their final lm out_xy value in the
+ *	case of partial update
+ * @crtc_state: Pointer to crtc state
+ * @crtc_roi: Output pointer to crtc roi in the given state
+ */
+void sde_crtc_get_crtc_roi(struct drm_crtc_state *state,
+		const struct sde_rect **crtc_roi);
+
 #endif /* _SDE_CRTC_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 8c41b12..742ea20 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -284,6 +284,24 @@
 	}
 }
 
+static void _sde_encoder_adjust_mode(struct drm_connector *connector,
+		struct drm_display_mode *adj_mode)
+{
+	struct drm_display_mode *cur_mode;
+
+	if (!connector || !adj_mode)
+		return;
+
+	list_for_each_entry(cur_mode, &connector->modes, head) {
+		if (cur_mode->vdisplay == adj_mode->vdisplay &&
+			cur_mode->hdisplay == adj_mode->hdisplay &&
+			cur_mode->vrefresh == adj_mode->vrefresh) {
+			adj_mode->private = cur_mode->private;
+			adj_mode->private_flags = cur_mode->private_flags;
+		}
+	}
+}
+
 static int sde_encoder_virt_atomic_check(
 		struct drm_encoder *drm_enc,
 		struct drm_crtc_state *crtc_state,
@@ -312,6 +330,15 @@
 	adj_mode = &crtc_state->adjusted_mode;
 	SDE_EVT32(DRMID(drm_enc));
 
+	/*
+	 * display drivers may populate private fields of the drm display mode
+	 * structure while registering possible modes of a connector with DRM.
+	 * These private fields are not populated back while DRM invokes
+	 * the mode_set callbacks. This module retrieves and populates the
+	 * private fields of the given mode.
+	 */
+	_sde_encoder_adjust_mode(conn_state->connector, adj_mode);
+
 	/* perform atomic check on the first physical encoder (master) */
 	for (i = 0; i < sde_enc->num_phys_encs; i++) {
 		struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index 11cca1f..cfa3b5e 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -490,8 +490,8 @@
 		return 0;
 
 	for (i = 0, cur_pos = dst_list_pos;
-		(cur_pos < (dst_list_size - 1)) && src_list[i].fourcc_format
-		&& (i < src_list_size); ++i, ++cur_pos)
+		(cur_pos < (dst_list_size - 1)) && (i < src_list_size)
+		&& src_list[i].fourcc_format; ++i, ++cur_pos)
 		dst_list[cur_pos] = src_list[i];
 
 	dst_list[cur_pos].fourcc_format = 0;
@@ -565,7 +565,7 @@
 				rc = -EINVAL;
 			}
 			*off_count = 0;
-			memset(prop_count, 0, sizeof(int *) * prop_size);
+			memset(prop_count, 0, sizeof(int) * prop_size);
 			return rc;
 		}
 	}
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 2393e61..4a5479d 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -566,7 +566,8 @@
 		.get_info =   dsi_display_get_info,
 		.set_backlight = dsi_display_set_backlight,
 		.soft_reset   = dsi_display_soft_reset,
-		.pre_kickoff  = dsi_conn_pre_kickoff
+		.pre_kickoff  = dsi_conn_pre_kickoff,
+		.clk_ctrl = dsi_display_clk_ctrl
 	};
 	static const struct sde_connector_ops wb_ops = {
 		.post_init =    sde_wb_connector_post_init,
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index bd6b302..8662207 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -2204,6 +2204,7 @@
 	struct drm_crtc *crtc;
 	struct drm_framebuffer *fb;
 	struct sde_rect src, dst;
+	const struct sde_rect *crtc_roi;
 	bool q16_data = true;
 	int idx;
 
@@ -2283,6 +2284,11 @@
 		}
 	}
 
+	/* re-program the output rects always in the case of partial update */
+	sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
+	if (!sde_kms_rect_is_null(crtc_roi))
+		pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
+
 	if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
 		memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
 
@@ -2320,6 +2326,13 @@
 			src.y &= ~0x1;
 		}
 
+		/*
+		 * adjust layer mixer position of the sspp in the presence
+		 * of a partial update to the active lm origin
+		 */
+		dst.x -= crtc_roi->x;
+		dst.y -= crtc_roi->y;
+
 		psde->pipe_cfg.src_rect = src;
 		psde->pipe_cfg.dst_rect = dst;
 
diff --git a/drivers/gpu/drm/msm/sde_power_handle.c b/drivers/gpu/drm/msm/sde_power_handle.c
index 62efe8e..9a68dbe 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.c
+++ b/drivers/gpu/drm/msm/sde_power_handle.c
@@ -25,10 +25,44 @@
 #include <linux/msm-bus.h>
 #include <linux/msm-bus-board.h>
 #include <linux/sde_io_util.h>
+#include <linux/sde_rsc.h>
 
 #include "sde_power_handle.h"
 #include "sde_trace.h"
 
+static void sde_power_event_trigger_locked(struct sde_power_handle *phandle,
+		u32 event_type)
+{
+	struct sde_power_event *event;
+
+	list_for_each_entry(event, &phandle->event_list, list) {
+		if (event->event_type & event_type)
+			event->cb_fnc(event_type, event->usr);
+	}
+}
+
+static int sde_power_rsc_update(struct sde_power_handle *phandle, bool enable)
+{
+	u32 rsc_state;
+
+	/* creates the rsc client on the first enable */
+	if (!phandle->rsc_client_init) {
+		phandle->rsc_client = sde_rsc_client_create(SDE_RSC_INDEX,
+				"sde_power_handle", false);
+		if (IS_ERR_OR_NULL(phandle->rsc_client)) {
+			pr_debug("sde rsc client create failed :%ld\n",
+						PTR_ERR(phandle->rsc_client));
+			phandle->rsc_client = NULL;
+		}
+		phandle->rsc_client_init = true;
+	}
+
+	rsc_state = enable ? SDE_RSC_CLK_STATE : SDE_RSC_IDLE_STATE;
+
+	return sde_rsc_client_state_update(phandle->rsc_client,
+			rsc_state, NULL, -1);
+}
+
 struct sde_power_client *sde_power_client_create(
 	struct sde_power_handle *phandle, char *client_name)
 {
@@ -48,6 +82,7 @@
 	strlcpy(client->name, client_name, MAX_CLIENT_NAME_LEN);
 	client->usecase_ndx = VOTE_INDEX_DISABLE;
 	client->id = id;
+	client->active = true;
 	pr_debug("client %s created:%pK id :%d\n", client_name,
 		client, id);
 	id++;
@@ -62,6 +97,9 @@
 {
 	if (!client  || !phandle) {
 		pr_err("reg bus vote: invalid client handle\n");
+	} else if (!client->active) {
+		pr_err("sde power deinit already done\n");
+		kfree(client);
 	} else {
 		pr_debug("bus vote client %s destroyed:%pK id:%u\n",
 			client->name, client, client->id);
@@ -661,6 +699,11 @@
 	}
 
 	INIT_LIST_HEAD(&phandle->power_client_clist);
+	INIT_LIST_HEAD(&phandle->event_list);
+
+	phandle->rsc_client = NULL;
+	phandle->rsc_client_init = false;
+
 	mutex_init(&phandle->phandle_lock);
 
 	return rc;
@@ -672,10 +715,12 @@
 clk_err:
 	msm_dss_config_vreg(&pdev->dev, mp->vreg_config, mp->num_vreg, 0);
 vreg_err:
-	devm_kfree(&pdev->dev, mp->vreg_config);
+	if (mp->vreg_config)
+		devm_kfree(&pdev->dev, mp->vreg_config);
 	mp->num_vreg = 0;
 parse_vreg_err:
-	devm_kfree(&pdev->dev, mp->clk_config);
+	if (mp->clk_config)
+		devm_kfree(&pdev->dev, mp->clk_config);
 	mp->num_clk = 0;
 end:
 	return rc;
@@ -685,6 +730,8 @@
 	struct sde_power_handle *phandle)
 {
 	struct dss_module_power *mp;
+	struct sde_power_client *curr_client, *next_client;
+	struct sde_power_event *curr_event, *next_event;
 
 	if (!phandle || !pdev) {
 		pr_err("invalid input param\n");
@@ -692,6 +739,26 @@
 	}
 	mp = &phandle->mp;
 
+	mutex_lock(&phandle->phandle_lock);
+	list_for_each_entry_safe(curr_client, next_client,
+			&phandle->power_client_clist, list) {
+		pr_err("cliend:%s-%d still registered with refcount:%d\n",
+				curr_client->name, curr_client->id,
+				curr_client->refcount);
+		curr_client->active = false;
+		list_del(&curr_client->list);
+	}
+
+	list_for_each_entry_safe(curr_event, next_event,
+			&phandle->event_list, list) {
+		pr_err("event:%d, client:%s still registered\n",
+				curr_event->event_type,
+				curr_event->client_name);
+		curr_event->active = false;
+		list_del(&curr_event->list);
+	}
+	mutex_unlock(&phandle->phandle_lock);
+
 	sde_power_data_bus_unregister(&phandle->data_bus_handle);
 
 	sde_power_reg_bus_unregister(phandle->reg_bus_hdl);
@@ -708,6 +775,9 @@
 
 	mp->num_vreg = 0;
 	mp->num_clk = 0;
+
+	if (phandle->rsc_client)
+		sde_rsc_client_destroy(phandle->rsc_client);
 }
 
 int sde_power_resource_enable(struct sde_power_handle *phandle,
@@ -757,6 +827,9 @@
 		goto end;
 
 	if (enable) {
+		sde_power_event_trigger_locked(phandle,
+				SDE_POWER_EVENT_PRE_ENABLE);
+
 		rc = sde_power_data_bus_update(&phandle->data_bus_handle,
 									enable);
 		if (rc) {
@@ -764,10 +837,13 @@
 			goto data_bus_hdl_err;
 		}
 
-		rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable);
-		if (rc) {
-			pr_err("failed to enable vregs rc=%d\n", rc);
-			goto vreg_err;
+		if (!phandle->rsc_client_init) {
+			rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg,
+									enable);
+			if (rc) {
+				pr_err("failed to enable vregs rc=%d\n", rc);
+				goto vreg_err;
+			}
 		}
 
 		rc = sde_power_reg_bus_update(phandle->reg_bus_hdl,
@@ -777,20 +853,39 @@
 			goto reg_bus_hdl_err;
 		}
 
+		rc = sde_power_rsc_update(phandle, true);
+		if (rc) {
+			pr_err("failed to update rsc\n");
+			goto rsc_err;
+		}
+
 		rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
 		if (rc) {
 			pr_err("clock enable failed rc:%d\n", rc);
 			goto clk_err;
 		}
+
+		sde_power_event_trigger_locked(phandle,
+				SDE_POWER_EVENT_POST_ENABLE);
+
 	} else {
+		sde_power_event_trigger_locked(phandle,
+				SDE_POWER_EVENT_PRE_DISABLE);
+
 		msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
 
+		sde_power_rsc_update(phandle, false);
+
 		sde_power_reg_bus_update(phandle->reg_bus_hdl,
 							max_usecase_ndx);
 
-		msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable);
-
+		if (!phandle->rsc_client_init)
+			msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg,
+									enable);
 		sde_power_data_bus_update(&phandle->data_bus_handle, enable);
+
+		sde_power_event_trigger_locked(phandle,
+				SDE_POWER_EVENT_POST_DISABLE);
 	}
 
 end:
@@ -798,9 +893,12 @@
 	return rc;
 
 clk_err:
+	sde_power_rsc_update(phandle, false);
+rsc_err:
 	sde_power_reg_bus_update(phandle->reg_bus_hdl, prev_usecase_ndx);
 reg_bus_hdl_err:
-	msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0);
+	if (!phandle->rsc_client_init)
+		msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0);
 vreg_err:
 	sde_power_data_bus_update(&phandle->data_bus_handle, 0);
 data_bus_hdl_err:
@@ -903,3 +1001,52 @@
 
 	return clk;
 }
+
+struct sde_power_event *sde_power_handle_register_event(
+		struct sde_power_handle *phandle,
+		u32 event_type, void (*cb_fnc)(u32 event_type, void *usr),
+		void *usr, char *client_name)
+{
+	struct sde_power_event *event;
+
+	if (!phandle) {
+		pr_err("invalid power handle\n");
+		return ERR_PTR(-EINVAL);
+	} else if (!cb_fnc || !event_type) {
+		pr_err("no callback fnc or event type\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	event = kzalloc(sizeof(struct sde_power_event), GFP_KERNEL);
+	if (!event)
+		return ERR_PTR(-ENOMEM);
+
+	event->event_type = event_type;
+	event->cb_fnc = cb_fnc;
+	event->usr = usr;
+	strlcpy(event->client_name, client_name, MAX_CLIENT_NAME_LEN);
+	event->active = true;
+
+	mutex_lock(&phandle->phandle_lock);
+	list_add(&event->list, &phandle->event_list);
+	mutex_unlock(&phandle->phandle_lock);
+
+	return event;
+}
+
+void sde_power_handle_unregister_event(
+		struct sde_power_handle *phandle,
+		struct sde_power_event *event)
+{
+	if (!phandle || !event) {
+		pr_err("invalid phandle or event\n");
+	} else if (!event->active) {
+		pr_err("power handle deinit already done\n");
+		kfree(event);
+	} else {
+		mutex_lock(&phandle->phandle_lock);
+		list_del_init(&event->list);
+		mutex_unlock(&phandle->phandle_lock);
+		kfree(event);
+	}
+}
diff --git a/drivers/gpu/drm/msm/sde_power_handle.h b/drivers/gpu/drm/msm/sde_power_handle.h
index 4e262a3..b26ef9f 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.h
+++ b/drivers/gpu/drm/msm/sde_power_handle.h
@@ -23,6 +23,18 @@
 
 #include <linux/sde_io_util.h>
 
+/* event will be triggered before power handler disable */
+#define SDE_POWER_EVENT_PRE_DISABLE	0x1
+
+/* event will be triggered after power handler disable */
+#define SDE_POWER_EVENT_POST_DISABLE	0x2
+
+/* event will be triggered before power handler enable */
+#define SDE_POWER_EVENT_PRE_ENABLE	0x4
+
+/* event will be triggered after power handler enable */
+#define SDE_POWER_EVENT_POST_ENABLE	0x8
+
 /**
  * mdss_bus_vote_type: register bus vote type
  * VOTE_INDEX_DISABLE: removes the client vote
@@ -59,6 +71,7 @@
  * @list:	list to attach power handle master list
  * @ab:         arbitrated bandwidth for each bus client
  * @ib:         instantaneous bandwidth for each bus client
+ * @active:	inidcates the state of sde power handle
  */
 struct sde_power_client {
 	char name[MAX_CLIENT_NAME_LEN];
@@ -68,6 +81,7 @@
 	struct list_head list;
 	u64 ab[SDE_POWER_HANDLE_DATA_BUS_CLIENT_MAX];
 	u64 ib[SDE_POWER_HANDLE_DATA_BUS_CLIENT_MAX];
+	bool active;
 };
 
 /**
@@ -90,6 +104,24 @@
 	u32 ao_bw_uc_idx;
 };
 
+/*
+ * struct sde_power_event - local event registration structure
+ * @client_name: name of the client registering
+ * @cb_fnc: pointer to desired callback function
+ * @usr: user pointer to pass to callback event trigger
+ * @event: refer to SDE_POWER_HANDLE_EVENT_*
+ * @list: list to attach event master list
+ * @active: indicates the state of sde power handle
+ */
+struct sde_power_event {
+	char client_name[MAX_CLIENT_NAME_LEN];
+	void (*cb_fnc)(u32 event_type, void *usr);
+	void *usr;
+	u32 event_type;
+	struct list_head list;
+	bool active;
+};
+
 /**
  * struct sde_power_handle: power handle main struct
  * @mp:		module power for clock and regulator
@@ -99,6 +131,9 @@
  * @usecase_ndx: current usecase index
  * @reg_bus_hdl: current register bus handle
  * @data_bus_handle: context structure for data bus control
+ * @event_list: current power handle event list
+ * @rsc_client: sde rsc client pointer
+ * @rsc_client_init: boolean to control rsc client create
  */
 struct sde_power_handle {
 	struct dss_module_power mp;
@@ -108,6 +143,9 @@
 	u32 current_usecase_ndx;
 	u32 reg_bus_hdl;
 	struct sde_power_data_bus_handle data_bus_handle;
+	struct list_head event_list;
+	struct sde_rsc_client *rsc_client;
+	bool rsc_client_init;
 };
 
 /**
@@ -226,4 +264,28 @@
 void sde_power_data_bus_bandwidth_ctrl(struct sde_power_handle *phandle,
 		struct sde_power_client *pclient, int enable);
 
+/**
+ * sde_power_handle_register_event - register a callback function for an event.
+ *	Clients can register for multiple events with a single register.
+ *	Any block with access to phandle can register for the event
+ *	notification.
+ * @phandle:	power handle containing the resources
+ * @event_type:	event type to register; refer SDE_POWER_HANDLE_EVENT_*
+ * @cb_fnc:	pointer to desired callback function
+ * @usr:	user pointer to pass to callback on event trigger
+ *
+ * Return:	event pointer if success, or error code otherwise
+ */
+struct sde_power_event *sde_power_handle_register_event(
+		struct sde_power_handle *phandle,
+		u32 event_type, void (*cb_fnc)(u32 event_type, void *usr),
+		void *usr, char *client_name);
+/**
+ * sde_power_handle_unregister_event - unregister callback for event(s)
+ * @phandle:	power handle containing the resources
+ * @event:	event pointer returned after power handle register
+ */
+void sde_power_handle_unregister_event(struct sde_power_handle *phandle,
+		struct sde_power_event *event);
+
 #endif /* _SDE_POWER_HANDLE_H_ */
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 6609357..c721065 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -857,13 +857,14 @@
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 	struct gmu_device *gmu = &device->gmu;
 
-	if (!IS_ERR_OR_NULL(gmu->gx_gdsc)) {
-		ret = regulator_enable(gmu->gx_gdsc);
-		if (ret) {
-			dev_err(&gmu->pdev->dev,
-					"Failed to turn on GPU HM HS\n");
-			return ret;
-		}
+	if (regulator_is_enabled(gmu->gx_gdsc))
+		return 0;
+
+	ret = regulator_enable(gmu->gx_gdsc);
+	if (ret) {
+		dev_err(&gmu->pdev->dev,
+				"Failed to turn on GPU HM HS\n");
+		return ret;
 	}
 
 	ret = clk_set_rate(pwr->grp_clks[0],
@@ -885,15 +886,15 @@
 	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
 	struct gmu_device *gmu = &device->gmu;
 
+	if (!regulator_is_enabled(gmu->gx_gdsc))
+		return 0;
+
 	clk_disable_unprepare(pwr->grp_clks[0]);
 
 	clk_set_rate(pwr->grp_clks[0],
 			pwr->pwrlevels[pwr->num_pwrlevels - 1].
 			gpu_freq);
 
-	if (IS_ERR_OR_NULL(gmu->gx_gdsc))
-		return 0;
-
 	return regulator_disable(gmu->gx_gdsc);
 }
 
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index b1f832f..2a1d352 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -137,11 +137,8 @@
 		break;
 	}
 	case KGSL_CMD_SYNCPOINT_TYPE_FENCE: {
-		char fence_str[128];
-
-		kgsl_dump_fence(sync_event->handle,
-				fence_str, sizeof(fence_str));
-		seq_printf(s, "sync: [%pK] %s", sync_event->handle, fence_str);
+		seq_printf(s, "sync: [%pK] %s", sync_event->handle,
+				sync_event->fence_name);
 		break;
 	}
 	default:
@@ -241,6 +238,9 @@
 static void drawobj_print(struct seq_file *s,
 			struct kgsl_drawobj *drawobj)
 {
+	if (!kref_get_unless_zero(&drawobj->refcount))
+		return;
+
 	if (drawobj->type == SYNCOBJ_TYPE)
 		syncobj_print(s, SYNCOBJ(drawobj));
 	else if ((drawobj->type == CMDOBJ_TYPE) ||
@@ -251,6 +251,7 @@
 	print_flags(s, drawobj_flags, ARRAY_SIZE(drawobj_flags),
 		    drawobj->flags);
 
+	kgsl_drawobj_put(drawobj);
 	seq_puts(s, "\n");
 }
 
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 9f4e185..f77d438 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -95,6 +95,9 @@
 			goto stats;
 		}
 
+		if (!kref_get_unless_zero(&drawobj->refcount))
+			goto stats;
+
 		if (drawobj->type == SYNCOBJ_TYPE) {
 			struct kgsl_drawobj_sync *syncobj = SYNCOBJ(drawobj);
 
@@ -106,6 +109,8 @@
 				kgsl_dump_syncpoints(device, syncobj);
 			}
 		}
+
+		kgsl_drawobj_put(drawobj);
 	}
 
 stats:
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 2283096..15f68bf 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1955,7 +1955,7 @@
 	}
 
 	handle = kgsl_sync_fence_async_wait(event.fd,
-		gpuobj_free_fence_func, entry);
+		gpuobj_free_fence_func, entry, NULL, 0);
 
 	/* if handle is NULL the fence has already signaled */
 	if (handle == NULL)
diff --git a/drivers/gpu/msm/kgsl_drawobj.c b/drivers/gpu/msm/kgsl_drawobj.c
index 3a87e6e..bca3d57 100644
--- a/drivers/gpu/msm/kgsl_drawobj.c
+++ b/drivers/gpu/msm/kgsl_drawobj.c
@@ -44,7 +44,7 @@
 static struct kmem_cache *sparseobjs_cache;
 
 
-static void drawobj_destroy_object(struct kref *kref)
+void kgsl_drawobj_destroy_object(struct kref *kref)
 {
 	struct kgsl_drawobj *drawobj = container_of(kref,
 		struct kgsl_drawobj, refcount);
@@ -68,12 +68,6 @@
 	}
 }
 
-static inline void drawobj_put(struct kgsl_drawobj *drawobj)
-{
-	if (drawobj)
-		kref_put(&drawobj->refcount, drawobj_destroy_object);
-}
-
 void kgsl_dump_syncpoints(struct kgsl_device *device,
 	struct kgsl_drawobj_sync *syncobj)
 {
@@ -100,16 +94,11 @@
 				retired);
 			break;
 		}
-		case KGSL_CMD_SYNCPOINT_TYPE_FENCE: {
-			char fence_str[128];
-
-			kgsl_dump_fence(event->handle,
-					fence_str, sizeof(fence_str));
-			dev_err(device->dev,
-				"  fence: %s\n", fence_str);
+		case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
+			dev_err(device->dev, "  fence: %s\n",
+					event->fence_name);
 			break;
 		}
-		}
 	}
 }
 
@@ -117,13 +106,23 @@
 {
 	struct kgsl_device *device;
 	struct kgsl_drawobj_sync *syncobj = (struct kgsl_drawobj_sync *) data;
-	struct kgsl_drawobj *drawobj = DRAWOBJ(syncobj);
+	struct kgsl_drawobj *drawobj;
 	struct kgsl_drawobj_sync_event *event;
 	unsigned int i;
 
-	if (syncobj == NULL || drawobj->context == NULL)
+	if (syncobj == NULL)
 		return;
 
+	drawobj = DRAWOBJ(syncobj);
+
+	if (!kref_get_unless_zero(&drawobj->refcount))
+		return;
+
+	if (drawobj->context == NULL) {
+		kgsl_drawobj_put(drawobj);
+		return;
+	}
+
 	device = drawobj->context->device;
 
 	dev_err(device->dev,
@@ -147,18 +146,14 @@
 			dev_err(device->dev, "       [%d] TIMESTAMP %d:%d\n",
 				i, event->context->id, event->timestamp);
 			break;
-		case KGSL_CMD_SYNCPOINT_TYPE_FENCE: {
-			char fence_str[128];
-
-			kgsl_dump_fence(event->handle,
-					fence_str, sizeof(fence_str));
+		case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
 			dev_err(device->dev, "       [%d] FENCE %s\n",
-				i, fence_str);
+					i, event->fence_name);
 			break;
 		}
-		}
 	}
 
+	kgsl_drawobj_put(drawobj);
 	dev_err(device->dev, "--gpu syncpoint deadlock print end--\n");
 }
 
@@ -204,7 +199,7 @@
 
 	drawobj_sync_expire(device, event);
 	kgsl_context_put(event->context);
-	drawobj_put(&event->syncobj->base);
+	kgsl_drawobj_put(&event->syncobj->base);
 }
 
 static inline void memobj_list_free(struct list_head *list)
@@ -265,7 +260,7 @@
 			break;
 		case KGSL_CMD_SYNCPOINT_TYPE_FENCE:
 			if (kgsl_sync_fence_async_cancel(event->handle))
-				drawobj_put(drawobj);
+				kgsl_drawobj_put(drawobj);
 			break;
 		}
 	}
@@ -321,21 +316,19 @@
 	else
 		return;
 
-	drawobj_put(drawobj);
+	kgsl_drawobj_put(drawobj);
 }
 EXPORT_SYMBOL(kgsl_drawobj_destroy);
 
 static void drawobj_sync_fence_func(void *priv)
 {
 	struct kgsl_drawobj_sync_event *event = priv;
-	char fence_str[128];
 
-	kgsl_dump_fence(event->handle, fence_str, sizeof(fence_str));
-	trace_syncpoint_fence_expire(event->syncobj, fence_str);
+	trace_syncpoint_fence_expire(event->syncobj, event->fence_name);
 
 	drawobj_sync_expire(event->device, event);
 
-	drawobj_put(&event->syncobj->base);
+	kgsl_drawobj_put(&event->syncobj->base);
 }
 
 /* drawobj_add_sync_fence() - Add a new sync fence syncpoint
@@ -352,7 +345,6 @@
 	struct kgsl_drawobj *drawobj = DRAWOBJ(syncobj);
 	struct kgsl_drawobj_sync_event *event;
 	unsigned int id;
-	char fence_str[128];
 
 	kref_get(&drawobj->refcount);
 
@@ -369,7 +361,8 @@
 	set_bit(event->id, &syncobj->pending);
 
 	event->handle = kgsl_sync_fence_async_wait(sync->fd,
-		drawobj_sync_fence_func, event);
+				drawobj_sync_fence_func, event,
+				event->fence_name, sizeof(event->fence_name));
 
 	if (IS_ERR_OR_NULL(event->handle)) {
 		int ret = PTR_ERR(event->handle);
@@ -377,7 +370,7 @@
 		clear_bit(event->id, &syncobj->pending);
 		event->handle = NULL;
 
-		drawobj_put(drawobj);
+		kgsl_drawobj_put(drawobj);
 
 		/*
 		 * If ret == 0 the fence was already signaled - print a trace
@@ -389,8 +382,7 @@
 		return ret;
 	}
 
-	kgsl_dump_fence(event->handle, fence_str, sizeof(fence_str));
-	trace_syncpoint_fence(syncobj, fence_str);
+	trace_syncpoint_fence(syncobj, event->fence_name);
 
 	return 0;
 }
@@ -457,7 +449,7 @@
 
 	if (ret) {
 		clear_bit(event->id, &syncobj->pending);
-		drawobj_put(drawobj);
+		kgsl_drawobj_put(drawobj);
 	} else {
 		trace_syncpoint_timestamp(syncobj, context, sync->timestamp);
 	}
diff --git a/drivers/gpu/msm/kgsl_drawobj.h b/drivers/gpu/msm/kgsl_drawobj.h
index 5ec98ed..06eef7f 100644
--- a/drivers/gpu/msm/kgsl_drawobj.h
+++ b/drivers/gpu/msm/kgsl_drawobj.h
@@ -105,6 +105,8 @@
 	unsigned long timeout_jiffies;
 };
 
+#define KGSL_FENCE_NAME_LEN 74
+
 /**
  * struct kgsl_drawobj_sync_event
  * @id: identifer (positiion within the pending bitmap)
@@ -114,6 +116,7 @@
  *           register this event
  * @timestamp: Pending timestamp for the event
  * @handle: Pointer to a sync fence handle
+ * @fence_name: A fence name string to describe the fence
  * @device: Pointer to the KGSL device
  */
 struct kgsl_drawobj_sync_event {
@@ -123,6 +126,7 @@
 	struct kgsl_context *context;
 	unsigned int timestamp;
 	struct kgsl_sync_fence_cb *handle;
+	char fence_name[KGSL_FENCE_NAME_LEN];
 	struct kgsl_device *device;
 };
 
@@ -206,6 +210,8 @@
 
 void kgsl_drawobj_destroy(struct kgsl_drawobj *drawobj);
 
+void kgsl_drawobj_destroy_object(struct kref *kref);
+
 static inline bool kgsl_drawobj_events_pending(
 		struct kgsl_drawobj_sync *syncobj)
 {
@@ -220,4 +226,11 @@
 
 	return test_bit(bit, &syncobj->pending);
 }
+
+static inline void kgsl_drawobj_put(struct kgsl_drawobj *drawobj)
+{
+	if (drawobj)
+		kref_put(&drawobj->refcount, kgsl_drawobj_destroy_object);
+}
+
 #endif /* __KGSL_DRAWOBJ_H */
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 9c078b6..973a2ff 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -431,8 +431,27 @@
 	kfree(kcb);
 }
 
+static void kgsl_get_fence_name(struct fence *fence,
+	char *fence_name, int name_len)
+{
+	char *ptr = fence_name;
+	char *last = fence_name + name_len;
+
+	ptr +=  snprintf(ptr, last - ptr, "%s %s",
+			fence->ops->get_driver_name(fence),
+			fence->ops->get_timeline_name(fence));
+
+	if ((ptr + 2) >= last)
+		return;
+
+	if (fence->ops->fence_value_str) {
+		ptr += snprintf(ptr, last - ptr, ": ");
+		fence->ops->fence_value_str(fence, ptr, last - ptr);
+	}
+}
+
 struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
-	void (*func)(void *priv), void *priv)
+	void (*func)(void *priv), void *priv, char *fence_name, int name_len)
 {
 	struct kgsl_sync_fence_cb *kcb;
 	struct fence *fence;
@@ -453,6 +472,9 @@
 	kcb->priv = priv;
 	kcb->func = func;
 
+	if (fence_name)
+		kgsl_get_fence_name(fence, fence_name, name_len);
+
 	/* if status then error or signaled */
 	status = fence_add_callback(fence, &kcb->fence_cb,
 				kgsl_sync_fence_callback);
@@ -789,43 +811,3 @@
 	.release = kgsl_syncsource_fence_release,
 };
 
-void kgsl_dump_fence(struct kgsl_sync_fence_cb *handle,
-				char *fence_str, int len)
-{
-	struct fence *fence;
-	char *ptr = fence_str;
-	char *last = fence_str + len;
-
-	if (!handle || !handle->fence) {
-		snprintf(fence_str, len, "NULL");
-		return;
-	}
-
-	fence = handle->fence;
-
-	ptr += snprintf(ptr, last - ptr, "%s %s",
-			fence->ops->get_timeline_name(fence),
-			fence->ops->get_driver_name(fence));
-	if (ptr >= last)
-		return;
-
-	if (fence->ops->timeline_value_str &&
-		fence->ops->fence_value_str) {
-		char value[64];
-		bool success;
-
-		fence->ops->fence_value_str(fence, value, sizeof(value));
-		success = !!strlen(value);
-
-		if (success) {
-			ptr += snprintf(ptr, last - ptr, ": %s", value);
-			if (ptr >= last)
-				return;
-
-			fence->ops->timeline_value_str(fence, value,
-							sizeof(value));
-			ptr += snprintf(ptr, last - ptr, " / %s", value);
-		}
-	}
-}
-
diff --git a/drivers/gpu/msm/kgsl_sync.h b/drivers/gpu/msm/kgsl_sync.h
index dc84c54..99fe0e1 100644
--- a/drivers/gpu/msm/kgsl_sync.h
+++ b/drivers/gpu/msm/kgsl_sync.h
@@ -91,7 +91,8 @@
 void kgsl_sync_timeline_put(struct kgsl_sync_timeline *ktimeline);
 
 struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
-					void (*func)(void *priv), void *priv);
+					void (*func)(void *priv), void *priv,
+					char *fence_name, int name_len);
 
 int kgsl_sync_fence_async_cancel(struct kgsl_sync_fence_cb *kcb);
 
@@ -109,8 +110,8 @@
 void kgsl_syncsource_cleanup(struct kgsl_process_private *private,
 					struct kgsl_syncsource *syncsource);
 
-void kgsl_dump_fence(struct kgsl_sync_fence_cb *handle,
-				char *fence_str, int len);
+void kgsl_dump_fence(struct kgsl_drawobj_sync_event *event,
+					char *fence_str, int len);
 
 #else
 static inline int kgsl_add_fence_event(struct kgsl_device *device,
@@ -134,8 +135,10 @@
 {
 }
 
-static inline struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
-					void (*func)(void *priv), void *priv)
+
+struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
+					void (*func)(void *priv), void *priv,
+					char *fence_name, int name_len)
 {
 	return NULL;
 }
@@ -185,8 +188,8 @@
 
 }
 
-void kgsl_dump_fence(struct kgsl_sync_fence_cb *handle,
-				char *fence_str, int len)
+void kgsl_dump_fence(struct kgsl_drawobj_sync_event *event,
+					char *fence_str, int len)
 {
 }
 
diff --git a/drivers/hwtracing/coresight/coresight-cti.c b/drivers/hwtracing/coresight/coresight-cti.c
index a2ce81a..8a57ed2 100644
--- a/drivers/hwtracing/coresight/coresight-cti.c
+++ b/drivers/hwtracing/coresight/coresight-cti.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-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
@@ -19,7 +19,7 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
-#include <linux/clk.h>
+#include <linux/amba/bus.h>
 #include <linux/cpu_pm.h>
 #include <linux/topology.h>
 #include <linux/of.h>
@@ -379,7 +379,7 @@
 	 * within the mutex lock region in addition to within the spinlock.
 	 */
 	if (drvdata->refcnt == 0) {
-		ret = clk_prepare_enable(drvdata->clk);
+		ret = pm_runtime_get_sync(drvdata->dev);
 		if (ret)
 			goto err1;
 	}
@@ -402,7 +402,7 @@
 	 * adjusting its value.
 	 */
 	if (drvdata->refcnt == 0)
-		clk_disable_unprepare(drvdata->clk);
+		pm_runtime_put(drvdata->dev);
 err1:
 	cti_trigin_gpio_disable(drvdata);
 err0:
@@ -463,7 +463,7 @@
 	 * within the mutex lock region in addition to within the spinlock.
 	 */
 	if (drvdata->refcnt == 0) {
-		ret = clk_prepare_enable(drvdata->clk);
+		ret = pm_runtime_get_sync(drvdata->dev);
 		if (ret)
 			goto err1;
 	}
@@ -485,7 +485,7 @@
 	 * __cti_map_trigout so it is safe to check it against 0.
 	 */
 	if (drvdata->refcnt == 0)
-		clk_disable_unprepare(drvdata->clk);
+		pm_runtime_put(drvdata->dev);
 err1:
 	cti_trigout_gpio_disable(drvdata);
 err0:
@@ -563,7 +563,7 @@
 	 * within the mutex lock region in addition to within the spinlock.
 	 */
 	if (drvdata->refcnt == 0)
-		clk_disable_unprepare(drvdata->clk);
+		pm_runtime_put(drvdata->dev);
 
 	if (drvdata->gpio_trigin->trig == trig)
 		cti_trigin_gpio_disable(drvdata);
@@ -632,7 +632,7 @@
 	 * within the mutex lock region in addition to within the spinlock.
 	 */
 	if (drvdata->refcnt == 0)
-		clk_disable_unprepare(drvdata->clk);
+		pm_runtime_put(drvdata->dev);
 
 	if (drvdata->gpio_trigout->trig == trig)
 		cti_trigout_gpio_disable(drvdata);
@@ -1388,34 +1388,29 @@
 	.notifier_call = cti_cpu_pm_callback,
 };
 
-static int cti_probe(struct platform_device *pdev)
+static int cti_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	int ret;
 	int trig;
-	struct device *dev = &pdev->dev;
+	struct device *dev = &adev->dev;
 	struct coresight_platform_data *pdata;
 	struct cti_drvdata *drvdata;
-	struct resource *res;
 	struct coresight_desc *desc;
 	struct device_node *cpu_node;
 
-	pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+	pdata = of_get_coresight_platform_data(dev, adev->dev.of_node);
 	if (IS_ERR(pdata))
 		return PTR_ERR(pdata);
-	pdev->dev.platform_data = pdata;
+	adev->dev.platform_data = pdata;
 
 	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
 	if (!drvdata)
 		return -ENOMEM;
 	/* Store the driver data pointer for use in exported functions */
-	drvdata->dev = &pdev->dev;
-	platform_set_drvdata(pdev, drvdata);
+	drvdata->dev = &adev->dev;
+	dev_set_drvdata(dev, drvdata);
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cti-base");
-	if (!res)
-		return -ENODEV;
-
-	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	drvdata->base = devm_ioremap_resource(dev, &adev->res);
 	if (!drvdata->base)
 		return -ENOMEM;
 
@@ -1423,21 +1418,13 @@
 
 	mutex_init(&drvdata->mutex);
 
-	drvdata->clk = devm_clk_get(dev, "core_clk");
-	if (IS_ERR(drvdata->clk))
-		return PTR_ERR(drvdata->clk);
-
-	ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
-	if (ret)
-		return ret;
-
 	drvdata->gpio_trigin = devm_kzalloc(dev, sizeof(struct cti_pctrl),
 					    GFP_KERNEL);
 	if (!drvdata->gpio_trigin)
 		return -ENOMEM;
 
 	drvdata->gpio_trigin->trig = -1;
-	ret = of_property_read_u32(pdev->dev.of_node,
+	ret = of_property_read_u32(adev->dev.of_node,
 				   "qcom,cti-gpio-trigin", &trig);
 	if (!ret)
 		drvdata->gpio_trigin->trig = trig;
@@ -1450,7 +1437,7 @@
 		return -ENOMEM;
 
 	drvdata->gpio_trigout->trig = -1;
-	ret = of_property_read_u32(pdev->dev.of_node,
+	ret = of_property_read_u32(adev->dev.of_node,
 				   "qcom,cti-gpio-trigout", &trig);
 	if (!ret)
 		drvdata->gpio_trigout->trig = trig;
@@ -1458,7 +1445,7 @@
 		return ret;
 
 	drvdata->cpu = -1;
-	cpu_node = of_parse_phandle(pdev->dev.of_node, "cpu", 0);
+	cpu_node = of_parse_phandle(adev->dev.of_node, "cpu", 0);
 	if (cpu_node) {
 		drvdata->cpu = pdata ? pdata->cpu : -1;
 		if (drvdata->cpu == -1) {
@@ -1468,7 +1455,7 @@
 	}
 
 	if (!cti_save_disable)
-		drvdata->cti_save = of_property_read_bool(pdev->dev.of_node,
+		drvdata->cti_save = of_property_read_bool(adev->dev.of_node,
 							  "qcom,cti-save");
 	if (drvdata->cti_save) {
 		drvdata->state = devm_kzalloc(dev, sizeof(struct cti_state),
@@ -1476,18 +1463,18 @@
 		if (!drvdata->state)
 			return -ENOMEM;
 
-		drvdata->cti_hwclk = of_property_read_bool(pdev->dev.of_node,
+		drvdata->cti_hwclk = of_property_read_bool(adev->dev.of_node,
 							   "qcom,cti-hwclk");
 	}
 	if (drvdata->cti_save && !drvdata->cti_hwclk) {
-		ret = clk_prepare_enable(drvdata->clk);
+		ret = pm_runtime_get_sync(drvdata->dev);
 		if (ret)
 			return ret;
 	}
 
 	mutex_lock(&cti_lock);
 	drvdata->cti.name = ((struct coresight_platform_data *)
-			     (pdev->dev.platform_data))->name;
+			     (adev->dev.platform_data))->name;
 	list_add_tail(&drvdata->cti.link, &cti_list);
 	mutex_unlock(&cti_lock);
 
@@ -1497,8 +1484,8 @@
 		goto err;
 	}
 	desc->type = CORESIGHT_DEV_TYPE_NONE;
-	desc->pdata = pdev->dev.platform_data;
-	desc->dev = &pdev->dev;
+	desc->pdata = adev->dev.platform_data;
+	desc->dev = &adev->dev;
 	desc->groups = cti_attr_grps;
 	drvdata->csdev = coresight_register(desc);
 	if (IS_ERR(drvdata->csdev)) {
@@ -1511,56 +1498,35 @@
 			cpu_pm_register_notifier(&cti_cpu_pm_notifier);
 		registered++;
 	}
-
+	pm_runtime_put(&adev->dev);
 	dev_dbg(dev, "CTI initialized\n");
 	return 0;
 err:
 	if (drvdata->cti_save && !drvdata->cti_hwclk)
-		clk_disable_unprepare(drvdata->clk);
+		pm_runtime_put(&adev->dev);
 	return ret;
 }
 
-static int cti_remove(struct platform_device *pdev)
-{
-	struct cti_drvdata *drvdata = platform_get_drvdata(pdev);
-
-	if (drvdata->cti_save) {
-		registered--;
-		if (!registered)
-			cpu_pm_unregister_notifier(&cti_cpu_pm_notifier);
-	}
-	coresight_unregister(drvdata->csdev);
-	if (drvdata->cti_save && !drvdata->cti_hwclk)
-		clk_disable_unprepare(drvdata->clk);
-	return 0;
-}
-
-static const struct of_device_id cti_match[] = {
-	{.compatible = "arm,coresight-cti"},
-	{}
+static struct amba_id cti_ids[] = {
+	{
+		.id     = 0x0003b966,
+		.mask   = 0x0003ffff,
+		.data	= "CTI",
+	},
+	{ 0, 0},
 };
 
-static struct platform_driver cti_driver = {
-	.probe          = cti_probe,
-	.remove         = cti_remove,
-	.driver         = {
+static struct amba_driver cti_driver = {
+	.drv = {
 		.name   = "coresight-cti",
 		.owner	= THIS_MODULE,
-		.of_match_table = cti_match,
+		.suppress_bind_attrs = true,
 	},
+	.probe          = cti_probe,
+	.id_table	= cti_ids,
 };
 
-static int __init cti_init(void)
-{
-	return platform_driver_register(&cti_driver);
-}
-module_init(cti_init);
-
-static void __exit cti_exit(void)
-{
-	platform_driver_unregister(&cti_driver);
-}
-module_exit(cti_exit);
+builtin_amba_driver(cti_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("CoreSight CTI driver");
diff --git a/drivers/hwtracing/coresight/coresight-replicator-qcom.c b/drivers/hwtracing/coresight/coresight-replicator-qcom.c
index 0bd8b78..98547a9 100644
--- a/drivers/hwtracing/coresight/coresight-replicator-qcom.c
+++ b/drivers/hwtracing/coresight/coresight-replicator-qcom.c
@@ -47,8 +47,6 @@
 {
 	struct replicator_state *drvdata = dev_get_drvdata(csdev->dev.parent);
 
-	pm_runtime_get_sync(drvdata->dev);
-
 	CS_UNLOCK(drvdata->base);
 
 	/*
@@ -85,7 +83,6 @@
 
 	CS_LOCK(drvdata->base);
 
-	pm_runtime_put(drvdata->dev);
 	dev_info(drvdata->dev, "REPLICATOR disabled\n");
 }
 
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index f5018fc..10e8da4 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -436,8 +436,11 @@
 		if (ret)
 			drvdata->size = SZ_1M;
 
+		if (of_property_read_bool(np, "arm,sg-enable"))
+			drvdata->memtype  = TMC_ETR_MEM_TYPE_SG;
+		else
+			drvdata->memtype  = TMC_ETR_MEM_TYPE_CONTIG;
 		drvdata->mem_size = drvdata->size;
-		drvdata->memtype  = TMC_ETR_MEM_TYPE_CONTIG;
 		drvdata->mem_type = drvdata->memtype;
 	} else {
 		drvdata->size = readl_relaxed(drvdata->base + TMC_RSZ) * 4;
diff --git a/drivers/hwtracing/coresight/coresight-tpda.c b/drivers/hwtracing/coresight/coresight-tpda.c
index c96087d..5d2d087 100644
--- a/drivers/hwtracing/coresight/coresight-tpda.c
+++ b/drivers/hwtracing/coresight/coresight-tpda.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-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
@@ -14,10 +14,10 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
+#include <linux/amba/bus.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/fs.h>
-#include <linux/clk.h>
 #include <linux/bitmap.h>
 #include <linux/of.h>
 #include <linux/coresight.h>
@@ -53,7 +53,6 @@
 	void __iomem		*base;
 	struct device		*dev;
 	struct coresight_device	*csdev;
-	struct clk		*clk;
 	struct mutex		lock;
 	bool			enable;
 	uint32_t		atid;
@@ -183,11 +182,6 @@
 static int tpda_enable(struct coresight_device *csdev, int inport, int outport)
 {
 	struct tpda_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-	int ret;
-
-	ret = clk_prepare_enable(drvdata->clk);
-	if (ret)
-		return ret;
 
 	mutex_lock(&drvdata->lock);
 	__tpda_enable(drvdata, inport);
@@ -221,8 +215,6 @@
 	drvdata->enable = false;
 	mutex_unlock(&drvdata->lock);
 
-	clk_disable_unprepare(drvdata->clk);
-
 	dev_info(drvdata->dev, "TPDA inport %d disabled\n", inport);
 }
 
@@ -653,31 +645,27 @@
 	drvdata->freq_ts = true;
 }
 
-static int tpda_probe(struct platform_device *pdev)
+static int tpda_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	int ret;
-	struct device *dev = &pdev->dev;
+	struct device *dev = &adev->dev;
 	struct coresight_platform_data *pdata;
 	struct tpda_drvdata *drvdata;
-	struct resource *res;
 	struct coresight_desc *desc;
 
-	pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+	pdata = of_get_coresight_platform_data(dev, adev->dev.of_node);
 	if (IS_ERR(pdata))
 		return PTR_ERR(pdata);
-	pdev->dev.platform_data = pdata;
+	adev->dev.platform_data = pdata;
 
 	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
 	if (!drvdata)
 		return -ENOMEM;
-	drvdata->dev = &pdev->dev;
-	platform_set_drvdata(pdev, drvdata);
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tpda-base");
-	if (!res)
-		return -ENODEV;
+	drvdata->dev = &adev->dev;
+	dev_set_drvdata(dev, drvdata);
 
-	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	drvdata->base = devm_ioremap_resource(dev, &adev->res);
 	if (!drvdata->base)
 		return -ENOMEM;
 
@@ -687,22 +675,10 @@
 	if (ret)
 		return ret;
 
-	drvdata->clk = devm_clk_get(dev, "core_clk");
-	if (IS_ERR(drvdata->clk))
-		return PTR_ERR(drvdata->clk);
-
-	ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
-	if (ret)
-		return ret;
-
-	ret = clk_prepare_enable(drvdata->clk);
-	if (ret)
-		return ret;
-
 	if (!coresight_authstatus_enabled(drvdata->base))
 		goto err;
 
-	clk_disable_unprepare(drvdata->clk);
+	pm_runtime_put(&adev->dev);
 
 	tpda_init_default_data(drvdata);
 
@@ -712,8 +688,8 @@
 	desc->type = CORESIGHT_DEV_TYPE_LINK;
 	desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
 	desc->ops = &tpda_cs_ops;
-	desc->pdata = pdev->dev.platform_data;
-	desc->dev = &pdev->dev;
+	desc->pdata = adev->dev.platform_data;
+	desc->dev = &adev->dev;
 	desc->groups = tpda_attr_grps;
 	drvdata->csdev = coresight_register(desc);
 	if (IS_ERR(drvdata->csdev))
@@ -722,44 +698,29 @@
 	dev_dbg(drvdata->dev, "TPDA initialized\n");
 	return 0;
 err:
-	clk_disable_unprepare(drvdata->clk);
 	return -EPERM;
 }
 
-static int tpda_remove(struct platform_device *pdev)
-{
-	struct tpda_drvdata *drvdata = platform_get_drvdata(pdev);
-
-	coresight_unregister(drvdata->csdev);
-	return 0;
-}
-
-static const struct of_device_id tpda_match[] = {
-	{.compatible = "qcom,coresight-tpda"},
-	{}
+static struct amba_id tpda_ids[] = {
+	{
+		.id     = 0x0003b969,
+		.mask   = 0x0003ffff,
+		.data	= "TPDA",
+	},
+	{ 0, 0},
 };
 
-static struct platform_driver tpda_driver = {
-	.probe          = tpda_probe,
-	.remove         = tpda_remove,
-	.driver         = {
+static struct amba_driver tpda_driver = {
+	.drv = {
 		.name   = "coresight-tpda",
 		.owner	= THIS_MODULE,
-		.of_match_table = tpda_match,
+		.suppress_bind_attrs = true,
 	},
+	.probe          = tpda_probe,
+	.id_table	= tpda_ids,
 };
 
-static int __init tpda_init(void)
-{
-	return platform_driver_register(&tpda_driver);
-}
-module_init(tpda_init);
-
-static void __exit tpda_exit(void)
-{
-	platform_driver_unregister(&tpda_driver);
-}
-module_exit(tpda_exit);
+builtin_amba_driver(tpda_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Aggregator driver");
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 69511cd..36e3db2 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -13,11 +13,10 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/device.h>
-#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/fs.h>
-#include <linux/clk.h>
 #include <linux/bitmap.h>
 #include <linux/of.h>
 #include <linux/coresight.h>
@@ -246,7 +245,6 @@
 	void __iomem		*base;
 	struct device		*dev;
 	struct coresight_device	*csdev;
-	struct clk		*clk;
 	struct mutex		lock;
 	bool			enable;
 	bool			clk_enable;
@@ -648,11 +646,6 @@
 		       struct perf_event *event, u32 mode)
 {
 	struct tpdm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-	int ret;
-
-	ret = clk_prepare_enable(drvdata->clk);
-	if (ret)
-		return ret;
 
 	mutex_lock(&drvdata->lock);
 	__tpdm_enable(drvdata);
@@ -732,8 +725,6 @@
 	drvdata->enable = false;
 	mutex_unlock(&drvdata->lock);
 
-	clk_disable_unprepare(drvdata->clk);
-
 	dev_info(drvdata->dev, "TPDM tracing disabled\n");
 }
 
@@ -3939,57 +3930,40 @@
 		drvdata->cmb->trig_ts = true;
 }
 
-static int tpdm_probe(struct platform_device *pdev)
+static int tpdm_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	int ret, i;
 	uint32_t pidr, devid;
-	struct device *dev = &pdev->dev;
+	struct device *dev = &adev->dev;
 	struct coresight_platform_data *pdata;
 	struct tpdm_drvdata *drvdata;
-	struct resource *res;
 	struct coresight_desc *desc;
 	static int traceid = TPDM_TRACE_ID_START;
 	uint32_t version;
 
-	pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+	pdata = of_get_coresight_platform_data(dev, adev->dev.of_node);
 	if (IS_ERR(pdata))
 		return PTR_ERR(pdata);
-	pdev->dev.platform_data = pdata;
+	adev->dev.platform_data = pdata;
 
 	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
 	if (!drvdata)
 		return -ENOMEM;
-	drvdata->dev = &pdev->dev;
-	platform_set_drvdata(pdev, drvdata);
+	drvdata->dev = &adev->dev;
+	dev_set_drvdata(dev, drvdata);
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tpdm-base");
-	if (!res)
-		return -ENODEV;
-
-	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	drvdata->base = devm_ioremap_resource(dev, &adev->res);
 	if (!drvdata->base)
 		return -ENOMEM;
 
-	drvdata->clk_enable = of_property_read_bool(pdev->dev.of_node,
+	drvdata->clk_enable = of_property_read_bool(adev->dev.of_node,
 						    "qcom,clk-enable");
 
-	drvdata->msr_fix_req = of_property_read_bool(pdev->dev.of_node,
+	drvdata->msr_fix_req = of_property_read_bool(adev->dev.of_node,
 						     "qcom,msr-fix-req");
 
 	mutex_init(&drvdata->lock);
 
-	drvdata->clk = devm_clk_get(dev, "core_clk");
-	if (IS_ERR(drvdata->clk))
-		return PTR_ERR(drvdata->clk);
-
-	ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
-	if (ret)
-		return ret;
-
-	ret = clk_prepare_enable(drvdata->clk);
-	if (ret)
-		return ret;
-
 	version = tpdm_readl(drvdata, CORESIGHT_PERIPHIDR2);
 	drvdata->version = BMVAL(version, 4, 7);
 
@@ -4017,7 +3991,7 @@
 	drvdata->bc_counters_avail = BMVAL(devid, 6, 10) + 1;
 	drvdata->tc_counters_avail = BMVAL(devid, 4, 5) + 1;
 
-	clk_disable_unprepare(drvdata->clk);
+	pm_runtime_put(&adev->dev);
 
 	drvdata->traceid = traceid++;
 
@@ -4027,8 +4001,8 @@
 	desc->type = CORESIGHT_DEV_TYPE_SOURCE;
 	desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
 	desc->ops = &tpdm_cs_ops;
-	desc->pdata = pdev->dev.platform_data;
-	desc->dev = &pdev->dev;
+	desc->pdata = adev->dev.platform_data;
+	desc->dev = &adev->dev;
 	desc->groups = tpdm_attr_grps;
 	drvdata->csdev = coresight_register(desc);
 	if (IS_ERR(drvdata->csdev))
@@ -4042,40 +4016,26 @@
 	return 0;
 }
 
-static int tpdm_remove(struct platform_device *pdev)
-{
-	struct tpdm_drvdata *drvdata = platform_get_drvdata(pdev);
-
-	coresight_unregister(drvdata->csdev);
-	return 0;
-}
-
-static const struct of_device_id tpdm_match[] = {
-	{.compatible = "qcom,coresight-tpdm"},
-	{}
+static struct amba_id tpdm_ids[] = {
+	{
+		.id     = 0x0003b968,
+		.mask   = 0x0003ffff,
+		.data	= "TPDM",
+	},
+	{ 0, 0},
 };
 
-static struct platform_driver tpdm_driver = {
-	.probe          = tpdm_probe,
-	.remove         = tpdm_remove,
-	.driver         = {
+static struct amba_driver tpdm_driver = {
+	.drv = {
 		.name   = "coresight-tpdm",
 		.owner	= THIS_MODULE,
-		.of_match_table = tpdm_match,
+		.suppress_bind_attrs = true,
 	},
+	.probe          = tpdm_probe,
+	.id_table	= tpdm_ids,
 };
 
-static int __init tpdm_init(void)
-{
-	return platform_driver_register(&tpdm_driver);
-}
-module_init(tpdm_init);
-
-static void __exit tpdm_exit(void)
-{
-	platform_driver_unregister(&tpdm_driver);
-}
-module_exit(tpdm_exit);
+builtin_amba_driver(tpdm_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("Trace, Profiling & Diagnostic Monitor driver");
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 1864e76..dd96670 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -4375,7 +4375,7 @@
 	/* Attempt to register child devices */
 	ret = device_for_each_child(dev, smmu, qsmmuv500_tbu_register);
 	if (ret)
-		return -EINVAL;
+		return -EPROBE_DEFER;
 
 	return 0;
 }
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index c90fbf0..261c125 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1750,3 +1750,23 @@
 	return 0;
 }
 EXPORT_SYMBOL_GPL(iommu_fwspec_add_ids);
+
+/*
+ * Return the id asoociated with a pci device.
+ */
+int iommu_fwspec_get_id(struct device *dev, u32 *id)
+{
+	struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+
+	if (!fwspec)
+		return -EINVAL;
+
+	if (!dev_is_pci(dev))
+		return -EINVAL;
+
+	if (fwspec->num_ids != 1)
+		return -EINVAL;
+
+	*id = fwspec->ids[0];
+	return 0;
+}
diff --git a/drivers/mailbox/qti-tcs.c b/drivers/mailbox/qti-tcs.c
index a9ddf0f..96b4472 100644
--- a/drivers/mailbox/qti-tcs.c
+++ b/drivers/mailbox/qti-tcs.c
@@ -15,6 +15,7 @@
 
 #include <linux/atomic.h>
 #include <linux/bitmap.h>
+#include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/kernel.h>
@@ -86,6 +87,7 @@
 #define TCS_TYPE_NR			4
 #define TCS_MBOX_TOUT_MS		2000
 #define MAX_POOL_SIZE			(MAX_TCS_PER_TYPE * TCS_TYPE_NR)
+#define TCS_M_INIT			0xFFFF
 
 struct tcs_drv;
 
@@ -97,10 +99,12 @@
 	struct tasklet_struct tasklet;
 	struct delayed_work dwork;
 	int err;
+	int idx;
+	bool in_use;
 };
 
 struct tcs_response_pool {
-	struct tcs_response *resp;
+	struct tcs_response resp[MAX_POOL_SIZE];
 	spinlock_t lock;
 	DECLARE_BITMAP(avail, MAX_POOL_SIZE);
 };
@@ -116,8 +120,6 @@
 	int ncpt; /* num cmds per tcs */
 	DECLARE_BITMAP(slots, MAX_TCS_SLOTS);
 	spinlock_t tcs_lock; /* TCS type lock */
-	spinlock_t tcs_m_lock[MAX_TCS_PER_TYPE];
-	struct tcs_response *resp[MAX_TCS_PER_TYPE];
 };
 
 /* One per MBOX controller */
@@ -148,16 +150,13 @@
 	if (!pool)
 		return -ENOMEM;
 
-	pool->resp = devm_kzalloc(&drv->pdev->dev, sizeof(*pool->resp) *
-				MAX_POOL_SIZE, GFP_KERNEL);
-	if (!pool->resp)
-		return -ENOMEM;
-
 	for (i = 0; i < MAX_POOL_SIZE; i++) {
 		tasklet_init(&pool->resp[i].tasklet, tcs_notify_tx_done,
 						(unsigned long) &pool->resp[i]);
-		INIT_DELAYED_WORK(&pool->resp[i].dwork,
-						tcs_notify_timeout);
+		INIT_DELAYED_WORK(&pool->resp[i].dwork, tcs_notify_timeout);
+		pool->resp[i].drv = drv;
+		pool->resp[i].idx = i;
+		pool->resp[i].m = TCS_M_INIT;
 	}
 
 	spin_lock_init(&pool->lock);
@@ -166,39 +165,59 @@
 	return 0;
 }
 
-static struct tcs_response *get_response_from_pool(struct tcs_drv *drv)
+static struct tcs_response *setup_response(struct tcs_drv *drv,
+		struct tcs_mbox_msg *msg, struct mbox_chan *chan,
+		u32 m, int err)
 {
 	struct tcs_response_pool *pool = drv->resp_pool;
 	struct tcs_response *resp = ERR_PTR(-ENOMEM);
-	unsigned long flags;
 	int pos;
 
-	spin_lock_irqsave(&pool->lock, flags);
+	spin_lock(&pool->lock);
 	pos = find_first_zero_bit(pool->avail, MAX_POOL_SIZE);
 	if (pos != MAX_POOL_SIZE) {
 		bitmap_set(pool->avail, pos, 1);
 		resp = &pool->resp[pos];
-		memset(resp, 0, sizeof(*resp));
-		tasklet_init(&resp->tasklet, tcs_notify_tx_done,
-						(unsigned long) resp);
-		INIT_DELAYED_WORK(&resp->dwork, tcs_notify_timeout);
-		resp->drv = drv;
+		resp->chan = chan;
+		resp->msg = msg;
+		resp->m = m;
+		resp->err = err;
+		resp->in_use = false;
 	}
-	spin_unlock_irqrestore(&pool->lock, flags);
+	spin_unlock(&pool->lock);
 
 	return resp;
 }
 
-static void free_response_to_pool(struct tcs_response *resp)
+static void free_response(struct tcs_response *resp)
 {
 	struct tcs_response_pool *pool = resp->drv->resp_pool;
-	unsigned long flags;
-	int i;
 
-	spin_lock_irqsave(&pool->lock, flags);
-	i = resp - pool->resp;
-	bitmap_clear(pool->avail, i, 1);
-	spin_unlock_irqrestore(&pool->lock, flags);
+	spin_lock(&pool->lock);
+	resp->err = -EINVAL;
+	bitmap_clear(pool->avail, resp->idx, 1);
+	spin_unlock(&pool->lock);
+}
+
+static inline struct tcs_response *get_response(struct tcs_drv *drv, u32 m)
+{
+	struct tcs_response_pool *pool = drv->resp_pool;
+	struct tcs_response *resp = NULL;
+	int pos = 0;
+
+	do {
+		pos = find_next_bit(pool->avail, MAX_POOL_SIZE, pos);
+		if (pos == MAX_POOL_SIZE)
+			break;
+		resp = &pool->resp[pos];
+		if (resp->m == m && !resp->in_use) {
+			resp->in_use = true;
+			break;
+		}
+		pos++;
+	} while (1);
+
+	return resp;
 }
 
 static inline u32 read_drv_config(void __iomem *base)
@@ -226,7 +245,7 @@
 		write_tcs_reg(base, reg, m, n, data);
 		if (data == read_tcs_reg(base, reg, m, n))
 			break;
-		cpu_relax();
+		udelay(1);
 	} while (1);
 }
 
@@ -311,13 +330,6 @@
 	return get_tcs_of_type(drv, type);
 }
 
-static inline struct tcs_response *get_tcs_response(struct tcs_drv *drv, int m)
-{
-	struct tcs_mbox *tcs = get_tcs_from_index(drv, m);
-
-	return tcs ? tcs->resp[m - tcs->tcs_offset] : NULL;
-}
-
 static inline void send_tcs_response(struct tcs_response *resp)
 {
 	tasklet_schedule(&resp->tasklet);
@@ -340,7 +352,6 @@
 	struct tcs_mbox *tcs;
 	struct tcs_response *resp;
 	struct tcs_cmd *cmd;
-	u32 irq_clear = 0;
 	u32 data;
 
 	/* Know which TCSes were triggered */
@@ -350,8 +361,7 @@
 		if (!(irq_status & BIT(m)))
 			continue;
 
-		/* Find the TCS that triggered */
-		resp = get_tcs_response(drv, m);
+		resp = get_response(drv, m);
 		if (!resp) {
 			pr_err("No resp request for TCS-%d\n", m);
 			continue;
@@ -397,18 +407,13 @@
 			write_tcs_reg(base, TCS_DRV_CMD_ENABLE, m, 0, 0);
 		}
 
-		/* Notify the client that this request is completed. */
+		/* Clear the TCS IRQ status */
+		write_tcs_reg(base, TCS_DRV_IRQ_CLEAR, 0, 0, BIT(m));
+
+		/* Clean up response object and notify mbox in tasklet */
 		send_tcs_response(resp);
-		irq_clear |= BIT(m);
-	}
 
-	/* Clear the TCS IRQ status */
-	write_tcs_reg(base, TCS_DRV_IRQ_CLEAR, 0, 0, irq_clear);
-
-	/* Mark the TCS as free */
-	for (m = 0; irq_status >= BIT(m); m++) {
-		if (!(irq_status & BIT(m)))
-			continue;
+		/* Notify the client that this request is completed. */
 		atomic_set(&drv->tcs_in_use[m], 0);
 	}
 
@@ -435,8 +440,8 @@
 	int err = resp->err;
 	int m = resp->m;
 
-	free_response_to_pool(resp);
 	mbox_notify_tx_done(chan, msg, m, err);
+	free_response(resp);
 }
 
 /**
@@ -468,7 +473,7 @@
 			cmd = &msg->payload[i];
 			addr = read_tcs_reg(drv->reg_base, TCS_DRV_CMD_ADDR,
 						m, i);
-			pending = (cmd->addr == addr);
+			pending |= (cmd->addr == addr);
 		}
 		if (pending) {
 			pr_err("TCS-%d blocked waiting for RPMH to respond.\n",
@@ -481,8 +486,8 @@
 		}
 	}
 
-	free_response_to_pool(resp);
 	mbox_notify_tx_done(chan, msg, -1, -ETIMEDOUT);
+	free_response(resp);
 }
 
 static void __tcs_buffer_write(struct tcs_drv *drv, int d, int m, int n,
@@ -525,8 +530,6 @@
 	write_tcs_reg(base, TCS_DRV_CMD_ENABLE, m, 0, cmd_enable);
 
 	if (trigger) {
-		/* Mark the TCS as busy */
-		atomic_set(&drv->tcs_in_use[m], 1);
 		/* HW req: Clear the DRV_CONTROL and enable TCS again */
 		write_tcs_reg_sync(base, TCS_DRV_CONTROL, m, 0, 0);
 		write_tcs_reg_sync(base, TCS_DRV_CONTROL, m, 0, enable);
@@ -590,13 +593,14 @@
 		}
 retry:
 		if (!is_free)
-			cpu_relax();
+			udelay(1);
 	} while (!is_free);
 }
 
 static int find_free_tcs(struct tcs_mbox *tcs)
 {
 	int slot, m = 0;
+	u32 irq_status;
 
 	/* Loop until we find a free AMC */
 	do {
@@ -604,9 +608,14 @@
 			slot = m * tcs->ncpt;
 			break;
 		}
-		if (++m >= tcs->num_tcs)
+		if (++m >= tcs->num_tcs) {
 			m = 0;
-		cpu_relax();
+			irq_status = read_tcs_reg(tcs->drv->reg_base,
+						TCS_DRV_IRQ_STATUS, 0, 0);
+			WARN((irq_status & tcs->tcs_mask && in_irq()),
+				"TCS busy. Request should not be made from hard IRQ context.");
+			udelay(10);
+		}
 	} while (1);
 
 	return slot;
@@ -663,26 +672,6 @@
 	return (slot != MAX_TCS_SLOTS) ? slot : -ENOMEM;
 }
 
-static struct tcs_response *setup_response(struct tcs_mbox *tcs,
-		struct mbox_chan *chan, struct tcs_mbox_msg *msg, int m)
-{
-	struct tcs_response *resp = get_response_from_pool(tcs->drv);
-
-	if (IS_ERR(resp))
-		return resp;
-
-	if (m < tcs->tcs_offset)
-		return ERR_PTR(-EINVAL);
-
-	tcs->resp[m - tcs->tcs_offset] = resp;
-	resp->msg = msg;
-	resp->chan = chan;
-	resp->m = m;
-	resp->err = 0;
-
-	return resp;
-}
-
 static int tcs_mbox_write(struct mbox_chan *chan, struct tcs_mbox_msg *msg,
 				bool trigger)
 {
@@ -697,14 +686,20 @@
 	if (IS_ERR(tcs))
 		return PTR_ERR(tcs);
 
+	if (trigger)
+		resp = setup_response(drv, msg, chan, TCS_M_INIT, 0);
+
 	/* Identify the sequential slots that we can write to */
 	spin_lock(&tcs->tcs_lock);
 	slot = find_slots(tcs, msg);
 	if (slot < 0) {
 		dev_err(dev, "No TCS slot found.\n");
 		spin_unlock(&tcs->tcs_lock);
+		if (resp)
+			free_response(resp);
 		return slot;
 	}
+
 	/* Mark the slots as in-use, before we unlock */
 	if (tcs->type == SLEEP_TCS || tcs->type == WAKE_TCS)
 		bitmap_set(tcs->slots, slot, msg->num_payload);
@@ -713,27 +708,16 @@
 	for (i = 0; tcs->cmd_addr && i < msg->num_payload; i++)
 		tcs->cmd_addr[slot + i] = msg->payload[i].addr;
 
-	if (trigger)
-		resp = setup_response(tcs, chan, msg,
-				slot / tcs->ncpt + tcs->tcs_offset);
-
-	spin_unlock(&tcs->tcs_lock);
-
-	/*
-	 * Find the TCS corresponding to the slot and start writing.
-	 * Break down 'slot' into a 'n' position in the 'm'th TCS.
-	 */
 	offset = slot / tcs->ncpt;
 	m = offset + tcs->tcs_offset;
 	n = slot % tcs->ncpt;
 
-	spin_lock(&tcs->tcs_m_lock[offset]);
+	/* Block, if we have an address from the msg in flight */
 	if (trigger) {
-		/* Block, if we have an address from the msg in flight */
+		resp->m = m;
+		/* Mark the TCS as busy */
+		atomic_set(&drv->tcs_in_use[m], 1);
 		wait_for_req_inflight(drv, tcs, msg);
-		/* If the TCS is busy there is nothing to do but spin wait */
-		while (!tcs_is_free(drv, m))
-			cpu_relax();
 	}
 
 	/* Write to the TCS or AMC */
@@ -743,7 +727,7 @@
 	if (trigger)
 		schedule_tcs_err_response(resp);
 
-	spin_unlock(&tcs->tcs_m_lock[offset]);
+	spin_unlock(&tcs->tcs_lock);
 
 	return 0;
 }
@@ -769,11 +753,9 @@
 		spin_lock(&tcs->tcs_lock);
 		for (i = 0; i < tcs->num_tcs; i++) {
 			m = i + tcs->tcs_offset;
-			spin_lock(&tcs->tcs_m_lock[i]);
 			while (!tcs_is_free(drv, m))
-				cpu_relax();
+				udelay(1);
 			__tcs_buffer_invalidate(drv->reg_base, m);
-			spin_unlock(&tcs->tcs_m_lock[i]);
 		}
 		/* Mark the TCS as free */
 		bitmap_zero(tcs->slots, MAX_TCS_SLOTS);
@@ -840,12 +822,9 @@
 tx_fail:
 	if (ret) {
 		struct tcs_drv *drv = container_of(chan->mbox,
-							struct tcs_drv, mbox);
-		struct tcs_response *resp = get_response_from_pool(drv);
-
-		resp->chan = chan;
-		resp->msg = msg;
-		resp->err = ret;
+					struct tcs_drv, mbox);
+		struct tcs_response *resp = setup_response(
+				drv, msg, chan, TCS_M_INIT, ret);
 
 		dev_err(dev, "Error sending RPMH message %d\n", ret);
 		send_tcs_response(resp);
@@ -1040,8 +1019,6 @@
 		tcs->ncpt = (tcs->type == CONTROL_TCS) ? TCS_HIDDEN_MAX_SLOTS
 							: ncpt;
 		spin_lock_init(&tcs->tcs_lock);
-		for (j = 0; j < ARRAY_SIZE(tcs->tcs_m_lock); j++)
-			spin_lock_init(&tcs->tcs_m_lock[j]);
 
 		if (tcs->num_tcs <= 0 || tcs->type == CONTROL_TCS)
 			continue;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c
index 4f75a19..019a775 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_util.c
@@ -28,25 +28,34 @@
 #endif
 
 static struct cam_req_mgr_util_hdl_tbl *hdl_tbl;
-static struct mutex hdl_tbl_mutex = __MUTEX_INITIALIZER(hdl_tbl_mutex);
+static DEFINE_SPINLOCK(hdl_tbl_lock);
 
 int cam_req_mgr_util_init(void)
 {
 	int rc = 0;
 	int bitmap_size;
+	static struct cam_req_mgr_util_hdl_tbl *hdl_tbl_local;
 
-	mutex_lock(&hdl_tbl_mutex);
 	if (hdl_tbl) {
 		rc = -EINVAL;
 		pr_err("Hdl_tbl is already present\n");
 		goto hdl_tbl_check_failed;
 	}
 
-	hdl_tbl = kzalloc(sizeof(*hdl_tbl), GFP_KERNEL);
-	if (!hdl_tbl) {
+	hdl_tbl_local = kzalloc(sizeof(*hdl_tbl), GFP_KERNEL);
+	if (!hdl_tbl_local) {
 		rc = -ENOMEM;
 		goto hdl_tbl_alloc_failed;
 	}
+	spin_lock_bh(&hdl_tbl_lock);
+	if (hdl_tbl) {
+		spin_unlock_bh(&hdl_tbl_lock);
+		rc = -EEXIST;
+		kfree(hdl_tbl_local);
+		goto hdl_tbl_check_failed;
+	}
+	hdl_tbl = hdl_tbl_local;
+	spin_unlock_bh(&hdl_tbl_lock);
 
 	bitmap_size = BITS_TO_LONGS(CAM_REQ_MGR_MAX_HANDLES) * sizeof(long);
 	hdl_tbl->bitmap = kzalloc(sizeof(bitmap_size), GFP_KERNEL);
@@ -55,7 +64,6 @@
 		goto bitmap_alloc_fail;
 	}
 	hdl_tbl->bits = bitmap_size * BITS_PER_BYTE;
-	mutex_unlock(&hdl_tbl_mutex);
 
 	return rc;
 
@@ -64,16 +72,15 @@
 	hdl_tbl = NULL;
 hdl_tbl_alloc_failed:
 hdl_tbl_check_failed:
-	mutex_unlock(&hdl_tbl_mutex);
 	return rc;
 }
 
 int cam_req_mgr_util_deinit(void)
 {
-	mutex_lock(&hdl_tbl_mutex);
+	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
 		pr_err("Hdl tbl is NULL\n");
-		mutex_unlock(&hdl_tbl_mutex);
+		spin_unlock_bh(&hdl_tbl_lock);
 		return -EINVAL;
 	}
 
@@ -81,7 +88,7 @@
 	hdl_tbl->bitmap = NULL;
 	kfree(hdl_tbl);
 	hdl_tbl = NULL;
-	mutex_unlock(&hdl_tbl_mutex);
+	spin_unlock_bh(&hdl_tbl_lock);
 
 	return 0;
 }
@@ -90,10 +97,10 @@
 {
 	int i = 0;
 
-	mutex_lock(&hdl_tbl_mutex);
+	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
 		pr_err("Hdl tbl is NULL\n");
-		mutex_unlock(&hdl_tbl_mutex);
+		spin_unlock_bh(&hdl_tbl_lock);
 		return -EINVAL;
 	}
 
@@ -107,7 +114,7 @@
 		}
 	}
 	bitmap_zero(hdl_tbl->bitmap, CAM_REQ_MGR_MAX_HANDLES);
-	mutex_unlock(&hdl_tbl_mutex);
+	spin_unlock_bh(&hdl_tbl_lock);
 
 	return 0;
 }
@@ -132,17 +139,17 @@
 	int rand = 0;
 	int32_t handle = 0;
 
-	mutex_lock(&hdl_tbl_mutex);
+	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
 		pr_err("Hdl tbl is NULL\n");
-		mutex_unlock(&hdl_tbl_mutex);
+		spin_unlock_bh(&hdl_tbl_lock);
 		return -EINVAL;
 	}
 
 	idx = cam_get_free_handle_index();
 	if (idx < 0) {
 		pr_err("Unable to create session handle\n");
-		mutex_unlock(&hdl_tbl_mutex);
+		spin_unlock_bh(&hdl_tbl_lock);
 		return idx;
 	}
 
@@ -154,7 +161,7 @@
 	hdl_tbl->hdl[idx].state = HDL_ACTIVE;
 	hdl_tbl->hdl[idx].priv = priv;
 	hdl_tbl->hdl[idx].ops = NULL;
-	mutex_unlock(&hdl_tbl_mutex);
+	spin_unlock_bh(&hdl_tbl_lock);
 
 	return handle;
 }
@@ -165,17 +172,17 @@
 	int rand = 0;
 	int32_t handle;
 
-	mutex_lock(&hdl_tbl_mutex);
+	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
 		pr_err("Hdl tbl is NULL\n");
-		mutex_unlock(&hdl_tbl_mutex);
+		spin_unlock_bh(&hdl_tbl_lock);
 		return -EINVAL;
 	}
 
 	idx = cam_get_free_handle_index();
 	if (idx < 0) {
 		pr_err("Unable to create device handle\n");
-		mutex_unlock(&hdl_tbl_mutex);
+		spin_unlock_bh(&hdl_tbl_lock);
 		return idx;
 	}
 
@@ -187,7 +194,7 @@
 	hdl_tbl->hdl[idx].state = HDL_ACTIVE;
 	hdl_tbl->hdl[idx].priv = hdl_data->priv;
 	hdl_tbl->hdl[idx].ops = hdl_data->ops;
-	mutex_unlock(&hdl_tbl_mutex);
+	spin_unlock_bh(&hdl_tbl_lock);
 
 	return handle;
 }
@@ -198,7 +205,7 @@
 	int type;
 	void *priv;
 
-	mutex_lock(&hdl_tbl_mutex);
+	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
 		pr_err("Hdl tbl is NULL\n");
 		goto device_priv_fail;
@@ -227,12 +234,12 @@
 	}
 
 	priv = hdl_tbl->hdl[idx].priv;
-	mutex_unlock(&hdl_tbl_mutex);
+	spin_unlock_bh(&hdl_tbl_lock);
 
 	return priv;
 
 device_priv_fail:
-	mutex_unlock(&hdl_tbl_mutex);
+	spin_unlock_bh(&hdl_tbl_lock);
 	return NULL;
 }
 
@@ -242,7 +249,7 @@
 	int type;
 	void *ops;
 
-	mutex_lock(&hdl_tbl_mutex);
+	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
 		pr_err("Hdl tbl is NULL\n");
 		goto device_ops_fail;
@@ -271,12 +278,12 @@
 	}
 
 	ops = hdl_tbl->hdl[idx].ops;
-	mutex_unlock(&hdl_tbl_mutex);
+	spin_unlock_bh(&hdl_tbl_lock);
 
 	return ops;
 
 device_ops_fail:
-	mutex_unlock(&hdl_tbl_mutex);
+	spin_unlock_bh(&hdl_tbl_lock);
 	return NULL;
 }
 
@@ -285,7 +292,7 @@
 	int idx;
 	int type;
 
-	mutex_lock(&hdl_tbl_mutex);
+	spin_lock_bh(&hdl_tbl_lock);
 	if (!hdl_tbl) {
 		pr_err("Hdl tbl is NULL\n");
 		goto destroy_hdl_fail;
@@ -315,12 +322,12 @@
 
 	hdl_tbl->hdl[idx].state = HDL_FREE;
 	clear_bit(idx, hdl_tbl->bitmap);
-	mutex_unlock(&hdl_tbl_mutex);
+	spin_unlock_bh(&hdl_tbl_lock);
 
 	return 0;
 
 destroy_hdl_fail:
-	mutex_unlock(&hdl_tbl_mutex);
+	spin_unlock_bh(&hdl_tbl_lock);
 	return -EINVAL;
 }
 
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
index e327723..08466b1 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
@@ -104,14 +104,14 @@
 	workq = (struct cam_req_mgr_core_workq *)
 		container_of(w, struct cam_req_mgr_core_workq, work);
 
-	spin_lock(&workq->task.lock);
 	list_for_each_entry_safe(task, task_save,
 		&workq->task.process_head, entry) {
 		atomic_sub(1, &workq->task.pending_cnt);
+		spin_lock(&workq->task.lock);
 		list_del_init(&task->entry);
+		spin_unlock(&workq->task.lock);
 		cam_req_mgr_process_task(task);
 	}
-	spin_unlock(&workq->task.lock);
 	CRM_DBG("processed task %p free_cnt %d",
 		task, atomic_read(&workq->task.free_cnt));
 }
@@ -138,7 +138,6 @@
 		goto end;
 	}
 
-	spin_lock(&workq->task.lock);
 	if (task->cancel == 1) {
 		cam_req_mgr_workq_put_task(task);
 		CRM_WARN("task aborted and queued back to pool");
@@ -146,12 +145,14 @@
 		spin_unlock(&workq->task.lock);
 		goto end;
 	}
+	spin_lock(&workq->task.lock);
 	list_add_tail(&task->entry,
 		&workq->task.process_head);
+	spin_unlock(&workq->task.lock);
 	atomic_add(1, &workq->task.pending_cnt);
 	CRM_DBG("enq task %p pending_cnt %d",
 		task, atomic_read(&workq->task.pending_cnt));
-	spin_unlock(&workq->task.lock);
+
 
 	queue_work(workq->job, &workq->work);
 
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
index a0b53bb..3bf6ce0 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.h
@@ -140,6 +140,18 @@
 	int domain;
 };
 
+/*
+ * struct sde_rot_debug_bus: rotator debugbus header structure
+ * @wr_addr: write address for debugbus controller
+ * @block_id: rotator debugbus block id
+ * @test_id: rotator debugbus test id
+ */
+struct sde_rot_debug_bus {
+	u32 wr_addr;
+	u32 block_id;
+	u32 test_id;
+};
+
 struct sde_rot_vbif_debug_bus {
 	u32 disable_bus_addr;
 	u32 block_bus_addr;
@@ -191,6 +203,8 @@
 
 	struct sde_rot_vbif_debug_bus *nrt_vbif_dbg_bus;
 	u32 nrt_vbif_dbg_bus_size;
+	struct sde_rot_debug_bus *rot_dbg_bus;
+	u32 rot_dbg_bus_size;
 
 	struct sde_rot_regdump *regdump;
 	u32 regdump_size;
@@ -199,6 +213,8 @@
 	int sec_cam_en;
 
 	struct ion_client *iclient;
+
+	bool clk_always_on;
 };
 
 int sde_rotator_base_init(struct sde_rot_data_type **pmdata,
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
index e56c70a..e9ff67c 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
@@ -30,6 +30,7 @@
 #define SDE_EVTLOG_DEFAULT_PANIC 1
 #define SDE_EVTLOG_DEFAULT_REGDUMP SDE_ROT_DBG_DUMP_IN_MEM
 #define SDE_EVTLOG_DEFAULT_VBIF_DBGBUSDUMP SDE_ROT_DBG_DUMP_IN_MEM
+#define SDE_EVTLOG_DEFAULT_ROT_DBGBUSDUMP SDE_ROT_DBG_DUMP_IN_MEM
 
 /*
  * evtlog will print this number of entries when it is called through
@@ -53,6 +54,8 @@
 #define GROUP_BYTES 4
 #define ROW_BYTES 16
 
+#define SDE_ROT_TEST_MASK(id, tp)	((id << 4) | (tp << 1) | BIT(0))
+
 static DEFINE_SPINLOCK(sde_rot_xlock);
 
 /*
@@ -86,11 +89,14 @@
  * @panic_on_err - boolean indicates issue panic after EVTLOG dump
  * @enable_reg_dump - control in-log/memory dump for rotator registers
  * @enable_vbif_dbgbus_dump - control in-log/memory dump for VBIF debug bus
+ * @enable_rot_dbgbus_dump - control in-log/memroy dump for rotator debug bus
  * @evtlog_dump_work - schedule work strucutre for timeout handler
  * @work_dump_reg - storage for register dump control in schedule work
  * @work_panic - storage for panic control in schedule work
  * @work_vbif_dbgbus - storage for VBIF debug bus control in schedule work
+ * @work_rot_dbgbus - storage for rotator debug bus control in schedule work
  * @nrt_vbif_dbgbus_dump - memory buffer for VBIF debug bus dumping
+ * @rot_dbgbus_dump - memory buffer for rotator debug bus dumping
  * @reg_dump_array - memory buffer for rotator registers dumping
  */
 struct sde_rot_dbg_evtlog {
@@ -103,14 +109,88 @@
 	u32 panic_on_err;
 	u32 enable_reg_dump;
 	u32 enable_vbif_dbgbus_dump;
+	u32 enable_rot_dbgbus_dump;
 	struct work_struct evtlog_dump_work;
 	bool work_dump_reg;
 	bool work_panic;
 	bool work_vbif_dbgbus;
+	bool work_rot_dbgbus;
 	u32 *nrt_vbif_dbgbus_dump; /* address for the nrt vbif debug bus dump */
+	u32 *rot_dbgbus_dump;
 	u32 *reg_dump_array[SDE_ROT_DEBUG_BASE_MAX];
 } sde_rot_dbg_evtlog;
 
+static void sde_rot_dump_debug_bus(u32 bus_dump_flag, u32 **dump_mem)
+{
+	struct sde_rot_data_type *mdata = sde_rot_get_mdata();
+	bool in_log, in_mem;
+	u32 *dump_addr = NULL;
+	u32 status = 0;
+	struct sde_rot_debug_bus *head;
+	phys_addr_t phys = 0;
+	int i;
+	u32 offset;
+	void __iomem *base;
+
+	in_log = (bus_dump_flag & SDE_ROT_DBG_DUMP_IN_LOG);
+	in_mem = (bus_dump_flag & SDE_ROT_DBG_DUMP_IN_MEM);
+	base = mdata->sde_io.base;
+
+	if (!base || !mdata->rot_dbg_bus || !mdata->rot_dbg_bus_size)
+		return;
+
+	pr_info("======== SDE Rotator Debug bus DUMP =========\n");
+
+	if (in_mem) {
+		if (!(*dump_mem))
+			*dump_mem = dma_alloc_coherent(&mdata->pdev->dev,
+				mdata->rot_dbg_bus_size * 4 * sizeof(u32),
+				&phys, GFP_KERNEL);
+
+		if (*dump_mem) {
+			dump_addr = *dump_mem;
+			pr_info("%s: start_addr:0x%pK end_addr:0x%pK\n",
+				__func__, dump_addr,
+				dump_addr + (u32)mdata->rot_dbg_bus_size * 16);
+		} else {
+			in_mem = false;
+			pr_err("dump_mem: allocation fails\n");
+		}
+	}
+
+	sde_smmu_ctrl(1);
+
+	for (i = 0; i < mdata->rot_dbg_bus_size; i++) {
+		head = mdata->rot_dbg_bus + i;
+		writel_relaxed(SDE_ROT_TEST_MASK(head->block_id, head->test_id),
+				base + head->wr_addr);
+		wmb(); /* make sure test bits were written */
+
+		offset = head->wr_addr + 0x4;
+
+		status = readl_relaxed(base + offset);
+
+		if (in_log)
+			pr_err("waddr=0x%x blk=%d tst=%d val=0x%x\n",
+				head->wr_addr, head->block_id, head->test_id,
+				status);
+
+		if (dump_addr && in_mem) {
+			dump_addr[i*4]     = head->wr_addr;
+			dump_addr[i*4 + 1] = head->block_id;
+			dump_addr[i*4 + 2] = head->test_id;
+			dump_addr[i*4 + 3] = status;
+		}
+
+		/* Disable debug bus once we are done */
+		writel_relaxed(0, base + head->wr_addr);
+	}
+
+	sde_smmu_ctrl(0);
+
+	pr_info("========End Debug bus=========\n");
+}
+
 /*
  * sde_rot_evtlog_is_enabled - helper function for checking EVTLOG
  *                             enable/disable
@@ -518,18 +598,26 @@
  * @dump_vbif_debug_bus: boolean indicates VBIF debug bus dump
  */
 static void sde_rot_evtlog_dump_helper(bool dead, const char *panic_name,
-	bool dump_rot, bool dump_vbif_debug_bus)
+	bool dump_rot, bool dump_vbif_debug_bus, bool dump_rot_debug_bus)
 {
 	sde_rot_evtlog_dump_all();
 
-	if (dump_rot)
-		sde_rot_dump_reg_all();
+	if (dump_rot_debug_bus)
+		sde_rot_dump_debug_bus(
+				sde_rot_dbg_evtlog.enable_rot_dbgbus_dump,
+				&sde_rot_dbg_evtlog.rot_dbgbus_dump);
 
 	if (dump_vbif_debug_bus)
 		sde_rot_dump_vbif_debug_bus(
 				sde_rot_dbg_evtlog.enable_vbif_dbgbus_dump,
 				&sde_rot_dbg_evtlog.nrt_vbif_dbgbus_dump);
 
+	/*
+	 * Rotator registers always dump last
+	 */
+	if (dump_rot)
+		sde_rot_dump_reg_all();
+
 	if (dead)
 		panic(panic_name);
 }
@@ -544,7 +632,8 @@
 		sde_rot_dbg_evtlog.work_panic,
 		"evtlog_workitem",
 		sde_rot_dbg_evtlog.work_dump_reg,
-		sde_rot_dbg_evtlog.work_vbif_dbgbus);
+		sde_rot_dbg_evtlog.work_vbif_dbgbus,
+		sde_rot_dbg_evtlog.work_rot_dbgbus);
 }
 
 /*
@@ -569,6 +658,7 @@
 	bool dead = false;
 	bool dump_rot = false;
 	bool dump_vbif_dbgbus = false;
+	bool dump_rot_dbgbus = false;
 	char *blk_name = NULL;
 	va_list args;
 
@@ -590,6 +680,9 @@
 		if (!strcmp(blk_name, "vbif_dbg_bus"))
 			dump_vbif_dbgbus = true;
 
+		if (!strcmp(blk_name, "rot_dbg_bus"))
+			dump_rot_dbgbus = true;
+
 		if (!strcmp(blk_name, "panic"))
 			dead = true;
 	}
@@ -600,10 +693,11 @@
 		sde_rot_dbg_evtlog.work_panic = dead;
 		sde_rot_dbg_evtlog.work_dump_reg = dump_rot;
 		sde_rot_dbg_evtlog.work_vbif_dbgbus = dump_vbif_dbgbus;
+		sde_rot_dbg_evtlog.work_rot_dbgbus = dump_rot_dbgbus;
 		schedule_work(&sde_rot_dbg_evtlog.evtlog_dump_work);
 	} else {
 		sde_rot_evtlog_dump_helper(dead, name, dump_rot,
-			dump_vbif_dbgbus);
+			dump_vbif_dbgbus, dump_rot_dbgbus);
 	}
 }
 
@@ -836,6 +930,13 @@
 		return -EINVAL;
 	}
 
+	mdata->clk_always_on = false;
+	if (!debugfs_create_bool("clk_always_on", 0644,
+			debugfs_root, &mdata->clk_always_on)) {
+		SDEROT_WARN("failed to create debugfs clk_always_on\n");
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -919,12 +1020,16 @@
 			    &sde_rot_dbg_evtlog.enable_reg_dump);
 	debugfs_create_u32("vbif_dbgbus_dump", 0644, sde_rot_dbg_evtlog.evtlog,
 			    &sde_rot_dbg_evtlog.enable_vbif_dbgbus_dump);
+	debugfs_create_u32("rot_dbgbus_dump", 0644, sde_rot_dbg_evtlog.evtlog,
+			    &sde_rot_dbg_evtlog.enable_rot_dbgbus_dump);
 
 	sde_rot_dbg_evtlog.evtlog_enable = SDE_EVTLOG_DEFAULT_ENABLE;
 	sde_rot_dbg_evtlog.panic_on_err = SDE_EVTLOG_DEFAULT_PANIC;
 	sde_rot_dbg_evtlog.enable_reg_dump = SDE_EVTLOG_DEFAULT_REGDUMP;
 	sde_rot_dbg_evtlog.enable_vbif_dbgbus_dump =
 		SDE_EVTLOG_DEFAULT_VBIF_DBGBUSDUMP;
+	sde_rot_dbg_evtlog.enable_rot_dbgbus_dump =
+		SDE_EVTLOG_DEFAULT_ROT_DBGBUSDUMP;
 
 	pr_info("evtlog_status: enable:%d, panic:%d, dump:%d\n",
 			sde_rot_dbg_evtlog.evtlog_enable,
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
index a152573..8f2746d 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -385,11 +385,95 @@
 };
 
 static struct sde_rot_vbif_debug_bus nrt_vbif_dbg_bus_r3[] = {
-	{0x214, 0x21c, 16, 1, 0x10}, /* arb clients */
+	{0x214, 0x21c, 16, 1, 0x200}, /* arb clients main */
 	{0x214, 0x21c, 0, 12, 0x13}, /* xin blocks - axi side */
 	{0x21c, 0x214, 0, 12, 0xc}, /* xin blocks - clock side */
 };
 
+static struct sde_rot_debug_bus rot_dbgbus_r3[] = {
+	/*
+	 * rottop - 0xA8850
+	 */
+	/* REGDMA */
+	{ 0XA8850, 0, 0 },
+	{ 0XA8850, 0, 1 },
+	{ 0XA8850, 0, 2 },
+	{ 0XA8850, 0, 3 },
+	{ 0XA8850, 0, 4 },
+
+	/* ROT_WB */
+	{ 0XA8850, 1, 0 },
+	{ 0XA8850, 1, 1 },
+	{ 0XA8850, 1, 2 },
+	{ 0XA8850, 1, 3 },
+	{ 0XA8850, 1, 4 },
+	{ 0XA8850, 1, 5 },
+	{ 0XA8850, 1, 6 },
+	{ 0XA8850, 1, 7 },
+
+	/* UBWC_DEC */
+	{ 0XA8850, 2, 0 },
+
+	/* UBWC_ENC */
+	{ 0XA8850, 3, 0 },
+
+	/* ROT_FETCH_0 */
+	{ 0XA8850, 4, 0 },
+	{ 0XA8850, 4, 1 },
+	{ 0XA8850, 4, 2 },
+	{ 0XA8850, 4, 3 },
+	{ 0XA8850, 4, 4 },
+	{ 0XA8850, 4, 5 },
+	{ 0XA8850, 4, 6 },
+	{ 0XA8850, 4, 7 },
+
+	/* ROT_FETCH_1 */
+	{ 0XA8850, 5, 0 },
+	{ 0XA8850, 5, 1 },
+	{ 0XA8850, 5, 2 },
+	{ 0XA8850, 5, 3 },
+	{ 0XA8850, 5, 4 },
+	{ 0XA8850, 5, 5 },
+	{ 0XA8850, 5, 6 },
+	{ 0XA8850, 5, 7 },
+
+	/* ROT_FETCH_2 */
+	{ 0XA8850, 6, 0 },
+	{ 0XA8850, 6, 1 },
+	{ 0XA8850, 6, 2 },
+	{ 0XA8850, 6, 3 },
+	{ 0XA8850, 6, 4 },
+	{ 0XA8850, 6, 5 },
+	{ 0XA8850, 6, 6 },
+	{ 0XA8850, 6, 7 },
+
+	/* ROT_FETCH_3 */
+	{ 0XA8850, 7, 0 },
+	{ 0XA8850, 7, 1 },
+	{ 0XA8850, 7, 2 },
+	{ 0XA8850, 7, 3 },
+	{ 0XA8850, 7, 4 },
+	{ 0XA8850, 7, 5 },
+	{ 0XA8850, 7, 6 },
+	{ 0XA8850, 7, 7 },
+
+	/* ROT_FETCH_4 */
+	{ 0XA8850, 8, 0 },
+	{ 0XA8850, 8, 1 },
+	{ 0XA8850, 8, 2 },
+	{ 0XA8850, 8, 3 },
+	{ 0XA8850, 8, 4 },
+	{ 0XA8850, 8, 5 },
+	{ 0XA8850, 8, 6 },
+	{ 0XA8850, 8, 7 },
+
+	/* ROT_UNPACK_0*/
+	{ 0XA8850, 9, 0 },
+	{ 0XA8850, 9, 1 },
+	{ 0XA8850, 9, 2 },
+	{ 0XA8850, 9, 3 },
+};
+
 static struct sde_rot_regdump sde_rot_r3_regdump[] = {
 	{ "SDEROT_ROTTOP", SDE_ROT_ROTTOP_OFFSET, 0x100, SDE_ROT_REGDUMP_READ },
 	{ "SDEROT_SSPP", SDE_ROT_SSPP_OFFSET, 0x200, SDE_ROT_REGDUMP_READ },
@@ -1430,7 +1514,8 @@
 	sts = (status & ROT_ERROR_BIT) ? -ENODEV : 0;
 
 	if (status & ROT_ERROR_BIT)
-		SDEROT_EVTLOG_TOUT_HANDLER("rot", "vbif_dbg_bus", "panic");
+		SDEROT_EVTLOG_TOUT_HANDLER("rot", "rot_dbg_bus",
+				"vbif_dbg_bus", "panic");
 
 	return sts;
 }
@@ -1614,8 +1699,8 @@
 			SDEROT_ERR(
 				"Mismatch SWTS with HWTS: swts:0x%x, hwts:0x%x, regdma-sts:0x%x, rottop-sts:0x%x\n",
 				swts, hwts, regdmasts, rotsts);
-			SDEROT_EVTLOG_TOUT_HANDLER("rot", "vbif_dbg_bus",
-					"panic");
+			SDEROT_EVTLOG_TOUT_HANDLER("rot", "rot_dbg_bus",
+					"vbif_dbg_bus", "panic");
 		}
 
 		/* Turn off rotator clock after checking rotator registers */
@@ -2134,6 +2219,17 @@
 	SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_WRITE_GATHTER_EN,
 			BIT(XIN_WRITEBACK));
 
+	/*
+	 * For debug purpose, disable clock gating, i.e. Clocks always on
+	 */
+	if (mdata->clk_always_on) {
+		SDE_VBIF_WRITE(mdata, MMSS_VBIF_CLKON, 0x3);
+		SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL0, 0x3);
+		SDE_VBIF_WRITE(mdata, MMSS_VBIF_NRT_VBIF_CLK_FORCE_CTRL1,
+				0xFFFF);
+		SDE_ROTREG_WRITE(rot->mdss_base, ROTTOP_CLK_CTRL, 1);
+	}
+
 	return 0;
 
 error:
@@ -2260,6 +2356,9 @@
 	mdata->nrt_vbif_dbg_bus_size =
 			ARRAY_SIZE(nrt_vbif_dbg_bus_r3);
 
+	mdata->rot_dbg_bus = rot_dbgbus_r3;
+	mdata->rot_dbg_bus_size = ARRAY_SIZE(rot_dbgbus_r3);
+
 	mdata->regdump = sde_rot_r3_regdump;
 	mdata->regdump_size = ARRAY_SIZE(sde_rot_r3_regdump);
 	SDE_ROTREG_WRITE(rot->mdss_base, REGDMA_TIMESTAMP_REG, 0);
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 0fa3262..ac6ded0 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -1115,6 +1115,14 @@
 		pkt->size += sizeof(u32) * 2;
 		break;
 	}
+	case HAL_PARAM_SECURE:
+	{
+		create_pkt_enable(pkt->rg_property_data,
+			  HFI_PROPERTY_PARAM_SECURE_SESSION,
+			  ((struct hal_enable *)pdata)->enable);
+		pkt->size += sizeof(u32) * 2;
+		break;
+	}
 	case HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER:
 	{
 		create_pkt_enable(pkt->rg_property_data,
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 85e721f..3d3b7e9 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -778,7 +778,10 @@
 		msm_dcvs_try_enable(inst);
 		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_SECURE:
+		property_id = HAL_PARAM_SECURE;
 		inst->flags |= VIDC_SECURE;
+		property_val = !!(inst->flags & VIDC_SECURE);
+		pdata = &property_val;
 		dprintk(VIDC_DBG, "Setting secure mode to: %d\n",
 				!!(inst->flags & VIDC_SECURE));
 		break;
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index c102687..e198d8e 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1501,6 +1501,9 @@
 		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_SECURE:
 		inst->flags |= VIDC_SECURE;
+		property_id = HAL_PARAM_SECURE;
+		property_val = !!(inst->flags & VIDC_SECURE);
+		pdata = &property_val;
 		dprintk(VIDC_INFO, "Setting secure mode to: %d\n",
 				!!(inst->flags & VIDC_SECURE));
 		break;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index c042a4a..1a1078d 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1965,6 +1965,8 @@
 	if (device->res->pm_qos_latency_us &&
 		pm_qos_request_active(&device->qos))
 		pm_qos_remove_request(&device->qos);
+
+	__resume(device);
 	__set_state(device, VENUS_STATE_DEINIT);
 	__unload_fw(device);
 
@@ -4054,6 +4056,8 @@
 	__venus_power_off(device);
 	device->resources.fw.cookie = NULL;
 	__deinit_resources(device);
+
+	dprintk(VIDC_PROF, "Firmware unloaded successfully\n");
 }
 
 static int venus_hfi_get_fw_info(void *dev, struct hal_fw_info *fw_info)
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index b0beeec..f8e0a6a 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -223,6 +223,7 @@
 	HAL_PARAM_VENC_IFRAMESIZE_TYPE,
 	HAL_PARAM_VIDEO_CORES_USAGE,
 	HAL_PARAM_VIDEO_WORK_MODE,
+	HAL_PARAM_SECURE,
 };
 
 enum hal_domain {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 04d7d01..d6c4bcb 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -218,6 +218,8 @@
 	(HFI_PROPERTY_PARAM_COMMON_START + 0x00E)
 #define  HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED	    \
 	(HFI_PROPERTY_PARAM_COMMON_START + 0x010)
+#define  HFI_PROPERTY_PARAM_SECURE_SESSION		\
+	(HFI_PROPERTY_PARAM_COMMON_START + 0x011)
 #define  HFI_PROPERTY_PARAM_WORK_MODE                       \
 	(HFI_PROPERTY_PARAM_COMMON_START + 0x015)
 
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c
index 8b3216cd..6523cb0 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -6457,7 +6457,6 @@
 	}
 
 	dev_set_drvdata(&msm_pcie_dev[rc_idx].pdev->dev, &msm_pcie_dev[rc_idx]);
-	msm_pcie_sysfs_init(&msm_pcie_dev[rc_idx]);
 
 	ret = msm_pcie_get_resources(&msm_pcie_dev[rc_idx],
 				msm_pcie_dev[rc_idx].pdev);
@@ -6508,6 +6507,8 @@
 		goto decrease_rc_num;
 	}
 
+	msm_pcie_sysfs_init(&msm_pcie_dev[rc_idx]);
+
 	msm_pcie_dev[rc_idx].drv_ready = true;
 
 	if (msm_pcie_dev[rc_idx].boot_option &
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index d45fa51..a37947b 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -126,6 +126,7 @@
 	__stringify(IPA_CLIENT_Q6_DECOMP_PROD),
 	__stringify(IPA_CLIENT_Q6_DECOMP2_PROD),
 	__stringify(IPA_CLIENT_UC_USB_PROD),
+	__stringify(IPA_CLIENT_ETHERNET_PROD),
 
 	/* Below PROD client type is only for test purpose */
 	__stringify(IPA_CLIENT_TEST_PROD),
@@ -164,6 +165,7 @@
 	__stringify(IPA_CLIENT_Q6_DECOMP_CONS),
 	__stringify(IPA_CLIENT_Q6_DECOMP2_CONS),
 	__stringify(IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS),
+	__stringify(IPA_CLIENT_ETHERNET_CONS),
 	/* Below CONS client type is only for test purpose */
 	__stringify(IPA_CLIENT_TEST_CONS),
 	__stringify(IPA_CLIENT_TEST1_CONS),
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index 15bb7b4..af4d4c8 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -1584,6 +1584,7 @@
 	struct ipa_hw_imm_cmd_dma_shared_mem *cmd = NULL;
 	struct ipa_desc desc;
 	struct ipa_mem_buffer mem;
+	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
 	int rc;
 
 	if (memory_region_size == 0)
@@ -1603,7 +1604,7 @@
 	memset(mem.base, 0, mem.size);
 
 	cmd = kzalloc(sizeof(*cmd),
-		GFP_KERNEL);
+		flag);
 	if (cmd == NULL) {
 		IPAERR("Failed to alloc immediate command object\n");
 		rc = -ENOMEM;
@@ -2166,6 +2167,7 @@
 	struct ipa_hw_imm_cmd_dma_shared_mem *cmd = NULL;
 	struct ipa_desc desc = {0};
 	struct ipa_mem_buffer mem;
+	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
 	int rc = 0;
 
 	phys_addr = ipa_ctx->ipa_wrapper_base +
@@ -2203,7 +2205,7 @@
 	}
 	memset(mem.base, 0, mem.size);
 
-	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	cmd = kzalloc(sizeof(*cmd), flag);
 	if (cmd == NULL) {
 		IPAERR("Failed to alloc immediate command object\n");
 		rc = -ENOMEM;
@@ -2314,6 +2316,7 @@
 	struct ipa_desc desc = { 0 };
 	struct ipa_mem_buffer mem;
 	struct ipa_hdr_init_local *cmd = NULL;
+	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
 	int rc = 0;
 
 	mem.size = IPA_MEM_PART(modem_hdr_size) + IPA_MEM_PART(apps_hdr_size);
@@ -2325,7 +2328,7 @@
 	}
 	memset(mem.base, 0, mem.size);
 
-	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	cmd = kzalloc(sizeof(*cmd), flag);
 	if (cmd == NULL) {
 		IPAERR("Failed to alloc header init command object\n");
 		rc = -ENOMEM;
@@ -2360,6 +2363,7 @@
 	struct ipa_mem_buffer mem;
 	struct ipa_hdr_init_local *cmd = NULL;
 	struct ipa_hw_imm_cmd_dma_shared_mem *dma_cmd = NULL;
+	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
 
 	mem.size = IPA_MEM_PART(modem_hdr_size) + IPA_MEM_PART(apps_hdr_size);
 	mem.base = dma_alloc_coherent(ipa_ctx->pdev, mem.size, &mem.phys_base,
@@ -2370,7 +2374,7 @@
 	}
 	memset(mem.base, 0, mem.size);
 
-	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	cmd = kzalloc(sizeof(*cmd), flag);
 	if (cmd == NULL) {
 		IPAERR("Failed to alloc header init command object\n");
 		dma_free_coherent(ipa_ctx->pdev, mem.size, mem.base,
@@ -2411,7 +2415,7 @@
 	memset(mem.base, 0, mem.size);
 	memset(&desc, 0, sizeof(desc));
 
-	dma_cmd = kzalloc(sizeof(*dma_cmd), GFP_KERNEL);
+	dma_cmd = kzalloc(sizeof(*dma_cmd), flag);
 	if (dma_cmd == NULL) {
 		IPAERR("Failed to alloc immediate command object\n");
 		dma_free_coherent(ipa_ctx->pdev,
@@ -2462,6 +2466,7 @@
 	struct ipa_desc desc = { 0 };
 	struct ipa_mem_buffer mem;
 	struct ipa_ip_v4_routing_init *v4_cmd = NULL;
+	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
 	u32 *entry;
 	int i;
 	int rc = 0;
@@ -2486,7 +2491,7 @@
 		entry++;
 	}
 
-	v4_cmd = kzalloc(sizeof(*v4_cmd), GFP_KERNEL);
+	v4_cmd = kzalloc(sizeof(*v4_cmd), flag);
 	if (v4_cmd == NULL) {
 		IPAERR("Failed to alloc v4 routing init command object\n");
 		rc = -ENOMEM;
@@ -2522,6 +2527,7 @@
 	struct ipa_desc desc = { 0 };
 	struct ipa_mem_buffer mem;
 	struct ipa_ip_v6_routing_init *v6_cmd = NULL;
+	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
 	u32 *entry;
 	int i;
 	int rc = 0;
@@ -2546,7 +2552,7 @@
 		entry++;
 	}
 
-	v6_cmd = kzalloc(sizeof(*v6_cmd), GFP_KERNEL);
+	v6_cmd = kzalloc(sizeof(*v6_cmd), flag);
 	if (v6_cmd == NULL) {
 		IPAERR("Failed to alloc v6 routing init command object\n");
 		rc = -ENOMEM;
@@ -2582,6 +2588,7 @@
 	struct ipa_desc desc = { 0 };
 	struct ipa_mem_buffer mem;
 	struct ipa_ip_v4_filter_init *v4_cmd = NULL;
+	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
 	u32 *entry;
 	int i;
 	int rc = 0;
@@ -2604,7 +2611,7 @@
 		entry++;
 	}
 
-	v4_cmd = kzalloc(sizeof(*v4_cmd), GFP_KERNEL);
+	v4_cmd = kzalloc(sizeof(*v4_cmd), flag);
 	if (v4_cmd == NULL) {
 		IPAERR("Failed to alloc v4 fliter init command object\n");
 		rc = -ENOMEM;
@@ -2640,6 +2647,7 @@
 	struct ipa_desc desc = { 0 };
 	struct ipa_mem_buffer mem;
 	struct ipa_ip_v6_filter_init *v6_cmd = NULL;
+	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
 	u32 *entry;
 	int i;
 	int rc = 0;
@@ -2662,7 +2670,7 @@
 		entry++;
 	}
 
-	v6_cmd = kzalloc(sizeof(*v6_cmd), GFP_KERNEL);
+	v6_cmd = kzalloc(sizeof(*v6_cmd), flag);
 	if (v6_cmd == NULL) {
 		IPAERR("Failed to alloc v6 fliter init command object\n");
 		rc = -ENOMEM;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
index 3dca3e6..ff47863 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
@@ -322,8 +322,8 @@
 		dma_address = desc->dma_address;
 		tx_pkt->no_unmap_dma = true;
 	}
-	if (!dma_address) {
-		IPAERR("failed to DMA wrap\n");
+	if (dma_mapping_error(ipa_ctx->pdev, dma_address)) {
+		IPAERR("dma_map_single failed\n");
 		goto fail_dma_map;
 	}
 
@@ -445,7 +445,7 @@
 		}
 		dma_addr  = dma_map_single(ipa_ctx->pdev,
 				transfer.iovec, size, DMA_TO_DEVICE);
-		if (!dma_addr) {
+		if (dma_mapping_error(ipa_ctx->pdev, dma_addr)) {
 			IPAERR("dma_map_single failed for sps xfr buff\n");
 			kfree(transfer.iovec);
 			return -EFAULT;
@@ -493,6 +493,15 @@
 					tx_pkt->mem.base,
 					tx_pkt->mem.size,
 					DMA_TO_DEVICE);
+
+				if (dma_mapping_error(ipa_ctx->pdev,
+					tx_pkt->mem.phys_base)) {
+					IPAERR("dma_map_single ");
+					IPAERR("failed\n");
+					fail_dma_wrap = 1;
+					goto failure;
+				}
+
 			} else {
 				tx_pkt->mem.phys_base = desc[i].dma_address;
 				tx_pkt->no_unmap_dma = true;
@@ -1873,8 +1882,8 @@
 		rx_pkt->data.dma_addr = dma_map_single(ipa_ctx->pdev, ptr,
 						     sys->rx_buff_sz,
 						     DMA_FROM_DEVICE);
-		if (rx_pkt->data.dma_addr == 0 ||
-				rx_pkt->data.dma_addr == ~0) {
+		if (dma_mapping_error(ipa_ctx->pdev,
+				rx_pkt->data.dma_addr)) {
 			pr_err_ratelimited("%s dma map fail %p for %p sys=%p\n",
 			       __func__, (void *)rx_pkt->data.dma_addr,
 			       ptr, sys);
@@ -2029,8 +2038,8 @@
 		ptr = skb_put(rx_pkt->data.skb, IPA_WLAN_RX_BUFF_SZ);
 		rx_pkt->data.dma_addr = dma_map_single(ipa_ctx->pdev, ptr,
 				IPA_WLAN_RX_BUFF_SZ, DMA_FROM_DEVICE);
-		if (rx_pkt->data.dma_addr == 0 ||
-				rx_pkt->data.dma_addr == ~0) {
+		if (dma_mapping_error(ipa_ctx->pdev,
+				rx_pkt->data.dma_addr)) {
 			IPAERR("dma_map_single failure %p for %p\n",
 			       (void *)rx_pkt->data.dma_addr, ptr);
 			goto fail_dma_mapping;
@@ -2101,8 +2110,8 @@
 		rx_pkt->data.dma_addr = dma_map_single(ipa_ctx->pdev, ptr,
 						     sys->rx_buff_sz,
 						     DMA_FROM_DEVICE);
-		if (rx_pkt->data.dma_addr == 0 ||
-				rx_pkt->data.dma_addr == ~0) {
+		if (dma_mapping_error(ipa_ctx->pdev,
+				rx_pkt->data.dma_addr)) {
 			IPAERR("dma_map_single failure %p for %p\n",
 			       (void *)rx_pkt->data.dma_addr, ptr);
 			goto fail_dma_mapping;
@@ -2159,9 +2168,10 @@
 		ptr = skb_put(rx_pkt->data.skb, sys->rx_buff_sz);
 		rx_pkt->data.dma_addr = dma_map_single(ipa_ctx->pdev,
 			ptr, sys->rx_buff_sz, DMA_FROM_DEVICE);
-		if (rx_pkt->data.dma_addr == 0 ||
-			rx_pkt->data.dma_addr == ~0)
+		if (dma_mapping_error(ipa_ctx->pdev, rx_pkt->data.dma_addr)) {
+			IPAERR("dma_map_single failure for rx_pkt\n");
 			goto fail_dma_mapping;
+		}
 
 		list_add_tail(&rx_pkt->link, &sys->head_desc_list);
 		rx_len_cached = ++sys->len;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
index 25f8923..046f77f 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
@@ -268,6 +268,7 @@
 	struct ipa_mem_buffer mem;
 	struct ipa_hdr_init_system *cmd = NULL;
 	struct ipa_hw_imm_cmd_dma_shared_mem *dma_cmd = NULL;
+	gfp_t flag = GFP_ATOMIC | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
 	int rc = -EFAULT;
 
 	if (ipa_generate_hdr_hw_tbl(&mem)) {
@@ -281,7 +282,7 @@
 				IPA_MEM_PART(apps_hdr_size));
 			goto fail_send_cmd;
 		} else {
-			dma_cmd = kzalloc(sizeof(*dma_cmd), GFP_ATOMIC);
+			dma_cmd = kzalloc(sizeof(*dma_cmd), flag);
 			if (dma_cmd == NULL) {
 				IPAERR("fail to alloc immediate cmd\n");
 				rc = -ENOMEM;
@@ -303,7 +304,7 @@
 				IPA_MEM_PART(apps_hdr_size_ddr));
 			goto fail_send_cmd;
 		} else {
-			cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
+			cmd = kzalloc(sizeof(*cmd), flag);
 			if (cmd == NULL) {
 				IPAERR("fail to alloc hdr init cmd\n");
 				rc = -ENOMEM;
@@ -359,6 +360,7 @@
 	struct ipa_hw_imm_cmd_dma_shared_mem *dma_cmd_hdr = NULL;
 	struct ipa_hw_imm_cmd_dma_shared_mem *dma_cmd_ctx = NULL;
 	struct ipa_register_write *reg_write_cmd = NULL;
+	gfp_t flag = GFP_ATOMIC | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
 	int rc = -EFAULT;
 	u32 proc_ctx_size;
 	u32 proc_ctx_ofst;
@@ -383,7 +385,7 @@
 				IPA_MEM_PART(apps_hdr_size));
 			goto fail_send_cmd1;
 		} else {
-			dma_cmd_hdr = kzalloc(sizeof(*dma_cmd_hdr), GFP_ATOMIC);
+			dma_cmd_hdr = kzalloc(sizeof(*dma_cmd_hdr), flag);
 			if (dma_cmd_hdr == NULL) {
 				IPAERR("fail to alloc immediate cmd\n");
 				rc = -ENOMEM;
@@ -406,7 +408,7 @@
 			goto fail_send_cmd1;
 		} else {
 			hdr_init_cmd = kzalloc(sizeof(*hdr_init_cmd),
-				GFP_ATOMIC);
+				flag);
 			if (hdr_init_cmd == NULL) {
 				IPAERR("fail to alloc immediate cmd\n");
 				rc = -ENOMEM;
@@ -431,7 +433,7 @@
 			goto fail_send_cmd1;
 		} else {
 			dma_cmd_ctx = kzalloc(sizeof(*dma_cmd_ctx),
-				GFP_ATOMIC);
+				flag);
 			if (dma_cmd_ctx == NULL) {
 				IPAERR("fail to alloc immediate cmd\n");
 				rc = -ENOMEM;
@@ -456,7 +458,7 @@
 			goto fail_send_cmd1;
 		} else {
 			reg_write_cmd = kzalloc(sizeof(*reg_write_cmd),
-				GFP_ATOMIC);
+				flag);
 			if (reg_write_cmd == NULL) {
 				IPAERR("fail to alloc immediate cmd\n");
 				rc = -ENOMEM;
@@ -722,6 +724,11 @@
 				entry->hdr,
 				entry->hdr_len,
 				DMA_TO_DEVICE);
+			if (dma_mapping_error(ipa_ctx->pdev,
+				entry->phys_base)) {
+				IPAERR("dma_map_single failure for entry\n");
+				goto fail_dma_mapping;
+			}
 		}
 	} else {
 		entry->is_hdr_proc_ctx = false;
@@ -798,6 +805,8 @@
 	list_del(&entry->link);
 	dma_unmap_single(ipa_ctx->pdev, entry->phys_base,
 			entry->hdr_len, DMA_TO_DEVICE);
+fail_dma_mapping:
+	entry->is_hdr_proc_ctx = false;
 bad_hdr_len:
 	entry->cookie = 0;
 	kmem_cache_free(ipa_ctx->hdr_cache, entry);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
index 84849a2..21fdec0 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
@@ -695,6 +695,7 @@
 	struct ipa_mem_buffer head;
 	struct ipa_hw_imm_cmd_dma_shared_mem *cmd1 = NULL;
 	struct ipa_hw_imm_cmd_dma_shared_mem *cmd2 = NULL;
+	gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0);
 	u16 avail;
 	u32 num_modem_rt_index;
 	int rc = 0;
@@ -745,7 +746,7 @@
 	}
 
 	cmd1 = kzalloc(sizeof(struct ipa_hw_imm_cmd_dma_shared_mem),
-		GFP_KERNEL);
+		flag);
 	if (cmd1 == NULL) {
 		IPAERR("Failed to alloc immediate command object\n");
 		rc = -ENOMEM;
@@ -762,7 +763,7 @@
 
 	if (lcl) {
 		cmd2 = kzalloc(sizeof(struct ipa_hw_imm_cmd_dma_shared_mem),
-			GFP_KERNEL);
+			flag);
 		if (cmd2 == NULL) {
 			IPAERR("Failed to alloc immediate command object\n");
 			rc = -ENOMEM;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 3937cfe..9d25e4a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -3509,6 +3509,7 @@
 	if (!gsi_channel_props.ring_base_vaddr) {
 		IPAERR("fail to dma alloc %u bytes\n",
 			gsi_channel_props.ring_len);
+		result = -ENOMEM;
 		goto fail_alloc_channel_ring;
 	}
 	gsi_channel_props.ring_base_addr = dma_addr;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 2ca33d8..3af4486 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1246,7 +1246,9 @@
  * Order and type of members should not be changed without a suitable change
  * to DTS file or the code that reads it.
  *
- * IPA v3.0 SRAM memory layout:
+ * IPA SRAM memory layout:
+ * +-------------------------+
+ * |    UC MEM               |
  * +-------------------------+
  * |    UC INFO              |
  * +-------------------------+
@@ -1314,10 +1316,14 @@
  * +-------------------------+
  * |    CANARY               |
  * +-------------------------+
+ * |    CANARY               |
+ * +-------------------------+
  * |  MODEM MEM              |
  * +-------------------------+
  * |    CANARY               |
  * +-------------------------+
+ * |  UC EVENT RING          | From IPA 3.5
+ * +-------------------------+
  */
 struct ipa3_mem_partition {
 	u32 ofst_start;
diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c
index efcc4e8..9f04957 100644
--- a/drivers/power/reset/msm-poweroff.c
+++ b/drivers/power/reset/msm-poweroff.c
@@ -28,6 +28,7 @@
 
 #include <asm/cacheflush.h>
 #include <asm/system_misc.h>
+#include <asm/memory.h>
 
 #include <soc/qcom/scm.h>
 #include <soc/qcom/restart.h>
@@ -57,11 +58,17 @@
 #ifdef CONFIG_QCOM_DLOAD_MODE
 #define EDL_MODE_PROP "qcom,msm-imem-emergency_download_mode"
 #define DL_MODE_PROP "qcom,msm-imem-download_mode"
+#ifdef CONFIG_RANDOMIZE_BASE
+#define KASLR_OFFSET_PROP "qcom,msm-imem-kaslr_offset"
+#endif
 
 static int in_panic;
 static void *dload_mode_addr;
 static bool dload_mode_enabled;
 static void *emergency_dload_mode_addr;
+#ifdef CONFIG_RANDOMIZE_BASE
+static void *kaslr_imem_addr;
+#endif
 static bool scm_dload_supported;
 
 static int dload_set(const char *val, struct kernel_param *kp);
@@ -420,6 +427,27 @@
 			pr_err("unable to map imem EDLOAD mode offset\n");
 	}
 
+#ifdef CONFIG_RANDOMIZE_BASE
+#define KASLR_OFFSET_BIT_MASK	0x00000000FFFFFFFF
+	np = of_find_compatible_node(NULL, NULL, KASLR_OFFSET_PROP);
+	if (!np) {
+		pr_err("unable to find DT imem KASLR_OFFSET node\n");
+	} else {
+		kaslr_imem_addr = of_iomap(np, 0);
+		if (!kaslr_imem_addr)
+			pr_err("unable to map imem KASLR offset\n");
+	}
+
+	if (kaslr_imem_addr && scm_is_secure_device()) {
+		__raw_writel(0xdead4ead, kaslr_imem_addr);
+		__raw_writel(KASLR_OFFSET_BIT_MASK &
+		(kimage_vaddr - KIMAGE_VADDR), kaslr_imem_addr + 4);
+		__raw_writel(KASLR_OFFSET_BIT_MASK &
+			((kimage_vaddr - KIMAGE_VADDR) >> 32),
+			kaslr_imem_addr + 8);
+		iounmap(kaslr_imem_addr);
+	}
+#endif
 #endif
 	np = of_find_compatible_node(NULL, NULL,
 				"qcom,msm-imem-restart_reason");
@@ -484,4 +512,4 @@
 {
 	return platform_driver_register(&msm_restart_driver);
 }
-device_initcall(msm_restart_init);
+pure_initcall(msm_restart_init);
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index b985ecd..54bef52 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -434,23 +434,28 @@
 		return rc;
 	}
 
-	split_fcc(chip, total_fcc_ua, &master_fcc_ua, &slave_fcc_ua);
-	pval.intval = slave_fcc_ua;
-	rc = power_supply_set_property(chip->pl_psy,
-			POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval);
-	if (rc < 0) {
-		pr_err("Couldn't set parallel fcc, rc=%d\n", rc);
-		return rc;
-	}
+	if (chip->pl_mode != POWER_SUPPLY_PL_NONE) {
+		split_fcc(chip, total_fcc_ua, &master_fcc_ua, &slave_fcc_ua);
 
-	chip->slave_fcc_ua = slave_fcc_ua;
+		pval.intval = slave_fcc_ua;
+		rc = power_supply_set_property(chip->pl_psy,
+				POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+				&pval);
+		if (rc < 0) {
+			pr_err("Couldn't set parallel fcc, rc=%d\n", rc);
+			return rc;
+		}
 
-	pval.intval = master_fcc_ua;
-	rc = power_supply_set_property(chip->main_psy,
-			POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, &pval);
-	if (rc < 0) {
-		pr_err("Could not set main fcc, rc=%d\n", rc);
-		return rc;
+		chip->slave_fcc_ua = slave_fcc_ua;
+
+		pval.intval = master_fcc_ua;
+		rc = power_supply_set_property(chip->main_psy,
+				POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+				&pval);
+		if (rc < 0) {
+			pr_err("Could not set main fcc, rc=%d\n", rc);
+			return rc;
+		}
 	}
 
 	pl_dbg(chip, PR_PARALLEL, "master_fcc=%d slave_fcc=%d distribution=(%d/%d)\n",
@@ -511,13 +516,14 @@
 	return 0;
 }
 
-#define ICL_STEP_UV	25000
+#define ICL_STEP_UA	25000
 static int usb_icl_vote_callback(struct votable *votable, void *data,
 			int icl_ua, const char *client)
 {
 	int rc;
 	struct pl_data *chip = data;
 	union power_supply_propval pval = {0, };
+	bool rerun_aicl = false;
 
 	if (!chip->main_psy)
 		return 0;
@@ -543,22 +549,28 @@
 	}
 
 	/* rerun AICL if new ICL is above settled ICL */
-	if (icl_ua > pval.intval) {
-		/* set a lower ICL */
-		pval.intval = max(pval.intval - ICL_STEP_UV, ICL_STEP_UV);
-		power_supply_set_property(chip->main_psy,
-				POWER_SUPPLY_PROP_CURRENT_MAX,
-				&pval);
-		/* wait for ICL change */
-		msleep(100);
+	if (icl_ua > pval.intval)
+		rerun_aicl = true;
 
-		pval.intval = icl_ua;
+	if (rerun_aicl) {
+		/* set a lower ICL */
+		pval.intval = max(pval.intval - ICL_STEP_UA, ICL_STEP_UA);
 		power_supply_set_property(chip->main_psy,
 				POWER_SUPPLY_PROP_CURRENT_MAX,
 				&pval);
 		/* wait for ICL change */
 		msleep(100);
 	}
+
+	/* set the effective ICL */
+	pval.intval = icl_ua;
+	power_supply_set_property(chip->main_psy,
+			POWER_SUPPLY_PROP_CURRENT_MAX,
+			&pval);
+	if (rerun_aicl)
+		/* wait for ICL change */
+		msleep(100);
+
 	vote(chip->pl_disable_votable, ICL_CHANGE_VOTER, false, 0);
 
 	return 0;
@@ -678,9 +690,6 @@
 
 	chip->main_psy = power_supply_get_by_name("main");
 
-	if (chip->main_psy)
-		rerun_election(chip->usb_icl_votable);
-
 	return !!chip->main_psy;
 }
 
@@ -859,7 +868,18 @@
 	struct pl_data *chip = container_of(work,
 			struct pl_data, status_change_work);
 
-	if (!is_main_available(chip))
+	if (!chip->main_psy && is_main_available(chip)) {
+		/*
+		 * re-run election for FCC/FV/ICL once main_psy
+		 * is available to ensure all votes are reflected
+		 * on hardware
+		 */
+		rerun_election(chip->usb_icl_votable);
+		rerun_election(chip->fcc_votable);
+		rerun_election(chip->fv_votable);
+	}
+
+	if (!chip->main_psy)
 		return;
 
 	if (!is_batt_available(chip))
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index ca551a5a..5983b5c 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -128,11 +128,6 @@
 	FG_IRQ_MAX,
 };
 
-/* WA flags */
-enum {
-	DELTA_SOC_IRQ_WA = BIT(0),
-};
-
 /*
  * List of FG_SRAM parameters. Please add a parameter only if it is an entry
  * that will be used either to configure an entity (e.g. termination current)
@@ -152,6 +147,7 @@
 	FG_SRAM_CC_SOC,
 	FG_SRAM_CC_SOC_SW,
 	FG_SRAM_ACT_BATT_CAP,
+	FG_SRAM_TIMEBASE,
 	/* Entries below here are configurable during initialization */
 	FG_SRAM_CUTOFF_VOLT,
 	FG_SRAM_EMPTY_VOLT,
@@ -212,6 +208,7 @@
 
 enum wa_flags {
 	PMI8998_V1_REV_WA = BIT(0),
+	PM660_TSMC_OSC_WA = BIT(1),
 };
 
 enum slope_limit_status {
@@ -325,6 +322,23 @@
 	{ 128000,	4852 },
 };
 
+/* each tuple is - <temperature in degC, Timebase> */
+static const struct fg_pt fg_tsmc_osc_table[] = {
+	{ -20,		395064 },
+	{ -10,		398114 },
+	{   0,		401669 },
+	{  10,		404641 },
+	{  20,		408856 },
+	{  25,		412449 },
+	{  30,		416532 },
+	{  40,		420289 },
+	{  50,		425020 },
+	{  60,		430160 },
+	{  70,		434175 },
+	{  80,		439475 },
+	{  90,		444992 },
+};
+
 struct fg_chip {
 	struct device		*dev;
 	struct pmic_revid_data	*pmic_rev_id;
@@ -336,6 +350,7 @@
 	struct power_supply	*dc_psy;
 	struct power_supply	*parallel_psy;
 	struct iio_channel	*batt_id_chan;
+	struct iio_channel	*die_temp_chan;
 	struct fg_memif		*sram;
 	struct fg_irq_info	*irqs;
 	struct votable		*awake_votable;
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index b42a65d..806460f 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -47,6 +47,7 @@
 #define ESR_UPD_TIGHT_LOW_TEMP_OFFSET	2
 #define ESR_UPD_BROAD_LOW_TEMP_OFFSET	3
 #define KI_COEFF_MED_DISCHG_WORD	9
+#define TIMEBASE_OFFSET			1
 #define KI_COEFF_MED_DISCHG_OFFSET	3
 #define KI_COEFF_HI_DISCHG_WORD		10
 #define KI_COEFF_HI_DISCHG_OFFSET	0
@@ -261,6 +262,8 @@
 		fg_decode_cc_soc),
 	PARAM(ACT_BATT_CAP, ACT_BATT_CAP_BKUP_WORD, ACT_BATT_CAP_BKUP_OFFSET, 2,
 		1, 1, 0, NULL, fg_decode_default),
+	PARAM(TIMEBASE, KI_COEFF_MED_DISCHG_WORD, TIMEBASE_OFFSET, 2, 1000,
+		61000, 0, fg_encode_default, NULL),
 	/* Entries below here are configurable during initialization */
 	PARAM(CUTOFF_VOLT, CUTOFF_VOLT_WORD, CUTOFF_VOLT_OFFSET, 2, 1000000,
 		244141, 0, fg_encode_voltage, NULL),
@@ -1967,7 +1970,7 @@
 {
 	union power_supply_propval prop = {0, };
 	int rc;
-	bool parallel_en = false;
+	bool parallel_en = false, qnovo_en = false;
 
 	if (is_parallel_charger_available(chip)) {
 		rc = power_supply_get_property(chip->parallel_psy,
@@ -1980,19 +1983,25 @@
 		parallel_en = prop.intval;
 	}
 
-	fg_dbg(chip, FG_POWER_SUPPLY, "charge_status: %d parallel_en: %d esr_fcc_ctrl_en: %d\n",
-		chip->charge_status, parallel_en, chip->esr_fcc_ctrl_en);
+	rc = power_supply_get_property(chip->batt_psy,
+			POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE, &prop);
+	if (!rc)
+		qnovo_en = prop.intval;
+
+	fg_dbg(chip, FG_POWER_SUPPLY, "chg_sts: %d par_en: %d qnov_en: %d esr_fcc_ctrl_en: %d\n",
+		chip->charge_status, parallel_en, qnovo_en,
+		chip->esr_fcc_ctrl_en);
 
 	if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING &&
-								parallel_en) {
+			(parallel_en || qnovo_en)) {
 		if (chip->esr_fcc_ctrl_en)
 			return 0;
 
 		/*
-		 * When parallel charging is enabled, configure ESR FCC to
-		 * 300mA to trigger an ESR pulse. Without this, FG can ask
-		 * the main charger to increase FCC when it is supposed to
-		 * decrease it.
+		 * When parallel charging or Qnovo is enabled, configure ESR
+		 * FCC to 300mA to trigger an ESR pulse. Without this, FG can
+		 * request the main charger to increase FCC when it is supposed
+		 * to decrease it.
 		 */
 		rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip),
 				ESR_FAST_CRG_IVAL_MASK |
@@ -2011,8 +2020,8 @@
 
 		/*
 		 * If we're here, then it means either the device is not in
-		 * charging state or parallel charging is disabled. Disable
-		 * ESR fast charge current control in SW.
+		 * charging state or parallel charging / Qnovo is disabled.
+		 * Disable ESR fast charge current control in SW.
 		 */
 		rc = fg_masked_write(chip, BATT_INFO_ESR_FAST_CRG_CFG(chip),
 				ESR_FAST_CRG_CTL_EN_BIT, 0);
@@ -3365,6 +3374,40 @@
 	return fg_ima_init(chip);
 }
 
+static int fg_adjust_timebase(struct fg_chip *chip)
+{
+	int rc = 0, die_temp;
+	s32 time_base = 0;
+	u8 buf[2] = {0};
+
+	if ((chip->wa_flags & PM660_TSMC_OSC_WA) && chip->die_temp_chan) {
+		rc = iio_read_channel_processed(chip->die_temp_chan, &die_temp);
+		if (rc < 0) {
+			pr_err("Error in reading die_temp, rc:%d\n", rc);
+			return rc;
+		}
+
+		rc = fg_lerp(fg_tsmc_osc_table, ARRAY_SIZE(fg_tsmc_osc_table),
+					die_temp / 1000, &time_base);
+		if (rc < 0) {
+			pr_err("Error to lookup fg_tsmc_osc_table rc=%d\n", rc);
+			return rc;
+		}
+
+		fg_encode(chip->sp, FG_SRAM_TIMEBASE, time_base, buf);
+		rc = fg_sram_write(chip,
+			chip->sp[FG_SRAM_TIMEBASE].addr_word,
+			chip->sp[FG_SRAM_TIMEBASE].addr_byte, buf,
+			chip->sp[FG_SRAM_TIMEBASE].len, FG_IMA_DEFAULT);
+		if (rc < 0) {
+			pr_err("Error in writing timebase, rc=%d\n", rc);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
 /* INTERRUPT HANDLERS STAY HERE */
 
 static irqreturn_t fg_mem_xcp_irq_handler(int irq, void *data)
@@ -3486,6 +3529,10 @@
 	chip->health = prop.intval;
 
 	if (chip->last_batt_temp != batt_temp) {
+		rc = fg_adjust_timebase(chip);
+		if (rc < 0)
+			pr_err("Error in adjusting timebase, rc=%d\n", rc);
+
 		chip->last_batt_temp = batt_temp;
 		power_supply_changed(chip->batt_psy);
 	}
@@ -3555,6 +3602,10 @@
 	if (rc < 0)
 		pr_err("Error in validating ESR, rc=%d\n", rc);
 
+	rc = fg_adjust_timebase(chip);
+	if (rc < 0)
+		pr_err("Error in adjusting timebase, rc=%d\n", rc);
+
 	if (batt_psy_initialized(chip))
 		power_supply_changed(chip->batt_psy);
 
@@ -3897,6 +3948,8 @@
 		chip->sp = pmi8998_v2_sram_params;
 		chip->alg_flags = pmi8998_v2_alg_flags;
 		chip->use_ima_single_mode = true;
+		if (chip->pmic_rev_id->fab_id == PM660_FAB_ID_TSMC)
+			chip->wa_flags |= PM660_TSMC_OSC_WA;
 		break;
 	default:
 		return -EINVAL;
@@ -4238,6 +4291,21 @@
 		return rc;
 	}
 
+	rc = of_property_match_string(chip->dev->of_node,
+				"io-channel-names", "rradc_die_temp");
+	if (rc >= 0) {
+		chip->die_temp_chan = iio_channel_get(chip->dev,
+						"rradc_die_temp");
+		if (IS_ERR(chip->die_temp_chan)) {
+			if (PTR_ERR(chip->die_temp_chan) != -EPROBE_DEFER)
+				pr_err("rradc_die_temp unavailable %ld\n",
+					PTR_ERR(chip->die_temp_chan));
+			rc = PTR_ERR(chip->die_temp_chan);
+			chip->die_temp_chan = NULL;
+			return rc;
+		}
+	}
+
 	chip->awake_votable = create_votable("FG_WS", VOTE_SET_ANY, fg_awake_cb,
 					chip);
 	if (IS_ERR(chip->awake_votable)) {
diff --git a/drivers/power/supply/qcom/qpnp-qnovo.c b/drivers/power/supply/qcom/qpnp-qnovo.c
index c74dc89..eb97eb0 100644
--- a/drivers/power/supply/qcom/qpnp-qnovo.c
+++ b/drivers/power/supply/qcom/qpnp-qnovo.c
@@ -89,7 +89,16 @@
 #define QNOVO_STRM_CTRL		0xA8
 #define QNOVO_IADC_OFFSET_OVR_VAL	0xA9
 #define QNOVO_IADC_OFFSET_OVR		0xAA
+
 #define QNOVO_DISABLE_CHARGING		0xAB
+#define ERR_SWITCHER_DISABLED		BIT(7)
+#define ERR_JEITA_SOFT_CONDITION	BIT(6)
+#define ERR_BAT_OV			BIT(5)
+#define ERR_CV_MODE			BIT(4)
+#define ERR_BATTERY_MISSING		BIT(3)
+#define ERR_SAFETY_TIMER_EXPIRED	BIT(2)
+#define ERR_CHARGING_DISABLED		BIT(1)
+#define ERR_JEITA_HARD_CONDITION	BIT(0)
 
 #define QNOVO_TR_IADC_OFFSET_0	0xF1
 #define QNOVO_TR_IADC_OFFSET_1	0xF2
@@ -1107,24 +1116,28 @@
 {
 	u8 val = 0;
 	int rc;
-	bool charging;
+	bool ok_to_qnovo;
 	bool changed = false;
 
 	rc = qnovo_read(chip, QNOVO_ERROR_STS2, &val, 1);
 	if (rc < 0) {
 		pr_err("Couldn't read error sts rc = %d\n", rc);
-		charging = false;
+		ok_to_qnovo = false;
 	} else {
-		charging = !(val & QNOVO_ERROR_CHARGING_DISABLED);
+		/*
+		 * For CV mode keep qnovo enabled, userspace is expected to
+		 * disable it after few runs
+		 */
+		ok_to_qnovo = (val == ERR_CV_MODE || val == 0) ? true : false;
 	}
 
-	if (chip->ok_to_qnovo ^ charging) {
+	if (chip->ok_to_qnovo ^ ok_to_qnovo) {
 
-		vote(chip->disable_votable, OK_TO_QNOVO_VOTER, !charging, 0);
-		if (!charging)
+		vote(chip->disable_votable, OK_TO_QNOVO_VOTER, !ok_to_qnovo, 0);
+		if (!ok_to_qnovo)
 			vote(chip->disable_votable, USER_VOTER, true, 0);
 
-		chip->ok_to_qnovo = charging;
+		chip->ok_to_qnovo = ok_to_qnovo;
 		changed = true;
 	}
 
@@ -1247,6 +1260,16 @@
 	chip->v_gain_mega = 1000000000 + (s64)(s8)vadc_gain * GAIN_LSB_FACTOR;
 	chip->v_gain_mega = div_s64(chip->v_gain_mega, 1000);
 
+	/* allow charger error conditions to disable qnovo, CV mode excluded */
+	val = ERR_SWITCHER_DISABLED | ERR_JEITA_SOFT_CONDITION | ERR_BAT_OV |
+		ERR_BATTERY_MISSING | ERR_SAFETY_TIMER_EXPIRED |
+		ERR_CHARGING_DISABLED | ERR_JEITA_HARD_CONDITION;
+	rc = qnovo_write(chip, QNOVO_DISABLE_CHARGING, &val, 1);
+	if (rc < 0) {
+		pr_err("Couldn't write QNOVO_DISABLE_CHARGING rc = %d\n", rc);
+		return rc;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 8fd45f18..e802fbd 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -244,6 +244,8 @@
 	int	boost_threshold_ua;
 	int	fv_uv;
 	int	wipower_max_uw;
+	int	min_freq_khz;
+	int	max_freq_khz;
 	u32	step_soc_threshold[STEP_CHARGING_MAX_STEPS - 1];
 	s32	step_cc_delta[STEP_CHARGING_MAX_STEPS];
 	struct	device_node *revid_dev_node;
@@ -338,6 +340,18 @@
 	if (rc < 0)
 		chip->dt.boost_threshold_ua = MICRO_P1A;
 
+	rc = of_property_read_u32(node,
+				"qcom,min-freq-khz",
+				&chip->dt.min_freq_khz);
+	if (rc < 0)
+		chip->dt.min_freq_khz = -EINVAL;
+
+	rc = of_property_read_u32(node,
+				"qcom,max-freq-khz",
+				&chip->dt.max_freq_khz);
+	if (rc < 0)
+		chip->dt.max_freq_khz = -EINVAL;
+
 	rc = of_property_read_u32(node, "qcom,wipower-max-uw",
 				&chip->dt.wipower_max_uw);
 	if (rc < 0)
@@ -526,6 +540,12 @@
 	struct smb_charger *chg = &chip->chg;
 	int rc = 0;
 
+	mutex_lock(&chg->lock);
+	if (!chg->typec_present) {
+		rc = -EINVAL;
+		goto unlock;
+	}
+
 	switch (psp) {
 	case POWER_SUPPLY_PROP_VOLTAGE_MIN:
 		rc = smblib_set_prop_usb_voltage_min(chg, val);
@@ -564,6 +584,8 @@
 		break;
 	}
 
+unlock:
+	mutex_unlock(&chg->lock);
 	return rc;
 }
 
@@ -1336,10 +1358,12 @@
 		return rc;
 	}
 
-	/* disable try.SINK mode */
-	rc = smblib_masked_write(chg, TYPE_C_CFG_3_REG, EN_TRYSINK_MODE_BIT, 0);
+	/* disable try.SINK mode and legacy cable IRQs */
+	rc = smblib_masked_write(chg, TYPE_C_CFG_3_REG, EN_TRYSINK_MODE_BIT |
+				TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN_BIT |
+				TYPEC_LEGACY_CABLE_INT_EN_BIT, 0);
 	if (rc < 0) {
-		dev_err(chg->dev, "Couldn't set TRYSINK_MODE rc=%d\n", rc);
+		dev_err(chg->dev, "Couldn't set Type-C config rc=%d\n", rc);
 		return rc;
 	}
 
@@ -1438,6 +1462,16 @@
 		smblib_get_charge_param(chg, &chg->param.dc_icl,
 					&chip->dt.dc_icl_ua);
 
+	if (chip->dt.min_freq_khz > 0) {
+		chg->param.freq_buck.min_u = chip->dt.min_freq_khz;
+		chg->param.freq_boost.min_u = chip->dt.min_freq_khz;
+	}
+
+	if (chip->dt.max_freq_khz > 0) {
+		chg->param.freq_buck.max_u = chip->dt.max_freq_khz;
+		chg->param.freq_boost.max_u = chip->dt.max_freq_khz;
+	}
+
 	/* set a slower soft start setting for OTG */
 	rc = smblib_masked_write(chg, DC_ENG_SSUPPLY_CFG2_REG,
 				ENG_SSUPPLY_IVREF_OTG_SS_MASK, OTG_SS_SLOW);
@@ -1485,6 +1519,8 @@
 		DEFAULT_VOTER, true, chip->dt.dc_icl_ua);
 	vote(chg->hvdcp_disable_votable_indirect, PD_INACTIVE_VOTER,
 			true, 0);
+	vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER,
+			true, 0);
 	vote(chg->hvdcp_disable_votable_indirect, DEFAULT_VOTER,
 		chip->dt.hvdcp_disable, 0);
 	vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER,
@@ -2022,6 +2058,16 @@
 	return rc;
 }
 
+static void smb2_disable_interrupts(struct smb_charger *chg)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(smb2_irqs); i++) {
+		if (smb2_irqs[i].irq > 0)
+			disable_irq(smb2_irqs[i].irq);
+	}
+}
+
 #if defined(CONFIG_DEBUG_FS)
 
 static int force_batt_psy_update_write(void *data, u64 val)
@@ -2233,7 +2279,7 @@
 	rc = smblib_get_prop_batt_health(chg, &val);
 	if (rc < 0) {
 		pr_err("Couldn't get batt health rc=%d\n", rc);
-		goto cleanup;
+		val.intval = POWER_SUPPLY_HEALTH_UNKNOWN;
 	}
 	batt_health = val.intval;
 
@@ -2284,6 +2330,9 @@
 	struct smb2 *chip = platform_get_drvdata(pdev);
 	struct smb_charger *chg = &chip->chg;
 
+	/* disable all interrupts */
+	smb2_disable_interrupts(chg);
+
 	/* configure power role for UFP */
 	smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
 				TYPEC_POWER_ROLE_CMD_MASK, UFP_EN_CMD_BIT);
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index c8deedd..7d5a8bd 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -542,30 +542,6 @@
 		smblib_err(chg, "Couldn't re-run APSD rc=%d\n", rc);
 }
 
-static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg)
-{
-	const struct apsd_result *apsd_result;
-
-	/*
-	 * PD_INACTIVE_VOTER on hvdcp_disable_votable indicates whether
-	 * apsd rerun was tried earlier
-	 */
-	if (get_client_vote(chg->hvdcp_disable_votable_indirect,
-						PD_INACTIVE_VOTER)) {
-		vote(chg->hvdcp_disable_votable_indirect,
-				PD_INACTIVE_VOTER, false, 0);
-		/* ensure hvdcp is enabled */
-		if (!get_effective_result(
-				chg->hvdcp_disable_votable_indirect)) {
-			apsd_result = smblib_get_apsd_result(chg);
-			if (apsd_result->bit & (QC_2P0_BIT | QC_3P0_BIT)) {
-				smblib_rerun_apsd(chg);
-			}
-		}
-	}
-	return 0;
-}
-
 static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg)
 {
 	const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
@@ -684,6 +660,7 @@
 	chg->voltage_max_uv = MICRO_5V;
 	chg->usb_icl_delta_ua = 0;
 	chg->pulse_cnt = 0;
+	chg->uusb_apsd_rerun_done = false;
 
 	/* clear USB ICL vote for USB_PSY_VOTER */
 	rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
@@ -751,6 +728,7 @@
 				rc);
 	}
 
+	chg->uusb_apsd_rerun_done = true;
 	smblib_rerun_apsd(chg);
 
 	return 0;
@@ -1020,6 +998,7 @@
 	struct smb_charger *chg = data;
 	int rc;
 	u8 val = HVDCP_AUTH_ALG_EN_CFG_BIT | HVDCP_EN_BIT;
+	u8 stat;
 
 	/* vote to enable/disable HW autonomous INOV */
 	vote(chg->hvdcp_hw_inov_dis_votable, client, !hvdcp_enable, 0);
@@ -1041,6 +1020,16 @@
 		return rc;
 	}
 
+	rc = smblib_read(chg, APSD_STATUS_REG, &stat);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read APSD status rc=%d\n", rc);
+		return rc;
+	}
+
+	/* re-run APSD if HVDCP was detected */
+	if (stat & QC_CHARGER_BIT)
+		smblib_rerun_apsd(chg);
+
 	return 0;
 }
 
@@ -1134,6 +1123,22 @@
 	return 0;
 }
 
+static int smblib_typec_irq_disable_vote_callback(struct votable *votable,
+				void *data, int disable, const char *client)
+{
+	struct smb_charger *chg = data;
+
+	if (!chg->irq_info[TYPE_C_CHANGE_IRQ].irq)
+		return 0;
+
+	if (disable)
+		disable_irq_nosync(chg->irq_info[TYPE_C_CHANGE_IRQ].irq);
+	else
+		enable_irq(chg->irq_info[TYPE_C_CHANGE_IRQ].irq);
+
+	return 0;
+}
+
 /*******************
  * VCONN REGULATOR *
  * *****************/
@@ -1142,7 +1147,7 @@
 static int _smblib_vconn_regulator_enable(struct regulator_dev *rdev)
 {
 	struct smb_charger *chg = rdev_get_drvdata(rdev);
-	u8 otg_stat, stat4;
+	u8 otg_stat, val;
 	int rc = 0, i;
 
 	if (!chg->external_vconn) {
@@ -1173,17 +1178,12 @@
 	 * VCONN_EN_ORIENTATION is overloaded with overriding the CC pin used
 	 * for Vconn, and it should be set with reverse polarity of CC_OUT.
 	 */
-	rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat4);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
-		return rc;
-	}
-
 	smblib_dbg(chg, PR_OTG, "enabling VCONN\n");
-	stat4 = stat4 & CC_ORIENTATION_BIT ? 0 : VCONN_EN_ORIENTATION_BIT;
+	val = chg->typec_status[3] &
+			CC_ORIENTATION_BIT ? 0 : VCONN_EN_ORIENTATION_BIT;
 	rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
 				 VCONN_EN_VALUE_BIT | VCONN_EN_ORIENTATION_BIT,
-				 VCONN_EN_VALUE_BIT | stat4);
+				 VCONN_EN_VALUE_BIT | val);
 	if (rc < 0) {
 		smblib_err(chg, "Couldn't enable vconn setting rc=%d\n", rc);
 		return rc;
@@ -1531,6 +1531,21 @@
 		break;
 	}
 
+	if (val->intval != POWER_SUPPLY_STATUS_CHARGING)
+		return 0;
+
+	rc = smblib_read(chg, BATTERY_CHARGER_STATUS_7_REG, &stat);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n",
+				rc);
+			return rc;
+		}
+
+	stat &= ENABLE_TRICKLE_BIT | ENABLE_PRE_CHARGING_BIT |
+		 ENABLE_FAST_CHARGING_BIT | ENABLE_FULLON_MODE_BIT;
+	if (!stat)
+		val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+
 	return 0;
 }
 
@@ -2131,23 +2146,13 @@
 int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
 					 union power_supply_propval *val)
 {
-	int rc = 0;
-	u8 stat;
-
-	rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
-		return rc;
-	}
-	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n",
-		   stat);
-
-	if (stat & CC_ATTACHED_BIT)
-		val->intval = (bool)(stat & CC_ORIENTATION_BIT) + 1;
+	if (chg->typec_status[3] & CC_ATTACHED_BIT)
+		val->intval =
+			(bool)(chg->typec_status[3] & CC_ORIENTATION_BIT) + 1;
 	else
 		val->intval = 0;
 
-	return rc;
+	return 0;
 }
 
 static const char * const smblib_typec_mode_name[] = {
@@ -2165,17 +2170,7 @@
 
 static int smblib_get_prop_ufp_mode(struct smb_charger *chg)
 {
-	int rc;
-	u8 stat;
-
-	rc = smblib_read(chg, TYPE_C_STATUS_1_REG, &stat);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't read TYPE_C_STATUS_1 rc=%d\n", rc);
-		return POWER_SUPPLY_TYPEC_NONE;
-	}
-	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_1 = 0x%02x\n", stat);
-
-	switch (stat) {
+	switch (chg->typec_status[0]) {
 	case 0:
 		return POWER_SUPPLY_TYPEC_NONE;
 	case UFP_TYPEC_RDSTD_BIT:
@@ -2193,17 +2188,7 @@
 
 static int smblib_get_prop_dfp_mode(struct smb_charger *chg)
 {
-	int rc;
-	u8 stat;
-
-	rc = smblib_read(chg, TYPE_C_STATUS_2_REG, &stat);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't read TYPE_C_STATUS_2 rc=%d\n", rc);
-		return POWER_SUPPLY_TYPEC_NONE;
-	}
-	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_2 = 0x%02x\n", stat);
-
-	switch (stat & DFP_TYPEC_MASK) {
+	switch (chg->typec_status[1] & DFP_TYPEC_MASK) {
 	case DFP_RA_RA_BIT:
 		return POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER;
 	case DFP_RD_RD_BIT:
@@ -2224,28 +2209,17 @@
 int smblib_get_prop_typec_mode(struct smb_charger *chg,
 			       union power_supply_propval *val)
 {
-	int rc;
-	u8 stat;
-
-	rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
+	if (!(chg->typec_status[3] & TYPEC_DEBOUNCE_DONE_STATUS_BIT)) {
 		val->intval = POWER_SUPPLY_TYPEC_NONE;
-		return rc;
-	}
-	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat);
-
-	if (!(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT)) {
-		val->intval = POWER_SUPPLY_TYPEC_NONE;
-		return rc;
+		return 0;
 	}
 
-	if (stat & UFP_DFP_MODE_STATUS_BIT)
+	if (chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT)
 		val->intval = smblib_get_prop_dfp_mode(chg);
 	else
 		val->intval = smblib_get_prop_ufp_mode(chg);
 
-	return rc;
+	return 0;
 }
 
 int smblib_get_prop_typec_power_role(struct smb_charger *chg,
@@ -2337,16 +2311,7 @@
 int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
 			       union power_supply_propval *val)
 {
-	int rc;
-	u8 ctrl;
-
-	rc = smblib_read(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, &ctrl);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG rc=%d\n",
-			rc);
-		return rc;
-	}
-	val->intval = ctrl & EXIT_SNK_BASED_ON_CC_BIT;
+	val->intval = chg->pd_hard_reset;
 	return 0;
 }
 
@@ -2542,53 +2507,60 @@
 			      const union power_supply_propval *val)
 {
 	int rc;
-	u8 stat = 0;
-	bool cc_debounced;
-	bool orientation;
-	bool pd_active = val->intval;
+	bool orientation, cc_debounced, sink_attached, hvdcp;
+	u8 stat;
 
-	if (!get_effective_result(chg->pd_allowed_votable)) {
-		smblib_err(chg, "PD is not allowed\n");
+	if (!get_effective_result(chg->pd_allowed_votable))
 		return -EINVAL;
-	}
 
-	vote(chg->apsd_disable_votable, PD_VOTER, pd_active, 0);
-	vote(chg->pd_allowed_votable, PD_VOTER, pd_active, 0);
-	vote(chg->usb_irq_enable_votable, PD_VOTER, pd_active, 0);
-
-	/*
-	 * VCONN_EN_ORIENTATION_BIT controls whether to use CC1 or CC2 line
-	 * when TYPEC_SPARE_CFG_BIT (CC pin selection s/w override) is set
-	 * or when VCONN_EN_VALUE_BIT is set.
-	 */
-	rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
+	rc = smblib_read(chg, APSD_STATUS_REG, &stat);
 	if (rc < 0) {
-		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
+		smblib_err(chg, "Couldn't read APSD status rc=%d\n", rc);
 		return rc;
 	}
 
-	if (pd_active) {
-		orientation = stat & CC_ORIENTATION_BIT;
+	cc_debounced = (bool)
+		(chg->typec_status[3] & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
+	sink_attached = (bool)
+		(chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT);
+	hvdcp = stat & QC_CHARGER_BIT;
+
+	chg->pd_active = val->intval;
+	if (chg->pd_active) {
+		vote(chg->apsd_disable_votable, PD_VOTER, true, 0);
+		vote(chg->pd_allowed_votable, PD_VOTER, true, 0);
+		vote(chg->usb_irq_enable_votable, PD_VOTER, true, 0);
+
+		/*
+		 * VCONN_EN_ORIENTATION_BIT controls whether to use CC1 or CC2
+		 * line when TYPEC_SPARE_CFG_BIT (CC pin selection s/w override)
+		 * is set or when VCONN_EN_VALUE_BIT is set.
+		 */
+		orientation = chg->typec_status[3] & CC_ORIENTATION_BIT;
 		rc = smblib_masked_write(chg,
 				TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
 				VCONN_EN_ORIENTATION_BIT,
 				orientation ? 0 : VCONN_EN_ORIENTATION_BIT);
-		if (rc < 0) {
+		if (rc < 0)
 			smblib_err(chg,
 				"Couldn't enable vconn on CC line rc=%d\n", rc);
-			return rc;
-		}
+
+		/* SW controlled CC_OUT */
+		rc = smblib_masked_write(chg, TAPER_TIMER_SEL_CFG_REG,
+				TYPEC_SPARE_CFG_BIT, TYPEC_SPARE_CFG_BIT);
+		if (rc < 0)
+			smblib_err(chg, "Couldn't enable SW cc_out rc=%d\n",
+									rc);
+
 		/*
 		 * Enforce 500mA for PD until the real vote comes in later.
 		 * It is guaranteed that pd_active is set prior to
 		 * pd_current_max
 		 */
 		rc = vote(chg->usb_icl_votable, PD_VOTER, true, USBIN_500MA);
-		if (rc < 0) {
+		if (rc < 0)
 			smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n",
-					rc);
-			return rc;
-		}
+									rc);
 
 		/* since PD was found the cable must be non-legacy */
 		vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0);
@@ -2596,36 +2568,40 @@
 		/* clear USB ICL vote for DCP_VOTER */
 		rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
 		if (rc < 0)
-			smblib_err(chg,
-				"Couldn't un-vote DCP from USB ICL rc=%d\n",
-				rc);
+			smblib_err(chg, "Couldn't un-vote DCP from USB ICL rc=%d\n",
+									rc);
 
 		/* remove USB_PSY_VOTER */
 		rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
-		if (rc < 0) {
+		if (rc < 0)
 			smblib_err(chg, "Couldn't unvote USB_PSY rc=%d\n", rc);
-			return rc;
-		}
+	} else {
+		vote(chg->apsd_disable_votable, PD_VOTER, false, 0);
+		vote(chg->pd_allowed_votable, PD_VOTER, true, 0);
+		vote(chg->usb_irq_enable_votable, PD_VOTER, true, 0);
+		vote(chg->hvdcp_disable_votable_indirect, PD_INACTIVE_VOTER,
+								false, 0);
+
+		/* HW controlled CC_OUT */
+		rc = smblib_masked_write(chg, TAPER_TIMER_SEL_CFG_REG,
+							TYPEC_SPARE_CFG_BIT, 0);
+		if (rc < 0)
+			smblib_err(chg, "Couldn't enable HW cc_out rc=%d\n",
+									rc);
+
+		/*
+		 * This WA should only run for HVDCP. Non-legacy SDP/CDP could
+		 * draw more, but this WA will remove Rd causing VBUS to drop,
+		 * and data could be interrupted. Non-legacy DCP could also draw
+		 * more, but it may impact compliance.
+		 */
+		if (!chg->typec_legacy_valid && cc_debounced &&
+							!sink_attached && hvdcp)
+			schedule_work(&chg->legacy_detection_work);
 	}
 
-	/* CC pin selection s/w override in PD session; h/w otherwise. */
-	rc = smblib_masked_write(chg, TAPER_TIMER_SEL_CFG_REG,
-				 TYPEC_SPARE_CFG_BIT,
-				 pd_active ? TYPEC_SPARE_CFG_BIT : 0);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't change cc_out ctrl to %s rc=%d\n",
-			pd_active ? "SW" : "HW", rc);
-		return rc;
-	}
-
-	cc_debounced = (bool)(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
-	if (!pd_active && cc_debounced)
-		try_rerun_apsd_for_hvdcp(chg);
-
-	chg->pd_active = pd_active;
 	smblib_update_usb_type(chg);
 	power_supply_changed(chg->usb_psy);
-
 	return rc;
 }
 
@@ -2728,88 +2704,70 @@
 
 static int smblib_cc2_sink_removal_enter(struct smb_charger *chg)
 {
-	int rc = 0;
-	union power_supply_propval cc2_val = {0, };
+	int rc, ccout, ufp_mode;
+	u8 stat;
 
 	if ((chg->wa_flags & TYPEC_CC2_REMOVAL_WA_BIT) == 0)
-		return rc;
+		return 0;
 
-	if (chg->cc2_sink_detach_flag != CC2_SINK_NONE)
-		return rc;
+	if (chg->cc2_detach_wa_active)
+		return 0;
 
-	rc = smblib_get_prop_typec_cc_orientation(chg, &cc2_val);
+	rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
 	if (rc < 0) {
-		smblib_err(chg, "Couldn't get cc orientation rc=%d\n", rc);
+		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
 		return rc;
 	}
-	if (cc2_val.intval == 1)
-		return rc;
+	ccout = (stat & CC_ATTACHED_BIT) ?
+					(!!(stat & CC_ORIENTATION_BIT) + 1) : 0;
+	ufp_mode = (stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT) ?
+					!(stat & UFP_DFP_MODE_STATUS_BIT) : 0;
 
-	rc = smblib_get_prop_typec_mode(chg, &cc2_val);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't get prop typec mode rc=%d\n", rc);
-		return rc;
-	}
+	if (ccout != 2)
+		return 0;
 
-	switch (cc2_val.intval) {
-	case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
-		smblib_reg_block_update(chg, cc2_detach_settings);
-		chg->cc2_sink_detach_flag = CC2_SINK_STD;
-		schedule_work(&chg->rdstd_cc2_detach_work);
-		break;
-	case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
-	case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
-		chg->cc2_sink_detach_flag = CC2_SINK_MEDIUM_HIGH;
-		break;
-	default:
-		break;
-	}
+	if (!ufp_mode)
+		return 0;
 
+	chg->cc2_detach_wa_active = true;
+	/* The CC2 removal WA will cause a type-c-change IRQ storm */
+	smblib_reg_block_update(chg, cc2_detach_settings);
+	schedule_work(&chg->rdstd_cc2_detach_work);
 	return rc;
 }
 
 static int smblib_cc2_sink_removal_exit(struct smb_charger *chg)
 {
-	int rc = 0;
-
 	if ((chg->wa_flags & TYPEC_CC2_REMOVAL_WA_BIT) == 0)
-		return rc;
+		return 0;
 
-	if (chg->cc2_sink_detach_flag == CC2_SINK_STD) {
-		cancel_work_sync(&chg->rdstd_cc2_detach_work);
-		smblib_reg_block_restore(chg, cc2_detach_settings);
-	}
+	if (!chg->cc2_detach_wa_active)
+		return 0;
 
-	chg->cc2_sink_detach_flag = CC2_SINK_NONE;
-
-	return rc;
+	chg->cc2_detach_wa_active = false;
+	cancel_work_sync(&chg->rdstd_cc2_detach_work);
+	smblib_reg_block_restore(chg, cc2_detach_settings);
+	return 0;
 }
 
 int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
 				const union power_supply_propval *val)
 {
-	int rc;
+	int rc = 0;
 
+	if (chg->pd_hard_reset == val->intval)
+		return rc;
+
+	chg->pd_hard_reset = val->intval;
 	rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
-				 EXIT_SNK_BASED_ON_CC_BIT,
-				 (val->intval) ? EXIT_SNK_BASED_ON_CC_BIT : 0);
-	if (rc < 0) {
-		smblib_err(chg, "Could not set EXIT_SNK_BASED_ON_CC rc=%d\n",
+			EXIT_SNK_BASED_ON_CC_BIT,
+			(chg->pd_hard_reset) ? EXIT_SNK_BASED_ON_CC_BIT : 0);
+	if (rc < 0)
+		smblib_err(chg, "Couldn't set EXIT_SNK_BASED_ON_CC rc=%d\n",
 				rc);
-		return rc;
-	}
 
-	vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, val->intval, 0);
-
-	if (val->intval)
-		rc = smblib_cc2_sink_removal_enter(chg);
-	else
-		rc = smblib_cc2_sink_removal_exit(chg);
-
-	if (rc < 0) {
-		smblib_err(chg, "Could not detect cc2 removal rc=%d\n", rc);
-		return rc;
-	}
+	vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER,
+							chg->pd_hard_reset, 0);
 
 	return rc;
 }
@@ -3116,25 +3074,43 @@
 	return IRQ_HANDLED;
 }
 
-#define PL_DELAY_MS			30000
-irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
+static void smblib_micro_usb_plugin(struct smb_charger *chg, bool vbus_rising)
 {
-	struct smb_irq_data *irq_data = data;
-	struct smb_charger *chg = irq_data->parent_data;
+	if (vbus_rising) {
+		/* use the typec flag even though its not typec */
+		chg->typec_present = 1;
+	} else {
+		chg->typec_present = 0;
+		smblib_update_usb_type(chg);
+		extcon_set_cable_state_(chg->extcon, EXTCON_USB, false);
+		smblib_uusb_removal(chg);
+	}
+}
+
+static void smblib_typec_usb_plugin(struct smb_charger *chg, bool vbus_rising)
+{
+	if (vbus_rising)
+		smblib_cc2_sink_removal_exit(chg);
+	else
+		smblib_cc2_sink_removal_enter(chg);
+}
+
+#define PL_DELAY_MS			30000
+void smblib_usb_plugin_locked(struct smb_charger *chg)
+{
 	int rc;
 	u8 stat;
 	bool vbus_rising;
 
 	rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
 	if (rc < 0) {
-		dev_err(chg->dev, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
-		return IRQ_HANDLED;
+		smblib_err(chg, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
+		return;
 	}
 
 	vbus_rising = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
-	smblib_set_opt_freq_buck(chg,
-		vbus_rising ? chg->chg_freq.freq_5V :
-			chg->chg_freq.freq_removal);
+	smblib_set_opt_freq_buck(chg, vbus_rising ? chg->chg_freq.freq_5V :
+						chg->chg_freq.freq_removal);
 
 	/* fetch the DPDM regulator */
 	if (!chg->dpdm_reg && of_get_property(chg->dev->of_node,
@@ -3171,17 +3147,26 @@
 				smblib_err(chg, "Couldn't disable dpdm regulator rc=%d\n",
 					rc);
 		}
-
-		if (chg->micro_usb_mode) {
-			smblib_update_usb_type(chg);
-			extcon_set_cable_state_(chg->extcon, EXTCON_USB, false);
-			smblib_uusb_removal(chg);
-		}
 	}
 
+	if (chg->micro_usb_mode)
+		smblib_micro_usb_plugin(chg, vbus_rising);
+	else
+		smblib_typec_usb_plugin(chg, vbus_rising);
+
 	power_supply_changed(chg->usb_psy);
-	smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s %s\n",
-		irq_data->name, vbus_rising ? "attached" : "detached");
+	smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n",
+					vbus_rising ? "attached" : "detached");
+}
+
+irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
+{
+	struct smb_irq_data *irq_data = data;
+	struct smb_charger *chg = irq_data->parent_data;
+
+	mutex_lock(&chg->lock);
+	smblib_usb_plugin_locked(chg);
+	mutex_unlock(&chg->lock);
 	return IRQ_HANDLED;
 }
 
@@ -3350,9 +3335,6 @@
 	if (rising) {
 		vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
 								false, 0);
-		if (get_effective_result(chg->pd_disallowed_votable_indirect))
-			/* could be a legacy cable, try doing hvdcp */
-			try_rerun_apsd_for_hvdcp(chg);
 
 		/* enable HDC and ICL irq for QC2/3 charger */
 		if (qc_charger)
@@ -3387,6 +3369,10 @@
 
 static void smblib_force_legacy_icl(struct smb_charger *chg, int pst)
 {
+	/* while PD is active it should have complete ICL control */
+	if (chg->pd_active)
+		return;
+
 	switch (pst) {
 	case POWER_SUPPLY_TYPE_USB:
 		/*
@@ -3426,7 +3412,7 @@
 
 	apsd_result = smblib_update_usb_type(chg);
 
-	if (!chg->pd_active)
+	if (!chg->typec_legacy_valid)
 		smblib_force_legacy_icl(chg, apsd_result->pst);
 
 	switch (apsd_result->bit) {
@@ -3472,6 +3458,17 @@
 	}
 	smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat);
 
+	if (chg->micro_usb_mode && (stat & APSD_DTC_STATUS_DONE_BIT)
+			&& !chg->uusb_apsd_rerun_done) {
+		/*
+		 * Force re-run APSD to handle slow insertion related
+		 * charger-mis-detection.
+		 */
+		chg->uusb_apsd_rerun_done = true;
+		smblib_rerun_apsd(chg);
+		return IRQ_HANDLED;
+	}
+
 	smblib_handle_apsd_done(chg,
 		(bool)(stat & APSD_DTC_STATUS_DONE_BIT));
 
@@ -3505,71 +3502,6 @@
 	return IRQ_HANDLED;
 }
 
-static void typec_source_removal(struct smb_charger *chg)
-{
-	int rc;
-
-	/* reset legacy unknown vote */
-	vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0);
-
-	/* reset both usbin current and voltage votes */
-	vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
-	vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
-
-	cancel_delayed_work_sync(&chg->hvdcp_detect_work);
-
-	if (chg->wa_flags & QC_AUTH_INTERRUPT_WA_BIT) {
-		/* re-enable AUTH_IRQ_EN_CFG_BIT */
-		rc = smblib_masked_write(chg,
-				USBIN_SOURCE_CHANGE_INTRPT_ENB_REG,
-				AUTH_IRQ_EN_CFG_BIT, AUTH_IRQ_EN_CFG_BIT);
-		if (rc < 0)
-			smblib_err(chg,
-				"Couldn't enable QC auth setting rc=%d\n", rc);
-	}
-
-	/* reconfigure allowed voltage for HVDCP */
-	rc = smblib_set_adapter_allowance(chg,
-			USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V);
-	if (rc < 0)
-		smblib_err(chg, "Couldn't set USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V rc=%d\n",
-			rc);
-
-	chg->voltage_min_uv = MICRO_5V;
-	chg->voltage_max_uv = MICRO_5V;
-
-	/* clear USB ICL vote for PD_VOTER */
-	rc = vote(chg->usb_icl_votable, PD_VOTER, false, 0);
-	if (rc < 0)
-		smblib_err(chg, "Couldn't un-vote PD from USB ICL rc=%d\n", rc);
-
-	/* clear USB ICL vote for USB_PSY_VOTER */
-	rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
-	if (rc < 0)
-		smblib_err(chg,
-			"Couldn't un-vote USB_PSY from USB ICL rc=%d\n", rc);
-
-	/* clear USB ICL vote for DCP_VOTER */
-	rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
-	if (rc < 0)
-		smblib_err(chg,
-			"Couldn't un-vote DCP from USB ICL rc=%d\n", rc);
-
-}
-
-static void typec_source_insertion(struct smb_charger *chg)
-{
-	/*
-	 * at any time we want LEGACY_UNKNOWN, PD, or USB_PSY to be voting for
-	 * ICL, so vote LEGACY_UNKNOWN here if none of the above three have
-	 * casted their votes
-	 */
-	if (!is_client_vote_enabled(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER)
-		&& !is_client_vote_enabled(chg->usb_icl_votable, PD_VOTER)
-		&& !is_client_vote_enabled(chg->usb_icl_votable, USB_PSY_VOTER))
-		vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 100000);
-}
-
 static void typec_sink_insertion(struct smb_charger *chg)
 {
 	/* when a sink is inserted we should not wait on hvdcp timeout to
@@ -3590,30 +3522,50 @@
 {
 	int rc;
 
-	cancel_delayed_work_sync(&chg->pl_enable_work);
-	vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0);
-	vote(chg->awake_votable, PL_DELAY_VOTER, false, 0);
+	chg->cc2_detach_wa_active = false;
 
+	/* reset APSD voters */
+	vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, false, 0);
+	vote(chg->apsd_disable_votable, PD_VOTER, false, 0);
+
+	cancel_delayed_work_sync(&chg->pl_enable_work);
+	cancel_delayed_work_sync(&chg->hvdcp_detect_work);
+
+	/* reset input current limit voters */
+	vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 100000);
+	vote(chg->usb_icl_votable, PD_VOTER, false, 0);
+	vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
+	vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
+	vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0);
+
+	/* reset hvdcp voters */
+	vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0);
+	vote(chg->hvdcp_disable_votable_indirect, PD_INACTIVE_VOTER, true, 0);
+
+	/* reset power delivery voters */
+	vote(chg->pd_allowed_votable, PD_VOTER, false, 0);
 	vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, true, 0);
 	vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0);
+
+	/* reset usb irq voters */
 	vote(chg->usb_irq_enable_votable, PD_VOTER, false, 0);
 	vote(chg->usb_irq_enable_votable, QC_VOTER, false, 0);
 
-	/* reset votes from vbus_cc_short */
-	vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER,
-			true, 0);
-	vote(chg->hvdcp_disable_votable_indirect, PD_INACTIVE_VOTER,
-			true, 0);
-	/*
-	 * cable could be removed during hard reset, remove its vote to
-	 * disable apsd
-	 */
-	vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, false, 0);
+	/* reset parallel voters */
+	vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0);
+	vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
+	vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
+	vote(chg->awake_votable, PL_DELAY_VOTER, false, 0);
 
 	chg->vconn_attempts = 0;
 	chg->otg_attempts = 0;
 	chg->pulse_cnt = 0;
 	chg->usb_icl_delta_ua = 0;
+	chg->voltage_min_uv = MICRO_5V;
+	chg->voltage_max_uv = MICRO_5V;
+	chg->pd_active = 0;
+	chg->pd_hard_reset = 0;
+	chg->typec_legacy_valid = false;
 
 	/* enable APSD CC trigger for next insertion */
 	rc = smblib_masked_write(chg, TYPE_C_CFG_REG,
@@ -3621,15 +3573,48 @@
 	if (rc < 0)
 		smblib_err(chg, "Couldn't enable APSD_START_ON_CC rc=%d\n", rc);
 
-	smblib_update_usb_type(chg);
-	typec_source_removal(chg);
+	if (chg->wa_flags & QC_AUTH_INTERRUPT_WA_BIT) {
+		/* re-enable AUTH_IRQ_EN_CFG_BIT */
+		rc = smblib_masked_write(chg,
+				USBIN_SOURCE_CHANGE_INTRPT_ENB_REG,
+				AUTH_IRQ_EN_CFG_BIT, AUTH_IRQ_EN_CFG_BIT);
+		if (rc < 0)
+			smblib_err(chg,
+				"Couldn't enable QC auth setting rc=%d\n", rc);
+	}
+
+	/* reconfigure allowed voltage for HVDCP */
+	rc = smblib_set_adapter_allowance(chg,
+			USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V);
+	if (rc < 0)
+		smblib_err(chg, "Couldn't set USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V rc=%d\n",
+			rc);
+
+	/* enable DRP */
+	rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+				 TYPEC_POWER_ROLE_CMD_MASK, 0);
+	if (rc < 0)
+		smblib_err(chg, "Couldn't enable DRP rc=%d\n", rc);
+
+	/* HW controlled CC_OUT */
+	rc = smblib_masked_write(chg, TAPER_TIMER_SEL_CFG_REG,
+							TYPEC_SPARE_CFG_BIT, 0);
+	if (rc < 0)
+		smblib_err(chg, "Couldn't enable HW cc_out rc=%d\n", rc);
+
+	/* restore crude sensor */
+	rc = smblib_write(chg, TM_IO_DTEST4_SEL, 0xA5);
+	if (rc < 0)
+		smblib_err(chg, "Couldn't restore crude sensor rc=%d\n", rc);
+
 	typec_sink_removal(chg);
+	smblib_update_usb_type(chg);
 }
 
 static void smblib_handle_typec_insertion(struct smb_charger *chg,
-		bool sink_attached, bool legacy_cable)
+							bool sink_attached)
 {
-	int rp, rc;
+	int rc;
 
 	vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, false, 0);
 
@@ -3639,59 +3624,36 @@
 		smblib_err(chg, "Couldn't disable APSD_START_ON_CC rc=%d\n",
 									rc);
 
-	if (sink_attached) {
-		typec_source_removal(chg);
+	if (sink_attached)
 		typec_sink_insertion(chg);
-	} else {
-		typec_source_insertion(chg);
+	else
 		typec_sink_removal(chg);
-	}
-
-	rp = smblib_get_prop_ufp_mode(chg);
-	if (rp == POWER_SUPPLY_TYPEC_SOURCE_HIGH
-			|| rp == POWER_SUPPLY_TYPEC_NON_COMPLIANT) {
-		smblib_dbg(chg, PR_MISC, "VBUS & CC could be shorted; keeping HVDCP disabled\n");
-		vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER,
-								true, 0);
-	} else {
-		vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER,
-								false, 0);
-	}
 }
 
 static void smblib_handle_typec_debounce_done(struct smb_charger *chg,
-			bool rising, bool sink_attached, bool legacy_cable)
+						bool rising, bool sink_attached)
 {
 	int rc;
 	union power_supply_propval pval = {0, };
 
-	if (rising)
-		smblib_handle_typec_insertion(chg, sink_attached, legacy_cable);
-	else
-		smblib_handle_typec_removal(chg);
+	if (rising) {
+		if (!chg->typec_present) {
+			chg->typec_present = true;
+			smblib_dbg(chg, PR_MISC,  "TypeC insertion\n");
+			smblib_handle_typec_insertion(chg, sink_attached);
+		}
+	} else {
+		if (chg->typec_present) {
+			chg->typec_present = false;
+			smblib_dbg(chg, PR_MISC,  "TypeC removal\n");
+			smblib_handle_typec_removal(chg);
+		}
+	}
 
 	rc = smblib_get_prop_typec_mode(chg, &pval);
 	if (rc < 0)
 		smblib_err(chg, "Couldn't get prop typec mode rc=%d\n", rc);
 
-	/*
-	 * HW BUG - after cable is removed, medium or high rd reading
-	 * falls to std. Use it for signal of typec cc detachment in
-	 * software WA.
-	 */
-	if (chg->cc2_sink_detach_flag == CC2_SINK_MEDIUM_HIGH
-		&& pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT) {
-
-		chg->cc2_sink_detach_flag = CC2_SINK_WA_DONE;
-
-		rc = smblib_masked_write(chg,
-				TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
-				EXIT_SNK_BASED_ON_CC_BIT, 0);
-		if (rc < 0)
-			smblib_err(chg, "Couldn't get prop typec mode rc=%d\n",
-				rc);
-	}
-
 	smblib_dbg(chg, PR_INTERRUPT, "IRQ: debounce-done %s; Type-C %s detected\n",
 		   rising ? "rising" : "falling",
 		   smblib_typec_mode_name[pval.intval]);
@@ -3717,50 +3679,54 @@
 	return IRQ_HANDLED;
 }
 
+static void smblib_usb_typec_change(struct smb_charger *chg)
+{
+	int rc;
+	bool debounce_done, sink_attached;
+
+	rc = smblib_multibyte_read(chg, TYPE_C_STATUS_1_REG,
+							chg->typec_status, 5);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't cache USB Type-C status rc=%d\n", rc);
+		return;
+	}
+
+	debounce_done =
+		(bool)(chg->typec_status[3] & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
+	sink_attached =
+		(bool)(chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT);
+
+	smblib_handle_typec_debounce_done(chg, debounce_done, sink_attached);
+
+	if (chg->typec_status[3] & TYPEC_VBUS_ERROR_STATUS_BIT)
+		smblib_dbg(chg, PR_INTERRUPT, "IRQ: vbus-error\n");
+
+	if (chg->typec_status[3] & TYPEC_VCONN_OVERCURR_STATUS_BIT)
+		schedule_work(&chg->vconn_oc_work);
+
+	power_supply_changed(chg->usb_psy);
+}
+
 irqreturn_t smblib_handle_usb_typec_change(int irq, void *data)
 {
 	struct smb_irq_data *irq_data = data;
 	struct smb_charger *chg = irq_data->parent_data;
-	int rc;
-	u8 stat4, stat5;
-	bool debounce_done, sink_attached, legacy_cable;
 
-	if (chg->micro_usb_mode)
-		return smblib_handle_usb_typec_change_for_uusb(chg);
-
-	/* WA - not when PD hard_reset WIP on cc2 in sink mode */
-	if (chg->cc2_sink_detach_flag == CC2_SINK_STD)
-		return IRQ_HANDLED;
-
-	rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat4);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
+	if (chg->micro_usb_mode) {
+		smblib_handle_usb_typec_change_for_uusb(chg);
 		return IRQ_HANDLED;
 	}
 
-	rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat5);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc);
+	if (chg->cc2_detach_wa_active || chg->typec_en_dis_active) {
+		smblib_dbg(chg, PR_INTERRUPT, "Ignoring since %s active\n",
+			chg->cc2_detach_wa_active ?
+			"cc2_detach_wa" : "typec_en_dis");
 		return IRQ_HANDLED;
 	}
 
-	debounce_done = (bool)(stat4 & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
-	sink_attached = (bool)(stat4 & UFP_DFP_MODE_STATUS_BIT);
-	legacy_cable = (bool)(stat5 & TYPEC_LEGACY_CABLE_STATUS_BIT);
-
-	smblib_handle_typec_debounce_done(chg,
-			debounce_done, sink_attached, legacy_cable);
-
-	if (stat4 & TYPEC_VBUS_ERROR_STATUS_BIT)
-		smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s vbus-error\n",
-			irq_data->name);
-
-	if (stat4 & TYPEC_VCONN_OVERCURR_STATUS_BIT)
-		schedule_work(&chg->vconn_oc_work);
-
-	power_supply_changed(chg->usb_psy);
-	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat4);
-	smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_5 = 0x%02x\n", stat5);
+	mutex_lock(&chg->lock);
+	smblib_usb_typec_change(chg);
+	mutex_unlock(&chg->lock);
 	return IRQ_HANDLED;
 }
 
@@ -3788,7 +3754,7 @@
 {
 	struct smb_irq_data *irq_data = data;
 	struct smb_charger *chg = irq_data->parent_data;
-	int rc;
+	int rc, usb_icl;
 	u8 stat;
 
 	if (!(chg->wa_flags & BOOST_BACK_WA))
@@ -3800,8 +3766,9 @@
 		return IRQ_HANDLED;
 	}
 
-	if ((stat & USE_USBIN_BIT) &&
-			get_effective_result(chg->usb_icl_votable) < USBIN_25MA)
+	/* skip suspending input if its already suspended by some other voter */
+	usb_icl = get_effective_result(chg->usb_icl_votable);
+	if ((stat & USE_USBIN_BIT) && usb_icl >= 0 && usb_icl < USBIN_25MA)
 		return IRQ_HANDLED;
 
 	if (stat & USE_DCIN_BIT)
@@ -3839,12 +3806,7 @@
 
 	vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
 				false, 0);
-	if (get_effective_result(chg->pd_disallowed_votable_indirect))
-		/* pd is still disabled, try hvdcp */
-		try_rerun_apsd_for_hvdcp(chg);
-	else
-		/* notify pd now that pd is allowed */
-		power_supply_changed(chg->usb_psy);
+	power_supply_changed(chg->usb_psy);
 }
 
 static void bms_update_work(struct work_struct *work)
@@ -3885,11 +3847,13 @@
 static void rdstd_cc2_detach_work(struct work_struct *work)
 {
 	int rc;
-	u8 stat;
-	struct smb_irq_data irq_data = {NULL, "cc2-removal-workaround"};
+	u8 stat4, stat5;
 	struct smb_charger *chg = container_of(work, struct smb_charger,
 						rdstd_cc2_detach_work);
 
+	if (!chg->cc2_detach_wa_active)
+		return;
+
 	/*
 	 * WA steps -
 	 * 1. Enable both UFP and DFP, wait for 10ms.
@@ -3897,7 +3861,7 @@
 	 * 3. Removal detected if both TYPEC_DEBOUNCE_DONE_STATUS
 	 *    and TIMER_STAGE bits are gone, otherwise repeat all by
 	 *    work rescheduling.
-	 * Note, work will be cancelled when pd_hard_reset is 0.
+	 * Note, work will be cancelled when USB_PLUGIN rises.
 	 */
 
 	rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
@@ -3920,30 +3884,35 @@
 
 	usleep_range(30000, 31000);
 
-	rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
+	rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat4);
 	if (rc < 0) {
-		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n",
-			rc);
+		smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
 		return;
 	}
-	if (stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT)
-		goto rerun;
 
-	rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat);
+	rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat5);
 	if (rc < 0) {
 		smblib_err(chg,
 			"Couldn't read TYPE_C_STATUS_5_REG rc=%d\n", rc);
 		return;
 	}
-	if (stat & TIMER_STAGE_2_BIT)
+
+	if ((stat4 & TYPEC_DEBOUNCE_DONE_STATUS_BIT)
+			|| (stat5 & TIMER_STAGE_2_BIT)) {
+		smblib_dbg(chg, PR_MISC, "rerunning DD=%d TS2BIT=%d\n",
+				(int)(stat4 & TYPEC_DEBOUNCE_DONE_STATUS_BIT),
+				(int)(stat5 & TIMER_STAGE_2_BIT));
 		goto rerun;
+	}
 
-	/* Bingo, cc2 removal detected */
+	smblib_dbg(chg, PR_MISC, "Bingo CC2 Removal detected\n");
+	chg->cc2_detach_wa_active = false;
+	rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+						EXIT_SNK_BASED_ON_CC_BIT, 0);
 	smblib_reg_block_restore(chg, cc2_detach_settings);
-	chg->cc2_sink_detach_flag = CC2_SINK_WA_DONE;
-	irq_data.parent_data = chg;
-	smblib_handle_usb_typec_change(0, &irq_data);
-
+	mutex_lock(&chg->lock);
+	smblib_usb_typec_change(chg);
+	mutex_unlock(&chg->lock);
 	return;
 
 rerun:
@@ -4166,6 +4135,56 @@
 	vote(chg->awake_votable, PL_DELAY_VOTER, false, 0);
 }
 
+static void smblib_legacy_detection_work(struct work_struct *work)
+{
+	struct smb_charger *chg = container_of(work, struct smb_charger,
+							legacy_detection_work);
+	int rc;
+	u8 stat;
+	bool legacy, rp_high;
+
+	mutex_lock(&chg->lock);
+	chg->typec_en_dis_active = 1;
+	smblib_dbg(chg, PR_MISC, "running legacy unknown workaround\n");
+	rc = smblib_masked_write(chg,
+				TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+				TYPEC_DISABLE_CMD_BIT,
+				TYPEC_DISABLE_CMD_BIT);
+	if (rc < 0)
+		smblib_err(chg, "Couldn't disable type-c rc=%d\n", rc);
+
+	/* wait for the adapter to turn off VBUS */
+	msleep(500);
+
+	rc = smblib_masked_write(chg,
+				TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+				TYPEC_DISABLE_CMD_BIT, 0);
+	if (rc < 0)
+		smblib_err(chg, "Couldn't enable type-c rc=%d\n", rc);
+
+	/* wait for type-c detection to complete */
+	msleep(100);
+
+	rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read typec stat5 rc = %d\n", rc);
+		goto unlock;
+	}
+
+	chg->typec_legacy_valid = true;
+	vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0);
+	legacy = stat & TYPEC_LEGACY_CABLE_STATUS_BIT;
+	rp_high = smblib_get_prop_ufp_mode(chg) ==
+						POWER_SUPPLY_TYPEC_SOURCE_HIGH;
+	if (!legacy || !rp_high)
+		vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER,
+								false, 0);
+
+unlock:
+	chg->typec_en_dis_active = 0;
+	mutex_unlock(&chg->lock);
+}
+
 static int smblib_create_votables(struct smb_charger *chg)
 {
 	int rc = 0;
@@ -4298,6 +4317,15 @@
 		return rc;
 	}
 
+	chg->typec_irq_disable_votable = create_votable("TYPEC_IRQ_DISABLE",
+					VOTE_SET_ANY,
+					smblib_typec_irq_disable_vote_callback,
+					chg);
+	if (IS_ERR(chg->typec_irq_disable_votable)) {
+		rc = PTR_ERR(chg->typec_irq_disable_votable);
+		return rc;
+	}
+
 	return rc;
 }
 
@@ -4323,6 +4351,8 @@
 		destroy_votable(chg->apsd_disable_votable);
 	if (chg->hvdcp_hw_inov_dis_votable)
 		destroy_votable(chg->hvdcp_hw_inov_dis_votable);
+	if (chg->typec_irq_disable_votable)
+		destroy_votable(chg->typec_irq_disable_votable);
 }
 
 static void smblib_iio_deinit(struct smb_charger *chg)
@@ -4343,6 +4373,7 @@
 {
 	int rc = 0;
 
+	mutex_init(&chg->lock);
 	mutex_init(&chg->write_lock);
 	mutex_init(&chg->otg_oc_lock);
 	INIT_WORK(&chg->bms_update_work, bms_update_work);
@@ -4355,6 +4386,7 @@
 	INIT_DELAYED_WORK(&chg->otg_ss_done_work, smblib_otg_ss_done_work);
 	INIT_DELAYED_WORK(&chg->icl_change_work, smblib_icl_change_work);
 	INIT_DELAYED_WORK(&chg->pl_enable_work, smblib_pl_enable_work);
+	INIT_WORK(&chg->legacy_detection_work, smblib_legacy_detection_work);
 	chg->fake_capacity = -EINVAL;
 
 	switch (chg->mode) {
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 49b9d3d..b0d84f0 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -61,6 +61,7 @@
 #define SW_QC3_VOTER			"SW_QC3_VOTER"
 #define AICL_RERUN_VOTER		"AICL_RERUN_VOTER"
 #define LEGACY_UNKNOWN_VOTER		"LEGACY_UNKNOWN_VOTER"
+#define CC2_WA_VOTER			"CC2_WA_VOTER"
 
 #define VCONN_MAX_ATTEMPTS	3
 #define OTG_MAX_ATTEMPTS	3
@@ -71,13 +72,6 @@
 	NUM_MODES,
 };
 
-enum cc2_sink_type {
-	CC2_SINK_NONE = 0,
-	CC2_SINK_STD,
-	CC2_SINK_MEDIUM_HIGH,
-	CC2_SINK_WA_DONE,
-};
-
 enum {
 	QC_CHARGER_DETECTION_WA_BIT	= BIT(0),
 	BOOST_BACK_WA			= BIT(1),
@@ -236,6 +230,7 @@
 	int			smb_version;
 
 	/* locks */
+	struct mutex		lock;
 	struct mutex		write_lock;
 	struct mutex		ps_change_lock;
 	struct mutex		otg_oc_lock;
@@ -276,6 +271,7 @@
 	struct votable		*apsd_disable_votable;
 	struct votable		*hvdcp_hw_inov_dis_votable;
 	struct votable		*usb_irq_enable_votable;
+	struct votable		*typec_irq_disable_votable;
 
 	/* work */
 	struct work_struct	bms_update_work;
@@ -289,6 +285,7 @@
 	struct delayed_work	otg_ss_done_work;
 	struct delayed_work	icl_change_work;
 	struct delayed_work	pl_enable_work;
+	struct work_struct	legacy_detection_work;
 
 	/* cached status */
 	int			voltage_min_uv;
@@ -312,10 +309,16 @@
 	int			vconn_attempts;
 	int			default_icl_ua;
 	int			otg_cl_ua;
+	bool			uusb_apsd_rerun_done;
+	bool			pd_hard_reset;
+	bool			typec_present;
+	u8			typec_status[5];
+	bool			typec_legacy_valid;
 
 	/* workaround flag */
 	u32			wa_flags;
-	enum cc2_sink_type	cc2_sink_detach_flag;
+	bool			cc2_detach_wa_active;
+	bool			typec_en_dis_active;
 	int			boost_current_ua;
 	int			temp_speed_reading_count;
 
diff --git a/drivers/power/supply/qcom/smb-reg.h b/drivers/power/supply/qcom/smb-reg.h
index 167666a..3f260a4 100644
--- a/drivers/power/supply/qcom/smb-reg.h
+++ b/drivers/power/supply/qcom/smb-reg.h
@@ -1025,4 +1025,14 @@
 /* CHGR FREQ Peripheral registers */
 #define FREQ_CLK_DIV_REG			(CHGR_FREQ_BASE + 0x50)
 
+/* SMB1355 specific registers */
+#define SMB1355_TEMP_COMP_STATUS_REG		(MISC_BASE + 0x07)
+#define SKIN_TEMP_RST_HOT_BIT			BIT(6)
+#define SKIN_TEMP_UB_HOT_BIT			BIT(5)
+#define SKIN_TEMP_LB_HOT_BIT			BIT(4)
+#define DIE_TEMP_TSD_HOT_BIT			BIT(3)
+#define DIE_TEMP_RST_HOT_BIT			BIT(2)
+#define DIE_TEMP_UB_HOT_BIT			BIT(1)
+#define DIE_TEMP_LB_HOT_BIT			BIT(0)
+
 #endif /* __SMB2_CHARGER_REG_H */
diff --git a/drivers/power/supply/qcom/smb1351-charger.c b/drivers/power/supply/qcom/smb1351-charger.c
index 0d1f2a6..b92a482 100644
--- a/drivers/power/supply/qcom/smb1351-charger.c
+++ b/drivers/power/supply/qcom/smb1351-charger.c
@@ -1655,7 +1655,7 @@
 
 	switch (prop) {
 	case POWER_SUPPLY_PROP_CHARGING_ENABLED:
-		val->intval = !chip->usb_suspended_status;
+		val->intval = !chip->parallel_charger_suspended;
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
 		if (!chip->parallel_charger_suspended)
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index 83374bb..a29871b 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -104,6 +104,8 @@
 	struct smb_dt_props	dt;
 	struct power_supply	*parallel_psy;
 	u32			wa_flags;
+	struct pmic_revid_data	*pmic_rev_id;
+	char			*name;
 };
 
 static int __debug_mask;
@@ -167,6 +169,14 @@
 	if (rc < 0)
 		chip->dt.pl_mode = POWER_SUPPLY_PL_USBMID_USBMID;
 
+	/* check that smb1355 is configured to run in mid-mid mode */
+	if (chip->pmic_rev_id->pmic_subtype == SMB1355_SUBTYPE
+		&& chip->dt.pl_mode != POWER_SUPPLY_PL_USBMID_USBMID) {
+		pr_err("Smb1355 can only run in MID-MID mode, saw = %d mode\n",
+				chip->dt.pl_mode);
+		return -EINVAL;
+	}
+
 	chip->dt.suspend_input = of_property_read_bool(node,
 				"qcom,suspend-input");
 
@@ -479,6 +489,30 @@
  * PARALLEL PSY REGISTRATION *
  *****************************/
 
+static int smb1355_get_prop_connector_health(struct smb138x *chip)
+{
+	struct smb_charger *chg = &chip->chg;
+	u8 temp;
+	int rc;
+
+	rc = smblib_read(chg, SMB1355_TEMP_COMP_STATUS_REG, &temp);
+	if (rc < 0) {
+		pr_err("Couldn't read comp stat reg rc = %d\n", rc);
+		return POWER_SUPPLY_HEALTH_UNKNOWN;
+	}
+
+	if (temp & SKIN_TEMP_RST_HOT_BIT)
+		return POWER_SUPPLY_HEALTH_OVERHEAT;
+
+	if (temp & SKIN_TEMP_UB_HOT_BIT)
+		return POWER_SUPPLY_HEALTH_HOT;
+
+	if (temp & SKIN_TEMP_LB_HOT_BIT)
+		return POWER_SUPPLY_HEALTH_WARM;
+
+	return POWER_SUPPLY_HEALTH_COOL;
+}
+
 static int smb138x_get_prop_connector_health(struct smb138x *chip)
 {
 	struct smb_charger *chg = &chip->chg;
@@ -536,16 +570,32 @@
 	POWER_SUPPLY_PROP_PIN_ENABLED,
 	POWER_SUPPLY_PROP_INPUT_SUSPEND,
 	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
-	POWER_SUPPLY_PROP_CURRENT_MAX,
 	POWER_SUPPLY_PROP_VOLTAGE_MAX,
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
-	POWER_SUPPLY_PROP_CURRENT_NOW,
-	POWER_SUPPLY_PROP_CHARGER_TEMP,
-	POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
 	POWER_SUPPLY_PROP_MODEL_NAME,
 	POWER_SUPPLY_PROP_PARALLEL_MODE,
 	POWER_SUPPLY_PROP_CONNECTOR_HEALTH,
 	POWER_SUPPLY_PROP_SET_SHIP_MODE,
+	POWER_SUPPLY_PROP_CHARGER_TEMP,
+	POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CURRENT_MAX,
+};
+
+static enum power_supply_property smb1355_parallel_props[] = {
+	POWER_SUPPLY_PROP_CHARGE_TYPE,
+	POWER_SUPPLY_PROP_CHARGING_ENABLED,
+	POWER_SUPPLY_PROP_PIN_ENABLED,
+	POWER_SUPPLY_PROP_INPUT_SUSPEND,
+	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX,
+	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+	POWER_SUPPLY_PROP_MODEL_NAME,
+	POWER_SUPPLY_PROP_PARALLEL_MODE,
+	POWER_SUPPLY_PROP_CONNECTOR_HEALTH,
+	POWER_SUPPLY_PROP_SET_SHIP_MODE,
+	POWER_SUPPLY_PROP_CHARGER_TEMP,
+	POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
 };
 
 static int smb138x_parallel_get_prop(struct power_supply *psy,
@@ -583,14 +633,6 @@
 		else
 			val->intval = 0;
 		break;
-	case POWER_SUPPLY_PROP_CURRENT_MAX:
-		if ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
-		|| (chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT))
-			rc = smblib_get_charge_param(chg, &chg->param.usb_icl,
-				&val->intval);
-		else
-			val->intval = 0;
-		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
 		rc = smblib_get_charge_param(chg, &chg->param.fv, &val->intval);
 		break;
@@ -598,28 +640,46 @@
 		rc = smblib_get_charge_param(chg, &chg->param.fcc,
 					     &val->intval);
 		break;
-	case POWER_SUPPLY_PROP_CURRENT_NOW:
-		rc = smblib_get_prop_slave_current_now(chg, val);
-		break;
-	case POWER_SUPPLY_PROP_CHARGER_TEMP:
-		rc = smb138x_get_prop_charger_temp(chip, val);
-		break;
-	case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
-		rc = smblib_get_prop_charger_temp_max(chg, val);
-		break;
 	case POWER_SUPPLY_PROP_MODEL_NAME:
-		val->strval = "smb138x";
+		val->strval = chip->name;
 		break;
 	case POWER_SUPPLY_PROP_PARALLEL_MODE:
 		val->intval = chip->dt.pl_mode;
 		break;
 	case POWER_SUPPLY_PROP_CONNECTOR_HEALTH:
-		val->intval = smb138x_get_prop_connector_health(chip);
+		if (chip->pmic_rev_id->pmic_subtype != SMB1355_SUBTYPE)
+			val->intval = smb138x_get_prop_connector_health(chip);
+		else
+			val->intval = smb1355_get_prop_connector_health(chip);
 		break;
 	case POWER_SUPPLY_PROP_SET_SHIP_MODE:
 		/* Not in ship mode as long as device is active */
 		val->intval = 0;
 		break;
+	case POWER_SUPPLY_PROP_CHARGER_TEMP:
+		if (chip->pmic_rev_id->pmic_subtype != SMB1355_SUBTYPE)
+			rc = smb138x_get_prop_charger_temp(chip, val);
+		else
+			rc = smblib_get_prop_charger_temp(chg, val);
+		break;
+	case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
+		rc = smblib_get_prop_charger_temp_max(chg, val);
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		if (chip->pmic_rev_id->pmic_subtype != SMB1355_SUBTYPE)
+			rc = smblib_get_prop_slave_current_now(chg, val);
+		else
+			rc = -ENODATA;
+		break;
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		if ((chip->pmic_rev_id->pmic_subtype != SMB1355_SUBTYPE)
+		  && ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
+		  || (chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN_EXT)))
+			rc = smblib_get_charge_param(chg, &chg->param.usb_icl,
+				&val->intval);
+		else
+			rc = -ENODATA;
+		break;
 	default:
 		pr_err("parallel power supply get prop %d not supported\n",
 			prop);
@@ -703,7 +763,7 @@
 	return 0;
 }
 
-static const struct power_supply_desc parallel_psy_desc = {
+static struct power_supply_desc parallel_psy_desc = {
 	.name			= "parallel",
 	.type			= POWER_SUPPLY_TYPE_PARALLEL,
 	.properties		= smb138x_parallel_props,
@@ -731,6 +791,28 @@
 	return 0;
 }
 
+static int smb1355_init_parallel_psy(struct smb138x *chip)
+{
+	struct power_supply_config parallel_cfg = {};
+	struct smb_charger *chg = &chip->chg;
+
+	parallel_cfg.drv_data = chip;
+	parallel_cfg.of_node = chg->dev->of_node;
+
+	/* change to smb1355's property list */
+	parallel_psy_desc.properties = smb1355_parallel_props;
+	parallel_psy_desc.num_properties = ARRAY_SIZE(smb1355_parallel_props);
+	chip->parallel_psy = devm_power_supply_register(chg->dev,
+						   &parallel_psy_desc,
+						   &parallel_cfg);
+	if (IS_ERR(chip->parallel_psy)) {
+		pr_err("Couldn't register parallel power supply\n");
+		return PTR_ERR(chip->parallel_psy);
+	}
+
+	return 0;
+}
+
 /******************************
  * VBUS REGULATOR REGISTRATION *
  ******************************/
@@ -1050,7 +1132,6 @@
 
 static int smb138x_setup_wa_flags(struct smb138x *chip)
 {
-	struct pmic_revid_data *pmic_rev_id;
 	struct device_node *revid_dev_node;
 
 	revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
@@ -1060,8 +1141,8 @@
 		return -EINVAL;
 	}
 
-	pmic_rev_id = get_revid_data(revid_dev_node);
-	if (IS_ERR_OR_NULL(pmic_rev_id)) {
+	chip->pmic_rev_id = get_revid_data(revid_dev_node);
+	if (IS_ERR_OR_NULL(chip->pmic_rev_id)) {
 		/*
 		 * the revid peripheral must be registered, any failure
 		 * here only indicates that the rev-id module has not
@@ -1070,14 +1151,14 @@
 		return -EPROBE_DEFER;
 	}
 
-	switch (pmic_rev_id->pmic_subtype) {
+	switch (chip->pmic_rev_id->pmic_subtype) {
 	case SMB1381_SUBTYPE:
-		if (pmic_rev_id->rev4 < 2) /* SMB1381 rev 1.0 */
+		if (chip->pmic_rev_id->rev4 < 2) /* SMB1381 rev 1.0 */
 			chip->wa_flags |= OOB_COMP_WA_BIT;
 		break;
 	default:
 		pr_err("PMIC subtype %d not supported\n",
-				pmic_rev_id->pmic_subtype);
+				chip->pmic_rev_id->pmic_subtype);
 		return -EINVAL;
 	}
 
@@ -1375,6 +1456,7 @@
 
 	chg->param = v1_params;
 
+	chip->name = "smb1381";
 	rc = smblib_init(chg);
 	if (rc < 0) {
 		pr_err("Couldn't initialize smblib rc=%d\n", rc);
@@ -1435,7 +1517,7 @@
 	return rc;
 }
 
-static int smb138x_slave_probe(struct smb138x *chip)
+static int smb1355_slave_probe(struct smb138x *chip)
 {
 	struct smb_charger *chg = &chip->chg;
 	int rc = 0;
@@ -1448,6 +1530,55 @@
 		goto cleanup;
 	}
 
+	rc = smb138x_parse_dt(chip);
+	if (rc < 0) {
+		pr_err("Couldn't parse device tree rc=%d\n", rc);
+		goto cleanup;
+	}
+
+	rc = smb138x_init_slave_hw(chip);
+	if (rc < 0) {
+		pr_err("Couldn't initialize hardware rc=%d\n", rc);
+		goto cleanup;
+	}
+
+	rc = smb1355_init_parallel_psy(chip);
+	if (rc < 0) {
+		pr_err("Couldn't initialize parallel psy rc=%d\n", rc);
+		goto cleanup;
+	}
+
+	rc = smb138x_determine_initial_slave_status(chip);
+	if (rc < 0) {
+		pr_err("Couldn't determine initial status rc=%d\n", rc);
+		goto cleanup;
+	}
+
+	rc = smb138x_request_interrupts(chip);
+	if (rc < 0) {
+		pr_err("Couldn't request interrupts rc=%d\n", rc);
+		goto cleanup;
+	}
+
+	return 0;
+
+cleanup:
+	smblib_deinit(chg);
+	return rc;
+}
+
+static int smb1381_slave_probe(struct smb138x *chip)
+{
+	struct smb_charger *chg = &chip->chg;
+	int rc = 0;
+
+	chg->param = v1_params;
+
+	rc = smblib_init(chg);
+	if (rc < 0) {
+		pr_err("Couldn't initialize smblib rc=%d\n", rc);
+		goto cleanup;
+	}
 	chg->iio.temp_max_chan = iio_channel_get(chg->dev, "charger_temp_max");
 	if (IS_ERR(chg->iio.temp_max_chan)) {
 		rc = PTR_ERR(chg->iio.temp_max_chan);
@@ -1515,25 +1646,71 @@
 		goto cleanup;
 	}
 
-	return rc;
+	return 0;
 
 cleanup:
 	smblib_deinit(chg);
-	if (chip->parallel_psy)
-		power_supply_unregister(chip->parallel_psy);
-	if (chg->vbus_vreg && chg->vbus_vreg->rdev)
-		regulator_unregister(chg->vbus_vreg->rdev);
 	return rc;
 }
 
+static int slave_probe(struct smb138x *chip)
+{
+	struct device_node *revid_dev_node;
+	int rc = 0;
+
+	revid_dev_node = of_parse_phandle(chip->chg.dev->of_node,
+					"qcom,pmic-revid", 0);
+	if (!revid_dev_node) {
+		pr_err("Missing qcom,pmic-revid property\n");
+		return -EINVAL;
+	}
+
+	chip->pmic_rev_id = get_revid_data(revid_dev_node);
+	if (IS_ERR_OR_NULL(chip->pmic_rev_id)) {
+		/*
+		 * the revid peripheral must be registered, any failure
+		 * here only indicates that the rev-id module has not
+		 * probed yet.
+		 */
+		return -EPROBE_DEFER;
+	}
+
+	switch (chip->pmic_rev_id->pmic_subtype) {
+	case SMB1355_SUBTYPE:
+		chip->name = "smb1355";
+		rc = smb1355_slave_probe(chip);
+		break;
+	case SMB1381_SUBTYPE:
+		chip->name = "smb1381";
+		rc = smb1381_slave_probe(chip);
+		break;
+	default:
+		pr_err("Unsupported pmic subtype = 0x%02x\n",
+				chip->pmic_rev_id->pmic_subtype);
+		rc = -EINVAL;
+	}
+
+	if (rc < 0) {
+		if (rc != -EPROBE_DEFER)
+			pr_err("Couldn't probe SMB138X rc=%d\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
+
 static const struct of_device_id match_table[] = {
 	{
-		.compatible = "qcom,smb138x-charger",
-		.data = (void *) PARALLEL_MASTER
+		.compatible	= "qcom,smb138x-charger",
+		.data		= (void *) PARALLEL_MASTER,
 	},
 	{
-		.compatible = "qcom,smb138x-parallel-slave",
-		.data = (void *) PARALLEL_SLAVE
+		.compatible	= "qcom,smb138x-parallel-slave",
+		.data		= (void *) PARALLEL_SLAVE,
+	},
+	{
+		.compatible	= "qcom,smb1355-parallel-slave",
+		.data		= (void *) PARALLEL_SLAVE,
 	},
 	{ },
 };
@@ -1580,7 +1757,7 @@
 		rc = smb138x_master_probe(chip);
 		break;
 	case PARALLEL_SLAVE:
-		rc = smb138x_slave_probe(chip);
+		rc = slave_probe(chip);
 		break;
 	default:
 		pr_err("Couldn't find a matching mode %d\n", chip->chg.mode);
@@ -1594,7 +1771,8 @@
 		goto cleanup;
 	}
 
-	pr_info("SMB138X probed successfully mode=%d\n", chip->chg.mode);
+	pr_info("%s probed successfully mode=%d pl_mode = %d\n",
+		chip->name, chip->chg.mode, chip->dt.pl_mode);
 	return rc;
 
 cleanup:
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 1635bab..b3c1150 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -108,7 +108,7 @@
 	struct rpmh_msg *rpm_msg = container_of(msg, struct rpmh_msg, msg);
 
 	atomic_dec(rpm_msg->wait_count);
-	wake_up_interruptible(rpm_msg->waitq);
+	wake_up(rpm_msg->waitq);
 }
 
 static void rpmh_tx_done(struct mbox_client *cl, void *msg, int r)
@@ -151,7 +151,7 @@
 	/* Signal the blocking thread we are done */
 	if (waitq) {
 		atomic_dec(wc);
-		wake_up_interruptible(waitq);
+		wake_up(waitq);
 	}
 }
 
@@ -329,9 +329,7 @@
 	if (ret < 0)
 		return ret;
 
-	ret = wait_event_interruptible(waitq, atomic_read(&wait_count) == 0);
-	if (ret)
-		return ret;
+	wait_event(waitq, atomic_read(&wait_count) == 0);
 
 	return rpm_msg.err;
 }
@@ -423,13 +421,11 @@
 	rpm_msg.msg.num_payload = n;
 
 	ret = __rpmh_write(rc, state, &rpm_msg);
-	if (ret < 0)
-		return ret;
-
-	ret = wait_event_interruptible(waitq, atomic_read(&wait_count) == 0);
 	if (ret)
 		return ret;
 
+	wait_event(waitq, atomic_read(&wait_count) == 0);
+
 	return rpm_msg.err;
 }
 EXPORT_SYMBOL(rpmh_write);
@@ -494,8 +490,6 @@
 		rpm_msg[i] = __get_rpmh_msg_async(rc, state, cmd, n[i]);
 		if (IS_ERR_OR_NULL(rpm_msg[i]))
 			return PTR_ERR(rpm_msg[i]);
-		rpm_msg[i]->waitq = &waitq;
-		rpm_msg[i]->wait_count = &wait_count;
 		cmd += n[i];
 	}
 
@@ -504,16 +498,18 @@
 		might_sleep();
 		atomic_set(&wait_count, count);
 		for (i = 0; i < count; i++) {
+			rpm_msg[i]->waitq = &waitq;
+			rpm_msg[i]->wait_count = &wait_count;
 			/* Bypass caching and write to mailbox directly */
 			ret = mbox_send_message(rc->chan, &rpm_msg[i]->msg);
 			if (ret < 0)
 				return ret;
 		}
-		return wait_event_interruptible(waitq,
-					atomic_read(&wait_count) == 0);
+		wait_event(waitq, atomic_read(&wait_count) == 0);
 	} else {
 		/* Send Sleep requests to the controller, expect no response */
 		for (i = 0; i < count; i++) {
+			rpm_msg[i]->waitq = NULL;
 			ret = mbox_send_controller_data(rc->chan,
 						&rpm_msg[i]->msg);
 			/* Clean up our call by spoofing tx_done */
@@ -521,6 +517,8 @@
 		}
 		return 0;
 	}
+
+	return 0;
 }
 EXPORT_SYMBOL(rpmh_write_passthru);
 
@@ -623,9 +621,7 @@
 		return ret;
 
 	/* Wait until the response is received from RPMH */
-	ret = wait_event_interruptible(waitq, atomic_read(&wait_count) == 0);
-	if (ret)
-		return ret;
+	wait_event(waitq, atomic_read(&wait_count) == 0);
 
 	/* Read the data back from the tcs_mbox_msg structrure */
 	*resp = rpm_msg.cmd[0].data;
diff --git a/drivers/soc/qcom/watchdog_v2.c b/drivers/soc/qcom/watchdog_v2.c
index f3d6209..7a784aa 100644
--- a/drivers/soc/qcom/watchdog_v2.c
+++ b/drivers/soc/qcom/watchdog_v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -30,6 +30,7 @@
 #include <soc/qcom/scm.h>
 #include <soc/qcom/memory_dump.h>
 #include <soc/qcom/watchdog.h>
+#include <linux/dma-mapping.h>
 
 #define MODULE_NAME "msm_watchdog"
 #define WDT0_ACCSCSSNBARK_INT 0
@@ -49,6 +50,7 @@
 #define SCM_SET_REGSAVE_CMD	0x2
 #define SCM_SVC_SEC_WDOG_DIS	0x7
 #define MAX_CPU_CTX_SIZE	2048
+#define MAX_CPU_SCANDUMP_SIZE	0x10000
 
 static struct msm_watchdog_data *wdog_data;
 
@@ -557,6 +559,49 @@
 	return;
 }
 
+static void configure_scandump(struct msm_watchdog_data *wdog_dd)
+{
+	int ret;
+	struct msm_dump_entry dump_entry;
+	struct msm_dump_data *cpu_data;
+	int cpu;
+	static dma_addr_t dump_addr;
+	static void *dump_vaddr;
+
+	for_each_cpu(cpu, cpu_present_mask) {
+		cpu_data = devm_kzalloc(wdog_dd->dev,
+					sizeof(struct msm_dump_data),
+					GFP_KERNEL);
+		if (!cpu_data)
+			continue;
+
+		dump_vaddr = (void *) dma_alloc_coherent(wdog_dd->dev,
+							 MAX_CPU_SCANDUMP_SIZE,
+							 &dump_addr,
+							 GFP_KERNEL);
+		if (!dump_vaddr) {
+			dev_err(wdog_dd->dev, "Couldn't get memory for dump\n");
+			continue;
+		}
+		memset(dump_vaddr, 0x0, MAX_CPU_SCANDUMP_SIZE);
+
+		cpu_data->addr = dump_addr;
+		cpu_data->len = MAX_CPU_SCANDUMP_SIZE;
+		dump_entry.id = MSM_DUMP_DATA_SCANDUMP_PER_CPU + cpu;
+		dump_entry.addr = virt_to_phys(cpu_data);
+		ret = msm_dump_data_register(MSM_DUMP_TABLE_APPS,
+					     &dump_entry);
+		if (ret) {
+			dev_err(wdog_dd->dev, "Dump setup failed, id = %d\n",
+				MSM_DUMP_DATA_SCANDUMP_PER_CPU + cpu);
+			dma_free_coherent(wdog_dd->dev, MAX_CPU_SCANDUMP_SIZE,
+					  dump_vaddr,
+					  dump_addr);
+			devm_kfree(wdog_dd->dev, cpu_data);
+		}
+	}
+}
+
 static int init_watchdog_sysfs(struct msm_watchdog_data *wdog_dd)
 {
 	int error = 0;
@@ -617,6 +662,7 @@
 	delay_time = msecs_to_jiffies(wdog_dd->pet_time);
 	wdog_dd->min_slack_ticks = UINT_MAX;
 	wdog_dd->min_slack_ns = ULLONG_MAX;
+	configure_scandump(wdog_dd);
 	configure_bark_dump(wdog_dd);
 	timeout = (wdog_dd->bark_time * WDT_HZ)/1000;
 	__raw_writel(timeout, wdog_dd->base + WDT0_BARK_TIME);
diff --git a/include/dt-bindings/clock/qcom,camcc-sdm845.h b/include/dt-bindings/clock/qcom,camcc-sdm845.h
index e169172..0d9d9f6 100644
--- a/include/dt-bindings/clock/qcom,camcc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,camcc-sdm845.h
@@ -34,71 +34,70 @@
 #define CAM_CC_CSIPHY0_CLK					17
 #define CAM_CC_CSIPHY1_CLK					18
 #define CAM_CC_CSIPHY2_CLK					19
-#define CAM_CC_DEBUG_CLK					20
-#define CAM_CC_FAST_AHB_CLK_SRC					21
-#define CAM_CC_FD_CORE_CLK					22
-#define CAM_CC_FD_CORE_CLK_SRC					23
-#define CAM_CC_FD_CORE_UAR_CLK					24
-#define CAM_CC_ICP_APB_CLK					25
-#define CAM_CC_ICP_ATB_CLK					26
-#define CAM_CC_ICP_CLK						27
-#define CAM_CC_ICP_CLK_SRC					28
-#define CAM_CC_ICP_CTI_CLK					29
-#define CAM_CC_ICP_TS_CLK					30
-#define CAM_CC_IFE_0_AXI_CLK					31
-#define CAM_CC_IFE_0_CLK					32
-#define CAM_CC_IFE_0_CLK_SRC					33
-#define CAM_CC_IFE_0_CPHY_RX_CLK				34
-#define CAM_CC_IFE_0_CSID_CLK					35
-#define CAM_CC_IFE_0_CSID_CLK_SRC				36
-#define CAM_CC_IFE_0_DSP_CLK					37
-#define CAM_CC_IFE_1_AXI_CLK					38
-#define CAM_CC_IFE_1_CLK					39
-#define CAM_CC_IFE_1_CLK_SRC					40
-#define CAM_CC_IFE_1_CPHY_RX_CLK				41
-#define CAM_CC_IFE_1_CSID_CLK					42
-#define CAM_CC_IFE_1_CSID_CLK_SRC				43
-#define CAM_CC_IFE_1_DSP_CLK					44
-#define CAM_CC_IFE_LITE_CLK					45
-#define CAM_CC_IFE_LITE_CLK_SRC					46
-#define CAM_CC_IFE_LITE_CPHY_RX_CLK				47
-#define CAM_CC_IFE_LITE_CSID_CLK				48
-#define CAM_CC_IFE_LITE_CSID_CLK_SRC				49
-#define CAM_CC_IPE_0_AHB_CLK					50
-#define CAM_CC_IPE_0_AREG_CLK					51
-#define CAM_CC_IPE_0_AXI_CLK					52
-#define CAM_CC_IPE_0_CLK					53
-#define CAM_CC_IPE_0_CLK_SRC					54
-#define CAM_CC_IPE_1_AHB_CLK					55
-#define CAM_CC_IPE_1_AREG_CLK					56
-#define CAM_CC_IPE_1_AXI_CLK					57
-#define CAM_CC_IPE_1_CLK					58
-#define CAM_CC_IPE_1_CLK_SRC					59
-#define CAM_CC_JPEG_CLK						60
-#define CAM_CC_JPEG_CLK_SRC					61
-#define CAM_CC_LRME_CLK						62
-#define CAM_CC_LRME_CLK_SRC					63
-#define CAM_CC_MCLK0_CLK					64
-#define CAM_CC_MCLK0_CLK_SRC					65
-#define CAM_CC_MCLK1_CLK					66
-#define CAM_CC_MCLK1_CLK_SRC					67
-#define CAM_CC_MCLK2_CLK					68
-#define CAM_CC_MCLK2_CLK_SRC					69
-#define CAM_CC_MCLK3_CLK					70
-#define CAM_CC_MCLK3_CLK_SRC					71
-#define CAM_CC_PLL0						72
-#define CAM_CC_PLL0_OUT_EVEN					73
-#define CAM_CC_PLL1						74
-#define CAM_CC_PLL1_OUT_EVEN					75
-#define CAM_CC_PLL2						76
-#define CAM_CC_PLL2_OUT_EVEN					77
-#define CAM_CC_PLL2_OUT_ODD					78
-#define CAM_CC_PLL3						79
-#define CAM_CC_PLL3_OUT_EVEN					80
-#define CAM_CC_PLL_TEST_CLK					81
-#define CAM_CC_SLOW_AHB_CLK_SRC					82
-#define CAM_CC_SOC_AHB_CLK					83
-#define CAM_CC_SYS_TMR_CLK					84
+#define CAM_CC_FAST_AHB_CLK_SRC					20
+#define CAM_CC_FD_CORE_CLK					21
+#define CAM_CC_FD_CORE_CLK_SRC					22
+#define CAM_CC_FD_CORE_UAR_CLK					23
+#define CAM_CC_ICP_APB_CLK					24
+#define CAM_CC_ICP_ATB_CLK					25
+#define CAM_CC_ICP_CLK						26
+#define CAM_CC_ICP_CLK_SRC					27
+#define CAM_CC_ICP_CTI_CLK					28
+#define CAM_CC_ICP_TS_CLK					29
+#define CAM_CC_IFE_0_AXI_CLK					30
+#define CAM_CC_IFE_0_CLK					31
+#define CAM_CC_IFE_0_CLK_SRC					32
+#define CAM_CC_IFE_0_CPHY_RX_CLK				33
+#define CAM_CC_IFE_0_CSID_CLK					34
+#define CAM_CC_IFE_0_CSID_CLK_SRC				35
+#define CAM_CC_IFE_0_DSP_CLK					36
+#define CAM_CC_IFE_1_AXI_CLK					37
+#define CAM_CC_IFE_1_CLK					38
+#define CAM_CC_IFE_1_CLK_SRC					39
+#define CAM_CC_IFE_1_CPHY_RX_CLK				40
+#define CAM_CC_IFE_1_CSID_CLK					41
+#define CAM_CC_IFE_1_CSID_CLK_SRC				42
+#define CAM_CC_IFE_1_DSP_CLK					43
+#define CAM_CC_IFE_LITE_CLK					44
+#define CAM_CC_IFE_LITE_CLK_SRC					45
+#define CAM_CC_IFE_LITE_CPHY_RX_CLK				46
+#define CAM_CC_IFE_LITE_CSID_CLK				47
+#define CAM_CC_IFE_LITE_CSID_CLK_SRC				48
+#define CAM_CC_IPE_0_AHB_CLK					49
+#define CAM_CC_IPE_0_AREG_CLK					50
+#define CAM_CC_IPE_0_AXI_CLK					51
+#define CAM_CC_IPE_0_CLK					52
+#define CAM_CC_IPE_0_CLK_SRC					53
+#define CAM_CC_IPE_1_AHB_CLK					54
+#define CAM_CC_IPE_1_AREG_CLK					55
+#define CAM_CC_IPE_1_AXI_CLK					56
+#define CAM_CC_IPE_1_CLK					57
+#define CAM_CC_IPE_1_CLK_SRC					58
+#define CAM_CC_JPEG_CLK						59
+#define CAM_CC_JPEG_CLK_SRC					60
+#define CAM_CC_LRME_CLK						61
+#define CAM_CC_LRME_CLK_SRC					62
+#define CAM_CC_MCLK0_CLK					63
+#define CAM_CC_MCLK0_CLK_SRC					64
+#define CAM_CC_MCLK1_CLK					65
+#define CAM_CC_MCLK1_CLK_SRC					66
+#define CAM_CC_MCLK2_CLK					67
+#define CAM_CC_MCLK2_CLK_SRC					68
+#define CAM_CC_MCLK3_CLK					69
+#define CAM_CC_MCLK3_CLK_SRC					70
+#define CAM_CC_PLL0						71
+#define CAM_CC_PLL0_OUT_EVEN					72
+#define CAM_CC_PLL1						73
+#define CAM_CC_PLL1_OUT_EVEN					74
+#define CAM_CC_PLL2						75
+#define CAM_CC_PLL2_OUT_EVEN					76
+#define CAM_CC_PLL2_OUT_ODD					77
+#define CAM_CC_PLL3						78
+#define CAM_CC_PLL3_OUT_EVEN					79
+#define CAM_CC_PLL_TEST_CLK					80
+#define CAM_CC_SLOW_AHB_CLK_SRC					81
+#define CAM_CC_SOC_AHB_CLK					82
+#define CAM_CC_SYS_TMR_CLK					83
 
 #define TITAN_CAM_CC_BPS_BCR					0
 #define TITAN_CAM_CC_CAMNOC_BCR					1
diff --git a/include/dt-bindings/clock/qcom,dispcc-sdm845.h b/include/dt-bindings/clock/qcom,dispcc-sdm845.h
index b1988e4..24dd11e 100644
--- a/include/dt-bindings/clock/qcom,dispcc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,dispcc-sdm845.h
@@ -14,49 +14,48 @@
 #ifndef _DT_BINDINGS_CLK_MSM_DISP_CC_SDM845_H
 #define _DT_BINDINGS_CLK_MSM_DISP_CC_SDM845_H
 
-#define DISP_CC_DEBUG_CLK					0
-#define DISP_CC_MDSS_AHB_CLK					1
-#define DISP_CC_MDSS_AXI_CLK					2
-#define DISP_CC_MDSS_BYTE0_CLK					3
-#define DISP_CC_MDSS_BYTE0_CLK_SRC				4
-#define DISP_CC_MDSS_BYTE0_INTF_CLK				5
-#define DISP_CC_MDSS_BYTE1_CLK					6
-#define DISP_CC_MDSS_BYTE1_CLK_SRC				7
-#define DISP_CC_MDSS_BYTE1_INTF_CLK				8
-#define DISP_CC_MDSS_DP_AUX_CLK					9
-#define DISP_CC_MDSS_DP_AUX_CLK_SRC				10
-#define DISP_CC_MDSS_DP_CRYPTO_CLK				11
-#define DISP_CC_MDSS_DP_CRYPTO_CLK_SRC				12
-#define DISP_CC_MDSS_DP_LINK_CLK				13
-#define DISP_CC_MDSS_DP_LINK_CLK_SRC				14
-#define DISP_CC_MDSS_DP_LINK_INTF_CLK				15
-#define DISP_CC_MDSS_DP_PIXEL1_CLK				16
-#define DISP_CC_MDSS_DP_PIXEL1_CLK_SRC				17
-#define DISP_CC_MDSS_DP_PIXEL_CLK				18
-#define DISP_CC_MDSS_DP_PIXEL_CLK_SRC				19
-#define DISP_CC_MDSS_ESC0_CLK					20
-#define DISP_CC_MDSS_ESC0_CLK_SRC				21
-#define DISP_CC_MDSS_ESC1_CLK					22
-#define DISP_CC_MDSS_ESC1_CLK_SRC				23
-#define DISP_CC_MDSS_MDP_CLK					24
-#define DISP_CC_MDSS_MDP_CLK_SRC				25
-#define DISP_CC_MDSS_MDP_LUT_CLK				26
-#define DISP_CC_MDSS_PCLK0_CLK					27
-#define DISP_CC_MDSS_PCLK0_CLK_SRC				28
-#define DISP_CC_MDSS_PCLK1_CLK					29
-#define DISP_CC_MDSS_PCLK1_CLK_SRC				30
-#define DISP_CC_MDSS_QDSS_AT_CLK				31
-#define DISP_CC_MDSS_QDSS_TSCTR_DIV8_CLK			32
-#define DISP_CC_MDSS_ROT_CLK					33
-#define DISP_CC_MDSS_ROT_CLK_SRC				34
-#define DISP_CC_MDSS_RSCC_AHB_CLK				35
-#define DISP_CC_MDSS_RSCC_VSYNC_CLK				36
-#define DISP_CC_MDSS_VSYNC_CLK					37
-#define DISP_CC_MDSS_VSYNC_CLK_SRC				38
-#define DISP_CC_PLL0						39
-#define DISP_CC_MDSS_BYTE0_DIV_CLK_SRC				40
-#define DISP_CC_MDSS_BYTE1_DIV_CLK_SRC				41
-#define DISP_CC_MDSS_DP_LINK_DIV_CLK_SRC			42
+#define DISP_CC_MDSS_AHB_CLK					0
+#define DISP_CC_MDSS_AXI_CLK					1
+#define DISP_CC_MDSS_BYTE0_CLK					2
+#define DISP_CC_MDSS_BYTE0_CLK_SRC				3
+#define DISP_CC_MDSS_BYTE0_INTF_CLK				4
+#define DISP_CC_MDSS_BYTE1_CLK					5
+#define DISP_CC_MDSS_BYTE1_CLK_SRC				6
+#define DISP_CC_MDSS_BYTE1_INTF_CLK				7
+#define DISP_CC_MDSS_DP_AUX_CLK					8
+#define DISP_CC_MDSS_DP_AUX_CLK_SRC				9
+#define DISP_CC_MDSS_DP_CRYPTO_CLK				10
+#define DISP_CC_MDSS_DP_CRYPTO_CLK_SRC				11
+#define DISP_CC_MDSS_DP_LINK_CLK				12
+#define DISP_CC_MDSS_DP_LINK_CLK_SRC				13
+#define DISP_CC_MDSS_DP_LINK_INTF_CLK				14
+#define DISP_CC_MDSS_DP_PIXEL1_CLK				15
+#define DISP_CC_MDSS_DP_PIXEL1_CLK_SRC				16
+#define DISP_CC_MDSS_DP_PIXEL_CLK				17
+#define DISP_CC_MDSS_DP_PIXEL_CLK_SRC				18
+#define DISP_CC_MDSS_ESC0_CLK					19
+#define DISP_CC_MDSS_ESC0_CLK_SRC				20
+#define DISP_CC_MDSS_ESC1_CLK					21
+#define DISP_CC_MDSS_ESC1_CLK_SRC				22
+#define DISP_CC_MDSS_MDP_CLK					23
+#define DISP_CC_MDSS_MDP_CLK_SRC				24
+#define DISP_CC_MDSS_MDP_LUT_CLK				25
+#define DISP_CC_MDSS_PCLK0_CLK					26
+#define DISP_CC_MDSS_PCLK0_CLK_SRC				27
+#define DISP_CC_MDSS_PCLK1_CLK					28
+#define DISP_CC_MDSS_PCLK1_CLK_SRC				29
+#define DISP_CC_MDSS_QDSS_AT_CLK				30
+#define DISP_CC_MDSS_QDSS_TSCTR_DIV8_CLK			31
+#define DISP_CC_MDSS_ROT_CLK					32
+#define DISP_CC_MDSS_ROT_CLK_SRC				33
+#define DISP_CC_MDSS_RSCC_AHB_CLK				34
+#define DISP_CC_MDSS_RSCC_VSYNC_CLK				35
+#define DISP_CC_MDSS_VSYNC_CLK					36
+#define DISP_CC_MDSS_VSYNC_CLK_SRC				37
+#define DISP_CC_PLL0						38
+#define DISP_CC_MDSS_BYTE0_DIV_CLK_SRC				39
+#define DISP_CC_MDSS_BYTE1_DIV_CLK_SRC				40
+#define DISP_CC_MDSS_DP_LINK_DIV_CLK_SRC			41
 
 #define DISP_CC_MDSS_CORE_BCR					0
 #define DISP_CC_MDSS_GCC_CLOCKS_BCR				1
diff --git a/include/dt-bindings/clock/qcom,gcc-sdm845.h b/include/dt-bindings/clock/qcom,gcc-sdm845.h
index f7a6978..6c62503 100644
--- a/include/dt-bindings/clock/qcom,gcc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,gcc-sdm845.h
@@ -35,161 +35,158 @@
 #define GCC_CPUSS_GNOC_CLK					17
 #define GCC_CPUSS_RBCPR_CLK					18
 #define GCC_CPUSS_RBCPR_CLK_SRC					19
-#define GCC_CXO_TX1_CLKREF_CLK					20
-#define GCC_DDRSS_GPU_AXI_CLK					21
-#define GCC_DISP_AHB_CLK					22
-#define GCC_DISP_AXI_CLK					23
-#define GCC_DISP_GPLL0_CLK_SRC					24
-#define GCC_DISP_GPLL0_DIV_CLK_SRC				25
-#define GCC_DISP_XO_CLK						26
-#define GCC_GP1_CLK						27
-#define GCC_GP1_CLK_SRC						28
-#define GCC_GP2_CLK						29
-#define GCC_GP2_CLK_SRC						30
-#define GCC_GP3_CLK						31
-#define GCC_GP3_CLK_SRC						32
-#define GCC_GPU_CFG_AHB_CLK					33
-#define GCC_GPU_GPLL0_CLK_SRC					34
-#define GCC_GPU_GPLL0_DIV_CLK_SRC				35
-#define GCC_GPU_MEMNOC_GFX_CLK					36
-#define GCC_GPU_SNOC_DVM_GFX_CLK				37
-#define GCC_MSS_AXIS2_CLK					38
-#define GCC_MSS_CFG_AHB_CLK					39
-#define GCC_MSS_GPLL0_DIV_CLK_SRC				40
-#define GCC_MSS_MFAB_AXIS_CLK					41
-#define GCC_MSS_Q6_MEMNOC_AXI_CLK				42
-#define GCC_MSS_SNOC_AXI_CLK					43
-#define GCC_PCIE_0_AUX_CLK					44
-#define GCC_PCIE_0_AUX_CLK_SRC					45
-#define GCC_PCIE_0_CFG_AHB_CLK					46
-#define GCC_PCIE_0_CLKREF_CLK					47
-#define GCC_PCIE_0_MSTR_AXI_CLK					48
-#define GCC_PCIE_0_PIPE_CLK					49
-#define GCC_PCIE_0_SLV_AXI_CLK					50
-#define GCC_PCIE_0_SLV_Q2A_AXI_CLK				51
-#define GCC_PCIE_1_AUX_CLK					52
-#define GCC_PCIE_1_AUX_CLK_SRC					53
-#define GCC_PCIE_1_CFG_AHB_CLK					54
-#define GCC_PCIE_1_CLKREF_CLK					55
-#define GCC_PCIE_1_MSTR_AXI_CLK					56
-#define GCC_PCIE_1_PIPE_CLK					57
-#define GCC_PCIE_1_SLV_AXI_CLK					58
-#define GCC_PCIE_1_SLV_Q2A_AXI_CLK				59
-#define GCC_PCIE_PHY_AUX_CLK					60
-#define GCC_PCIE_PHY_REFGEN_CLK					61
-#define GCC_PCIE_PHY_REFGEN_CLK_SRC				62
-#define GCC_PDM2_CLK						63
-#define GCC_PDM2_CLK_SRC					64
-#define GCC_PDM_AHB_CLK						65
-#define GCC_PDM_XO4_CLK						66
-#define GCC_PRNG_AHB_CLK					67
-#define GCC_QMIP_CAMERA_AHB_CLK					68
-#define GCC_QMIP_DISP_AHB_CLK					69
-#define GCC_QMIP_VIDEO_AHB_CLK					70
-#define GCC_QUPV3_WRAP0_S0_CLK					71
-#define GCC_QUPV3_WRAP0_S0_CLK_SRC				72
-#define GCC_QUPV3_WRAP0_S1_CLK					73
-#define GCC_QUPV3_WRAP0_S1_CLK_SRC				74
-#define GCC_QUPV3_WRAP0_S2_CLK					75
-#define GCC_QUPV3_WRAP0_S2_CLK_SRC				76
-#define GCC_QUPV3_WRAP0_S3_CLK					77
-#define GCC_QUPV3_WRAP0_S3_CLK_SRC				78
-#define GCC_QUPV3_WRAP0_S4_CLK					79
-#define GCC_QUPV3_WRAP0_S4_CLK_SRC				80
-#define GCC_QUPV3_WRAP0_S5_CLK					81
-#define GCC_QUPV3_WRAP0_S5_CLK_SRC				82
-#define GCC_QUPV3_WRAP0_S6_CLK					83
-#define GCC_QUPV3_WRAP0_S6_CLK_SRC				84
-#define GCC_QUPV3_WRAP0_S7_CLK					85
-#define GCC_QUPV3_WRAP0_S7_CLK_SRC				86
-#define GCC_QUPV3_WRAP1_S0_CLK					87
-#define GCC_QUPV3_WRAP1_S0_CLK_SRC				88
-#define GCC_QUPV3_WRAP1_S1_CLK					89
-#define GCC_QUPV3_WRAP1_S1_CLK_SRC				90
-#define GCC_QUPV3_WRAP1_S2_CLK					91
-#define GCC_QUPV3_WRAP1_S2_CLK_SRC				92
-#define GCC_QUPV3_WRAP1_S3_CLK					93
-#define GCC_QUPV3_WRAP1_S3_CLK_SRC				94
-#define GCC_QUPV3_WRAP1_S4_CLK					95
-#define GCC_QUPV3_WRAP1_S4_CLK_SRC				96
-#define GCC_QUPV3_WRAP1_S5_CLK					97
-#define GCC_QUPV3_WRAP1_S5_CLK_SRC				98
-#define GCC_QUPV3_WRAP1_S6_CLK					99
-#define GCC_QUPV3_WRAP1_S6_CLK_SRC				100
-#define GCC_QUPV3_WRAP1_S7_CLK					101
-#define GCC_QUPV3_WRAP1_S7_CLK_SRC				102
-#define GCC_QUPV3_WRAP_0_M_AHB_CLK				103
-#define GCC_QUPV3_WRAP_0_S_AHB_CLK				104
-#define GCC_QUPV3_WRAP_1_M_AHB_CLK				105
-#define GCC_QUPV3_WRAP_1_S_AHB_CLK				106
-#define GCC_RX1_USB2_CLKREF_CLK					107
-#define GCC_RX2_QLINK_CLKREF_CLK				108
-#define GCC_SDCC2_AHB_CLK					109
-#define GCC_SDCC2_APPS_CLK					110
-#define GCC_SDCC2_APPS_CLK_SRC					111
-#define GCC_SDCC4_AHB_CLK					112
-#define GCC_SDCC4_APPS_CLK					113
-#define GCC_SDCC4_APPS_CLK_SRC					114
-#define GCC_SYS_NOC_CPUSS_AHB_CLK				115
-#define GCC_TSIF_AHB_CLK					116
-#define GCC_TSIF_INACTIVITY_TIMERS_CLK				117
-#define GCC_TSIF_REF_CLK					118
-#define GCC_TSIF_REF_CLK_SRC					119
-#define GCC_UFS_CARD_AHB_CLK					120
-#define GCC_UFS_CARD_AXI_CLK					121
-#define GCC_UFS_CARD_AXI_CLK_SRC				122
-#define GCC_UFS_CARD_CLKREF_CLK					123
-#define GCC_UFS_CARD_ICE_CORE_CLK				124
-#define GCC_UFS_CARD_ICE_CORE_CLK_SRC				125
-#define GCC_UFS_CARD_PHY_AUX_CLK				126
-#define GCC_UFS_CARD_PHY_AUX_CLK_SRC				127
-#define GCC_UFS_CARD_RX_SYMBOL_0_CLK				128
-#define GCC_UFS_CARD_RX_SYMBOL_1_CLK				129
-#define GCC_UFS_CARD_TX_SYMBOL_0_CLK				130
-#define GCC_UFS_CARD_UNIPRO_CORE_CLK				131
-#define GCC_UFS_CARD_UNIPRO_CORE_CLK_SRC			132
-#define GCC_UFS_MEM_CLKREF_CLK					133
-#define GCC_UFS_PHY_AHB_CLK					134
-#define GCC_UFS_PHY_AXI_CLK					135
-#define GCC_UFS_PHY_AXI_CLK_SRC					136
-#define GCC_UFS_PHY_ICE_CORE_CLK				137
-#define GCC_UFS_PHY_ICE_CORE_CLK_SRC				138
-#define GCC_UFS_PHY_PHY_AUX_CLK					139
-#define GCC_UFS_PHY_PHY_AUX_CLK_SRC				140
-#define GCC_UFS_PHY_RX_SYMBOL_0_CLK				141
-#define GCC_UFS_PHY_RX_SYMBOL_1_CLK				142
-#define GCC_UFS_PHY_TX_SYMBOL_0_CLK				143
-#define GCC_UFS_PHY_UNIPRO_CORE_CLK				144
-#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC				145
-#define GCC_USB30_PRIM_MASTER_CLK				146
-#define GCC_USB30_PRIM_MASTER_CLK_SRC				147
-#define GCC_USB30_PRIM_MOCK_UTMI_CLK				148
-#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC			149
-#define GCC_USB30_PRIM_SLEEP_CLK				150
-#define GCC_USB30_SEC_MASTER_CLK				151
-#define GCC_USB30_SEC_MASTER_CLK_SRC				152
-#define GCC_USB30_SEC_MOCK_UTMI_CLK				153
-#define GCC_USB30_SEC_MOCK_UTMI_CLK_SRC				154
-#define GCC_USB30_SEC_SLEEP_CLK					155
-#define GCC_USB3_PRIM_CLKREF_CLK				156
-#define GCC_USB3_PRIM_PHY_AUX_CLK				157
-#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC				158
-#define GCC_USB3_PRIM_PHY_COM_AUX_CLK				159
-#define GCC_USB3_PRIM_PHY_PIPE_CLK				160
-#define GCC_USB3_SEC_CLKREF_CLK					161
-#define GCC_USB3_SEC_PHY_AUX_CLK				162
-#define GCC_USB3_SEC_PHY_AUX_CLK_SRC				163
-#define GCC_USB3_SEC_PHY_COM_AUX_CLK				164
-#define GCC_USB3_SEC_PHY_PIPE_CLK				165
-#define GCC_USB_PHY_CFG_AHB2PHY_CLK				166
-#define GCC_VIDEO_AHB_CLK					167
-#define GCC_VIDEO_AXI_CLK					168
-#define GCC_VIDEO_XO_CLK					169
-#define GPLL0							170
-#define GPLL0_OUT_EVEN						171
-#define GPLL0_OUT_MAIN						172
-#define GPLL1							173
-#define GPLL1_OUT_MAIN						174
+#define GCC_DDRSS_GPU_AXI_CLK					20
+#define GCC_DISP_AHB_CLK					21
+#define GCC_DISP_AXI_CLK					22
+#define GCC_DISP_GPLL0_CLK_SRC					23
+#define GCC_DISP_GPLL0_DIV_CLK_SRC				24
+#define GCC_DISP_XO_CLK						25
+#define GCC_GP1_CLK						26
+#define GCC_GP1_CLK_SRC						27
+#define GCC_GP2_CLK						28
+#define GCC_GP2_CLK_SRC						29
+#define GCC_GP3_CLK						30
+#define GCC_GP3_CLK_SRC						31
+#define GCC_GPU_CFG_AHB_CLK					32
+#define GCC_GPU_GPLL0_CLK_SRC					33
+#define GCC_GPU_GPLL0_DIV_CLK_SRC				34
+#define GCC_GPU_MEMNOC_GFX_CLK					35
+#define GCC_GPU_SNOC_DVM_GFX_CLK				36
+#define GCC_MSS_AXIS2_CLK					37
+#define GCC_MSS_CFG_AHB_CLK					38
+#define GCC_MSS_GPLL0_DIV_CLK_SRC				39
+#define GCC_MSS_MFAB_AXIS_CLK					40
+#define GCC_MSS_Q6_MEMNOC_AXI_CLK				41
+#define GCC_MSS_SNOC_AXI_CLK					42
+#define GCC_PCIE_0_AUX_CLK					43
+#define GCC_PCIE_0_AUX_CLK_SRC					44
+#define GCC_PCIE_0_CFG_AHB_CLK					45
+#define GCC_PCIE_0_CLKREF_CLK					46
+#define GCC_PCIE_0_MSTR_AXI_CLK					47
+#define GCC_PCIE_0_PIPE_CLK					48
+#define GCC_PCIE_0_SLV_AXI_CLK					49
+#define GCC_PCIE_0_SLV_Q2A_AXI_CLK				50
+#define GCC_PCIE_1_AUX_CLK					51
+#define GCC_PCIE_1_AUX_CLK_SRC					52
+#define GCC_PCIE_1_CFG_AHB_CLK					53
+#define GCC_PCIE_1_CLKREF_CLK					54
+#define GCC_PCIE_1_MSTR_AXI_CLK					55
+#define GCC_PCIE_1_PIPE_CLK					56
+#define GCC_PCIE_1_SLV_AXI_CLK					57
+#define GCC_PCIE_1_SLV_Q2A_AXI_CLK				58
+#define GCC_PCIE_PHY_AUX_CLK					59
+#define GCC_PCIE_PHY_REFGEN_CLK					60
+#define GCC_PCIE_PHY_REFGEN_CLK_SRC				61
+#define GCC_PDM2_CLK						62
+#define GCC_PDM2_CLK_SRC					63
+#define GCC_PDM_AHB_CLK						64
+#define GCC_PDM_XO4_CLK						65
+#define GCC_PRNG_AHB_CLK					66
+#define GCC_QMIP_CAMERA_AHB_CLK					67
+#define GCC_QMIP_DISP_AHB_CLK					68
+#define GCC_QMIP_VIDEO_AHB_CLK					69
+#define GCC_QUPV3_WRAP0_S0_CLK					70
+#define GCC_QUPV3_WRAP0_S0_CLK_SRC				71
+#define GCC_QUPV3_WRAP0_S1_CLK					72
+#define GCC_QUPV3_WRAP0_S1_CLK_SRC				73
+#define GCC_QUPV3_WRAP0_S2_CLK					74
+#define GCC_QUPV3_WRAP0_S2_CLK_SRC				75
+#define GCC_QUPV3_WRAP0_S3_CLK					76
+#define GCC_QUPV3_WRAP0_S3_CLK_SRC				77
+#define GCC_QUPV3_WRAP0_S4_CLK					78
+#define GCC_QUPV3_WRAP0_S4_CLK_SRC				79
+#define GCC_QUPV3_WRAP0_S5_CLK					80
+#define GCC_QUPV3_WRAP0_S5_CLK_SRC				81
+#define GCC_QUPV3_WRAP0_S6_CLK					82
+#define GCC_QUPV3_WRAP0_S6_CLK_SRC				83
+#define GCC_QUPV3_WRAP0_S7_CLK					84
+#define GCC_QUPV3_WRAP0_S7_CLK_SRC				85
+#define GCC_QUPV3_WRAP1_S0_CLK					86
+#define GCC_QUPV3_WRAP1_S0_CLK_SRC				87
+#define GCC_QUPV3_WRAP1_S1_CLK					88
+#define GCC_QUPV3_WRAP1_S1_CLK_SRC				89
+#define GCC_QUPV3_WRAP1_S2_CLK					90
+#define GCC_QUPV3_WRAP1_S2_CLK_SRC				91
+#define GCC_QUPV3_WRAP1_S3_CLK					92
+#define GCC_QUPV3_WRAP1_S3_CLK_SRC				93
+#define GCC_QUPV3_WRAP1_S4_CLK					94
+#define GCC_QUPV3_WRAP1_S4_CLK_SRC				95
+#define GCC_QUPV3_WRAP1_S5_CLK					96
+#define GCC_QUPV3_WRAP1_S5_CLK_SRC				97
+#define GCC_QUPV3_WRAP1_S6_CLK					98
+#define GCC_QUPV3_WRAP1_S6_CLK_SRC				99
+#define GCC_QUPV3_WRAP1_S7_CLK					100
+#define GCC_QUPV3_WRAP1_S7_CLK_SRC				101
+#define GCC_QUPV3_WRAP_0_M_AHB_CLK				102
+#define GCC_QUPV3_WRAP_0_S_AHB_CLK				103
+#define GCC_QUPV3_WRAP_1_M_AHB_CLK				104
+#define GCC_QUPV3_WRAP_1_S_AHB_CLK				105
+#define GCC_SDCC2_AHB_CLK					106
+#define GCC_SDCC2_APPS_CLK					107
+#define GCC_SDCC2_APPS_CLK_SRC					108
+#define GCC_SDCC4_AHB_CLK					109
+#define GCC_SDCC4_APPS_CLK					110
+#define GCC_SDCC4_APPS_CLK_SRC					111
+#define GCC_SYS_NOC_CPUSS_AHB_CLK				112
+#define GCC_TSIF_AHB_CLK					113
+#define GCC_TSIF_INACTIVITY_TIMERS_CLK				114
+#define GCC_TSIF_REF_CLK					115
+#define GCC_TSIF_REF_CLK_SRC					116
+#define GCC_UFS_CARD_AHB_CLK					117
+#define GCC_UFS_CARD_AXI_CLK					118
+#define GCC_UFS_CARD_AXI_CLK_SRC				119
+#define GCC_UFS_CARD_CLKREF_CLK					120
+#define GCC_UFS_CARD_ICE_CORE_CLK				121
+#define GCC_UFS_CARD_ICE_CORE_CLK_SRC				122
+#define GCC_UFS_CARD_PHY_AUX_CLK				123
+#define GCC_UFS_CARD_PHY_AUX_CLK_SRC				124
+#define GCC_UFS_CARD_RX_SYMBOL_0_CLK				125
+#define GCC_UFS_CARD_RX_SYMBOL_1_CLK				126
+#define GCC_UFS_CARD_TX_SYMBOL_0_CLK				127
+#define GCC_UFS_CARD_UNIPRO_CORE_CLK				128
+#define GCC_UFS_CARD_UNIPRO_CORE_CLK_SRC			129
+#define GCC_UFS_MEM_CLKREF_CLK					130
+#define GCC_UFS_PHY_AHB_CLK					131
+#define GCC_UFS_PHY_AXI_CLK					132
+#define GCC_UFS_PHY_AXI_CLK_SRC					133
+#define GCC_UFS_PHY_ICE_CORE_CLK				134
+#define GCC_UFS_PHY_ICE_CORE_CLK_SRC				135
+#define GCC_UFS_PHY_PHY_AUX_CLK					136
+#define GCC_UFS_PHY_PHY_AUX_CLK_SRC				137
+#define GCC_UFS_PHY_RX_SYMBOL_0_CLK				138
+#define GCC_UFS_PHY_RX_SYMBOL_1_CLK				139
+#define GCC_UFS_PHY_TX_SYMBOL_0_CLK				140
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK				141
+#define GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC				142
+#define GCC_USB30_PRIM_MASTER_CLK				143
+#define GCC_USB30_PRIM_MASTER_CLK_SRC				144
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK				145
+#define GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC			146
+#define GCC_USB30_PRIM_SLEEP_CLK				147
+#define GCC_USB30_SEC_MASTER_CLK				148
+#define GCC_USB30_SEC_MASTER_CLK_SRC				149
+#define GCC_USB30_SEC_MOCK_UTMI_CLK				150
+#define GCC_USB30_SEC_MOCK_UTMI_CLK_SRC				151
+#define GCC_USB30_SEC_SLEEP_CLK					152
+#define GCC_USB3_PRIM_CLKREF_CLK				153
+#define GCC_USB3_PRIM_PHY_AUX_CLK				154
+#define GCC_USB3_PRIM_PHY_AUX_CLK_SRC				155
+#define GCC_USB3_PRIM_PHY_COM_AUX_CLK				156
+#define GCC_USB3_PRIM_PHY_PIPE_CLK				157
+#define GCC_USB3_SEC_CLKREF_CLK					158
+#define GCC_USB3_SEC_PHY_AUX_CLK				159
+#define GCC_USB3_SEC_PHY_AUX_CLK_SRC				160
+#define GCC_USB3_SEC_PHY_COM_AUX_CLK				161
+#define GCC_USB3_SEC_PHY_PIPE_CLK				162
+#define GCC_USB_PHY_CFG_AHB2PHY_CLK				163
+#define GCC_VIDEO_AHB_CLK					164
+#define GCC_VIDEO_AXI_CLK					165
+#define GCC_VIDEO_XO_CLK					166
+#define GPLL0							167
+#define GPLL0_OUT_EVEN						168
+#define GPLL0_OUT_MAIN						169
+#define GPLL1							170
+#define GPLL1_OUT_MAIN						171
 
 /* GCC reset clocks */
 #define GCC_GPU_BCR						0
diff --git a/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h b/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h
new file mode 100644
index 0000000..6243588
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_GCC_SDX24_H
+#define _DT_BINDINGS_CLK_MSM_GCC_SDX24_H
+
+/* GCC clock registers */
+#define GCC_BLSP1_AHB_CLK					0
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK				1
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK_SRC				2
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK				3
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK_SRC				4
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK				5
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK_SRC				6
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK				7
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK_SRC				8
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK				9
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK_SRC				10
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK				11
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK_SRC				12
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK				13
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK_SRC				14
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK				15
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK_SRC				16
+#define GCC_BLSP1_SLEEP_CLK					17
+#define GCC_BLSP1_UART1_APPS_CLK				18
+#define GCC_BLSP1_UART1_APPS_CLK_SRC				19
+#define GCC_BLSP1_UART2_APPS_CLK				20
+#define GCC_BLSP1_UART2_APPS_CLK_SRC				21
+#define GCC_BLSP1_UART3_APPS_CLK				22
+#define GCC_BLSP1_UART3_APPS_CLK_SRC				23
+#define GCC_BLSP1_UART4_APPS_CLK				24
+#define GCC_BLSP1_UART4_APPS_CLK_SRC				25
+#define GCC_BOOT_ROM_AHB_CLK					26
+#define GCC_CE1_AHB_CLK						27
+#define GCC_CE1_AXI_CLK						28
+#define GCC_CE1_CLK						29
+#define GCC_CPUSS_AHB_CLK					30
+#define GCC_CPUSS_AHB_CLK_SRC					31
+#define GCC_CPUSS_GNOC_CLK					32
+#define GCC_CPUSS_GPLL0_CLK_SRC					33
+#define GCC_CPUSS_RBCPR_CLK					34
+#define GCC_CPUSS_RBCPR_CLK_SRC					35
+#define GCC_GP1_CLK						36
+#define GCC_GP1_CLK_SRC						37
+#define GCC_GP2_CLK						38
+#define GCC_GP2_CLK_SRC						39
+#define GCC_GP3_CLK						40
+#define GCC_GP3_CLK_SRC						41
+#define GCC_MSS_CFG_AHB_CLK					42
+#define GCC_MSS_GPLL0_DIV_CLK_SRC				43
+#define GCC_MSS_SNOC_AXI_CLK					44
+#define GCC_PCIE_AUX_CLK					45
+#define GCC_PCIE_AUX_PHY_CLK_SRC				46
+#define GCC_PCIE_CFG_AHB_CLK					47
+#define GCC_PCIE_MSTR_AXI_CLK					48
+#define GCC_PCIE_PHY_REFGEN_CLK					49
+#define GCC_PCIE_PHY_REFGEN_CLK_SRC				50
+#define GCC_PCIE_PIPE_CLK					51
+#define GCC_PCIE_SLEEP_CLK					52
+#define GCC_PCIE_SLV_AXI_CLK					53
+#define GCC_PCIE_SLV_Q2A_AXI_CLK				54
+#define GCC_PDM2_CLK						55
+#define GCC_PDM2_CLK_SRC					56
+#define GCC_PDM_AHB_CLK						57
+#define GCC_PDM_XO4_CLK						58
+#define GCC_PRNG_AHB_CLK					59
+#define GCC_SDCC1_AHB_CLK					60
+#define GCC_SDCC1_APPS_CLK					61
+#define GCC_SDCC1_APPS_CLK_SRC					62
+#define GCC_SPMI_FETCHER_AHB_CLK				63
+#define GCC_SPMI_FETCHER_CLK					64
+#define GCC_SPMI_FETCHER_CLK_SRC				65
+#define GCC_SYS_NOC_CPUSS_AHB_CLK				66
+#define GCC_USB30_MASTER_CLK					67
+#define GCC_USB30_MASTER_CLK_SRC				68
+#define GCC_USB30_MOCK_UTMI_CLK					69
+#define GCC_USB30_MOCK_UTMI_CLK_SRC				70
+#define GCC_USB30_SLEEP_CLK					71
+#define GCC_USB3_PHY_AUX_CLK					72
+#define GCC_USB3_PHY_AUX_CLK_SRC				73
+#define GCC_USB3_PHY_PIPE_CLK					74
+#define GCC_USB_PHY_CFG_AHB2PHY_CLK				75
+#define GCC_XO_DIV4_CLK						76
+#define GPLL0							77
+#define GPLL0_OUT_EVEN						78
+
+/* GDSCs */
+#define PCIE_GDSC						0
+#define USB30_GDSC						1
+
+/* CPU clocks */
+#define CLOCK_A7SS						0
+
+/* GCC reset clocks */
+#define GCC_BLSP1_QUP1_BCR					0
+#define GCC_BLSP1_QUP2_BCR					1
+#define GCC_BLSP1_QUP3_BCR					2
+#define GCC_BLSP1_QUP4_BCR					3
+#define GCC_BLSP1_UART2_BCR					4
+#define GCC_BLSP1_UART3_BCR					5
+#define GCC_BLSP1_UART4_BCR					6
+#define GCC_CE1_BCR						7
+#define GCC_PCIE_BCR						8
+#define GCC_PCIE_PHY_BCR					9
+#define GCC_PDM_BCR						10
+#define GCC_PRNG_BCR						11
+#define GCC_SDCC1_BCR						12
+#define GCC_SPMI_FETCHER_BCR					13
+#define GCC_USB30_BCR						14
+#define GCC_USB_PHY_CFG_AHB2PHY_BCR				15
+
+#endif
diff --git a/include/dt-bindings/clock/qcom,gpucc-sdm845.h b/include/dt-bindings/clock/qcom,gpucc-sdm845.h
index 13de1e1..c43a9f8 100644
--- a/include/dt-bindings/clock/qcom,gpucc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,gpucc-sdm845.h
@@ -17,37 +17,36 @@
 /* GPUCC clock registers */
 #define GPU_CC_ACD_AHB_CLK					0
 #define GPU_CC_ACD_CXO_CLK					1
-#define GPU_CC_AHB_CLK					2
+#define GPU_CC_AHB_CLK						2
 #define GPU_CC_CRC_AHB_CLK					3
 #define GPU_CC_CX_APB_CLK					4
 #define GPU_CC_CX_GMU_CLK					5
 #define GPU_CC_CX_QDSS_AT_CLK					6
 #define GPU_CC_CX_QDSS_TRIG_CLK					7
-#define GPU_CC_CX_QDSS_TSCTR_CLK					8
-#define GPU_CC_CX_SNOC_DVM_CLK						9
+#define GPU_CC_CX_QDSS_TSCTR_CLK				8
+#define GPU_CC_CX_SNOC_DVM_CLK					9
 #define GPU_CC_CXO_AON_CLK					10
-#define GPU_CC_CXO_CLK					11
-#define GPU_CC_DEBUG_CLK					12
-#define GPU_CC_GX_CXO_CLK					13
-#define GPU_CC_GX_GMU_CLK					14
-#define GPU_CC_GX_QDSS_TSCTR_CLK					15
-#define GPU_CC_GX_VSENSE_CLK					16
-#define GPU_CC_PLL0_OUT_MAIN					 17
-#define GPU_CC_PLL0_OUT_ODD						18
-#define GPU_CC_PLL0_OUT_TEST					19
-#define GPU_CC_PLL1						20
-#define GPU_CC_PLL1_OUT_EVEN					21
-#define GPU_CC_PLL1_OUT_MAIN					22
-#define GPU_CC_PLL1_OUT_ODD					23
-#define GPU_CC_PLL1_OUT_TEST					24
-#define GPU_CC_PLL_TEST_CLK					25
-#define GPU_CC_RBCPR_AHB_CLK					26
-#define GPU_CC_RBCPR_CLK					27
-#define GPU_CC_RBCPR_CLK_SRC					28
-#define GPU_CC_SLEEP_CLK					29
-#define GPU_CC_GMU_CLK_SRC					30
-#define GPU_CC_CX_GFX3D_CLK					31
-#define GPU_CC_CX_GFX3D_SLV_CLK					32
+#define GPU_CC_CXO_CLK						11
+#define GPU_CC_GX_CXO_CLK					12
+#define GPU_CC_GX_GMU_CLK					13
+#define GPU_CC_GX_QDSS_TSCTR_CLK				14
+#define GPU_CC_GX_VSENSE_CLK					15
+#define GPU_CC_PLL0_OUT_MAIN					16
+#define GPU_CC_PLL0_OUT_ODD					17
+#define GPU_CC_PLL0_OUT_TEST					18
+#define GPU_CC_PLL1						19
+#define GPU_CC_PLL1_OUT_EVEN					20
+#define GPU_CC_PLL1_OUT_MAIN					21
+#define GPU_CC_PLL1_OUT_ODD					22
+#define GPU_CC_PLL1_OUT_TEST					23
+#define GPU_CC_PLL_TEST_CLK					24
+#define GPU_CC_RBCPR_AHB_CLK					25
+#define GPU_CC_RBCPR_CLK					26
+#define GPU_CC_RBCPR_CLK_SRC					27
+#define GPU_CC_SLEEP_CLK					28
+#define GPU_CC_GMU_CLK_SRC					29
+#define GPU_CC_CX_GFX3D_CLK					30
+#define GPU_CC_CX_GFX3D_SLV_CLK					31
 
 /* GPUCC reset clock registers */
 #define GPUCC_GPU_CC_ACD_BCR					0
@@ -63,5 +62,5 @@
 #define GPU_CC_PLL0						0
 #define GPU_CC_PLL0_OUT_EVEN					1
 #define GPU_CC_GX_GFX3D_CLK_SRC					2
-#define GPU_CC_GX_GFX3D_CLK						3
+#define GPU_CC_GX_GFX3D_CLK					3
 #endif
diff --git a/include/dt-bindings/clock/qcom,videocc-sdm845.h b/include/dt-bindings/clock/qcom,videocc-sdm845.h
index 723d2e0..b362852d 100644
--- a/include/dt-bindings/clock/qcom,videocc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,videocc-sdm845.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-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,18 +16,17 @@
 
 #define VIDEO_CC_APB_CLK					0
 #define VIDEO_CC_AT_CLK						1
-#define VIDEO_CC_DEBUG_CLK					2
-#define VIDEO_CC_QDSS_TRIG_CLK					3
-#define VIDEO_CC_QDSS_TSCTR_DIV8_CLK				4
-#define VIDEO_CC_VCODEC0_AXI_CLK				5
-#define VIDEO_CC_VCODEC0_CORE_CLK				6
-#define VIDEO_CC_VCODEC1_AXI_CLK				7
-#define VIDEO_CC_VCODEC1_CORE_CLK				8
-#define VIDEO_CC_VENUS_AHB_CLK					9
-#define VIDEO_CC_VENUS_CLK_SRC					10
-#define VIDEO_CC_VENUS_CTL_AXI_CLK				11
-#define VIDEO_CC_VENUS_CTL_CORE_CLK				12
-#define VIDEO_PLL0						13
+#define VIDEO_CC_QDSS_TRIG_CLK					2
+#define VIDEO_CC_QDSS_TSCTR_DIV8_CLK				3
+#define VIDEO_CC_VCODEC0_AXI_CLK				4
+#define VIDEO_CC_VCODEC0_CORE_CLK				5
+#define VIDEO_CC_VCODEC1_AXI_CLK				6
+#define VIDEO_CC_VCODEC1_CORE_CLK				7
+#define VIDEO_CC_VENUS_AHB_CLK					8
+#define VIDEO_CC_VENUS_CLK_SRC					9
+#define VIDEO_CC_VENUS_CTL_AXI_CLK				10
+#define VIDEO_CC_VENUS_CTL_CORE_CLK				11
+#define VIDEO_PLL0						12
 
 #define VIDEO_CC_INTERFACE_BCR					0
 #define VIDEO_CC_VCODEC0_BCR					1
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 5d3a4cd..3efd210 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -435,6 +435,7 @@
 		      const struct iommu_ops *ops);
 void iommu_fwspec_free(struct device *dev);
 int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
+int iommu_fwspec_get_id(struct device *dev, u32 *id);
 
 #else /* CONFIG_IOMMU_API */
 
@@ -705,6 +706,11 @@
 	return -ENODEV;
 }
 
+int iommu_fwspec_get_id(struct device *dev, u32 *id)
+{
+	return -ENODEV;
+}
+
 #endif /* CONFIG_IOMMU_API */
 
 #endif /* __LINUX_IOMMU_H */
diff --git a/include/linux/qpnp/qpnp-revid.h b/include/linux/qpnp/qpnp-revid.h
index a0e2283..7fca674 100644
--- a/include/linux/qpnp/qpnp-revid.h
+++ b/include/linux/qpnp/qpnp-revid.h
@@ -208,6 +208,12 @@
 #define PM660_V1P1_REV3		0x01
 #define PM660_V1P1_REV4		0x01
 
+/* PM660L REV_ID */
+#define PM660L_V1P1_REV1	0x00
+#define PM660L_V1P1_REV2	0x00
+#define PM660L_V1P1_REV3	0x01
+#define PM660L_V1P1_REV4	0x01
+
 /* PMI8998 FAB_ID */
 #define PMI8998_FAB_ID_SMIC	0x11
 #define PMI8998_FAB_ID_GF	0x30
@@ -229,6 +235,9 @@
 /* SMB1381 */
 #define SMB1381_SUBTYPE		0x17
 
+/* SMB1355 */
+#define SMB1355_SUBTYPE		0x1C
+
 struct pmic_revid_data {
 	u8		rev1;
 	u8		rev2;
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index 8ec7c30..931b494 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -260,27 +260,6 @@
 #define SCSI_INQ_PQ_NOT_CON     0x01
 #define SCSI_INQ_PQ_NOT_CAP     0x03
 
-
-/*
- * Here are some scsi specific ioctl commands which are sometimes useful.
- *
- * Note that include/linux/cdrom.h also defines IOCTL 0x5300 - 0x5395
- */
-
-/* Used to obtain PUN and LUN info.  Conflicts with CDROMAUDIOBUFSIZ */
-#define SCSI_IOCTL_GET_IDLUN		0x5382
-
-/* 0x5383 and 0x5384 were used for SCSI_IOCTL_TAGGED_{ENABLE,DISABLE} */
-
-/* Used to obtain the host number of a device. */
-#define SCSI_IOCTL_PROBE_HOST		0x5385
-
-/* Used to obtain the bus number for a device */
-#define SCSI_IOCTL_GET_BUS_NUMBER	0x5386
-
-/* Used to obtain the PCI location of a device */
-#define SCSI_IOCTL_GET_PCI		0x5387
-
 /* Pull a u32 out of a SCSI message (using BE SCSI conventions) */
 static inline __u32 scsi_to_u32(__u8 *ptr)
 {
diff --git a/include/soc/qcom/memory_dump.h b/include/soc/qcom/memory_dump.h
index a7b87aa..dbae8e8 100644
--- a/include/soc/qcom/memory_dump.h
+++ b/include/soc/qcom/memory_dump.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 2014-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
@@ -62,7 +62,7 @@
 #define MSM_DUMP_MINOR(val)		(val & 0xFFFFF)
 
 
-#define MAX_NUM_ENTRIES		0x120
+#define MAX_NUM_ENTRIES		0x140
 
 enum msm_dump_data_ids {
 	MSM_DUMP_DATA_CPU_CTX = 0x00,
@@ -82,10 +82,12 @@
 	MSM_DUMP_DATA_VSENSE = 0xE9,
 	MSM_DUMP_DATA_RPM = 0xEA,
 	MSM_DUMP_DATA_SCANDUMP = 0xEB,
+	MSM_DUMP_DATA_RPMH = 0xEC,
 	MSM_DUMP_DATA_TMC_ETF = 0xF0,
 	MSM_DUMP_DATA_TMC_REG = 0x100,
 	MSM_DUMP_DATA_LOG_BUF = 0x110,
 	MSM_DUMP_DATA_LOG_BUF_FIRST_IDX = 0x111,
+	MSM_DUMP_DATA_SCANDUMP_PER_CPU = 0x130,
 	MSM_DUMP_DATA_MAX = MAX_NUM_ENTRIES,
 };
 
diff --git a/include/uapi/drm/sde_drm.h b/include/uapi/drm/sde_drm.h
index b1bf6aa..74034c6 100644
--- a/include/uapi/drm/sde_drm.h
+++ b/include/uapi/drm/sde_drm.h
@@ -344,4 +344,16 @@
 	uint64_t modes;
 };
 
+#define SDE_MAX_ROI_V1	4
+
+/**
+ * struct sde_drm_roi_v1 - list of regions of interest for a drm object
+ * @num_rects: number of valid rectangles in the roi array
+ * @roi: list of roi rectangles
+ */
+struct sde_drm_roi_v1 {
+	uint32_t num_rects;
+	struct drm_clip_rect roi[SDE_MAX_ROI_V1];
+};
+
 #endif /* _SDE_DRM_H_ */
diff --git a/include/uapi/scsi/scsi_ioctl.h b/include/uapi/scsi/scsi_ioctl.h
index 516c581a..d9ce5cc 100644
--- a/include/uapi/scsi/scsi_ioctl.h
+++ b/include/uapi/scsi/scsi_ioctl.h
@@ -17,9 +17,25 @@
 #define	SCSI_REMOVAL_PREVENT	1
 #define	SCSI_REMOVAL_ALLOW	0
 
-#ifdef __KERNEL__
+/*
+ * Here are some scsi specific ioctl commands which are sometimes useful.
+ *
+ * Note that include/linux/cdrom.h also defines IOCTL 0x5300 - 0x5395
+ */
 
-struct scsi_device;
+/* Used to obtain PUN and LUN info.  Conflicts with CDROMAUDIOBUFSIZ */
+#define SCSI_IOCTL_GET_IDLUN		0x5382
+
+/* 0x5383 and 0x5384 were used for SCSI_IOCTL_TAGGED_{ENABLE,DISABLE} */
+
+/* Used to obtain the host number of a device. */
+#define SCSI_IOCTL_PROBE_HOST		0x5385
+
+/* Used to obtain the bus number for a device */
+#define SCSI_IOCTL_GET_BUS_NUMBER	0x5386
+
+/* Used to obtain the PCI location of a device */
+#define SCSI_IOCTL_GET_PCI		0x5387
 
 /*
  * Structures used for scsi_ioctl et al.
@@ -42,9 +58,11 @@
 	unsigned char host_wwn[8]; // include NULL term.
 } Scsi_FCTargAddress;
 
+#ifdef __KERNEL__
+struct scsi_device;
+
 int scsi_ioctl_block_when_processing_errors(struct scsi_device *sdev,
 		int cmd, bool ndelay);
 extern int scsi_ioctl(struct scsi_device *, int, void __user *);
-
 #endif /* __KERNEL__ */
 #endif /* _SCSI_IOCTL_H */
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 69e0689..27d96e2 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -12,11 +12,14 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/cpufreq.h>
+#include <linux/kthread.h>
 #include <linux/slab.h>
 #include <trace/events/power.h>
 
 #include "sched.h"
 
+#define SUGOV_KTHREAD_PRIORITY	50
+
 struct sugov_tunables {
 	struct gov_attr_set attr_set;
 	unsigned int rate_limit_us;
@@ -32,11 +35,14 @@
 	u64 last_freq_update_time;
 	s64 freq_update_delay_ns;
 	unsigned int next_freq;
+	unsigned int cached_raw_freq;
 
 	/* The next fields are only needed if fast switch cannot be used. */
 	struct irq_work irq_work;
-	struct work_struct work;
+	struct kthread_work work;
 	struct mutex work_lock;
+	struct kthread_worker worker;
+	struct task_struct *thread;
 	bool work_in_progress;
 
 	bool need_freq_update;
@@ -46,7 +52,6 @@
 	struct update_util_data update_util;
 	struct sugov_policy *sg_policy;
 
-	unsigned int cached_raw_freq;
 	unsigned long iowait_boost;
 	unsigned long iowait_boost_max;
 	u64 last_update;
@@ -110,7 +115,7 @@
 
 /**
  * get_next_freq - Compute a new frequency for a given cpufreq policy.
- * @sg_cpu: schedutil cpu object to compute the new frequency for.
+ * @sg_policy: schedutil policy object to compute the new frequency for.
  * @util: Current CPU utilization.
  * @max: CPU capacity.
  *
@@ -130,19 +135,18 @@
  * next_freq (as calculated above) is returned, subject to policy min/max and
  * cpufreq driver limitations.
  */
-static unsigned int get_next_freq(struct sugov_cpu *sg_cpu, unsigned long util,
-				  unsigned long max)
+static unsigned int get_next_freq(struct sugov_policy *sg_policy,
+				  unsigned long util, unsigned long max)
 {
-	struct sugov_policy *sg_policy = sg_cpu->sg_policy;
 	struct cpufreq_policy *policy = sg_policy->policy;
 	unsigned int freq = arch_scale_freq_invariant() ?
 				policy->cpuinfo.max_freq : policy->cur;
 
 	freq = (freq + (freq >> 2)) * util / max;
 
-	if (freq == sg_cpu->cached_raw_freq && sg_policy->next_freq != UINT_MAX)
+	if (freq == sg_policy->cached_raw_freq && sg_policy->next_freq != UINT_MAX)
 		return sg_policy->next_freq;
-	sg_cpu->cached_raw_freq = freq;
+	sg_policy->cached_raw_freq = freq;
 	return cpufreq_driver_resolve_freq(policy, freq);
 }
 
@@ -207,7 +211,7 @@
 	} else {
 		sugov_get_util(&util, &max);
 		sugov_iowait_boost(sg_cpu, &util, &max);
-		next_f = get_next_freq(sg_cpu, util, max);
+		next_f = get_next_freq(sg_policy, util, max);
 	}
 	sugov_update_commit(sg_policy, time, next_f);
 }
@@ -261,7 +265,7 @@
 		sugov_iowait_boost(j_sg_cpu, &util, &max);
 	}
 
-	return get_next_freq(sg_cpu, util, max);
+	return get_next_freq(sg_policy, util, max);
 }
 
 static void sugov_update_shared(struct update_util_data *hook, u64 time,
@@ -291,7 +295,7 @@
 	raw_spin_unlock(&sg_policy->update_lock);
 }
 
-static void sugov_work(struct work_struct *work)
+static void sugov_work(struct kthread_work *work)
 {
 	struct sugov_policy *sg_policy = container_of(work, struct sugov_policy, work);
 
@@ -308,7 +312,21 @@
 	struct sugov_policy *sg_policy;
 
 	sg_policy = container_of(irq_work, struct sugov_policy, irq_work);
-	schedule_work_on(smp_processor_id(), &sg_policy->work);
+
+	/*
+	 * For RT and deadline tasks, the schedutil governor shoots the
+	 * frequency to maximum. Special care must be taken to ensure that this
+	 * kthread doesn't result in the same behavior.
+	 *
+	 * This is (mostly) guaranteed by the work_in_progress flag. The flag is
+	 * updated only at the end of the sugov_work() function and before that
+	 * the schedutil governor rejects all other frequency scaling requests.
+	 *
+	 * There is a very rare case though, where the RT thread yields right
+	 * after the work_in_progress flag is cleared. The effects of that are
+	 * neglected for now.
+	 */
+	kthread_queue_work(&sg_policy->worker, &sg_policy->work);
 }
 
 /************************** sysfs interface ************************/
@@ -371,19 +389,64 @@
 		return NULL;
 
 	sg_policy->policy = policy;
-	init_irq_work(&sg_policy->irq_work, sugov_irq_work);
-	INIT_WORK(&sg_policy->work, sugov_work);
-	mutex_init(&sg_policy->work_lock);
 	raw_spin_lock_init(&sg_policy->update_lock);
 	return sg_policy;
 }
 
 static void sugov_policy_free(struct sugov_policy *sg_policy)
 {
-	mutex_destroy(&sg_policy->work_lock);
 	kfree(sg_policy);
 }
 
+static int sugov_kthread_create(struct sugov_policy *sg_policy)
+{
+	struct task_struct *thread;
+	struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO / 2 };
+	struct cpufreq_policy *policy = sg_policy->policy;
+	int ret;
+
+	/* kthread only required for slow path */
+	if (policy->fast_switch_enabled)
+		return 0;
+
+	kthread_init_work(&sg_policy->work, sugov_work);
+	kthread_init_worker(&sg_policy->worker);
+	thread = kthread_create(kthread_worker_fn, &sg_policy->worker,
+				"sugov:%d",
+				cpumask_first(policy->related_cpus));
+	if (IS_ERR(thread)) {
+		pr_err("failed to create sugov thread: %ld\n", PTR_ERR(thread));
+		return PTR_ERR(thread);
+	}
+
+	ret = sched_setscheduler_nocheck(thread, SCHED_FIFO, &param);
+	if (ret) {
+		kthread_stop(thread);
+		pr_warn("%s: failed to set SCHED_FIFO\n", __func__);
+		return ret;
+	}
+
+	sg_policy->thread = thread;
+	kthread_bind_mask(thread, policy->related_cpus);
+	init_irq_work(&sg_policy->irq_work, sugov_irq_work);
+	mutex_init(&sg_policy->work_lock);
+
+	wake_up_process(thread);
+
+	return 0;
+}
+
+static void sugov_kthread_stop(struct sugov_policy *sg_policy)
+{
+	/* kthread only required for slow path */
+	if (sg_policy->policy->fast_switch_enabled)
+		return;
+
+	kthread_flush_worker(&sg_policy->worker);
+	kthread_stop(sg_policy->thread);
+	mutex_destroy(&sg_policy->work_lock);
+}
+
 static struct sugov_tunables *sugov_tunables_alloc(struct sugov_policy *sg_policy)
 {
 	struct sugov_tunables *tunables;
@@ -416,16 +479,24 @@
 	if (policy->governor_data)
 		return -EBUSY;
 
+	cpufreq_enable_fast_switch(policy);
+
 	sg_policy = sugov_policy_alloc(policy);
-	if (!sg_policy)
-		return -ENOMEM;
+	if (!sg_policy) {
+		ret = -ENOMEM;
+		goto disable_fast_switch;
+	}
+
+	ret = sugov_kthread_create(sg_policy);
+	if (ret)
+		goto free_sg_policy;
 
 	mutex_lock(&global_tunables_lock);
 
 	if (global_tunables) {
 		if (WARN_ON(have_governor_per_policy())) {
 			ret = -EINVAL;
-			goto free_sg_policy;
+			goto stop_kthread;
 		}
 		policy->governor_data = sg_policy;
 		sg_policy->tunables = global_tunables;
@@ -437,7 +508,7 @@
 	tunables = sugov_tunables_alloc(sg_policy);
 	if (!tunables) {
 		ret = -ENOMEM;
-		goto free_sg_policy;
+		goto stop_kthread;
 	}
 
 	tunables->rate_limit_us = LATENCY_MULTIPLIER;
@@ -454,20 +525,25 @@
 	if (ret)
 		goto fail;
 
- out:
+out:
 	mutex_unlock(&global_tunables_lock);
-
-	cpufreq_enable_fast_switch(policy);
 	return 0;
 
- fail:
+fail:
 	policy->governor_data = NULL;
 	sugov_tunables_free(tunables);
 
- free_sg_policy:
+stop_kthread:
+	sugov_kthread_stop(sg_policy);
+
+free_sg_policy:
 	mutex_unlock(&global_tunables_lock);
 
 	sugov_policy_free(sg_policy);
+
+disable_fast_switch:
+	cpufreq_disable_fast_switch(policy);
+
 	pr_err("initialization failed (error %d)\n", ret);
 	return ret;
 }
@@ -478,8 +554,6 @@
 	struct sugov_tunables *tunables = sg_policy->tunables;
 	unsigned int count;
 
-	cpufreq_disable_fast_switch(policy);
-
 	mutex_lock(&global_tunables_lock);
 
 	count = gov_attr_set_put(&tunables->attr_set, &sg_policy->tunables_hook);
@@ -489,7 +563,9 @@
 
 	mutex_unlock(&global_tunables_lock);
 
+	sugov_kthread_stop(sg_policy);
 	sugov_policy_free(sg_policy);
+	cpufreq_disable_fast_switch(policy);
 }
 
 static int sugov_start(struct cpufreq_policy *policy)
@@ -502,25 +578,19 @@
 	sg_policy->next_freq = UINT_MAX;
 	sg_policy->work_in_progress = false;
 	sg_policy->need_freq_update = false;
+	sg_policy->cached_raw_freq = 0;
 
 	for_each_cpu(cpu, policy->cpus) {
 		struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu);
 
+		memset(sg_cpu, 0, sizeof(*sg_cpu));
 		sg_cpu->sg_policy = sg_policy;
-		if (policy_is_shared(policy)) {
-			sg_cpu->util = 0;
-			sg_cpu->max = 0;
-			sg_cpu->flags = SCHED_CPUFREQ_RT;
-			sg_cpu->last_update = 0;
-			sg_cpu->cached_raw_freq = 0;
-			sg_cpu->iowait_boost = 0;
-			sg_cpu->iowait_boost_max = policy->cpuinfo.max_freq;
-			cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
-						     sugov_update_shared);
-		} else {
-			cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
-						     sugov_update_single);
-		}
+		sg_cpu->flags = SCHED_CPUFREQ_RT;
+		sg_cpu->iowait_boost_max = policy->cpuinfo.max_freq;
+		cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
+					     policy_is_shared(policy) ?
+							sugov_update_shared :
+							sugov_update_single);
 	}
 	return 0;
 }
@@ -535,8 +605,10 @@
 
 	synchronize_sched();
 
-	irq_work_sync(&sg_policy->irq_work);
-	cancel_work_sync(&sg_policy->work);
+	if (!policy->fast_switch_enabled) {
+		irq_work_sync(&sg_policy->irq_work);
+		kthread_cancel_work_sync(&sg_policy->work);
+	}
 }
 
 static void sugov_limits(struct cpufreq_policy *policy)
diff --git a/mm/Kconfig b/mm/Kconfig
index 0183305..eb10c90 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -720,3 +720,13 @@
 	bool
 config ARCH_HAS_PKEYS
 	bool
+
+config FORCE_ALLOC_FROM_DMA_ZONE
+	bool "Force certain memory allocators to always return ZONE_DMA memory"
+	depends on ZONE_DMA
+	help
+	  Ensure certain memory allocators always return memory from ZONE_DMA.
+	  This option helps ensure that clients who require ZONE_DMA memory are
+	  always using ZONE_DMA memory.
+
+	  If unsure, say "n".
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 9d3f6d3..b4d398b 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2595,16 +2595,23 @@
 				    sc->nr_scanned - nr_scanned,
 				    node_lru_pages);
 
+		/*
+		 * Record the subtree's reclaim efficiency. The reclaimed
+		 * pages from slab is excluded here because the corresponding
+		 * scanned pages is not accounted. Moreover, freeing a page
+		 * by slab shrinking depends on each slab's object population,
+		 * making the cost model (i.e. scan:free) different from that
+		 * of LRU.
+		 */
+		vmpressure(sc->gfp_mask, sc->target_mem_cgroup, true,
+			   sc->nr_scanned - nr_scanned,
+			   sc->nr_reclaimed - nr_reclaimed);
+
 		if (reclaim_state) {
 			sc->nr_reclaimed += reclaim_state->reclaimed_slab;
 			reclaim_state->reclaimed_slab = 0;
 		}
 
-		/* Record the subtree's reclaim efficiency */
-		vmpressure(sc->gfp_mask, sc->target_mem_cgroup, true,
-			   sc->nr_scanned - nr_scanned,
-			   sc->nr_reclaimed - nr_reclaimed);
-
 		if (sc->nr_reclaimed - nr_reclaimed)
 			reclaimable = true;
 
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f0f462c..8de6707 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -209,6 +209,9 @@
 	u8 *data;
 	bool pfmemalloc;
 
+	if (IS_ENABLED(CONFIG_FORCE_ALLOC_FROM_DMA_ZONE))
+		gfp_mask |= GFP_DMA;
+
 	cache = (flags & SKB_ALLOC_FCLONE)
 		? skbuff_fclone_cache : skbuff_head_cache;
 
@@ -367,6 +370,9 @@
 	unsigned long flags;
 	void *data;
 
+	if (IS_ENABLED(CONFIG_FORCE_ALLOC_FROM_DMA_ZONE))
+		gfp_mask |= GFP_DMA;
+
 	local_irq_save(flags);
 	nc = this_cpu_ptr(&netdev_alloc_cache);
 	data = __alloc_page_frag(nc, fragsz, gfp_mask);
diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c
index 51c27b7..b75ba98 100644
--- a/sound/soc/msm/msm8998.c
+++ b/sound/soc/msm/msm8998.c
@@ -5247,7 +5247,6 @@
 		.platform_name = "msm-pcm-hostless",
 		.dynamic = 1,
 		.dpcm_playback = 1,
-		.dpcm_capture = 1,
 		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 			    SND_SOC_DPCM_TRIGGER_POST},
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index 826f566..654806e 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -153,27 +153,27 @@
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct msm_voice *voice;
 
-	if (!strcmp("VoLTE", substream->pcm->id)) {
+	if (!strncmp("VoLTE", substream->pcm->id, 5)) {
 		voice = &voice_info[VOLTE_SESSION_INDEX];
 		pr_debug("%s: Open VoLTE Substream Id=%s\n",
 			 __func__, substream->pcm->id);
-	} else if (!strcmp("Voice2", substream->pcm->id)) {
+	} else if (!strncmp("Voice2", substream->pcm->id, 6)) {
 		voice = &voice_info[VOICE2_SESSION_INDEX];
 		pr_debug("%s: Open Voice2 Substream Id=%s\n",
 			 __func__, substream->pcm->id);
-	} else if (!strcmp("QCHAT", substream->pcm->id)) {
+	} else if (!strncmp("QCHAT", substream->pcm->id, 5)) {
 		voice = &voice_info[QCHAT_SESSION_INDEX];
 		pr_debug("%s: Open QCHAT Substream Id=%s\n",
 			 __func__, substream->pcm->id);
-	} else if (!strcmp("VoWLAN", substream->pcm->id)) {
+	} else if (!strncmp("VoWLAN", substream->pcm->id, 6)) {
 		voice = &voice_info[VOWLAN_SESSION_INDEX];
 		pr_debug("%s: Open VoWLAN Substream Id=%s\n",
 			 __func__, substream->pcm->id);
-	} else if (!strcmp("VoiceMMode1", substream->pcm->id)) {
+	} else if (!strncmp("VoiceMMode1", substream->pcm->id, 11)) {
 		voice = &voice_info[VOICEMMODE1_INDEX];
 		pr_debug("%s: Open VoiceMMode1 Substream Id=%s\n",
 			 __func__, substream->pcm->id);
-	} else if (!strcmp("VoiceMMode2", substream->pcm->id)) {
+	} else if (!strncmp("VoiceMMode2", substream->pcm->id, 11)) {
 		voice = &voice_info[VOICEMMODE2_INDEX];
 		pr_debug("%s: Open VoiceMMode2 Substream Id=%s\n",
 			 __func__, substream->pcm->id);
diff --git a/sound/soc/msm/sdm660-ext-dai-links.c b/sound/soc/msm/sdm660-ext-dai-links.c
index f64074d..1c03d8c 100644
--- a/sound/soc/msm/sdm660-ext-dai-links.c
+++ b/sound/soc/msm/sdm660-ext-dai-links.c
@@ -335,7 +335,6 @@
 		.platform_name = "msm-pcm-hostless",
 		.dynamic = 1,
 		.dpcm_playback = 1,
-		.dpcm_capture = 1,
 		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
 			    SND_SOC_DPCM_TRIGGER_POST},
 		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
diff --git a/sound/soc/msm/sdm845.c b/sound/soc/msm/sdm845.c
index 96f3f85..2b8c9c7 100644
--- a/sound/soc/msm/sdm845.c
+++ b/sound/soc/msm/sdm845.c
@@ -397,7 +397,8 @@
 					"KHZ_88P2", "KHZ_96", "KHZ_176P4",
 					"KHZ_192", "KHZ_352P8", "KHZ_384"};
 static char const *ext_disp_sample_rate_text[] = {"KHZ_48", "KHZ_96",
-						  "KHZ_192"};
+						"KHZ_192", "KHZ_32", "KHZ_44P1",
+						"KHZ_88P2", "KHZ_176P4"	};
 static char const *tdm_ch_text[] = {"One", "Two", "Three", "Four",
 				    "Five", "Six", "Seven", "Eight"};
 static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S32_LE"};
@@ -1466,6 +1467,22 @@
 		return idx;
 
 	switch (ext_disp_rx_cfg[idx].sample_rate) {
+	case SAMPLING_RATE_176P4KHZ:
+		sample_rate_val = 6;
+		break;
+
+	case SAMPLING_RATE_88P2KHZ:
+		sample_rate_val = 5;
+		break;
+
+	case SAMPLING_RATE_44P1KHZ:
+		sample_rate_val = 4;
+		break;
+
+	case SAMPLING_RATE_32KHZ:
+		sample_rate_val = 3;
+		break;
+
 	case SAMPLING_RATE_192KHZ:
 		sample_rate_val = 2;
 		break;
@@ -1496,6 +1513,18 @@
 		return idx;
 
 	switch (ucontrol->value.integer.value[0]) {
+	case 6:
+		ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_176P4KHZ;
+		break;
+	case 5:
+		ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_88P2KHZ;
+		break;
+	case 4:
+		ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_44P1KHZ;
+		break;
+	case 3:
+		ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_32KHZ;
+		break;
 	case 2:
 		ext_disp_rx_cfg[idx].sample_rate = SAMPLING_RATE_192KHZ;
 		break;