Merge "UPSTREAM: Merge remote-tracking branch 'quic/dev/msm-4.9-camx' into msm-4.9 - 092117"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index bc82bdc..765b5e4 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -92,6 +92,12 @@
 - SDM670
   compatible = "qcom,sdm670"
 
+- QCS605
+  compatible = "qcom,qcs605"
+
+- SDA670
+  compatible = "qcom,sda670"
+
 - MSM8952
   compatible = "qcom,msm8952"
 
@@ -276,6 +282,10 @@
 compatible = "qcom,sdm670-rumi"
 compatible = "qcom,sdm670-cdp"
 compatible = "qcom,sdm670-mtp"
+compatible = "qcom,qcs605-cdp"
+compatible = "qcom,qcs605-mtp"
+compatible = "qcom,sda670-cdp"
+compatible = "qcom,sda670-mtp"
 compatible = "qcom,msm8952-rumi"
 compatible = "qcom,msm8952-sim"
 compatible = "qcom,msm8952-qrd"
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8953-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8953-pinctrl.txt
new file mode 100644
index 0000000..d4bf1ce
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8953-pinctrl.txt
@@ -0,0 +1,210 @@
+Qualcomm MSM8953 TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+MSM8953 platform.
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be "qcom,msm8953-pinctrl"
+
+- reg:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: the base address and size of the TLMM register space.
+
+- interrupts:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: should specify the TLMM summary IRQ.
+
+- interrupt-controller:
+	Usage: required
+	Value type: <none>
+	Definition: identifies this node as an interrupt controller
+
+- #interrupt-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 2. Specifying the pin number and flags, as defined
+		    in <dt-bindings/interrupt-controller/irq.h>
+
+- gpio-controller:
+	Usage: required
+	Value type: <none>
+	Definition: identifies this node as a gpio controller
+
+- #gpio-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 2. Specifying the pin number and flags, as defined
+		    in <dt-bindings/gpio/gpio.h>
+
+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
+a general description of GPIO and interrupt bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, drive strength, etc.
+
+
+PIN CONFIGURATION NODES:
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pin configuration subnode:
+
+- pins:
+	Usage: required
+	Value type: <string-array>
+	Definition: List of gpio pins affected by the properties specified in
+		    this subnode.
+		    Valid pins are:
+		    gpio0-gpio141,
+		    sdc1_clk,
+		    sdc1_cmd,
+		    sdc1_data,
+		    sdc1_rclk,
+		    sdc2_clk,
+		    sdc2_cmd,
+		    sdc2_data,
+		    qdsd_cmd,
+		    qdsd_data0,
+		    qdsd_data1,
+		    qdsd_data2,
+		    qdsd_data3
+
+- function:
+	Usage: required
+	Value type: <string>
+	Definition: Specify the alternative function to be configured for the
+		    specified pins. Functions are only valid for gpio pins.
+		    Valid values are:
+	gpio, blsp_spi1, smb_int, adsp_ext, prng_rosc, blsp_i2c1,
+	qdss_cti_trig_out_b0, qdss_cti_trig_out_a1, blsp_spi2, blsp_uart2,
+	ldo_update, dac_calib0, ldo_en, blsp_i2c2, gcc_gp1_clk_b,
+	atest_gpsadc_dtest0_native, blsp_spi3, qdss_tracedata_b,
+	pwr_modem_enabled_b, blsp_i2c3, gcc_gp2_clk_b, gcc_gp3_clk_b, hall_int,
+	blsp_spi4, blsp_uart4, pwr_nav_enabled_b, dac_calib1, cap_int,
+	pwr_crypto_enabled_b, dac_calib2, blsp_i2c4, nfc_disable, blsp_spi5,
+	blsp_uart5, qdss_traceclk_a, atest_bbrx1, nfc_irq, m_voc,
+	qdss_cti_trig_in_a0, atest_bbrx0, blsp_i2c5, qdss_tracectl_a,
+	atest_gpsadc_dtest1_native, qdss_tracedata_a, blsp_spi6, blsp_uart6,
+	qdss_tracectl_b, dac_calib15, qdss_cti_trig_in_b0, dac_calib16, blsp_i2c6,
+	qdss_traceclk_b, atest_wlan0, atest_wlan1, mdp_vsync, pri_mi2s_mclk_a,
+	sec_mi2s_mclk_a, qdss_cti_trig_out_b1, cam_mclk, dac_calib3, cci_i2c,
+	pwr_modem_enabled_a, dac_calib4, dac_calib19, flash_strobe, cci_timer0,
+	cci_timer1, cam_irq, cci_timer2, blsp1_spi, pwr_nav_enabled_a, ois_sync,
+	cci_timer3, cci_timer4, blsp3_spi, qdss_cti_trig_out_a0, dac_calib7,
+	accel_int, gcc_gp1_clk_a, dac_calib8, alsp_int, gcc_gp2_clk_a, dac_calib9,
+	mag_int, gcc_gp3_clk_a, pwr_crypto_enabled_a, cci_async, cam1_standby,
+	dac_calib5, cam1_rst, dac_calib6, dac_calib10, gyro_int, dac_calib11,
+	pressure_int, dac_calib12, blsp6_spi, dac_calib13, fp_int,
+	qdss_cti_trig_in_b1, dac_calib14, uim_batt, cam0_ldo, sd_write, uim1_data,
+	uim1_clk, uim1_reset, uim1_present, uim2_data, uim2_clk, uim2_reset,
+	uim2_present, ts_xvdd, mipi_dsi0, nfc_dwl, us_euro, atest_char3, dbg_out,
+	bimc_dte0, ts_resout, ts_sample, sec_mi2s_mclk_b, pri_mi2s, codec_reset,
+	cdc_pdm0, atest_char1, ebi_cdc, dac_calib17, us_emitter, atest_char0,
+	pri_mi2s_mclk_b, lpass_slimbus, lpass_slimbus0, lpass_slimbus1, codec_int1,
+	codec_int2, wcss_bt, atest_char2, ebi_ch0, wcss_wlan2, wcss_wlan1,
+	wcss_wlan0, wcss_wlan, wcss_fm, ext_lpass, mss_lte, key_volp, pbs0,
+	cri_trng0, key_snapshot, pbs1, cri_trng1, key_focus, pbs2, cri_trng,
+	gcc_tlmm, key_home, pwr_down, dmic0_clk, blsp7_spi, hdmi_int, dmic0_data,
+	qdss_cti_trig_in_a1, pri_mi2s_ws, wsa_io, wsa_en, blsp_spi8, wsa_irq,
+	blsp_i2c8, gcc_plltest, nav_pps_in_a, pa_indicator, nav_pps_in_b, nav_pps,
+	modem_tsync, nav_tsync, ssbi_wtr1, gsm1_tx, dac_calib18, gsm0_tx,
+	atest_char, atest_tsens, bimc_dte1, dac_calib20, cam2_rst, ddr_bist,
+	dac_calib21, cam2_standby, dac_calib22, cam3_rst, dac_calib23,
+	cam3_standby, dac_calib24, sdcard_det, dac_calib25, cam1_ldo, sec_mi2s,
+	blsp_spi7, blsp_i2c7, ss_switch, tsens_max
+
+- bias-disable:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as no pull.
+
+- bias-pull-down:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as pull down.
+
+- bias-pull-up:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as pull up.
+
+- output-high:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins are configured in output mode, driven
+		    high.
+		    Not valid for sdc pins.
+
+- output-low:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins are configured in output mode, driven
+		    low.
+		    Not valid for sdc pins.
+
+- drive-strength:
+	Usage: optional
+	Value type: <u32>
+	Definition: Selects the drive strength for the specified pins, in mA.
+		    Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
+
+Example:
+
+	tlmm: pinctrl@1000000 {
+		compatible = "qcom,msm8953-pinctrl";
+		reg = <0x1000000 0x300000>;
+		interrupts = <0 208 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		pmx-uartconsole {
+			uart_console_active: uart_console_active {
+				mux {
+					pins = "gpio4", "gpio5";
+					function = "blsp_uart2";
+				};
+
+				config {
+					pins = "gpio4", "gpio5";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			uart_console_sleep: uart_console_sleep {
+				mux {
+					pins = "gpio4", "gpio5";
+					function = "blsp_uart2";
+				};
+
+				config {
+					pins = "gpio4", "gpio5";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+
+		};
+	};
diff --git a/Makefile b/Makefile
index a8d289a..155351a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 9
-SUBLEVEL = 48
+SUBLEVEL = 50
 EXTRAVERSION =
 NAME = Roaring Lionus
 
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-smp2p.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-smp2p.dtsi
new file mode 100644
index 0000000..f9ad6f4
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-smp2p.dtsi
@@ -0,0 +1,109 @@
+/* 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.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+&soc {
+	qcom,smp2p-modem@17811008 {
+		compatible = "qcom,smp2p";
+		reg = <0x17811008 0x4>;
+		qcom,remote-pid = <1>;
+		qcom,irq-bitmask = <0x4000>;
+		interrupts = <GIC_SPI 113 IRQ_TYPE_EDGE_RISING>;
+	};
+
+	smp2pgpio_smp2p_15_in: qcom,smp2pgpio-smp2p-15-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <15>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_15_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_15_in";
+		gpios = <&smp2pgpio_smp2p_15_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_15_out: qcom,smp2pgpio-smp2p-15-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <15>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_15_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_15_out";
+		gpios = <&smp2pgpio_smp2p_15_out 0 0>;
+	};
+
+	smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+		gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+		gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+	};
+
+	/* ssr - inbound entry from mss */
+	smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "slave-kernel";
+		qcom,remote-pid = <1>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	/* ssr - outbound entry to mss */
+	smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "master-kernel";
+		qcom,remote-pid = <1>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+};
+
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index 2ef277f..d538efe 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -34,6 +34,13 @@
 			reg = <0x8fd00000 0x300000>;
 			label = "peripheral2_mem";
 		};
+
+		mss_mem: mss_region@87800000 {
+			compatible = "removed-dma-pool";
+			no-map;
+			reg = <0x87800000 0x8000000>;
+			label = "mss_mem";
+		};
 	};
 
 	cpus {
@@ -324,8 +331,134 @@
 		#interrupt-cells = <4>;
 		cell-index = <0>;
 	};
+
+	qcom,ipc-spinlock@1f40000 {
+		compatible = "qcom,ipc-spinlock-sfpb";
+		reg = <0x1f40000 0x8000>;
+		qcom,num-locks = <8>;
+	};
+
+	qcom,smem@8fe40000 {
+		compatible = "qcom,smem";
+		reg = <0x8fe40000 0xc0000>,
+			<0x17811008 0x4>,
+			<0x1fd4000 0x8>;
+		reg-names = "smem", "irq-reg-base",
+			"smem_targ_info_reg";
+		qcom,mpu-enabled;
+	};
+
+	qcom,glink-smem-native-xprt-modem@8fe40000 {
+		compatible = "qcom,glink-smem-native-xprt";
+		reg = <0x8fe40000 0xc0000>,
+			<0x17811008 0x4>;
+		reg-names = "smem", "irq-reg-base";
+		qcom,irq-mask = <0x1000>;
+		interrupts = <GIC_SPI 111 IRQ_TYPE_EDGE_RISING>;
+		label = "mpss";
+	};
+
+	qcom,ipc_router {
+		compatible = "qcom,ipc_router";
+		qcom,node-id = <1>;
+	};
+
+	qcom,ipc_router_modem_xprt {
+		compatible = "qcom,ipc_router_glink_xprt";
+		qcom,ch-name = "IPCRTR";
+		qcom,xprt-remote = "mpss";
+		qcom,glink-xprt = "smem";
+		qcom,xprt-linkid = <1>;
+		qcom,xprt-version = <1>;
+		qcom,fragmented-data;
+	};
+
+	qcom,glink_pkt {
+		compatible = "qcom,glinkpkt";
+
+		qcom,glinkpkt-at-mdm0 {
+			qcom,glinkpkt-transport = "smem";
+			qcom,glinkpkt-edge = "mpss";
+			qcom,glinkpkt-ch-name = "DS";
+			qcom,glinkpkt-dev-name = "at_mdm0";
+		};
+
+		qcom,glinkpkt-loopback_cntl {
+			qcom,glinkpkt-transport = "lloop";
+			qcom,glinkpkt-edge = "local";
+			qcom,glinkpkt-ch-name = "LOCAL_LOOPBACK_CLNT";
+			qcom,glinkpkt-dev-name = "glink_pkt_loopback_ctrl";
+		};
+
+		qcom,glinkpkt-loopback_data {
+			qcom,glinkpkt-transport = "lloop";
+			qcom,glinkpkt-edge = "local";
+			qcom,glinkpkt-ch-name = "glink_pkt_lloop_CLNT";
+			qcom,glinkpkt-dev-name = "glink_pkt_loopback";
+		};
+
+		qcom,glinkpkt-data40-cntl {
+			qcom,glinkpkt-transport = "smem";
+			qcom,glinkpkt-edge = "mpss";
+			qcom,glinkpkt-ch-name = "DATA40_CNTL";
+			qcom,glinkpkt-dev-name = "smdcntl8";
+		};
+
+		qcom,glinkpkt-data1 {
+			qcom,glinkpkt-transport = "smem";
+			qcom,glinkpkt-edge = "mpss";
+			qcom,glinkpkt-ch-name = "DATA1";
+			qcom,glinkpkt-dev-name = "smd7";
+		};
+
+		qcom,glinkpkt-data4 {
+			qcom,glinkpkt-transport = "smem";
+			qcom,glinkpkt-edge = "mpss";
+			qcom,glinkpkt-ch-name = "DATA4";
+			qcom,glinkpkt-dev-name = "smd8";
+		};
+
+		qcom,glinkpkt-data11 {
+			qcom,glinkpkt-transport = "smem";
+			qcom,glinkpkt-edge = "mpss";
+			qcom,glinkpkt-ch-name = "DATA11";
+			qcom,glinkpkt-dev-name = "smd11";
+		};
+	};
+
+	pil_modem: qcom,mss@4080000 {
+		compatible = "qcom,pil-tz-generic";
+		reg = <0x4080000 0x100>;
+		interrupts = <0 250 1>;
+
+		clocks = <&clock_rpmh RPMH_CXO_CLK>;
+		clock-names = "xo";
+		qcom,proxy-clock-names = "xo";
+
+		vdd_cx-supply = <&pmxpoorwills_s5_level>;
+		qcom,proxy-reg-names = "vdd_cx";
+
+		qcom,pas-id = <0>;
+		qcom,smem-id = <421>;
+		qcom,proxy-timeout-ms = <10000>;
+		qcom,sysmon-id = <0>;
+		qcom,ssctl-instance-id = <0x12>;
+		qcom,firmware-name = "modem";
+		memory-region = <&mss_mem>;
+		status = "ok";
+
+		/* GPIO inputs from mss */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
+		qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_1_in 3 0>;
+
+		/* GPIO output to mss */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
+	};
 };
 
 #include "pmxpoorwills.dtsi"
 #include "sdxpoorwills-regulator.dtsi"
+#include "sdxpoorwills-smp2p.dtsi"
 #include "sdxpoorwills-usb.dtsi"
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index bde40e0..1826b6f 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -195,6 +195,7 @@
 CONFIG_INPUT_GPIO=m
 CONFIG_SERIO_LIBPS2=y
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -280,10 +281,15 @@
 CONFIG_QCOM_SCM=y
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_MSM_SMEM=y
+CONFIG_MSM_GLINK=y
+CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
+CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
 CONFIG_TRACER_PKT=y
 CONFIG_MSM_SMP2P=y
 CONFIG_MSM_SMP2P_TEST=y
+CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
 CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_GLINK_PKT=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_PIL=y
 CONFIG_MSM_PIL_SSR_GENERIC=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index 24ae9bd..ce61464 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -189,6 +189,7 @@
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_DIAG_CHAR=y
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -204,6 +205,7 @@
 CONFIG_POWER_SUPPLY=y
 CONFIG_THERMAL=y
 CONFIG_THERMAL_TSENS=y
+CONFIG_MFD_SYSCON=y
 CONFIG_MSM_CDC_PINCTRL=y
 CONFIG_MSM_CDC_SUPPLY=y
 CONFIG_REGULATOR=y
@@ -272,14 +274,20 @@
 CONFIG_IPA_UT=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_NDP_BAM=y
-CONFIG_HWSPINLOCK_QCOM=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
 CONFIG_MAILBOX=y
-CONFIG_QCOM_SMEM=y
-CONFIG_QCOM_SMD=y
 CONFIG_QCOM_SCM=y
 CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_SMEM=y
+CONFIG_MSM_GLINK=y
+CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
+CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
 CONFIG_TRACER_PKT=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_SMP2P_TEST=y
+CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
 CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_GLINK_PKT=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_PIL=y
 CONFIG_MSM_PIL_SSR_GENERIC=y
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index aec74bf..a9ef54d 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -314,8 +314,11 @@
 	 * signal first. We do not need to release the mmap_sem because
 	 * it would already be released in __lock_page_or_retry in
 	 * mm/filemap.c. */
-	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) {
+		if (!user_mode(regs))
+			goto no_context;
 		return 0;
+	}
 
 	/*
 	 * Major/minor page fault accounting is only done on the
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index f96fba6..e1454fb 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -139,6 +139,15 @@
 	  This enables support for the SDM670 chipset. If you do not
 	  wish to build a kernel that runs on this chipset, say 'N' here.
 
+config ARCH_MSM8953
+	bool "Enable Support for Qualcomm Technologies Inc. MSM8953"
+	depends on ARCH_QCOM
+	select COMMON_CLK_QCOM
+	select QCOM_GDSC
+	help
+	  This enables support for the MSM8953 chipset. If you do not
+	  wish to build a kernel that runs on this chipset, say 'N' here.
+
 config ARCH_ROCKCHIP
 	bool "Rockchip Platforms"
 	select ARCH_HAS_RESET_CONTROLLER
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index 49a5d8c..68e6f88 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -170,6 +170,7 @@
 				interrupt-controller;
 				reg = <0x1d00000 0x10000>, /* GICD */
 				      <0x1d40000 0x40000>; /* GICR */
+				interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
 			};
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 779ace6..276e09c 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -92,7 +92,14 @@
 		sdm670-usbc-external-codec-cdp-overlay.dtbo \
 		sdm670-usbc-external-codec-mtp-overlay.dtbo \
 		sdm670-usbc-external-codec-pm660a-cdp-overlay.dtbo \
-		sdm670-usbc-external-codec-pm660a-mtp-overlay.dtbo
+		sdm670-usbc-external-codec-pm660a-mtp-overlay.dtbo \
+		sda670-cdp-overlay.dtbo \
+		sda670-mtp-overlay.dtbo \
+		sda670-pm660a-cdp-overlay.dtbo \
+		sda670-pm660a-mtp-overlay.dtbo \
+		qcs605-cdp-overlay.dtbo \
+		qcs605-mtp-overlay.dtbo \
+		qcs605-external-codec-mtp-overlay.dtbo
 
 sdm670-cdp-overlay.dtbo-base := sdm670.dtb
 sdm670-mtp-overlay.dtbo-base := sdm670.dtb
@@ -111,6 +118,14 @@
 sdm670-usbc-external-codec-mtp-overlay.dtbo-base := sdm670.dtb
 sdm670-usbc-external-codec-pm660a-cdp-overlay.dtbo-base := sdm670.dtb
 sdm670-usbc-external-codec-pm660a-mtp-overlay.dtbo-base := sdm670.dtb
+sda670-cdp-overlay.dtbo-base := sda670.dtb
+sda670-mtp-overlay.dtbo-base := sda670.dtb
+sda670-pm660a-cdp-overlay.dtbo-base := sda670.dtb
+sda670-pm660a-mtp-overlay.dtbo-base := sda670.dtb
+qcs605-cdp-overlay.dtbo-base := qcs605.dtb
+qcs605-mtp-overlay.dtbo-base := qcs605.dtb
+qcs605-external-codec-mtp-overlay.dtbo-base := qcs605.dtb
+
 else
 dtb-$(CONFIG_ARCH_SDM670) += sdm670-rumi.dtb \
 	sdm670-mtp.dtb \
@@ -128,7 +143,14 @@
 	sdm670-usbc-external-codec-pm660a-mtp.dtb \
 	sdm670-usbc-mtp.dtb \
 	sdm670-usbc-pm660a-cdp.dtb \
-	sdm670-usbc-pm660a-mtp.dtb
+	sdm670-usbc-pm660a-mtp.dtb \
+	sda670-mtp.dtb \
+	sda670-cdp.dtb \
+	sda670-pm660a-mtp.dtb \
+	sda670-pm660a-cdp.dtb \
+	qcs605-mtp.dtb \
+	qcs605-cdp.dtb \
+	qcs605-external-codec-mtp.dtb
 endif
 
 always		:= $(dtb-y)
diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi
index 80103cb..1fdb3f6 100644
--- a/arch/arm64/boot/dts/qcom/pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660.dtsi
@@ -353,15 +353,6 @@
 			};
 		};
 
-		pm660_rradc: rradc@4500 {
-			compatible = "qcom,rradc";
-			reg = <0x4500 0x100>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			#io-channel-cells = <1>;
-			qcom,pmic-revid = <&pm660_revid>;
-		};
-
 		bcl_sensor: bcl@4200 {
 			compatible = "qcom,msm-bcl-lmh";
 			reg = <0x4200 0xff>,
diff --git a/arch/arm64/boot/dts/qcom/qcs605-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-cdp-overlay.dts
new file mode 100644
index 0000000..fe7a027
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-cdp-overlay.dts
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS605 PM660 + PM660L CDP";
+	compatible = "qcom,qcs605-cdp", "qcom,qcs605", "qcom,cdp";
+	qcom,msm-id = <347 0x0>;
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-cdp.dts b/arch/arm64/boot/dts/qcom/qcs605-cdp.dts
new file mode 100644
index 0000000..7b38a58
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-cdp.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "qcs605.dtsi"
+#include "sdm670-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS605 PM660 + PM660L CDP";
+	compatible = "qcom,qcs605-cdp", "qcom,qcs605", "qcom,cdp";
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp-overlay.dts
new file mode 100644
index 0000000..1f439ae
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp-overlay.dts
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS605 PM660 + PM660L Ext. Audio Codec MTP";
+	compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
+	qcom,msm-id = <347 0x0>;
+	qcom,board-id = <8 1>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp.dts b/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp.dts
new file mode 100644
index 0000000..abc3f2d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "qcs605.dtsi"
+#include "sdm670-mtp.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS605 PM660 + PM660L Ext. Audio Codec MTP";
+	compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
+	qcom,board-id = <8 1>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-mtp-overlay.dts
new file mode 100644
index 0000000..7327440
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-mtp-overlay.dts
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS605 PM660 + PM660L MTP";
+	compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
+	qcom,msm-id = <347 0x0>;
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-mtp.dts b/arch/arm64/boot/dts/qcom/qcs605-mtp.dts
new file mode 100644
index 0000000..bc7b376
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-mtp.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "qcs605.dtsi"
+#include "sdm670-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS605 PM660 + PM660L MTP";
+	compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dts b/arch/arm64/boot/dts/qcom/qcs605.dts
new file mode 100644
index 0000000..28c417f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "qcs605.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS605 SoC";
+	compatible = "qcom,qcs605";
+	qcom,board-id = <0 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi
new file mode 100644
index 0000000..12da650
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+#include "sda670.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS605";
+	qcom,msm-id = <347 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sda670-cdp-overlay.dts
new file mode 100644
index 0000000..141ed59
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda670-cdp-overlay.dts
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA670 PM660 + PM660L CDP";
+	compatible = "qcom,sda670-cdp", "qcom,sda670", "qcom,cdp";
+	qcom,msm-id = <337 0x0>;
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670-cdp.dts b/arch/arm64/boot/dts/qcom/sda670-cdp.dts
new file mode 100644
index 0000000..fcb340e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda670-cdp.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sda670.dtsi"
+#include "sdm670-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA670 PM660 + PM660L CDP";
+	compatible = "qcom,sda670-cdp", "qcom,sda670", "qcom,cdp";
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sda670-mtp-overlay.dts
new file mode 100644
index 0000000..af8e8f1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda670-mtp-overlay.dts
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA670 PM660 + PM660L MTP";
+	compatible = "qcom,sda670-mtp", "qcom,sda670", "qcom,mtp";
+	qcom,msm-id = <337 0x0>;
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670-mtp.dts b/arch/arm64/boot/dts/qcom/sda670-mtp.dts
new file mode 100644
index 0000000..2123b44
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda670-mtp.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sda670.dtsi"
+#include "sdm670-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA670 PM660 + PM660L MTP";
+	compatible = "qcom,sda670-mtp", "qcom,sda670", "qcom,mtp";
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670-pm660a-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sda670-pm660a-cdp-overlay.dts
new file mode 100644
index 0000000..3e1365d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda670-pm660a-cdp-overlay.dts
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA670 PM660 + PM660A CDP";
+	compatible = "qcom,sda670-cdp", "qcom,sda670", "qcom,cdp";
+	qcom,msm-id = <337 0x0>;
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670-pm660a-cdp.dts b/arch/arm64/boot/dts/qcom/sda670-pm660a-cdp.dts
new file mode 100644
index 0000000..6cbf224
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda670-pm660a-cdp.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sda670.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA670 PM660 + PM660A CDP";
+	compatible = "qcom,sda670-cdp", "qcom,sda670", "qcom,cdp";
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670-pm660a-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sda670-pm660a-mtp-overlay.dts
new file mode 100644
index 0000000..9855b11
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda670-pm660a-mtp-overlay.dts
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-mtp.dtsi"
+#include "pm660a.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA670 PM660 + PM660A MTP";
+	compatible = "qcom,sda670-mtp", "qcom,sda670", "qcom,mtp";
+	qcom,msm-id = <337 0x0>;
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670-pm660a-mtp.dts b/arch/arm64/boot/dts/qcom/sda670-pm660a-mtp.dts
new file mode 100644
index 0000000..ffb6aa3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda670-pm660a-mtp.dts
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sda670.dtsi"
+#include "sdm670-mtp.dtsi"
+#include "pm660a.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA670 PM660 + PM660A MTP";
+	compatible = "qcom,sda670-mtp", "qcom,sda670", "qcom,mtp";
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670.dts b/arch/arm64/boot/dts/qcom/sda670.dts
new file mode 100644
index 0000000..8852e30
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda670.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sda670.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA670 SoC";
+	compatible = "qcom,sda670";
+	qcom,board-id = <0 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670.dtsi b/arch/arm64/boot/dts/qcom/sda670.dtsi
new file mode 100644
index 0000000..d19aac3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda670.dtsi
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+#include "sdm670.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA670";
+	qcom,msm-id = <337 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi
new file mode 100644
index 0000000..94ac27d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi
@@ -0,0 +1,375 @@
+/*
+ * 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.
+ */
+#include "sdm670-wcd.dtsi"
+#include "sdm670-wsa881x.dtsi"
+#include <dt-bindings/clock/qcom,audio-ext-clk.h>
+
+&tavil_snd {
+	qcom,msm-mi2s-master = <1>, <1>, <1>, <1>;
+	qcom,audio-routing =
+		"AIF4 VI", "MCLK",
+		"RX_BIAS", "MCLK",
+		"MADINPUT", "MCLK",
+		"hifi amp", "LINEOUT1",
+		"hifi amp", "LINEOUT2",
+		"AMIC2", "MIC BIAS2",
+		"MIC BIAS2", "Headset Mic",
+		"AMIC3", "MIC BIAS2",
+		"MIC BIAS2", "ANCRight Headset Mic",
+		"AMIC4", "MIC BIAS2",
+		"MIC BIAS2", "ANCLeft Headset Mic",
+		"AMIC5", "MIC BIAS3",
+		"MIC BIAS3", "Handset Mic",
+		"DMIC0", "MIC BIAS1",
+		"MIC BIAS1", "Digital Mic0",
+		"DMIC1", "MIC BIAS1",
+		"MIC BIAS1", "Digital Mic1",
+		"DMIC2", "MIC BIAS3",
+		"MIC BIAS3", "Digital Mic2",
+		"DMIC3", "MIC BIAS3",
+		"MIC BIAS3", "Digital Mic3",
+		"DMIC4", "MIC BIAS4",
+		"MIC BIAS4", "Digital Mic4",
+		"DMIC5", "MIC BIAS4",
+		"MIC BIAS4", "Digital Mic5",
+		"SpkrLeft IN", "SPK1 OUT",
+		"SpkrRight IN", "SPK2 OUT";
+
+	qcom,msm-mbhc-hphl-swh = <1>;
+	qcom,msm-mbhc-gnd-swh = <1>;
+	qcom,hph-en0-gpio = <&tavil_hph_en0>;
+	qcom,hph-en1-gpio = <&tavil_hph_en1>;
+	qcom,msm-mclk-freq = <9600000>;
+	qcom,usbc-analog-en1_gpio = <&wcd_usbc_analog_en1_gpio>;
+	asoc-codec = <&stub_codec>;
+	asoc-codec-names = "msm-stub-codec.1";
+	qcom,wsa-max-devs = <2>;
+	qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0212>,
+		<&wsa881x_0213>, <&wsa881x_0214>;
+	qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+		"SpkrLeft", "SpkrRight";
+};
+
+&int_codec {
+	qcom,audio-routing =
+		"RX_BIAS", "INT_MCLK0",
+		"SPK_RX_BIAS", "INT_MCLK0",
+		"INT_LDO_H", "INT_MCLK0",
+		"MIC BIAS External", "Handset Mic",
+		"MIC BIAS External2", "Headset Mic",
+		"MIC BIAS External", "Secondary Mic",
+		"AMIC1", "MIC BIAS External",
+		"AMIC2", "MIC BIAS External2",
+		"AMIC3", "MIC BIAS External",
+		"DMIC1", "MIC BIAS External",
+		"MIC BIAS External", "Digital Mic1",
+		"DMIC2", "MIC BIAS External",
+		"MIC BIAS External", "Digital Mic2",
+		"DMIC3", "MIC BIAS External",
+		"MIC BIAS External", "Digital Mic3",
+		"DMIC4", "MIC BIAS External",
+		"MIC BIAS External", "Digital Mic4",
+		"SpkrLeft IN", "SPK1 OUT",
+		"SpkrRight IN", "SPK2 OUT",
+		"PDM_IN_RX1", "PDM_OUT_RX1",
+		"PDM_IN_RX2", "PDM_OUT_RX2",
+		"PDM_IN_RX3", "PDM_OUT_RX3",
+		"ADC1_IN", "ADC1_OUT",
+		"ADC2_IN", "ADC2_OUT",
+		"ADC3_IN", "ADC3_OUT";
+
+	qcom,msm-mi2s-master = <1>, <1>, <1>, <1>;
+	qcom,msm-mclk-freq = <9600000>;
+	qcom,msm-mbhc-hphl-swh = <1>;
+	qcom,msm-mbhc-gnd-swh = <1>;
+	qcom,msm-micbias2-ext-cap;
+	qcom,msm-hs-micbias-type = "external";
+	qcom,cdc-pdm-gpios = <&cdc_pdm_gpios>;
+	qcom,cdc-comp-gpios = <&cdc_comp_gpios>;
+	qcom,cdc-dmic-gpios = <&cdc_dmic_gpios>;
+
+	asoc-codec = <&stub_codec>, <&msm_digital_codec>,
+		     <&pmic_analog_codec>, <&msm_sdw_codec>;
+	asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+			   "analog-codec", "msm_sdw_codec";
+
+	qcom,wsa-max-devs = <2>;
+	qcom,wsa-devs = <&wsa881x_211_en>, <&wsa881x_212_en>,
+			<&wsa881x_213_en>, <&wsa881x_214_en>;
+	qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+				  "SpkrLeft", "SpkrRight";
+};
+
+&soc {
+	wcd_usbc_analog_en1_gpio: msm_cdc_pinctrl_usbc_audio_en1 {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&wcd_usbc_analog_en1_active>;
+		pinctrl-1 = <&wcd_usbc_analog_en1_idle>;
+	};
+
+	cdc_pdm_gpios: cdc_pdm_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_pdm_clk_active &cdc_pdm_sync_active
+			     &cdc_pdm_rx0_active &cdc_pdm_rx1_2_active
+			     &cdc_pdm_2_gpios_active>;
+		pinctrl-1 = <&cdc_pdm_clk_sleep &cdc_pdm_sync_sleep
+			     &cdc_pdm_rx0_sleep &cdc_pdm_rx1_2_sleep
+			     &cdc_pdm_2_gpios_sleep>;
+		qcom,lpi-gpios;
+	};
+
+	cdc_comp_gpios: cdc_comp_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_rx0_comp_active &cdc_rx1_comp_active>;
+		pinctrl-1 = <&cdc_rx0_comp_sleep &cdc_rx1_comp_sleep>;
+		qcom,lpi-gpios;
+	};
+
+	cdc_dmic_gpios: cdc_dmic_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_dmic12_gpios_active
+			     &cdc_dmic34_gpios_active>;
+		pinctrl-1 = <&cdc_dmic12_gpios_sleep
+			     &cdc_dmic34_gpios_sleep>;
+		qcom,lpi-gpios;
+	};
+
+	cdc_sdw_gpios: sdw_clk_data_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&sdw_clk_active &sdw_data_active>;
+		pinctrl-1 = <&sdw_clk_sleep &sdw_data_sleep>;
+	};
+
+	wsa_spkr_en1: wsa_spkr_en1_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&spkr_1_sd_n_active>;
+		pinctrl-1 = <&spkr_1_sd_n_sleep>;
+	};
+
+	wsa_spkr_en2: wsa_spkr_en2_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&spkr_2_sd_n_active>;
+		pinctrl-1 = <&spkr_2_sd_n_sleep>;
+	};
+
+	msm_sdw_codec: msm-sdw-codec@62ec1000 {
+		status = "okay";
+		compatible = "qcom,msm-sdw-codec";
+		reg = <0x62ec1000 0x0>;
+		interrupts = <0 161 0>;
+		interrupt-names = "swr_master_irq";
+		qcom,cdc-sdw-gpios = <&cdc_sdw_gpios>;
+
+		swr_master {
+			compatible = "qcom,swr-wcd";
+			#address-cells = <2>;
+			#size-cells = <0>;
+
+			wsa881x_211_en: wsa881x_en@20170211 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x20170211>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_en1>;
+			};
+
+			wsa881x_212_en: wsa881x_en@20170212 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x20170212>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_en2>;
+			};
+
+			wsa881x_213_en: wsa881x_en@21170213 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x21170213>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_en1>;
+			};
+
+			wsa881x_214_en: wsa881x_en@21170214 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x21170214>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_en2>;
+			};
+		};
+	};
+
+	wcd9xxx_intc: wcd9xxx-irq {
+		status = "disabled";
+		compatible = "qcom,wcd9xxx-irq";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&tlmm>;
+		qcom,gpio-connect = <&tlmm 80 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&wcd_intr_default>;
+	};
+
+	clock_audio_lnbb: audio_ext_clk_lnbb {
+		status = "disabled";
+		compatible = "qcom,audio-ref-clk";
+		clock-names = "osr_clk";
+		clocks = <&clock_rpmh RPMH_LN_BB_CLK2>;
+		qcom,node_has_rpm_clock;
+		#clock-cells = <1>;
+	};
+
+	wcd_rst_gpio: msm_cdc_pinctrl@64 {
+		status = "disabled";
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&lpi_cdc_reset_active>;
+		pinctrl-1 = <&lpi_cdc_reset_sleep>;
+		qcom,lpi-gpios;
+	};
+
+	wdsp_mgr: qcom,wcd-dsp-mgr {
+		compatible = "qcom,wcd-dsp-mgr";
+		qcom,wdsp-components = <&wcd934x_cdc 0>,
+				       <&wcd_spi_0 1>,
+				       <&glink_spi_xprt_wdsp 2>;
+					qcom,img-filename = "cpe_9340";
+	};
+
+	wdsp_glink: qcom,wcd-dsp-glink {
+		compatible = "qcom,wcd-dsp-glink";
+	};
+};
+
+&slim_aud {
+	wcd934x_cdc: tavil_codec {
+		status = "disabled";
+		compatible = "qcom,tavil-slim-pgd";
+		elemental-addr = [00 01 50 02 17 02];
+
+		interrupt-parent = <&wcd9xxx_intc>;
+		interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+			      17 18 19 20 21 22 23 24 25 26 27 28 29
+			      30 31>;
+
+		qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+
+		clock-names = "wcd_clk";
+		clocks = <&clock_audio_lnbb AUDIO_PMIC_LNBB_CLK>;
+
+		cdc-vdd-mic-bias-supply = <&pm660l_bob>;
+		qcom,cdc-vdd-mic-bias-voltage = <3312000 3312000>;
+		qcom,cdc-vdd-mic-bias-current = <30400>;
+
+		qcom,cdc-static-supplies = "cdc-vdd-mic-bias";
+
+		qcom,cdc-micbias1-mv = <1800>;
+		qcom,cdc-micbias2-mv = <1800>;
+		qcom,cdc-micbias3-mv = <1800>;
+		qcom,cdc-micbias4-mv = <1800>;
+
+		qcom,cdc-mclk-clk-rate = <9600000>;
+		qcom,cdc-slim-ifd = "tavil-slim-ifd";
+		qcom,cdc-slim-ifd-elemental-addr = [00 00 50 02 17 02];
+		qcom,cdc-dmic-sample-rate = <4800000>;
+		qcom,cdc-mad-dmic-rate = <600000>;
+
+		qcom,wdsp-cmpnt-dev-name = "tavil_codec";
+
+		wcd_spi_0: wcd_spi {
+			compatible = "qcom,wcd-spi-v2";
+			qcom,master-bus-num = <8>;
+			qcom,chip-select = <0>;
+			qcom,max-frequency = <24000000>;
+			qcom,mem-base-addr = <0x100000>;
+		};
+	};
+};
+
+&pm660l_3 {
+	pmic_analog_codec: analog-codec@f000 {
+		status = "okay";
+		compatible = "qcom,pmic-analog-codec";
+		reg = <0xf000 0x200>;
+		#address-cells = <2>;
+		#size-cells = <0>;
+		interrupt-parent = <&spmi_bus>;
+		interrupts = <0x3 0xf0 0x0 IRQ_TYPE_NONE>,
+			     <0x3 0xf0 0x1 IRQ_TYPE_NONE>,
+			     <0x3 0xf0 0x2 IRQ_TYPE_NONE>,
+			     <0x3 0xf0 0x3 IRQ_TYPE_NONE>,
+			     <0x3 0xf0 0x4 IRQ_TYPE_NONE>,
+			     <0x3 0xf0 0x5 IRQ_TYPE_NONE>,
+			     <0x3 0xf0 0x6 IRQ_TYPE_NONE>,
+			     <0x3 0xf0 0x7 IRQ_TYPE_NONE>,
+			     <0x3 0xf1 0x0 IRQ_TYPE_NONE>,
+			     <0x3 0xf1 0x1 IRQ_TYPE_NONE>,
+			     <0x3 0xf1 0x2 IRQ_TYPE_NONE>,
+			     <0x3 0xf1 0x3 IRQ_TYPE_NONE>,
+			     <0x3 0xf1 0x4 IRQ_TYPE_NONE>,
+			     <0x3 0xf1 0x5 IRQ_TYPE_NONE>;
+		interrupt-names = "spk_cnp_int",
+				   "spk_clip_int",
+				   "spk_ocp_int",
+				   "ins_rem_det1",
+				   "but_rel_det",
+				   "but_press_det",
+				   "ins_rem_det",
+				   "mbhc_int",
+				   "ear_ocp_int",
+				   "hphr_ocp_int",
+				   "hphl_ocp_det",
+				   "ear_cnp_int",
+				   "hphr_cnp_int",
+				   "hphl_cnp_int";
+
+		cdc-vdda-cp-supply = <&pm660_s4>;
+		qcom,cdc-vdda-cp-voltage = <1900000 2050000>;
+		qcom,cdc-vdda-cp-current = <50000>;
+
+		cdc-vdd-pa-supply = <&pm660_s4>;
+		qcom,cdc-vdd-pa-voltage = <2040000 2040000>;
+		qcom,cdc-vdd-pa-current = <260000>;
+
+		cdc-vdd-mic-bias-supply = <&pm660l_l7>;
+		qcom,cdc-vdd-mic-bias-voltage = <3088000 3088000>;
+		qcom,cdc-vdd-mic-bias-current = <5000>;
+
+		qcom,cdc-mclk-clk-rate = <9600000>;
+
+		qcom,cdc-static-supplies = "cdc-vdda-cp",
+					   "cdc-vdd-pa";
+
+		qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+
+		/*
+		 * Not marking address @ as driver searches this child
+		 * with name msm-dig-codec
+		 */
+		msm_digital_codec: msm-dig-codec {
+			compatible = "qcom,msm-digital-codec";
+			reg = <0x62ec0000 0x0>;
+		};
+	};
+};
+
+&pm660_gpios {
+	gpio@c200 {
+		status = "ok";
+		qcom,mode = <1>;
+		qcom,pull = <4>;
+		qcom,vin-sel = <0>;
+		qcom,src-sel = <2>;
+		qcom,master-en = <1>;
+		qcom,out-strength = <2>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi b/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi
index 3bd0350..ac92561 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-audio.dtsi
@@ -39,42 +39,6 @@
 		qcom,wcn-btfm;
 		qcom,mi2s-audio-intf;
 		qcom,auxpcm-audio-intf;
-		qcom,msm-mi2s-master = <1>, <1>, <1>, <1>;
-		qcom,audio-routing =
-			"AIF4 VI", "MCLK",
-			"RX_BIAS", "MCLK",
-			"MADINPUT", "MCLK",
-			"hifi amp", "LINEOUT1",
-			"hifi amp", "LINEOUT2",
-			"AMIC2", "MIC BIAS2",
-			"MIC BIAS2", "Headset Mic",
-			"AMIC3", "MIC BIAS2",
-			"MIC BIAS2", "ANCRight Headset Mic",
-			"AMIC4", "MIC BIAS2",
-			"MIC BIAS2", "ANCLeft Headset Mic",
-			"AMIC5", "MIC BIAS3",
-			"MIC BIAS3", "Handset Mic",
-			"DMIC0", "MIC BIAS1",
-			"MIC BIAS1", "Digital Mic0",
-			"DMIC1", "MIC BIAS1",
-			"MIC BIAS1", "Digital Mic1",
-			"DMIC2", "MIC BIAS3",
-			"MIC BIAS3", "Digital Mic2",
-			"DMIC3", "MIC BIAS3",
-			"MIC BIAS3", "Digital Mic3",
-			"DMIC4", "MIC BIAS4",
-			"MIC BIAS4", "Digital Mic4",
-			"DMIC5", "MIC BIAS4",
-			"MIC BIAS4", "Digital Mic5",
-			"SpkrLeft IN", "SPK1 OUT",
-			"SpkrRight IN", "SPK2 OUT";
-
-		qcom,msm-mbhc-hphl-swh = <1>;
-		qcom,msm-mbhc-gnd-swh = <1>;
-		qcom,hph-en0-gpio = <&tavil_hph_en0>;
-		qcom,hph-en1-gpio = <&tavil_hph_en1>;
-		qcom,msm-mclk-freq = <9600000>;
-		qcom,usbc-analog-en1_gpio = <&wcd_usbc_analog_en1_gpio>;
 		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
 			<&loopback>, <&compress>, <&hostless>,
 			<&afe>, <&lsm>, <&routing>, <&cpe>, <&compr>,
@@ -126,58 +90,15 @@
 			"msm-dai-q6-tdm.36880", "msm-dai-q6-tdm.36881",
 			"msm-dai-q6-tdm.36896", "msm-dai-q6-tdm.36897",
 			"msm-dai-q6-tdm.36912", "msm-dai-q6-tdm.36913";
-		asoc-codec = <&stub_codec>;
-		asoc-codec-names = "msm-stub-codec.1";
-		qcom,wsa-max-devs = <2>;
-		qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0212>,
-				<&wsa881x_0213>, <&wsa881x_0214>;
-		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
-					"SpkrLeft", "SpkrRight";
 	};
 
-int_codec: sound {
+	int_codec: sound {
 		status = "okay";
 		compatible = "qcom,sdm670-asoc-snd";
 		qcom,model = "sdm670-snd-card";
 		qcom,wcn-btfm;
 		qcom,mi2s-audio-intf;
 		qcom,auxpcm-audio-intf;
-		qcom,msm-mi2s-master = <1>, <1>, <1>, <1>;
-		qcom,msm-mclk-freq = <9600000>;
-		qcom,msm-mbhc-hphl-swh = <1>;
-		qcom,msm-mbhc-gnd-swh = <1>;
-		qcom,msm-micbias2-ext-cap;
-		qcom,msm-hs-micbias-type = "external";
-		qcom,cdc-pdm-gpios = <&cdc_pdm_gpios>;
-		qcom,cdc-comp-gpios = <&cdc_comp_gpios>;
-		qcom,cdc-dmic-gpios = <&cdc_dmic_gpios>;
-		qcom,audio-routing =
-			"RX_BIAS", "INT_MCLK0",
-			"SPK_RX_BIAS", "INT_MCLK0",
-			"INT_LDO_H", "INT_MCLK0",
-			"MIC BIAS External", "Handset Mic",
-			"MIC BIAS External2", "Headset Mic",
-			"MIC BIAS External", "Secondary Mic",
-			"AMIC1", "MIC BIAS External",
-			"AMIC2", "MIC BIAS External2",
-			"AMIC3", "MIC BIAS External",
-			"DMIC1", "MIC BIAS External",
-			"MIC BIAS External", "Digital Mic1",
-			"DMIC2", "MIC BIAS External",
-			"MIC BIAS External", "Digital Mic2",
-			"DMIC3", "MIC BIAS External",
-			"MIC BIAS External", "Digital Mic3",
-			"DMIC4", "MIC BIAS External",
-			"MIC BIAS External", "Digital Mic4",
-			"SpkrLeft IN", "SPK1 OUT",
-			"SpkrRight IN", "SPK2 OUT",
-			"PDM_IN_RX1", "PDM_OUT_RX1",
-			"PDM_IN_RX2", "PDM_OUT_RX2",
-			"PDM_IN_RX3", "PDM_OUT_RX3",
-			"ADC1_IN", "ADC1_OUT",
-			"ADC2_IN", "ADC2_OUT",
-			"ADC3_IN", "ADC3_OUT";
-
 		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
 			<&loopback>, <&compress>, <&hostless>,
 			<&afe>, <&lsm>, <&routing>, <&compr>,
@@ -224,135 +145,6 @@
 			"msm-dai-q6-tdm.36880", "msm-dai-q6-tdm.36881",
 			"msm-dai-q6-tdm.36896", "msm-dai-q6-tdm.36897",
 			"msm-dai-q6-tdm.36912", "msm-dai-q6-tdm.36913";
-		asoc-codec = <&stub_codec>, <&msm_digital_codec>,
-				<&pmic_analog_codec>, <&msm_sdw_codec>;
-		asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
-				"analog-codec", "msm_sdw_codec";
-
-		qcom,wsa-max-devs = <2>;
-		qcom,wsa-devs = <&wsa881x_211_en>, <&wsa881x_212_en>,
-				<&wsa881x_213_en>, <&wsa881x_214_en>;
-		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
-					"SpkrLeft", "SpkrRight";
-	};
-
-	cdc_pdm_gpios: cdc_pdm_pinctrl {
-		compatible = "qcom,msm-cdc-pinctrl";
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&cdc_pdm_clk_active &cdc_pdm_sync_active
-			     &cdc_pdm_rx0_active &cdc_pdm_rx1_2_active
-			     &cdc_pdm_2_gpios_active>;
-		pinctrl-1 = <&cdc_pdm_clk_sleep &cdc_pdm_sync_sleep
-			     &cdc_pdm_rx0_sleep &cdc_pdm_rx1_2_sleep
-			     &cdc_pdm_2_gpios_sleep>;
-		qcom,lpi-gpios;
-	};
-
-	cdc_comp_gpios: cdc_comp_pinctrl {
-		compatible = "qcom,msm-cdc-pinctrl";
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&cdc_rx0_comp_active &cdc_rx1_comp_active>;
-		pinctrl-1 = <&cdc_rx0_comp_sleep &cdc_rx1_comp_sleep>;
-		qcom,lpi-gpios;
-	};
-
-	cdc_dmic_gpios: cdc_dmic_pinctrl {
-		compatible = "qcom,msm-cdc-pinctrl";
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&cdc_dmic12_gpios_active
-				&cdc_dmic34_gpios_active>;
-		pinctrl-1 = <&cdc_dmic12_gpios_sleep
-				&cdc_dmic34_gpios_sleep>;
-		qcom,lpi-gpios;
-	};
-
-	cdc_sdw_gpios: sdw_clk_data_pinctrl {
-		compatible = "qcom,msm-cdc-pinctrl";
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&sdw_clk_active &sdw_data_active>;
-		pinctrl-1 = <&sdw_clk_sleep &sdw_data_sleep>;
-	};
-
-	wsa_spkr_en1: wsa_spkr_en1_pinctrl {
-		compatible = "qcom,msm-cdc-pinctrl";
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&spkr_1_sd_n_active>;
-		pinctrl-1 = <&spkr_1_sd_n_sleep>;
-	};
-
-	wsa_spkr_en2: wsa_spkr_en2_pinctrl {
-		compatible = "qcom,msm-cdc-pinctrl";
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&spkr_2_sd_n_active>;
-		pinctrl-1 = <&spkr_2_sd_n_sleep>;
-	};
-
-	msm_sdw_codec: msm-sdw-codec@62ec1000 {
-		status = "okay";
-		compatible = "qcom,msm-sdw-codec";
-		reg = <0x62ec1000 0x0>;
-		interrupts = <0 161 0>;
-		interrupt-names = "swr_master_irq";
-		qcom,cdc-sdw-gpios = <&cdc_sdw_gpios>;
-
-		swr_master {
-			compatible = "qcom,swr-wcd";
-			#address-cells = <2>;
-			#size-cells = <0>;
-
-			wsa881x_211_en: wsa881x_en@20170211 {
-				compatible = "qcom,wsa881x";
-				reg = <0x0 0x20170211>;
-				qcom,spkr-sd-n-node = <&wsa_spkr_en1>;
-			};
-
-			wsa881x_212_en: wsa881x_en@20170212 {
-				compatible = "qcom,wsa881x";
-				reg = <0x0 0x20170212>;
-				qcom,spkr-sd-n-node = <&wsa_spkr_en2>;
-			};
-
-			wsa881x_213_en: wsa881x_en@21170213 {
-				compatible = "qcom,wsa881x";
-				reg = <0x0 0x21170213>;
-				qcom,spkr-sd-n-node = <&wsa_spkr_en1>;
-			};
-
-			wsa881x_214_en: wsa881x_en@21170214 {
-				compatible = "qcom,wsa881x";
-				reg = <0x0 0x21170214>;
-				qcom,spkr-sd-n-node = <&wsa_spkr_en2>;
-			};
-		};
-	};
-
-	wcd9xxx_intc: wcd9xxx-irq {
-		status = "disabled";
-		compatible = "qcom,wcd9xxx-irq";
-		interrupt-controller;
-		#interrupt-cells = <1>;
-		interrupt-parent = <&tlmm>;
-		qcom,gpio-connect = <&tlmm 80 0>;
-		pinctrl-names = "default";
-		pinctrl-0 = <&wcd_intr_default>;
-	};
-
-	clock_audio_lnbb: audio_ext_clk_lnbb {
-		status = "disabled";
-		compatible = "qcom,audio-ref-clk";
-		clock-names = "osr_clk";
-		clocks = <&clock_rpmh RPMH_LN_BB_CLK2>;
-		qcom,node_has_rpm_clock;
-		#clock-cells = <1>;
-	};
-
-	wcd_rst_gpio: msm_cdc_pinctrl@64 {
-		status = "disabled";
-		compatible = "qcom,msm-cdc-pinctrl";
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&lpi_cdc_reset_active>;
-		pinctrl-1 = <&lpi_cdc_reset_sleep>;
-		qcom,lpi-gpios;
 	};
 
 	cpe: qcom,msm-cpe-lsm {
@@ -363,18 +155,6 @@
 		compatible = "qcom,msm-cpe-lsm";
 		qcom,msm-cpe-lsm-id = <3>;
 	};
-
-	wdsp_mgr: qcom,wcd-dsp-mgr {
-		compatible = "qcom,wcd-dsp-mgr";
-		qcom,wdsp-components = <&wcd934x_cdc 0>,
-				       <&wcd_spi_0 1>,
-				       <&glink_spi_xprt_wdsp 2>;
-		qcom,img-filename = "cpe_9340";
-	};
-
-	wdsp_glink: qcom,wcd-dsp-glink {
-		compatible = "qcom,wcd-dsp-glink";
-	};
 };
 
 &slim_aud {
@@ -384,56 +164,6 @@
 		compatible = "qcom,msm-dai-slim";
 		elemental-addr = [ff ff ff fe 17 02];
 	};
-
-	wcd934x_cdc: tavil_codec {
-		status = "disabled";
-		compatible = "qcom,tavil-slim-pgd";
-		elemental-addr = [00 01 50 02 17 02];
-
-		interrupt-parent = <&wcd9xxx_intc>;
-		interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
-			      17 18 19 20 21 22 23 24 25 26 27 28 29
-			      30 31>;
-
-		qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
-
-		clock-names = "wcd_clk";
-		clocks = <&clock_audio_lnbb AUDIO_PMIC_LNBB_CLK>;
-
-		cdc-vdd-mic-bias-supply = <&pm660l_bob>;
-		qcom,cdc-vdd-mic-bias-voltage = <3300000 3300000>;
-		qcom,cdc-vdd-mic-bias-current = <30400>;
-
-		qcom,cdc-static-supplies = "cdc-vdd-mic-bias";
-
-		qcom,cdc-micbias1-mv = <1800>;
-		qcom,cdc-micbias2-mv = <1800>;
-		qcom,cdc-micbias3-mv = <1800>;
-		qcom,cdc-micbias4-mv = <1800>;
-
-		qcom,cdc-mclk-clk-rate = <9600000>;
-		qcom,cdc-slim-ifd = "tavil-slim-ifd";
-		qcom,cdc-slim-ifd-elemental-addr = [00 00 50 02 17 02];
-		qcom,cdc-dmic-sample-rate = <4800000>;
-		qcom,cdc-mad-dmic-rate = <600000>;
-
-		qcom,wdsp-cmpnt-dev-name = "tavil_codec";
-
-		wcd_spi_0: wcd_spi {
-			compatible = "qcom,wcd-spi-v2";
-			qcom,master-bus-num = <8>;
-			qcom,chip-select = <0>;
-			qcom,max-frequency = <24000000>;
-			qcom,mem-base-addr = <0x100000>;
-		};
-
-		wcd_usbc_analog_en1_gpio: msm_cdc_pinctrl_usbc_audio_en1 {
-			compatible = "qcom,msm-cdc-pinctrl";
-			pinctrl-names = "aud_active", "aud_sleep";
-			pinctrl-0 = <&wcd_usbc_analog_en1_active>;
-			pinctrl-1 = <&wcd_usbc_analog_en1_idle>;
-		};
-	};
 };
 
 &msm_dai_mi2s {
@@ -486,83 +216,3 @@
 		qcom,msm-mi2s-tx-lines = <3>;
 	};
 };
-
-&pm660l_3 {
-	pmic_analog_codec: analog-codec@f000 {
-		status = "okay";
-		compatible = "qcom,pmic-analog-codec";
-		reg = <0xf000 0x200>;
-		#address-cells = <2>;
-		#size-cells = <0>;
-		interrupt-parent = <&spmi_bus>;
-		interrupts = <0x3 0xf0 0x0 IRQ_TYPE_NONE>,
-				<0x3 0xf0 0x1 IRQ_TYPE_NONE>,
-				<0x3 0xf0 0x2 IRQ_TYPE_NONE>,
-				<0x3 0xf0 0x3 IRQ_TYPE_NONE>,
-				<0x3 0xf0 0x4 IRQ_TYPE_NONE>,
-				<0x3 0xf0 0x5 IRQ_TYPE_NONE>,
-				<0x3 0xf0 0x6 IRQ_TYPE_NONE>,
-				<0x3 0xf0 0x7 IRQ_TYPE_NONE>,
-				<0x3 0xf1 0x0 IRQ_TYPE_NONE>,
-				<0x3 0xf1 0x1 IRQ_TYPE_NONE>,
-				<0x3 0xf1 0x2 IRQ_TYPE_NONE>,
-				<0x3 0xf1 0x3 IRQ_TYPE_NONE>,
-				<0x3 0xf1 0x4 IRQ_TYPE_NONE>,
-				<0x3 0xf1 0x5 IRQ_TYPE_NONE>;
-		interrupt-names = "spk_cnp_int",
-				  "spk_clip_int",
-				  "spk_ocp_int",
-				  "ins_rem_det1",
-				  "but_rel_det",
-				  "but_press_det",
-				  "ins_rem_det",
-				  "mbhc_int",
-				  "ear_ocp_int",
-				  "hphr_ocp_int",
-				  "hphl_ocp_det",
-				  "ear_cnp_int",
-				  "hphr_cnp_int",
-				  "hphl_cnp_int";
-
-
-		cdc-vdda-cp-supply = <&pm660_s4>;
-		qcom,cdc-vdda-cp-voltage = <1900000 2050000>;
-		qcom,cdc-vdda-cp-current = <50000>;
-
-		cdc-vdd-pa-supply = <&pm660_s4>;
-		qcom,cdc-vdd-pa-voltage = <2040000 2040000>;
-		qcom,cdc-vdd-pa-current = <260000>;
-
-		cdc-vdd-mic-bias-supply = <&pm660l_l7>;
-		qcom,cdc-vdd-mic-bias-voltage = <3088000 3088000>;
-		qcom,cdc-vdd-mic-bias-current = <5000>;
-
-		qcom,cdc-mclk-clk-rate = <9600000>;
-
-		qcom,cdc-static-supplies = "cdc-vdda-cp",
-					   "cdc-vdd-pa";
-
-		qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
-
-		/*
-		 * Not marking address @ as driver searches this child
-		 * with name msm-dig-codec
-		 */
-		msm_digital_codec: msm-dig-codec {
-			compatible = "qcom,msm-digital-codec";
-			reg = <0x62ec0000 0x0>;
-		};
-	};
-};
-
-&pm660_gpios {
-	gpio@c200 {
-		status = "ok";
-		qcom,mode = <1>;
-		qcom,pull = <4>;
-		qcom,vin-sel = <0>;
-		qcom,src-sel = <2>;
-		qcom,master-en = <1>;
-		qcom,out-strength = <2>;
-	};
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-cdp.dts b/arch/arm64/boot/dts/qcom/sdm670-cdp.dts
index 27882dd..7aa87a2 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm670-cdp.dts
@@ -15,6 +15,7 @@
 
 #include "sdm670.dtsi"
 #include "sdm670-cdp.dtsi"
+#include "sdm670-int-codec-audio-overlay.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM670 PM660 + PM660L CDP";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi
index 00f454c..257698a 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi
@@ -10,7 +10,9 @@
  * GNU General Public License for more details.
  */
 
+#include <dt-bindings/gpio/gpio.h>
 #include "sdm670-pmic-overlay.dtsi"
+#include "sdm670-sde-display.dtsi"
 
 &ufsphy_mem {
 	compatible = "qcom,ufs-phy-qmp-v3";
@@ -106,7 +108,8 @@
 
 		pinctrl-names = "default";
 		pinctrl-0 = <&key_cam_snapshot_default
-			     &key_cam_focus_default>;
+			     &key_cam_focus_default
+			     &key_vol_up_default>;
 
 		cam_snapshot {
 			label = "cam_snapshot";
@@ -127,5 +130,106 @@
 			debounce-interval = <15>;
 			linux,can-disable;
 		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&pm660l_gpios 7 GPIO_ACTIVE_LOW>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+			linux,can-disable;
+		};
 	};
 };
+
+&dsi_dual_nt35597_truly_video {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 76 0>;
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_dual_nt35597_truly_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 76 0>;
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+};
+
+&dsi_nt35597_truly_dsc_video {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
+	qcom,panel-mode-gpio = <&tlmm 76 0>;
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_nt35597_truly_dsc_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
+	qcom,panel-mode-gpio = <&tlmm 76 0>;
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+};
+
+&dsi_sim_vid {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_dual_sim_vid {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_sim_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_dual_sim_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_sim_dsc_375_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_dual_sim_dsc_375_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_dual_nt35597_truly_video {
+	qcom,dsi-display-active;
+};
+
+&pm660l_wled {
+	status = "okay";
+	qcom,led-strings-list = [01 02];
+};
+
+&mdss_mdp {
+	#cooling-cells = <2>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-ext-codec-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm670-ext-codec-audio-overlay.dtsi
new file mode 100644
index 0000000..775cf48
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-ext-codec-audio-overlay.dtsi
@@ -0,0 +1,96 @@
+/* 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.
+ */
+#include "sdm670-audio-overlay.dtsi"
+
+&pmic_analog_codec {
+	status = "disabled";
+};
+
+&msm_sdw_codec {
+	status = "disabled";
+};
+
+&cdc_pdm_gpios {
+	status = "disabled";
+};
+
+&cdc_comp_gpios {
+	status = "disabled";
+};
+
+&cdc_dmic_gpios {
+	status = "disabled";
+};
+
+&cdc_sdw_gpios {
+	status = "disabled";
+};
+
+&wsa_spkr_en1 {
+	status = "disabled";
+};
+
+&wsa_spkr_en2 {
+	status = "disabled";
+};
+
+&qupv3_se8_spi {
+	status = "okay";
+};
+
+&soc {
+	wcd_buck_vreg_gpio: msm_cdc_pinctrl@94 {
+		status = "okay";
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&wcd_buck_vsel_default>;
+		pinctrl-1 = <&wcd_buck_vsel_default>;
+	};
+};
+
+&wcd9xxx_intc {
+	status = "okay";
+};
+
+&wdsp_mgr {
+	status = "okay";
+};
+
+&wdsp_glink {
+	status = "okay";
+};
+
+&slim_aud {
+	status = "okay";
+};
+
+&dai_slim {
+	status = "okay";
+};
+
+&wcd934x_cdc {
+	status = "okay";
+	qcom,has-buck-vsel-gpio;
+	qcom,buck-vsel-gpio-node = <&wcd_buck_vreg_gpio>;
+};
+
+&clock_audio_lnbb {
+	status = "okay";
+};
+
+&wcd_rst_gpio {
+	status = "okay";
+};
+
+&wcd9xxx_intc {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-external-codec.dtsi b/arch/arm64/boot/dts/qcom/sdm670-external-codec.dtsi
index 6ea92ee..dbcc6bd 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-external-codec.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-external-codec.dtsi
@@ -9,3 +9,21 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
+
+#include "sdm670-ext-codec-audio-overlay.dtsi"
+
+&int_codec {
+	status = "disabled";
+};
+
+&tavil_snd {
+	status = "okay";
+};
+
+&slim_aud {
+	status = "okay";
+};
+
+&dai_slim {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-int-codec-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm670-int-codec-audio-overlay.dtsi
new file mode 100644
index 0000000..bc431f2
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-int-codec-audio-overlay.dtsi
@@ -0,0 +1,12 @@
+/* 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.
+ */
+#include "sdm670-audio-overlay.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm670-mtp.dts b/arch/arm64/boot/dts/qcom/sdm670-mtp.dts
index 38a9fae..f12be2ae 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm670-mtp.dts
@@ -15,6 +15,7 @@
 
 #include "sdm670.dtsi"
 #include "sdm670-mtp.dtsi"
+#include "sdm670-int-codec-audio-overlay.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM670 PM660 + PM660L MTP";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi
index 320a1f2..fa76a2e 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi
@@ -10,7 +10,9 @@
  * GNU General Public License for more details.
  */
 
+#include <dt-bindings/gpio/gpio.h>
 #include "sdm670-pmic-overlay.dtsi"
+#include "sdm670-sde-display.dtsi"
 
 &ufsphy_mem {
 	compatible = "qcom,ufs-phy-qmp-v3";
@@ -115,7 +117,8 @@
 
 		pinctrl-names = "default";
 		pinctrl-0 = <&key_cam_snapshot_default
-			     &key_cam_focus_default>;
+			     &key_cam_focus_default
+			     &key_vol_up_default>;
 
 		cam_snapshot {
 			label = "cam_snapshot";
@@ -136,5 +139,106 @@
 			debounce-interval = <15>;
 			linux,can-disable;
 		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&pm660l_gpios 7 GPIO_ACTIVE_LOW>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+			linux,can-disable;
+		};
 	};
 };
+
+&dsi_dual_nt35597_truly_video {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 76 0>;
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_dual_nt35597_truly_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 76 0>;
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+};
+
+&dsi_nt35597_truly_dsc_video {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
+	qcom,panel-mode-gpio = <&tlmm 76 0>;
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_nt35597_truly_dsc_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
+	qcom,panel-mode-gpio = <&tlmm 76 0>;
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+};
+
+&dsi_sim_vid {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_dual_sim_vid {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_sim_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_dual_sim_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_sim_dsc_375_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_dual_sim_dsc_375_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+};
+
+&dsi_dual_nt35597_truly_video {
+	qcom,dsi-display-active;
+};
+
+&pm660l_wled {
+	status = "okay";
+	qcom,led-strings-list = [01 02];
+};
+
+&mdss_mdp {
+	#cooling-cells = <2>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
index 2a2b6d8..e747185 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
@@ -1406,6 +1406,22 @@
 			};
 		};
 
+		wcd_buck_vsel {
+			wcd_buck_vsel_default: wcd_buck_vsel_default{
+				mux {
+					pins = "gpio94";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio94";
+					drive-strength = <8>; /* 8 mA */
+					bias-pull-down; /* pull down */
+					output-high;
+				};
+			};
+		};
+
 		wcd_gnd_mic_swap {
 			wcd_gnd_mic_swap_idle: wcd_gnd_mic_swap_idle {
 				mux {
@@ -1473,5 +1489,123 @@
 			};
 		};
 
+		pmx_sde: pmx_sde {
+			sde_dsi_active: sde_dsi_active {
+				mux {
+					pins = "gpio75", "gpio76";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio75", "gpio76";
+					drive-strength = <8>;   /* 8 mA */
+					bias-disable = <0>;   /* no pull */
+				};
+			};
+			sde_dsi_suspend: sde_dsi_suspend {
+				mux {
+					pins = "gpio75", "gpio76";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio75", "gpio76";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+				};
+			};
+		};
+
+		pmx_sde_te {
+			sde_te_active: sde_te_active {
+				mux {
+					pins = "gpio10";
+					function = "mdp_vsync";
+				};
+
+				config {
+					pins = "gpio10";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+				};
+			};
+
+			sde_te_suspend: sde_te_suspend {
+				mux {
+					pins = "gpio10";
+					function = "mdp_vsync";
+				};
+
+				config {
+					pins = "gpio10";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+				};
+			};
+		};
+
+		sde_dp_aux_active: sde_dp_aux_active {
+			mux {
+				pins = "gpio40", "gpio50";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio40", "gpio50";
+				bias-disable = <0>; /* no pull */
+				drive-strength = <8>;
+			};
+		};
+
+		sde_dp_aux_suspend: sde_dp_aux_suspend {
+			mux {
+				pins = "gpio40", "gpio50";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio40", "gpio50";
+				bias-pull-down;
+				drive-strength = <2>;
+			};
+		};
+
+		sde_dp_usbplug_cc_active: sde_dp_usbplug_cc_active {
+			mux {
+				pins = "gpio38";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio38";
+				bias-disable;
+				drive-strength = <16>;
+			};
+		};
+
+		sde_dp_usbplug_cc_suspend: sde_dp_usbplug_cc_suspend {
+			mux {
+				pins = "gpio38";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio38";
+				bias-pull-down;
+				drive-strength = <2>;
+			};
+		};
+	};
+};
+
+&pm660l_gpios {
+	key_vol_up {
+		key_vol_up_default: key_vol_up_default {
+			pins = "gpio7";
+			function = "normal";
+			input-enable;
+			bias-pull-up;
+			power-source = <0>;
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pm660a-cdp.dts b/arch/arm64/boot/dts/qcom/sdm670-pm660a-cdp.dts
index 5cf3513..95642f9 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pm660a-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm670-pm660a-cdp.dts
@@ -16,6 +16,7 @@
 #include "sdm670.dtsi"
 #include "sdm670-cdp.dtsi"
 #include "pm660a.dtsi"
+#include "sdm670-int-codec-audio-overlay.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM670 PM660 + PM660A CDP";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pm660a-mtp.dts b/arch/arm64/boot/dts/qcom/sdm670-pm660a-mtp.dts
index febd5d9..5592ce4 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pm660a-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm670-pm660a-mtp.dts
@@ -16,6 +16,7 @@
 #include "sdm670.dtsi"
 #include "sdm670-mtp.dtsi"
 #include "pm660a.dtsi"
+#include "sdm670-int-codec-audio-overlay.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM670 PM660 + PM660A MTP";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi
index 75922b0..aa6be24 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi
@@ -156,6 +156,15 @@
 		};
 	};
 
+	pm660_rradc: rradc@4500 {
+		compatible = "qcom,rradc";
+		reg = <0x4500 0x100>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#io-channel-cells = <1>;
+		qcom,pmic-revid = <&pm660_revid>;
+	};
+
 	pm660_fg: qpnp,fg {
 		compatible = "qcom,fg-gen3";
 		#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
index 23792b1..24b8dd6 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
@@ -642,4 +642,14 @@
 			qcom,init-voltage = <3312000>;
 		};
 	};
+
+	refgen: refgen-regulator@ff1000 {
+		compatible = "qcom,refgen-regulator";
+		reg = <0xff1000 0x60>;
+		regulator-name = "refgen";
+		regulator-enable-ramp-delay = <5>;
+		proxy-supply = <&refgen>;
+		qcom,proxy-consumer-enable;
+		regulator-always-on;
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm670-rumi.dts b/arch/arm64/boot/dts/qcom/sdm670-rumi.dts
index 6201488..e2a2df7 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-rumi.dts
+++ b/arch/arm64/boot/dts/qcom/sdm670-rumi.dts
@@ -16,6 +16,7 @@
 
 #include "sdm670.dtsi"
 #include "sdm670-rumi.dtsi"
+#include "sdm670-int-codec-audio-overlay.dtsi"
 / {
 	model = "Qualcomm Technologies, Inc. SDM670 RUMI";
 	compatible = "qcom,sdm670-rumi", "qcom,sdm670", "qcom,rumi";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
new file mode 100644
index 0000000..3e9d967
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
@@ -0,0 +1,597 @@
+/* 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.
+ */
+
+#include "dsi-panel-sim-video.dtsi"
+#include "dsi-panel-sim-cmd.dtsi"
+#include "dsi-panel-sim-dsc375-cmd.dtsi"
+#include "dsi-panel-sim-dualmipi-video.dtsi"
+#include "dsi-panel-sim-dualmipi-cmd.dtsi"
+#include "dsi-panel-sim-dualmipi-dsc375-cmd.dtsi"
+#include "dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi"
+#include "dsi-panel-nt35597-truly-dualmipi-wqxga-cmd.dtsi"
+#include "dsi-panel-nt35597-truly-dsc-wqxga-cmd.dtsi"
+#include "dsi-panel-nt35597-truly-dsc-wqxga-video.dtsi"
+#include <dt-bindings/clock/mdss-10nm-pll-clk.h>
+
+&soc {
+	dsi_panel_pwr_supply: dsi_panel_pwr_supply {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,panel-supply-entry@0 {
+			reg = <0>;
+			qcom,supply-name = "vddio";
+			qcom,supply-min-voltage = <1800000>;
+			qcom,supply-max-voltage = <1800000>;
+			qcom,supply-enable-load = <62000>;
+			qcom,supply-disable-load = <80>;
+			qcom,supply-post-on-sleep = <20>;
+		};
+
+		qcom,panel-supply-entry@1 {
+			reg = <1>;
+			qcom,supply-name = "lab";
+			qcom,supply-min-voltage = <4600000>;
+			qcom,supply-max-voltage = <6000000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+		};
+
+		qcom,panel-supply-entry@2 {
+			reg = <2>;
+			qcom,supply-name = "ibb";
+			qcom,supply-min-voltage = <4600000>;
+			qcom,supply-max-voltage = <6000000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-post-on-sleep = <20>;
+		};
+	};
+
+	dsi_panel_pwr_supply_no_labibb: dsi_panel_pwr_supply_no_labibb {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,panel-supply-entry@0 {
+			reg = <0>;
+			qcom,supply-name = "vddio";
+			qcom,supply-min-voltage = <1800000>;
+			qcom,supply-max-voltage = <1800000>;
+			qcom,supply-enable-load = <62000>;
+			qcom,supply-disable-load = <80>;
+			qcom,supply-post-on-sleep = <20>;
+		};
+	};
+
+	dsi_panel_pwr_supply_vdd_no_labibb: dsi_panel_pwr_supply_vdd_no_labibb {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,panel-supply-entry@0 {
+			reg = <0>;
+			qcom,supply-name = "vddio";
+			qcom,supply-min-voltage = <1800000>;
+			qcom,supply-max-voltage = <1800000>;
+			qcom,supply-enable-load = <62000>;
+			qcom,supply-disable-load = <80>;
+			qcom,supply-post-on-sleep = <20>;
+		};
+
+		qcom,panel-supply-entry@1 {
+			reg = <1>;
+			qcom,supply-name = "vdd";
+			qcom,supply-min-voltage = <3000000>;
+			qcom,supply-max-voltage = <3000000>;
+			qcom,supply-enable-load = <857000>;
+			qcom,supply-disable-load = <0>;
+			qcom,supply-post-on-sleep = <0>;
+		};
+	};
+
+	dsi_dual_nt35597_truly_video_display: qcom,dsi-display@0 {
+		compatible = "qcom,dsi-display";
+		label = "dsi_dual_nt35597_truly_video_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
+		qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
+		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+			<&mdss_dsi0_pll PCLK_MUX_0_CLK>;
+		clock-names = "src_byte_clk", "src_pixel_clk";
+
+		pinctrl-names = "panel_active", "panel_suspend";
+		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+		qcom,platform-reset-gpio = <&tlmm 75 0>;
+		qcom,panel-mode-gpio = <&tlmm 76 0>;
+
+		qcom,dsi-panel = <&dsi_dual_nt35597_truly_video>;
+		vddio-supply = <&pm660_l11>;
+		lab-supply = <&lcdb_ldo_vreg>;
+		ibb-supply = <&lcdb_ncp_vreg>;
+	};
+
+	dsi_dual_nt35597_truly_cmd_display: qcom,dsi-display@1 {
+		compatible = "qcom,dsi-display";
+		label = "dsi_dual_nt35597_truly_cmd_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
+		qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
+		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+			<&mdss_dsi0_pll PCLK_MUX_0_CLK>;
+		clock-names = "src_byte_clk", "src_pixel_clk";
+
+		pinctrl-names = "panel_active", "panel_suspend";
+		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+		qcom,platform-te-gpio = <&tlmm 10 0>;
+		qcom,platform-reset-gpio = <&tlmm 75 0>;
+		qcom,panel-mode-gpio = <&tlmm 76 0>;
+
+		qcom,dsi-panel = <&dsi_dual_nt35597_truly_cmd>;
+		vddio-supply = <&pm660_l11>;
+		lab-supply = <&lcdb_ldo_vreg>;
+		ibb-supply = <&lcdb_ncp_vreg>;
+	};
+
+	dsi_nt35597_truly_dsc_cmd_display: qcom,dsi-display@2 {
+		compatible = "qcom,dsi-display";
+		label = "dsi_nt35597_truly_dsc_cmd_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl = <&mdss_dsi1>;
+		qcom,dsi-phy = <&mdss_dsi_phy1>;
+		clocks = <&mdss_dsi1_pll BYTECLK_MUX_1_CLK>,
+			<&mdss_dsi1_pll PCLK_MUX_1_CLK>;
+		clock-names = "src_byte_clk", "src_pixel_clk";
+
+		pinctrl-names = "panel_active", "panel_suspend";
+		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+		qcom,platform-te-gpio = <&tlmm 10 0>;
+		qcom,platform-reset-gpio = <&tlmm 75 0>;
+		qcom,panel-mode-gpio = <&tlmm 76 0>;
+
+		qcom,dsi-panel = <&dsi_nt35597_truly_dsc_cmd>;
+		vddio-supply = <&pm660_l11>;
+		lab-supply = <&lcdb_ldo_vreg>;
+		ibb-supply = <&lcdb_ncp_vreg>;
+	};
+
+	dsi_nt35597_truly_dsc_video_display: qcom,dsi-display@3 {
+		compatible = "qcom,dsi-display";
+		label = "dsi_nt35597_truly_dsc_video_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl = <&mdss_dsi1>;
+		qcom,dsi-phy = <&mdss_dsi_phy1>;
+		clocks = <&mdss_dsi1_pll BYTECLK_MUX_1_CLK>,
+			<&mdss_dsi1_pll PCLK_MUX_1_CLK>;
+		clock-names = "src_byte_clk", "src_pixel_clk";
+
+		pinctrl-names = "panel_active", "panel_suspend";
+		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+		qcom,platform-te-gpio = <&tlmm 10 0>;
+		qcom,platform-reset-gpio = <&tlmm 75 0>;
+		qcom,panel-mode-gpio = <&tlmm 76 0>;
+
+		qcom,dsi-panel = <&dsi_nt35597_truly_dsc_video>;
+		vddio-supply = <&pm660_l11>;
+		lab-supply = <&lcdb_ldo_vreg>;
+		ibb-supply = <&lcdb_ncp_vreg>;
+	};
+
+	dsi_sim_vid_display: qcom,dsi-display@4 {
+		compatible = "qcom,dsi-display";
+		label = "dsi_sim_vid_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl = <&mdss_dsi0>;
+		qcom,dsi-phy = <&mdss_dsi_phy0>;
+		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+			<&mdss_dsi0_pll PCLK_MUX_0_CLK>;
+		clock-names = "src_byte_clk", "src_pixel_clk";
+
+		pinctrl-names = "panel_active", "panel_suspend";
+		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+
+		qcom,dsi-panel = <&dsi_sim_vid>;
+	};
+
+	dsi_dual_sim_vid_display: qcom,dsi-display@5 {
+		compatible = "qcom,dsi-display";
+		label = "dsi_dual_sim_vid_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
+		qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
+		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+			<&mdss_dsi0_pll PCLK_MUX_0_CLK>;
+		clock-names = "src_byte_clk", "src_pixel_clk";
+
+		pinctrl-names = "panel_active", "panel_suspend";
+		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+
+		qcom,dsi-panel = <&dsi_dual_sim_vid>;
+	};
+
+	dsi_sim_cmd_display: qcom,dsi-display@6 {
+		compatible = "qcom,dsi-display";
+		label = "dsi_sim_cmd_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl = <&mdss_dsi0>;
+		qcom,dsi-phy = <&mdss_dsi_phy0>;
+		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+			<&mdss_dsi0_pll PCLK_MUX_0_CLK>;
+		clock-names = "src_byte_clk", "src_pixel_clk";
+
+		pinctrl-names = "panel_active", "panel_suspend";
+		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+
+		qcom,dsi-panel = <&dsi_sim_cmd>;
+	};
+
+	dsi_dual_sim_cmd_display: qcom,dsi-display@7 {
+		compatible = "qcom,dsi-display";
+		label = "dsi_dual_sim_cmd_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
+		qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
+		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+			<&mdss_dsi0_pll PCLK_MUX_0_CLK>;
+		clock-names = "src_byte_clk", "src_pixel_clk";
+
+		pinctrl-names = "panel_active", "panel_suspend";
+		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+
+		qcom,dsi-panel = <&dsi_dual_sim_cmd>;
+	};
+
+	dsi_sim_dsc_375_cmd_display: qcom,dsi-display@8 {
+		compatible = "qcom,dsi-display";
+		label = "dsi_sim_dsc_375_cmd_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl = <&mdss_dsi0>;
+		qcom,dsi-phy = <&mdss_dsi_phy0>;
+		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+			<&mdss_dsi0_pll PCLK_MUX_0_CLK>;
+		clock-names = "src_byte_clk", "src_pixel_clk";
+
+		pinctrl-names = "panel_active", "panel_suspend";
+		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+
+		qcom,dsi-panel = <&dsi_sim_dsc_375_cmd>;
+	};
+
+	dsi_dual_sim_dsc_375_cmd_display: qcom,dsi-display@9 {
+		compatible = "qcom,dsi-display";
+		label = "dsi_dual_sim_dsc_375_cmd_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
+		qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
+		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+			<&mdss_dsi0_pll PCLK_MUX_0_CLK>;
+		clock-names = "src_byte_clk", "src_pixel_clk";
+
+		pinctrl-names = "panel_active", "panel_suspend";
+		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+
+		qcom,dsi-panel = <&dsi_dual_sim_dsc_375_cmd>;
+	};
+
+	sde_wb: qcom,wb-display@0 {
+		compatible = "qcom,wb-display";
+		cell-index = <0>;
+		label = "wb_display";
+	};
+
+	ext_disp: qcom,msm-ext-disp {
+		compatible = "qcom,msm-ext-disp";
+		status = "disabled";
+
+		ext_disp_audio_codec: qcom,msm-ext-disp-audio-codec-rx {
+			compatible = "qcom,msm-ext-disp-audio-codec-rx";
+		};
+	};
+
+	sde_dp: qcom,dp_display@0{
+		cell-index = <0>;
+		compatible = "qcom,dp-display";
+		status = "disabled";
+
+		gdsc-supply = <&mdss_core_gdsc>;
+		vdda-1p2-supply = <&pm660_l1>;
+		vdda-0p9-supply = <&pm660l_l1>;
+
+		reg =	<0xae90000 0xa84>,
+			<0x88eaa00 0x200>,
+			<0x88ea200 0x200>,
+			<0x88ea600 0x200>,
+			<0xaf02000 0x1a0>,
+			<0x780000 0x621c>,
+			<0x88ea030 0x10>,
+			<0x0aee1000 0x034>;
+		reg-names = "dp_ctrl", "dp_phy", "dp_ln_tx0", "dp_ln_tx1",
+			"dp_mmss_cc", "qfprom_physical", "dp_pll",
+			"hdcp_physical";
+
+		interrupt-parent = <&mdss_mdp>;
+		interrupts = <12 0>;
+
+		clocks =  <&clock_dispcc DISP_CC_MDSS_DP_AUX_CLK>,
+			 <&clock_rpmh RPMH_CXO_CLK>,
+			 <&clock_gcc GCC_USB3_PRIM_CLKREF_CLK>,
+			 <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
+			 <&clock_gcc GCC_USB3_PRIM_PHY_PIPE_CLK>,
+			 <&clock_dispcc DISP_CC_MDSS_DP_LINK_CLK>,
+			 <&clock_dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>,
+			 <&clock_dispcc DISP_CC_MDSS_DP_PIXEL_CLK>,
+			 <&clock_dispcc DISP_CC_MDSS_DP_CRYPTO_CLK>,
+			 <&clock_dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>,
+			 <&mdss_dp_pll DP_VCO_DIVIDED_CLK_SRC_MUX>;
+		clock-names = "core_aux_clk", "core_usb_ref_clk_src",
+			"core_usb_ref_clk", "core_usb_cfg_ahb_clk",
+			"core_usb_pipe_clk", "ctrl_link_clk",
+			"ctrl_link_iface_clk", "ctrl_pixel_clk",
+			"crypto_clk", "pixel_clk_rcg", "pixel_parent";
+
+		qcom,dp-usbpd-detection = <&pm660_pdphy>;
+		qcom,ext-disp = <&ext_disp>;
+
+		qcom,aux-cfg0-settings = [20 00];
+		qcom,aux-cfg1-settings = [24 13 23 1d];
+		qcom,aux-cfg2-settings = [28 24];
+		qcom,aux-cfg3-settings = [2c 00];
+		qcom,aux-cfg4-settings = [30 0a];
+		qcom,aux-cfg5-settings = [34 26];
+		qcom,aux-cfg6-settings = [38 0a];
+		qcom,aux-cfg7-settings = [3c 03];
+		qcom,aux-cfg8-settings = [40 bb];
+		qcom,aux-cfg9-settings = [44 03];
+
+		qcom,max-pclk-frequency-khz = <675000>;
+
+		qcom,core-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			qcom,core-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>;
+			};
+		};
+
+		qcom,ctrl-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			qcom,ctrl-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "vdda-1p2";
+				qcom,supply-min-voltage = <1200000>;
+				qcom,supply-max-voltage = <1200000>;
+				qcom,supply-enable-load = <21800>;
+				qcom,supply-disable-load = <4>;
+			};
+		};
+
+		qcom,phy-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			qcom,phy-supply-entry@0 {
+				reg = <0>;
+				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>;
+			};
+		};
+	};
+};
+
+&sde_dp {
+	status = "disabled";
+	pinctrl-names = "mdss_dp_active", "mdss_dp_sleep";
+	pinctrl-0 = <&sde_dp_aux_active &sde_dp_usbplug_cc_active>;
+	pinctrl-1 = <&sde_dp_aux_suspend &sde_dp_usbplug_cc_suspend>;
+	qcom,aux-en-gpio = <&tlmm 50 0>;
+	qcom,aux-sel-gpio = <&tlmm 40 0>;
+	qcom,usbplug-cc-gpio = <&tlmm 38 0>;
+};
+
+&mdss_mdp {
+	connectors = <&sde_rscc &sde_wb>;
+};
+
+&dsi_dual_nt35597_truly_video {
+	qcom,mdss-dsi-t-clk-post = <0x0D>;
+	qcom,mdss-dsi-t-clk-pre = <0x2D>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <2 0 2>,
+						<1 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+	};
+};
+
+&dsi_dual_nt35597_truly_cmd {
+	qcom,mdss-dsi-t-clk-post = <0x0D>;
+	qcom,mdss-dsi-t-clk-pre = <0x2D>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <2 0 2>,
+						<1 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+	};
+};
+
+&dsi_nt35597_truly_dsc_cmd {
+	qcom,mdss-dsi-t-clk-post = <0x0b>;
+	qcom,mdss-dsi-t-clk-pre = <0x23>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05
+				05 03 03 04 00];
+			qcom,display-topology = <1 1 1>,
+						<2 2 1>, /* dsc merge */
+						<2 1 1>; /* 3d mux */
+			qcom,default-topology-index = <1>;
+		};
+	};
+};
+
+&dsi_nt35597_truly_dsc_video {
+	qcom,mdss-dsi-t-clk-post = <0x0b>;
+	qcom,mdss-dsi-t-clk-pre = <0x23>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05
+				04 03 03 04 00];
+			qcom,display-topology = <1 1 1>,
+						<2 2 1>, /* dsc merge */
+						<2 1 1>; /* 3d mux */
+			qcom,default-topology-index = <1>;
+		};
+	};
+};
+
+&dsi_sim_vid {
+	qcom,mdss-dsi-t-clk-post = <0x0d>;
+	qcom,mdss-dsi-t-clk-pre = <0x2d>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <1 0 1>,
+						<2 0 1>;
+			qcom,default-topology-index = <0>;
+		};
+	};
+};
+
+&dsi_dual_sim_vid {
+	qcom,mdss-dsi-t-clk-post = <0x0d>;
+	qcom,mdss-dsi-t-clk-pre = <0x2d>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <2 0 2>,
+						<1 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+	};
+};
+
+&dsi_sim_cmd {
+	qcom,mdss-dsi-t-clk-post = <0x0d>;
+	qcom,mdss-dsi-t-clk-pre = <0x2d>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <1 0 1>,
+						<2 0 1>;
+			qcom,default-topology-index = <0>;
+		};
+	};
+};
+
+&dsi_dual_sim_cmd {
+	qcom,mdss-dsi-t-clk-post = <0x0d>;
+	qcom,mdss-dsi-t-clk-pre = <0x2d>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 24 09 09 26 24 09
+				09 06 03 04 00];
+			qcom,display-topology = <2 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+		timing@1{
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <2 0 2>,
+						<1 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+		timing@2{
+			qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06
+				06 04 03 04 00];
+			qcom,display-topology = <2 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+	};
+};
+
+&dsi_sim_dsc_375_cmd {
+	qcom,mdss-dsi-t-clk-post = <0x0d>;
+	qcom,mdss-dsi-t-clk-pre = <0x2d>;
+	qcom,mdss-dsi-display-timings {
+		timing@0 { /* 1080p */
+			qcom,mdss-dsi-panel-phy-timings = [00 1A 06 06 22 20 07
+				07 04 03 04 00];
+			qcom,display-topology = <1 1 1>;
+			qcom,default-topology-index = <0>;
+		};
+		timing@1 { /* qhd */
+			qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05
+				05 03 03 04 00];
+			qcom,display-topology = <1 1 1>,
+						<2 2 1>, /* dsc merge */
+						<2 1 1>; /* 3d mux */
+			qcom,default-topology-index = <0>;
+		};
+	};
+};
+
+&dsi_dual_sim_dsc_375_cmd {
+	qcom,mdss-dsi-t-clk-post = <0x0d>;
+	qcom,mdss-dsi-t-clk-pre = <0x2d>;
+	qcom,mdss-dsi-display-timings {
+		timing@0 { /* qhd */
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <2 2 2>;
+			qcom,default-topology-index = <0>;
+		};
+		timing@1 { /* 4k */
+			qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06
+				06 04 03 04 00];
+			qcom,display-topology = <2 2 2>;
+			qcom,default-topology-index = <0>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-sde-pll.dtsi b/arch/arm64/boot/dts/qcom/sdm670-sde-pll.dtsi
new file mode 100644
index 0000000..78e5d94
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-sde-pll.dtsi
@@ -0,0 +1,110 @@
+/* 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.
+ */
+
+&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>;
+			};
+		};
+	};
+
+	mdss_dp_pll: qcom,mdss_dp_pll@88ea000 {
+		compatible = "qcom,mdss_dp_pll_10nm";
+		status = "disabled";
+		label = "MDSS DP PLL";
+		cell-index = <0>;
+		#clock-cells = <1>;
+
+		reg = <0x088ea000 0x200>,
+		      <0x088eaa00 0x200>,
+		      <0x088ea200 0x200>,
+		      <0x088ea600 0x200>,
+		      <0xaf03000 0x8>;
+		reg-names = "pll_base", "phy_base", "ln_tx0_base",
+			"ln_tx1_base", "gdsc_base";
+
+		gdsc-supply = <&mdss_core_gdsc>;
+
+		clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>,
+			 <&clock_rpmh RPMH_CXO_CLK>,
+			 <&clock_gcc GCC_USB3_PRIM_CLKREF_CLK>,
+			 <&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
+			 <&clock_gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
+		clock-names = "iface_clk", "ref_clk_src", "ref_clk",
+			"cfg_ahb_clk", "pipe_clk";
+		clock-rate = <0>;
+
+		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/sdm670-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi
new file mode 100644
index 0000000..bb30a20
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi
@@ -0,0 +1,532 @@
+/* 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.
+ */
+
+&soc {
+	mdss_mdp: qcom,mdss_mdp@ae00000 {
+		compatible = "qcom,sde-kms";
+		reg = <0x0ae00000 0x81d40>,
+		      <0x0aeb0000 0x2008>,
+		      <0x0aeac000 0xf0>;
+		reg-names = "mdp_phys",
+			"vbif_phys",
+			"regdma_phys";
+
+		clocks =
+			<&clock_gcc GCC_DISP_AHB_CLK>,
+			<&clock_gcc GCC_DISP_AXI_CLK>,
+			<&clock_dispcc DISP_CC_MDSS_AHB_CLK>,
+			<&clock_dispcc DISP_CC_MDSS_AXI_CLK>,
+			<&clock_dispcc DISP_CC_MDSS_MDP_CLK>,
+			<&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>;
+		clock-names = "gcc_iface", "gcc_bus", "iface_clk",
+				"bus_clk", "core_clk", "vsync_clk";
+		clock-rate = <0 0 0 0 300000000 19200000 0>;
+		clock-max-rate = <0 0 0 0 412500000 19200000 0>;
+
+		sde-vdd-supply = <&mdss_core_gdsc>;
+
+		/* interrupt config */
+		interrupt-parent = <&pdc>;
+		interrupts = <0 83 0>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		iommus = <&apps_smmu 0x880 0x8>,
+			<&apps_smmu 0xc80 0x8>;
+
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		/* hw blocks */
+		qcom,sde-off = <0x1000>;
+		qcom,sde-len = <0x45C>;
+
+		qcom,sde-ctl-off = <0x2000 0x2200 0x2400
+				     0x2600 0x2800>;
+		qcom,sde-ctl-size = <0xE4>;
+
+		qcom,sde-mixer-off = <0x45000 0x46000 0x47000
+				      0x48000 0x49000 0x4a000>;
+		qcom,sde-mixer-size = <0x320>;
+
+		qcom,sde-dspp-top-off = <0x1300>;
+		qcom,sde-dspp-top-size = <0xc>;
+
+		qcom,sde-dspp-off = <0x55000 0x57000>;
+		qcom,sde-dspp-size = <0x17e0>;
+
+		qcom,sde-wb-off = <0x66000>;
+		qcom,sde-wb-size = <0x2c8>;
+		qcom,sde-wb-xin-id = <6>;
+		qcom,sde-wb-id = <2>;
+		qcom,sde-wb-clk-ctrl = <0x3b8 24>;
+
+		qcom,sde-intf-off = <0x6b000 0x6b800
+					0x6c000 0x6c800>;
+		qcom,sde-intf-size = <0x280>;
+
+		qcom,sde-intf-type = "dp", "dsi", "dsi", "dp";
+		qcom,sde-pp-off = <0x71000 0x71800
+					  0x72000 0x72800 0x73000>;
+		qcom,sde-pp-slave = <0x0 0x0 0x0 0x0 0x1>;
+		qcom,sde-pp-size = <0xd4>;
+
+		qcom,sde-te2-off = <0x2000 0x2000 0x0 0x0 0x0>;
+		qcom,sde-cdm-off = <0x7a200>;
+		qcom,sde-cdm-size = <0x224>;
+
+		qcom,sde-dsc-off = <0x81000 0x81400>;
+		qcom,sde-dsc-size = <0x140>;
+
+		qcom,sde-dither-off = <0x30e0 0x30e0 0x30e0 0x30e0 0x0>;
+		qcom,sde-dither-version = <0x00010000>;
+		qcom,sde-dither-size = <0x20>;
+
+		qcom,sde-sspp-type = "vig", "vig",
+					"dma", "dma", "dma";
+
+		qcom,sde-sspp-off = <0x5000 0x7000 0x25000 0x27000 0x29000>;
+		qcom,sde-sspp-src-size = <0x1c8>;
+
+		qcom,sde-sspp-xin-id = <0 4 1 5 9>;
+		qcom,sde-sspp-excl-rect = <1 1 1 1 1>;
+		qcom,sde-sspp-smart-dma-priority = <4 5 1 2 3>;
+		qcom,sde-smart-dma-rev = "smart_dma_v2";
+
+		qcom,sde-mixer-pair-mask = <2 1 6 0 0 3>;
+
+		qcom,sde-mixer-blend-op-off = <0x20 0x38 0x50 0x68 0x80 0x98
+						0xb0 0xc8 0xe0 0xf8 0x110>;
+
+		/* offsets are relative to "mdp_phys + qcom,sde-off */
+		qcom,sde-sspp-clk-ctrl =
+				<0x2ac 0>, <0x2b4 0>,
+				 <0x2ac 8>, <0x2b4 8>, <0x2bc 8>;
+		qcom,sde-sspp-csc-off = <0x1a00>;
+		qcom,sde-csc-type = "csc-10bit";
+		qcom,sde-qseed-type = "qseedv3";
+		qcom,sde-sspp-qseed-off = <0xa00>;
+		qcom,sde-mixer-linewidth = <2560>;
+		qcom,sde-sspp-linewidth = <2560>;
+		qcom,sde-wb-linewidth = <4096>;
+		qcom,sde-mixer-blendstages = <0xb>;
+		qcom,sde-highest-bank-bit = <0x1>;
+		qcom,sde-ubwc-version = <0x200>;
+		qcom,sde-panic-per-pipe;
+		qcom,sde-has-cdp;
+		qcom,sde-has-src-split;
+		qcom,sde-has-dim-layer;
+		qcom,sde-has-idle-pc;
+		qcom,sde-max-bw-low-kbps = <9600000>;
+		qcom,sde-max-bw-high-kbps = <9600000>;
+		qcom,sde-dram-channels = <2>;
+		qcom,sde-num-nrt-paths = <0>;
+		qcom,sde-dspp-ad-version = <0x00040000>;
+		qcom,sde-dspp-ad-off = <0x28000 0x27000>;
+
+		qcom,sde-vbif-off = <0>;
+		qcom,sde-vbif-size = <0x1040>;
+		qcom,sde-vbif-id = <0>;
+		qcom,sde-vbif-memtype-0 = <3 3 3 3 3 3 3 3>;
+		qcom,sde-vbif-memtype-1 = <3 3 3 3 3 3>;
+
+		qcom,sde-vbif-qos-rt-remap = <3 3 4 4 5 5 6 6>;
+		qcom,sde-vbif-qos-nrt-remap = <3 3 3 3 3 3 3 3>;
+
+		qcom,sde-danger-lut = <0x0000000f 0x0000ffff 0x00000000
+			0x00000000>;
+		qcom,sde-safe-lut = <0xfffc 0xff00 0xffff 0xffff>;
+		qcom,sde-qos-lut-linear =
+			<4 0x00000000 0x00000357>,
+			<5 0x00000000 0x00003357>,
+			<6 0x00000000 0x00023357>,
+			<7 0x00000000 0x00223357>,
+			<8 0x00000000 0x02223357>,
+			<9 0x00000000 0x22223357>,
+			<10 0x00000002 0x22223357>,
+			<11 0x00000022 0x22223357>,
+			<12 0x00000222 0x22223357>,
+			<13 0x00002222 0x22223357>,
+			<14 0x00012222 0x22223357>,
+			<0 0x00112222 0x22223357>;
+		qcom,sde-qos-lut-macrotile =
+			<10 0x00000003 0x44556677>,
+			<11 0x00000033 0x44556677>,
+			<12 0x00000233 0x44556677>,
+			<13 0x00002233 0x44556677>,
+			<14 0x00012233 0x44556677>,
+			<0 0x00112233 0x44556677>;
+		qcom,sde-qos-lut-nrt =
+			<0 0x00000000 0x00000000>;
+		qcom,sde-qos-lut-cwb =
+			<0 0x75300000 0x00000000>;
+
+		qcom,sde-cdp-setting = <1 1>, <1 0>;
+
+		qcom,sde-inline-rotator = <&mdss_rotator 0>;
+		qcom,sde-inline-rot-xin = <10 11>;
+		qcom,sde-inline-rot-xin-type = "sspp", "wb";
+
+		/* offsets are relative to "mdp_phys + qcom,sde-off */
+		qcom,sde-inline-rot-clk-ctrl = <0x2bc 0x8>, <0x2bc 0xc>;
+
+		qcom,sde-reg-dma-off = <0>;
+		qcom,sde-reg-dma-version = <0x1>;
+		qcom,sde-reg-dma-trigger-off = <0x119c>;
+
+		qcom,sde-sspp-vig-blocks {
+			qcom,sde-vig-csc-off = <0x1a00>;
+			qcom,sde-vig-qseed-off = <0xa00>;
+			qcom,sde-vig-qseed-size = <0xa0>;
+		};
+
+		qcom,sde-dspp-blocks {
+			qcom,sde-dspp-igc = <0x0 0x00030001>;
+			qcom,sde-dspp-vlut = <0xa00 0x00010008>;
+			qcom,sde-dspp-gamut = <0x1000 0x00040000>;
+			qcom,sde-dspp-pcc = <0x1700 0x00040000>;
+			qcom,sde-dspp-gc = <0x17c0 0x00010008>;
+		};
+
+		qcom,platform-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			qcom,platform-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "sde-vdd";
+				qcom,supply-min-voltage = <0>;
+				qcom,supply-max-voltage = <0>;
+				qcom,supply-enable-load = <0>;
+				qcom,supply-disable-load = <0>;
+			};
+		};
+
+		smmu_sde_sec: qcom,smmu_sde_sec_cb {
+			compatible = "qcom,smmu_sde_sec";
+			iommus = <&apps_smmu 0x881 0x8>,
+			       <&apps_smmu 0xc81 0x8>;
+		};
+
+		/* data and reg bus scale settings */
+		qcom,sde-data-bus {
+			qcom,msm-bus,name = "mdss_sde_mnoc";
+			qcom,msm-bus,num-cases = <3>;
+			qcom,msm-bus,num-paths = <2>;
+			qcom,msm-bus,vectors-KBps =
+			    <22 773 0 0>, <23 773 0 0>,
+			    <22 773 0 6400000>, <23 773 0 6400000>,
+			    <22 773 0 6400000>, <23 773 0 6400000>;
+		};
+
+		qcom,sde-llcc-bus {
+			qcom,msm-bus,name = "mdss_sde_llcc";
+			qcom,msm-bus,num-cases = <3>;
+			qcom,msm-bus,num-paths = <1>;
+			qcom,msm-bus,vectors-KBps =
+			    <132 770 0 0>,
+			    <132 770 0 6400000>,
+			    <132 770 0 6400000>;
+		};
+
+		qcom,sde-ebi-bus {
+			qcom,msm-bus,name = "mdss_sde_ebi";
+			qcom,msm-bus,num-cases = <3>;
+			qcom,msm-bus,num-paths = <1>;
+			qcom,msm-bus,vectors-KBps =
+			    <129 512 0 0>,
+			    <129 512 0 6400000>,
+			    <129 512 0 6400000>;
+		};
+
+		qcom,sde-reg-bus {
+			qcom,msm-bus,name = "mdss_reg";
+			qcom,msm-bus,num-cases = <4>;
+			qcom,msm-bus,num-paths = <1>;
+			qcom,msm-bus,active-only;
+			qcom,msm-bus,vectors-KBps =
+				<1 590 0 0>,
+				<1 590 0 76800>,
+				<1 590 0 150000>,
+				<1 590 0 300000>;
+		};
+	};
+
+	sde_rscc: qcom,sde_rscc@af20000 {
+		cell-index = <0>;
+		compatible = "qcom,sde-rsc";
+		reg = <0xaf20000 0x1c44>,
+			<0xaf30000 0x3fd4>;
+		reg-names = "drv", "wrapper";
+		qcom,sde-rsc-version = <1>;
+
+		vdd-supply = <&mdss_core_gdsc>;
+		clocks = <&clock_dispcc DISP_CC_MDSS_RSCC_VSYNC_CLK>,
+			<&clock_dispcc DISP_CC_MDSS_RSCC_AHB_CLK>;
+		clock-names = "vsync_clk", "iface_clk";
+		clock-rate = <0 0>;
+
+		qcom,sde-dram-channels = <2>;
+
+		mboxes = <&disp_rsc 0>;
+		mbox-names = "disp_rsc";
+
+		/* data and reg bus scale settings */
+		qcom,sde-data-bus {
+			qcom,msm-bus,name = "disp_rsc_mnoc";
+			qcom,msm-bus,active-only;
+			qcom,msm-bus,num-cases = <3>;
+			qcom,msm-bus,num-paths = <2>;
+			qcom,msm-bus,vectors-KBps =
+			    <20003 20515 0 0>, <20004 20515 0 0>,
+			    <20003 20515 0 6400000>, <20004 20515 0 6400000>,
+			    <20003 20515 0 6400000>, <20004 20515 0 6400000>;
+		};
+
+		qcom,sde-llcc-bus {
+			qcom,msm-bus,name = "disp_rsc_llcc";
+			qcom,msm-bus,active-only;
+			qcom,msm-bus,num-cases = <3>;
+			qcom,msm-bus,num-paths = <1>;
+			qcom,msm-bus,vectors-KBps =
+			    <20001 20513 0 0>,
+			    <20001 20513 0 6400000>,
+			    <20001 20513 0 6400000>;
+		};
+
+		qcom,sde-ebi-bus {
+			qcom,msm-bus,name = "disp_rsc_ebi";
+			qcom,msm-bus,active-only;
+			qcom,msm-bus,num-cases = <3>;
+			qcom,msm-bus,num-paths = <1>;
+			qcom,msm-bus,vectors-KBps =
+			    <20000 20512 0 0>,
+			    <20000 20512 0 6400000>,
+			    <20000 20512 0 6400000>;
+		};
+	};
+
+	mdss_rotator: qcom,mdss_rotator@ae00000 {
+		compatible = "qcom,sde_rotator";
+		reg = <0x0ae00000 0xac000>,
+		      <0x0aeb8000 0x3000>;
+		reg-names = "mdp_phys",
+			"rot_vbif_phys";
+
+		#list-cells = <1>;
+
+		qcom,mdss-rot-mode = <1>;
+		qcom,mdss-highest-bank-bit = <0x1>;
+
+		/* Bus Scale Settings */
+		qcom,msm-bus,name = "mdss_rotator";
+		qcom,msm-bus,num-cases = <3>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<25 512 0 0>,
+			<25 512 0 6400000>,
+			<25 512 0 6400000>;
+
+		rot-vdd-supply = <&mdss_core_gdsc>;
+		qcom,supply-names = "rot-vdd";
+
+		clocks =
+			<&clock_gcc GCC_DISP_AHB_CLK>,
+			<&clock_gcc GCC_DISP_AXI_CLK>,
+			<&clock_dispcc DISP_CC_MDSS_AHB_CLK>,
+			<&clock_dispcc DISP_CC_MDSS_ROT_CLK>,
+			<&clock_dispcc DISP_CC_MDSS_AXI_CLK>;
+		clock-names = "gcc_iface", "gcc_bus",
+			"iface_clk", "rot_clk", "axi_clk";
+
+		interrupt-parent = <&mdss_mdp>;
+		interrupts = <2 0>;
+
+		/* Offline rotator QoS setting */
+		qcom,mdss-rot-vbif-qos-setting = <3 3 3 3 3 3 3 3>;
+		qcom,mdss-rot-vbif-memtype = <3 3>;
+		qcom,mdss-rot-cdp-setting = <1 1>;
+		qcom,mdss-rot-qos-lut = <0x0 0x0 0x0 0x0>;
+		qcom,mdss-rot-danger-lut = <0x0 0x0>;
+		qcom,mdss-rot-safe-lut = <0x0000ffff 0x0000ffff>;
+
+		/* Inline rotator QoS Setting */
+		/* setting default register values for RD - qos/danger/safe */
+		qcom,mdss-inline-rot-qos-lut = <0x44556677 0x00112233
+							0x44556677 0x00112233>;
+		qcom,mdss-inline-rot-danger-lut = <0x0055aaff 0x0000ffff>;
+		qcom,mdss-inline-rot-safe-lut = <0x0000f000 0x0000ff00>;
+
+		qcom,mdss-default-ot-rd-limit = <32>;
+		qcom,mdss-default-ot-wr-limit = <32>;
+
+		qcom,mdss-sbuf-headroom = <20>;
+
+		cache-slice-names = "rotator";
+		cache-slices = <&llcc 4>;
+
+		/* reg bus scale settings */
+		rot_reg: qcom,rot-reg-bus {
+			qcom,msm-bus,name = "mdss_rot_reg";
+			qcom,msm-bus,num-cases = <2>;
+			qcom,msm-bus,num-paths = <1>;
+			qcom,msm-bus,active-only;
+			qcom,msm-bus,vectors-KBps =
+				<1 590 0 0>,
+				<1 590 0 76800>;
+		};
+
+		smmu_rot_unsec: qcom,smmu_rot_unsec_cb {
+			compatible = "qcom,smmu_sde_rot_unsec";
+			iommus = <&apps_smmu 0x1090 0x0>;
+		};
+
+		smmu_rot_sec: qcom,smmu_rot_sec_cb {
+			compatible = "qcom,smmu_sde_rot_sec";
+			iommus = <&apps_smmu 0x1091 0x0>;
+		};
+	};
+
+	mdss_dsi0: qcom,mdss_dsi_ctrl0@ae94000 {
+		compatible = "qcom,dsi-ctrl-hw-v2.2";
+		label = "dsi-ctrl-0";
+		cell-index = <0>;
+		reg =   <0xae94000 0x400>,
+			<0xaf08000 0x4>;
+		reg-names = "dsi_ctrl", "disp_cc_base";
+		interrupt-parent = <&mdss_mdp>;
+		interrupts = <4 0>;
+		vdda-1p2-supply = <&pm660_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_ESC0_CLK>;
+		clock-names = "byte_clk", "byte_clk_rcg", "byte_intf_clk",
+					"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-1p2";
+				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.2";
+		label = "dsi-ctrl-1";
+		cell-index = <1>;
+		reg =   <0xae96000 0x400>,
+			<0xaf08000 0x4>;
+		reg-names = "dsi_ctrl", "disp_cc_base";
+		interrupt-parent = <&mdss_mdp>;
+		interrupts = <5 0>;
+		vdda-1p2-supply = <&pm660_l1>;
+		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", "esc_clk";
+		qcom,ctrl-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			qcom,ctrl-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "vdda-1p2";
+				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";
+		label = "dsi-phy-0";
+		cell-index = <0>;
+		reg = <0xae94400 0x7c0>;
+		reg-names = "dsi_phy";
+		gdsc-supply = <&mdss_core_gdsc>;
+		vdda-0p9-supply = <&pm660l_l1>;
+		qcom,platform-strength-ctrl = [55 03
+						55 03
+						55 03
+						55 03
+						55 00];
+		qcom,platform-lane-config = [00 00 00 00
+						00 00 00 00
+						00 00 00 00
+						00 00 00 00
+						00 00 00 80];
+		qcom,platform-regulator-settings = [1d 1d 1d 1d 1d];
+		qcom,phy-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			qcom,phy-supply-entry@0 {
+				reg = <0>;
+				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";
+		label = "dsi-phy-1";
+		cell-index = <1>;
+		reg = <0xae96400 0x7c0>;
+		reg-names = "dsi_phy";
+		gdsc-supply = <&mdss_core_gdsc>;
+		vdda-0p9-supply = <&pm660l_l1>;
+		qcom,platform-strength-ctrl = [55 03
+						55 03
+						55 03
+						55 03
+						55 00];
+		qcom,platform-regulator-settings = [1d 1d 1d 1d 1d];
+		qcom,platform-lane-config = [00 00 00 00
+						00 00 00 00
+						00 00 00 00
+						00 00 00 00
+						00 00 00 80];
+		qcom,phy-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			qcom,phy-supply-entry@0 {
+				reg = <0>;
+				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/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index c8bb003..f0c1c92 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -614,6 +614,10 @@
 
 #include "sdm670-vidc.dtsi"
 
+#include "sdm670-sde-pll.dtsi"
+
+#include "sdm670-sde.dtsi"
+
 &soc {
 	#address-cells = <1>;
 	#size-cells = <1>;
@@ -646,6 +650,14 @@
 		qcom,pipe-attr-ee;
 	};
 
+	qcom,qbt1000 {
+		compatible = "qcom,qbt1000";
+		clock-names = "core", "iface";
+		clock-frequency = <25000000>;
+		qcom,ipc-gpio = <&tlmm 121 0>;
+		qcom,finger-detect-gpio = <&tlmm 122 0>;
+	};
+
 	thermal_zones: thermal-zones {};
 
 	tsens0: tsens@c222000 {
@@ -833,7 +845,7 @@
 	};
 
 	clock_aop: qcom,aopclk {
-		compatible = "qcom,aop-qmp-clk-v2";
+		compatible = "qcom,aop-qmp-clk-v1";
 		#clock-cells = <1>;
 		mboxes = <&qmp_aop 0>;
 		mbox-names = "qdss_clk";
@@ -1675,17 +1687,17 @@
 			<90 512 80000 640000>,
 			<90 585 80000 640000>,
 			<1 676 80000 80000>,
-			<143 777 0 150000>,
+			<143 777 0 150>, /* IB defined for IPA clk in MHz*/
 		/* NOMINAL */
 			<90 512 206000 960000>,
 			<90 585 206000 960000>,
 			<1 676 206000 160000>,
-			<143 777 0 300000>,
+			<143 777 0 300>, /* IB defined for IPA clk in MHz*/
 		/* TURBO */
 			<90 512 206000 3600000>,
 			<90 585 206000 3600000>,
 			<1 676 206000 300000>,
-			<143 777 0 355333>;
+			<143 777 0 355>; /* IB defined for IPA clk in MHz*/
 		qcom,bus-vector-names = "MIN", "SVS", "NOMINAL", "TURBO";
 
 		/* IPA RAM mmap */
@@ -2270,8 +2282,21 @@
 				< 2438400 6881 >;
 		};
 	};
+
+	gpu_gx_domain_addr: syscon@0x5091508 {
+		compatible = "syscon";
+		reg = <0x5091508 0x4>;
+	};
+
+	gpu_gx_sw_reset: syscon@0x5091008 {
+		compatible = "syscon";
+		reg = <0x5091008 0x4>;
+	};
 };
 
+#include "pm660.dtsi"
+#include "pm660l.dtsi"
+#include "sdm670-regulator.dtsi"
 #include "sdm670-pinctrl.dtsi"
 #include "msm-arm-smmu-sdm670.dtsi"
 #include "msm-gdsc-sdm845.dtsi"
@@ -2346,6 +2371,9 @@
 	clocks = <&clock_gfx GPU_CC_GX_GFX3D_CLK_SRC>;
 	qcom,force-enable-root-clk;
 	parent-supply = <&pm660l_s2_level>;
+	domain-addr = <&gpu_gx_domain_addr>;
+	sw-reset = <&gpu_gx_sw_reset>;
+	qcom,reset-aon-logic;
 	status = "ok";
 };
 
@@ -2363,9 +2391,6 @@
 	status = "ok";
 };
 
-#include "pm660.dtsi"
-#include "pm660l.dtsi"
-#include "sdm670-regulator.dtsi"
 #include "sdm670-audio.dtsi"
 #include "sdm670-usb.dtsi"
 #include "sdm670-gpu.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
index e36a759e..5578ece 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
@@ -216,11 +216,11 @@
 
 &clock_gpucc {
 	/delete-property/ vdd_cx-supply;
+	/delete-property/ vdd_mx-supply;
 };
 
 &clock_gfx {
 	/delete-property/ vdd_gfx-supply;
-	/delete-property/ vdd_mx-supply;
 };
 
 &pil_modem {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-audio-overlay.dtsi
new file mode 100644
index 0000000..54bd5201
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-audio-overlay.dtsi
@@ -0,0 +1,53 @@
+/* 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.
+ */
+#include "sdm670-audio-overlay.dtsi"
+
+&pm660l_3 {
+	/delete-node/analog-codec;
+};
+
+&soc {
+	/delete-node/msm-sdw-codec@62ec1000;
+	/delete-node/cdc_pdm_pinctrl;
+	/delete-node/wsa_spkr_en1_pinctrl;
+	/delete-node/wsa_spkr_en2_pinctrl;
+	/delete-node/sdw_clk_data_pinctrl;
+};
+
+&qupv3_se8_spi {
+	status = "okay";
+};
+
+&wcd9xxx_intc {
+	status = "okay";
+	qcom,gpio-connect = <&tlmm 54 0>;
+};
+
+&wdsp_mgr {
+	status = "okay";
+};
+
+&wdsp_glink {
+	status = "okay";
+};
+
+&wcd934x_cdc {
+	status = "okay";
+};
+
+&clock_audio_lnbb {
+	status = "okay";
+};
+
+&wcd_rst_gpio {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-audio.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-audio.dtsi
index f861ca3..88892d7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-audio.dtsi
@@ -10,44 +10,17 @@
  * GNU General Public License for more details.
  */
 
-#include "sdm670-audio.dtsi"
 
 &msm_audio_ion {
 	iommus = <&apps_smmu 0x1821 0x0>;
 	qcom,smmu-sid-mask = /bits/ 64 <0xf>;
 };
 
-&qupv3_se8_spi {
-	status = "okay";
-};
-
-&pm660l_3 {
-	/delete-node/analog-codec;
-};
-
 &soc {
-	/delete-node/msm-sdw-codec@62ec1000;
 	/delete-node/sound;
-	/delete-node/cdc_pdm_pinctrl;
-	/delete-node/wsa_spkr_en1_pinctrl;
-	/delete-node/wsa_spkr_en2_pinctrl;
-	/delete-node/sdw_clk_data_pinctrl;
 };
 
-&msm_audio_ion {
-	iommus = <&apps_smmu 0x1821 0x0>;
-};
-
-&wcd9xxx_intc {
-	status = "okay";
-	qcom,gpio-connect = <&tlmm 54 0>;
-};
-
-&wdsp_mgr {
-	status = "okay";
-};
-
-&wdsp_glink {
+&tavil_snd {
 	status = "okay";
 };
 
@@ -58,24 +31,3 @@
 &dai_slim {
 	status = "okay";
 };
-
-&wcd934x_cdc {
-	status = "okay";
-};
-
-&clock_audio_lnbb {
-	status = "okay";
-};
-
-&wcd_rst_gpio {
-	status = "okay";
-};
-
-&wcd9xxx_intc {
-	status = "okay";
-};
-
-&tavil_snd {
-	status = "okay";
-};
-
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp-overlay.dts
index da59bcf..9d61324 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp-overlay.dts
@@ -21,7 +21,7 @@
 
 #include "sdm845-sde-display.dtsi"
 #include "sdm845-interposer-sdm670-cdp.dtsi"
-
+#include "sdm845-interposer-sdm670-audio-overlay.dtsi"
 / {
 	model = "Qualcomm Technologies, Inc. SDM845 v1 Interposer SDM670 CDP";
 	compatible = "qcom,sdm845-cdp", "qcom,sdm845", "qcom,cdp";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dts
index ebb5e8f..597773e 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dts
@@ -16,6 +16,8 @@
 #include "sdm845-interposer-sdm670.dtsi"
 #include "sdm845-sde-display.dtsi"
 #include "sdm845-interposer-sdm670-cdp.dtsi"
+#include "sdm670-audio.dtsi"
+#include "sdm845-interposer-sdm670-audio.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. MSM sdm845 v1 Interposer SDM670 CDP";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi
index e435cdd..1265d2a 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-cdp.dtsi
@@ -12,7 +12,6 @@
 
 #include "sdm845-cdp.dtsi"
 #include "sdm845-interposer-pm660.dtsi"
-#include "sdm845-interposer-sdm670-audio.dtsi"
 
 &soc {
 	/delete-node/ ssusb@a800000;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp-overlay.dts
index 3ca15b9..1690174 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp-overlay.dts
@@ -21,7 +21,7 @@
 
 #include "sdm845-sde-display.dtsi"
 #include "sdm845-interposer-sdm670-mtp.dtsi"
-
+#include "sdm845-interposer-sdm670-audio-overlay.dtsi"
 / {
 	model = "Qualcomm Technologies, Inc. SDM845 v1 Interposer SDM670 MTP";
 	compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dts b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dts
index 39664f1..52869da 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dts
@@ -16,6 +16,8 @@
 #include "sdm845-interposer-sdm670.dtsi"
 #include "sdm845-sde-display.dtsi"
 #include "sdm845-interposer-sdm670-mtp.dtsi"
+#include "sdm670-audio.dtsi"
+#include "sdm845-interposer-sdm670-audio.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. MSM sdm845 v1 Interposer SDM670 MTP";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi
index 4b24b0d..9d722df 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-sdm670-mtp.dtsi
@@ -12,7 +12,6 @@
 
 #include "sdm845-mtp.dtsi"
 #include "sdm845-interposer-pm660.dtsi"
-#include "sdm845-interposer-sdm670-audio.dtsi"
 
 &qupv3_se10_i2c {
 	/delete-node/ qcom,smb1355@8;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
index 0b55736..80ef35f 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
@@ -57,7 +57,7 @@
 		qcom,cpr-saw-use-unit-mV;
 
 		qcom,saw-avs-ctrl = <0x101C031>;
-		qcom,saw-avs-limit = <0x3B803B8>;
+		qcom,saw-avs-limit = <0x3E803E8>;
 
 		qcom,cpr-enable;
 		qcom,cpr-hw-closed-loop;
@@ -85,9 +85,9 @@
 				regulator-max-microvolt = <18>;
 
 				qcom,cpr-fuse-corners = <4>;
-				qcom,cpr-fuse-combos = <16>;
-				qcom,cpr-speed-bins = <2>;
-				qcom,cpr-speed-bin-corners = <18 18>;
+				qcom,cpr-fuse-combos = <24>;
+				qcom,cpr-speed-bins = <3>;
+				qcom,cpr-speed-bin-corners = <18 18 18>;
 				qcom,cpr-corners = <18>;
 
 				qcom,cpr-corner-fmax-map = <6 12 15 18>;
@@ -133,10 +133,62 @@
 					 1950 2632>;
 
 				qcom,cpr-open-loop-voltage-fuse-adjustment =
-					<     0      0  12000  12000>;
+					/* Speed bin 0 */
+					<      0        0    12000    12000>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					/* Speed bin 1 */
+					<      0        0    12000    12000>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					/* Speed bin 2 */
+					<      0        0    12000    12000>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>,
+					<(-15000) (-15000)  (-3000)  (-3000)>;
 
 				qcom,cpr-closed-loop-voltage-fuse-adjustment =
-					<     0      0  12000  10000>;
+					/* Speed bin 0 */
+					<      0        0    12000    10000>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					/* Speed bin 1 */
+					<      0        0    12000    10000>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					/* Speed bin 2 */
+					<      0        0    12000    10000>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>,
+					<(-15000) (-15000)  (-3000)  (-5000)>;
 
 				qcom,allow-voltage-interpolation;
 				qcom,allow-quotient-interpolation;
@@ -149,6 +201,8 @@
 					/* Speed bin 0 */
 					<0 1 1 1 1 1 1 1>,
 					/* Speed bin 1 */
+					<0 1 1 1 1 1 1 1>,
+					/* Speed bin 2 */
 					<0 1 1 1 1 1 1 1>;
 				qcom,allow-aging-open-loop-voltage-adjustment =
 					<1>;
@@ -168,19 +222,23 @@
 				regulator-max-microvolt = <15>;
 
 				qcom,cpr-fuse-corners = <4>;
-				qcom,cpr-fuse-combos = <16>;
-				qcom,cpr-speed-bins = <2>;
-				qcom,cpr-speed-bin-corners = <14 15>;
+				qcom,cpr-fuse-combos = <24>;
+				qcom,cpr-speed-bins = <3>;
+				qcom,cpr-speed-bin-corners = <14 15 15>;
 				qcom,cpr-corners =
 					/* Speed bin 0 */
 					<14 14 14 14 14 14 14 14>,
 					/* Speed bin 1 */
+					<15 15 15 15 15 15 15 15>,
+					/* Speed bin 2 */
 					<15 15 15 15 15 15 15 15>;
 
 				qcom,cpr-corner-fmax-map =
 					/* Speed bin 0 */
 					<4 8 11 14>,
 					/* Speed bin 1 */
+					<4 8 11 15>,
+					/* Speed bin 2 */
 					<4 8 11 15>;
 
 				qcom,cpr-voltage-ceiling =
@@ -192,6 +250,11 @@
 					<828000  828000  828000  828000  828000
 					 828000  828000  828000  828000  828000
 					 828000  932000  932000 1000000
+					1000000>,
+					/* Speed bin 2 */
+					<828000  828000  828000  828000  828000
+					 828000  828000  828000  828000  828000
+					 828000  932000  932000 1000000
 					1000000>;
 
 				qcom,cpr-voltage-floor =
@@ -203,6 +266,11 @@
 					<568000  568000  568000  568000  568000
 					 568000  568000  568000  568000  568000
 					 568000  568000  568000  568000
+					 568000>,
+					/* Speed bin 2 */
+					<568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000
 					 568000>;
 
 				qcom,cpr-floor-to-ceiling-max-range =
@@ -213,6 +281,10 @@
 					/* Speed bin 1 */
 					<32000  32000  32000  32000  32000
 					 32000  32000  32000  32000  32000
+					 32000  32000  32000  40000  40000>,
+					/* Speed bin 2 */
+					<32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
 					 32000  32000  32000  40000  40000>;
 
 				qcom,corner-frequencies =
@@ -227,6 +299,12 @@
 					 576000000  652800000  748800000
 					 844800000  940800000 1036800000
 					1132800000 1209600000 1305600000
+					1401600000 1497600000 1593600000>,
+					/* Speed bin 2 */
+					<300000000  403200000  480000000
+					 576000000  652800000  748800000
+					 844800000  940800000 1036800000
+					1132800000 1209600000 1305600000
 					1401600000 1497600000 1593600000>;
 
 				qcom,cpr-ro-scaling-factor =
@@ -244,22 +322,76 @@
 					 2501 2095>;
 
 				qcom,cpr-open-loop-voltage-fuse-adjustment =
-					<  8000  16000  16000  12000>;
+					/* Speed bin 0 */
+					<   8000    16000    16000    12000>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					/* Speed bin 1 */
+					<   8000    16000    16000    12000>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					/* Speed bin 2 */
+					<   8000    16000    16000    12000>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>,
+					< (-7000)    1000     1000   (-3000)>;
 
 				qcom,cpr-closed-loop-voltage-fuse-adjustment =
-					<  6000  14000  16000  12000>;
+					/* Speed bin 0 */
+					<   6000    14000    16000    12000>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					/* Speed bin 1 */
+					<   6000    14000    16000    12000>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					/* Speed bin 2 */
+					<   6000    14000    16000    12000>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>,
+					< (-9000)  (-1000)    1000   (-3000)>;
 
 				qcom,allow-voltage-interpolation;
 				qcom,allow-quotient-interpolation;
 				qcom,cpr-scaled-open-loop-voltage-as-ceiling;
 
 				qcom,cpr-aging-max-voltage-adjustment = <15000>;
-				qcom,cpr-aging-ref-corner = <14 15>;
+				qcom,cpr-aging-ref-corner = <14 15 15>;
 				qcom,cpr-aging-ro-scaling-factor = <1620>;
 				qcom,allow-aging-voltage-adjustment =
 					/* Speed bin 0 */
 					<0 1 1 1 1 1 1 1>,
 					/* Speed bin 1 */
+					<0 1 1 1 1 1 1 1>,
+					/* Speed bin 2 */
 					<0 1 1 1 1 1 1 1>;
 				qcom,allow-aging-open-loop-voltage-adjustment =
 					<1>;
@@ -302,7 +434,7 @@
 		qcom,cpr-saw-use-unit-mV;
 
 		qcom,saw-avs-ctrl = <0x101C031>;
-		qcom,saw-avs-limit = <0x4700470>;
+		qcom,saw-avs-limit = <0x4880488>;
 
 		qcom,cpr-enable;
 		qcom,cpr-hw-closed-loop;
@@ -312,7 +444,7 @@
 		qcom,cpr-panic-reg-name-list =
 			"APSS_GOLD_CPRH_STATUS_0", "GOLD_SAW4_PMIC_STS";
 
-		qcom,cpr-aging-ref-voltage = <1136000>;
+		qcom,cpr-aging-ref-voltage = <1160000>;
 		vdd-supply = <&pm8998_s12>;
 
 		thread@0 {
@@ -325,23 +457,27 @@
 			apc1_perfcl_vreg: regulator {
 				regulator-name = "apc1_perfcl_corner";
 				regulator-min-microvolt = <1>;
-				regulator-max-microvolt = <33>;
+				regulator-max-microvolt = <35>;
 
 				qcom,cpr-fuse-corners = <5>;
-				qcom,cpr-fuse-combos = <16>;
-				qcom,cpr-speed-bins = <2>;
-				qcom,cpr-speed-bin-corners = <28 31>;
+				qcom,cpr-fuse-combos = <24>;
+				qcom,cpr-speed-bins = <3>;
+				qcom,cpr-speed-bin-corners = <28 31 33>;
 				qcom,cpr-corners =
 					/* Speed bin 0 */
 					<28 28 28 28 28 28 28 28>,
 					/* Speed bin 1 */
-					<31 31 31 31 31 31 31 31>;
+					<31 31 31 31 31 31 31 31>,
+					/* Speed bin 2 */
+					<33 33 33 33 33 33 33 33>;
 
 				qcom,cpr-corner-fmax-map =
 					/* Speed bin 0 */
 					<7 14 22 27 28>,
 					/* Speed bin 1 */
-					<7 14 22 27 31>;
+					<7 14 22 27 31>,
+					/* Speed bin 2 */
+					<7 14 22 30 33>;
 
 				qcom,cpr-voltage-ceiling =
 					/* Speed bin 0 */
@@ -350,15 +486,23 @@
 					 828000  828000  828000  828000  828000
 					 828000  828000  828000  932000  932000
 					 932000  932000 1104000 1104000 1104000
-					1104000 1136000 1136000>,
+					1104000 1160000 1160000>,
 					/* Speed bin 1 */
 					<828000  828000  828000  828000  828000
 					 828000  828000  828000  828000  828000
 					 828000  828000  828000  828000  828000
 					 828000  828000  828000  932000  932000
 					 932000  932000 1104000 1104000 1104000
-					1104000 1136000 1136000 1136000 1136000
-					1136000>;
+					1104000 1160000 1160000 1160000 1160000
+					1160000>,
+					/* Speed bin 2 */
+					<828000  828000  828000  828000  828000
+					 828000  828000  828000  828000  828000
+					 828000  828000  828000  828000  828000
+					 828000  828000  828000  932000  932000
+					 932000  932000 1104000 1104000 1104000
+					1104000 1160000 1160000 1160000 1160000
+					1160000 1160000 1160000>;
 
 				qcom,cpr-voltage-floor =
 					/* Speed bin 0 */
@@ -375,7 +519,15 @@
 					 568000  568000  568000  568000  568000
 					 568000  568000  568000  568000  568000
 					 568000  568000  568000  568000  568000
-					 568000>;
+					 568000>,
+					/* Speed bin 2 */
+					<568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000  568000  568000
+					 568000  568000  568000>;
 
 				qcom,cpr-floor-to-ceiling-max-range =
 					/* Speed bin 0 */
@@ -392,7 +544,15 @@
 					 32000  32000  32000  32000  32000
 					 32000  32000  32000  32000  32000
 					 32000  32000  40000  40000  40000
-					 40000>;
+					 40000>,
+					/* Speed bin 2 */
+					<32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  32000  32000  32000
+					 32000  32000  40000  40000  40000
+					 40000  40000  40000>;
 
 				qcom,corner-frequencies =
 					/* Speed bin 0 */
@@ -417,7 +577,19 @@
 					1996800000 2092800000 2169600000
 					2246400000 2323200000 2400000000
 					2476800000 2553600000 2649600000
-					2707200000>;
+					2707200000>,
+					/* Speed bin 2 */
+					<300000000  403200000  480000000
+					 576000000  652800000  748800000
+					 825600000  902400000  979200000
+					1056000000 1132800000 1209600000
+					1286400000 1363200000 1459200000
+					1536000000 1612800000 1689600000
+					1766400000 1843200000 1920000000
+					1996800000 2092800000 2169600000
+					2246400000 2323200000 2400000000
+					2476800000 2553600000 2649600000
+					2707200000 2726400000 2745600000>;
 
 				qcom,cpr-ro-scaling-factor =
 					<2857 3056 2828 2952 2699 2796 2447
@@ -437,28 +609,76 @@
 					 2003 1675>;
 
 				qcom,cpr-open-loop-voltage-fuse-adjustment =
-					/* Speed bin 0 */
-					<  8000   8000   8000      0      0>,
-					/* Speed bin 1 */
-					<  8000   8000   8000      0  16000>;
+				 /* Speed bin 0 */
+				 <   8000     8000     8000        0        0>,
+				 < (-7000)  (-7000)  (-7000) (-15000) (-15000)>,
+				 < (-7000)  (-7000)  (-7000) (-15000) (-15000)>,
+				 < (-7000)  (-7000)  (-7000) (-15000) (-15000)>,
+				 < (-7000)  (-7000)  (-7000) (-15000) (-15000)>,
+				 < (-7000)  (-7000)  (-7000) (-15000) (-15000)>,
+				 < (-7000)  (-7000)  (-7000) (-15000) (-15000)>,
+				 < (-7000)  (-7000)  (-7000) (-15000) (-15000)>,
+				 /* Speed bin 1 */
+				 <   8000     8000     8000        0    16000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>,
+				 /* Speed bin 2 */
+				 <   8000     8000     8000        0    16000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>,
+				 < (-7000)  (-7000)  (-7000) (-15000)    1000>;
 
 				qcom,cpr-closed-loop-voltage-fuse-adjustment =
-					/* Speed bin 0 */
-					<  6000   6000   8000      0      0>,
-					/* Speed bin 1 */
-					<  6000   6000   8000      0  16000>;
+				 /* Speed bin 0 */
+				 <   6000     6000     8000        0        0>,
+				 < (-9000)  (-9000)  (-7000) (-15000) (-15000)>,
+				 < (-9000)  (-9000)  (-7000) (-15000) (-15000)>,
+				 < (-9000)  (-9000)  (-7000) (-15000) (-15000)>,
+				 < (-9000)  (-9000)  (-7000) (-15000) (-15000)>,
+				 < (-9000)  (-9000)  (-7000) (-15000) (-15000)>,
+				 < (-9000)  (-9000)  (-7000) (-15000) (-15000)>,
+				 < (-9000)  (-9000)  (-7000) (-15000) (-15000)>,
+				 /* Speed bin 1 */
+				 <   6000     6000     8000        0    16000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>,
+				 /* Speed bin 2 */
+				 <   6000     6000     8000        0    16000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>,
+				 < (-9000)  (-9000)  (-7000) (-15000)    1000>;
 
 				qcom,allow-voltage-interpolation;
 				qcom,allow-quotient-interpolation;
 				qcom,cpr-scaled-open-loop-voltage-as-ceiling;
 
 				qcom,cpr-aging-max-voltage-adjustment = <15000>;
-				qcom,cpr-aging-ref-corner = <27 31>;
+				qcom,cpr-aging-ref-corner = <27 31 33>;
 				qcom,cpr-aging-ro-scaling-factor = <1700>;
 				qcom,allow-aging-voltage-adjustment =
 					/* Speed bin 0 */
 					<0 1 1 1 1 1 1 1>,
 					/* Speed bin 1 */
+					<0 1 1 1 1 1 1 1>,
+					/* Speed bin 2 */
 					<0 1 1 1 1 1 1 1>;
 				qcom,allow-aging-open-loop-voltage-adjustment =
 					<1>;
@@ -490,7 +710,7 @@
 /* VDD_APC1 */
 &pm8998_s12 {
 	regulator-min-microvolt = <568000>;
-	regulator-max-microvolt = <1136000>;
+	regulator-max-microvolt = <1160000>;
 };
 
 &clock_cpucc {
@@ -533,6 +753,23 @@
 		<  1497600000 0x403c0d4e 0x00003e3e 0x2 14 >,
 		<  1593600000 0x403c0e53 0x00004242 0x2 15 >;
 
+	qcom,l3-speedbin2-v0 =
+		<   300000000 0x000c000f 0x00002020 0x1 1 >,
+		<   403200000 0x500c0115 0x00002020 0x1 2 >,
+		<   480000000 0x50140219 0x00002020 0x1 3 >,
+		<   576000000 0x5014031e 0x00002020 0x1 4 >,
+		<   652800000 0x401c0422 0x00002020 0x1 5 >,
+		<   748800000 0x401c0527 0x00002020 0x1 6 >,
+		<   844800000 0x4024062c 0x00002323 0x2 7 >,
+		<   940800000 0x40240731 0x00002727 0x2 8 >,
+		<  1036800000 0x40240836 0x00002b2b 0x2 9 >,
+		<  1132800000 0x402c093b 0x00002f2f 0x2 10 >,
+		<  1209600000 0x402c0a3f 0x00003232 0x2 11 >,
+		<  1305600000 0x40340b44 0x00003636 0x2 12 >,
+		<  1401600000 0x40340c49 0x00003a3a 0x2 13 >,
+		<  1497600000 0x403c0d4e 0x00003e3e 0x2 14 >,
+		<  1593600000 0x403c0e53 0x00004242 0x2 15 >;
+
 	qcom,pwrcl-speedbin0-v0 =
 		<   300000000 0x000c000f 0x00002020 0x1 1 >,
 		<   403200000 0x500c0115 0x00002020 0x1 2 >,
@@ -573,6 +810,26 @@
 		<  1689600000 0x40441058 0x00004646 0x2 17 >,
 		<  1766400000 0x4044115c 0x00004a4a 0x2 18 >;
 
+	qcom,pwrcl-speedbin2-v0 =
+		<   300000000 0x000c000f 0x00002020 0x1 1 >,
+		<   403200000 0x500c0115 0x00002020 0x1 2 >,
+		<   480000000 0x50140219 0x00002020 0x1 3 >,
+		<   576000000 0x5014031e 0x00002020 0x1 4 >,
+		<   652800000 0x401c0422 0x00002020 0x1 5 >,
+		<   748800000 0x401c0527 0x00002020 0x1 6 >,
+		<   825600000 0x401c062b 0x00002222 0x1 7 >,
+		<   902400000 0x4024072f 0x00002626 0x1 8 >,
+		<   979200000 0x40240833 0x00002929 0x1 9 >,
+		<  1056000000 0x402c0937 0x00002c2c 0x2 10 >,
+		<  1132800000 0x402c0a3b 0x00002f2f 0x2 11 >,
+		<  1228800000 0x402c0b40 0x00003333 0x2 12 >,
+		<  1324800000 0x40340c45 0x00003737 0x2 13 >,
+		<  1420800000 0x40340d4a 0x00003b3b 0x2 14 >,
+		<  1516800000 0x403c0e4f 0x00003f3f 0x2 15 >,
+		<  1612800000 0x403c0f54 0x00004343 0x2 16 >,
+		<  1689600000 0x40441058 0x00004646 0x2 17 >,
+		<  1766400000 0x4044115c 0x00004a4a 0x2 18 >;
+
 	qcom,perfcl-speedbin0-v0 =
 		<   300000000 0x000c000f 0x00002020 0x1 1 >,
 		<   403200000 0x500c0115 0x00002020 0x1 2 >,
@@ -635,14 +892,53 @@
 		<  2649600000 0x40541d8a 0x00006e6e 0x2 30 >,
 		<  2745600000 0x40511e8f 0x00007272 0x2 31 >;
 
+	qcom,perfcl-speedbin2-v0 =
+		<   300000000 0x000c000f 0x00002020 0x1 1 >,
+		<   403200000 0x500c0115 0x00002020 0x1 2 >,
+		<   480000000 0x50140219 0x00002020 0x1 3 >,
+		<   576000000 0x5014031e 0x00002020 0x1 4 >,
+		<   652800000 0x401c0422 0x00002020 0x1 5 >,
+		<   748800000 0x401c0527 0x00002020 0x1 6 >,
+		<   825600000 0x401c062b 0x00002222 0x1 7 >,
+		<   902400000 0x4024072f 0x00002626 0x1 8 >,
+		<   979200000 0x40240833 0x00002929 0x1 9 >,
+		<  1056000000 0x402c0937 0x00002c2c 0x1 10 >,
+		<  1132800000 0x402c0a3b 0x00002f2f 0x1 11 >,
+		<  1209600000 0x402c0b3f 0x00003232 0x2 12 >,
+		<  1286400000 0x40340c43 0x00003636 0x2 13 >,
+		<  1363200000 0x40340d47 0x00003939 0x2 14 >,
+		<  1459200000 0x403c0e4c 0x00003d3d 0x2 15 >,
+		<  1536000000 0x403c0f50 0x00004040 0x2 16 >,
+		<  1612800000 0x403c1054 0x00004343 0x2 17 >,
+		<  1689600000 0x40441158 0x00004646 0x2 18 >,
+		<  1766400000 0x4044125c 0x00004a4a 0x2 19 >,
+		<  1843200000 0x40441360 0x00004d4d 0x2 20 >,
+		<  1920000000 0x404c1464 0x00005050 0x2 21 >,
+		<  1996800000 0x404c1568 0x00005353 0x2 22 >,
+		<  2092800000 0x4054166d 0x00005757 0x2 23 >,
+		<  2169600000 0x40541771 0x00005a5a 0x2 24 >,
+		<  2246400000 0x40541875 0x00005e5e 0x2 25 >,
+		<  2323200000 0x40541979 0x00006161 0x2 26 >,
+		<  2400000000 0x40541a7d 0x00006464 0x2 27 >,
+		<  2476800000 0x40541b81 0x00006767 0x2 28 >,
+		<  2553600000 0x40541c85 0x00006a6a 0x2 29 >,
+		<  2649600000 0x40541d8a 0x00006e6e 0x2 30 >,
+		<  2707200000 0x40511e8d 0x00007171 0x2 30 >,
+		<  2764800000 0x40511f90 0x00007373 0x2 31 >,
+		<  2784000000 0x40512091 0x00007474 0x2 32 >,
+		<  2803200000 0x40512192 0x00007575 0x2 33 >;
+
 	qcom,l3-memacc-level-vc-bin0 = <8 13>;
 	qcom,l3-memacc-level-vc-bin1 = <8 13>;
+	qcom,l3-memacc-level-vc-bin2 = <8 13>;
 
 	qcom,pwrcl-memacc-level-vc-bin0 = <12 16>;
 	qcom,pwrcl-memacc-level-vc-bin1 = <12 16>;
+	qcom,pwrcl-memacc-level-vc-bin2 = <12 16>;
 
 	qcom,perfcl-memacc-level-vc-bin0 = <14 22>;
 	qcom,perfcl-memacc-level-vc-bin1 = <14 22>;
+	qcom,perfcl-memacc-level-vc-bin2 = <14 22>;
 };
 
 &pcie1 {
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index b4c1fb3..ff092ea 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -1094,6 +1094,7 @@
 		reg = <0x5090000 0x9000>;
 		reg-names = "cc_base";
 		vdd_cx-supply = <&pm8998_s9_level>;
+		vdd_mx-supply = <&pm8998_s6_level>;
 		qcom,gpu_cc_gmu_clk_src-opp-handle = <&gmu>;
 		#clock-cells = <1>;
 		#reset-cells = <1>;
@@ -1104,7 +1105,6 @@
 		reg = <0x5090000 0x9000>;
 		reg-names = "cc_base";
 		vdd_gfx-supply = <&pm8005_s1_level>;
-		vdd_mx-supply = <&pm8998_s6_level>;
 		qcom,gpu_cc_gx_gfx3d_clk_src-opp-handle = <&msm_gpu>;
 		#clock-cells = <1>;
 		#reset-cells = <1>;
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
new file mode 100644
index 0000000..98def01
--- /dev/null
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -0,0 +1,474 @@
+CONFIG_LOCALVERSION="-perf"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_FHANDLE is not set
+CONFIG_AUDIT=y
+# CONFIG_AUDITSYSCALL is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_SCHED_WALT=y
+CONFIG_RCU_EXPERT=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_ALL=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHEDTUNE=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_BPF=y
+CONFIG_SCHED_CORE_CTL=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SCHED_TUNE=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_AIO is not set
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MSM8953=y
+CONFIG_SCHED_MC=y
+CONFIG_NR_CPUS=8
+CONFIG_PREEMPT=y
+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
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_SETEND_EMULATION=y
+# CONFIG_ARM64_VHE is not set
+CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_COMPAT=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TEE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_RPFILTER=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RPFILTER=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_L2TP=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_SKBEDIT=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_BT=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+# CONFIG_CFG80211_CRDA_SUPPORT is not set
+CONFIG_RFKILL=y
+CONFIG_NFC_NQ=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_DMA_CMA=y
+CONFIG_ZRAM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_QSEECOM=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_MSM_RDBG=m
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QCOM_GENI=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_QCOM_GENI=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
+CONFIG_PINCTRL_MSM8953=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_XGENE=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_CPRH_KBSS=y
+CONFIG_REGULATOR_QPNP_LABIBB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_GOVERNORS=y
+CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_QCOM_KGSL=y
+CONFIG_DRM=y
+CONFIG_DRM_SDE_EVTLOG_DEBUG=y
+CONFIG_DRM_SDE_RSC=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_USB_DWC3=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_DUAL_ROLE_USB_INTF=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_QUSB_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_QPNP_WLED=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_DMADEVICES=y
+CONFIG_QCOM_SPS_DMA=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_GSI=y
+CONFIG_IPA3=y
+CONFIG_RMNET_IPA3=y
+CONFIG_RNDIS_IPA=y
+CONFIG_IPA_UT=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_COINCELL=y
+CONFIG_QPNP_REVID=y
+CONFIG_USB_BAM=y
+CONFIG_QCOM_MDSS_PLL=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_ARM_SMMU=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_QCOM_EUD=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_QCOM_SECURE_BUFFER=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_MSM_SMEM=y
+CONFIG_MSM_GLINK=y
+CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
+CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
+CONFIG_MSM_GLINK_SPI_XPRT=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_SMP2P_TEST=y
+CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_GLINK_PKT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_ICNSS=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_PM=y
+CONFIG_QTI_RPM_STATS_LOG=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
+CONFIG_ARM_GIC_V3_ACL=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_SENSORS_SSC=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_FUSE_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_IPC_LOGGING=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_DEBUG_ALIGN_RODATA=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_EVENT=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_ARM64_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM64_CE=y
+CONFIG_CRYPTO_SHA2_ARM64_CE=y
+CONFIG_CRYPTO_GHASH_ARM64_CE=y
+CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
+CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y
+CONFIG_CRYPTO_CRC32_ARM64=y
+CONFIG_QMI_ENCDEC=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
new file mode 100644
index 0000000..8b5c2ea
--- /dev/null
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -0,0 +1,544 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_FHANDLE is not set
+CONFIG_AUDIT=y
+# CONFIG_AUDITSYSCALL is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_SCHED_WALT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_RCU_EXPERT=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_ALL=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHEDTUNE=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_BPF=y
+CONFIG_SCHED_CORE_CTL=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SCHED_TUNE=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_AIO is not set
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MSM8953=y
+CONFIG_SCHED_MC=y
+CONFIG_NR_CPUS=8
+CONFIG_PREEMPT=y
+CONFIG_HZ_100=y
+CONFIG_CLEANCACHE=y
+CONFIG_CMA=y
+CONFIG_CMA_DEBUGFS=y
+CONFIG_ZSMALLOC=y
+CONFIG_BALANCE_ANON_FILE_RECLAIM=y
+CONFIG_SECCOMP=y
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_SWP_EMULATION=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_SETEND_EMULATION=y
+# CONFIG_ARM64_VHE is not set
+CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_COMPAT=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_DEBUG=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TEE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_RPFILTER=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RPFILTER=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_L2TP=y
+CONFIG_L2TP_DEBUGFS=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_SKBEDIT=y
+CONFIG_DNS_RESOLVER=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_BT=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+# CONFIG_CFG80211_CRDA_SUPPORT is not set
+CONFIG_RFKILL=y
+CONFIG_NFC_NQ=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_DMA_CMA=y
+CONFIG_ZRAM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_MSM_RDBG=m
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QCOM_GENI=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_QCOM_GENI=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
+CONFIG_PINCTRL_MSM8953=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_XGENE=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_CPRH_KBSS=y
+CONFIG_REGULATOR_QPNP_LABIBB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_GOVERNORS=y
+CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_QCOM_KGSL=y
+CONFIG_DRM=y
+CONFIG_DRM_SDE_EVTLOG_DEBUG=y
+CONFIG_DRM_SDE_RSC=y
+CONFIG_FB_VIRTUAL=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_USB_DWC3=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_DUAL_ROLE_USB_INTF=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_QUSB_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_RING_BUFFER=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_QPNP_WLED=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_DMADEVICES=y
+CONFIG_QCOM_SPS_DMA=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_GSI=y
+CONFIG_IPA3=y
+CONFIG_RMNET_IPA3=y
+CONFIG_RNDIS_IPA=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_COINCELL=y
+CONFIG_QPNP_REVID=y
+CONFIG_USB_BAM=y
+CONFIG_QCOM_MDSS_PLL=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_ARM_SMMU=y
+CONFIG_IOMMU_DEBUG=y
+CONFIG_IOMMU_DEBUG_TRACKING=y
+CONFIG_IOMMU_TESTS=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_CORE_HANG_DETECT=y
+CONFIG_MSM_GLADIATOR_HANG_DETECT=y
+CONFIG_QCOM_EUD=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_QCOM_SECURE_BUFFER=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_MSM_SMEM=y
+CONFIG_MSM_GLINK=y
+CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
+CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
+CONFIG_MSM_GLINK_SPI_XPRT=y
+CONFIG_TRACER_PKT=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_SMP2P_TEST=y
+CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_GLINK_PKT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_ICNSS=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_PM=y
+CONFIG_QTI_RPM_STATS_LOG=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
+CONFIG_ARM_GIC_V3_ACL=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_SENSORS_SSC=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_PAGE_OWNER=y
+CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_SLUB_DEBUG_PANIC_ON=y
+CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
+CONFIG_PAGE_POISONING=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_FREE=y
+CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_DEBUG_OBJECTS_WORK=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
+CONFIG_SLUB_DEBUG_ON=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_WQ_WATCHDOG=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_PANIC_ON_SCHED_BUG=y
+CONFIG_PANIC_ON_RT_THROTTLING=y
+CONFIG_SCHEDSTATS=y
+CONFIG_SCHED_STACK_END_CHECK=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_LIST=y
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_IPC_LOGGING=y
+CONFIG_QCOM_RTB=y
+CONFIG_QCOM_RTB_SEPARATE_CPUS=y
+CONFIG_FUNCTION_TRACER=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_LKDTM=y
+CONFIG_MEMTEST=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
+CONFIG_ARM64_PTDUMP=y
+CONFIG_PID_IN_CONTEXTIDR=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_REMOTE_ETM=y
+CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
+CONFIG_CORESIGHT_CTI=y
+CONFIG_CORESIGHT_EVENT=y
+CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_ARM64_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM64_CE=y
+CONFIG_CRYPTO_SHA2_ARM64_CE=y
+CONFIG_CRYPTO_GHASH_ARM64_CE=y
+CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
+CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y
+CONFIG_CRYPTO_CRC32_ARM64=y
+CONFIG_QMI_ENCDEC=y
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index dc09f04..cd393c2 100644
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -335,6 +335,7 @@
 CONFIG_REGULATOR_QPNP_LCDB=y
 CONFIG_REGULATOR_QPNP_OLEDB=y
 CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_REFGEN=y
 CONFIG_REGULATOR_RPMH=y
 CONFIG_REGULATOR_STUB=y
 CONFIG_MEDIA_SUPPORT=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index 79bb308..17231c7 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -342,6 +342,7 @@
 CONFIG_REGULATOR_QPNP_LCDB=y
 CONFIG_REGULATOR_QPNP_OLEDB=y
 CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_REFGEN=y
 CONFIG_REGULATOR_RPMH=y
 CONFIG_REGULATOR_STUB=y
 CONFIG_MEDIA_SUPPORT=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 7655c91..edf67c7 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -455,9 +455,6 @@
 CONFIG_EDAC_KRYO3XX_ARM64=y
 CONFIG_EDAC_KRYO3XX_ARM64_PANIC_ON_CE=y
 CONFIG_EDAC_KRYO3XX_ARM64_PANIC_ON_UE=y
-CONFIG_EDAC_QCOM_LLCC=y
-CONFIG_EDAC_QCOM_LLCC_PANIC_ON_CE=y
-CONFIG_EDAC_QCOM_LLCC_PANIC_ON_UE=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_QPNP=y
 CONFIG_DMADEVICES=y
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 5edb6ed..f3a142e 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -165,6 +165,11 @@
 /* the offset between the kernel virtual and physical mappings */
 extern u64			kimage_voffset;
 
+static inline unsigned long kaslr_offset(void)
+{
+	return kimage_vaddr - KIMAGE_VADDR;
+}
+
 /*
  * Allow all memory at the discovery stage. We will clip it later.
  */
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index ba29095..a58fb92 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -356,11 +356,11 @@
 static int dump_kernel_offset(struct notifier_block *self, unsigned long v,
 			      void *p)
 {
-	u64 const kaslr_offset = kimage_vaddr - KIMAGE_VADDR;
+	const unsigned long offset = kaslr_offset();
 
-	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && kaslr_offset > 0) {
-		pr_emerg("Kernel Offset: 0x%llx from 0x%lx\n",
-			 kaslr_offset, KIMAGE_VADDR);
+	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && offset > 0) {
+		pr_emerg("Kernel Offset: 0x%lx from 0x%lx\n",
+			 offset, KIMAGE_VADDR);
 	} else {
 		pr_emerg("Kernel Offset: disabled\n");
 	}
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 0cea702..d33f245 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -480,7 +480,7 @@
  * In the case that a guest uses storage keys
  * faults should no longer be backed by zero pages
  */
-#define mm_forbids_zeropage mm_use_skey
+#define mm_forbids_zeropage mm_has_pgste
 static inline int mm_use_skey(struct mm_struct *mm)
 {
 #ifdef CONFIG_PGSTE
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
index 3ba6227..cb2cd04 100644
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -2125,6 +2125,37 @@
 }
 
 /*
+ * Remove all empty zero pages from the mapping for lazy refaulting
+ * - This must be called after mm->context.has_pgste is set, to avoid
+ *   future creation of zero pages
+ * - This must be called after THP was enabled
+ */
+static int __zap_zero_pages(pmd_t *pmd, unsigned long start,
+			   unsigned long end, struct mm_walk *walk)
+{
+	unsigned long addr;
+
+	for (addr = start; addr != end; addr += PAGE_SIZE) {
+		pte_t *ptep;
+		spinlock_t *ptl;
+
+		ptep = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
+		if (is_zero_pfn(pte_pfn(*ptep)))
+			ptep_xchg_direct(walk->mm, addr, ptep, __pte(_PAGE_INVALID));
+		pte_unmap_unlock(ptep, ptl);
+	}
+	return 0;
+}
+
+static inline void zap_zero_pages(struct mm_struct *mm)
+{
+	struct mm_walk walk = { .pmd_entry = __zap_zero_pages };
+
+	walk.mm = mm;
+	walk_page_range(0, TASK_SIZE, &walk);
+}
+
+/*
  * switch on pgstes for its userspace process (for kvm)
  */
 int s390_enable_sie(void)
@@ -2141,6 +2172,7 @@
 	mm->context.has_pgste = 1;
 	/* split thp mappings and disable thp for future mappings */
 	thp_split_mm(mm);
+	zap_zero_pages(mm);
 	up_write(&mm->mmap_sem);
 	return 0;
 }
@@ -2153,13 +2185,6 @@
 static int __s390_enable_skey(pte_t *pte, unsigned long addr,
 			      unsigned long next, struct mm_walk *walk)
 {
-	/*
-	 * Remove all zero page mappings,
-	 * after establishing a policy to forbid zero page mappings
-	 * following faults for that page will get fresh anonymous pages
-	 */
-	if (is_zero_pfn(pte_pfn(*pte)))
-		ptep_xchg_direct(walk->mm, addr, pte, __pte(_PAGE_INVALID));
 	/* Clear storage key */
 	ptep_zap_key(walk->mm, addr, pte);
 	return 0;
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index 8d4d959..8706533 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -616,6 +616,7 @@
 	{ PCI_VDEVICE(NVIDIA,	PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE),	8 },
 	{ PCI_VDEVICE(NVIDIA,	PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE),	8 },
 	{ PCI_VDEVICE(AMD,	PCI_DEVICE_ID_AMD_CS5536_IDE),		9 },
+	{ PCI_VDEVICE(AMD,	PCI_DEVICE_ID_AMD_CS5536_DEV_IDE),	9 },
 
 	{ },
 };
diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c
index 6c15a55..dc12552 100644
--- a/drivers/ata/pata_cs5536.c
+++ b/drivers/ata/pata_cs5536.c
@@ -289,6 +289,7 @@
 
 static const struct pci_device_id cs5536[] = {
 	{ PCI_VDEVICE(AMD,	PCI_DEVICE_ID_AMD_CS5536_IDE), },
+	{ PCI_VDEVICE(AMD,	PCI_DEVICE_ID_AMD_CS5536_DEV_IDE), },
 	{ },
 };
 
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 6470eb8..e32a74e 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -736,7 +736,7 @@
 
 out_unregister:
 	kobject_put(&priv->kobj);
-	kfree(drv->p);
+	/* drv->p is freed in driver_release()  */
 	drv->p = NULL;
 out_put_bus:
 	bus_put(bus);
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index b0beb52..914433f 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -958,7 +958,7 @@
 		timeout = MAX_JIFFY_OFFSET;
 	}
 
-	timeout = wait_for_completion_interruptible_timeout(&buf->completion,
+	timeout = wait_for_completion_killable_timeout(&buf->completion,
 			timeout);
 	if (timeout == -ERESTARTSYS || !timeout) {
 		retval = timeout;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index dd220fa..74e677a 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -342,6 +342,7 @@
 	{ USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK },
 	{ USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK },
 	{ USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
+	{ USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK },
 
 	/* Additional Realtek 8821AE Bluetooth devices */
 	{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 874639f..89bf7c6 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1822,18 +1822,62 @@
 {
 }
 
+static int fastrpc_search_ctx(uint64_t rctx)
+{
+	struct fastrpc_apps *me = &gfa;
+	struct fastrpc_file *fl;
+	struct hlist_node *n, *m;
+	struct smq_invoke_ctx *ictx = NULL;
+	struct smq_invoke_ctx *ctx;
+	int bfound = 0;
+
+	ctx = (struct smq_invoke_ctx *)(uint64_to_ptr(rctx));
+	if (!ctx)
+		return bfound;
+
+	spin_lock(&me->hlock);
+	hlist_for_each_entry_safe(fl, n, &me->drivers, hn) {
+		if (ctx->fl != fl)
+			continue;
+		spin_lock(&fl->hlock);
+		hlist_for_each_entry_safe(ictx, m, &fl->clst.pending, hn) {
+			if (ptr_to_uint64(ictx) == rctx) {
+				bfound = 1;
+				break;
+			}
+		}
+		hlist_for_each_entry_safe(ictx, m, &fl->clst.interrupted, hn) {
+			if (ptr_to_uint64(ictx) == rctx) {
+				bfound = 1;
+				break;
+			}
+		}
+		spin_unlock(&fl->hlock);
+		if (bfound)
+			break;
+	}
+	spin_unlock(&me->hlock);
+	return bfound;
+}
+
 void fastrpc_glink_notify_rx(void *handle, const void *priv,
 	const void *pkt_priv, const void *ptr, size_t size)
 {
 	struct smq_invoke_rsp *rsp = (struct smq_invoke_rsp *)ptr;
-	int len = size;
+	int bfound = 0;
 
-	while (len >= sizeof(*rsp) && rsp) {
-		rsp->ctx = rsp->ctx & ~1;
-		context_notify_user(uint64_to_ptr(rsp->ctx), rsp->retval);
-		rsp++;
-		len = len - sizeof(*rsp);
+	if (!rsp || (size < sizeof(*rsp)))
+		goto bail;
+
+	bfound = fastrpc_search_ctx((uint64_t)(rsp->ctx & ~1));
+	if (!bfound) {
+		pr_err("adsprpc: invalid context %pK\n", (void *)rsp->ctx);
+		goto bail;
 	}
+
+	rsp->ctx = rsp->ctx & ~1;
+	context_notify_user(uint64_to_ptr(rsp->ctx), rsp->retval);
+bail:
 	glink_rx_done(handle, ptr, true);
 }
 
@@ -1899,6 +1943,8 @@
 		return 0;
 	cid = fl->cid;
 
+	(void)fastrpc_release_current_dsp_process(fl);
+
 	spin_lock(&fl->apps->hlock);
 	hlist_del_init(&fl->hn);
 	spin_unlock(&fl->apps->hlock);
@@ -1907,7 +1953,6 @@
 		kfree(fl);
 		return 0;
 	}
-	(void)fastrpc_release_current_dsp_process(fl);
 	spin_lock(&fl->hlock);
 	fl->file_close = 1;
 	spin_unlock(&fl->hlock);
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 5638333..4f2fb77 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2712,9 +2712,10 @@
 	struct clk_core *core;
 	int cnt = 0;
 
-	clock_debug_output(s, 0, "Enabled clocks:\n");
+	if (!mutex_trylock(&clk_debug_lock))
+		return;
 
-	mutex_lock(&clk_debug_lock);
+	clock_debug_output(s, 0, "Enabled clocks:\n");
 
 	hlist_for_each_entry(core, &clk_debug_list, debug_node)
 		cnt += clock_debug_print_clock(core, s);
@@ -3037,14 +3038,19 @@
 
 /*
  * Print the names of all enabled clocks and their parents if
- * debug_suspend is set from debugfs.
+ * debug_suspend is set from debugfs along with print_parent flag set to 1.
+ * Otherwise if print_parent set to 0, print only enabled clocks
+ *
  */
-void clock_debug_print_enabled(void)
+void clock_debug_print_enabled(bool print_parent)
 {
 	if (likely(!debug_suspend))
 		return;
 
-	clock_debug_print_enabled_debug_suspend(NULL);
+	if (print_parent)
+		clock_debug_print_enabled_clocks(NULL);
+	else
+		clock_debug_print_enabled_debug_suspend(NULL);
 }
 EXPORT_SYMBOL_GPL(clock_debug_print_enabled);
 
diff --git a/drivers/clk/clk.h b/drivers/clk/clk.h
index b52aa25..a7d0981 100644
--- a/drivers/clk/clk.h
+++ b/drivers/clk/clk.h
@@ -23,7 +23,7 @@
 void __clk_free_clk(struct clk *clk);
 
 /* Debugfs API to print the enabled clocks */
-void clock_debug_print_enabled(void);
+void clock_debug_print_enabled(bool print_parent);
 void clk_debug_print_hw(struct clk_core *clk, struct seq_file *f);
 
 #else
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 5d2e918..746cdc0 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -1606,7 +1606,7 @@
 	 * clocks that are enabled and preventing the system level
 	 * LPMs(XO and Vmin).
 	 */
-	clock_debug_print_enabled();
+	clock_debug_print_enabled(true);
 
 	psci_enter_sleep(lpm_cpu, idx, false);
 
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 2cf303e..94b3c17 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -340,8 +340,6 @@
 	if (authdata) {
 		handle->sha_ctxt.auth_data[0] = auth32[0];
 		handle->sha_ctxt.auth_data[1] = auth32[1];
-		handle->sha_ctxt.auth_data[2] = auth32[2];
-		handle->sha_ctxt.auth_data[3] = auth32[3];
 	}
 
 	tasklet_schedule(&pdev->done_tasklet);
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h
index 161c923..3e74e1a 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h
@@ -315,6 +315,8 @@
 	bool edid_read;
 
 	wait_queue_head_t wq;
+	struct work_struct hpd_work;
+
 	struct drm_bridge bridge;
 	struct drm_connector connector;
 
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 8ed3906..213d892 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -402,6 +402,27 @@
 	return false;
 }
 
+static void adv7511_hpd_work(struct work_struct *work)
+{
+	struct adv7511 *adv7511 = container_of(work, struct adv7511, hpd_work);
+	enum drm_connector_status status;
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(adv7511->regmap, ADV7511_REG_STATUS, &val);
+	if (ret < 0)
+		status = connector_status_disconnected;
+	else if (val & ADV7511_STATUS_HPD)
+		status = connector_status_connected;
+	else
+		status = connector_status_disconnected;
+
+	if (adv7511->connector.status != status) {
+		adv7511->connector.status = status;
+		drm_kms_helper_hotplug_event(adv7511->connector.dev);
+	}
+}
+
 static int adv7511_irq_process(struct adv7511 *adv7511, bool process_hpd)
 {
 	unsigned int irq0, irq1;
@@ -419,7 +440,7 @@
 	regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
 
 	if (process_hpd && irq0 & ADV7511_INT0_HPD && adv7511->bridge.encoder)
-		drm_helper_hpd_irq_event(adv7511->connector.dev);
+		schedule_work(&adv7511->hpd_work);
 
 	if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
 		adv7511->edid_read = true;
@@ -1006,6 +1027,8 @@
 			goto err_i2c_unregister_edid;
 	}
 
+	INIT_WORK(&adv7511->hpd_work, adv7511_hpd_work);
+
 	if (i2c->irq) {
 		init_waitqueue_head(&adv7511->wq);
 
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c
index ac5437e..6394109 100644
--- a/drivers/gpu/drm/drm_dp_helper.c
+++ b/drivers/gpu/drm/drm_dp_helper.c
@@ -358,20 +358,13 @@
  */
 int drm_dp_link_power_up(struct drm_dp_aux *aux, struct drm_dp_link *link)
 {
-	u8 value;
+	u8 value = DP_SET_POWER_D0;
 	int err;
 
 	/* DP_SET_POWER register is only available on DPCD v1.1 and later */
 	if (link->revision < 0x11)
 		return 0;
 
-	err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
-	if (err < 0)
-		return err;
-
-	value &= ~DP_SET_POWER_MASK;
-	value |= DP_SET_POWER_D0;
-
 	err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
 	if (err < 0)
 		return err;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 270e677..e50bac1 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -1291,7 +1291,7 @@
 		}
 		break;
 	default:
-		SDE_ERROR_ENC(sde_enc, "Unexpected topology:%d\n", topology);
+		SDE_DEBUG_ENC(sde_enc, "Unexpected topology:%d\n", topology);
 		return -EINVAL;
 	};
 
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
index eb9b278..a4cb824 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
@@ -192,6 +192,10 @@
 		}
 	}
 
+#ifdef __BIG_ENDIAN
+	pci->msi = false;
+#endif
+
 	pci->msi = nvkm_boolopt(device->cfgopt, "NvMSI", pci->msi);
 	if (pci->msi && func->msi_rearm) {
 		pci->msi = pci_enable_msi(pci->pdev) == 0;
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 780cefe..7943745 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2870,7 +2870,7 @@
 			gpu_busy += adj;
 		}
 
-		if (kgsl_gmu_isenabled(device)) {
+		if (adreno_is_a6xx(adreno_dev)) {
 			/* clock sourced from XO */
 			stats->busy_time = gpu_busy * 10 / 192;
 		} else {
@@ -3091,6 +3091,7 @@
 	.irq_handler = adreno_irq_handler,
 	.drain = adreno_drain,
 	/* Optional functions */
+	.snapshot_gmu = adreno_snapshot_gmu,
 	.drawctxt_create = adreno_drawctxt_create,
 	.drawctxt_detach = adreno_drawctxt_detach,
 	.drawctxt_destroy = adreno_drawctxt_destroy,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 49dc5ed..8349a9f 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -621,6 +621,8 @@
 	ADRENO_REG_RBBM_RBBM_CTL,
 	ADRENO_REG_UCHE_INVALIDATE0,
 	ADRENO_REG_UCHE_INVALIDATE1,
+	ADRENO_REG_RBBM_PERFCTR_RBBM_0_LO,
+	ADRENO_REG_RBBM_PERFCTR_RBBM_0_HI,
 	ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_LO,
 	ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI,
 	ADRENO_REG_RBBM_SECVID_TRUST_CONTROL,
@@ -832,6 +834,7 @@
 	/* GPU specific function hooks */
 	void (*irq_trace)(struct adreno_device *, unsigned int status);
 	void (*snapshot)(struct adreno_device *, struct kgsl_snapshot *);
+	void (*snapshot_gmu)(struct adreno_device *, struct kgsl_snapshot *);
 	void (*platform_setup)(struct adreno_device *);
 	void (*init)(struct adreno_device *);
 	void (*remove)(struct adreno_device *);
@@ -1006,6 +1009,9 @@
 		struct kgsl_snapshot *snapshot,
 		struct kgsl_context *context);
 
+void adreno_snapshot_gmu(struct kgsl_device *device,
+		struct kgsl_snapshot *snapshot);
+
 int adreno_reset(struct kgsl_device *device, int fault);
 
 void adreno_fault_skipcmd_detached(struct adreno_device *adreno_dev,
@@ -1697,21 +1703,60 @@
 	spin_unlock_irqrestore(&rb->preempt_lock, flags);
 }
 
+static inline bool is_power_counter_overflow(struct adreno_device *adreno_dev,
+	unsigned int reg, unsigned int prev_val, unsigned int *perfctr_pwr_hi)
+{
+	unsigned int val;
+	bool ret = false;
+
+	/*
+	 * If prev_val is zero, it is first read after perf counter reset.
+	 * So set perfctr_pwr_hi register to zero.
+	 */
+	if (prev_val == 0) {
+		*perfctr_pwr_hi = 0;
+		return ret;
+	}
+	adreno_readreg(adreno_dev, ADRENO_REG_RBBM_PERFCTR_RBBM_0_HI, &val);
+	if (val != *perfctr_pwr_hi) {
+		*perfctr_pwr_hi = val;
+		ret = true;
+	}
+	return ret;
+}
+
 static inline unsigned int counter_delta(struct kgsl_device *device,
 			unsigned int reg, unsigned int *counter)
 {
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	unsigned int val;
 	unsigned int ret = 0;
+	bool overflow = true;
+	static unsigned int perfctr_pwr_hi;
 
 	/* Read the value */
 	kgsl_regread(device, reg, &val);
 
+	if (adreno_is_a5xx(adreno_dev) && reg == adreno_getreg
+		(adreno_dev, ADRENO_REG_RBBM_PERFCTR_RBBM_0_LO))
+		overflow = is_power_counter_overflow(adreno_dev, reg,
+				*counter, &perfctr_pwr_hi);
+
 	/* Return 0 for the first read */
 	if (*counter != 0) {
-		if (val < *counter)
-			ret = (0xFFFFFFFF - *counter) + val;
-		else
+		if (val >= *counter) {
 			ret = val - *counter;
+		} else if (overflow == true) {
+			ret = (0xFFFFFFFF - *counter) + val;
+		} else {
+			/*
+			 * Since KGSL got abnormal value from the counter,
+			 * We will drop the value from being accumulated.
+			 */
+			pr_warn_once("KGSL: Abnormal value :0x%x (0x%x) from perf counter : 0x%x\n",
+					val, *counter, reg);
+			return 0;
+		}
 	}
 
 	*counter = val;
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 356d7c2..b2cdf56 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -1533,6 +1533,10 @@
 			A3XX_UCHE_CACHE_INVALIDATE0_REG),
 	ADRENO_REG_DEFINE(ADRENO_REG_UCHE_INVALIDATE1,
 			A3XX_UCHE_CACHE_INVALIDATE1_REG),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_RBBM_0_LO,
+			A3XX_RBBM_PERFCTR_RBBM_0_LO),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_RBBM_0_HI,
+			A3XX_RBBM_PERFCTR_RBBM_0_HI),
 	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_LO,
 				A3XX_RBBM_PERFCTR_LOAD_VALUE_LO),
 	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI,
diff --git a/drivers/gpu/msm/adreno_a4xx.c b/drivers/gpu/msm/adreno_a4xx.c
index 0cf909e..80ceabd 100644
--- a/drivers/gpu/msm/adreno_a4xx.c
+++ b/drivers/gpu/msm/adreno_a4xx.c
@@ -808,6 +808,10 @@
 	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_SW_RESET_CMD, A4XX_RBBM_SW_RESET_CMD),
 	ADRENO_REG_DEFINE(ADRENO_REG_UCHE_INVALIDATE0, A4XX_UCHE_INVALIDATE0),
 	ADRENO_REG_DEFINE(ADRENO_REG_UCHE_INVALIDATE1, A4XX_UCHE_INVALIDATE1),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_RBBM_0_LO,
+				A4XX_RBBM_PERFCTR_RBBM_0_LO),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_RBBM_0_HI,
+				A4XX_RBBM_PERFCTR_RBBM_0_HI),
 	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_LO,
 				A4XX_RBBM_PERFCTR_LOAD_VALUE_LO),
 	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI,
diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c
index 6cddd08..2d078ba 100644
--- a/drivers/gpu/msm/adreno_a5xx.c
+++ b/drivers/gpu/msm/adreno_a5xx.c
@@ -2998,6 +2998,10 @@
 		ADRENO_REG_DEFINE(ADRENO_REG_RBBM_BLOCK_SW_RESET_CMD2,
 					  A5XX_RBBM_BLOCK_SW_RESET_CMD2),
 	ADRENO_REG_DEFINE(ADRENO_REG_UCHE_INVALIDATE0, A5XX_UCHE_INVALIDATE0),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_RBBM_0_LO,
+				A5XX_RBBM_PERFCTR_RBBM_0_LO),
+	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_RBBM_0_HI,
+				A5XX_RBBM_PERFCTR_RBBM_0_HI),
 	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_LO,
 				A5XX_RBBM_PERFCTR_LOAD_VALUE_LO),
 	ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_VALUE_HI,
diff --git a/drivers/gpu/msm/adreno_a5xx_snapshot.c b/drivers/gpu/msm/adreno_a5xx_snapshot.c
index 78b56bc..6dc62866 100644
--- a/drivers/gpu/msm/adreno_a5xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a5xx_snapshot.c
@@ -767,6 +767,8 @@
 
 	crash_dump_valid = false;
 
+	if (!device->snapshot_crashdumper)
+		return;
 	if (capturescript.gpuaddr == 0 || registers.gpuaddr == 0)
 		return;
 
@@ -872,8 +874,7 @@
 		ARRAY_SIZE(a5xx_vbif_snapshot_registers));
 
 	/* Try to run the crash dumper */
-	if (device->snapshot_crashdumper)
-		_a5xx_do_crashdump(device);
+	_a5xx_do_crashdump(device);
 
 	kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS,
 		snapshot, a5xx_snapshot_registers, NULL);
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index b9df4ec..88c15eb 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -2915,6 +2915,7 @@
 	.reg_offsets = &a6xx_reg_offsets,
 	.start = a6xx_start,
 	.snapshot = a6xx_snapshot,
+	.snapshot_gmu = a6xx_snapshot_gmu,
 	.irq = &a6xx_irq,
 	.snapshot_data = &a6xx_snapshot_data,
 	.irq_trace = trace_kgsl_a5xx_irq_status,
diff --git a/drivers/gpu/msm/adreno_a6xx.h b/drivers/gpu/msm/adreno_a6xx.h
index ee2fd71..dd8af80 100644
--- a/drivers/gpu/msm/adreno_a6xx.h
+++ b/drivers/gpu/msm/adreno_a6xx.h
@@ -110,6 +110,8 @@
 
 void a6xx_snapshot(struct adreno_device *adreno_dev,
 		struct kgsl_snapshot *snapshot);
+void a6xx_snapshot_gmu(struct adreno_device *adreno_dev,
+		struct kgsl_snapshot *snapshot);
 
 void a6xx_crashdump_init(struct adreno_device *adreno_dev);
 #endif
diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c
index 1d5f4a5..ca011e4 100644
--- a/drivers/gpu/msm/adreno_a6xx_preempt.c
+++ b/drivers/gpu/msm/adreno_a6xx_preempt.c
@@ -635,6 +635,9 @@
 		return;
 
 	gpumem_free_entry(context->user_ctxt_record);
+
+	/* Put the extra ref from gpumem_alloc_entry() */
+	kgsl_mem_entry_put(context->user_ctxt_record);
 }
 
 int a6xx_preemption_context_init(struct kgsl_context *context)
@@ -645,6 +648,10 @@
 	if (!adreno_is_preemption_setup_enabled(adreno_dev))
 		return 0;
 
+	/*
+	 * gpumem_alloc_entry takes an extra refcount. Put it only when
+	 * destroying the context to keep the context record valid
+	 */
 	context->user_ctxt_record = gpumem_alloc_entry(context->dev_priv,
 			A6XX_CP_CTXRECORD_USER_RESTORE_SIZE, 0);
 	if (IS_ERR(context->user_ctxt_record)) {
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index 80c9a61..880ee13 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -569,38 +569,33 @@
 	(((_a)[(2 * (_i)) + 1] - (_a)[2 * (_i)]) + 1)
 
 static size_t a6xx_legacy_snapshot_registers(struct kgsl_device *device,
-		u8 *buf, size_t remain)
+		u8 *buf, size_t remain, struct reg_list *regs)
 {
-	unsigned int i;
-	size_t used = 0;
+	struct kgsl_snapshot_registers snapshot_regs = {
+		.regs = regs->regs,
+		.count = regs->count,
+	};
 
-	for (i = 0; i < ARRAY_SIZE(a6xx_reg_list); i++) {
-		struct reg_list *regs = &a6xx_reg_list[i];
-		struct kgsl_snapshot_registers snapshot_regs = {
-			.regs = regs->regs,
-			.count = regs->count,
-		};
+	if (regs->sel)
+		kgsl_regwrite(device, regs->sel->host_reg, regs->sel->val);
 
-		if (regs->sel)
-			kgsl_regwrite(device, regs->sel->host_reg,
-				regs->sel->val);
-		used += kgsl_snapshot_dump_registers(device, buf + used,
-						remain - used, &snapshot_regs);
-	}
-	return used;
+	return kgsl_snapshot_dump_registers(device, buf, remain,
+		&snapshot_regs);
 }
 
 static size_t a6xx_snapshot_registers(struct kgsl_device *device, u8 *buf,
 		size_t remain, void *priv)
 {
 	struct kgsl_snapshot_regs *header = (struct kgsl_snapshot_regs *)buf;
+	struct reg_list *regs = (struct reg_list *)priv;
 	unsigned int *data = (unsigned int *)(buf + sizeof(*header));
 	unsigned int *src = (unsigned int *)a6xx_crashdump_registers.hostptr;
-	unsigned int i, j, k;
+	unsigned int j, k;
 	unsigned int count = 0;
 
 	if (crash_dump_valid == false)
-		return a6xx_legacy_snapshot_registers(device, buf, remain);
+		return a6xx_legacy_snapshot_registers(device, buf, remain,
+			regs);
 
 	if (remain < sizeof(*header)) {
 		SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
@@ -609,24 +604,20 @@
 
 	remain -= sizeof(*header);
 
-	for (i = 0; i < ARRAY_SIZE(a6xx_reg_list); i++) {
-		struct reg_list *regs = &a6xx_reg_list[i];
+	for (j = 0; j < regs->count; j++) {
+		unsigned int start = regs->regs[2 * j];
+		unsigned int end = regs->regs[(2 * j) + 1];
 
-		for (j = 0; j < regs->count; j++) {
-			unsigned int start = regs->regs[2 * j];
-			unsigned int end = regs->regs[(2 * j) + 1];
+		if (remain < ((end - start) + 1) * 8) {
+			SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
+			goto out;
+		}
 
-			if (remain < ((end - start) + 1) * 8) {
-				SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
-				goto out;
-			}
+		remain -= ((end - start) + 1) * 8;
 
-			remain -= ((end - start) + 1) * 8;
-
-			for (k = start; k <= end; k++, count++) {
-				*data++ = k;
-				*data++ = *src++;
-			}
+		for (k = start; k <= end; k++, count++) {
+			*data++ = k;
+			*data++ = *src++;
 		}
 	}
 
@@ -1471,10 +1462,18 @@
 	}
 }
 
-static void a6xx_snapshot_gmu(struct kgsl_device *device,
+/*
+ * a6xx_snapshot_gmu() - A6XX GMU snapshot function
+ * @adreno_dev: Device being snapshotted
+ * @snapshot: Pointer to the snapshot instance
+ *
+ * This is where all of the A6XX GMU specific bits and pieces are grabbed
+ * into the snapshot memory
+ */
+void a6xx_snapshot_gmu(struct adreno_device *adreno_dev,
 		struct kgsl_snapshot *snapshot)
 {
-	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct kgsl_device *device = KGSL_DEVICE(adreno_dev);
 	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
 
 	if (!kgsl_gmu_isenabled(device))
@@ -1519,6 +1518,8 @@
 
 	crash_dump_valid = false;
 
+	if (!device->snapshot_crashdumper)
+		return;
 	if (a6xx_capturescript.gpuaddr == 0 ||
 		a6xx_crashdump_registers.gpuaddr == 0)
 		return;
@@ -1570,17 +1571,13 @@
 	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
 	struct adreno_snapshot_data *snap_data = gpudev->snapshot_data;
 	bool sptprac_on;
-
-	/* GMU TCM data dumped through AHB */
-	a6xx_snapshot_gmu(device, snapshot);
+	unsigned int i;
 
 	sptprac_on = gpudev->sptprac_is_on(adreno_dev);
 
 	/* Return if the GX is off */
-	if (!gpudev->gx_is_on(adreno_dev)) {
-		pr_err("GX is off. Only dumping GMU data in snapshot\n");
+	if (!gpudev->gx_is_on(adreno_dev))
 		return;
-	}
 
 	/* Dump the registers which get affected by crash dumper trigger */
 	kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS,
@@ -1595,8 +1592,10 @@
 	if (sptprac_on)
 		_a6xx_do_crashdump(device);
 
-	kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS,
-		snapshot, a6xx_snapshot_registers, NULL);
+	for (i = 0; i < ARRAY_SIZE(a6xx_reg_list); i++) {
+		kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_REGS,
+			snapshot, a6xx_snapshot_registers, &a6xx_reg_list[i]);
+	}
 
 	/* CP_SQE indexed registers */
 	kgsl_snapshot_indexed_registers(device, snapshot,
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index f608927..b5999e6 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -837,8 +837,7 @@
 
 	snapshot_frozen_objsize = 0;
 
-	if (!IS_ERR(context))
-		setup_fault_process(device, snapshot,
+	setup_fault_process(device, snapshot,
 			context ? context->proc_priv : NULL);
 
 	/* Add GPU specific sections - registers mainly, but other stuff too */
@@ -946,6 +945,24 @@
 
 }
 
+/* adreno_snapshot_gmu - Snapshot the Adreno GMU state
+ * @device - KGSL device to snapshot
+ * @snapshot - Pointer to the snapshot instance
+ * This is a hook function called by kgsl_snapshot to snapshot the
+ * Adreno specific information for the GMU snapshot.  In turn, this function
+ * calls the GMU specific snapshot function to get core specific information.
+ */
+void adreno_snapshot_gmu(struct kgsl_device *device,
+		struct kgsl_snapshot *snapshot)
+{
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
+
+	/* Add GMU specific sections */
+	if (gpudev->snapshot_gmu)
+		gpudev->snapshot_gmu(adreno_dev, snapshot);
+}
+
 /*
  * adreno_snapshot_cp_roq - Dump CP merciu data in snapshot
  * @device: Device being snapshotted
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 7dff251..0a7d165 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2280,7 +2280,7 @@
 		struct kgsl_mem_entry *entry,
 		struct kgsl_gpuobj_import *param)
 {
-	struct kgsl_gpuobj_import_useraddr useraddr;
+	struct kgsl_gpuobj_import_useraddr useraddr = {0};
 	int ret;
 
 	param->flags &= KGSL_MEMFLAGS_GPUREADONLY
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index f8d5f5b..0ab775a 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -151,6 +151,8 @@
 	unsigned int (*gpuid)(struct kgsl_device *device, unsigned int *chipid);
 	void (*snapshot)(struct kgsl_device *device,
 		struct kgsl_snapshot *snapshot, struct kgsl_context *context);
+	void (*snapshot_gmu)(struct kgsl_device *device,
+		struct kgsl_snapshot *snapshot);
 	irqreturn_t (*irq_handler)(struct kgsl_device *device);
 	int (*drain)(struct kgsl_device *device);
 	/*
@@ -706,7 +708,6 @@
 void kgsl_device_snapshot(struct kgsl_device *device,
 			struct kgsl_context *context, bool gmu_fault);
 void kgsl_device_snapshot_close(struct kgsl_device *device);
-void kgsl_snapshot_save_frozen_objs(struct work_struct *work);
 
 void kgsl_events_init(void);
 void kgsl_events_exit(void);
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index 3bd7cf3..7ea2255 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -1366,7 +1366,7 @@
 		/* Wait for the NMI to be handled */
 		wmb();
 		udelay(100);
-		kgsl_device_snapshot(device, ERR_PTR(-EINVAL), true);
+		kgsl_device_snapshot(device, NULL, true);
 
 		adreno_write_gmureg(adreno_dev,
 				ADRENO_REG_GMU_GMU2HOST_INTR_CLR, 0xFFFFFFFF);
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index f9494a4..f710d8f 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -24,6 +24,8 @@
 #include "kgsl_snapshot.h"
 #include "adreno_cp_parser.h"
 
+static void kgsl_snapshot_save_frozen_objs(struct work_struct *work);
+
 /* Placeholder for list of ib objects that contain all objects in that IB */
 
 struct kgsl_snapshot_cp_obj {
@@ -182,8 +184,7 @@
 	context = kgsl_context_get(device, header->current_context);
 
 	/* Get the current PT base */
-	if (!IS_ERR(priv))
-		header->ptbase = kgsl_mmu_get_current_ttbr0(&device->mmu);
+	header->ptbase = kgsl_mmu_get_current_ttbr0(&device->mmu);
 
 	/* And the PID for the task leader */
 	if (context) {
@@ -207,6 +208,44 @@
 	return size;
 }
 
+/* Snapshot the Linux specific information */
+static size_t snapshot_os_no_ctxt(struct kgsl_device *device,
+	u8 *buf, size_t remain, void *priv)
+{
+	struct kgsl_snapshot_linux_v2 *header =
+		(struct kgsl_snapshot_linux_v2 *)buf;
+	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+	size_t size = sizeof(*header);
+
+	/* Make sure there is enough room for the data */
+	if (remain < size) {
+		SNAPSHOT_ERR_NOMEM(device, "OS");
+		return 0;
+	}
+
+	memset(header, 0, sizeof(*header));
+
+	header->osid = KGSL_SNAPSHOT_OS_LINUX_V3;
+
+	/* Get the kernel build information */
+	strlcpy(header->release, init_utsname()->release,
+			sizeof(header->release));
+	strlcpy(header->version, init_utsname()->version,
+			sizeof(header->version));
+
+	/* Get the Unix time for the timestamp */
+	header->seconds = get_seconds();
+
+	/* Remember the power information */
+	header->power_flags = pwr->power_flags;
+	header->power_level = pwr->active_pwrlevel;
+	header->power_interval_timeout = pwr->interval_timeout;
+	header->grpclk = kgsl_get_clkrate(pwr->grp_clks[0]);
+
+	/* Return the size of the data segment */
+	return size;
+}
+
 static void kgsl_snapshot_put_object(struct kgsl_snapshot_object *obj)
 {
 	list_del(&obj->node);
@@ -663,14 +702,24 @@
 	snapshot->size += sizeof(*header);
 
 	/* Build the Linux specific header */
-	/* Context err is implied a GMU fault, so limit dump */
-	kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_OS,
-			snapshot, snapshot_os,
-			IS_ERR(context) ? context : NULL);
+	/* We either want to only dump GMU, or we want to dump GPU and GMU */
+	if (gmu_fault) {
+		/* Dump only the GMU */
+		kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_OS,
+				snapshot, snapshot_os_no_ctxt, NULL);
 
-	/* Get the device specific sections */
-	if (device->ftbl->snapshot)
-		device->ftbl->snapshot(device, snapshot, context);
+		if (device->ftbl->snapshot_gmu)
+			device->ftbl->snapshot_gmu(device, snapshot);
+	} else {
+		/* Dump GPU and GMU */
+		kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_OS,
+				snapshot, snapshot_os, NULL);
+
+		if (device->ftbl->snapshot)
+			device->ftbl->snapshot(device, snapshot, context);
+		if (device->ftbl->snapshot_gmu)
+			device->ftbl->snapshot_gmu(device, snapshot);
+	}
 
 	/*
 	 * The timestamp is the seconds since boot so it is easier to match to
@@ -1193,7 +1242,7 @@
  * is taken
  * @work: The work item that scheduled this work
  */
-void kgsl_snapshot_save_frozen_objs(struct work_struct *work)
+static void kgsl_snapshot_save_frozen_objs(struct work_struct *work)
 {
 	struct kgsl_snapshot *snapshot = container_of(work,
 				struct kgsl_snapshot, work);
@@ -1205,6 +1254,9 @@
 	if (IS_ERR_OR_NULL(device))
 		return;
 
+	if (snapshot->gmu_fault)
+		goto gmu_only;
+
 	kgsl_snapshot_process_ib_obj_list(snapshot);
 
 	list_for_each_entry(obj, &snapshot->obj_list, node) {
@@ -1251,6 +1303,7 @@
 			       "snapshot: Active IB2:%016llx not dumped\n",
 				snapshot->ib2base);
 
+gmu_only:
 	complete_all(&snapshot->dump_gate);
 	BUG_ON(device->force_panic);
 }
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 3af358a..9caac56 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -157,7 +157,7 @@
 static inline void msm_qdss_csr_enable_bam_to_usb(void) {}
 static inline void msm_qdss_csr_disable_bam_to_usb(void) {}
 static inline void msm_qdss_csr_disable_flush(void) {}
-static inline int coresight_csr_hwctrl_set(uint64_t addr,	95
+static inline int coresight_csr_hwctrl_set(uint64_t addr,
 					   uint32_t val) { return -EINVAL; }
 #endif
 
diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
index 0bba384..63b5db4 100644
--- a/drivers/hwtracing/intel_th/pci.c
+++ b/drivers/hwtracing/intel_th/pci.c
@@ -85,6 +85,16 @@
 		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa2a6),
 		.driver_data = (kernel_ulong_t)0,
 	},
+	{
+		/* Cannon Lake H */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa326),
+		.driver_data = (kernel_ulong_t)0,
+	},
+	{
+		/* Cannon Lake LP */
+		PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9da6),
+		.driver_data = (kernel_ulong_t)0,
+	},
 	{ 0 },
 };
 
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index f70dbf2..7264381 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -191,13 +191,6 @@
 
 static void geni_i2c_err(struct geni_i2c_dev *gi2c, int err)
 {
-	u32 m_cmd = readl_relaxed(gi2c->base + SE_GENI_M_CMD0);
-	u32 m_stat = readl_relaxed(gi2c->base + SE_GENI_M_IRQ_STATUS);
-	u32 geni_s = readl_relaxed(gi2c->base + SE_GENI_STATUS);
-	u32 geni_ios = readl_relaxed(gi2c->base + SE_GENI_IOS);
-	u32 dma = readl_relaxed(gi2c->base + SE_GENI_DMA_MODE_EN);
-	u32 rx_st, tx_st;
-
 	if (gi2c->cur)
 		GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
 			    "len:%d, slv-addr:0x%x, RD/WR:%d\n", gi2c->cur->len,
@@ -211,23 +204,9 @@
 		GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "%s\n",
 			     gi2c_log[err].msg);
 	}
-	if (gi2c->se_mode == GSI_ONLY)
-		goto err_out;
-
-	if (dma) {
-		rx_st = readl_relaxed(gi2c->base + SE_DMA_RX_IRQ_STAT);
-		tx_st = readl_relaxed(gi2c->base + SE_DMA_TX_IRQ_STAT);
-	} else {
-		rx_st = readl_relaxed(gi2c->base + SE_GENI_RX_FIFO_STATUS);
-		tx_st = readl_relaxed(gi2c->base + SE_GENI_TX_FIFO_STATUS);
-	}
-	GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
-		     "DMA:%d tx_stat:0x%x, rx_stat:0x%x, irq-stat:0x%x\n",
-		     dma, tx_st, rx_st, m_stat);
-err_out:
-	GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
-			     "m_cmd:0x%x, geni_status:0x%x, geni_ios:0x%x\n",
-			     m_cmd, geni_s, geni_ios);
+	GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "%s: se-mode:%d\n", __func__,
+							gi2c->se_mode);
+	geni_se_dump_dbg_regs(&gi2c->i2c_rsc, gi2c->base, gi2c->ipcl);
 err_ret:
 	gi2c->err = gi2c_log[err].err;
 }
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
index cde6f13..472641f 100644
--- a/drivers/iio/adc/ti-ads1015.c
+++ b/drivers/iio/adc/ti-ads1015.c
@@ -80,18 +80,12 @@
 	8, 16, 32, 64, 128, 250, 475, 860
 };
 
-static const struct {
-	int scale;
-	int uscale;
-} ads1015_scale[] = {
-	{3, 0},
-	{2, 0},
-	{1, 0},
-	{0, 500000},
-	{0, 250000},
-	{0, 125000},
-	{0, 125000},
-	{0, 125000},
+/*
+ * Translation from PGA bits to full-scale positive and negative input voltage
+ * range in mV
+ */
+static int ads1015_fullscale_range[] = {
+	6144, 4096, 2048, 1024, 512, 256, 256, 256
 };
 
 #define ADS1015_V_CHAN(_chan, _addr) {				\
@@ -182,6 +176,12 @@
 	struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
 
 	unsigned int *data_rate;
+	/*
+	 * Set to true when the ADC is switched to the continuous-conversion
+	 * mode and exits from a power-down state.  This flag is used to avoid
+	 * getting the stale result from the conversion register.
+	 */
+	bool conv_invalid;
 };
 
 static bool ads1015_is_writeable_reg(struct device *dev, unsigned int reg)
@@ -234,33 +234,43 @@
 		ret = pm_runtime_put_autosuspend(dev);
 	}
 
-	return ret;
+	return ret < 0 ? ret : 0;
 }
 
 static
 int ads1015_get_adc_result(struct ads1015_data *data, int chan, int *val)
 {
 	int ret, pga, dr, conv_time;
-	bool change;
+	unsigned int old, mask, cfg;
 
 	if (chan < 0 || chan >= ADS1015_CHANNELS)
 		return -EINVAL;
 
-	pga = data->channel_data[chan].pga;
-	dr = data->channel_data[chan].data_rate;
-
-	ret = regmap_update_bits_check(data->regmap, ADS1015_CFG_REG,
-				       ADS1015_CFG_MUX_MASK |
-				       ADS1015_CFG_PGA_MASK,
-				       chan << ADS1015_CFG_MUX_SHIFT |
-				       pga << ADS1015_CFG_PGA_SHIFT,
-				       &change);
-	if (ret < 0)
+	ret = regmap_read(data->regmap, ADS1015_CFG_REG, &old);
+	if (ret)
 		return ret;
 
-	if (change) {
-		conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]);
+	pga = data->channel_data[chan].pga;
+	dr = data->channel_data[chan].data_rate;
+	mask = ADS1015_CFG_MUX_MASK | ADS1015_CFG_PGA_MASK |
+		ADS1015_CFG_DR_MASK;
+	cfg = chan << ADS1015_CFG_MUX_SHIFT | pga << ADS1015_CFG_PGA_SHIFT |
+		dr << ADS1015_CFG_DR_SHIFT;
+
+	cfg = (old & ~mask) | (cfg & mask);
+
+	ret = regmap_write(data->regmap, ADS1015_CFG_REG, cfg);
+	if (ret)
+		return ret;
+
+	if (old != cfg || data->conv_invalid) {
+		int dr_old = (old & ADS1015_CFG_DR_MASK) >>
+				ADS1015_CFG_DR_SHIFT;
+
+		conv_time = DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr_old]);
+		conv_time += DIV_ROUND_UP(USEC_PER_SEC, data->data_rate[dr]);
 		usleep_range(conv_time, conv_time + 1);
+		data->conv_invalid = false;
 	}
 
 	return regmap_read(data->regmap, ADS1015_CONV_REG, val);
@@ -297,17 +307,20 @@
 	return IRQ_HANDLED;
 }
 
-static int ads1015_set_scale(struct ads1015_data *data, int chan,
+static int ads1015_set_scale(struct ads1015_data *data,
+			     struct iio_chan_spec const *chan,
 			     int scale, int uscale)
 {
 	int i, ret, rindex = -1;
+	int fullscale = div_s64((scale * 1000000LL + uscale) <<
+				(chan->scan_type.realbits - 1), 1000000);
 
-	for (i = 0; i < ARRAY_SIZE(ads1015_scale); i++)
-		if (ads1015_scale[i].scale == scale &&
-		    ads1015_scale[i].uscale == uscale) {
+	for (i = 0; i < ARRAY_SIZE(ads1015_fullscale_range); i++) {
+		if (ads1015_fullscale_range[i] == fullscale) {
 			rindex = i;
 			break;
 		}
+	}
 	if (rindex < 0)
 		return -EINVAL;
 
@@ -317,32 +330,23 @@
 	if (ret < 0)
 		return ret;
 
-	data->channel_data[chan].pga = rindex;
+	data->channel_data[chan->address].pga = rindex;
 
 	return 0;
 }
 
 static int ads1015_set_data_rate(struct ads1015_data *data, int chan, int rate)
 {
-	int i, ret, rindex = -1;
+	int i;
 
-	for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++)
+	for (i = 0; i < ARRAY_SIZE(ads1015_data_rate); i++) {
 		if (data->data_rate[i] == rate) {
-			rindex = i;
-			break;
+			data->channel_data[chan].data_rate = i;
+			return 0;
 		}
-	if (rindex < 0)
-		return -EINVAL;
+	}
 
-	ret = regmap_update_bits(data->regmap, ADS1015_CFG_REG,
-				 ADS1015_CFG_DR_MASK,
-				 rindex << ADS1015_CFG_DR_SHIFT);
-	if (ret < 0)
-		return ret;
-
-	data->channel_data[chan].data_rate = rindex;
-
-	return 0;
+	return -EINVAL;
 }
 
 static int ads1015_read_raw(struct iio_dev *indio_dev,
@@ -384,9 +388,9 @@
 	}
 	case IIO_CHAN_INFO_SCALE:
 		idx = data->channel_data[chan->address].pga;
-		*val = ads1015_scale[idx].scale;
-		*val2 = ads1015_scale[idx].uscale;
-		ret = IIO_VAL_INT_PLUS_MICRO;
+		*val = ads1015_fullscale_range[idx];
+		*val2 = chan->scan_type.realbits - 1;
+		ret = IIO_VAL_FRACTIONAL_LOG2;
 		break;
 	case IIO_CHAN_INFO_SAMP_FREQ:
 		idx = data->channel_data[chan->address].data_rate;
@@ -413,7 +417,7 @@
 	mutex_lock(&data->lock);
 	switch (mask) {
 	case IIO_CHAN_INFO_SCALE:
-		ret = ads1015_set_scale(data, chan->address, val, val2);
+		ret = ads1015_set_scale(data, chan, val, val2);
 		break;
 	case IIO_CHAN_INFO_SAMP_FREQ:
 		ret = ads1015_set_data_rate(data, chan->address, val);
@@ -445,7 +449,10 @@
 	.validate_scan_mask = &iio_validate_scan_mask_onehot,
 };
 
-static IIO_CONST_ATTR(scale_available, "3 2 1 0.5 0.25 0.125");
+static IIO_CONST_ATTR_NAMED(ads1015_scale_available, scale_available,
+	"3 2 1 0.5 0.25 0.125");
+static IIO_CONST_ATTR_NAMED(ads1115_scale_available, scale_available,
+	"0.1875 0.125 0.0625 0.03125 0.015625 0.007813");
 
 static IIO_CONST_ATTR_NAMED(ads1015_sampling_frequency_available,
 	sampling_frequency_available, "128 250 490 920 1600 2400 3300");
@@ -453,7 +460,7 @@
 	sampling_frequency_available, "8 16 32 64 128 250 475 860");
 
 static struct attribute *ads1015_attributes[] = {
-	&iio_const_attr_scale_available.dev_attr.attr,
+	&iio_const_attr_ads1015_scale_available.dev_attr.attr,
 	&iio_const_attr_ads1015_sampling_frequency_available.dev_attr.attr,
 	NULL,
 };
@@ -463,7 +470,7 @@
 };
 
 static struct attribute *ads1115_attributes[] = {
-	&iio_const_attr_scale_available.dev_attr.attr,
+	&iio_const_attr_ads1115_scale_available.dev_attr.attr,
 	&iio_const_attr_ads1115_sampling_frequency_available.dev_attr.attr,
 	NULL,
 };
@@ -624,6 +631,15 @@
 		dev_err(&client->dev, "iio triggered buffer setup failed\n");
 		return ret;
 	}
+
+	ret = regmap_update_bits(data->regmap, ADS1015_CFG_REG,
+				ADS1015_CFG_MOD_MASK,
+				ADS1015_CONTINUOUS << ADS1015_CFG_MOD_SHIFT);
+	if (ret)
+		return ret;
+
+	data->conv_invalid = true;
+
 	ret = pm_runtime_set_active(&client->dev);
 	if (ret)
 		goto err_buffer_cleanup;
@@ -679,10 +695,15 @@
 {
 	struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
 	struct ads1015_data *data = iio_priv(indio_dev);
+	int ret;
 
-	return regmap_update_bits(data->regmap, ADS1015_CFG_REG,
+	ret = regmap_update_bits(data->regmap, ADS1015_CFG_REG,
 				  ADS1015_CFG_MOD_MASK,
 				  ADS1015_CONTINUOUS << ADS1015_CFG_MOD_SHIFT);
+	if (!ret)
+		data->conv_invalid = true;
+
+	return ret;
 }
 #endif
 
diff --git a/drivers/input/mouse/trackpoint.c b/drivers/input/mouse/trackpoint.c
index ce6ff9b..7e2dc5e 100644
--- a/drivers/input/mouse/trackpoint.c
+++ b/drivers/input/mouse/trackpoint.c
@@ -381,8 +381,8 @@
 		return 0;
 
 	if (trackpoint_read(&psmouse->ps2dev, TP_EXT_BTN, &button_info)) {
-		psmouse_warn(psmouse, "failed to get extended button data\n");
-		button_info = 0;
+		psmouse_warn(psmouse, "failed to get extended button data, assuming 3 buttons\n");
+		button_info = 0x33;
 	}
 
 	psmouse->private = kzalloc(sizeof(struct trackpoint_data), GFP_KERNEL);
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 817dfa3..e3cfffb 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -875,6 +875,14 @@
 		}
 		if (led->mpp_cfg->pwm_mode == PWM_MODE) {
 			/*config pwm for brightness scaling*/
+			rc = pwm_change_mode(led->mpp_cfg->pwm_cfg->pwm_dev,
+					PM_PWM_MODE_PWM);
+			if (rc < 0) {
+				dev_err(&led->pdev->dev,
+					"Failed to set PWM mode, rc = %d\n",
+					rc);
+				return rc;
+			}
 			period_us = led->mpp_cfg->pwm_cfg->pwm_period_us;
 			if (period_us > INT_MAX / NSEC_PER_USEC) {
 				duty_us = (period_us * led->cdev.brightness) /
@@ -1213,7 +1221,7 @@
 
 static int qpnp_flash_set(struct qpnp_led_data *led)
 {
-	int rc, error;
+	int rc = 0, error;
 	int val = led->cdev.brightness;
 
 	if (led->flash_cfg->torch_enable)
@@ -1251,7 +1259,8 @@
 				}
 			}
 
-			qpnp_led_masked_write(led, FLASH_MAX_CURR(led->base),
+			rc = qpnp_led_masked_write(led,
+				FLASH_MAX_CURR(led->base),
 				FLASH_CURRENT_MASK,
 				TORCH_MAX_LEVEL);
 			if (rc) {
@@ -1261,7 +1270,7 @@
 				goto error_reg_write;
 			}
 
-			qpnp_led_masked_write(led,
+			rc = qpnp_led_masked_write(led,
 				FLASH_LED_TMR_CTRL(led->base),
 				FLASH_TMR_MASK,
 				FLASH_TMR_WATCHDOG);
@@ -1293,7 +1302,7 @@
 				goto error_reg_write;
 			}
 
-			qpnp_led_masked_write(led,
+			rc = qpnp_led_masked_write(led,
 				FLASH_WATCHDOG_TMR(led->base),
 				FLASH_WATCHDOG_MASK,
 				led->flash_cfg->duration);
@@ -1341,7 +1350,7 @@
 				goto error_flash_set;
 			}
 
-			qpnp_led_masked_write(led,
+			rc = qpnp_led_masked_write(led,
 				FLASH_LED_TMR_CTRL(led->base),
 				FLASH_TMR_MASK,
 				FLASH_TMR_SAFETY);
@@ -1580,6 +1589,14 @@
 		}
 
 		if (led->kpdbl_cfg->pwm_cfg->mode == PWM_MODE) {
+			rc = pwm_change_mode(led->kpdbl_cfg->pwm_cfg->pwm_dev,
+					PM_PWM_MODE_PWM);
+			if (rc < 0) {
+				dev_err(&led->pdev->dev,
+					"Failed to set PWM mode, rc = %d\n",
+					rc);
+				return rc;
+			}
 			period_us = led->kpdbl_cfg->pwm_cfg->pwm_period_us;
 			if (period_us > INT_MAX / NSEC_PER_USEC) {
 				duty_us = (period_us * led->cdev.brightness) /
@@ -1701,6 +1718,14 @@
 			led->rgb_cfg->pwm_cfg->mode =
 				led->rgb_cfg->pwm_cfg->default_mode;
 		if (led->rgb_cfg->pwm_cfg->mode == PWM_MODE) {
+			rc = pwm_change_mode(led->rgb_cfg->pwm_cfg->pwm_dev,
+					PM_PWM_MODE_PWM);
+			if (rc < 0) {
+				dev_err(&led->pdev->dev,
+					"Failed to set PWM mode, rc = %d\n",
+					rc);
+				return rc;
+			}
 			period_us = led->rgb_cfg->pwm_cfg->pwm_period_us;
 			if (period_us > INT_MAX / NSEC_PER_USEC) {
 				duty_us = (period_us * led->cdev.brightness) /
@@ -2135,6 +2160,11 @@
 				dev_err(&pdev->dev, "Failed to configure pwm LUT\n");
 				return rc;
 			}
+			rc = pwm_change_mode(pwm_cfg->pwm_dev, PM_PWM_MODE_LPG);
+			if (rc < 0) {
+				dev_err(&pdev->dev, "Failed to set LPG mode\n");
+				return rc;
+			}
 		}
 	} else {
 		dev_err(&pdev->dev, "Invalid PWM device\n");
diff --git a/drivers/mailbox/msm_qmp.c b/drivers/mailbox/msm_qmp.c
index f0bb0bc..3b07c47 100644
--- a/drivers/mailbox/msm_qmp.c
+++ b/drivers/mailbox/msm_qmp.c
@@ -27,7 +27,7 @@
 #define QMP_VERSION	0x1
 #define QMP_FEATURES	0x0
 #define QMP_TOUT_MS	5000
-#define QMP_TX_TOUT_MS	2000
+#define QMP_TX_TOUT_MS	1000
 
 #define QMP_MBOX_LINK_DOWN		0xFFFF0000
 #define QMP_MBOX_LINK_UP		0x0000FFFF
@@ -229,7 +229,7 @@
 }
 
 /**
- * qmp_notify_timeout() - Notify client of tx timeout with -EIO
+ * qmp_notify_timeout() - Notify client of tx timeout with -ETIME
  * @work:	Structure for work that was scheduled.
  */
 static void qmp_notify_timeout(struct work_struct *work)
@@ -237,7 +237,7 @@
 	struct delayed_work *dwork = to_delayed_work(work);
 	struct qmp_mbox *mbox = container_of(dwork, struct qmp_mbox, dwork);
 	struct mbox_chan *chan = &mbox->ctrl.chans[mbox->idx_in_flight];
-	int err = -EIO;
+	int err = -ETIME;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mbox->tx_lock, flags);
@@ -246,6 +246,7 @@
 		return;
 	}
 	pr_err("%s: qmp tx timeout for %d\n", __func__, mbox->idx_in_flight);
+	iowrite32(0, mbox->mdev->msgram + mbox->mcore_mbox_offset);
 	mbox->tx_sent = false;
 	spin_unlock_irqrestore(&mbox->tx_lock, flags);
 	mbox_chan_txdone(chan, err);
diff --git a/drivers/mcb/mcb-lpc.c b/drivers/mcb/mcb-lpc.c
index d072c08..945091a 100644
--- a/drivers/mcb/mcb-lpc.c
+++ b/drivers/mcb/mcb-lpc.c
@@ -114,6 +114,12 @@
 	.flags = IORESOURCE_MEM,
 };
 
+static struct resource sc31_fpga_resource = {
+	.start = 0xf000e000,
+	.end = 0xf000e000 + CHAM_HEADER_SIZE,
+	.flags = IORESOURCE_MEM,
+};
+
 static struct platform_driver mcb_lpc_driver = {
 	.driver		= {
 		.name = "mcb-lpc",
@@ -132,6 +138,15 @@
 		.driver_data = (void *)&sc24_fpga_resource,
 		.callback = mcb_lpc_create_platform_device,
 	},
+	{
+		.ident = "SC31",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "MEN"),
+			DMI_MATCH(DMI_PRODUCT_VERSION, "14SC31"),
+		},
+		.driver_data = (void *)&sc31_fpga_resource,
+		.callback = mcb_lpc_create_platform_device,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(dmi, mcb_lpc_dmi_table);
diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
index bca4c0e..e289aae 100644
--- a/drivers/md/dm-rq.c
+++ b/drivers/md/dm-rq.c
@@ -848,8 +848,12 @@
 		tio = tio_from_request(rq);
 		/* Establish tio->ti before queuing work (map_tio_request) */
 		tio->ti = ti;
-		kthread_queue_work(&md->kworker, &tio->work);
+		spin_unlock(q->queue_lock);
+		if (map_request(tio) == DM_MAPIO_REQUEUE)
+			dm_requeue_original_request(tio, false);
+
 		BUG_ON(!irqs_disabled());
+		spin_lock(q->queue_lock);
 	}
 }
 
diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c
index 9b23376..7688f89 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.c
+++ b/drivers/media/platform/msm/vidc/msm_smem.c
@@ -603,22 +603,25 @@
 		__func__, mem->handle, mem->device_addr, mem->size,
 		mem->kvaddr, mem->buffer_type);
 
-	if (mem->device_addr)
+	if (mem->device_addr) {
 		msm_ion_put_device_address(client, mem->handle, mem->flags,
 			&mem->mapping_info, mem->buffer_type);
+		mem->device_addr = 0x0;
+	}
 
-	if (mem->kvaddr)
+	if (mem->kvaddr) {
 		ion_unmap_kernel(client->clnt, mem->handle);
+		mem->kvaddr = NULL;
+	}
 
 	if (mem->handle) {
 		trace_msm_smem_buffer_ion_op_start("FREE",
 				(u32)mem->buffer_type, -1, mem->size, -1,
 				mem->flags, -1);
 		ion_free(client->clnt, mem->handle);
+		mem->handle = NULL;
 		trace_msm_smem_buffer_ion_op_end("FREE", (u32)mem->buffer_type,
 			-1, mem->size, -1, mem->flags, -1);
-	} else {
-		dprintk(VIDC_ERR, "%s: invalid ion_handle\n", __func__);
 	}
 
 	return rc;
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index a527717..286a67e 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -537,7 +537,7 @@
 		.name = "VP8",
 		.description = "VP8 compressed format",
 		.fourcc = V4L2_PIX_FMT_VP8,
-		.get_frame_size = get_frame_size_compressed,
+		.get_frame_size = get_frame_size_compressed_full_yuv,
 		.type = OUTPUT_PORT,
 		.defer_outputs = false,
 	},
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index b4c0ab9..ae2a2c6 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -280,6 +280,7 @@
 		break;
 	case V4L2_PIX_FMT_NV12_TP10_UBWC:
 		color_format = COLOR_FMT_NV12_BPP10_UBWC;
+		break;
 	case V4L2_PIX_FMT_SDE_Y_CBCR_H2V2_P010:
 		color_format = COLOR_FMT_P010;
 		break;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 1ef1282..c6d31f7 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -553,7 +553,8 @@
 static int msm_vidc_set_clocks(struct msm_vidc_core *core)
 {
 	struct hfi_device *hdev;
-	unsigned long freq = 0, rate = 0;
+	unsigned long freq_core_1 = 0, freq_core_2 = 0, rate = 0;
+	unsigned long freq_core_max = 0;
 	struct msm_vidc_inst *temp = NULL;
 	int rc = 0, i = 0;
 	struct allowed_clock_rates_table *allowed_clks_tbl = NULL;
@@ -568,20 +569,33 @@
 
 	mutex_lock(&core->lock);
 	list_for_each_entry(temp, &core->instances, list) {
-		freq += temp->clk_data.curr_freq;
+
+		if (temp->clk_data.core_id == VIDC_CORE_ID_1)
+			freq_core_1 += temp->clk_data.min_freq;
+		else if (temp->clk_data.core_id == VIDC_CORE_ID_2)
+			freq_core_2 += temp->clk_data.min_freq;
+		else if (temp->clk_data.core_id == VIDC_CORE_ID_3) {
+			freq_core_1 += temp->clk_data.min_freq / 2;
+			freq_core_2 += temp->clk_data.min_freq / 2;
+		}
+
+		freq_core_max = max_t(unsigned long, freq_core_1, freq_core_2);
+
 		if (temp->clk_data.turbo_mode) {
 			dprintk(VIDC_PROF,
 				"Found an instance with Turbo request\n");
-			freq = msm_vidc_max_freq(core);
+			freq_core_max = msm_vidc_max_freq(core);
 			break;
 		}
 	}
+
 	for (i = core->resources.allowed_clks_tbl_size - 1; i >= 0; i--) {
 		rate = allowed_clks_tbl[i].clock_rate;
-		if (rate >= freq)
+		if (rate >= freq_core_max)
 			break;
 	}
-	core->min_freq = freq;
+
+	core->min_freq = freq_core_max;
 	core->curr_freq = rate;
 	mutex_unlock(&core->lock);
 
@@ -1018,17 +1032,21 @@
 }
 
 static u32 get_core_load(struct msm_vidc_core *core,
-	u32 core_id, bool lp_mode)
+	u32 core_id, bool lp_mode, bool real_time)
 {
 	struct msm_vidc_inst *inst = NULL;
 	u32 current_inst_mbs_per_sec = 0, load = 0;
+	bool real_time_mode = false;
 
 	mutex_lock(&core->lock);
 	list_for_each_entry(inst, &core->instances, list) {
 		u32 cycles, lp_cycles;
 
+		real_time_mode = inst->flags & VIDC_REALTIME ? true : false;
 		if (!(inst->clk_data.core_id & core_id))
 			continue;
+		if (real_time_mode != real_time)
+			continue;
 		if (inst->session_type == MSM_VIDC_DECODER) {
 			cycles = lp_cycles = inst->clk_data.entry->vpp_cycles;
 		} else if (inst->session_type == MSM_VIDC_ENCODER) {
@@ -1073,10 +1091,10 @@
 	max_freq = msm_vidc_max_freq(inst->core);
 	inst->clk_data.core_id = 0;
 
-	core0_load = get_core_load(core, VIDC_CORE_ID_1, false);
-	core1_load = get_core_load(core, VIDC_CORE_ID_2, false);
-	core0_lp_load = get_core_load(core, VIDC_CORE_ID_1, true);
-	core1_lp_load = get_core_load(core, VIDC_CORE_ID_2, true);
+	core0_load = get_core_load(core, VIDC_CORE_ID_1, false, true);
+	core1_load = get_core_load(core, VIDC_CORE_ID_2, false, true);
+	core0_lp_load = get_core_load(core, VIDC_CORE_ID_1, true, true);
+	core1_lp_load = get_core_load(core, VIDC_CORE_ID_2, true, true);
 
 	min_load = min(core0_load, core1_load);
 	min_core_id = core0_load < core1_load ?
@@ -1095,9 +1113,9 @@
 	current_inst_lp_load = msm_comm_get_inst_load(inst,
 		LOAD_CALC_NO_QUIRKS) * lp_cycles;
 
-	dprintk(VIDC_DBG, "Core 0 Load = %d Core 1 Load = %d\n",
+	dprintk(VIDC_DBG, "Core 0 RT Load = %d Core 1 RT Load = %d\n",
 		 core0_load, core1_load);
-	dprintk(VIDC_DBG, "Core 0 LP Load = %d Core 1 LP Load = %d\n",
+	dprintk(VIDC_DBG, "Core 0 RT LP Load = %d Core 1 RT LP Load = %d\n",
 		core0_lp_load, core1_lp_load);
 	dprintk(VIDC_DBG, "Max Load = %lu\n", max_freq);
 	dprintk(VIDC_DBG, "Current Load = %d Current LP Load = %d\n",
@@ -1191,12 +1209,12 @@
 	mutex_lock(&core->lock);
 	list_for_each_entry(inst, &core->instances, list) {
 
-		if (!((inst->clk_data.core_id & core_id) ||
-			  (inst->clk_data.core_id & VIDC_CORE_ID_3)))
+		if ((inst->clk_data.core_id != core_id) &&
+			(inst->clk_data.core_id != VIDC_CORE_ID_3))
 			continue;
 
 		dprintk(VIDC_PROF,
-			"inst %pK (%4ux%4u) to (%4ux%4u) %3u %s %s %s %s\n",
+			"inst %pK (%4ux%4u) to (%4ux%4u) %3u %s %s %s %s %lu\n",
 			inst,
 			inst->prop.width[OUTPUT_PORT],
 			inst->prop.height[OUTPUT_PORT],
@@ -1207,7 +1225,8 @@
 			inst->clk_data.work_mode == VIDC_WORK_MODE_1 ?
 				"WORK_MODE_1" : "WORK_MODE_2",
 			inst->flags & VIDC_LOW_POWER ? "LP" : "HQ",
-			inst->flags & VIDC_REALTIME ? "RealTime" : "NonRTime");
+			inst->flags & VIDC_REALTIME ? "RealTime" : "NonRTime",
+			inst->clk_data.min_freq);
 	}
 	mutex_unlock(&core->lock);
 }
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 4238eda..2beb90c 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -2196,7 +2196,8 @@
 			"%s: Send sys error for inst %pK\n", __func__, inst);
 		change_inst_state(inst, MSM_VIDC_CORE_INVALID);
 		msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_SYS_ERROR);
-		msm_comm_print_inst_info(inst);
+		if (!core->trigger_ssr)
+			msm_comm_print_inst_info(inst);
 	}
 	dprintk(VIDC_DBG, "Calling core_release\n");
 	rc = call_hfi_op(hdev, core_release, hdev->hfi_device_data);
@@ -4776,6 +4777,7 @@
 	mutex_lock(&inst->eosbufs.lock);
 	list_for_each_entry_safe(buf, next, &inst->eosbufs.list, list) {
 		list_del(&buf->list);
+		msm_comm_smem_free(inst, &buf->smem);
 		kfree(buf);
 	}
 	INIT_LIST_HEAD(&inst->eosbufs.list);
@@ -5323,8 +5325,7 @@
 		LOAD_CALC_IGNORE_NON_REALTIME_LOAD;
 
 	if (inst->state == MSM_VIDC_OPEN_DONE) {
-		max_load_adj = inst->core->resources.max_load +
-			inst->capability.mbs_per_frame.max;
+		max_load_adj = inst->core->resources.max_load;
 		num_mbs_per_sec = msm_comm_get_load(inst->core,
 					MSM_VIDC_DECODER, quirks);
 		num_mbs_per_sec += msm_comm_get_load(inst->core,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.h b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
index c1828b3..dbebe5d 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.h
@@ -113,7 +113,6 @@
 
 #define MSM_VIDC_ERROR(value)					\
 	do {							\
-		dprintk(VIDC_DBG, "Fatal Level = %d\n", value);\
 		BUG_ON(value);					\
 	} while (0)
 
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_platform.c b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
index 3aaee84..a82b598 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_platform.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
@@ -119,7 +119,7 @@
 	},
 	{
 		.key = "qcom,max-hw-load",
-		.value = 2563200,
+		.value = 3110400,	/* 4096x2160@90 */
 	},
 	{
 		.key = "qcom,max-hq-mbs-per-frame",
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index dde6029..0fbc96e 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -4282,10 +4282,65 @@
 	return rc;
 }
 
+static void __noc_error_info(struct venus_hfi_device *device, u32 core_num)
+{
+	u32 vcodec_core_video_noc_base_offs, val;
+
+	if (!device) {
+		dprintk(VIDC_ERR, "%s: null device\n", __func__);
+		return;
+	}
+	if (!core_num) {
+		vcodec_core_video_noc_base_offs =
+			VCODEC_CORE0_VIDEO_NOC_BASE_OFFS;
+	} else if (core_num == 1) {
+		vcodec_core_video_noc_base_offs =
+			VCODEC_CORE1_VIDEO_NOC_BASE_OFFS;
+	} else {
+		dprintk(VIDC_ERR, "%s: invalid core_num %u\n",
+			__func__, core_num);
+		return;
+	}
+
+	val = __read_register(device, vcodec_core_video_noc_base_offs +
+			VCODEC_COREX_VIDEO_NOC_ERR_SWID_LOW_OFFS);
+	dprintk(VIDC_ERR, "CORE%d_NOC_ERR_SWID_LOW:     %#x\n", core_num, val);
+	val = __read_register(device, vcodec_core_video_noc_base_offs +
+			VCODEC_COREX_VIDEO_NOC_ERR_SWID_HIGH_OFFS);
+	dprintk(VIDC_ERR, "CORE%d_NOC_ERR_SWID_HIGH:    %#x\n", core_num, val);
+	val = __read_register(device, vcodec_core_video_noc_base_offs +
+			VCODEC_COREX_VIDEO_NOC_ERR_MAINCTL_LOW_OFFS);
+	dprintk(VIDC_ERR, "CORE%d_NOC_ERR_MAINCTL_LOW:  %#x\n", core_num, val);
+	val = __read_register(device, vcodec_core_video_noc_base_offs +
+			VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG0_LOW_OFFS);
+	dprintk(VIDC_ERR, "CORE%d_NOC_ERR_ERRLOG0_LOW:  %#x\n", core_num, val);
+	val = __read_register(device, vcodec_core_video_noc_base_offs +
+			VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG0_HIGH_OFFS);
+	dprintk(VIDC_ERR, "CORE%d_NOC_ERR_ERRLOG0_HIGH: %#x\n", core_num, val);
+	val = __read_register(device, vcodec_core_video_noc_base_offs +
+			VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG1_LOW_OFFS);
+	dprintk(VIDC_ERR, "CORE%d_NOC_ERR_ERRLOG1_LOW:  %#x\n", core_num, val);
+	val = __read_register(device, vcodec_core_video_noc_base_offs +
+			VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG1_HIGH_OFFS);
+	dprintk(VIDC_ERR, "CORE%d_NOC_ERR_ERRLOG1_HIGH: %#x\n", core_num, val);
+	val = __read_register(device, vcodec_core_video_noc_base_offs +
+			VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG2_LOW_OFFS);
+	dprintk(VIDC_ERR, "CORE%d_NOC_ERR_ERRLOG2_LOW:  %#x\n", core_num, val);
+	val = __read_register(device, vcodec_core_video_noc_base_offs +
+			VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG2_HIGH_OFFS);
+	dprintk(VIDC_ERR, "CORE%d_NOC_ERR_ERRLOG2_HIGH: %#x\n", core_num, val);
+	val = __read_register(device, vcodec_core_video_noc_base_offs +
+			VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG3_LOW_OFFS);
+	dprintk(VIDC_ERR, "CORE%d_NOC_ERR_ERRLOG3_LOW:  %#x\n", core_num, val);
+	val = __read_register(device, vcodec_core_video_noc_base_offs +
+			VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG3_HIGH_OFFS);
+	dprintk(VIDC_ERR, "CORE%d_NOC_ERR_ERRLOG3_HIGH: %#x\n", core_num, val);
+}
+
 static int venus_hfi_noc_error_info(void *dev)
 {
 	struct venus_hfi_device *device;
-	u32 val = 0;
+	const u32 core0 = 0, core1 = 1;
 
 	if (!dev) {
 		dprintk(VIDC_ERR, "%s: null device\n", __func__);
@@ -4296,44 +4351,13 @@
 	mutex_lock(&device->lock);
 	dprintk(VIDC_ERR, "%s: non error information\n", __func__);
 
-	val = __read_register(device, 0x0C500);
-	dprintk(VIDC_ERR, "NOC_ERR_SWID_LOW(0x00AA0C500):     %#x\n", val);
+	if (__read_register(device, VCODEC_CORE0_VIDEO_NOC_BASE_OFFS +
+			VCODEC_COREX_VIDEO_NOC_ERR_ERRVLD_LOW_OFFS))
+		__noc_error_info(device, core0);
 
-	val = __read_register(device, 0x0C504);
-	dprintk(VIDC_ERR, "NOC_ERR_SWID_HIGH(0x00AA0C504):    %#x\n", val);
-
-	val = __read_register(device, 0x0C508);
-	dprintk(VIDC_ERR, "NOC_ERR_MAINCTL_LOW(0x00AA0C508):  %#x\n", val);
-
-	val = __read_register(device, 0x0C510);
-	dprintk(VIDC_ERR, "NOC_ERR_ERRVLD_LOW(0x00AA0C510):   %#x\n", val);
-
-	val = __read_register(device, 0x0C518);
-	dprintk(VIDC_ERR, "NOC_ERR_ERRCLR_LOW(0x00AA0C518):   %#x\n", val);
-
-	val = __read_register(device, 0x0C520);
-	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG0_LOW(0x00AA0C520):  %#x\n", val);
-
-	val = __read_register(device, 0x0C524);
-	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG0_HIGH(0x00AA0C524): %#x\n", val);
-
-	val = __read_register(device, 0x0C528);
-	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG1_LOW(0x00AA0C528):  %#x\n", val);
-
-	val = __read_register(device, 0x0C52C);
-	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG1_HIGH(0x00AA0C52C): %#x\n", val);
-
-	val = __read_register(device, 0x0C530);
-	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG2_LOW(0x00AA0C530):  %#x\n", val);
-
-	val = __read_register(device, 0x0C534);
-	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG2_HIGH(0x00AA0C534): %#x\n", val);
-
-	val = __read_register(device, 0x0C538);
-	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG3_LOW(0x00AA0C538):  %#x\n", val);
-
-	val = __read_register(device, 0x0C53C);
-	dprintk(VIDC_ERR, "NOC_ERR_ERRLOG3_HIGH(0x00AA0C53C): %#x\n", val);
+	if (__read_register(device, VCODEC_CORE1_VIDEO_NOC_BASE_OFFS +
+			VCODEC_COREX_VIDEO_NOC_ERR_ERRVLD_LOW_OFFS))
+		__noc_error_info(device, core1);
 
 	mutex_unlock(&device->lock);
 
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_io.h b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
index fc32d73..3433483 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_io.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
@@ -190,4 +190,25 @@
 #define VIDC_UC_REGION_ADDR 0x000D2064
 #define VIDC_UC_REGION_SIZE 0x000D2068
 
+/*
+ * --------------------------------------------------------------------------
+ * MODULE: vcodec noc error log registers
+ * --------------------------------------------------------------------------
+ */
+#define VCODEC_CORE0_VIDEO_NOC_BASE_OFFS		0x00004000
+#define VCODEC_CORE1_VIDEO_NOC_BASE_OFFS		0x0000C000
+#define VCODEC_COREX_VIDEO_NOC_ERR_SWID_LOW_OFFS	0x0500
+#define VCODEC_COREX_VIDEO_NOC_ERR_SWID_HIGH_OFFS	0x0504
+#define VCODEC_COREX_VIDEO_NOC_ERR_MAINCTL_LOW_OFFS	0x0508
+#define VCODEC_COREX_VIDEO_NOC_ERR_ERRVLD_LOW_OFFS	0x0510
+#define VCODEC_COREX_VIDEO_NOC_ERR_ERRCLR_LOW_OFFS	0x0518
+#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG0_LOW_OFFS	0x0520
+#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG0_HIGH_OFFS	0x0524
+#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG1_LOW_OFFS	0x0528
+#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG1_HIGH_OFFS	0x052C
+#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG2_LOW_OFFS	0x0530
+#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG2_HIGH_OFFS	0x0534
+#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG3_LOW_OFFS	0x0538
+#define VCODEC_COREX_VIDEO_NOC_ERR_ERRLOG3_HIGH_OFFS	0x053C
+
 #endif
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 7077b30..7567f86 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -3126,6 +3126,7 @@
 				struct qseecom_send_cmd_req *req)
 {
 	int ret = 0;
+	int ret2 = 0;
 	u32 reqd_len_sb_in = 0;
 	struct qseecom_client_send_data_ireq send_data_req = {0};
 	struct qseecom_client_send_data_64bit_ireq send_data_req_64bit = {0};
@@ -3224,32 +3225,38 @@
 	if (ret) {
 		pr_err("scm_call() failed with err: %d (app_id = %d)\n",
 					ret, data->client.app_id);
-		return ret;
+		goto exit;
 	}
 
 	if (qseecom.qsee_reentrancy_support) {
 		ret = __qseecom_process_reentrancy(&resp, ptr_app, data);
+		if (ret)
+			goto exit;
 	} else {
 		if (resp.result == QSEOS_RESULT_INCOMPLETE) {
 			ret = __qseecom_process_incomplete_cmd(data, &resp);
 			if (ret) {
 				pr_err("process_incomplete_cmd failed err: %d\n",
 						ret);
-				return ret;
+				goto exit;
 			}
 		} else {
 			if (resp.result != QSEOS_RESULT_SUCCESS) {
 				pr_err("Response result %d not supported\n",
 								resp.result);
 				ret = -EINVAL;
+				goto exit;
 			}
 		}
 	}
-	ret = msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle,
+exit:
+	ret2 = msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle,
 				data->client.sb_virt, data->client.sb_length,
 				ION_IOC_INV_CACHES);
-	if (ret)
-		pr_err("cache operation failed %d\n", ret);
+	if (ret2) {
+		pr_err("cache operation failed %d\n", ret2);
+		return ret2;
+	}
 	return ret;
 }
 
@@ -6575,6 +6582,7 @@
 	bool found_app = false;
 	unsigned long flags;
 	int ret = 0;
+	int ret2 = 0;
 	uint32_t reqd_len_sb_in = 0;
 	void *cmd_buf = NULL;
 	size_t cmd_len;
@@ -6684,43 +6692,47 @@
 	if (ret) {
 		pr_err("scm_call() failed with err: %d (app_id = %d)\n",
 					ret, data->client.app_id);
-		return ret;
+		goto exit;
 	}
 
 	if (qseecom.qsee_reentrancy_support) {
 		ret = __qseecom_process_reentrancy(&resp, ptr_app, data);
+		if (ret)
+			goto exit;
 	} else {
 		if (resp.result == QSEOS_RESULT_INCOMPLETE) {
 			ret = __qseecom_process_incomplete_cmd(data, &resp);
 			if (ret) {
 				pr_err("process_incomplete_cmd failed err: %d\n",
 						ret);
-				return ret;
+				goto exit;
 			}
 		} else {
 			if (resp.result != QSEOS_RESULT_SUCCESS) {
 				pr_err("Response result %d not supported\n",
 								resp.result);
 				ret = -EINVAL;
+				goto exit;
 			}
 		}
 	}
-	ret = msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle,
+exit:
+	ret2 = msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle,
 				data->client.sb_virt, data->client.sb_length,
 				ION_IOC_INV_CACHES);
-	if (ret) {
+	if (ret2) {
 		pr_err("cache operation failed %d\n", ret);
-		return ret;
+		return ret2;
 	}
 
 	if ((cmd_id == QSEOS_TEE_OPEN_SESSION) ||
 			(cmd_id == QSEOS_TEE_REQUEST_CANCELLATION)) {
-		ret = __qseecom_update_qteec_req_buf(
+		ret2 = __qseecom_update_qteec_req_buf(
 			(struct qseecom_qteec_modfd_req *)req, data, true);
-		if (ret)
-			return ret;
+		if (ret2)
+			return ret2;
 	}
-	return 0;
+	return ret;
 }
 
 static int qseecom_qteec_open_session(struct qseecom_dev_handle *data,
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index 82ff1a5..591d6b2 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -220,6 +220,10 @@
 static void cmdq_dumpregs(struct cmdq_host *cq_host)
 {
 	struct mmc_host *mmc = cq_host->mmc;
+	int offset = 0;
+
+	if (cq_host->offset_changed)
+		offset = CQ_V5_VENDOR_CFG;
 
 	MMC_TRACE(mmc,
 	"%s: 0x0C=0x%08x 0x10=0x%08x 0x14=0x%08x 0x18=0x%08x 0x28=0x%08x 0x2C=0x%08x 0x30=0x%08x 0x34=0x%08x 0x54=0x%08x 0x58=0x%08x 0x5C=0x%08x 0x48=0x%08x\n",
@@ -266,7 +270,7 @@
 		cmdq_readl(cq_host, CQCRI),
 		cmdq_readl(cq_host, CQCRA));
 	pr_err(DRV_NAME": Vendor cfg 0x%08x\n",
-	       cmdq_readl(cq_host, CQ_VENDOR_CFG));
+	       cmdq_readl(cq_host, CQ_VENDOR_CFG + offset));
 	pr_err(DRV_NAME ": ===========================================\n");
 
 	cmdq_dump_task_history(cq_host);
@@ -407,6 +411,12 @@
 		cq_host->caps |= CMDQ_CAP_CRYPTO_SUPPORT |
 				 CMDQ_TASK_DESC_SZ_128;
 		cqcfg |= CQ_ICE_ENABLE;
+		/*
+		 * For SDHC v5.0 onwards, ICE 3.0 specific registers are added
+		 * in CQ register space, due to which few CQ registers are
+		 * shifted. Set offset_changed boolean to use updated address.
+		 */
+		cq_host->offset_changed = true;
 	}
 
 	cmdq_writel(cq_host, cqcfg, CQCFG);
@@ -841,16 +851,29 @@
 {
 	struct mmc_request *mrq;
 	struct cmdq_host *cq_host = (struct cmdq_host *)mmc_cmdq_private(mmc);
+	int offset = 0;
+	int err = 0;
 
+	if (cq_host->offset_changed)
+		offset = CQ_V5_VENDOR_CFG;
 	mrq = get_req_by_tag(cq_host, tag);
 	if (tag == cq_host->dcmd_slot)
 		mrq->cmd->resp[0] = cmdq_readl(cq_host, CQCRDCT);
 
 	if (mrq->cmdq_req->cmdq_req_flags & DCMD)
-		cmdq_writel(cq_host, cmdq_readl(cq_host, CQ_VENDOR_CFG) |
-			    CMDQ_SEND_STATUS_TRIGGER, CQ_VENDOR_CFG);
+		cmdq_writel(cq_host,
+			cmdq_readl(cq_host, CQ_VENDOR_CFG + offset) |
+			CMDQ_SEND_STATUS_TRIGGER, CQ_VENDOR_CFG + offset);
 
 	cmdq_runtime_pm_put(cq_host);
+
+	if (cq_host->ops->crypto_cfg_end) {
+		err = cq_host->ops->crypto_cfg_end(mmc, mrq);
+		if (err) {
+			pr_err("%s: failed to end ice config: err %d tag %d\n",
+					mmc_hostname(mmc), err, tag);
+		}
+	}
 	if (!(cq_host->caps & CMDQ_CAP_CRYPTO_SUPPORT) &&
 			cq_host->ops->crypto_cfg_reset)
 		cq_host->ops->crypto_cfg_reset(mmc, tag);
diff --git a/drivers/mmc/host/cmdq_hci.h b/drivers/mmc/host/cmdq_hci.h
index 551a7c5..1aabce9 100644
--- a/drivers/mmc/host/cmdq_hci.h
+++ b/drivers/mmc/host/cmdq_hci.h
@@ -145,6 +145,11 @@
 #define DAT_ADDR_LO(x)	((x & 0xFFFFFFFF) << 32)
 #define DAT_ADDR_HI(x)	((x & 0xFFFFFFFF) << 0)
 
+/*
+ * Add new macro for updated CQ vendor specific
+ * register address for SDHC v5.0 onwards.
+ */
+#define CQ_V5_VENDOR_CFG	0x900
 #define CQ_VENDOR_CFG	0x100
 #define CMDQ_SEND_STATUS_TRIGGER (1 << 31)
 
@@ -177,6 +182,7 @@
 	bool enabled;
 	bool halted;
 	bool init_done;
+	bool offset_changed;
 
 	u8 *desc_base;
 
@@ -218,6 +224,7 @@
 	void (*post_cqe_halt)(struct mmc_host *mmc);
 	int (*crypto_cfg)(struct mmc_host *mmc, struct mmc_request *mrq,
 				u32 slot, u64 *ice_ctx);
+	int (*crypto_cfg_end)(struct mmc_host *mmc, struct mmc_request *mrq);
 	void (*crypto_cfg_reset)(struct mmc_host *mmc, unsigned int slot);
 };
 
diff --git a/drivers/mmc/host/sdhci-msm-ice.c b/drivers/mmc/host/sdhci-msm-ice.c
index 29eaff4..f86ce5b 100644
--- a/drivers/mmc/host/sdhci-msm-ice.c
+++ b/drivers/mmc/host/sdhci-msm-ice.c
@@ -377,7 +377,7 @@
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = pltfm_host->priv;
 	int err = 0;
-	short key_index;
+	short key_index = 0;
 	sector_t lba = 0;
 	unsigned int bypass = SDHCI_MSM_ICE_ENABLE_BYPASS;
 	struct request *req;
@@ -414,6 +414,37 @@
 	return 0;
 }
 
+int sdhci_msm_ice_cfg_end(struct sdhci_host *host, struct mmc_request *mrq)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	int err = 0;
+	struct request *req;
+
+	if (!host->is_crypto_en)
+		return 0;
+
+	if (msm_host->ice.state != SDHCI_MSM_ICE_STATE_ACTIVE) {
+		pr_err("%s: ice is in invalid state %d\n",
+			mmc_hostname(host->mmc), msm_host->ice.state);
+		return -EINVAL;
+	}
+
+	req = mrq->req;
+	if (req) {
+		if (msm_host->ice.vops->config_end) {
+			err = msm_host->ice.vops->config_end(req);
+			if (err) {
+				pr_err("%s: ice config end failed %d\n",
+						mmc_hostname(host->mmc), err);
+				return err;
+			}
+		}
+	}
+
+	return 0;
+}
+
 int sdhci_msm_ice_reset(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
diff --git a/drivers/mmc/host/sdhci-msm-ice.h b/drivers/mmc/host/sdhci-msm-ice.h
index 1afd1a9..6296174 100644
--- a/drivers/mmc/host/sdhci-msm-ice.h
+++ b/drivers/mmc/host/sdhci-msm-ice.h
@@ -107,6 +107,7 @@
 			u32 slot);
 int sdhci_msm_ice_cmdq_cfg(struct sdhci_host *host,
 			struct mmc_request *mrq, u32 slot, u64 *ice_ctx);
+int sdhci_msm_ice_cfg_end(struct sdhci_host *host, struct mmc_request *mrq);
 int sdhci_msm_ice_reset(struct sdhci_host *host);
 int sdhci_msm_ice_resume(struct sdhci_host *host);
 int sdhci_msm_ice_suspend(struct sdhci_host *host);
@@ -143,6 +144,11 @@
 {
 	return 0;
 }
+static inline int sdhci_msm_ice_cfg_end(struct sdhci_host *host,
+			struct mmc_request *mrq)
+{
+	return 0;
+}
 inline int sdhci_msm_ice_reset(struct sdhci_host *host)
 {
 	return 0;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index d93de2e..55d9cf5 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -1902,8 +1902,16 @@
 			dev_err(dev, "Invalid clock table\n");
 			goto out;
 		}
+		if (ice_clk_table_len != 2) {
+			dev_err(dev, "Need max and min frequencies in the table\n");
+			goto out;
+		}
 		pdata->sup_ice_clk_table = ice_clk_table;
 		pdata->sup_ice_clk_cnt = ice_clk_table_len;
+		pdata->ice_clk_max = pdata->sup_ice_clk_table[0];
+		pdata->ice_clk_min = pdata->sup_ice_clk_table[1];
+		dev_dbg(dev, "supported ICE clock rates (Hz): max: %u min: %u\n",
+				pdata->ice_clk_max, pdata->ice_clk_min);
 	}
 
 	pdata->vreg_data = devm_kzalloc(dev, sizeof(struct
@@ -3408,6 +3416,8 @@
 	/* registers offset changed starting from 4.2.0 */
 	int offset = minor >= SDHCI_MSM_VER_420 ? 0 : 0x48;
 
+	if (cq_host->offset_changed)
+		offset += CQ_V5_VENDOR_CFG;
 	pr_err("---- Debug RAM dump ----\n");
 	pr_err(DRV_NAME ": Debug RAM wrap-around: 0x%08x | Debug RAM overlap: 0x%08x\n",
 	       cmdq_readl(cq_host, CQ_CMD_DBG_RAM_WA + offset),
@@ -4113,9 +4123,36 @@
 	return max_curr;
 }
 
+static int sdhci_msm_notify_load(struct sdhci_host *host, enum mmc_load state)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct sdhci_msm_host *msm_host = pltfm_host->priv;
+	int ret = 0;
+	u32 clk_rate = 0;
+
+	if (!IS_ERR(msm_host->ice_clk)) {
+		clk_rate = (state == MMC_LOAD_LOW) ?
+			msm_host->pdata->ice_clk_min :
+			msm_host->pdata->ice_clk_max;
+		if (msm_host->ice_clk_rate == clk_rate)
+			return 0;
+		pr_debug("%s: changing ICE clk rate to %u\n",
+				mmc_hostname(host->mmc), clk_rate);
+		ret = clk_set_rate(msm_host->ice_clk, clk_rate);
+		if (ret) {
+			pr_err("%s: ICE_CLK rate set failed (%d) for %u\n",
+				mmc_hostname(host->mmc), ret, clk_rate);
+			return ret;
+		}
+		msm_host->ice_clk_rate = clk_rate;
+	}
+	return 0;
+}
+
 static struct sdhci_ops sdhci_msm_ops = {
 	.crypto_engine_cfg = sdhci_msm_ice_cfg,
 	.crypto_engine_cmdq_cfg = sdhci_msm_ice_cmdq_cfg,
+	.crypto_engine_cfg_end = sdhci_msm_ice_cfg_end,
 	.crypto_cfg_reset = sdhci_msm_ice_cfg_reset,
 	.crypto_engine_reset = sdhci_msm_ice_reset,
 	.set_uhs_signaling = sdhci_msm_set_uhs_signaling,
@@ -4139,6 +4176,7 @@
 	.pre_req = sdhci_msm_pre_req,
 	.post_req = sdhci_msm_post_req,
 	.get_current_limit = sdhci_msm_get_current_limit,
+	.notify_load = sdhci_msm_notify_load,
 };
 
 static void sdhci_set_default_hw_caps(struct sdhci_msm_host *msm_host,
@@ -4351,7 +4389,7 @@
 		 */
 		dev_err(&pdev->dev, "%s: required ICE device not probed yet err = %d\n",
 			__func__, ret);
-		goto out_host_free;
+		goto pltfm_free;
 
 	} else if (ret == -ENODEV) {
 		/*
@@ -4363,7 +4401,7 @@
 	} else if (ret) {
 		dev_err(&pdev->dev, "%s: sdhci_msm_ice_get_dev failed %d\n",
 			__func__, ret);
-		goto out_host_free;
+		goto pltfm_free;
 	}
 
 	/* Extract platform data */
@@ -4436,11 +4474,11 @@
 		if (!IS_ERR(msm_host->ice_clk)) {
 			/* ICE core has only one clock frequency for now */
 			ret = clk_set_rate(msm_host->ice_clk,
-					msm_host->pdata->sup_ice_clk_table[0]);
+					msm_host->pdata->ice_clk_max);
 			if (ret) {
 				dev_err(&pdev->dev, "ICE_CLK rate set failed (%d) for %u\n",
 					ret,
-					msm_host->pdata->sup_ice_clk_table[0]);
+					msm_host->pdata->ice_clk_max);
 				goto pclk_disable;
 			}
 			ret = clk_prepare_enable(msm_host->ice_clk);
@@ -4448,7 +4486,7 @@
 				goto pclk_disable;
 
 			msm_host->ice_clk_rate =
-				msm_host->pdata->sup_clk_table[0];
+				msm_host->pdata->ice_clk_max;
 		}
 	}
 
diff --git a/drivers/mmc/host/sdhci-msm.h b/drivers/mmc/host/sdhci-msm.h
index cdbaaa9..7c0b873 100644
--- a/drivers/mmc/host/sdhci-msm.h
+++ b/drivers/mmc/host/sdhci-msm.h
@@ -151,6 +151,8 @@
 	unsigned char sup_ice_clk_cnt;
 	struct sdhci_msm_pm_qos_data pm_qos_data;
 	bool sdr104_wa;
+	u32 ice_clk_max;
+	u32 ice_clk_min;
 };
 
 struct sdhci_msm_bus_vote {
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 7f13f07..4476e51 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1785,6 +1785,22 @@
 	return err;
 }
 
+static int sdhci_crypto_cfg_end(struct sdhci_host *host,
+				struct mmc_request *mrq)
+{
+	int err = 0;
+
+	if (host->ops->crypto_engine_cfg_end) {
+		err = host->ops->crypto_engine_cfg_end(host, mrq);
+		if (err) {
+			pr_err("%s: failed to configure crypto\n",
+					mmc_hostname(host->mmc));
+			return err;
+		}
+	}
+	return 0;
+}
+
 static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
 	struct sdhci_host *host;
@@ -2876,6 +2892,7 @@
 	mmiowb();
 	spin_unlock_irqrestore(&host->lock, flags);
 
+	sdhci_crypto_cfg_end(host, mrq);
 	mmc_request_done(host->mmc, mrq);
 
 	return false;
@@ -3806,6 +3823,17 @@
 	return err;
 }
 
+static int sdhci_cmdq_crypto_cfg_end(struct mmc_host *mmc,
+					struct mmc_request *mrq)
+{
+	struct sdhci_host *host = mmc_priv(mmc);
+
+	if (!host->is_crypto_en)
+		return 0;
+
+	return sdhci_crypto_cfg_end(host, mrq);
+}
+
 static void sdhci_cmdq_crypto_cfg_reset(struct mmc_host *mmc, unsigned int slot)
 {
 	struct sdhci_host *host = mmc_priv(mmc);
@@ -3868,6 +3896,12 @@
 	return 0;
 }
 
+static int sdhci_cmdq_crypto_cfg_end(struct mmc_host *mmc,
+				struct mmc_request *mrq)
+{
+	return 0;
+}
+
 static void sdhci_cmdq_crypto_cfg_reset(struct mmc_host *mmc, unsigned int slot)
 {
 
@@ -3884,6 +3918,7 @@
 	.post_cqe_halt = sdhci_cmdq_post_cqe_halt,
 	.set_transfer_params = sdhci_cmdq_set_transfer_params,
 	.crypto_cfg	= sdhci_cmdq_crypto_cfg,
+	.crypto_cfg_end	= sdhci_cmdq_crypto_cfg_end,
 	.crypto_cfg_reset	= sdhci_cmdq_crypto_cfg_reset,
 };
 
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index a463e45..2b67d0a 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -673,6 +673,8 @@
 				struct mmc_request *mrq, u32 slot);
 	int	(*crypto_engine_cmdq_cfg)(struct sdhci_host *host,
 			struct mmc_request *mrq, u32 slot, u64 *ice_ctx);
+	int	(*crypto_engine_cfg_end)(struct sdhci_host *host,
+					struct mmc_request *mrq);
 	int	(*crypto_engine_reset)(struct sdhci_host *host);
 	void	(*crypto_cfg_reset)(struct sdhci_host *host, unsigned int slot);
 	void	(*set_uhs_signaling)(struct sdhci_host *host, unsigned int uhs);
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index d7f724b..0c84ee8 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -877,6 +877,8 @@
 	}
 }
 
+#define MXC_V1_ECCBYTES		5
+
 static int mxc_v1_ooblayout_ecc(struct mtd_info *mtd, int section,
 				struct mtd_oob_region *oobregion)
 {
@@ -886,7 +888,7 @@
 		return -ERANGE;
 
 	oobregion->offset = (section * 16) + 6;
-	oobregion->length = nand_chip->ecc.bytes;
+	oobregion->length = MXC_V1_ECCBYTES;
 
 	return 0;
 }
@@ -908,8 +910,7 @@
 			oobregion->length = 4;
 		}
 	} else {
-		oobregion->offset = ((section - 1) * 16) +
-				    nand_chip->ecc.bytes + 6;
+		oobregion->offset = ((section - 1) * 16) + MXC_V1_ECCBYTES + 6;
 		if (section < nand_chip->ecc.steps)
 			oobregion->length = (section * 16) + 6 -
 					    oobregion->offset;
diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c
index 57d483a..6f0fd15 100644
--- a/drivers/mtd/nand/qcom_nandc.c
+++ b/drivers/mtd/nand/qcom_nandc.c
@@ -109,7 +109,11 @@
 #define	READ_ADDR			0
 
 /* NAND_DEV_CMD_VLD bits */
-#define	READ_START_VLD			0
+#define	READ_START_VLD			BIT(0)
+#define	READ_STOP_VLD			BIT(1)
+#define	WRITE_START_VLD			BIT(2)
+#define	ERASE_START_VLD			BIT(3)
+#define	SEQ_READ_START_VLD		BIT(4)
 
 /* NAND_EBI2_ECC_BUF_CFG bits */
 #define	NUM_STEPS			0
@@ -148,6 +152,10 @@
 #define	FETCH_ID			0xb
 #define	RESET_DEVICE			0xd
 
+/* Default Value for NAND_DEV_CMD_VLD */
+#define NAND_DEV_CMD_VLD_VAL		(READ_START_VLD | WRITE_START_VLD | \
+					 ERASE_START_VLD | SEQ_READ_START_VLD)
+
 /*
  * the NAND controller performs reads/writes with ECC in 516 byte chunks.
  * the driver calls the chunks 'step' or 'codeword' interchangeably
@@ -672,8 +680,7 @@
 
 	/* configure CMD1 and VLD for ONFI param probing */
 	nandc_set_reg(nandc, NAND_DEV_CMD_VLD,
-		      (nandc->vld & ~(1 << READ_START_VLD))
-		      | 0 << READ_START_VLD);
+		      (nandc->vld & ~READ_START_VLD));
 	nandc_set_reg(nandc, NAND_DEV_CMD1,
 		      (nandc->cmd1 & ~(0xFF << READ_ADDR))
 		      | NAND_CMD_PARAM << READ_ADDR);
@@ -1893,7 +1900,7 @@
 				| wide_bus << WIDE_FLASH
 				| 1 << DEV0_CFG1_ECC_DISABLE;
 
-	host->ecc_bch_cfg = host->bch_enabled << ECC_CFG_ECC_DISABLE
+	host->ecc_bch_cfg = !host->bch_enabled << ECC_CFG_ECC_DISABLE
 				| 0 << ECC_SW_RESET
 				| host->cw_data << ECC_NUM_DATA_BYTES
 				| 1 << ECC_FORCE_CLK_OPEN
@@ -1972,13 +1979,14 @@
 {
 	/* kill onenand */
 	nandc_write(nandc, SFLASHC_BURST_CFG, 0);
+	nandc_write(nandc, NAND_DEV_CMD_VLD, NAND_DEV_CMD_VLD_VAL);
 
 	/* enable ADM DMA */
 	nandc_write(nandc, NAND_FLASH_CHIP_SELECT, DM_EN);
 
 	/* save the original values of these registers */
 	nandc->cmd1 = nandc_read(nandc, NAND_DEV_CMD1);
-	nandc->vld = nandc_read(nandc, NAND_DEV_CMD_VLD);
+	nandc->vld = NAND_DEV_CMD_VLD_VAL;
 
 	return 0;
 }
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 972b5e2..366d3dc 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -1852,6 +1852,12 @@
 		goto err_wmi_detach;
 	}
 
+	/* If firmware indicates Full Rx Reorder support it must be used in a
+	 * slightly different manner. Let HTT code know.
+	 */
+	ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER,
+						ar->wmi.svc_map));
+
 	status = ath10k_htt_rx_alloc(&ar->htt);
 	if (status) {
 		ath10k_err(ar, "failed to alloc htt rx: %d\n", status);
@@ -1964,12 +1970,6 @@
 		}
 	}
 
-	/* If firmware indicates Full Rx Reorder support it must be used in a
-	 * slightly different manner. Let HTT code know.
-	 */
-	ar->htt.rx_ring.in_ord_rx = !!(test_bit(WMI_SERVICE_RX_FULL_REORDER,
-						ar->wmi.svc_map));
-
 	status = ath10k_htt_rx_ring_refill(ar);
 	if (status) {
 		ath10k_err(ar, "failed to refill htt rx ring: %d\n", status);
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 2f8134b..177fd5b 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -429,6 +429,7 @@
 	{IWL_PCI_DEVICE(0x095B, 0x520A, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9000, iwl7265_2ac_cfg)},
 	{IWL_PCI_DEVICE(0x095A, 0x9400, iwl7265_2ac_cfg)},
+	{IWL_PCI_DEVICE(0x095A, 0x9E10, iwl7265_2ac_cfg)},
 
 /* 8000 Series */
 	{IWL_PCI_DEVICE(0x24F3, 0x0010, iwl8260_2ac_cfg)},
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index afdbbf5..8677a53 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -4188,7 +4188,7 @@
 	if (adapter->config_bands & BAND_A)
 		n_channels_a = mwifiex_band_5ghz.n_channels;
 
-	adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a);
+	adapter->num_in_chan_stats = n_channels_bg + n_channels_a;
 	adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) *
 				      adapter->num_in_chan_stats);
 
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
index 97c9765..78d59a6 100644
--- a/drivers/net/wireless/marvell/mwifiex/scan.c
+++ b/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -2479,6 +2479,12 @@
 					      sizeof(struct mwifiex_chan_stats);
 
 	for (i = 0 ; i < num_chan; i++) {
+		if (adapter->survey_idx >= adapter->num_in_chan_stats) {
+			mwifiex_dbg(adapter, WARN,
+				    "FW reported too many channel results (max %d)\n",
+				    adapter->num_in_chan_stats);
+			return;
+		}
 		chan_stats.chan_num = fw_chan_stats->chan_num;
 		chan_stats.bandcfg = fw_chan_stats->bandcfg;
 		chan_stats.flags = fw_chan_stats->flags;
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 5be4fc9..75ffeaa 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -2269,7 +2269,7 @@
 	/* find adapter */
 	if (!_rtl_pci_find_adapter(pdev, hw)) {
 		err = -ENODEV;
-		goto fail3;
+		goto fail2;
 	}
 
 	/* Init IO handler */
@@ -2339,10 +2339,10 @@
 	pci_set_drvdata(pdev, NULL);
 	rtl_deinit_core(hw);
 
+fail2:
 	if (rtlpriv->io.pci_mem_start != 0)
 		pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
 
-fail2:
 	pci_release_regions(pdev);
 	complete(&rtlpriv->firmware_loading_complete);
 
diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c
index 5a3f008..eef1a68 100644
--- a/drivers/nvme/host/fabrics.c
+++ b/drivers/nvme/host/fabrics.c
@@ -77,7 +77,7 @@
 	kref_init(&host->ref);
 	uuid_be_gen(&host->id);
 	snprintf(host->nqn, NVMF_NQN_SIZE,
-		"nqn.2014-08.org.nvmexpress:NVMf:uuid:%pUb", &host->id);
+		"nqn.2014-08.org.nvmexpress:uuid:%pUb", &host->id);
 
 	mutex_lock(&nvmf_hosts_mutex);
 	list_add_tail(&host->list, &nvmf_hosts);
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index 8da8571..d39a17f 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -79,6 +79,16 @@
 	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
 	  Qualcomm TLMM block found on the Qualcomm 8916 platform.
 
+config PINCTRL_MSM8953
+	tristate "Qualcomm Technologies Inc MSM8953 pin controller driver"
+	depends on GPIOLIB && OF
+	select PINCTRL_MSM
+	help
+	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+	  Qualcomm Technologies Inc TLMM block found on the Qualcomm
+	  Technologies Inc MSM8953 platform.
+	  If unsure say N.
+
 config PINCTRL_SDM845
 	tristate "Qualcomm Technologies Inc SDM845 pin controller driver"
 	depends on GPIOLIB && OF
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 392ed2a..c9f5c11 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -11,6 +11,7 @@
 obj-$(CONFIG_PINCTRL_MSM8996)   += pinctrl-msm8996.o
 obj-$(CONFIG_PINCTRL_QDF2XXX)	+= pinctrl-qdf2xxx.o
 obj-$(CONFIG_PINCTRL_MDM9615)	+= pinctrl-mdm9615.o
+obj-$(CONFIG_PINCTRL_MSM8953)   += pinctrl-msm8953.o
 obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-gpio.o
 obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-mpp.o
 obj-$(CONFIG_PINCTRL_QCOM_SSBI_PMIC) += pinctrl-ssbi-gpio.o
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8953.c b/drivers/pinctrl/qcom/pinctrl-msm8953.c
new file mode 100644
index 0000000..ba1cad0
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-msm8953.c
@@ -0,0 +1,1686 @@
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+#define FUNCTION(fname)			                \
+	[msm_mux_##fname] = {		                \
+		.name = #fname,				\
+		.groups = fname##_groups,               \
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+#define REG_SIZE 0x1000
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9)	\
+	{					        \
+		.name = "gpio" #id,			\
+		.pins = gpio##id##_pins,		\
+		.npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins),	\
+		.funcs = (int[]){			\
+			msm_mux_gpio, /* gpio mode */	\
+			msm_mux_##f1,			\
+			msm_mux_##f2,			\
+			msm_mux_##f3,			\
+			msm_mux_##f4,			\
+			msm_mux_##f5,			\
+			msm_mux_##f6,			\
+			msm_mux_##f7,			\
+			msm_mux_##f8,			\
+			msm_mux_##f9			\
+		},				        \
+		.nfuncs = 10,				\
+		.ctl_reg = REG_SIZE * id,			\
+		.io_reg = 0x4 + REG_SIZE * id,		\
+		.intr_cfg_reg = 0x8 + REG_SIZE * id,		\
+		.intr_status_reg = 0xc + REG_SIZE * id,	\
+		.intr_target_reg = 0x8 + REG_SIZE * id,	\
+		.mux_bit = 2,			\
+		.pull_bit = 0,			\
+		.drv_bit = 6,			\
+		.oe_bit = 9,			\
+		.in_bit = 0,			\
+		.out_bit = 1,			\
+		.intr_enable_bit = 0,		\
+		.intr_status_bit = 0,		\
+		.intr_target_bit = 5,		\
+		.intr_target_kpss_val = 4,	\
+		.intr_raw_status_bit = 4,	\
+		.intr_polarity_bit = 1,		\
+		.intr_detection_bit = 2,	\
+		.intr_detection_width = 2,	\
+	}
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv)	\
+	{					        \
+		.name = #pg_name,			\
+		.pins = pg_name##_pins,			\
+		.npins = (unsigned int)ARRAY_SIZE(pg_name##_pins),	\
+		.ctl_reg = ctl,				\
+		.io_reg = 0,				\
+		.intr_cfg_reg = 0,			\
+		.intr_status_reg = 0,			\
+		.intr_target_reg = 0,			\
+		.mux_bit = -1,				\
+		.pull_bit = pull,			\
+		.drv_bit = drv,				\
+		.oe_bit = -1,				\
+		.in_bit = -1,				\
+		.out_bit = -1,				\
+		.intr_enable_bit = -1,			\
+		.intr_status_bit = -1,			\
+		.intr_target_bit = -1,			\
+		.intr_raw_status_bit = -1,		\
+		.intr_polarity_bit = -1,		\
+		.intr_detection_bit = -1,		\
+		.intr_detection_width = -1,		\
+	}
+static const struct pinctrl_pin_desc msm8953_pins[] = {
+	PINCTRL_PIN(0, "GPIO_0"),
+	PINCTRL_PIN(1, "GPIO_1"),
+	PINCTRL_PIN(2, "GPIO_2"),
+	PINCTRL_PIN(3, "GPIO_3"),
+	PINCTRL_PIN(4, "GPIO_4"),
+	PINCTRL_PIN(5, "GPIO_5"),
+	PINCTRL_PIN(6, "GPIO_6"),
+	PINCTRL_PIN(7, "GPIO_7"),
+	PINCTRL_PIN(8, "GPIO_8"),
+	PINCTRL_PIN(9, "GPIO_9"),
+	PINCTRL_PIN(10, "GPIO_10"),
+	PINCTRL_PIN(11, "GPIO_11"),
+	PINCTRL_PIN(12, "GPIO_12"),
+	PINCTRL_PIN(13, "GPIO_13"),
+	PINCTRL_PIN(14, "GPIO_14"),
+	PINCTRL_PIN(15, "GPIO_15"),
+	PINCTRL_PIN(16, "GPIO_16"),
+	PINCTRL_PIN(17, "GPIO_17"),
+	PINCTRL_PIN(18, "GPIO_18"),
+	PINCTRL_PIN(19, "GPIO_19"),
+	PINCTRL_PIN(20, "GPIO_20"),
+	PINCTRL_PIN(21, "GPIO_21"),
+	PINCTRL_PIN(22, "GPIO_22"),
+	PINCTRL_PIN(23, "GPIO_23"),
+	PINCTRL_PIN(24, "GPIO_24"),
+	PINCTRL_PIN(25, "GPIO_25"),
+	PINCTRL_PIN(26, "GPIO_26"),
+	PINCTRL_PIN(27, "GPIO_27"),
+	PINCTRL_PIN(28, "GPIO_28"),
+	PINCTRL_PIN(29, "GPIO_29"),
+	PINCTRL_PIN(30, "GPIO_30"),
+	PINCTRL_PIN(31, "GPIO_31"),
+	PINCTRL_PIN(32, "GPIO_32"),
+	PINCTRL_PIN(33, "GPIO_33"),
+	PINCTRL_PIN(34, "GPIO_34"),
+	PINCTRL_PIN(35, "GPIO_35"),
+	PINCTRL_PIN(36, "GPIO_36"),
+	PINCTRL_PIN(37, "GPIO_37"),
+	PINCTRL_PIN(38, "GPIO_38"),
+	PINCTRL_PIN(39, "GPIO_39"),
+	PINCTRL_PIN(40, "GPIO_40"),
+	PINCTRL_PIN(41, "GPIO_41"),
+	PINCTRL_PIN(42, "GPIO_42"),
+	PINCTRL_PIN(43, "GPIO_43"),
+	PINCTRL_PIN(44, "GPIO_44"),
+	PINCTRL_PIN(45, "GPIO_45"),
+	PINCTRL_PIN(46, "GPIO_46"),
+	PINCTRL_PIN(47, "GPIO_47"),
+	PINCTRL_PIN(48, "GPIO_48"),
+	PINCTRL_PIN(49, "GPIO_49"),
+	PINCTRL_PIN(50, "GPIO_50"),
+	PINCTRL_PIN(51, "GPIO_51"),
+	PINCTRL_PIN(52, "GPIO_52"),
+	PINCTRL_PIN(53, "GPIO_53"),
+	PINCTRL_PIN(54, "GPIO_54"),
+	PINCTRL_PIN(55, "GPIO_55"),
+	PINCTRL_PIN(56, "GPIO_56"),
+	PINCTRL_PIN(57, "GPIO_57"),
+	PINCTRL_PIN(58, "GPIO_58"),
+	PINCTRL_PIN(59, "GPIO_59"),
+	PINCTRL_PIN(60, "GPIO_60"),
+	PINCTRL_PIN(61, "GPIO_61"),
+	PINCTRL_PIN(62, "GPIO_62"),
+	PINCTRL_PIN(63, "GPIO_63"),
+	PINCTRL_PIN(64, "GPIO_64"),
+	PINCTRL_PIN(65, "GPIO_65"),
+	PINCTRL_PIN(66, "GPIO_66"),
+	PINCTRL_PIN(67, "GPIO_67"),
+	PINCTRL_PIN(68, "GPIO_68"),
+	PINCTRL_PIN(69, "GPIO_69"),
+	PINCTRL_PIN(70, "GPIO_70"),
+	PINCTRL_PIN(71, "GPIO_71"),
+	PINCTRL_PIN(72, "GPIO_72"),
+	PINCTRL_PIN(73, "GPIO_73"),
+	PINCTRL_PIN(74, "GPIO_74"),
+	PINCTRL_PIN(75, "GPIO_75"),
+	PINCTRL_PIN(76, "GPIO_76"),
+	PINCTRL_PIN(77, "GPIO_77"),
+	PINCTRL_PIN(78, "GPIO_78"),
+	PINCTRL_PIN(79, "GPIO_79"),
+	PINCTRL_PIN(80, "GPIO_80"),
+	PINCTRL_PIN(81, "GPIO_81"),
+	PINCTRL_PIN(82, "GPIO_82"),
+	PINCTRL_PIN(83, "GPIO_83"),
+	PINCTRL_PIN(84, "GPIO_84"),
+	PINCTRL_PIN(85, "GPIO_85"),
+	PINCTRL_PIN(86, "GPIO_86"),
+	PINCTRL_PIN(87, "GPIO_87"),
+	PINCTRL_PIN(88, "GPIO_88"),
+	PINCTRL_PIN(89, "GPIO_89"),
+	PINCTRL_PIN(90, "GPIO_90"),
+	PINCTRL_PIN(91, "GPIO_91"),
+	PINCTRL_PIN(92, "GPIO_92"),
+	PINCTRL_PIN(93, "GPIO_93"),
+	PINCTRL_PIN(94, "GPIO_94"),
+	PINCTRL_PIN(95, "GPIO_95"),
+	PINCTRL_PIN(96, "GPIO_96"),
+	PINCTRL_PIN(97, "GPIO_97"),
+	PINCTRL_PIN(98, "GPIO_98"),
+	PINCTRL_PIN(99, "GPIO_99"),
+	PINCTRL_PIN(100, "GPIO_100"),
+	PINCTRL_PIN(101, "GPIO_101"),
+	PINCTRL_PIN(102, "GPIO_102"),
+	PINCTRL_PIN(103, "GPIO_103"),
+	PINCTRL_PIN(104, "GPIO_104"),
+	PINCTRL_PIN(105, "GPIO_105"),
+	PINCTRL_PIN(106, "GPIO_106"),
+	PINCTRL_PIN(107, "GPIO_107"),
+	PINCTRL_PIN(108, "GPIO_108"),
+	PINCTRL_PIN(109, "GPIO_109"),
+	PINCTRL_PIN(110, "GPIO_110"),
+	PINCTRL_PIN(111, "GPIO_111"),
+	PINCTRL_PIN(112, "GPIO_112"),
+	PINCTRL_PIN(113, "GPIO_113"),
+	PINCTRL_PIN(114, "GPIO_114"),
+	PINCTRL_PIN(115, "GPIO_115"),
+	PINCTRL_PIN(116, "GPIO_116"),
+	PINCTRL_PIN(117, "GPIO_117"),
+	PINCTRL_PIN(118, "GPIO_118"),
+	PINCTRL_PIN(119, "GPIO_119"),
+	PINCTRL_PIN(120, "GPIO_120"),
+	PINCTRL_PIN(121, "GPIO_121"),
+	PINCTRL_PIN(122, "GPIO_122"),
+	PINCTRL_PIN(123, "GPIO_123"),
+	PINCTRL_PIN(124, "GPIO_124"),
+	PINCTRL_PIN(125, "GPIO_125"),
+	PINCTRL_PIN(126, "GPIO_126"),
+	PINCTRL_PIN(127, "GPIO_127"),
+	PINCTRL_PIN(128, "GPIO_128"),
+	PINCTRL_PIN(129, "GPIO_129"),
+	PINCTRL_PIN(130, "GPIO_130"),
+	PINCTRL_PIN(131, "GPIO_131"),
+	PINCTRL_PIN(132, "GPIO_132"),
+	PINCTRL_PIN(133, "GPIO_133"),
+	PINCTRL_PIN(134, "GPIO_134"),
+	PINCTRL_PIN(135, "GPIO_135"),
+	PINCTRL_PIN(136, "GPIO_136"),
+	PINCTRL_PIN(137, "GPIO_137"),
+	PINCTRL_PIN(138, "GPIO_138"),
+	PINCTRL_PIN(139, "GPIO_139"),
+	PINCTRL_PIN(140, "GPIO_140"),
+	PINCTRL_PIN(141, "GPIO_141"),
+	PINCTRL_PIN(142, "SDC1_CLK"),
+	PINCTRL_PIN(143, "SDC1_CMD"),
+	PINCTRL_PIN(144, "SDC1_DATA"),
+	PINCTRL_PIN(145, "SDC1_RCLK"),
+	PINCTRL_PIN(146, "SDC2_CLK"),
+	PINCTRL_PIN(147, "SDC2_CMD"),
+	PINCTRL_PIN(148, "SDC2_DATA"),
+	PINCTRL_PIN(149, "QDSD_CLK"),
+	PINCTRL_PIN(150, "QDSD_CMD"),
+	PINCTRL_PIN(151, "QDSD_DATA0"),
+	PINCTRL_PIN(152, "QDSD_DATA1"),
+	PINCTRL_PIN(153, "QDSD_DATA2"),
+	PINCTRL_PIN(154, "QDSD_DATA3"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+	static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+DECLARE_MSM_GPIO_PINS(133);
+DECLARE_MSM_GPIO_PINS(134);
+DECLARE_MSM_GPIO_PINS(135);
+DECLARE_MSM_GPIO_PINS(136);
+DECLARE_MSM_GPIO_PINS(137);
+DECLARE_MSM_GPIO_PINS(138);
+DECLARE_MSM_GPIO_PINS(139);
+DECLARE_MSM_GPIO_PINS(140);
+DECLARE_MSM_GPIO_PINS(141);
+
+static const unsigned int sdc1_clk_pins[] = { 142 };
+static const unsigned int sdc1_cmd_pins[] = { 143 };
+static const unsigned int sdc1_data_pins[] = { 144 };
+static const unsigned int sdc1_rclk_pins[] = { 145 };
+static const unsigned int sdc2_clk_pins[] = { 146 };
+static const unsigned int sdc2_cmd_pins[] = { 147 };
+static const unsigned int sdc2_data_pins[] = { 148 };
+static const unsigned int qdsd_clk_pins[] = { 149 };
+static const unsigned int qdsd_cmd_pins[] = { 150 };
+static const unsigned int qdsd_data0_pins[] = { 151 };
+static const unsigned int qdsd_data1_pins[] = { 152 };
+static const unsigned int qdsd_data2_pins[] = { 153 };
+static const unsigned int qdsd_data3_pins[] = { 154 };
+
+enum msm8953_functions {
+	msm_mux_gpio,
+	msm_mux_blsp_spi1,
+	msm_mux_smb_int,
+	msm_mux_adsp_ext,
+	msm_mux_prng_rosc,
+	msm_mux_blsp_i2c1,
+	msm_mux_qdss_cti_trig_out_b0,
+	msm_mux_qdss_cti_trig_out_a1,
+	msm_mux_blsp_spi2,
+	msm_mux_blsp_uart2,
+	msm_mux_ldo_update,
+	msm_mux_dac_calib0,
+	msm_mux_ldo_en,
+	msm_mux_blsp_i2c2,
+	msm_mux_gcc_gp1_clk_b,
+	msm_mux_atest_gpsadc_dtest0_native,
+	msm_mux_blsp_spi3,
+	msm_mux_qdss_tracedata_b,
+	msm_mux_pwr_modem_enabled_b,
+	msm_mux_blsp_i2c3,
+	msm_mux_gcc_gp2_clk_b,
+	msm_mux_gcc_gp3_clk_b,
+	msm_mux_hall_int,
+	msm_mux_blsp_spi4,
+	msm_mux_blsp_uart4,
+	msm_mux_pwr_nav_enabled_b,
+	msm_mux_dac_calib1,
+	msm_mux_cap_int,
+	msm_mux_pwr_crypto_enabled_b,
+	msm_mux_dac_calib2,
+	msm_mux_blsp_i2c4,
+	msm_mux_nfc_disable,
+	msm_mux_blsp_spi5,
+	msm_mux_blsp_uart5,
+	msm_mux_qdss_traceclk_a,
+	msm_mux_atest_bbrx1,
+	msm_mux_nfc_irq,
+	msm_mux_m_voc,
+	msm_mux_qdss_cti_trig_in_a0,
+	msm_mux_atest_bbrx0,
+	msm_mux_blsp_i2c5,
+	msm_mux_qdss_tracectl_a,
+	msm_mux_atest_gpsadc_dtest1_native,
+	msm_mux_qdss_tracedata_a,
+	msm_mux_blsp_spi6,
+	msm_mux_blsp_uart6,
+	msm_mux_qdss_tracectl_b,
+	msm_mux_dac_calib15,
+	msm_mux_qdss_cti_trig_in_b0,
+	msm_mux_dac_calib16,
+	msm_mux_blsp_i2c6,
+	msm_mux_qdss_traceclk_b,
+	msm_mux_atest_wlan0,
+	msm_mux_atest_wlan1,
+	msm_mux_mdp_vsync,
+	msm_mux_pri_mi2s_mclk_a,
+	msm_mux_sec_mi2s_mclk_a,
+	msm_mux_qdss_cti_trig_out_b1,
+	msm_mux_cam_mclk,
+	msm_mux_dac_calib3,
+	msm_mux_cci_i2c,
+	msm_mux_pwr_modem_enabled_a,
+	msm_mux_dac_calib4,
+	msm_mux_dac_calib19,
+	msm_mux_flash_strobe,
+	msm_mux_cci_timer0,
+	msm_mux_cci_timer1,
+	msm_mux_cam_irq,
+	msm_mux_cci_timer2,
+	msm_mux_blsp1_spi,
+	msm_mux_pwr_nav_enabled_a,
+	msm_mux_ois_sync,
+	msm_mux_cci_timer3,
+	msm_mux_cci_timer4,
+	msm_mux_blsp3_spi,
+	msm_mux_qdss_cti_trig_out_a0,
+	msm_mux_dac_calib7,
+	msm_mux_accel_int,
+	msm_mux_gcc_gp1_clk_a,
+	msm_mux_dac_calib8,
+	msm_mux_alsp_int,
+	msm_mux_gcc_gp2_clk_a,
+	msm_mux_dac_calib9,
+	msm_mux_mag_int,
+	msm_mux_gcc_gp3_clk_a,
+	msm_mux_pwr_crypto_enabled_a,
+	msm_mux_cci_async,
+	msm_mux_cam1_standby,
+	msm_mux_dac_calib5,
+	msm_mux_cam1_rst,
+	msm_mux_dac_calib6,
+	msm_mux_dac_calib10,
+	msm_mux_gyro_int,
+	msm_mux_dac_calib11,
+	msm_mux_pressure_int,
+	msm_mux_dac_calib12,
+	msm_mux_blsp6_spi,
+	msm_mux_dac_calib13,
+	msm_mux_fp_int,
+	msm_mux_qdss_cti_trig_in_b1,
+	msm_mux_dac_calib14,
+	msm_mux_uim_batt,
+	msm_mux_cam0_ldo,
+	msm_mux_sd_write,
+	msm_mux_uim1_data,
+	msm_mux_uim1_clk,
+	msm_mux_uim1_reset,
+	msm_mux_uim1_present,
+	msm_mux_uim2_data,
+	msm_mux_uim2_clk,
+	msm_mux_uim2_reset,
+	msm_mux_uim2_present,
+	msm_mux_ts_xvdd,
+	msm_mux_mipi_dsi0,
+	msm_mux_nfc_dwl,
+	msm_mux_us_euro,
+	msm_mux_atest_char3,
+	msm_mux_dbg_out,
+	msm_mux_bimc_dte0,
+	msm_mux_ts_resout,
+	msm_mux_ts_sample,
+	msm_mux_sec_mi2s_mclk_b,
+	msm_mux_pri_mi2s,
+	msm_mux_codec_reset,
+	msm_mux_cdc_pdm0,
+	msm_mux_atest_char1,
+	msm_mux_ebi_cdc,
+	msm_mux_dac_calib17,
+	msm_mux_us_emitter,
+	msm_mux_atest_char0,
+	msm_mux_pri_mi2s_mclk_b,
+	msm_mux_lpass_slimbus,
+	msm_mux_lpass_slimbus0,
+	msm_mux_lpass_slimbus1,
+	msm_mux_codec_int1,
+	msm_mux_codec_int2,
+	msm_mux_wcss_bt,
+	msm_mux_atest_char2,
+	msm_mux_ebi_ch0,
+	msm_mux_wcss_wlan2,
+	msm_mux_wcss_wlan1,
+	msm_mux_wcss_wlan0,
+	msm_mux_wcss_wlan,
+	msm_mux_wcss_fm,
+	msm_mux_ext_lpass,
+	msm_mux_mss_lte,
+	msm_mux_key_volp,
+	msm_mux_pbs0,
+	msm_mux_cri_trng0,
+	msm_mux_key_snapshot,
+	msm_mux_pbs1,
+	msm_mux_cri_trng1,
+	msm_mux_key_focus,
+	msm_mux_pbs2,
+	msm_mux_cri_trng,
+	msm_mux_gcc_tlmm,
+	msm_mux_key_home,
+	msm_mux_pwr_down,
+	msm_mux_dmic0_clk,
+	msm_mux_blsp7_spi,
+	msm_mux_hdmi_int,
+	msm_mux_dmic0_data,
+	msm_mux_qdss_cti_trig_in_a1,
+	msm_mux_pri_mi2s_ws,
+	msm_mux_wsa_io,
+	msm_mux_wsa_en,
+	msm_mux_blsp_spi8,
+	msm_mux_wsa_irq,
+	msm_mux_blsp_i2c8,
+	msm_mux_gcc_plltest,
+	msm_mux_nav_pps_in_a,
+	msm_mux_pa_indicator,
+	msm_mux_nav_pps_in_b,
+	msm_mux_nav_pps,
+	msm_mux_modem_tsync,
+	msm_mux_nav_tsync,
+	msm_mux_ssbi_wtr1,
+	msm_mux_gsm1_tx,
+	msm_mux_dac_calib18,
+	msm_mux_gsm0_tx,
+	msm_mux_atest_char,
+	msm_mux_atest_tsens,
+	msm_mux_bimc_dte1,
+	msm_mux_dac_calib20,
+	msm_mux_cam2_rst,
+	msm_mux_ddr_bist,
+	msm_mux_dac_calib21,
+	msm_mux_cam2_standby,
+	msm_mux_dac_calib22,
+	msm_mux_cam3_rst,
+	msm_mux_dac_calib23,
+	msm_mux_cam3_standby,
+	msm_mux_dac_calib24,
+	msm_mux_sdcard_det,
+	msm_mux_dac_calib25,
+	msm_mux_cam1_ldo,
+	msm_mux_sec_mi2s,
+	msm_mux_blsp_spi7,
+	msm_mux_blsp_i2c7,
+	msm_mux_ss_switch,
+	msm_mux_tsens_max,
+	msm_mux_NA,
+};
+
+static const char * const gpio_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+	"gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+	"gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+	"gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+	"gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+	"gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+	"gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+	"gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+	"gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+	"gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+	"gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+	"gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+	"gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
+	"gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140",
+	"gpio141",
+};
+static const char * const blsp_spi1_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const smb_int_groups[] = {
+	"gpio1",
+};
+static const char * const adsp_ext_groups[] = {
+	"gpio1",
+};
+static const char * const prng_rosc_groups[] = {
+	"gpio2",
+};
+static const char * const blsp_i2c1_groups[] = {
+	"gpio2", "gpio3",
+};
+static const char * const qdss_cti_trig_out_b0_groups[] = {
+	"gpio2",
+};
+static const char * const qdss_cti_trig_out_a1_groups[] = {
+	"gpio3",
+};
+static const char * const blsp_spi2_groups[] = {
+	"gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uart2_groups[] = {
+	"gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const ldo_update_groups[] = {
+	"gpio4",
+};
+static const char * const dac_calib0_groups[] = {
+	"gpio4",
+};
+static const char * const ldo_en_groups[] = {
+	"gpio5",
+};
+static const char * const blsp_i2c2_groups[] = {
+	"gpio6", "gpio7",
+};
+static const char * const gcc_gp1_clk_b_groups[] = {
+	"gpio6", "gpio41",
+};
+static const char * const atest_gpsadc_dtest0_native_groups[] = {
+	"gpio7",
+};
+static const char * const blsp_spi3_groups[] = {
+	"gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const qdss_tracedata_b_groups[] = {
+	"gpio8", "gpio9", "gpio12", "gpio13", "gpio23", "gpio42", "gpio43",
+	"gpio44", "gpio45", "gpio46", "gpio47", "gpio66", "gpio86", "gpio87",
+	"gpio88", "gpio92",
+};
+static const char * const pwr_modem_enabled_b_groups[] = {
+	"gpio9",
+};
+static const char * const blsp_i2c3_groups[] = {
+	"gpio10", "gpio11",
+};
+static const char * const gcc_gp2_clk_b_groups[] = {
+	"gpio10",
+};
+static const char * const gcc_gp3_clk_b_groups[] = {
+	"gpio11",
+};
+static const char * const hall_int_groups[] = {
+	"gpio12",
+};
+static const char * const blsp_spi4_groups[] = {
+	"gpio12", "gpio13", "gpio14", "gpio15",
+};
+static const char * const blsp_uart4_groups[] = {
+	"gpio12", "gpio13", "gpio14", "gpio15",
+};
+static const char * const pwr_nav_enabled_b_groups[] = {
+	"gpio12",
+};
+static const char * const dac_calib1_groups[] = {
+	"gpio12",
+};
+static const char * const cap_int_groups[] = {
+	"gpio13",
+};
+static const char * const pwr_crypto_enabled_b_groups[] = {
+	"gpio13",
+};
+static const char * const dac_calib2_groups[] = {
+	"gpio13",
+};
+static const char * const blsp_i2c4_groups[] = {
+	"gpio14", "gpio15",
+};
+static const char * const nfc_disable_groups[] = {
+	"gpio16",
+};
+static const char * const blsp_spi5_groups[] = {
+	"gpio16", "gpio17", "gpio18", "gpio19",
+};
+static const char * const blsp_uart5_groups[] = {
+	"gpio16", "gpio17", "gpio18", "gpio19",
+};
+static const char * const qdss_traceclk_a_groups[] = {
+	"gpio16",
+};
+static const char * const atest_bbrx1_groups[] = {
+	"gpio16",
+};
+static const char * const nfc_irq_groups[] = {
+	"gpio17",
+};
+static const char * const m_voc_groups[] = {
+	"gpio17", "gpio21",
+};
+static const char * const qdss_cti_trig_in_a0_groups[] = {
+	"gpio17",
+};
+static const char * const atest_bbrx0_groups[] = {
+	"gpio17",
+};
+static const char * const blsp_i2c5_groups[] = {
+	"gpio18", "gpio19",
+};
+static const char * const qdss_tracectl_a_groups[] = {
+	"gpio18",
+};
+static const char * const atest_gpsadc_dtest1_native_groups[] = {
+	"gpio18",
+};
+static const char * const qdss_tracedata_a_groups[] = {
+	"gpio19", "gpio26", "gpio27", "gpio28", "gpio29", "gpio30", "gpio31",
+	"gpio32", "gpio33", "gpio34", "gpio35", "gpio36", "gpio38", "gpio39",
+	"gpio40", "gpio50",
+};
+static const char * const blsp_spi6_groups[] = {
+	"gpio20", "gpio21", "gpio22", "gpio23",
+};
+static const char * const blsp_uart6_groups[] = {
+	"gpio20", "gpio21", "gpio22", "gpio23",
+};
+static const char * const qdss_tracectl_b_groups[] = {
+	"gpio20",
+};
+static const char * const dac_calib15_groups[] = {
+	"gpio20",
+};
+static const char * const qdss_cti_trig_in_b0_groups[] = {
+	"gpio21",
+};
+static const char * const dac_calib16_groups[] = {
+	"gpio21",
+};
+static const char * const blsp_i2c6_groups[] = {
+	"gpio22", "gpio23",
+};
+static const char * const qdss_traceclk_b_groups[] = {
+	"gpio22",
+};
+static const char * const atest_wlan0_groups[] = {
+	"gpio22",
+};
+static const char * const atest_wlan1_groups[] = {
+	"gpio23",
+};
+static const char * const mdp_vsync_groups[] = {
+	"gpio24", "gpio25",
+};
+static const char * const pri_mi2s_mclk_a_groups[] = {
+	"gpio25",
+};
+static const char * const sec_mi2s_mclk_a_groups[] = {
+	"gpio25",
+};
+static const char * const qdss_cti_trig_out_b1_groups[] = {
+	"gpio25",
+};
+static const char * const cam_mclk_groups[] = {
+	"gpio26", "gpio27", "gpio28", "gpio128",
+};
+static const char * const dac_calib3_groups[] = {
+	"gpio28",
+};
+static const char * const cci_i2c_groups[] = {
+	"gpio29", "gpio30", "gpio31", "gpio32",
+};
+static const char * const pwr_modem_enabled_a_groups[] = {
+	"gpio29",
+};
+static const char * const dac_calib4_groups[] = {
+	"gpio29",
+};
+static const char * const dac_calib19_groups[] = {
+	"gpio30",
+};
+static const char * const flash_strobe_groups[] = {
+	"gpio33", "gpio34",
+};
+static const char * const cci_timer0_groups[] = {
+	"gpio33",
+};
+static const char * const cci_timer1_groups[] = {
+	"gpio34",
+};
+static const char * const cam_irq_groups[] = {
+	"gpio35",
+};
+static const char * const cci_timer2_groups[] = {
+	"gpio35",
+};
+static const char * const blsp1_spi_groups[] = {
+	"gpio35", "gpio36",
+};
+static const char * const pwr_nav_enabled_a_groups[] = {
+	"gpio35",
+};
+static const char * const ois_sync_groups[] = {
+	"gpio36",
+};
+static const char * const cci_timer3_groups[] = {
+	"gpio36",
+};
+static const char * const cci_timer4_groups[] = {
+	"gpio41",
+};
+static const char * const blsp3_spi_groups[] = {
+	"gpio41", "gpio50",
+};
+static const char * const qdss_cti_trig_out_a0_groups[] = {
+	"gpio41",
+};
+static const char * const dac_calib7_groups[] = {
+	"gpio41",
+};
+static const char * const accel_int_groups[] = {
+	"gpio42",
+};
+static const char * const gcc_gp1_clk_a_groups[] = {
+	"gpio42",
+};
+static const char * const dac_calib8_groups[] = {
+	"gpio42",
+};
+static const char * const alsp_int_groups[] = {
+	"gpio43",
+};
+static const char * const gcc_gp2_clk_a_groups[] = {
+	"gpio43",
+};
+static const char * const dac_calib9_groups[] = {
+	"gpio43",
+};
+static const char * const mag_int_groups[] = {
+	"gpio44",
+};
+static const char * const gcc_gp3_clk_a_groups[] = {
+	"gpio44",
+};
+static const char * const pwr_crypto_enabled_a_groups[] = {
+	"gpio36",
+};
+static const char * const cci_async_groups[] = {
+	"gpio38",
+};
+static const char * const cam1_standby_groups[] = {
+	"gpio39",
+};
+static const char * const dac_calib5_groups[] = {
+	"gpio39",
+};
+static const char * const cam1_rst_groups[] = {
+	"gpio40",
+};
+static const char * const dac_calib6_groups[] = {
+	"gpio40",
+};
+static const char * const dac_calib10_groups[] = {
+	"gpio44",
+};
+static const char * const gyro_int_groups[] = {
+	"gpio45",
+};
+static const char * const dac_calib11_groups[] = {
+	"gpio45",
+};
+static const char * const pressure_int_groups[] = {
+	"gpio46",
+};
+static const char * const dac_calib12_groups[] = {
+	"gpio46",
+};
+static const char * const blsp6_spi_groups[] = {
+	"gpio47", "gpio48",
+};
+static const char * const dac_calib13_groups[] = {
+	"gpio47",
+};
+static const char * const fp_int_groups[] = {
+	"gpio48",
+};
+static const char * const qdss_cti_trig_in_b1_groups[] = {
+	"gpio48",
+};
+static const char * const dac_calib14_groups[] = {
+	"gpio48",
+};
+static const char * const uim_batt_groups[] = {
+	"gpio49",
+};
+static const char * const cam0_ldo_groups[] = {
+	"gpio50",
+};
+static const char * const sd_write_groups[] = {
+	"gpio50",
+};
+static const char * const uim1_data_groups[] = {
+	"gpio51",
+};
+static const char * const uim1_clk_groups[] = {
+	"gpio52",
+};
+static const char * const uim1_reset_groups[] = {
+	"gpio53",
+};
+static const char * const uim1_present_groups[] = {
+	"gpio54",
+};
+static const char * const uim2_data_groups[] = {
+	"gpio55",
+};
+static const char * const uim2_clk_groups[] = {
+	"gpio56",
+};
+static const char * const uim2_reset_groups[] = {
+	"gpio57",
+};
+static const char * const uim2_present_groups[] = {
+	"gpio58",
+};
+static const char * const ts_xvdd_groups[] = {
+	"gpio60",
+};
+static const char * const mipi_dsi0_groups[] = {
+	"gpio61",
+};
+static const char * const nfc_dwl_groups[] = {
+	"gpio62",
+};
+static const char * const us_euro_groups[] = {
+	"gpio63",
+};
+static const char * const atest_char3_groups[] = {
+	"gpio63",
+};
+static const char * const dbg_out_groups[] = {
+	"gpio63",
+};
+static const char * const bimc_dte0_groups[] = {
+	"gpio63", "gpio65",
+};
+static const char * const ts_resout_groups[] = {
+	"gpio64",
+};
+static const char * const ts_sample_groups[] = {
+	"gpio65",
+};
+static const char * const sec_mi2s_mclk_b_groups[] = {
+	"gpio66",
+};
+static const char * const pri_mi2s_groups[] = {
+	"gpio66", "gpio88", "gpio91", "gpio93", "gpio94", "gpio95",
+};
+static const char * const codec_reset_groups[] = {
+	"gpio67",
+};
+static const char * const cdc_pdm0_groups[] = {
+	"gpio67", "gpio68", "gpio69", "gpio70", "gpio71", "gpio72", "gpio73",
+	"gpio74",
+};
+static const char * const atest_char1_groups[] = {
+	"gpio67",
+};
+static const char * const ebi_cdc_groups[] = {
+	"gpio67", "gpio69", "gpio118", "gpio119", "gpio120", "gpio123",
+};
+static const char * const dac_calib17_groups[] = {
+	"gpio67",
+};
+static const char * const us_emitter_groups[] = {
+	"gpio68",
+};
+static const char * const atest_char0_groups[] = {
+	"gpio68",
+};
+static const char * const pri_mi2s_mclk_b_groups[] = {
+	"gpio69",
+};
+static const char * const lpass_slimbus_groups[] = {
+	"gpio70",
+};
+static const char * const lpass_slimbus0_groups[] = {
+	"gpio71",
+};
+static const char * const lpass_slimbus1_groups[] = {
+	"gpio72",
+};
+static const char * const codec_int1_groups[] = {
+	"gpio73",
+};
+static const char * const codec_int2_groups[] = {
+	"gpio74",
+};
+static const char * const wcss_bt_groups[] = {
+	"gpio75", "gpio83", "gpio84",
+};
+static const char * const atest_char2_groups[] = {
+	"gpio75",
+};
+static const char * const ebi_ch0_groups[] = {
+	"gpio75",
+};
+static const char * const wcss_wlan2_groups[] = {
+	"gpio76",
+};
+static const char * const wcss_wlan1_groups[] = {
+	"gpio77",
+};
+static const char * const wcss_wlan0_groups[] = {
+	"gpio78",
+};
+static const char * const wcss_wlan_groups[] = {
+	"gpio79", "gpio80",
+};
+static const char * const wcss_fm_groups[] = {
+	"gpio81", "gpio82",
+};
+static const char * const ext_lpass_groups[] = {
+	"gpio81",
+};
+static const char * const mss_lte_groups[] = {
+	"gpio82", "gpio83",
+};
+static const char * const key_volp_groups[] = {
+	"gpio85",
+};
+static const char * const pbs0_groups[] = {
+	"gpio85",
+};
+static const char * const cri_trng0_groups[] = {
+	"gpio85",
+};
+static const char * const key_snapshot_groups[] = {
+	"gpio86",
+};
+static const char * const pbs1_groups[] = {
+	"gpio86",
+};
+static const char * const cri_trng1_groups[] = {
+	"gpio86",
+};
+static const char * const key_focus_groups[] = {
+	"gpio87",
+};
+static const char * const pbs2_groups[] = {
+	"gpio87",
+};
+static const char * const cri_trng_groups[] = {
+	"gpio87",
+};
+static const char * const gcc_tlmm_groups[] = {
+	"gpio87",
+};
+static const char * const key_home_groups[] = {
+	"gpio88",
+};
+static const char * const pwr_down_groups[] = {
+	"gpio89",
+};
+static const char * const dmic0_clk_groups[] = {
+	"gpio89",
+};
+static const char * const blsp7_spi_groups[] = {
+	"gpio89", "gpio90",
+};
+static const char * const hdmi_int_groups[] = {
+	"gpio90",
+};
+static const char * const dmic0_data_groups[] = {
+	"gpio90",
+};
+static const char * const qdss_cti_trig_in_a1_groups[] = {
+	"gpio91",
+};
+static const char * const pri_mi2s_ws_groups[] = {
+	"gpio92",
+};
+static const char * const wsa_io_groups[] = {
+	"gpio94", "gpio95",
+};
+static const char * const wsa_en_groups[] = {
+	"gpio96",
+};
+static const char * const blsp_spi8_groups[] = {
+	"gpio96", "gpio97", "gpio98", "gpio99",
+};
+static const char * const wsa_irq_groups[] = {
+	"gpio97",
+};
+static const char * const blsp_i2c8_groups[] = {
+	"gpio98", "gpio99",
+};
+static const char * const gcc_plltest_groups[] = {
+	"gpio98", "gpio99",
+};
+static const char * const nav_pps_in_a_groups[] = {
+	"gpio111",
+};
+static const char * const pa_indicator_groups[] = {
+	"gpio112",
+};
+static const char * const nav_pps_in_b_groups[] = {
+	"gpio113",
+};
+static const char * const nav_pps_groups[] = {
+	"gpio113",
+};
+static const char * const modem_tsync_groups[] = {
+	"gpio113",
+};
+static const char * const nav_tsync_groups[] = {
+	"gpio113",
+};
+static const char * const ssbi_wtr1_groups[] = {
+	"gpio114", "gpio123",
+};
+static const char * const gsm1_tx_groups[] = {
+	"gpio115",
+};
+static const char * const dac_calib18_groups[] = {
+	"gpio115",
+};
+static const char * const gsm0_tx_groups[] = {
+	"gpio117",
+};
+static const char * const atest_char_groups[] = {
+	"gpio120",
+};
+static const char * const atest_tsens_groups[] = {
+	"gpio120",
+};
+static const char * const bimc_dte1_groups[] = {
+	"gpio121", "gpio122",
+};
+static const char * const dac_calib20_groups[] = {
+	"gpio128",
+};
+static const char * const cam2_rst_groups[] = {
+	"gpio129",
+};
+static const char * const ddr_bist_groups[] = {
+	"gpio129", "gpio130", "gpio131", "gpio132",
+};
+static const char * const dac_calib21_groups[] = {
+	"gpio129",
+};
+static const char * const cam2_standby_groups[] = {
+	"gpio130",
+};
+static const char * const dac_calib22_groups[] = {
+	"gpio130",
+};
+static const char * const cam3_rst_groups[] = {
+	"gpio131",
+};
+static const char * const dac_calib23_groups[] = {
+	"gpio131",
+};
+static const char * const cam3_standby_groups[] = {
+	"gpio132",
+};
+static const char * const dac_calib24_groups[] = {
+	"gpio132",
+};
+static const char * const sdcard_det_groups[] = {
+	"gpio133",
+};
+static const char * const dac_calib25_groups[] = {
+	"gpio133",
+};
+static const char * const cam1_ldo_groups[] = {
+	"gpio134",
+};
+static const char * const sec_mi2s_groups[] = {
+	"gpio135", "gpio136", "gpio137", "gpio138",
+};
+static const char * const blsp_spi7_groups[] = {
+	"gpio135", "gpio136", "gpio137", "gpio138",
+};
+static const char * const blsp_i2c7_groups[] = {
+	"gpio135", "gpio136",
+};
+static const char * const ss_switch_groups[] = {
+	"gpio139",
+};
+static const char * const tsens_max_groups[] = {
+	"gpio139",
+};
+
+static const struct msm_function msm8953_functions[] = {
+	FUNCTION(gpio),
+	FUNCTION(blsp_spi1),
+	FUNCTION(smb_int),
+	FUNCTION(adsp_ext),
+	FUNCTION(prng_rosc),
+	FUNCTION(blsp_i2c1),
+	FUNCTION(qdss_cti_trig_out_b0),
+	FUNCTION(qdss_cti_trig_out_a1),
+	FUNCTION(blsp_spi2),
+	FUNCTION(blsp_uart2),
+	FUNCTION(ldo_update),
+	FUNCTION(dac_calib0),
+	FUNCTION(ldo_en),
+	FUNCTION(blsp_i2c2),
+	FUNCTION(gcc_gp1_clk_b),
+	FUNCTION(atest_gpsadc_dtest0_native),
+	FUNCTION(blsp_spi3),
+	FUNCTION(qdss_tracedata_b),
+	FUNCTION(pwr_modem_enabled_b),
+	FUNCTION(blsp_i2c3),
+	FUNCTION(gcc_gp2_clk_b),
+	FUNCTION(gcc_gp3_clk_b),
+	FUNCTION(hall_int),
+	FUNCTION(blsp_spi4),
+	FUNCTION(blsp_uart4),
+	FUNCTION(pwr_nav_enabled_b),
+	FUNCTION(dac_calib1),
+	FUNCTION(cap_int),
+	FUNCTION(pwr_crypto_enabled_b),
+	FUNCTION(dac_calib2),
+	FUNCTION(blsp_i2c4),
+	FUNCTION(nfc_disable),
+	FUNCTION(blsp_spi5),
+	FUNCTION(blsp_uart5),
+	FUNCTION(qdss_traceclk_a),
+	FUNCTION(atest_bbrx1),
+	FUNCTION(nfc_irq),
+	FUNCTION(m_voc),
+	FUNCTION(qdss_cti_trig_in_a0),
+	FUNCTION(atest_bbrx0),
+	FUNCTION(blsp_i2c5),
+	FUNCTION(qdss_tracectl_a),
+	FUNCTION(atest_gpsadc_dtest1_native),
+	FUNCTION(qdss_tracedata_a),
+	FUNCTION(blsp_spi6),
+	FUNCTION(blsp_uart6),
+	FUNCTION(qdss_tracectl_b),
+	FUNCTION(dac_calib15),
+	FUNCTION(qdss_cti_trig_in_b0),
+	FUNCTION(dac_calib16),
+	FUNCTION(blsp_i2c6),
+	FUNCTION(qdss_traceclk_b),
+	FUNCTION(atest_wlan0),
+	FUNCTION(atest_wlan1),
+	FUNCTION(mdp_vsync),
+	FUNCTION(pri_mi2s_mclk_a),
+	FUNCTION(sec_mi2s_mclk_a),
+	FUNCTION(qdss_cti_trig_out_b1),
+	FUNCTION(cam_mclk),
+	FUNCTION(dac_calib3),
+	FUNCTION(cci_i2c),
+	FUNCTION(pwr_modem_enabled_a),
+	FUNCTION(dac_calib4),
+	FUNCTION(dac_calib19),
+	FUNCTION(flash_strobe),
+	FUNCTION(cci_timer0),
+	FUNCTION(cci_timer1),
+	FUNCTION(cam_irq),
+	FUNCTION(cci_timer2),
+	FUNCTION(blsp1_spi),
+	FUNCTION(pwr_nav_enabled_a),
+	FUNCTION(ois_sync),
+	FUNCTION(cci_timer3),
+	FUNCTION(cci_timer4),
+	FUNCTION(blsp3_spi),
+	FUNCTION(qdss_cti_trig_out_a0),
+	FUNCTION(dac_calib7),
+	FUNCTION(accel_int),
+	FUNCTION(gcc_gp1_clk_a),
+	FUNCTION(dac_calib8),
+	FUNCTION(alsp_int),
+	FUNCTION(gcc_gp2_clk_a),
+	FUNCTION(dac_calib9),
+	FUNCTION(mag_int),
+	FUNCTION(gcc_gp3_clk_a),
+	FUNCTION(pwr_crypto_enabled_a),
+	FUNCTION(cci_async),
+	FUNCTION(cam1_standby),
+	FUNCTION(dac_calib5),
+	FUNCTION(cam1_rst),
+	FUNCTION(dac_calib6),
+	FUNCTION(dac_calib10),
+	FUNCTION(gyro_int),
+	FUNCTION(dac_calib11),
+	FUNCTION(pressure_int),
+	FUNCTION(dac_calib12),
+	FUNCTION(blsp6_spi),
+	FUNCTION(dac_calib13),
+	FUNCTION(fp_int),
+	FUNCTION(qdss_cti_trig_in_b1),
+	FUNCTION(dac_calib14),
+	FUNCTION(uim_batt),
+	FUNCTION(cam0_ldo),
+	FUNCTION(sd_write),
+	FUNCTION(uim1_data),
+	FUNCTION(uim1_clk),
+	FUNCTION(uim1_reset),
+	FUNCTION(uim1_present),
+	FUNCTION(uim2_data),
+	FUNCTION(uim2_clk),
+	FUNCTION(uim2_reset),
+	FUNCTION(uim2_present),
+	FUNCTION(ts_xvdd),
+	FUNCTION(mipi_dsi0),
+	FUNCTION(nfc_dwl),
+	FUNCTION(us_euro),
+	FUNCTION(atest_char3),
+	FUNCTION(dbg_out),
+	FUNCTION(bimc_dte0),
+	FUNCTION(ts_resout),
+	FUNCTION(ts_sample),
+	FUNCTION(sec_mi2s_mclk_b),
+	FUNCTION(pri_mi2s),
+	FUNCTION(codec_reset),
+	FUNCTION(cdc_pdm0),
+	FUNCTION(atest_char1),
+	FUNCTION(ebi_cdc),
+	FUNCTION(dac_calib17),
+	FUNCTION(us_emitter),
+	FUNCTION(atest_char0),
+	FUNCTION(pri_mi2s_mclk_b),
+	FUNCTION(lpass_slimbus),
+	FUNCTION(lpass_slimbus0),
+	FUNCTION(lpass_slimbus1),
+	FUNCTION(codec_int1),
+	FUNCTION(codec_int2),
+	FUNCTION(wcss_bt),
+	FUNCTION(atest_char2),
+	FUNCTION(ebi_ch0),
+	FUNCTION(wcss_wlan2),
+	FUNCTION(wcss_wlan1),
+	FUNCTION(wcss_wlan0),
+	FUNCTION(wcss_wlan),
+	FUNCTION(wcss_fm),
+	FUNCTION(ext_lpass),
+	FUNCTION(mss_lte),
+	FUNCTION(key_volp),
+	FUNCTION(pbs0),
+	FUNCTION(cri_trng0),
+	FUNCTION(key_snapshot),
+	FUNCTION(pbs1),
+	FUNCTION(cri_trng1),
+	FUNCTION(key_focus),
+	FUNCTION(pbs2),
+	FUNCTION(cri_trng),
+	FUNCTION(gcc_tlmm),
+	FUNCTION(key_home),
+	FUNCTION(pwr_down),
+	FUNCTION(dmic0_clk),
+	FUNCTION(blsp7_spi),
+	FUNCTION(hdmi_int),
+	FUNCTION(dmic0_data),
+	FUNCTION(qdss_cti_trig_in_a1),
+	FUNCTION(pri_mi2s_ws),
+	FUNCTION(wsa_io),
+	FUNCTION(wsa_en),
+	FUNCTION(blsp_spi8),
+	FUNCTION(wsa_irq),
+	FUNCTION(blsp_i2c8),
+	FUNCTION(gcc_plltest),
+	FUNCTION(nav_pps_in_a),
+	FUNCTION(pa_indicator),
+	FUNCTION(nav_pps_in_b),
+	FUNCTION(nav_pps),
+	FUNCTION(modem_tsync),
+	FUNCTION(nav_tsync),
+	FUNCTION(ssbi_wtr1),
+	FUNCTION(gsm1_tx),
+	FUNCTION(dac_calib18),
+	FUNCTION(gsm0_tx),
+	FUNCTION(atest_char),
+	FUNCTION(atest_tsens),
+	FUNCTION(bimc_dte1),
+	FUNCTION(dac_calib20),
+	FUNCTION(cam2_rst),
+	FUNCTION(ddr_bist),
+	FUNCTION(dac_calib21),
+	FUNCTION(cam2_standby),
+	FUNCTION(dac_calib22),
+	FUNCTION(cam3_rst),
+	FUNCTION(dac_calib23),
+	FUNCTION(cam3_standby),
+	FUNCTION(dac_calib24),
+	FUNCTION(sdcard_det),
+	FUNCTION(dac_calib25),
+	FUNCTION(cam1_ldo),
+	FUNCTION(sec_mi2s),
+	FUNCTION(blsp_spi7),
+	FUNCTION(blsp_i2c7),
+	FUNCTION(ss_switch),
+	FUNCTION(tsens_max),
+};
+
+static const struct msm_pingroup msm8953_groups[] = {
+	PINGROUP(0, blsp_spi1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(1, blsp_spi1, adsp_ext, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(2, blsp_spi1, blsp_i2c1, prng_rosc, NA, NA, NA,
+		 qdss_cti_trig_out_b0, NA, NA),
+	PINGROUP(3, blsp_spi1, blsp_i2c1, NA, NA, NA, qdss_cti_trig_out_a1, NA,
+		 NA, NA),
+	PINGROUP(4, blsp_spi2, blsp_uart2, ldo_update, NA, dac_calib0, NA, NA,
+		 NA, NA),
+	PINGROUP(5, blsp_spi2, blsp_uart2, ldo_en, NA, NA, NA, NA, NA, NA),
+	PINGROUP(6, blsp_spi2, blsp_uart2, blsp_i2c2, gcc_gp1_clk_b, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(7, blsp_spi2, blsp_uart2, blsp_i2c2, NA,
+		 atest_gpsadc_dtest0_native, NA, NA, NA, NA),
+	PINGROUP(8, blsp_spi3, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA),
+	PINGROUP(9, blsp_spi3, pwr_modem_enabled_b, NA, NA, qdss_tracedata_b,
+		 NA, NA, NA, NA),
+	PINGROUP(10, blsp_spi3, blsp_i2c3, gcc_gp2_clk_b, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(11, blsp_spi3, blsp_i2c3, gcc_gp3_clk_b, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(12, blsp_spi4, blsp_uart4, pwr_nav_enabled_b, NA, NA,
+		 qdss_tracedata_b, NA, dac_calib1, NA),
+	PINGROUP(13, blsp_spi4, blsp_uart4, pwr_crypto_enabled_b, NA, NA, NA,
+		 qdss_tracedata_b, NA, dac_calib2),
+	PINGROUP(14, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA, NA, NA, NA),
+	PINGROUP(15, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA, NA, NA, NA),
+	PINGROUP(16, blsp_spi5, blsp_uart5, NA, NA, qdss_traceclk_a, NA,
+		 atest_bbrx1, NA, NA),
+	PINGROUP(17, blsp_spi5, blsp_uart5, m_voc, qdss_cti_trig_in_a0, NA,
+		 atest_bbrx0, NA, NA, NA),
+	PINGROUP(18, blsp_spi5, blsp_uart5, blsp_i2c5, qdss_tracectl_a, NA,
+		 atest_gpsadc_dtest1_native, NA, NA, NA),
+	PINGROUP(19, blsp_spi5, blsp_uart5, blsp_i2c5, qdss_tracedata_a, NA,
+		 NA, NA, NA, NA),
+	PINGROUP(20, blsp_spi6, blsp_uart6, NA, NA, NA, qdss_tracectl_b, NA,
+		 dac_calib15, NA),
+	PINGROUP(21, blsp_spi6, blsp_uart6, m_voc, NA, NA, NA,
+		 qdss_cti_trig_in_b0, NA, dac_calib16),
+	PINGROUP(22, blsp_spi6, blsp_uart6, blsp_i2c6, qdss_traceclk_b, NA,
+		 atest_wlan0, NA, NA, NA),
+	PINGROUP(23, blsp_spi6, blsp_uart6, blsp_i2c6, qdss_tracedata_b, NA,
+		 atest_wlan1, NA, NA, NA),
+	PINGROUP(24, mdp_vsync, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(25, mdp_vsync, pri_mi2s_mclk_a, sec_mi2s_mclk_a,
+		 qdss_cti_trig_out_b1, NA, NA, NA, NA, NA),
+	PINGROUP(26, cam_mclk, NA, NA, NA, qdss_tracedata_a, NA, NA, NA, NA),
+	PINGROUP(27, cam_mclk, NA, NA, NA, qdss_tracedata_a, NA, NA, NA, NA),
+	PINGROUP(28, cam_mclk, NA, NA, NA, qdss_tracedata_a, NA, dac_calib3,
+		 NA, NA),
+	PINGROUP(29, cci_i2c, pwr_modem_enabled_a, NA, NA, NA,
+		 qdss_tracedata_a, NA, dac_calib4, NA),
+	PINGROUP(30, cci_i2c, NA, NA, NA, qdss_tracedata_a, NA, dac_calib19,
+		 NA, NA),
+	PINGROUP(31, cci_i2c, NA, NA, NA, qdss_tracedata_a, NA, NA, NA, NA),
+	PINGROUP(32, cci_i2c, NA, NA, NA, qdss_tracedata_a, NA, NA, NA, NA),
+	PINGROUP(33, cci_timer0, NA, NA, NA, NA, qdss_tracedata_a, NA, NA, NA),
+	PINGROUP(34, cci_timer1, NA, NA, NA, NA, qdss_tracedata_a, NA, NA, NA),
+	PINGROUP(35, cci_timer2, blsp1_spi, pwr_nav_enabled_a, NA, NA, NA,
+		 qdss_tracedata_a, NA, NA),
+	PINGROUP(36, cci_timer3, blsp1_spi, NA, pwr_crypto_enabled_a, NA, NA,
+		 NA, qdss_tracedata_a, NA),
+	PINGROUP(37, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(38, cci_async, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, NA),
+	PINGROUP(39, NA, NA, NA, qdss_tracedata_a, NA, dac_calib5, NA, NA, NA),
+	PINGROUP(40, NA, NA, qdss_tracedata_a, NA, dac_calib6, NA, NA, NA, NA),
+	PINGROUP(41, cci_timer4, blsp3_spi, gcc_gp1_clk_b, NA, NA,
+		 qdss_cti_trig_out_a0, NA, dac_calib7, NA),
+	PINGROUP(42, gcc_gp1_clk_a, qdss_tracedata_b, NA, dac_calib8, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(43, gcc_gp2_clk_a, qdss_tracedata_b, NA, dac_calib9, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(44, gcc_gp3_clk_a, qdss_tracedata_b, NA, dac_calib10, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(45, NA, qdss_tracedata_b, NA, dac_calib11, NA, NA, NA, NA, NA),
+	PINGROUP(46, qdss_tracedata_b, NA, dac_calib12, NA, NA, NA, NA, NA, NA),
+	PINGROUP(47, blsp6_spi, qdss_tracedata_b, NA, dac_calib13, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(48, blsp6_spi, NA, qdss_cti_trig_in_b1, NA, dac_calib14, NA,
+		 NA, NA, NA),
+	PINGROUP(49, uim_batt, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(50, blsp3_spi, sd_write, NA, NA, NA, qdss_tracedata_a, NA, NA,
+		 NA),
+	PINGROUP(51, uim1_data, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(52, uim1_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(53, uim1_reset, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(54, uim1_present, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(55, uim2_data, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(56, uim2_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(57, uim2_reset, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(58, uim2_present, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(59, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(60, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(61, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(62, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(63, atest_char3, dbg_out, bimc_dte0, NA, NA, NA, NA, NA, NA),
+	PINGROUP(64, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(65, bimc_dte0, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(66, sec_mi2s_mclk_b, pri_mi2s, NA, qdss_tracedata_b, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(67, cdc_pdm0, atest_char1, ebi_cdc, NA, dac_calib17, NA, NA,
+		 NA, NA),
+	PINGROUP(68, cdc_pdm0, atest_char0, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(69, cdc_pdm0, pri_mi2s_mclk_b, ebi_cdc, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(70, lpass_slimbus, cdc_pdm0, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(71, lpass_slimbus0, cdc_pdm0, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(72, lpass_slimbus1, cdc_pdm0, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(73, cdc_pdm0, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(74, cdc_pdm0, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(75, wcss_bt, atest_char2, NA, ebi_ch0, NA, NA, NA, NA, NA),
+	PINGROUP(76, wcss_wlan2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(77, wcss_wlan1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(78, wcss_wlan0, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(79, wcss_wlan, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(80, wcss_wlan, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(81, wcss_fm, ext_lpass, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(82, wcss_fm, mss_lte, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(83, wcss_bt, mss_lte, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(84, wcss_bt, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(85, pbs0, cri_trng0, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(86, pbs1, cri_trng1, qdss_tracedata_b, NA, NA, NA, NA, NA, NA),
+	PINGROUP(87, pbs2, cri_trng, qdss_tracedata_b, gcc_tlmm, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(88, pri_mi2s, NA, NA, NA, qdss_tracedata_b, NA, NA, NA, NA),
+	PINGROUP(89, dmic0_clk, blsp7_spi, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(90, dmic0_data, blsp7_spi, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(91, pri_mi2s, NA, NA, NA, qdss_cti_trig_in_a1, NA, NA, NA, NA),
+	PINGROUP(92, pri_mi2s_ws, NA, NA, NA, qdss_tracedata_b, NA, NA, NA, NA),
+	PINGROUP(93, pri_mi2s, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(94, wsa_io, pri_mi2s, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(95, wsa_io, pri_mi2s, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(96, blsp_spi8, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(97, blsp_spi8, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(98, blsp_i2c8, blsp_spi8, gcc_plltest, NA, NA, NA, NA, NA, NA),
+	PINGROUP(99, blsp_i2c8, blsp_spi8, gcc_plltest, NA, NA, NA, NA, NA, NA),
+	PINGROUP(100, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(101, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(102, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(103, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(104, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(105, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(106, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(107, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(108, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(109, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(110, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(111, NA, NA, nav_pps_in_a, NA, NA, NA, NA, NA, NA),
+	PINGROUP(112, NA, pa_indicator, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(113, NA, nav_pps_in_b, nav_pps, modem_tsync, nav_tsync, NA,
+		 NA, NA, NA),
+	PINGROUP(114, NA, ssbi_wtr1, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(115, NA, gsm1_tx, NA, dac_calib18, NA, NA, NA, NA, NA),
+	PINGROUP(116, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(117, gsm0_tx, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(118, NA, ebi_cdc, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(119, NA, ebi_cdc, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(120, NA, atest_char, ebi_cdc, NA, atest_tsens, NA, NA, NA, NA),
+	PINGROUP(121, NA, NA, NA, bimc_dte1, NA, NA, NA, NA, NA),
+	PINGROUP(122, NA, NA, NA, bimc_dte1, NA, NA, NA, NA, NA),
+	PINGROUP(123, NA, ssbi_wtr1, ebi_cdc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(124, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(125, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(126, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(127, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(128, cam_mclk, NA, dac_calib20, NA, NA, NA, NA, NA, NA),
+	PINGROUP(129, ddr_bist, NA, dac_calib21, NA, NA, NA, NA, NA, NA),
+	PINGROUP(130, ddr_bist, NA, dac_calib22, NA, NA, NA, NA, NA, NA),
+	PINGROUP(131, ddr_bist, NA, dac_calib23, NA, NA, NA, NA, NA, NA),
+	PINGROUP(132, ddr_bist, NA, dac_calib24, NA, NA, NA, NA, NA, NA),
+	PINGROUP(133, NA, dac_calib25, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(134, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(135, sec_mi2s, blsp_spi7, blsp_i2c7, NA, NA, NA, NA, NA, NA),
+	PINGROUP(136, sec_mi2s, blsp_spi7, blsp_i2c7, NA, NA, NA, NA, NA, NA),
+	PINGROUP(137, sec_mi2s, blsp_spi7, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(138, sec_mi2s, blsp_spi7, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(139, tsens_max, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(140, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(141, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	SDC_QDSD_PINGROUP(sdc1_clk, 0x10a000, 13, 6),
+	SDC_QDSD_PINGROUP(sdc1_cmd, 0x10a000, 11, 3),
+	SDC_QDSD_PINGROUP(sdc1_data, 0x10a000, 9, 0),
+	SDC_QDSD_PINGROUP(sdc1_rclk, 0x10a000, 15, 0),
+	SDC_QDSD_PINGROUP(sdc2_clk, 0x109000, 14, 6),
+	SDC_QDSD_PINGROUP(sdc2_cmd, 0x109000, 11, 3),
+	SDC_QDSD_PINGROUP(sdc2_data, 0x109000, 9, 0),
+	SDC_QDSD_PINGROUP(qdsd_clk, 0x19c000, 3, 0),
+	SDC_QDSD_PINGROUP(qdsd_cmd, 0x19c000, 8, 5),
+	SDC_QDSD_PINGROUP(qdsd_data0, 0x19c000, 13, 10),
+	SDC_QDSD_PINGROUP(qdsd_data1, 0x19c000, 18, 15),
+	SDC_QDSD_PINGROUP(qdsd_data2, 0x19c000, 23, 20),
+	SDC_QDSD_PINGROUP(qdsd_data3, 0x19c000, 28, 25),
+};
+
+static const struct msm_pinctrl_soc_data msm8953_pinctrl = {
+	.pins = msm8953_pins,
+	.npins = ARRAY_SIZE(msm8953_pins),
+	.functions = msm8953_functions,
+	.nfunctions = ARRAY_SIZE(msm8953_functions),
+	.groups = msm8953_groups,
+	.ngroups = ARRAY_SIZE(msm8953_groups),
+	.ngpios = 142,
+};
+
+static int msm8953_pinctrl_probe(struct platform_device *pdev)
+{
+	return msm_pinctrl_probe(pdev, &msm8953_pinctrl);
+}
+
+static const struct of_device_id msm8953_pinctrl_of_match[] = {
+	{ .compatible = "qcom,msm8953-pinctrl", },
+	{ },
+};
+
+static struct platform_driver msm8953_pinctrl_driver = {
+	.driver = {
+		.name = "msm8953-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = msm8953_pinctrl_of_match,
+	},
+	.probe = msm8953_pinctrl_probe,
+	.remove = msm_pinctrl_remove,
+};
+
+static int __init msm8953_pinctrl_init(void)
+{
+	return platform_driver_register(&msm8953_pinctrl_driver);
+}
+arch_initcall(msm8953_pinctrl_init);
+
+static void __exit msm8953_pinctrl_exit(void)
+{
+	platform_driver_unregister(&msm8953_pinctrl_driver);
+}
+module_exit(msm8953_pinctrl_exit);
+
+MODULE_DESCRIPTION("QTI msm8953 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, msm8953_pinctrl_of_match);
diff --git a/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c b/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c
index 105294a..2975192 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c
@@ -19,6 +19,8 @@
 #include <linux/sched.h>
 #include <linux/atomic.h>
 #include <linux/ecm_ipa.h>
+#include "../ipa_common_i.h"
+#include "../ipa_v3/ipa_pm.h"
 
 #define DRIVER_NAME "ecm_ipa"
 #define ECM_IPA_IPV4_HDR_NAME "ecm_eth_ipv4"
@@ -120,6 +122,7 @@
  * @usb_to_ipa_client: producer client
  * @ipa_rm_resource_name_prod: IPA resource manager producer resource
  * @ipa_rm_resource_name_cons: IPA resource manager consumer resource
+ * @pm_hdl: handle for IPA PM
  */
 struct ecm_ipa_dev {
 	struct net_device *net;
@@ -137,6 +140,7 @@
 	enum ipa_client_type usb_to_ipa_client;
 	enum ipa_rm_resource_name ipa_rm_resource_name_prod;
 	enum ipa_rm_resource_name ipa_rm_resource_name_cons;
+	u32 pm_hdl;
 };
 
 static int ecm_ipa_open(struct net_device *net);
@@ -158,6 +162,8 @@
 static struct net_device_stats *ecm_ipa_get_stats(struct net_device *net);
 static int ecm_ipa_create_rm_resource(struct ecm_ipa_dev *ecm_ipa_ctx);
 static void ecm_ipa_destroy_rm_resource(struct ecm_ipa_dev *ecm_ipa_ctx);
+static int ecm_ipa_register_pm_client(struct ecm_ipa_dev *ecm_ipa_ctx);
+static void ecm_ipa_deregister_pm_client(struct ecm_ipa_dev *ecm_ipa_ctx);
 static int resource_request(struct ecm_ipa_dev *ecm_ipa_ctx);
 static void resource_release(struct ecm_ipa_dev *ecm_ipa_ctx);
 static netdev_tx_t ecm_ipa_start_xmit
@@ -403,27 +409,34 @@
 	ECM_IPA_DEBUG("usb_to_ipa_client = %d\n",
 		      ecm_ipa_ctx->usb_to_ipa_client);
 
-	ecm_ipa_ctx->ipa_rm_resource_name_cons =
-		ipa_get_rm_resource_from_ep(ipa_to_usb_hdl);
-	if (ecm_ipa_ctx->ipa_rm_resource_name_cons < 0) {
-		ECM_IPA_ERROR("Error getting CONS RM resource from handle %d\n",
+	if (ipa_pm_is_used()) {
+		retval = ecm_ipa_register_pm_client(ecm_ipa_ctx);
+	} else {
+		ecm_ipa_ctx->ipa_rm_resource_name_cons =
+			ipa_get_rm_resource_from_ep(ipa_to_usb_hdl);
+		if (ecm_ipa_ctx->ipa_rm_resource_name_cons < 0) {
+			ECM_IPA_ERROR(
+			"Error getting CONS RM resource from handle %d\n",
+				      ecm_ipa_ctx->ipa_rm_resource_name_cons);
+			return -EINVAL;
+		}
+		ECM_IPA_DEBUG("ipa_rm_resource_name_cons = %d\n",
 			      ecm_ipa_ctx->ipa_rm_resource_name_cons);
-		return -EINVAL;
-	}
-	ECM_IPA_DEBUG("ipa_rm_resource_name_cons = %d\n",
-		      ecm_ipa_ctx->ipa_rm_resource_name_cons);
 
-	ecm_ipa_ctx->ipa_rm_resource_name_prod =
-		ipa_get_rm_resource_from_ep(usb_to_ipa_hdl);
-	if (ecm_ipa_ctx->ipa_rm_resource_name_prod < 0) {
-		ECM_IPA_ERROR("Error getting PROD RM resource from handle %d\n",
+		ecm_ipa_ctx->ipa_rm_resource_name_prod =
+			ipa_get_rm_resource_from_ep(usb_to_ipa_hdl);
+		if (ecm_ipa_ctx->ipa_rm_resource_name_prod < 0) {
+			ECM_IPA_ERROR(
+			"Error getting PROD RM resource from handle %d\n",
+				      ecm_ipa_ctx->ipa_rm_resource_name_prod);
+			return -EINVAL;
+		}
+		ECM_IPA_DEBUG("ipa_rm_resource_name_prod = %d\n",
 			      ecm_ipa_ctx->ipa_rm_resource_name_prod);
-		return -EINVAL;
-	}
-	ECM_IPA_DEBUG("ipa_rm_resource_name_prod = %d\n",
-		      ecm_ipa_ctx->ipa_rm_resource_name_prod);
 
-	retval = ecm_ipa_create_rm_resource(ecm_ipa_ctx);
+		retval = ecm_ipa_create_rm_resource(ecm_ipa_ctx);
+	}
+
 	if (retval) {
 		ECM_IPA_ERROR("fail on RM create\n");
 		goto fail_create_rm;
@@ -488,7 +501,10 @@
 fail:
 	ecm_ipa_deregister_properties();
 fail_create_rm:
-	ecm_ipa_destroy_rm_resource(ecm_ipa_ctx);
+	if (ipa_pm_is_used())
+		ecm_ipa_deregister_pm_client(ecm_ipa_ctx);
+	else
+		ecm_ipa_destroy_rm_resource(ecm_ipa_ctx);
 	return retval;
 }
 EXPORT_SYMBOL(ecm_ipa_connect);
@@ -746,7 +762,10 @@
 	netif_stop_queue(ecm_ipa_ctx->net);
 	ECM_IPA_DEBUG("queue stopped\n");
 
-	ecm_ipa_destroy_rm_resource(ecm_ipa_ctx);
+	if (ipa_pm_is_used())
+		ecm_ipa_deregister_pm_client(ecm_ipa_ctx);
+	else
+		ecm_ipa_destroy_rm_resource(ecm_ipa_ctx);
 
 	outstanding_dropped_pkts =
 		atomic_read(&ecm_ipa_ctx->outstanding_pkts);
@@ -1117,15 +1136,65 @@
 	ECM_IPA_LOG_EXIT();
 }
 
+static void ecm_ipa_pm_cb(void *p, enum ipa_pm_cb_event event)
+{
+	struct ecm_ipa_dev *ecm_ipa_ctx = p;
+
+	ECM_IPA_LOG_ENTRY();
+	if (event != IPA_PM_CLIENT_ACTIVATED) {
+		ECM_IPA_ERROR("unexpected event %d\n", event);
+		WARN_ON(1);
+		return;
+	}
+
+	if (netif_queue_stopped(ecm_ipa_ctx->net)) {
+		ECM_IPA_DEBUG("Resource Granted - starting queue\n");
+		netif_start_queue(ecm_ipa_ctx->net);
+	}
+	ECM_IPA_LOG_EXIT();
+}
+
+static int ecm_ipa_register_pm_client(struct ecm_ipa_dev *ecm_ipa_ctx)
+{
+	int result;
+	struct ipa_pm_register_params pm_reg;
+
+	memset(&pm_reg, 0, sizeof(pm_reg));
+	pm_reg.name = ecm_ipa_ctx->net->name;
+	pm_reg.user_data = ecm_ipa_ctx;
+	pm_reg.callback = ecm_ipa_pm_cb;
+	pm_reg.group = IPA_PM_GROUP_APPS;
+	result = ipa_pm_register(&pm_reg, &ecm_ipa_ctx->pm_hdl);
+	if (result) {
+		ECM_IPA_ERROR("failed to create IPA PM client %d\n", result);
+		return result;
+	}
+	return 0;
+}
+
+static void ecm_ipa_deregister_pm_client(struct ecm_ipa_dev *ecm_ipa_ctx)
+{
+	ipa_pm_deactivate_sync(ecm_ipa_ctx->pm_hdl);
+	ipa_pm_deregister(ecm_ipa_ctx->pm_hdl);
+	ecm_ipa_ctx->pm_hdl = ~0;
+}
+
 static int resource_request(struct ecm_ipa_dev *ecm_ipa_ctx)
 {
+	if (ipa_pm_is_used())
+		return ipa_pm_activate(ecm_ipa_ctx->pm_hdl);
+
 	return ipa_rm_inactivity_timer_request_resource(
 		IPA_RM_RESOURCE_STD_ECM_PROD);
 }
 
 static void resource_release(struct ecm_ipa_dev *ecm_ipa_ctx)
 {
-	ipa_rm_inactivity_timer_release_resource(IPA_RM_RESOURCE_STD_ECM_PROD);
+	if (ipa_pm_is_used())
+		ipa_pm_deferred_deactivate(ecm_ipa_ctx->pm_hdl);
+	else
+		ipa_rm_inactivity_timer_release_resource(
+			IPA_RM_RESOURCE_STD_ECM_PROD);
 }
 
 /**
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
index 9b3b53d..4d3113f 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
@@ -19,6 +19,7 @@
 #include <linux/ipa_qmi_service_v01.h>
 #include <linux/ipa_mhi.h>
 #include "../ipa_common_i.h"
+#include "../ipa_v3/ipa_pm.h"
 
 #define IPA_MHI_DRV_NAME "ipa_mhi_client"
 #define IPA_MHI_DBG(fmt, args...) \
@@ -136,6 +137,8 @@
 	u32 use_ipadma;
 	bool assert_bit40;
 	bool test_mode;
+	u32 pm_hdl;
+	u32 modem_pm_hdl;
 };
 
 static struct ipa_mhi_client_ctx *ipa_mhi_client_ctx;
@@ -834,25 +837,38 @@
 	IPA_MHI_DBG("event_context_array_addr 0x%llx\n",
 		ipa_mhi_client_ctx->event_context_array_addr);
 
-	/* Add MHI <-> Q6 dependencies to IPA RM */
-	res = ipa_rm_add_dependency(IPA_RM_RESOURCE_MHI_PROD,
-		IPA_RM_RESOURCE_Q6_CONS);
-	if (res && res != -EINPROGRESS) {
-		IPA_MHI_ERR("failed to add dependency %d\n", res);
-		goto fail_add_mhi_q6_dep;
-	}
+	if (ipa_pm_is_used()) {
+		res = ipa_pm_activate_sync(ipa_mhi_client_ctx->pm_hdl);
+		if (res) {
+			IPA_MHI_ERR("failed activate client %d\n", res);
+			goto fail_pm_activate;
+		}
+		res = ipa_pm_activate_sync(ipa_mhi_client_ctx->modem_pm_hdl);
+		if (res) {
+			IPA_MHI_ERR("failed activate modem client %d\n", res);
+			goto fail_pm_activate_modem;
+		}
+	} else {
+		/* Add MHI <-> Q6 dependencies to IPA RM */
+		res = ipa_rm_add_dependency(IPA_RM_RESOURCE_MHI_PROD,
+			IPA_RM_RESOURCE_Q6_CONS);
+		if (res && res != -EINPROGRESS) {
+			IPA_MHI_ERR("failed to add dependency %d\n", res);
+			goto fail_add_mhi_q6_dep;
+		}
 
-	res = ipa_rm_add_dependency(IPA_RM_RESOURCE_Q6_PROD,
-		IPA_RM_RESOURCE_MHI_CONS);
-	if (res && res != -EINPROGRESS) {
-		IPA_MHI_ERR("failed to add dependency %d\n", res);
-		goto fail_add_q6_mhi_dep;
-	}
+		res = ipa_rm_add_dependency(IPA_RM_RESOURCE_Q6_PROD,
+			IPA_RM_RESOURCE_MHI_CONS);
+		if (res && res != -EINPROGRESS) {
+			IPA_MHI_ERR("failed to add dependency %d\n", res);
+			goto fail_add_q6_mhi_dep;
+		}
 
-	res = ipa_mhi_request_prod();
-	if (res) {
-		IPA_MHI_ERR("failed request prod %d\n", res);
-		goto fail_request_prod;
+		res = ipa_mhi_request_prod();
+		if (res) {
+			IPA_MHI_ERR("failed request prod %d\n", res);
+			goto fail_request_prod;
+		}
 	}
 
 	/* gsi params */
@@ -880,14 +896,23 @@
 	return 0;
 
 fail_init_engine:
-	ipa_mhi_release_prod();
+	if (!ipa_pm_is_used())
+		ipa_mhi_release_prod();
 fail_request_prod:
-	ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
-		IPA_RM_RESOURCE_MHI_CONS);
+	if (!ipa_pm_is_used())
+		ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
+			IPA_RM_RESOURCE_MHI_CONS);
 fail_add_q6_mhi_dep:
-	ipa_rm_delete_dependency(IPA_RM_RESOURCE_MHI_PROD,
-		IPA_RM_RESOURCE_Q6_CONS);
+	if (!ipa_pm_is_used())
+		ipa_rm_delete_dependency(IPA_RM_RESOURCE_MHI_PROD,
+			IPA_RM_RESOURCE_Q6_CONS);
 fail_add_mhi_q6_dep:
+	if (ipa_pm_is_used())
+		ipa_pm_deactivate_sync(ipa_mhi_client_ctx->modem_pm_hdl);
+fail_pm_activate_modem:
+	if (ipa_pm_is_used())
+		ipa_pm_deactivate_sync(ipa_mhi_client_ctx->pm_hdl);
+fail_pm_activate:
 	ipa_mhi_set_state(IPA_MHI_STATE_INITIALIZED);
 	return res;
 }
@@ -2095,20 +2120,32 @@
 	 */
 	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
 
-	IPA_MHI_DBG("release prod\n");
-	res = ipa_mhi_release_prod();
-	if (res) {
-		IPA_MHI_ERR("ipa_mhi_release_prod failed %d\n", res);
-		goto fail_release_prod;
-	}
+	if (ipa_pm_is_used()) {
+		res = ipa_pm_deactivate_sync(ipa_mhi_client_ctx->pm_hdl);
+		if (res) {
+			IPA_MHI_ERR("fail to deactivate client %d\n", res);
+			goto fail_deactivate_pm;
+		}
+		res = ipa_pm_deactivate_sync(ipa_mhi_client_ctx->modem_pm_hdl);
+		if (res) {
+			IPA_MHI_ERR("fail to deactivate client %d\n", res);
+			goto fail_deactivate_modem_pm;
+		}
+	} else {
+		IPA_MHI_DBG("release prod\n");
+		res = ipa_mhi_release_prod();
+		if (res) {
+			IPA_MHI_ERR("ipa_mhi_release_prod failed %d\n", res);
+			goto fail_release_prod;
+		}
 
-	IPA_MHI_DBG("wait for cons release\n");
-	res = ipa_mhi_wait_for_cons_release();
-	if (res) {
-		IPA_MHI_ERR("ipa_mhi_wait_for_cons_release failed %d\n", res);
-		goto fail_release_cons;
+		IPA_MHI_DBG("wait for cons release\n");
+		res = ipa_mhi_wait_for_cons_release();
+		if (res) {
+			IPA_MHI_ERR("ipa_mhi_wait_for_cons_release failed\n");
+			goto fail_release_cons;
+		}
 	}
-
 	usleep_range(IPA_MHI_SUSPEND_SLEEP_MIN, IPA_MHI_SUSPEND_SLEEP_MAX);
 
 	res = ipa_mhi_suspend_dl(force);
@@ -2132,8 +2169,15 @@
 
 fail_suspend_dl_channel:
 fail_release_cons:
+	if (!ipa_pm_is_used())
 	ipa_mhi_request_prod();
 fail_release_prod:
+	if (ipa_pm_is_used())
+		ipa_pm_deactivate_sync(ipa_mhi_client_ctx->modem_pm_hdl);
+fail_deactivate_modem_pm:
+	if (ipa_pm_is_used())
+		ipa_pm_deactivate_sync(ipa_mhi_client_ctx->pm_hdl);
+fail_deactivate_pm:
 	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 fail_suspend_ul_channel:
 	ipa_mhi_resume_channels(true, ipa_mhi_client_ctx->ul_channels);
@@ -2193,10 +2237,23 @@
 		ipa_mhi_client_ctx->rm_cons_state = IPA_MHI_RM_STATE_GRANTED;
 	}
 
-	res = ipa_mhi_request_prod();
-	if (res) {
-		IPA_MHI_ERR("ipa_mhi_request_prod failed %d\n", res);
-		goto fail_request_prod;
+	if (ipa_pm_is_used()) {
+		res = ipa_pm_activate_sync(ipa_mhi_client_ctx->pm_hdl);
+		if (res) {
+			IPA_MHI_ERR("fail to activate client %d\n", res);
+			goto fail_pm_activate;
+		}
+		ipa_pm_activate_sync(ipa_mhi_client_ctx->modem_pm_hdl);
+		if (res) {
+			IPA_MHI_ERR("fail to activate client %d\n", res);
+			goto fail_pm_activate_modem;
+		}
+	} else {
+		res = ipa_mhi_request_prod();
+		if (res) {
+			IPA_MHI_ERR("ipa_mhi_request_prod failed %d\n", res);
+			goto fail_request_prod;
+		}
 	}
 
 	/* resume all UL channels */
@@ -2234,8 +2291,15 @@
 fail_resume_dl_channels2:
 	ipa_mhi_suspend_channels(ipa_mhi_client_ctx->ul_channels);
 fail_resume_ul_channels:
-	ipa_mhi_release_prod();
+	if (!ipa_pm_is_used())
+		ipa_mhi_release_prod();
 fail_request_prod:
+	if (ipa_pm_is_used())
+		ipa_pm_deactivate_sync(ipa_mhi_client_ctx->modem_pm_hdl);
+fail_pm_activate_modem:
+	if (ipa_pm_is_used())
+		ipa_pm_deactivate_sync(ipa_mhi_client_ctx->pm_hdl);
+fail_pm_activate:
 	ipa_mhi_suspend_channels(ipa_mhi_client_ctx->dl_channels);
 fail_resume_dl_channels:
 	ipa_mhi_set_state(IPA_MHI_STATE_SUSPENDED);
@@ -2319,6 +2383,85 @@
 	debugfs_remove_recursive(dent);
 }
 
+static void ipa_mhi_delete_rm_resources(void)
+{
+	int res;
+
+	if (ipa_mhi_client_ctx->state != IPA_MHI_STATE_INITIALIZED  &&
+		ipa_mhi_client_ctx->state != IPA_MHI_STATE_READY) {
+
+		IPA_MHI_DBG("release prod\n");
+		res = ipa_mhi_release_prod();
+		if (res) {
+			IPA_MHI_ERR("ipa_mhi_release_prod failed %d\n",
+				res);
+			goto fail;
+		}
+		IPA_MHI_DBG("wait for cons release\n");
+		res = ipa_mhi_wait_for_cons_release();
+		if (res) {
+			IPA_MHI_ERR("ipa_mhi_wait_for_cons_release%d\n",
+				res);
+			goto fail;
+		}
+
+		usleep_range(IPA_MHI_SUSPEND_SLEEP_MIN,
+			IPA_MHI_SUSPEND_SLEEP_MAX);
+
+		IPA_MHI_DBG("deleate dependency Q6_PROD->MHI_CONS\n");
+		res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
+			IPA_RM_RESOURCE_MHI_CONS);
+		if (res) {
+			IPA_MHI_ERR(
+				"Error deleting dependency %d->%d, res=%d\n",
+				IPA_RM_RESOURCE_Q6_PROD,
+				IPA_RM_RESOURCE_MHI_CONS,
+				res);
+			goto fail;
+		}
+		IPA_MHI_DBG("deleate dependency MHI_PROD->Q6_CONS\n");
+		res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_MHI_PROD,
+			IPA_RM_RESOURCE_Q6_CONS);
+		if (res) {
+			IPA_MHI_ERR(
+				"Error deleting dependency %d->%d, res=%d\n",
+				IPA_RM_RESOURCE_MHI_PROD,
+				IPA_RM_RESOURCE_Q6_CONS,
+				res);
+			goto fail;
+		}
+	}
+
+	res = ipa_rm_delete_resource(IPA_RM_RESOURCE_MHI_PROD);
+	if (res) {
+		IPA_MHI_ERR("Error deleting resource %d, res=%d\n",
+			IPA_RM_RESOURCE_MHI_PROD, res);
+		goto fail;
+	}
+
+	res = ipa_rm_delete_resource(IPA_RM_RESOURCE_MHI_CONS);
+	if (res) {
+		IPA_MHI_ERR("Error deleting resource %d, res=%d\n",
+			IPA_RM_RESOURCE_MHI_CONS, res);
+		goto fail;
+	}
+
+	return;
+fail:
+	ipa_assert();
+}
+
+static void ipa_mhi_deregister_pm(void)
+{
+	ipa_pm_deactivate_sync(ipa_mhi_client_ctx->pm_hdl);
+	ipa_pm_deregister(ipa_mhi_client_ctx->pm_hdl);
+	ipa_mhi_client_ctx->pm_hdl = ~0;
+
+	ipa_pm_deactivate_sync(ipa_mhi_client_ctx->modem_pm_hdl);
+	ipa_pm_deregister(ipa_mhi_client_ctx->modem_pm_hdl);
+	ipa_mhi_client_ctx->modem_pm_hdl = ~0;
+}
+
 /**
  * ipa_mhi_destroy() - Destroy MHI IPA
  *
@@ -2351,62 +2494,10 @@
 		ipa_uc_mhi_cleanup();
 	}
 
-
-	if (ipa_mhi_client_ctx->state != IPA_MHI_STATE_INITIALIZED  &&
-			ipa_mhi_client_ctx->state != IPA_MHI_STATE_READY) {
-		IPA_MHI_DBG("release prod\n");
-		res = ipa_mhi_release_prod();
-		if (res) {
-			IPA_MHI_ERR("ipa_mhi_release_prod failed %d\n", res);
-			goto fail;
-		}
-		IPA_MHI_DBG("wait for cons release\n");
-		res = ipa_mhi_wait_for_cons_release();
-		if (res) {
-			IPA_MHI_ERR("ipa_mhi_wait_for_cons_release failed %d\n",
-				res);
-			goto fail;
-		}
-		usleep_range(IPA_MHI_SUSPEND_SLEEP_MIN,
-				IPA_MHI_SUSPEND_SLEEP_MAX);
-
-		IPA_MHI_DBG("deleate dependency Q6_PROD->MHI_CONS\n");
-		res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
-			IPA_RM_RESOURCE_MHI_CONS);
-		if (res) {
-			IPA_MHI_ERR(
-				"Error deleting dependency %d->%d, res=%d\n"
-				, IPA_RM_RESOURCE_Q6_PROD,
-				IPA_RM_RESOURCE_MHI_CONS,
-				res);
-			goto fail;
-		}
-		IPA_MHI_DBG("deleate dependency MHI_PROD->Q6_CONS\n");
-		res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_MHI_PROD,
-			IPA_RM_RESOURCE_Q6_CONS);
-		if (res) {
-			IPA_MHI_ERR(
-				"Error deleting dependency %d->%d, res=%d\n",
-			IPA_RM_RESOURCE_MHI_PROD,
-			IPA_RM_RESOURCE_Q6_CONS,
-			res);
-			goto fail;
-		}
-	}
-
-	res = ipa_rm_delete_resource(IPA_RM_RESOURCE_MHI_PROD);
-	if (res) {
-		IPA_MHI_ERR("Error deleting resource %d, res=%d\n",
-			IPA_RM_RESOURCE_MHI_PROD, res);
-		goto fail;
-	}
-
-	res = ipa_rm_delete_resource(IPA_RM_RESOURCE_MHI_CONS);
-	if (res) {
-		IPA_MHI_ERR("Error deleting resource %d, res=%d\n",
-			IPA_RM_RESOURCE_MHI_CONS, res);
-		goto fail;
-	}
+	if (ipa_pm_is_used())
+		ipa_mhi_deregister_pm();
+	else
+		ipa_mhi_delete_rm_resources();
 
 	ipa_mhi_debugfs_destroy();
 	destroy_workqueue(ipa_mhi_client_ctx->wq);
@@ -2420,6 +2511,132 @@
 	ipa_assert();
 }
 
+static void ipa_mhi_pm_cb(void *p, enum ipa_pm_cb_event event)
+{
+	unsigned long flags;
+
+	IPA_MHI_FUNC_ENTRY();
+
+	if (event != IPA_PM_REQUEST_WAKEUP) {
+		IPA_MHI_ERR("Unexpected event %d\n", event);
+		WARN_ON(1);
+		return;
+	}
+
+	IPA_MHI_DBG("%s\n", MHI_STATE_STR(ipa_mhi_client_ctx->state));
+	spin_lock_irqsave(&ipa_mhi_client_ctx->state_lock, flags);
+	if (ipa_mhi_client_ctx->state == IPA_MHI_STATE_SUSPENDED) {
+		ipa_mhi_notify_wakeup();
+	} else if (ipa_mhi_client_ctx->state ==
+		IPA_MHI_STATE_SUSPEND_IN_PROGRESS) {
+		/* wakeup event will be trigger after suspend finishes */
+		ipa_mhi_client_ctx->trigger_wakeup = true;
+	}
+	spin_unlock_irqrestore(&ipa_mhi_client_ctx->state_lock, flags);
+	IPA_MHI_DBG("EXIT");
+}
+
+static int ipa_mhi_register_pm(void)
+{
+	int res;
+	struct ipa_pm_register_params params;
+
+	memset(&params, 0, sizeof(params));
+	params.name = "MHI";
+	params.callback = ipa_mhi_pm_cb;
+	params.group = IPA_PM_GROUP_DEFAULT;
+	res = ipa_pm_register(&params, &ipa_mhi_client_ctx->pm_hdl);
+	if (res) {
+		IPA_MHI_ERR("fail to register with PM %d\n", res);
+		return res;
+	}
+
+	res = ipa_pm_associate_ipa_cons_to_client(ipa_mhi_client_ctx->pm_hdl,
+		IPA_CLIENT_MHI_CONS);
+	if (res) {
+		IPA_MHI_ERR("fail to associate cons with PM %d\n", res);
+		goto fail_pm_cons;
+	}
+
+	res = ipa_pm_set_perf_profile(ipa_mhi_client_ctx->pm_hdl, 1000);
+	if (res) {
+		IPA_MHI_ERR("fail to set perf profile to PM %d\n", res);
+		goto fail_pm_cons;
+	}
+
+	/* create a modem client for clock scaling */
+	memset(&params, 0, sizeof(params));
+	params.name = "MODEM (MHI)";
+	params.group = IPA_PM_GROUP_MODEM;
+	params.skip_clk_vote = true;
+	res = ipa_pm_register(&params, &ipa_mhi_client_ctx->modem_pm_hdl);
+	if (res) {
+		IPA_MHI_ERR("fail to register with PM %d\n", res);
+		goto fail_pm_cons;
+	}
+
+	return 0;
+
+fail_pm_cons:
+	ipa_pm_deregister(ipa_mhi_client_ctx->pm_hdl);
+	ipa_mhi_client_ctx->pm_hdl = ~0;
+	return res;
+}
+
+static int ipa_mhi_create_rm_resources(void)
+{
+	int res;
+	struct ipa_rm_create_params mhi_prod_params;
+	struct ipa_rm_create_params mhi_cons_params;
+	struct ipa_rm_perf_profile profile;
+
+	/* Create PROD in IPA RM */
+	memset(&mhi_prod_params, 0, sizeof(mhi_prod_params));
+	mhi_prod_params.name = IPA_RM_RESOURCE_MHI_PROD;
+	mhi_prod_params.floor_voltage = IPA_VOLTAGE_SVS;
+	mhi_prod_params.reg_params.notify_cb = ipa_mhi_rm_prod_notify;
+	res = ipa_rm_create_resource(&mhi_prod_params);
+	if (res) {
+		IPA_MHI_ERR("fail to create IPA_RM_RESOURCE_MHI_PROD\n");
+		goto fail_create_rm_prod;
+	}
+
+	memset(&profile, 0, sizeof(profile));
+	profile.max_supported_bandwidth_mbps = 1000;
+	res = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_MHI_PROD, &profile);
+	if (res) {
+		IPA_MHI_ERR("fail to set profile to MHI_PROD\n");
+		goto fail_perf_rm_prod;
+	}
+
+	/* Create CONS in IPA RM */
+	memset(&mhi_cons_params, 0, sizeof(mhi_cons_params));
+	mhi_cons_params.name = IPA_RM_RESOURCE_MHI_CONS;
+	mhi_cons_params.floor_voltage = IPA_VOLTAGE_SVS;
+	mhi_cons_params.request_resource = ipa_mhi_rm_cons_request;
+	mhi_cons_params.release_resource = ipa_mhi_rm_cons_release;
+	res = ipa_rm_create_resource(&mhi_cons_params);
+	if (res) {
+		IPA_MHI_ERR("fail to create IPA_RM_RESOURCE_MHI_CONS\n");
+		goto fail_create_rm_cons;
+	}
+
+	memset(&profile, 0, sizeof(profile));
+	profile.max_supported_bandwidth_mbps = 1000;
+	res = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_MHI_CONS, &profile);
+	if (res) {
+		IPA_MHI_ERR("fail to set profile to MHI_CONS\n");
+		goto fail_perf_rm_cons;
+	}
+fail_perf_rm_cons:
+	ipa_rm_delete_resource(IPA_RM_RESOURCE_MHI_CONS);
+fail_create_rm_cons:
+fail_perf_rm_prod:
+	ipa_rm_delete_resource(IPA_RM_RESOURCE_MHI_PROD);
+fail_create_rm_prod:
+	return res;
+}
+
 /**
  * ipa_mhi_init() - Initialize IPA MHI driver
  * @params: initialization params
@@ -2437,9 +2654,6 @@
 int ipa_mhi_init(struct ipa_mhi_init_params *params)
 {
 	int res;
-	struct ipa_rm_create_params mhi_prod_params;
-	struct ipa_rm_create_params mhi_cons_params;
-	struct ipa_rm_perf_profile profile;
 
 	IPA_MHI_FUNC_ENTRY();
 
@@ -2500,43 +2714,14 @@
 		goto fail_create_wq;
 	}
 
-	/* Create PROD in IPA RM */
-	memset(&mhi_prod_params, 0, sizeof(mhi_prod_params));
-	mhi_prod_params.name = IPA_RM_RESOURCE_MHI_PROD;
-	mhi_prod_params.floor_voltage = IPA_VOLTAGE_SVS;
-	mhi_prod_params.reg_params.notify_cb = ipa_mhi_rm_prod_notify;
-	res = ipa_rm_create_resource(&mhi_prod_params);
+	if (ipa_pm_is_used())
+		res = ipa_mhi_register_pm();
+	else
+		res = ipa_mhi_create_rm_resources();
 	if (res) {
-		IPA_MHI_ERR("fail to create IPA_RM_RESOURCE_MHI_PROD\n");
-		goto fail_create_rm_prod;
-	}
-
-	memset(&profile, 0, sizeof(profile));
-	profile.max_supported_bandwidth_mbps = 1000;
-	res = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_MHI_PROD, &profile);
-	if (res) {
-		IPA_MHI_ERR("fail to set profile to MHI_PROD\n");
-		goto fail_perf_rm_prod;
-	}
-
-	/* Create CONS in IPA RM */
-	memset(&mhi_cons_params, 0, sizeof(mhi_cons_params));
-	mhi_cons_params.name = IPA_RM_RESOURCE_MHI_CONS;
-	mhi_cons_params.floor_voltage = IPA_VOLTAGE_SVS;
-	mhi_cons_params.request_resource = ipa_mhi_rm_cons_request;
-	mhi_cons_params.release_resource = ipa_mhi_rm_cons_release;
-	res = ipa_rm_create_resource(&mhi_cons_params);
-	if (res) {
-		IPA_MHI_ERR("fail to create IPA_RM_RESOURCE_MHI_CONS\n");
-		goto fail_create_rm_cons;
-	}
-
-	memset(&profile, 0, sizeof(profile));
-	profile.max_supported_bandwidth_mbps = 1000;
-	res = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_MHI_CONS, &profile);
-	if (res) {
-		IPA_MHI_ERR("fail to set profile to MHI_CONS\n");
-		goto fail_perf_rm_cons;
+		IPA_MHI_ERR("failed to create RM resources\n");
+		res = -EFAULT;
+		goto fail_rm;
 	}
 
 	/* Initialize uC interface */
@@ -2551,12 +2736,7 @@
 	IPA_MHI_FUNC_EXIT();
 	return 0;
 
-fail_perf_rm_cons:
-	ipa_rm_delete_resource(IPA_RM_RESOURCE_MHI_CONS);
-fail_create_rm_cons:
-fail_perf_rm_prod:
-	ipa_rm_delete_resource(IPA_RM_RESOURCE_MHI_PROD);
-fail_create_rm_prod:
+fail_rm:
 	destroy_workqueue(ipa_mhi_client_ctx->wq);
 fail_create_wq:
 	kfree(ipa_mhi_client_ctx);
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c b/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c
index a15a9d8..e19d297 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c
@@ -13,6 +13,7 @@
 #include <linux/ipa_uc_offload.h>
 #include <linux/msm_ipa.h>
 #include "../ipa_common_i.h"
+#include "../ipa_v3/ipa_pm.h"
 
 #define IPA_NTN_DMA_POOL_ALIGNMENT 8
 #define OFFLOAD_DRV_NAME "ipa_uc_offload"
@@ -69,6 +70,7 @@
 	char netdev_name[IPA_RESOURCE_NAME_MAX];
 	ipa_notify_cb notify;
 	struct completion ntn_completion;
+	u32 pm_hdl;
 };
 
 static struct ipa_uc_offload_ctx *ipa_uc_offload_ctx[IPA_UC_MAX_PROT_SIZE];
@@ -113,22 +115,53 @@
 	return 0;
 }
 
-static int ipa_uc_offload_ntn_reg_intf(
-	struct ipa_uc_offload_intf_params *inp,
-	struct ipa_uc_offload_out_params *outp,
+static void ipa_uc_offload_ntn_pm_cb(void *p, enum ipa_pm_cb_event event)
+{
+	/* suspend/resume is not supported */
+	IPA_UC_OFFLOAD_DBG("event = %d\n", event);
+}
+
+static int ipa_uc_offload_ntn_register_pm_client(
 	struct ipa_uc_offload_ctx *ntn_ctx)
 {
-	struct ipa_ioc_add_hdr *hdr = NULL;
-	struct ipa_tx_intf tx;
-	struct ipa_rx_intf rx;
-	struct ipa_ioc_tx_intf_prop tx_prop[2];
-	struct ipa_ioc_rx_intf_prop rx_prop[2];
-	struct ipa_rm_create_params param;
-	u32 len;
-	int ret = 0;
+	int res;
+	struct ipa_pm_register_params params;
 
-	IPA_UC_OFFLOAD_DBG("register interface for netdev %s\n",
-					 inp->netdev_name);
+	memset(&params, 0, sizeof(params));
+	params.name = "ETH";
+	params.callback = ipa_uc_offload_ntn_pm_cb;
+	params.user_data = ntn_ctx;
+	params.group = IPA_PM_GROUP_DEFAULT;
+	res = ipa_pm_register(&params, &ntn_ctx->pm_hdl);
+	if (res) {
+		IPA_UC_OFFLOAD_ERR("fail to register with PM %d\n", res);
+		return res;
+	}
+
+	res = ipa_pm_associate_ipa_cons_to_client(ntn_ctx->pm_hdl,
+		IPA_CLIENT_ETHERNET_CONS);
+	if (res) {
+		IPA_UC_OFFLOAD_ERR("fail to associate cons with PM %d\n", res);
+		ipa_pm_deregister(ntn_ctx->pm_hdl);
+		ntn_ctx->pm_hdl = ~0;
+		return res;
+	}
+
+	return 0;
+}
+
+static void ipa_uc_offload_ntn_deregister_pm_client(
+	struct ipa_uc_offload_ctx *ntn_ctx)
+{
+	ipa_pm_deactivate_sync(ntn_ctx->pm_hdl);
+	ipa_pm_deregister(ntn_ctx->pm_hdl);
+}
+static int ipa_uc_offload_ntn_create_rm_resources(
+	struct ipa_uc_offload_ctx *ntn_ctx)
+{
+	int ret;
+	struct ipa_rm_create_params param;
+
 	memset(&param, 0, sizeof(param));
 	param.name = IPA_RM_RESOURCE_ETHERNET_PROD;
 	param.reg_params.user_data = ntn_ctx;
@@ -147,9 +180,37 @@
 	ret = ipa_rm_create_resource(&param);
 	if (ret) {
 		IPA_UC_OFFLOAD_ERR("fail to create ETHERNET_CONS resource\n");
-		goto fail_create_rm_cons;
+		ipa_rm_delete_resource(IPA_RM_RESOURCE_ETHERNET_PROD);
+		return -EFAULT;
 	}
 
+	return 0;
+}
+
+static int ipa_uc_offload_ntn_reg_intf(
+	struct ipa_uc_offload_intf_params *inp,
+	struct ipa_uc_offload_out_params *outp,
+	struct ipa_uc_offload_ctx *ntn_ctx)
+{
+	struct ipa_ioc_add_hdr *hdr = NULL;
+	struct ipa_tx_intf tx;
+	struct ipa_rx_intf rx;
+	struct ipa_ioc_tx_intf_prop tx_prop[2];
+	struct ipa_ioc_rx_intf_prop rx_prop[2];
+	int ret = 0;
+	u32 len;
+
+
+	IPA_UC_OFFLOAD_DBG("register interface for netdev %s\n",
+					 inp->netdev_name);
+	if (ipa_pm_is_used())
+		ret = ipa_uc_offload_ntn_register_pm_client(ntn_ctx);
+	else
+		ret = ipa_uc_offload_ntn_create_rm_resources(ntn_ctx);
+	if (ret) {
+		IPA_UC_OFFLOAD_ERR("fail to create rm resource\n");
+		return -EFAULT;
+	}
 	memcpy(ntn_ctx->netdev_name, inp->netdev_name, IPA_RESOURCE_NAME_MAX);
 	ntn_ctx->hdr_len = inp->hdr_info[0].hdr_len;
 	ntn_ctx->notify = inp->notify;
@@ -228,9 +289,12 @@
 fail:
 	kfree(hdr);
 fail_alloc:
-	ipa_rm_delete_resource(IPA_RM_RESOURCE_ETHERNET_CONS);
-fail_create_rm_cons:
-	ipa_rm_delete_resource(IPA_RM_RESOURCE_ETHERNET_PROD);
+	if (ipa_pm_is_used()) {
+		ipa_uc_offload_ntn_deregister_pm_client(ntn_ctx);
+	} else {
+		ipa_rm_delete_resource(IPA_RM_RESOURCE_ETHERNET_CONS);
+		ipa_rm_delete_resource(IPA_RM_RESOURCE_ETHERNET_PROD);
+	}
 	return ret;
 }
 
@@ -348,25 +412,34 @@
 		return -EINVAL;
 	}
 
-	result = ipa_rm_add_dependency(IPA_RM_RESOURCE_ETHERNET_PROD,
-		IPA_RM_RESOURCE_APPS_CONS);
-	if (result) {
-		IPA_UC_OFFLOAD_ERR("fail to add rm dependency: %d\n", result);
-		return result;
-	}
+	if (ipa_pm_is_used()) {
+		result = ipa_pm_activate_sync(ntn_ctx->pm_hdl);
+		if (result) {
+			IPA_UC_OFFLOAD_ERR("fail to activate: %d\n", result);
+			return result;
+		}
+	} else {
+		result = ipa_rm_add_dependency(IPA_RM_RESOURCE_ETHERNET_PROD,
+			IPA_RM_RESOURCE_APPS_CONS);
+		if (result) {
+			IPA_UC_OFFLOAD_ERR("fail to add rm dependency: %d\n",
+				result);
+			return result;
+		}
 
-	result = ipa_rm_request_resource(IPA_RM_RESOURCE_ETHERNET_PROD);
-	if (result == -EINPROGRESS) {
-		if (wait_for_completion_timeout(&ntn_ctx->ntn_completion,
-			10*HZ) == 0) {
-			IPA_UC_OFFLOAD_ERR("ETH_PROD resource req time out\n");
+		result = ipa_rm_request_resource(IPA_RM_RESOURCE_ETHERNET_PROD);
+		if (result == -EINPROGRESS) {
+			if (wait_for_completion_timeout(&ntn_ctx->ntn_completion
+				, 10*HZ) == 0) {
+				IPA_UC_OFFLOAD_ERR("ETH_PROD req timeout\n");
+				result = -EFAULT;
+				goto fail;
+			}
+		} else if (result != 0) {
+			IPA_UC_OFFLOAD_ERR("fail to request resource\n");
 			result = -EFAULT;
 			goto fail;
 		}
-	} else if (result != 0) {
-		IPA_UC_OFFLOAD_ERR("fail to request resource\n");
-		result = -EFAULT;
-		goto fail;
 	}
 
 	ntn_ctx->state = IPA_UC_OFFLOAD_STATE_UP;
@@ -383,8 +456,9 @@
 	return 0;
 
 fail:
-	ipa_rm_delete_dependency(IPA_RM_RESOURCE_ETHERNET_PROD,
-		IPA_RM_RESOURCE_APPS_CONS);
+	if (!ipa_pm_is_used())
+		ipa_rm_delete_dependency(IPA_RM_RESOURCE_ETHERNET_PROD,
+			IPA_RM_RESOURCE_APPS_CONS);
 	return result;
 }
 
@@ -455,6 +529,11 @@
 		return -EINVAL;
 	}
 
+	if (ipa_pm_is_used())
+		return ipa_pm_set_perf_profile(
+			ipa_uc_offload_ctx[IPA_UC_NTN]->pm_hdl,
+			profile->max_supported_bw_mbps);
+
 	if (ipa_rm_set_perf_profile(resource_name, &rm_profile)) {
 		IPA_UC_OFFLOAD_ERR("fail to setup rm perf profile\n");
 		return -EFAULT;
@@ -471,18 +550,27 @@
 
 	ntn_ctx->state = IPA_UC_OFFLOAD_STATE_INITIALIZED;
 
-	ret = ipa_rm_release_resource(IPA_RM_RESOURCE_ETHERNET_PROD);
-	if (ret) {
-		IPA_UC_OFFLOAD_ERR("fail to release ETHERNET_PROD res: %d\n",
-						  ret);
-		return -EFAULT;
-	}
+	if (ipa_pm_is_used()) {
+		ret = ipa_pm_deactivate_sync(ntn_ctx->pm_hdl);
+		if (ret) {
+			IPA_UC_OFFLOAD_ERR("fail to deactivate res: %d\n",
+			ret);
+			return -EFAULT;
+		}
+	} else {
+		ret = ipa_rm_release_resource(IPA_RM_RESOURCE_ETHERNET_PROD);
+		if (ret) {
+			IPA_UC_OFFLOAD_ERR("fail release ETHERNET_PROD: %d\n",
+							ret);
+			return -EFAULT;
+		}
 
-	ret = ipa_rm_delete_dependency(IPA_RM_RESOURCE_ETHERNET_PROD,
-		IPA_RM_RESOURCE_APPS_CONS);
-	if (ret) {
-		IPA_UC_OFFLOAD_ERR("fail to del dep ETH_PROD->APPS, %d\n", ret);
-		return -EFAULT;
+		ret = ipa_rm_delete_dependency(IPA_RM_RESOURCE_ETHERNET_PROD,
+			IPA_RM_RESOURCE_APPS_CONS);
+		if (ret) {
+			IPA_UC_OFFLOAD_ERR("fail del dep ETH->APPS, %d\n", ret);
+			return -EFAULT;
+		}
 	}
 
 	ipa_ep_idx_ul = ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_PROD);
@@ -539,14 +627,18 @@
 	int len, result = 0;
 	struct ipa_ioc_del_hdr *hdr;
 
-	if (ipa_rm_delete_resource(IPA_RM_RESOURCE_ETHERNET_PROD)) {
-		IPA_UC_OFFLOAD_ERR("fail to delete ETHERNET_PROD resource\n");
-		return -EFAULT;
-	}
+	if (ipa_pm_is_used()) {
+		ipa_uc_offload_ntn_deregister_pm_client(ntn_ctx);
+	} else {
+		if (ipa_rm_delete_resource(IPA_RM_RESOURCE_ETHERNET_PROD)) {
+			IPA_UC_OFFLOAD_ERR("fail to delete ETHERNET_PROD\n");
+			return -EFAULT;
+		}
 
-	if (ipa_rm_delete_resource(IPA_RM_RESOURCE_ETHERNET_CONS)) {
-		IPA_UC_OFFLOAD_ERR("fail to delete ETHERNET_CONS resource\n");
-		return -EFAULT;
+		if (ipa_rm_delete_resource(IPA_RM_RESOURCE_ETHERNET_CONS)) {
+			IPA_UC_OFFLOAD_ERR("fail to delete ETHERNET_CONS\n");
+			return -EFAULT;
+		}
 	}
 
 	len = sizeof(struct ipa_ioc_del_hdr) + 2 * sizeof(struct ipa_hdr_del);
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
index f5d8d61..745e429 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
@@ -119,6 +119,12 @@
 	bool cons_requested_released;
 };
 
+struct ipa3_usb_pm_context {
+	struct ipa_pm_register_params reg_params;
+	struct work_struct *remote_wakeup_work;
+	u32 hdl;
+};
+
 enum ipa3_usb_state {
 	IPA_USB_INVALID,
 	IPA_USB_INITIALIZED,
@@ -157,6 +163,7 @@
  */
 struct ipa3_usb_transport_type_ctx {
 	struct ipa3_usb_rm_context rm_ctx;
+	struct ipa3_usb_pm_context pm_ctx;
 	int (*ipa_usb_notify_cb)(enum ipa_usb_notify_event, void *user_data);
 	void *user_data;
 	enum ipa3_usb_state state;
@@ -362,7 +369,8 @@
 			ipa3_usb_state_to_string(new_state));
 	}
 
-	if (state_legal && (new_state == IPA_USB_CONNECTED)) {
+	if (!ipa_pm_is_used() &&
+		state_legal && (new_state == IPA_USB_CONNECTED)) {
 		rm_ctx = &ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx;
 		if ((rm_ctx->cons_state == IPA_USB_CONS_GRANTED) ||
 			rm_ctx->cons_requested_released) {
@@ -656,6 +664,30 @@
 	return ipa3_usb_cons_release_resource_cb_do(IPA_USB_TRANSPORT_DPL);
 }
 
+static void ipa3_usb_pm_cb(void *p, enum ipa_pm_cb_event event)
+{
+	struct ipa3_usb_transport_type_ctx *ttype_ctx =
+		(struct ipa3_usb_transport_type_ctx *)p;
+	unsigned long flags;
+
+	IPA_USB_DBG_LOW("entry\n");
+
+	if (event != IPA_PM_REQUEST_WAKEUP) {
+		IPA_USB_ERR("Unexpected event %d\n", event);
+		WARN_ON(1);
+		return;
+	}
+
+	spin_lock_irqsave(&ipa3_usb_ctx->state_lock, flags);
+	IPA_USB_DBG("state is %s\n",
+		ipa3_usb_state_to_string(ttype_ctx->state));
+	if (ttype_ctx->state == IPA_USB_SUSPENDED)
+		queue_work(ipa3_usb_ctx->wq,
+			ttype_ctx->pm_ctx.remote_wakeup_work);
+	spin_unlock_irqrestore(&ipa3_usb_ctx->state_lock, flags);
+	IPA_USB_DBG_LOW("exit\n");
+}
+
 static char *ipa3_usb_teth_prot_to_string(enum ipa_usb_teth_prot teth_prot)
 {
 	switch (teth_prot) {
@@ -703,6 +735,59 @@
 	return 0;
 }
 
+static int ipa3_usb_register_pm(enum ipa3_usb_transport_type ttype)
+{
+	struct ipa3_usb_transport_type_ctx *ttype_ctx =
+		&ipa3_usb_ctx->ttype_ctx[ttype];
+	int result;
+
+	memset(&ttype_ctx->pm_ctx.reg_params, 0,
+		sizeof(ttype_ctx->pm_ctx.reg_params));
+	ttype_ctx->pm_ctx.reg_params.name = (ttype == IPA_USB_TRANSPORT_DPL) ?
+				"USB DPL" : "USB";
+	ttype_ctx->pm_ctx.reg_params.callback = ipa3_usb_pm_cb;
+	ttype_ctx->pm_ctx.reg_params.user_data = ttype_ctx;
+	ttype_ctx->pm_ctx.reg_params.group = IPA_PM_GROUP_DEFAULT;
+
+	result = ipa_pm_register(&ttype_ctx->pm_ctx.reg_params,
+		&ttype_ctx->pm_ctx.hdl);
+	if (result) {
+		IPA_USB_ERR("fail to register with PM %d\n", result);
+		goto fail_pm_reg;
+	}
+
+	result = ipa_pm_associate_ipa_cons_to_client(ttype_ctx->pm_ctx.hdl,
+		(ttype == IPA_USB_TRANSPORT_DPL) ?
+		IPA_CLIENT_USB_DPL_CONS : IPA_CLIENT_USB_CONS);
+	if (result) {
+		IPA_USB_ERR("fail to associate cons with PM %d\n", result);
+		goto fail_pm_cons;
+	}
+
+	return 0;
+
+fail_pm_cons:
+	ipa_pm_deregister(ttype_ctx->pm_ctx.hdl);
+fail_pm_reg:
+	memset(&ttype_ctx->pm_ctx.reg_params, 0,
+		sizeof(ttype_ctx->pm_ctx.reg_params));
+	return result;
+}
+
+static int ipa3_usb_deregister_pm(enum ipa3_usb_transport_type ttype)
+{
+	struct ipa3_usb_pm_context *pm_ctx =
+		&ipa3_usb_ctx->ttype_ctx[ttype].pm_ctx;
+	int result;
+
+	result = ipa_pm_deregister(pm_ctx->hdl);
+	if (result)
+		return result;
+
+	memset(&pm_ctx->reg_params, 0, sizeof(pm_ctx->reg_params));
+	return 0;
+}
+
 static int ipa3_usb_create_rm_resources(enum ipa3_usb_transport_type ttype)
 {
 	struct ipa3_usb_rm_context *rm_ctx;
@@ -802,7 +887,10 @@
 	}
 
 	/* Create IPA RM USB resources */
-	result = ipa3_usb_create_rm_resources(ttype);
+	if (ipa_pm_is_used())
+		result = ipa3_usb_register_pm(ttype);
+	else
+		result = ipa3_usb_create_rm_resources(ttype);
 	if (result) {
 		IPA_USB_ERR("Failed creating IPA RM USB resources\n");
 		goto bad_params;
@@ -934,12 +1022,18 @@
 teth_prot_init_fail:
 	if ((IPA3_USB_IS_TTYPE_DPL(ttype))
 		|| (ipa3_usb_ctx->num_init_prot == 0)) {
-		ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.prod_valid = false;
-		ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_valid = false;
-		ipa_rm_delete_resource(
+		if (ipa_pm_is_used()) {
+			ipa3_usb_deregister_pm(ttype);
+		} else {
+			ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.prod_valid =
+				false;
+			ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_valid =
+				false;
+			ipa_rm_delete_resource(
 			ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.prod_params.name);
-		ipa_rm_delete_resource(
+			ipa_rm_delete_resource(
 			ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_params.name);
+		}
 	}
 bad_params:
 	mutex_unlock(&ipa3_usb_ctx->general_mutex);
@@ -1393,6 +1487,9 @@
 {
 	int res = 0;
 
+	if (ipa_pm_is_used())
+		return 0;
+
 	/*
 	 * Add DPL dependency to RM dependency graph, first add_dependency call
 	 * is sync in order to make sure the IPA clocks are up before we
@@ -1572,6 +1669,9 @@
 {
 	int res;
 
+	if (ipa_pm_is_used())
+		return 0;
+
 	/* Remove DPL RM dependency */
 	res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_DPL_DUMMY_PROD,
 				    IPA_RM_RESOURCE_Q6_CONS);
@@ -1699,32 +1799,51 @@
 		return result;
 	}
 
-	/* Set RM PROD & CONS perf profile */
-	profile.max_supported_bandwidth_mbps =
-			params->max_supported_bandwidth_mbps;
-	result = ipa_rm_set_perf_profile(
-		ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.prod_params.name,
-		&profile);
-	if (result) {
-		IPA_USB_ERR("failed to set %s perf profile\n",
-			ipa_rm_resource_str(ipa3_usb_ctx->ttype_ctx[ttype].
-				rm_ctx.prod_params.name));
-		return result;
-	}
-	result = ipa_rm_set_perf_profile(
-		ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_params.name,
-		&profile);
-	if (result) {
-		IPA_USB_ERR("failed to set %s perf profile\n",
-			ipa_rm_resource_str(ipa3_usb_ctx->ttype_ctx[ttype].
-				rm_ctx.cons_params.name));
-		return result;
-	}
+	if (ipa_pm_is_used()) {
+		result = ipa_pm_set_perf_profile(
+			ipa3_usb_ctx->ttype_ctx[ttype].pm_ctx.hdl,
+			params->max_supported_bandwidth_mbps);
+		if (result) {
+			IPA_USB_ERR("failed to set perf profile\n");
+			return result;
+		}
 
-	/* Request PROD */
-	result = ipa3_usb_request_prod(ttype);
-	if (result)
-		return result;
+		result = ipa_pm_activate_sync(
+			ipa3_usb_ctx->ttype_ctx[ttype].pm_ctx.hdl);
+		if (result) {
+			IPA_USB_ERR("failed to activate pm\n");
+			return result;
+		}
+	} else {
+		/* Set RM PROD & CONS perf profile */
+		profile.max_supported_bandwidth_mbps =
+				params->max_supported_bandwidth_mbps;
+		result = ipa_rm_set_perf_profile(
+			ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.prod_params.name,
+			&profile);
+		if (result) {
+			IPA_USB_ERR("failed to set %s perf profile\n",
+				ipa_rm_resource_str(ipa3_usb_ctx->
+					ttype_ctx[ttype].
+					rm_ctx.prod_params.name));
+			return result;
+		}
+		result = ipa_rm_set_perf_profile(
+			ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_params.name,
+			&profile);
+		if (result) {
+			IPA_USB_ERR("failed to set %s perf profile\n",
+				ipa_rm_resource_str(ipa3_usb_ctx->
+					ttype_ctx[ttype].
+					rm_ctx.cons_params.name));
+			return result;
+		}
+
+		/* Request PROD */
+		result = ipa3_usb_request_prod(ttype);
+		if (result)
+			return result;
+	}
 
 	if (params->teth_prot != IPA_USB_DIAG) {
 		/* Start UL channel */
@@ -1775,7 +1894,11 @@
 		ipa3_reset_gsi_event_ring(params->usb_to_ipa_clnt_hdl);
 	}
 connect_ul_fail:
-	ipa3_usb_release_prod(ttype);
+	if (ipa_pm_is_used())
+		ipa_pm_deactivate_sync(
+			ipa3_usb_ctx->ttype_ctx[ttype].pm_ctx.hdl);
+	else
+		ipa3_usb_release_prod(ttype);
 	return result;
 }
 
@@ -2224,7 +2347,11 @@
 		goto bad_params;
 
 	if (orig_state != IPA_USB_SUSPENDED) {
-		result = ipa3_usb_release_prod(ttype);
+		if (ipa_pm_is_used())
+			result = ipa_pm_deactivate_sync(
+				ipa3_usb_ctx->ttype_ctx[ttype].pm_ctx.hdl);
+		else
+			result = ipa3_usb_release_prod(ttype);
 		if (result) {
 			IPA_USB_ERR("failed to release PROD.\n");
 			goto bad_params;
@@ -2334,13 +2461,19 @@
 		(ipa3_usb_ctx->num_init_prot == 0)) {
 		if (!ipa3_usb_set_state(IPA_USB_INVALID, false, ttype))
 			IPA_USB_ERR("failed to change state to invalid\n");
-		ipa_rm_delete_resource(
+		if (ipa_pm_is_used()) {
+			ipa3_usb_deregister_pm(ttype);
+		} else {
+			ipa_rm_delete_resource(
 			ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.prod_params.name);
-		ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.prod_valid = false;
-		ipa_rm_delete_resource(
+			ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.prod_valid =
+				false;
+			ipa_rm_delete_resource(
 			ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_params.name);
-		ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_valid = false;
-		ipa3_usb_ctx->ttype_ctx[ttype].ipa_usb_notify_cb = NULL;
+			ipa3_usb_ctx->ttype_ctx[ttype].rm_ctx.cons_valid =
+				false;
+			ipa3_usb_ctx->ttype_ctx[ttype].ipa_usb_notify_cb = NULL;
+		}
 	}
 
 	IPA_USB_DBG_LOW("exit\n");
@@ -2400,7 +2533,11 @@
 	if (result)
 		goto start_ul;
 
-	result = ipa3_usb_release_prod(ttype);
+	if (ipa_pm_is_used())
+		result = ipa_pm_deactivate_sync(
+			ipa3_usb_ctx->ttype_ctx[ttype].pm_ctx.hdl);
+	else
+		result = ipa3_usb_release_prod(ttype);
 	if (result) {
 		IPA_USB_ERR("failed to release PROD.\n");
 		goto connect_teth;
@@ -2477,7 +2614,11 @@
 	}
 	ipa3_usb_ctx->qmi_req_id++;
 
-	result = ipa3_usb_release_prod(ttype);
+	if (ipa_pm_is_used())
+		result = ipa_pm_deactivate_sync(
+			ipa3_usb_ctx->ttype_ctx[ttype].pm_ctx.hdl);
+	else
+		result = ipa3_usb_release_prod(ttype);
 	if (result) {
 		IPA_USB_ERR("failed to release PROD\n");
 		goto release_prod_fail;
@@ -2543,7 +2684,11 @@
 		"DPL channel":"Data Tethering channels");
 
 	/* Request USB_PROD */
-	result = ipa3_usb_request_prod(ttype);
+	if (ipa_pm_is_used())
+		result = ipa_pm_activate_sync(
+			ipa3_usb_ctx->ttype_ctx[ttype].pm_ctx.hdl);
+	else
+		result = ipa3_usb_request_prod(ttype);
 	if (result)
 		goto fail_exit;
 
@@ -2590,7 +2735,11 @@
 disconn_teth:
 	(void)ipa3_usb_disconnect_teth_prot(teth_prot);
 release_prod:
-	(void)ipa3_usb_release_prod(ttype);
+	if (ipa_pm_is_used())
+		(void)ipa_pm_deactivate_sync(
+			ipa3_usb_ctx->ttype_ctx[ttype].pm_ctx.hdl);
+	else
+		(void)ipa3_usb_release_prod(ttype);
 fail_exit:
 	return result;
 }
@@ -2642,7 +2791,11 @@
 	}
 
 	/* Request USB_PROD */
-	result = ipa3_usb_request_prod(ttype);
+	if (ipa_pm_is_used())
+		result = ipa_pm_activate_sync(
+			ipa3_usb_ctx->ttype_ctx[ttype].pm_ctx.hdl);
+	else
+		result = ipa3_usb_request_prod(ttype);
 	if (result)
 		goto prod_req_fail;
 
@@ -2685,7 +2838,11 @@
 			IPA_USB_ERR("Error stopping UL channel: %d\n", result);
 	}
 start_ul_fail:
-	ipa3_usb_release_prod(ttype);
+	if (ipa_pm_is_used())
+		ipa_pm_deactivate_sync(
+			ipa3_usb_ctx->ttype_ctx[ttype].pm_ctx.hdl);
+	else
+		ipa3_usb_release_prod(ttype);
 prod_req_fail:
 	/* Change state back to prev_state */
 	if (!ipa3_usb_set_state(prev_state, true, ttype))
@@ -2722,6 +2879,20 @@
 	ipa3_usb_ctx->dl_data_pending = false;
 	mutex_init(&ipa3_usb_ctx->general_mutex);
 
+	if (ipa_pm_is_used()) {
+		struct ipa3_usb_pm_context *pm_ctx;
+
+		pm_ctx =
+			&ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].pm_ctx;
+		pm_ctx->hdl = ~0;
+		pm_ctx->remote_wakeup_work =
+			&ipa3_usb_notify_remote_wakeup_work;
+		pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_DPL].pm_ctx;
+		pm_ctx->hdl = ~0;
+		pm_ctx->remote_wakeup_work =
+			&ipa3_usb_dpl_notify_remote_wakeup_work;
+	}
+
 	for (i = 0; i < IPA_USB_TRANSPORT_MAX; i++) {
 		ipa3_usb_ctx->ttype_ctx[i].rm_ctx.prod_valid = false;
 		ipa3_usb_ctx->ttype_ctx[i].rm_ctx.cons_valid = false;
diff --git a/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c b/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c
index a623d0b..f0d1102 100644
--- a/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_clients/odu_bridge.c
@@ -27,6 +27,7 @@
 #include <linux/cdev.h>
 #include <linux/ipa_odu_bridge.h>
 #include "../ipa_common_i.h"
+#include "../ipa_v3/ipa_pm.h"
 
 #define ODU_BRIDGE_DRV_NAME "odu_ipa_bridge"
 
@@ -152,6 +153,7 @@
 	void *logbuf_low;
 	struct completion rm_comp;
 	void (*wakeup_request)(void *);
+	u32 pm_hdl;
 };
 static struct odu_bridge_ctx *odu_bridge_ctx;
 
@@ -273,20 +275,22 @@
 	memset(&odu_prod_params, 0, sizeof(odu_prod_params));
 	memset(&odu_emb_cons_params, 0, sizeof(odu_emb_cons_params));
 
-	/* Build IPA Resource manager dependency graph */
-	ODU_BRIDGE_DBG_LOW("build dependency graph\n");
-	res = ipa_rm_add_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
+	if (!ipa_pm_is_used()) {
+		/* Build IPA Resource manager dependency graph */
+		ODU_BRIDGE_DBG_LOW("build dependency graph\n");
+		res = ipa_rm_add_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
 					IPA_RM_RESOURCE_Q6_CONS);
-	if (res && res != -EINPROGRESS) {
-		ODU_BRIDGE_ERR("ipa_rm_add_dependency() failed\n");
-		goto fail_add_dependency_1;
-	}
+		if (res && res != -EINPROGRESS) {
+			ODU_BRIDGE_ERR("ipa_rm_add_dependency() failed\n");
+			goto fail_add_dependency_1;
+		}
 
-	res = ipa_rm_add_dependency(IPA_RM_RESOURCE_Q6_PROD,
+		res = ipa_rm_add_dependency(IPA_RM_RESOURCE_Q6_PROD,
 					IPA_RM_RESOURCE_ODU_ADAPT_CONS);
-	if (res && res != -EINPROGRESS) {
-		ODU_BRIDGE_ERR("ipa_rm_add_dependency() failed\n");
-		goto fail_add_dependency_2;
+		if (res && res != -EINPROGRESS) {
+			ODU_BRIDGE_ERR("ipa_rm_add_dependency() failed\n");
+			goto fail_add_dependency_2;
+		}
 	}
 
 	/* configure RX (ODU->IPA) EP */
@@ -346,10 +350,12 @@
 	ipa_teardown_sys_pipe(odu_bridge_ctx->odu_prod_hdl);
 	odu_bridge_ctx->odu_prod_hdl = 0;
 fail_odu_prod:
-	ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
+	if (!ipa_pm_is_used())
+		ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
 				IPA_RM_RESOURCE_ODU_ADAPT_CONS);
 fail_add_dependency_2:
-	ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
+	if (!ipa_pm_is_used())
+		ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
 				IPA_RM_RESOURCE_Q6_CONS);
 fail_add_dependency_1:
 	return res;
@@ -397,17 +403,19 @@
 		ODU_BRIDGE_ERR("teardown ODU EMB CONS failed\n");
 	odu_bridge_ctx->odu_emb_cons_hdl = 0;
 
-	/* Delete IPA Resource manager dependency graph */
-	ODU_BRIDGE_DBG("deleting dependency graph\n");
-	res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
-		IPA_RM_RESOURCE_Q6_CONS);
-	if (res && res != -EINPROGRESS)
-		ODU_BRIDGE_ERR("ipa_rm_delete_dependency() failed\n");
+	if (!ipa_pm_is_used()) {
+		/* Delete IPA Resource manager dependency graph */
+		ODU_BRIDGE_DBG("deleting dependency graph\n");
+		res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
+			IPA_RM_RESOURCE_Q6_CONS);
+		if (res && res != -EINPROGRESS)
+			ODU_BRIDGE_ERR("ipa_rm_delete_dependency() failed\n");
 
-	res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
-		IPA_RM_RESOURCE_ODU_ADAPT_CONS);
-	if (res && res != -EINPROGRESS)
-		ODU_BRIDGE_ERR("ipa_rm_delete_dependency() failed\n");
+		res = ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
+			IPA_RM_RESOURCE_ODU_ADAPT_CONS);
+		if (res && res != -EINPROGRESS)
+			ODU_BRIDGE_ERR("ipa_rm_delete_dependency() failed\n");
+	}
 
 	return 0;
 }
@@ -1319,24 +1327,58 @@
 	return 0;
 }
 
-/* IPA Bridge API is the new API which will replaces old odu_bridge API */
-int ipa_bridge_init(struct ipa_bridge_init_params *params, u32 *hdl)
+static void ipa_br_pm_cb(void *p, enum ipa_pm_cb_event event)
+{
+	ODU_BRIDGE_FUNC_ENTRY();
+	if (event != IPA_PM_REQUEST_WAKEUP) {
+		ODU_BRIDGE_ERR("Unexpected event %d\n", event);
+		WARN_ON(1);
+		return;
+	}
+
+	if (odu_bridge_ctx->is_suspended)
+		odu_bridge_ctx->wakeup_request(odu_bridge_ctx->priv);
+	ODU_BRIDGE_FUNC_EXIT();
+}
+
+static int ipa_br_register_pm(void)
+{
+	struct ipa_pm_register_params reg_params;
+	int ret;
+
+	memset(&reg_params, 0, sizeof(reg_params));
+	reg_params.name = "ODU Bridge";
+	reg_params.callback = ipa_br_pm_cb;
+	reg_params.group = IPA_PM_GROUP_DEFAULT;
+
+	ret = ipa_pm_register(&reg_params,
+		&odu_bridge_ctx->pm_hdl);
+	if (ret) {
+		ODU_BRIDGE_ERR("fail to register with PM %d\n", ret);
+		goto fail_pm_reg;
+	}
+
+	ret = ipa_pm_associate_ipa_cons_to_client(odu_bridge_ctx->pm_hdl,
+		IPA_CLIENT_ODU_EMB_CONS);
+	if (ret) {
+		ODU_BRIDGE_ERR("fail to associate cons with PM %d\n", ret);
+		goto fail_pm_cons;
+	}
+
+	return 0;
+
+fail_pm_cons:
+	ipa_pm_deregister(odu_bridge_ctx->pm_hdl);
+	odu_bridge_ctx->pm_hdl = ~0;
+fail_pm_reg:
+	return ret;
+}
+
+static int ipa_br_create_rm_resources(void)
 {
 	int ret;
 	struct ipa_rm_create_params create_params;
 
-	if (!params || !params->wakeup_request || !hdl) {
-		ODU_BRIDGE_ERR("NULL arg\n");
-		return -EINVAL;
-	}
-
-
-	ret = odu_bridge_init(&params->info);
-	if (ret)
-		return ret;
-
-	odu_bridge_ctx->wakeup_request = params->wakeup_request;
-
 	/* create IPA RM resources for power management */
 	init_completion(&odu_bridge_ctx->rm_comp);
 	memset(&create_params, 0, sizeof(create_params));
@@ -1368,9 +1410,6 @@
 		goto fail_rm_cons;
 	}
 
-	/* handle is ignored for now */
-	*hdl = 0;
-
 	return 0;
 
 fail_rm_cons:
@@ -1379,6 +1418,41 @@
 fail_add_dep:
 	ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
 fail_rm_prod:
+	return ret;
+}
+
+/* IPA Bridge API is the new API which will replaces old odu_bridge API */
+int ipa_bridge_init(struct ipa_bridge_init_params *params, u32 *hdl)
+{
+	int ret;
+
+	if (!params || !params->wakeup_request || !hdl) {
+		ODU_BRIDGE_ERR("NULL arg\n");
+		return -EINVAL;
+	}
+
+
+	ret = odu_bridge_init(&params->info);
+	if (ret)
+		return ret;
+
+	odu_bridge_ctx->wakeup_request = params->wakeup_request;
+
+	if (ipa_pm_is_used())
+		ret = ipa_br_register_pm();
+	else
+		ret = ipa_br_create_rm_resources();
+	if (ret) {
+		ODU_BRIDGE_ERR("fail to register woth RM/PM %d\n", ret);
+		goto fail_pm;
+	}
+
+	/* handle is ignored for now */
+	*hdl = 0;
+
+	return 0;
+
+fail_pm:
 	odu_bridge_cleanup();
 	return ret;
 }
@@ -1398,7 +1472,10 @@
 		return -EFAULT;
 	}
 
-	ret = ipa_br_request_prod();
+	if (ipa_pm_is_used())
+		ret = ipa_pm_activate_sync(odu_bridge_ctx->pm_hdl);
+	else
+		ret = ipa_br_request_prod();
 	if (ret)
 		return ret;
 
@@ -1411,6 +1488,10 @@
 	struct ipa_rm_perf_profile profile = {0};
 	int ret;
 
+	if (ipa_pm_is_used())
+		return ipa_pm_set_perf_profile(odu_bridge_ctx->pm_hdl,
+			bandwidth);
+
 	profile.max_supported_bandwidth_mbps = bandwidth;
 	ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_ODU_ADAPT_PROD, &profile);
 	if (ret) {
@@ -1436,7 +1517,10 @@
 	if (ret)
 		return ret;
 
-	ret = ipa_br_release_prod();
+	if (ipa_pm_is_used())
+		ret = ipa_pm_deactivate_sync(odu_bridge_ctx->pm_hdl);
+	else
+		ret = ipa_br_release_prod();
 	if (ret)
 		return ret;
 
@@ -1470,7 +1554,10 @@
 		return ret;
 	}
 
-	ret = ipa_br_release_prod();
+	if (ipa_pm_is_used())
+		ret = ipa_pm_deactivate_sync(odu_bridge_ctx->pm_hdl);
+	else
+		ret = ipa_br_release_prod();
 	if (ret) {
 		ODU_BRIDGE_ERR("failed to release prod %d\n", ret);
 		ipa_start_gsi_channel(odu_bridge_ctx->odu_emb_cons_hdl);
@@ -1501,7 +1588,10 @@
 		return -EFAULT;
 	}
 
-	ret = ipa_br_request_prod();
+	if (ipa_pm_is_used())
+		ret = ipa_pm_activate_sync(odu_bridge_ctx->pm_hdl);
+	else
+		ret = ipa_br_request_prod();
 	if (ret)
 		return ret;
 
@@ -1523,12 +1613,27 @@
 }
 EXPORT_SYMBOL(ipa_bridge_tx_dp);
 
-int ipa_bridge_cleanup(u32 hdl)
+static void ipa_br_delete_rm_resources(void)
 {
 	ipa_rm_delete_dependency(IPA_RM_RESOURCE_ODU_ADAPT_PROD,
 		IPA_RM_RESOURCE_APPS_CONS);
 	ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_PROD);
 	ipa_rm_delete_resource(IPA_RM_RESOURCE_ODU_ADAPT_CONS);
+}
+
+static void ipa_br_deregister_pm(void)
+{
+	ipa_pm_deactivate_sync(odu_bridge_ctx->pm_hdl);
+	ipa_pm_deregister(odu_bridge_ctx->pm_hdl);
+	odu_bridge_ctx->pm_hdl = ~0;
+}
+
+int ipa_bridge_cleanup(u32 hdl)
+{
+	if (ipa_pm_is_used())
+		ipa_br_deregister_pm();
+	else
+		ipa_br_delete_rm_resources();
 	return odu_bridge_cleanup();
 }
 EXPORT_SYMBOL(ipa_bridge_cleanup);
diff --git a/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c b/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c
index f62cb27..1c47e69 100644
--- a/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c
@@ -9,7 +9,6 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-
 #include <linux/atomic.h>
 #include <linux/errno.h>
 #include <linux/etherdevice.h>
@@ -27,6 +26,8 @@
 #include <linux/random.h>
 #include <linux/rndis_ipa.h>
 #include <linux/workqueue.h>
+#include "../ipa_common_i.h"
+#include "../ipa_v3/ipa_pm.h"
 
 #define CREATE_TRACE_POINTS
 #include "rndis_ipa_trace.h"
@@ -160,6 +161,7 @@
  * state is changed to RNDIS_IPA_CONNECTED_AND_UP
  * @xmit_error_delayed_work: work item for cases where IPA driver Tx fails
  * @state_lock: used to protect the state variable.
+ * @pm_hdl: handle for IPA PM framework
  */
 struct rndis_ipa_dev {
 	struct net_device *net;
@@ -188,6 +190,7 @@
 	void (*device_ready_notify)(void);
 	struct delayed_work xmit_error_delayed_work;
 	spinlock_t state_lock; /* Spinlock for the state variable.*/
+	u32 pm_hdl;
 };
 
 /**
@@ -233,6 +236,8 @@
 	unsigned long data);
 static int rndis_ipa_create_rm_resource(struct rndis_ipa_dev *rndis_ipa_ctx);
 static int rndis_ipa_destroy_rm_resource(struct rndis_ipa_dev *rndis_ipa_ctx);
+static int rndis_ipa_register_pm_client(struct rndis_ipa_dev *rndis_ipa_ctx);
+static int rndis_ipa_deregister_pm_client(struct rndis_ipa_dev *rndis_ipa_ctx);
 static bool rx_filter(struct sk_buff *skb);
 static bool tx_filter(struct sk_buff *skb);
 static bool rm_enabled(struct rndis_ipa_dev *rndis_ipa_ctx);
@@ -701,7 +706,10 @@
 		return -EINVAL;
 	}
 
-	result = rndis_ipa_create_rm_resource(rndis_ipa_ctx);
+	if (ipa_pm_is_used())
+		result = rndis_ipa_register_pm_client(rndis_ipa_ctx);
+	else
+		result = rndis_ipa_create_rm_resource(rndis_ipa_ctx);
 	if (result) {
 		RNDIS_IPA_ERROR("fail on RM create\n");
 		goto fail_create_rm;
@@ -763,7 +771,10 @@
 	return 0;
 
 fail:
-	rndis_ipa_destroy_rm_resource(rndis_ipa_ctx);
+	if (ipa_pm_is_used())
+		rndis_ipa_deregister_pm_client(rndis_ipa_ctx);
+	else
+		rndis_ipa_destroy_rm_resource(rndis_ipa_ctx);
 fail_create_rm:
 	return result;
 }
@@ -1235,7 +1246,10 @@
 	rndis_ipa_ctx->net->stats.tx_dropped += outstanding_dropped_pkts;
 	atomic_set(&rndis_ipa_ctx->outstanding_pkts, 0);
 
-	retval = rndis_ipa_destroy_rm_resource(rndis_ipa_ctx);
+	if (ipa_pm_is_used())
+		retval = rndis_ipa_deregister_pm_client(rndis_ipa_ctx);
+	else
+		retval = rndis_ipa_destroy_rm_resource(rndis_ipa_ctx);
 	if (retval) {
 		RNDIS_IPA_ERROR("Fail to clean RM\n");
 		return retval;
@@ -1772,6 +1786,29 @@
 	return result;
 }
 
+static void rndis_ipa_pm_cb(void *p, enum ipa_pm_cb_event event)
+{
+	struct rndis_ipa_dev *rndis_ipa_ctx = p;
+
+	RNDIS_IPA_LOG_ENTRY();
+
+	if (event != IPA_PM_CLIENT_ACTIVATED) {
+		RNDIS_IPA_ERROR("unexpected event %d\n", event);
+		WARN_ON(1);
+		return;
+	}
+	RNDIS_IPA_DEBUG("Resource Granted\n");
+
+	if (netif_queue_stopped(rndis_ipa_ctx->net)) {
+		RNDIS_IPA_DEBUG("starting queue\n");
+		netif_start_queue(rndis_ipa_ctx->net);
+	} else {
+		RNDIS_IPA_DEBUG("queue already awake\n");
+	}
+
+	RNDIS_IPA_LOG_EXIT();
+}
+
 /**
  * rndis_ipa_destroy_rm_resource() - delete the dependency and destroy
  * the resource done on rndis_ipa_create_rm_resource()
@@ -1831,6 +1868,33 @@
 	return result;
 }
 
+static int rndis_ipa_register_pm_client(struct rndis_ipa_dev *rndis_ipa_ctx)
+{
+	int result;
+	struct ipa_pm_register_params pm_reg;
+
+	memset(&pm_reg, 0, sizeof(pm_reg));
+
+	pm_reg.name = rndis_ipa_ctx->net->name;
+	pm_reg.user_data = rndis_ipa_ctx;
+	pm_reg.callback = rndis_ipa_pm_cb;
+	pm_reg.group = IPA_PM_GROUP_APPS;
+	result = ipa_pm_register(&pm_reg, &rndis_ipa_ctx->pm_hdl);
+	if (result) {
+		RNDIS_IPA_ERROR("failed to create IPA PM client %d\n", result);
+		return result;
+	}
+	return 0;
+}
+
+static int rndis_ipa_deregister_pm_client(struct rndis_ipa_dev *rndis_ipa_ctx)
+{
+	ipa_pm_deactivate_sync(rndis_ipa_ctx->pm_hdl);
+	ipa_pm_deregister(rndis_ipa_ctx->pm_hdl);
+	rndis_ipa_ctx->pm_hdl = ~0;
+	return 0;
+}
+
 /**
  * resource_request() - request for the Netdev resource
  * @rndis_ipa_ctx: main driver context
@@ -1849,11 +1913,14 @@
 	int result = 0;
 
 	if (!rm_enabled(rndis_ipa_ctx))
-		goto out;
-	result = ipa_rm_inactivity_timer_request_resource(
+		return result;
+
+	if (ipa_pm_is_used())
+		return ipa_pm_activate(rndis_ipa_ctx->pm_hdl);
+
+	return ipa_rm_inactivity_timer_request_resource(
 			DRV_RESOURCE_ID);
-out:
-	return result;
+
 }
 
 /**
@@ -1868,9 +1935,12 @@
 static void resource_release(struct rndis_ipa_dev *rndis_ipa_ctx)
 {
 	if (!rm_enabled(rndis_ipa_ctx))
-		goto out;
-	ipa_rm_inactivity_timer_release_resource(DRV_RESOURCE_ID);
-out:
+		return;
+	if (ipa_pm_is_used())
+		ipa_pm_deferred_deactivate(rndis_ipa_ctx->pm_hdl);
+	else
+		ipa_rm_inactivity_timer_release_resource(DRV_RESOURCE_ID);
+
 	return;
 }
 
diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h
index 32c8b25..a487bf4 100644
--- a/drivers/platform/msm/ipa/ipa_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_common_i.h
@@ -386,4 +386,6 @@
 const char *ipa_get_version_string(enum ipa_hw_type ver);
 int ipa_start_gsi_channel(u32 clnt_hdl);
 
+bool ipa_pm_is_used(void);
+
 #endif /* _IPA_COMMON_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/Makefile b/drivers/platform/msm/ipa/ipa_v3/Makefile
index e3f8d45..5db2545 100644
--- a/drivers/platform/msm/ipa/ipa_v3/Makefile
+++ b/drivers/platform/msm/ipa/ipa_v3/Makefile
@@ -4,6 +4,6 @@
 ipat-y := ipa.o ipa_debugfs.o ipa_hdr.o ipa_flt.o ipa_rt.o ipa_dp.o ipa_client.o \
 	ipa_utils.o ipa_nat.o ipa_intf.o teth_bridge.o ipa_interrupts.o \
 	ipa_uc.o ipa_uc_wdi.o ipa_dma.o ipa_uc_mhi.o ipa_mhi.o ipa_uc_ntn.o \
-	ipa_hw_stats.o
+	ipa_hw_stats.o ipa_pm.o
 
 obj-$(CONFIG_RMNET_IPA3) += rmnet_ipa.o ipa_qmi_service_v01.o ipa_qmi_service.o rmnet_ipa_fd_ioctl.o
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 2210ee7..a52b4e0 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -1466,6 +1466,10 @@
 		}
 		break;
 	case IPA_IOC_RM_ADD_DEPENDENCY:
+		/* deprecate if IPA PM is used */
+		if (ipa3_ctx->use_ipa_pm)
+			return 0;
+
 		if (copy_from_user((u8 *)&rm_depend, (u8 *)arg,
 				sizeof(struct ipa_ioc_rm_dependency))) {
 			retval = -EFAULT;
@@ -1475,6 +1479,10 @@
 			rm_depend.resource_name, rm_depend.depends_on_name);
 		break;
 	case IPA_IOC_RM_DEL_DEPENDENCY:
+		/* deprecate if IPA PM is used */
+		if (ipa3_ctx->use_ipa_pm)
+			return 0;
+
 		if (copy_from_user((u8 *)&rm_depend, (u8 *)arg,
 				sizeof(struct ipa_ioc_rm_dependency))) {
 			retval = -EFAULT;
@@ -2350,7 +2358,6 @@
 	struct ipahal_imm_cmd_register_write reg_write;
 	struct ipahal_imm_cmd_pyld *cmd_pyld;
 	int retval;
-	struct ipahal_reg_valmask valmask;
 
 	desc = kcalloc(ipa3_ctx->ipa_num_pipes, sizeof(struct ipa3_desc),
 			GFP_KERNEL);
@@ -2365,39 +2372,10 @@
 		if (ep_idx == -1)
 			continue;
 
-		if (ipa3_ctx->ep[ep_idx].valid &&
-			ipa3_ctx->ep[ep_idx].skip_ep_cfg) {
-			BUG_ON(num_descs >= ipa3_ctx->ipa_num_pipes);
-
-			reg_write.skip_pipeline_clear = false;
-			reg_write.pipeline_clear_options =
-				IPAHAL_HPS_CLEAR;
-			reg_write.offset =
-				ipahal_get_reg_n_ofst(IPA_ENDP_STATUS_n,
-					ep_idx);
-			ipahal_get_status_ep_valmask(
-				ipa3_get_ep_mapping(IPA_CLIENT_APPS_LAN_CONS),
-				&valmask);
-			reg_write.value = valmask.val;
-			reg_write.value_mask = valmask.mask;
-			cmd_pyld = ipahal_construct_imm_cmd(
-				IPA_IMM_CMD_REGISTER_WRITE, &reg_write, false);
-			if (!cmd_pyld) {
-				IPAERR("fail construct register_write cmd\n");
-				BUG();
-			}
-
-			desc[num_descs].opcode = cmd_pyld->opcode;
-			desc[num_descs].type = IPA_IMM_CMD_DESC;
-			desc[num_descs].callback = ipa3_destroy_imm;
-			desc[num_descs].user1 = cmd_pyld;
-			desc[num_descs].pyld = cmd_pyld->data;
-			desc[num_descs].len = cmd_pyld->len;
-			num_descs++;
-		}
-
-		/* disable statuses for modem producers */
-		if (IPA_CLIENT_IS_Q6_PROD(client_idx)) {
+		/* disable statuses for all modem controlled prod pipes */
+		if (IPA_CLIENT_IS_Q6_PROD(client_idx) ||
+			(ipa3_ctx->ep[ep_idx].valid &&
+			ipa3_ctx->ep[ep_idx].skip_ep_cfg)) {
 			ipa_assert_on(num_descs >= ipa3_ctx->ipa_num_pipes);
 
 			reg_write.skip_pipeline_clear = false;
@@ -3712,6 +3690,53 @@
 	spin_unlock_irqrestore(&ipa3_ctx->wakelock_ref_cnt.spinlock, flags);
 }
 
+int ipa3_set_clock_plan_from_pm(int idx)
+{
+	u32 clk_rate;
+
+	IPADBG_LOW("idx = %d\n", idx);
+
+	if (idx <= 0 || idx >= ipa3_ctx->ctrl->msm_bus_data_ptr->num_usecases) {
+		IPAERR("bad voltage\n");
+		return -EINVAL;
+	}
+
+	if (idx == 1)
+		clk_rate = ipa3_ctx->ctrl->ipa_clk_rate_svs;
+	else if (idx == 2)
+		clk_rate = ipa3_ctx->ctrl->ipa_clk_rate_nominal;
+	else if (idx == 3)
+		clk_rate = ipa3_ctx->ctrl->ipa_clk_rate_turbo;
+	else {
+		IPAERR("bad voltage\n");
+		WARN_ON(1);
+		return -EFAULT;
+	}
+
+	if (clk_rate == ipa3_ctx->curr_ipa_clk_rate) {
+		IPADBG_LOW("Same voltage\n");
+		return 0;
+	}
+
+	mutex_lock(&ipa3_ctx->ipa3_active_clients.mutex);
+	ipa3_ctx->curr_ipa_clk_rate = clk_rate;
+	ipa3_ctx->ipa3_active_clients.bus_vote_idx = idx;
+	IPADBG_LOW("setting clock rate to %u\n", ipa3_ctx->curr_ipa_clk_rate);
+	if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) > 0) {
+		if (ipa3_clk)
+			clk_set_rate(ipa3_clk, ipa3_ctx->curr_ipa_clk_rate);
+		if (msm_bus_scale_client_update_request(ipa3_ctx->ipa_bus_hdl,
+				ipa3_get_bus_vote()))
+			WARN_ON(1);
+	} else {
+		IPADBG_LOW("clocks are gated, not setting rate\n");
+	}
+	mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);
+	IPADBG_LOW("Done\n");
+
+	return 0;
+}
+
 int ipa3_set_required_perf_profile(enum ipa_voltage_level floor_voltage,
 				  u32 bandwidth_mbps)
 {
@@ -3814,14 +3839,19 @@
 	u32 i = 0;
 	int res;
 	struct ipa_ep_cfg_holb holb_cfg;
+	u32 pipe_bitmask = 0;
 
 	IPADBG("interrupt=%d, interrupt_data=%u\n",
 		interrupt, suspend_data);
 	memset(&holb_cfg, 0, sizeof(holb_cfg));
 	holb_cfg.tmr_val = 0;
 
-	for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) {
+	for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++, bmsk = bmsk << 1) {
 		if ((suspend_data & bmsk) && (ipa3_ctx->ep[i].valid)) {
+			if (ipa3_ctx->use_ipa_pm) {
+				pipe_bitmask |= bmsk;
+				continue;
+			}
 			if (IPA_CLIENT_IS_APPS_CONS(ipa3_ctx->ep[i].client)) {
 				/*
 				 * pipe will be unsuspended as part of
@@ -3860,7 +3890,13 @@
 				}
 			}
 		}
-		bmsk = bmsk << 1;
+	}
+	if (ipa3_ctx->use_ipa_pm) {
+		res = ipa_pm_handle_suspend(pipe_bitmask);
+		if (res) {
+			IPAERR("ipa_pm_handle_suspend failed %d\n", res);
+			return;
+		}
 	}
 }
 
@@ -4621,6 +4657,7 @@
 	ipa3_ctx->ee = resource_p->ee;
 	ipa3_ctx->apply_rg10_wa = resource_p->apply_rg10_wa;
 	ipa3_ctx->gsi_ch20_wa = resource_p->gsi_ch20_wa;
+	ipa3_ctx->use_ipa_pm = resource_p->use_ipa_pm;
 	ipa3_ctx->ipa3_active_clients_logging.log_rdy = false;
 	if (resource_p->ipa_tz_unlock_reg) {
 		ipa3_ctx->ipa_tz_unlock_reg_num =
@@ -4934,20 +4971,30 @@
 	wakeup_source_init(&ipa3_ctx->w_lock, "IPA_WS");
 	spin_lock_init(&ipa3_ctx->wakelock_ref_cnt.spinlock);
 
-	/* Initialize IPA RM (resource manager) */
-	result = ipa_rm_initialize();
-	if (result) {
-		IPAERR("RM initialization failed (%d)\n", -result);
-		result = -ENODEV;
-		goto fail_ipa_rm_init;
-	}
-	IPADBG("IPA resource manager initialized");
+	/* Initialize Power Management framework */
+	if (ipa3_ctx->use_ipa_pm) {
+		result = ipa_pm_init(&ipa3_res.pm_init);
+		if (result) {
+			IPAERR("IPA PM initialization failed (%d)\n", -result);
+			result = -ENODEV;
+			goto fail_ipa_rm_init;
+		}
+		IPADBG("IPA resource manager initialized");
+	} else {
+		result = ipa_rm_initialize();
+		if (result) {
+			IPAERR("RM initialization failed (%d)\n", -result);
+			result = -ENODEV;
+			goto fail_ipa_rm_init;
+		}
+		IPADBG("IPA resource manager initialized");
 
-	result = ipa3_create_apps_resource();
-	if (result) {
-		IPAERR("Failed to create APPS_CONS resource\n");
-		result = -ENODEV;
-		goto fail_create_apps_resource;
+		result = ipa3_create_apps_resource();
+		if (result) {
+			IPAERR("Failed to create APPS_CONS resource\n");
+			result = -ENODEV;
+			goto fail_create_apps_resource;
+		}
 	}
 
 	result = ipa3_alloc_pkt_init();
@@ -4998,9 +5045,11 @@
 
 fail_cdev_add:
 fail_ipa_init_interrupts:
-	ipa_rm_delete_resource(IPA_RM_RESOURCE_APPS_CONS);
+	if (!ipa3_ctx->use_ipa_pm)
+		ipa_rm_delete_resource(IPA_RM_RESOURCE_APPS_CONS);
 fail_create_apps_resource:
-	ipa_rm_exit();
+	if (!ipa3_ctx->use_ipa_pm)
+		ipa_rm_exit();
 fail_ipa_rm_init:
 fail_nat_dev_add:
 	device_destroy(ipa3_ctx->class, ipa3_ctx->dev_num);
@@ -5069,6 +5118,101 @@
 	return result;
 }
 
+bool ipa_pm_is_used(void)
+{
+	return (ipa3_ctx) ? ipa3_ctx->use_ipa_pm : false;
+}
+
+static int get_ipa_dts_pm_info(struct platform_device *pdev,
+	struct ipa3_plat_drv_res *ipa_drv_res)
+{
+	int result;
+	int i, j;
+
+	ipa_drv_res->use_ipa_pm = of_property_read_bool(pdev->dev.of_node,
+		"qcom,use-ipa-pm");
+	IPADBG("use_ipa_pm=%d\n", ipa_drv_res->use_ipa_pm);
+	if (!ipa_drv_res->use_ipa_pm)
+		return 0;
+
+	result = of_property_read_u32(pdev->dev.of_node,
+		"qcom,msm-bus,num-cases",
+		&ipa_drv_res->pm_init.threshold_size);
+	/* No vote is ignored */
+	ipa_drv_res->pm_init.threshold_size -= 2;
+	if (result || ipa_drv_res->pm_init.threshold_size >
+		IPA_PM_THRESHOLD_MAX) {
+		IPAERR("invalid property qcom,msm-bus,num-cases %d\n",
+			ipa_drv_res->pm_init.threshold_size);
+		return -EFAULT;
+	}
+
+	result = of_property_read_u32_array(pdev->dev.of_node,
+		"qcom,throughput-threshold",
+		ipa_drv_res->pm_init.default_threshold,
+		ipa_drv_res->pm_init.threshold_size);
+	if (result) {
+		IPAERR("failed to read qcom,throughput-thresholds\n");
+		return -EFAULT;
+	}
+
+	result = of_property_count_strings(pdev->dev.of_node,
+		"qcom,scaling-exceptions");
+	if (result < 0) {
+		IPADBG("no exception list for ipa pm\n");
+		result = 0;
+	}
+
+	if (result % (ipa_drv_res->pm_init.threshold_size + 1)) {
+		IPAERR("failed to read qcom,scaling-exceptions\n");
+		return -EFAULT;
+	}
+
+	ipa_drv_res->pm_init.exception_size = result /
+		(ipa_drv_res->pm_init.threshold_size + 1);
+	if (ipa_drv_res->pm_init.exception_size >=
+		IPA_PM_EXCEPTION_MAX) {
+		IPAERR("exception list larger then max %d\n",
+			ipa_drv_res->pm_init.exception_size);
+		return -EFAULT;
+	}
+
+	for (i = 0; i < ipa_drv_res->pm_init.exception_size; i++) {
+		struct ipa_pm_exception *ex = ipa_drv_res->pm_init.exceptions;
+
+		result = of_property_read_string_index(pdev->dev.of_node,
+			"qcom,scaling-exceptions",
+			i * ipa_drv_res->pm_init.threshold_size,
+			&ex[i].usecase);
+		if (result) {
+			IPAERR("failed to read qcom,scaling-exceptions");
+			return -EFAULT;
+		}
+
+		for (j = 0; j < ipa_drv_res->pm_init.threshold_size; j++) {
+			const char *str;
+
+			result = of_property_read_string_index(
+				pdev->dev.of_node,
+				"qcom,scaling-exceptions",
+				i * ipa_drv_res->pm_init.threshold_size + j + 1,
+				&str);
+			if (result) {
+				IPAERR("failed to read qcom,scaling-exceptions"
+					);
+				return -EFAULT;
+			}
+
+			if (kstrtou32(str, 0, &ex[i].threshold[j])) {
+				IPAERR("error str=%s\n", str);
+				return -EFAULT;
+			}
+		}
+	}
+
+	return 0;
+}
+
 static int get_ipa_dts_configuration(struct platform_device *pdev,
 		struct ipa3_plat_drv_res *ipa_drv_res)
 {
@@ -5307,6 +5451,14 @@
 		}
 		kfree(ipa_tz_unlock_reg);
 	}
+
+	/* get IPA PM related information */
+	result = get_ipa_dts_pm_info(pdev, ipa_drv_res);
+	if (result) {
+		IPAERR("failed to get pm info from dts %d\n", result);
+		return result;
+	}
+
 	return 0;
 }
 
@@ -5844,11 +5996,16 @@
 		}
 	}
 
-	/*
-	 * Release transport IPA resource without waiting for inactivity timer
-	 */
-	atomic_set(&ipa3_ctx->transport_pm.eot_activity, 0);
-	ipa3_transport_release_resource(NULL);
+	if (ipa3_ctx->use_ipa_pm) {
+		ipa_pm_deactivate_all_deferred();
+	} else {
+		/*
+		 * Release transport IPA resource without waiting
+		 * for inactivity timer
+		 */
+		atomic_set(&ipa3_ctx->transport_pm.eot_activity, 0);
+		ipa3_transport_release_resource(NULL);
+	}
 	IPADBG("Exit\n");
 
 	return 0;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index 153548b..dabd6a3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -1705,6 +1705,10 @@
 {
 	int result, nbytes, cnt = 0;
 
+	/* deprecate if IPA PM is used */
+	if (ipa3_ctx->use_ipa_pm)
+		return 0;
+
 	result = ipa_rm_stat(dbg_buff, IPA_MAX_MSG_LEN);
 	if (result < 0) {
 		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
@@ -1716,6 +1720,45 @@
 	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
 }
 
+static ssize_t ipa3_pm_read_stats(struct file *file, char __user *ubuf,
+		size_t count, loff_t *ppos)
+{
+	int result, nbytes, cnt = 0;
+
+	if (!ipa3_ctx->use_ipa_pm)
+		return 0;
+
+	result = ipa_pm_stat(dbg_buff, IPA_MAX_MSG_LEN);
+	if (result < 0) {
+		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
+				"Error in printing PM stat %d\n", result);
+		cnt += nbytes;
+	} else
+		cnt += result;
+
+	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
+}
+
+static ssize_t ipa3_pm_ex_read_stats(struct file *file, char __user *ubuf,
+		size_t count, loff_t *ppos)
+{
+	int result, nbytes, cnt = 0;
+
+	if (!ipa3_ctx->use_ipa_pm)
+		return 0;
+
+	result = ipa_pm_exceptions_stat(dbg_buff, IPA_MAX_MSG_LEN);
+	if (result < 0) {
+		nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN,
+				"Error in printing PM stat %d\n", result);
+		cnt += nbytes;
+	} else
+		cnt += result;
+
+	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
+}
+
+
 static void ipa_dump_status(struct ipahal_pkt_status *status)
 {
 	IPA_DUMP_STATUS_FIELD(status_opcode);
@@ -1940,6 +1983,15 @@
 	.read = ipa3_rm_read_stats,
 };
 
+static const struct file_operations ipa3_pm_stats = {
+	.read = ipa3_pm_read_stats,
+};
+
+
+static const struct file_operations ipa3_pm_ex_stats = {
+	.read = ipa3_pm_ex_read_stats,
+};
+
 const struct file_operations ipa3_active_clients = {
 	.read = ipa3_print_active_clients_log,
 	.write = ipa3_clear_active_clients_log,
@@ -2131,11 +2183,27 @@
 		goto fail;
 	}
 
-	dfile_rm_stats = debugfs_create_file("rm_stats",
-			read_only_mode, dent, 0, &ipa3_rm_stats);
-	if (!dfile_rm_stats || IS_ERR(dfile_rm_stats)) {
-		IPAERR("fail to create file for debug_fs rm_stats\n");
-		goto fail;
+	if (ipa3_ctx->use_ipa_pm) {
+		file = dfile_rm_stats = debugfs_create_file("pm_stats",
+			read_only_mode, dent, NULL, &ipa3_pm_stats);
+		if (!file || IS_ERR(file)) {
+			IPAERR("fail to create file for debug_fs pm_stats\n");
+			goto fail;
+		}
+
+		file = dfile_rm_stats = debugfs_create_file("pm_ex_stats",
+			read_only_mode, dent, NULL, &ipa3_pm_ex_stats);
+		if (!file || IS_ERR(file)) {
+			IPAERR("fail to create file for debugfs pm_ex_stats\n");
+			goto fail;
+		}
+	} else {
+		dfile_rm_stats = debugfs_create_file("rm_stats",
+				read_only_mode, dent, NULL, &ipa3_rm_stats);
+		if (!dfile_rm_stats || IS_ERR(dfile_rm_stats)) {
+			IPAERR("fail to create file for debug_fs rm_stats\n");
+			goto fail;
+		}
 	}
 
 	dfile_status_stats = debugfs_create_file("status_stats",
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 26d5f5e..7f30a10 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -73,6 +73,8 @@
 
 #define IPA_TX_SEND_COMPL_NOP_DELAY_NS (2 * 1000 * 1000)
 
+#define IPA_APPS_BW_FOR_PM 700
+
 static struct sk_buff *ipa3_get_skb_ipa_rx(unsigned int len, gfp_t flags);
 static void ipa3_replenish_wlan_rx_cache(struct ipa3_sys_context *sys);
 static void ipa3_replenish_rx_cache(struct ipa3_sys_context *sys);
@@ -748,7 +750,10 @@
 	int inactive_cycles = 0;
 	int cnt;
 
-	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
+	if (ipa3_ctx->use_ipa_pm)
+		ipa_pm_activate_sync(sys->pm_hdl);
+	else
+		IPA_ACTIVE_CLIENTS_INC_SIMPLE();
 	do {
 		cnt = ipa3_handle_rx_core(sys, true, true);
 		if (cnt == 0)
@@ -772,7 +777,10 @@
 
 	trace_poll_to_intr3(sys->ep->client);
 	ipa3_rx_switch_to_intr_mode(sys);
-	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+	if (ipa3_ctx->use_ipa_pm)
+		ipa_pm_deferred_deactivate(sys->pm_hdl);
+	else
+		IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 }
 
 static void ipa3_switch_to_intr_rx_work_func(struct work_struct *work)
@@ -799,6 +807,32 @@
 	return HRTIMER_NORESTART;
 }
 
+static void ipa_pm_sys_pipe_cb(void *p, enum ipa_pm_cb_event event)
+{
+	struct ipa3_sys_context *sys = (struct ipa3_sys_context *)p;
+
+	switch (event) {
+	case IPA_PM_CLIENT_ACTIVATED:
+		/*
+		 * this event is ignored as the sync version of activation
+		 * will be used.
+		 */
+		break;
+	case IPA_PM_REQUEST_WAKEUP:
+		/*
+		 * pipe will be unsuspended as part of
+		 * enabling IPA clocks
+		 */
+		ipa_pm_activate_sync(sys->pm_hdl);
+		ipa_pm_deferred_deactivate(sys->pm_hdl);
+		break;
+	default:
+		IPAERR("Unexpected event %d\n", event);
+		WARN_ON(1);
+		return;
+	}
+}
+
 /**
  * ipa3_setup_sys_pipe() - Setup an IPA GPI pipe and perform
  * IPA EP configuration
@@ -846,6 +880,9 @@
 	memset(ep, 0, offsetof(struct ipa3_ep_context, sys));
 
 	if (!ep->sys) {
+		struct ipa_pm_register_params pm_reg;
+
+		memset(&pm_reg, 0, sizeof(pm_reg));
 		ep->sys = kzalloc(sizeof(struct ipa3_sys_context), GFP_KERNEL);
 		if (!ep->sys) {
 			IPAERR("failed to sys ctx for client %d\n",
@@ -884,6 +921,35 @@
 		hrtimer_init(&ep->sys->db_timer, CLOCK_MONOTONIC,
 			HRTIMER_MODE_REL);
 		ep->sys->db_timer.function = ipa3_ring_doorbell_timer_fn;
+
+		/* create IPA PM resources for handling polling mode */
+		if (ipa3_ctx->use_ipa_pm &&
+			IPA_CLIENT_IS_CONS(sys_in->client)) {
+			pm_reg.name = ipa_clients_strings[sys_in->client];
+			pm_reg.callback = ipa_pm_sys_pipe_cb;
+			pm_reg.user_data = ep->sys;
+			pm_reg.group = IPA_PM_GROUP_APPS;
+			result = ipa_pm_register(&pm_reg, &ep->sys->pm_hdl);
+			if (result) {
+				IPAERR("failed to create IPA PM client %d\n",
+					result);
+				goto fail_pm;
+			}
+
+			result = ipa_pm_associate_ipa_cons_to_client(
+				ep->sys->pm_hdl, sys_in->client);
+			if (result) {
+				IPAERR("failed to associate IPA PM client\n");
+				goto fail_gen2;
+			}
+
+			result = ipa_pm_set_perf_profile(ep->sys->pm_hdl,
+				IPA_APPS_BW_FOR_PM);
+			if (result) {
+				IPAERR("failed to set profile IPA PM client\n");
+				goto fail_gen2;
+			}
+		}
 	} else {
 		memset(ep->sys, 0, offsetof(struct ipa3_sys_context, ep));
 	}
@@ -984,6 +1050,9 @@
 	return 0;
 
 fail_gen2:
+	if (ipa3_ctx->use_ipa_pm)
+		ipa_pm_deregister(ep->sys->pm_hdl);
+fail_pm:
 	destroy_workqueue(ep->sys->repl_wq);
 fail_wq2:
 	destroy_workqueue(ep->sys->wq);
@@ -1402,7 +1471,8 @@
 	sys = container_of(work, struct ipa3_sys_context, work);
 
 	if (sys->ep->napi_enabled) {
-		IPA_ACTIVE_CLIENTS_INC_SPECIAL("NAPI");
+		if (!ipa3_ctx->use_ipa_pm)
+			IPA_ACTIVE_CLIENTS_INC_SPECIAL("NAPI");
 		sys->ep->client_notify(sys->ep->priv,
 				IPA_CLIENT_START_POLL, 0);
 	} else
@@ -3283,11 +3353,48 @@
 	}
 }
 
+void __ipa_gsi_irq_rx_scedule_poll(struct ipa3_sys_context *sys)
+{
+	bool clk_off;
+
+	atomic_set(&sys->curr_polling_state, 1);
+	ipa3_inc_acquire_wakelock();
+
+	/*
+	 * pm deactivate is done in wq context
+	 * or after NAPI poll
+	 */
+	if (ipa3_ctx->use_ipa_pm) {
+		clk_off = ipa_pm_activate(sys->pm_hdl);
+		if (!clk_off && sys->ep->napi_enabled) {
+			sys->ep->client_notify(sys->ep->priv,
+				IPA_CLIENT_START_POLL, 0);
+			return;
+		}
+		queue_work(sys->wq, &sys->work);
+		return;
+	}
+
+	if (sys->ep->napi_enabled) {
+		struct ipa_active_client_logging_info log;
+
+		IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log, "NAPI");
+		clk_off = ipa3_inc_client_enable_clks_no_block(
+			&log);
+		if (!clk_off) {
+			sys->ep->client_notify(sys->ep->priv,
+				IPA_CLIENT_START_POLL, 0);
+			return;
+		}
+	}
+
+	queue_work(sys->wq, &sys->work);
+}
+
 static void ipa_gsi_irq_rx_notify_cb(struct gsi_chan_xfer_notify *notify)
 {
 	struct ipa3_sys_context *sys;
 	struct ipa3_rx_pkt_wrapper *rx_pkt_expected, *rx_pkt_rcvd;
-	int clk_off;
 
 	if (!notify) {
 		IPAERR("gsi notify is NULL.\n");
@@ -3317,22 +3424,7 @@
 			/* put the gsi channel into polling mode */
 			gsi_config_channel_mode(sys->ep->gsi_chan_hdl,
 				GSI_CHAN_MODE_POLL);
-			ipa3_inc_acquire_wakelock();
-			atomic_set(&sys->curr_polling_state, 1);
-			if (sys->ep->napi_enabled) {
-				struct ipa_active_client_logging_info log;
-
-				IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log, "NAPI");
-				clk_off = ipa3_inc_client_enable_clks_no_block(
-					&log);
-				if (!clk_off)
-					sys->ep->client_notify(sys->ep->priv,
-						IPA_CLIENT_START_POLL, 0);
-				else
-					queue_work(sys->wq, &sys->work);
-			} else {
-				queue_work(sys->wq, &sys->work);
-			}
+			__ipa_gsi_irq_rx_scedule_poll(sys);
 		}
 		break;
 	default:
@@ -3734,7 +3826,10 @@
 	if (cnt < weight) {
 		ep->client_notify(ep->priv, IPA_CLIENT_COMP_NAPI, 0);
 		ipa3_rx_switch_to_intr_mode(ep->sys);
-		ipa3_dec_client_disable_clks_no_block(&log);
+		if (ipa3_ctx->use_ipa_pm)
+			ipa_pm_deferred_deactivate(ep->sys->pm_hdl);
+		else
+			ipa3_dec_client_disable_clks_no_block(&log);
 	}
 
 	return cnt;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 4d1baea..3e1d188 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -36,6 +36,7 @@
 #include "ipahal/ipahal_hw_stats.h"
 #include "../ipa_common_i.h"
 #include "ipa_uc_offload_i.h"
+#include "ipa_pm.h"
 
 #define DRV_NAME "ipa"
 #define NAT_DEV_NAME "ipaNatTable"
@@ -647,6 +648,7 @@
 	struct workqueue_struct *wq;
 	struct workqueue_struct *repl_wq;
 	struct ipa3_status_stats *status_stat;
+	u32 pm_hdl;
 	/* ordering is important - other immutable fields go below */
 };
 
@@ -869,6 +871,7 @@
 struct ipa3_active_clients {
 	struct mutex mutex;
 	atomic_t cnt;
+	int bus_vote_idx;
 };
 
 struct ipa3_wakelock_ref_cnt {
@@ -1314,6 +1317,7 @@
 	struct ipa_cne_evt ipa_cne_evt_req_cache[IPA_MAX_NUM_REQ_CACHE];
 	int num_ipa_cne_evt_req;
 	struct mutex ipa_cne_evt_lock;
+	bool use_ipa_pm;
 };
 
 struct ipa3_plat_drv_res {
@@ -1341,6 +1345,8 @@
 	bool tethered_flow_control;
 	u32 ipa_tz_unlock_reg_num;
 	struct ipa_tz_unlock_reg_info *ipa_tz_unlock_reg;
+	bool use_ipa_pm;
+	struct ipa_pm_init_params pm_init;
 };
 
 /**
@@ -2226,4 +2232,6 @@
 int ipa3_alloc_common_event_ring(void);
 int ipa3_allocate_dma_task_for_gsi(void);
 void ipa3_free_dma_task_for_gsi(void);
+int ipa3_set_clock_plan_from_pm(int idx);
+void __ipa_gsi_irq_rx_scedule_poll(struct ipa3_sys_context *sys);
 #endif /* _IPA3_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c
new file mode 100644
index 0000000..66c712c
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.c
@@ -0,0 +1,1301 @@
+/* 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.
+ */
+
+#include <linux/debugfs.h>
+#include "ipa_pm.h"
+#include "ipa_i.h"
+
+static const char *client_state_to_str[IPA_PM_STATE_MAX] = {
+	__stringify(IPA_PM_DEACTIVATED),
+	__stringify(IPA_PM_DEACTIVATE_IN_PROGRESS),
+	__stringify(IPA_PM_ACTIVATE_IN_PROGRESS),
+	__stringify(IPA_PM_ACTIVATED),
+	__stringify(IPA_PM_ACTIVATED_PENDING_DEACTIVATION),
+	__stringify(IPA_PM_ACTIVATED_TIMER_SET),
+	__stringify(IPA_PM_ACTIVATED_PENDING_RESCHEDULE),
+};
+
+static const char *ipa_pm_group_to_str[IPA_PM_GROUP_MAX] = {
+	__stringify(IPA_PM_GROUP_DEFAULT),
+	__stringify(IPA_PM_GROUP_APPS),
+	__stringify(IPA_PM_GROUP_MODEM),
+};
+
+
+#define IPA_PM_DRV_NAME "ipa_pm"
+
+#define IPA_PM_DBG(fmt, args...) \
+	do { \
+		pr_debug(IPA_PM_DRV_NAME " %s:%d " fmt, \
+			__func__, __LINE__, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+			IPA_PM_DRV_NAME " %s:%d " fmt, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+			IPA_PM_DRV_NAME " %s:%d " fmt, ## args); \
+	} while (0)
+#define IPA_PM_DBG_LOW(fmt, args...) \
+	do { \
+		pr_debug(IPA_PM_DRV_NAME " %s:%d " fmt, \
+			__func__, __LINE__, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+			IPA_PM_DRV_NAME " %s:%d " fmt, ## args); \
+	} while (0)
+#define IPA_PM_ERR(fmt, args...) \
+	do { \
+		pr_err(IPA_PM_DRV_NAME " %s:%d " fmt, \
+			__func__, __LINE__, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+			IPA_PM_DRV_NAME " %s:%d " fmt, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+			IPA_PM_DRV_NAME " %s:%d " fmt, ## args); \
+	} while (0)
+#define IPA_PM_DBG_STATE(hdl, name, state) \
+	IPA_PM_DBG_LOW("Client[%d] %s: %s\n", hdl, name, \
+		client_state_to_str[state])
+
+
+#if IPA_PM_MAX_CLIENTS > 32
+#error max client greater than 32 all bitmask types should be changed
+#endif
+
+/*
+ * struct ipa_pm_exception_list - holds information about an exception
+ * @pending: number of clients in exception that have not yet been adctivated
+ * @bitmask: bitmask of the clients in the exception based on handle
+ * @threshold: the threshold values for the exception
+ */
+struct ipa_pm_exception_list {
+	char clients[IPA_PM_MAX_EX_CL];
+	int pending;
+	u32 bitmask;
+	int threshold[IPA_PM_THRESHOLD_MAX];
+};
+
+/*
+ * struct clk_scaling_db - holds information about threshholds and exceptions
+ * @lock: lock the bitmasks and thresholds
+ * @exception_list: pointer to the list of exceptions
+ * @work: work for clock scaling algorithm
+ * @active_client_bitmask: the bits represent handles in the clients array that
+ * contain non-null client
+ * @threshold_size: size of the throughput threshold
+ * @exception_size: size of the exception list
+ * @cur_vote: idx of the threshold
+ * @default_threshold: the thresholds used if no exception passes
+ * @current_threshold: the current threshold of the clock plan
+ */
+struct clk_scaling_db {
+	spinlock_t lock;
+	struct ipa_pm_exception_list exception_list[IPA_PM_EXCEPTION_MAX];
+	struct work_struct work;
+	u32 active_client_bitmask;
+	int threshold_size;
+	int exception_size;
+	int cur_vote;
+	int default_threshold[IPA_PM_THRESHOLD_MAX];
+	int *current_threshold;
+};
+
+/*
+ * ipa_pm state names
+ *
+ * Timer free states:
+ * @IPA_PM_DEACTIVATED: client starting state when registered
+ * @IPA_PM_DEACTIVATE_IN_PROGRESS: deactivate was called in progress of a client
+ *				   activating
+ * @IPA_PM_ACTIVATE_IN_PROGRESS: client is being activated by work_queue
+ * @IPA_PM_ACTIVATED: client is activated without any timers
+ *
+ * Timer set states:
+ * @IPA_PM_ACTIVATED_PENDING_DEACTIVATION: moves to deactivate once timer pass
+ * @IPA_PM_ACTIVATED_TIMER_SET: client was activated while timer was set, so
+ *			 when the timer pass, client will still be activated
+ *@IPA_PM_ACTIVATED_PENDING_RESCHEDULE: state signifying extended timer when
+ *             a client is deferred_deactivated when a time ris still active
+ */
+enum ipa_pm_state {
+	IPA_PM_DEACTIVATED,
+	IPA_PM_DEACTIVATE_IN_PROGRESS,
+	IPA_PM_ACTIVATE_IN_PROGRESS,
+	IPA_PM_ACTIVATED,
+	IPA_PM_ACTIVATED_PENDING_DEACTIVATION,
+	IPA_PM_ACTIVATED_TIMER_SET,
+	IPA_PM_ACTIVATED_PENDING_RESCHEDULE,
+};
+
+#define IPA_PM_STATE_ACTIVE(state) \
+	(state == IPA_PM_ACTIVATED ||\
+		state == IPA_PM_ACTIVATED_PENDING_DEACTIVATION ||\
+		state  == IPA_PM_ACTIVATED_TIMER_SET ||\
+		state == IPA_PM_ACTIVATED_PENDING_RESCHEDULE)
+
+#define IPA_PM_STATE_IN_PROGRESS(state) \
+	(state == IPA_PM_ACTIVATE_IN_PROGRESS \
+		|| state == IPA_PM_DEACTIVATE_IN_PROGRESS)
+
+/*
+ * struct ipa_pm_client - holds information about a specific IPA client
+ * @name: string name of the client
+ * @callback: pointer to the client's callback function
+ * @callback_params: pointer to the client's callback parameters
+ * @state: Activation state of the client
+ * @skip_clk_vote: 0 if client votes for clock when activated, 1 if no vote
+ * @group: the ipa_pm_group the client belongs to
+ * @hdl: handle of the client
+ * @throughput: the throughput of the client for clock scaling
+ * @state_lock: spinlock to lock the pm_states
+ * @activate_work: work for activate (blocking case)
+ * @deactivate work: delayed work for deferred_deactivate function
+ * @complete: generic wait-for-completion handler
+ */
+struct ipa_pm_client {
+	char name[IPA_PM_MAX_EX_CL];
+	void (*callback)(void*, enum ipa_pm_cb_event);
+	void *callback_params;
+	enum ipa_pm_state state;
+	bool skip_clk_vote;
+	int group;
+	int hdl;
+	int throughput;
+	spinlock_t state_lock;
+	struct work_struct activate_work;
+	struct delayed_work deactivate_work;
+	struct completion complete;
+};
+
+/*
+ * struct ipa_pm_ctx - global ctx that will hold the client arrays and tput info
+ * @clients: array to the clients with the handle as its index
+ * @clients_by_pipe: array to the clients with endpoint as the index
+ * @wq: work queue for deferred deactivate, activate, and clk_scaling work
+ 8 @clk_scaling: pointer to clock scaling database
+ * @client_mutex: global mutex to  lock the client arrays
+ * @aggragated_tput: aggragated tput value of all valid activated clients
+ * @group_tput: combined throughput for the groups
+ */
+struct ipa_pm_ctx {
+	struct ipa_pm_client *clients[IPA_PM_MAX_CLIENTS];
+	struct ipa_pm_client *clients_by_pipe[IPA3_MAX_NUM_PIPES];
+	struct workqueue_struct *wq;
+	struct clk_scaling_db clk_scaling;
+	struct mutex client_mutex;
+	int aggregated_tput;
+	int group_tput[IPA_PM_GROUP_MAX];
+};
+
+static struct ipa_pm_ctx *ipa_pm_ctx;
+
+/**
+ * pop_max_from_array() -pop the max and move the last element to where the
+ * max was popped
+ * @arr: array to be searched for max
+ * @n: size of the array
+ *
+ * Returns: max value of the array
+ */
+static int pop_max_from_array(int *arr, int *n)
+{
+	int i;
+	int max, max_idx;
+
+	max_idx = *n - 1;
+	max = 0;
+
+	if (*n == 0)
+		return 0;
+
+	for (i = 0; i < *n; i++) {
+		if (arr[i] > max) {
+			max = arr[i];
+			max_idx = i;
+		}
+	}
+	(*n)--;
+	arr[max_idx] = arr[*n];
+
+	return max;
+}
+
+/**
+ * calculate_throughput() - calculate the aggregated throughput
+ * based on active clients
+ *
+ * Returns: aggregated tput value
+ */
+static int calculate_throughput(void)
+{
+	int client_tput[IPA_PM_MAX_CLIENTS] = { 0 };
+	bool group_voted[IPA_PM_GROUP_MAX] = { false };
+	int i, n;
+	int max, second_max, aggregated_tput;
+	struct ipa_pm_client *client;
+
+	/* Create a basic array to hold throughputs*/
+	for (i = 0, n = 0; i < IPA_PM_MAX_CLIENTS; i++) {
+		client = ipa_pm_ctx->clients[i];
+		if (client != NULL && IPA_PM_STATE_ACTIVE(client->state)) {
+			/* default case */
+			if (client->group == IPA_PM_GROUP_DEFAULT) {
+				client_tput[n++] = client->throughput;
+			} else if (group_voted[client->group] == false) {
+				client_tput[n++] = ipa_pm_ctx->group_tput
+					[client->group];
+				group_voted[client->group] = true;
+			}
+		}
+	}
+	/*the array will only use n+1 spots. n will be the last index used*/
+
+	aggregated_tput = 0;
+
+	/**
+	 * throughput algorithm:
+	 * 1) pop the max and second_max
+	 * 2) add the 2nd max to aggregated tput
+	 * 3) insert the value of max - 2nd max
+	 * 4) repeat until array is of size 1
+	 */
+	while (n > 1) {
+		max = pop_max_from_array(client_tput, &n);
+		second_max = pop_max_from_array(client_tput, &n);
+		client_tput[n++] = max - second_max;
+		aggregated_tput += second_max;
+	}
+
+	IPA_PM_DBG_LOW("Aggregated throughput: %d\n", aggregated_tput);
+
+	return aggregated_tput;
+}
+
+/**
+ * deactivate_client() - turn off the bit in the active client bitmask based on
+ * the handle passed in
+ * @hdl: The index of the client to be deactivated
+ */
+static void deactivate_client(u32 hdl)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ipa_pm_ctx->clk_scaling.lock, flags);
+	ipa_pm_ctx->clk_scaling.active_client_bitmask &= ~(1 << hdl);
+	spin_unlock_irqrestore(&ipa_pm_ctx->clk_scaling.lock, flags);
+	IPA_PM_DBG_LOW("active bitmask: %x\n",
+		ipa_pm_ctx->clk_scaling.active_client_bitmask);
+}
+
+/**
+ * activate_client() - turn on the bit in the active client bitmask based on
+ * the handle passed in
+ * @hdl: The index of the client to be activated
+ */
+static void activate_client(u32 hdl)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ipa_pm_ctx->clk_scaling.lock, flags);
+	ipa_pm_ctx->clk_scaling.active_client_bitmask |= (1 << hdl);
+	spin_unlock_irqrestore(&ipa_pm_ctx->clk_scaling.lock, flags);
+	IPA_PM_DBG_LOW("active bitmask: %x\n",
+		ipa_pm_ctx->clk_scaling.active_client_bitmask);
+}
+
+/**
+ * deactivate_client() - get threshold
+ *
+ * Returns: threshold of the exception that passes or default if none pass
+ */
+static void set_current_threshold(void)
+{
+	int i;
+	struct clk_scaling_db *clk;
+	struct ipa_pm_exception_list *exception;
+	unsigned long flags;
+
+	clk = &ipa_pm_ctx->clk_scaling;
+
+	spin_lock_irqsave(&ipa_pm_ctx->clk_scaling.lock, flags);
+	for (i = 0; i < clk->exception_size; i++) {
+		exception = &clk->exception_list[i];
+		if (exception->pending == 0 && (exception->bitmask
+			& ~clk->active_client_bitmask) == 0) {
+			spin_unlock_irqrestore(&ipa_pm_ctx->clk_scaling.lock,
+				 flags);
+			clk->current_threshold = exception->threshold;
+			IPA_PM_DBG("Exception %d set\n", i);
+			return;
+		}
+	}
+	clk->current_threshold = clk->default_threshold;
+	spin_unlock_irqrestore(&ipa_pm_ctx->clk_scaling.lock, flags);
+}
+
+/**
+ * do_clk_scaling() - set the clock based on the activated clients
+ *
+ * Returns: 0 if success, negative otherwise
+ */
+static int do_clk_scaling(void)
+{
+	int i, tput;
+	int new_th_idx = 1;
+	struct clk_scaling_db *clk_scaling;
+
+	clk_scaling = &ipa_pm_ctx->clk_scaling;
+
+	mutex_lock(&ipa_pm_ctx->client_mutex);
+	IPA_PM_DBG("clock scaling started\n");
+	tput = calculate_throughput();
+	ipa_pm_ctx->aggregated_tput = tput;
+	set_current_threshold();
+
+	mutex_unlock(&ipa_pm_ctx->client_mutex);
+
+	for (i = 0; i < clk_scaling->threshold_size; i++) {
+		if (tput > clk_scaling->current_threshold[i])
+			new_th_idx++;
+	}
+
+	IPA_PM_DBG("old idx was at %d\n", ipa_pm_ctx->clk_scaling.cur_vote);
+
+
+	if (ipa_pm_ctx->clk_scaling.cur_vote != new_th_idx) {
+		ipa_pm_ctx->clk_scaling.cur_vote = new_th_idx;
+		ipa3_set_clock_plan_from_pm(ipa_pm_ctx->clk_scaling.cur_vote);
+	}
+
+	IPA_PM_DBG("new idx is at %d\n", ipa_pm_ctx->clk_scaling.cur_vote);
+
+	return 0;
+}
+
+/**
+ * clock_scaling_func() - set the clock on a work queue
+ */
+static void clock_scaling_func(struct work_struct *work)
+{
+	do_clk_scaling();
+}
+
+/**
+ * activate_work_func - activate a client and vote for clock on a work queue
+ */
+static void activate_work_func(struct work_struct *work)
+{
+	struct ipa_pm_client *client;
+	bool dec_clk = false;
+	unsigned long flags;
+
+	client = container_of(work, struct ipa_pm_client, activate_work);
+	if (!client->skip_clk_vote)
+		IPA_ACTIVE_CLIENTS_INC_SPECIAL(client->name);
+
+	spin_lock_irqsave(&client->state_lock, flags);
+	IPA_PM_DBG_STATE(client->hdl, client->name, client->state);
+	if (client->state == IPA_PM_ACTIVATE_IN_PROGRESS) {
+		client->state = IPA_PM_ACTIVATED;
+	} else if (client->state == IPA_PM_DEACTIVATE_IN_PROGRESS) {
+		client->state = IPA_PM_DEACTIVATED;
+		dec_clk = true;
+	} else {
+		IPA_PM_ERR("unexpected state %d\n", client->state);
+		WARN_ON(1);
+	}
+	spin_unlock_irqrestore(&client->state_lock, flags);
+
+	complete_all(&client->complete);
+
+	if (dec_clk) {
+		ipa_set_tag_process_before_gating(true);
+		if (!client->skip_clk_vote)
+			IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name);
+
+		IPA_PM_DBG_STATE(client->hdl, client->name, client->state);
+		return;
+	}
+
+	activate_client(client->hdl);
+
+	mutex_lock(&ipa_pm_ctx->client_mutex);
+	client->callback(client->callback_params, IPA_PM_CLIENT_ACTIVATED);
+	mutex_unlock(&ipa_pm_ctx->client_mutex);
+
+	IPA_PM_DBG_STATE(client->hdl, client->name, client->state);
+	do_clk_scaling();
+}
+
+/**
+ * delayed_deferred_deactivate_work_func - deferred deactivate on a work queue
+ */
+static void delayed_deferred_deactivate_work_func(struct work_struct *work)
+{
+	struct delayed_work *dwork;
+	struct ipa_pm_client *client;
+	unsigned long flags;
+
+	dwork = container_of(work, struct delayed_work, work);
+	client = container_of(dwork, struct ipa_pm_client, deactivate_work);
+
+	spin_lock_irqsave(&client->state_lock, flags);
+	IPA_PM_DBG_STATE(client->hdl, client->name, client->state);
+	switch (client->state) {
+	case IPA_PM_ACTIVATED_TIMER_SET:
+		client->state = IPA_PM_ACTIVATED;
+		goto bail;
+	case IPA_PM_ACTIVATED_PENDING_RESCHEDULE:
+		queue_delayed_work(ipa_pm_ctx->wq, &client->deactivate_work,
+			msecs_to_jiffies(IPA_PM_DEFERRED_TIMEOUT));
+		client->state = IPA_PM_ACTIVATED_PENDING_DEACTIVATION;
+		goto bail;
+	case IPA_PM_ACTIVATED_PENDING_DEACTIVATION:
+		client->state = IPA_PM_DEACTIVATED;
+		IPA_PM_DBG_STATE(client->hdl, client->name, client->state);
+		spin_unlock_irqrestore(&client->state_lock, flags);
+		ipa_set_tag_process_before_gating(true);
+		if (!client->skip_clk_vote)
+			IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name);
+
+		deactivate_client(client->hdl);
+		do_clk_scaling();
+		return;
+	default:
+		IPA_PM_ERR("unexpected state %d\n", client->state);
+		WARN_ON(1);
+		goto bail;
+	}
+
+bail:
+	IPA_PM_DBG_STATE(client->hdl, client->name, client->state);
+	spin_unlock_irqrestore(&client->state_lock, flags);
+}
+
+static int find_next_open_array_element(const char *name)
+{
+	int i, n;
+
+	n = -ENOBUFS;
+
+	for (i = IPA_PM_MAX_CLIENTS - 1; i >= 0; i--) {
+		if (ipa_pm_ctx->clients[i] == NULL) {
+			n = i;
+			continue;
+		}
+
+		if (strlen(name) == strlen(ipa_pm_ctx->clients[i]->name))
+			if (!strcmp(name, ipa_pm_ctx->clients[i]->name))
+				return -EEXIST;
+	}
+	return n;
+}
+
+/**
+ * add_client_to_exception_list() - add client to the exception list and
+ * update pending if necessary
+ * @hdl: index of the IPA client
+ *
+ * Returns: 0 if success, negative otherwise
+ */
+static int add_client_to_exception_list(u32 hdl)
+{
+	int i;
+	struct ipa_pm_exception_list *exception;
+
+	mutex_lock(&ipa_pm_ctx->client_mutex);
+	for (i = 0; i < ipa_pm_ctx->clk_scaling.exception_size; i++) {
+		exception = &ipa_pm_ctx->clk_scaling.exception_list[i];
+		if (strnstr(exception->clients, ipa_pm_ctx->clients[hdl]->name,
+			strlen(exception->clients))) {
+			exception->pending--;
+
+			if (exception->pending < 0) {
+				WARN_ON(1);
+				exception->pending = 0;
+				mutex_unlock(&ipa_pm_ctx->client_mutex);
+				return -EPERM;
+			}
+			exception->bitmask |= (1 << hdl);
+		}
+	}
+	IPA_PM_DBG("%s added to exception list\n",
+		ipa_pm_ctx->clients[hdl]->name);
+	mutex_unlock(&ipa_pm_ctx->client_mutex);
+
+	return 0;
+}
+
+/**
+ * remove_client_to_exception_list() - remove client from the exception list and
+ * update pending if necessary
+ * @hdl: index of the IPA client
+ *
+ * Returns: 0 if success, negative otherwise
+ */
+static int remove_client_from_exception_list(u32 hdl)
+{
+	int i;
+	struct ipa_pm_exception_list *exception;
+
+	for (i = 0; i < ipa_pm_ctx->clk_scaling.exception_size; i++) {
+		exception = &ipa_pm_ctx->clk_scaling.exception_list[i];
+		if (exception->bitmask & (1 << hdl)) {
+			exception->pending++;
+			exception->bitmask &= ~(1 << hdl);
+		}
+	}
+	IPA_PM_DBG("Client %d removed from exception list\n", hdl);
+
+	return 0;
+}
+
+/**
+ * ipa_pm_init() - initialize  IPA PM Components
+ * @ipa_pm_init_params: parameters needed to fill exceptions and thresholds
+ *
+ * Returns: 0 on success, negative on failure
+ */
+int ipa_pm_init(struct ipa_pm_init_params *params)
+{
+	int i, j;
+	struct clk_scaling_db *clk_scaling;
+
+	if (params == NULL) {
+		IPA_PM_ERR("Invalid Params\n");
+		return -EINVAL;
+	}
+
+	if (params->threshold_size <= 0
+		|| params->threshold_size > IPA_PM_THRESHOLD_MAX) {
+		IPA_PM_ERR("Invalid threshold size\n");
+		return -EINVAL;
+	}
+
+	if (params->exception_size < 0
+		|| params->exception_size > IPA_PM_EXCEPTION_MAX) {
+		IPA_PM_ERR("Invalid exception size\n");
+		return -EINVAL;
+	}
+
+	IPA_PM_DBG("IPA PM initialization started\n");
+
+	if (ipa_pm_ctx != NULL) {
+		IPA_PM_ERR("Already initialized\n");
+		return -EPERM;
+	}
+
+
+	ipa_pm_ctx = kzalloc(sizeof(*ipa_pm_ctx), GFP_KERNEL);
+	if (!ipa_pm_ctx) {
+		IPA_PM_ERR(":kzalloc err.\n");
+		return -ENOMEM;
+	}
+
+	ipa_pm_ctx->wq = create_singlethread_workqueue("ipa_pm_activate");
+	if (!ipa_pm_ctx->wq) {
+		IPA_PM_ERR("create workqueue failed\n");
+		kfree(ipa_pm_ctx);
+		return -ENOMEM;
+	}
+
+	mutex_init(&ipa_pm_ctx->client_mutex);
+
+	/* Populate and init locks in clk_scaling_db */
+	clk_scaling = &ipa_pm_ctx->clk_scaling;
+	spin_lock_init(&clk_scaling->lock);
+	clk_scaling->threshold_size = params->threshold_size;
+	clk_scaling->exception_size = params->exception_size;
+	INIT_WORK(&clk_scaling->work, clock_scaling_func);
+
+	for (i = 0; i < params->threshold_size; i++)
+		clk_scaling->default_threshold[i] =
+			params->default_threshold[i];
+
+	/* Populate exception list*/
+	for (i = 0; i < params->exception_size; i++) {
+		strlcpy(clk_scaling->exception_list[i].clients,
+			params->exceptions[i].usecase, IPA_PM_MAX_EX_CL);
+		IPA_PM_DBG("Usecase: %s\n", params->exceptions[i].usecase);
+
+		/* Parse the commas to count the size of the clients */
+		for (j = 0; j < IPA_PM_MAX_EX_CL &&
+			clk_scaling->exception_list[i].clients[j]; j++) {
+			if (clk_scaling->exception_list[i].clients[j] == ',')
+				clk_scaling->exception_list[i].pending++;
+		}
+
+		clk_scaling->exception_list[i].pending++;
+		IPA_PM_DBG("Pending: %d\n", clk_scaling->
+			exception_list[i].pending);
+
+		/* populate the threshold */
+		for (j = 0; j < params->threshold_size; j++) {
+			clk_scaling->exception_list[i].threshold[j]
+			= params->exceptions[i].threshold[j];
+		}
+
+	}
+	IPA_PM_DBG("initialization success");
+
+	return 0;
+}
+
+int ipa_pm_destroy(void)
+{
+	IPA_PM_DBG("IPA PM destroy started\n");
+
+	if (ipa_pm_ctx == NULL) {
+		IPA_PM_ERR("Already destroyed\n");
+		return -EPERM;
+	}
+
+	destroy_workqueue(ipa_pm_ctx->wq);
+
+	kfree(ipa_pm_ctx);
+	ipa_pm_ctx = NULL;
+
+	return 0;
+}
+
+/**
+ * ipa_rm_delete_register() - register an IPA PM client with the PM
+ * @register_params: params for a client like throughput, callback, etc.
+ * @hdl: int pointer that will be used as an index to access the client
+ *
+ * Returns: 0 on success, negative on failure
+ *
+ * Side effects: *hdl is replaced with the client index or -EEXIST if
+ * client is already registered
+ */
+int ipa_pm_register(struct ipa_pm_register_params *params, u32 *hdl)
+{
+	struct ipa_pm_client *client;
+
+	if (params == NULL || hdl == NULL || params->name == NULL
+		|| params->callback == NULL) {
+		IPA_PM_ERR("Invalid Params\n");
+		return -EINVAL;
+	}
+
+	IPA_PM_DBG("IPA PM registering client\n");
+
+	mutex_lock(&ipa_pm_ctx->client_mutex);
+
+	*hdl = find_next_open_array_element(params->name);
+
+	if (*hdl > IPA_CLIENT_MAX) {
+		mutex_unlock(&ipa_pm_ctx->client_mutex);
+		IPA_PM_ERR("client is already registered or array is full\n");
+		return *hdl;
+	}
+
+	ipa_pm_ctx->clients[*hdl] = kzalloc(sizeof
+		(struct ipa_pm_client), GFP_KERNEL);
+	if (!ipa_pm_ctx->clients[*hdl]) {
+		mutex_unlock(&ipa_pm_ctx->client_mutex);
+		IPA_PM_ERR(":kzalloc err.\n");
+		return -ENOMEM;
+	}
+	mutex_unlock(&ipa_pm_ctx->client_mutex);
+
+	client = ipa_pm_ctx->clients[*hdl];
+
+	spin_lock_init(&client->state_lock);
+
+	INIT_DELAYED_WORK(&client->deactivate_work,
+		delayed_deferred_deactivate_work_func);
+
+	INIT_WORK(&client->activate_work, activate_work_func);
+
+	/* populate fields */
+	strlcpy(client->name, params->name, IPA_PM_MAX_EX_CL);
+	client->callback = params->callback;
+	client->callback_params = params->user_data;
+	client->group = params->group;
+	client->hdl = *hdl;
+	client->skip_clk_vote = params->skip_clk_vote;
+
+	/* add client to exception list */
+	if (add_client_to_exception_list(*hdl)) {
+		ipa_pm_deregister(*hdl);
+		IPA_PM_ERR("Fail to add client to exception_list\n");
+		return -EPERM;
+	}
+
+	IPA_PM_DBG("IPA PM client registered with handle %d\n", *hdl);
+	return 0;
+}
+
+/**
+ * ipa_pm_deregister() - deregister IPA client from the PM
+ * @hdl: index of the client in the array
+ *
+ * Returns: 0 on success, negative on failure
+ */
+int ipa_pm_deregister(u32 hdl)
+{
+	struct ipa_pm_client *client;
+	int i;
+	unsigned long flags;
+
+	if (hdl >= IPA_PM_MAX_CLIENTS) {
+		IPA_PM_ERR("Invalid Param\n");
+		return -EINVAL;
+	}
+
+	if (ipa_pm_ctx->clients[hdl] == NULL) {
+		IPA_PM_ERR("Client is Null\n");
+		return -EINVAL;
+	}
+
+	IPA_PM_DBG("IPA PM deregistering client\n");
+
+	client = ipa_pm_ctx->clients[hdl];
+	spin_lock_irqsave(&client->state_lock, flags);
+	if (IPA_PM_STATE_IN_PROGRESS(client->state)) {
+		spin_unlock_irqrestore(&client->state_lock, flags);
+		wait_for_completion(&client->complete);
+		spin_lock_irqsave(&client->state_lock, flags);
+	}
+
+	if (IPA_PM_STATE_ACTIVE(client->state)) {
+		IPA_PM_DBG("Activated clients cannot be deregistered");
+		spin_unlock_irqrestore(&client->state_lock, flags);
+		return -EPERM;
+	}
+	spin_unlock_irqrestore(&client->state_lock, flags);
+
+	mutex_lock(&ipa_pm_ctx->client_mutex);
+
+	/* nullify pointers in pipe array */
+	for (i = 0; i < IPA3_MAX_NUM_PIPES; i++) {
+		if (ipa_pm_ctx->clients_by_pipe[i] == ipa_pm_ctx->clients[hdl])
+			ipa_pm_ctx->clients_by_pipe[i] = NULL;
+	}
+	kfree(client);
+	ipa_pm_ctx->clients[hdl] = NULL;
+
+	remove_client_from_exception_list(hdl);
+	IPA_PM_DBG("IPA PM client %d deregistered\n", hdl);
+	mutex_unlock(&ipa_pm_ctx->client_mutex);
+
+	return 0;
+}
+
+/**
+ * ipa_pm_associate_ipa_cons_to_client() - add mapping to pipe with ipa cllent
+ * @hdl: index of the client to be mapped
+ * @consumer: the pipe/consumer name to be pipped to the client
+ *
+ * Returns: 0 on success, negative on failure
+ *
+ * Side effects: multiple pipes are allowed to be mapped to a single client
+ */
+int ipa_pm_associate_ipa_cons_to_client(u32 hdl, enum ipa_client_type consumer)
+{
+	int idx;
+
+	if (hdl >= IPA_PM_MAX_CLIENTS || consumer < 0 ||
+		consumer >= IPA_CLIENT_MAX) {
+		IPA_PM_ERR("invalid params\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&ipa_pm_ctx->client_mutex);
+	idx = ipa_get_ep_mapping(consumer);
+
+	IPA_PM_DBG("Mapping pipe %d to client %d\n", idx, hdl);
+
+	if (idx < 0) {
+		mutex_unlock(&ipa_pm_ctx->client_mutex);
+		IPA_PM_DBG("Pipe is not used\n");
+		return 0;
+	}
+
+	if (ipa_pm_ctx->clients[hdl] == NULL) {
+		mutex_unlock(&ipa_pm_ctx->client_mutex);
+		IPA_PM_ERR("Client is NULL\n");
+		return -EPERM;
+	}
+
+	if (ipa_pm_ctx->clients_by_pipe[idx] != NULL) {
+		mutex_unlock(&ipa_pm_ctx->client_mutex);
+		IPA_PM_ERR("Pipe is already mapped\n");
+		return -EPERM;
+	}
+	ipa_pm_ctx->clients_by_pipe[idx] = ipa_pm_ctx->clients[hdl];
+	mutex_unlock(&ipa_pm_ctx->client_mutex);
+
+	IPA_PM_DBG("Pipe %d is mapped to client %d\n", idx, hdl);
+
+	return 0;
+}
+
+static int ipa_pm_activate_helper(struct ipa_pm_client *client, bool sync)
+{
+	struct ipa_active_client_logging_info log_info;
+	int result = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&client->state_lock, flags);
+	IPA_PM_DBG_STATE(client->hdl, client->name, client->state);
+
+	if (IPA_PM_STATE_IN_PROGRESS(client->state)) {
+		if (sync) {
+			spin_unlock_irqrestore(&client->state_lock, flags);
+			wait_for_completion(&client->complete);
+			spin_lock_irqsave(&client->state_lock, flags);
+		} else {
+			client->state = IPA_PM_ACTIVATE_IN_PROGRESS;
+			spin_unlock_irqrestore(&client->state_lock, flags);
+			return -EINPROGRESS;
+		}
+	}
+
+	switch (client->state) {
+	case IPA_PM_ACTIVATED_PENDING_RESCHEDULE:
+	case IPA_PM_ACTIVATED_PENDING_DEACTIVATION:
+		client->state = IPA_PM_ACTIVATED_TIMER_SET;
+	case IPA_PM_ACTIVATED:
+	case IPA_PM_ACTIVATED_TIMER_SET:
+		spin_unlock_irqrestore(&client->state_lock, flags);
+		return 0;
+	case IPA_PM_DEACTIVATED:
+		break;
+	default:
+		IPA_PM_ERR("Invalid State\n");
+		spin_unlock_irqrestore(&client->state_lock, flags);
+		return -EPERM;
+	}
+	IPA_PM_DBG_STATE(client->hdl, client->name, client->state);
+
+	IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, client->name);
+	if (!client->skip_clk_vote) {
+		if (sync) {
+			client->state = IPA_PM_ACTIVATE_IN_PROGRESS;
+			spin_unlock_irqrestore(&client->state_lock, flags);
+			IPA_ACTIVE_CLIENTS_INC_SPECIAL(client->name);
+			spin_lock_irqsave(&client->state_lock, flags);
+		} else
+			result = ipa3_inc_client_enable_clks_no_block
+				 (&log_info);
+	}
+
+	/* we got the clocks */
+	if (result == 0) {
+		client->state = IPA_PM_ACTIVATED;
+		spin_unlock_irqrestore(&client->state_lock, flags);
+		activate_client(client->hdl);
+		if (sync)
+			do_clk_scaling();
+		else
+			queue_work(ipa_pm_ctx->wq,
+				   &ipa_pm_ctx->clk_scaling.work);
+		IPA_PM_DBG_STATE(client->hdl, client->name, client->state);
+		return 0;
+	}
+
+	client->state = IPA_PM_ACTIVATE_IN_PROGRESS;
+	init_completion(&client->complete);
+	queue_work(ipa_pm_ctx->wq, &client->activate_work);
+	spin_unlock_irqrestore(&client->state_lock, flags);
+	IPA_PM_DBG_STATE(client->hdl, client->name, client->state);
+	return -EINPROGRESS;
+}
+
+/**
+ * ipa_pm_activate(): activate ipa client to vote for clock(). Can be called
+ * from atomic context and returns -EINPROGRESS if cannot be done synchronously
+ * @hdl: index of the client in the array
+ *
+ * Returns: 0 on success, -EINPROGRESS if operation cannot be done synchronously
+ * and other negatives on failure
+ */
+int ipa_pm_activate(u32 hdl)
+{
+	if (hdl >= IPA_PM_MAX_CLIENTS || ipa_pm_ctx->clients[hdl] == NULL) {
+		IPA_PM_ERR("Invalid Param\n");
+		return -EINVAL;
+	}
+
+	return ipa_pm_activate_helper(ipa_pm_ctx->clients[hdl], false);
+}
+
+/**
+ * ipa_pm_activate(): activate ipa client to vote for clock synchronously.
+ * Cannot be called from an atomic contex.
+ * @hdl: index of the client in the array
+ *
+ * Returns: 0 on success, negative on failure
+ */
+int ipa_pm_activate_sync(u32 hdl)
+{
+	if (hdl >= IPA_PM_MAX_CLIENTS || ipa_pm_ctx->clients[hdl] == NULL) {
+		IPA_PM_ERR("Invalid Param\n");
+		return -EINVAL;
+	}
+
+	return ipa_pm_activate_helper(ipa_pm_ctx->clients[hdl], true);
+}
+
+/**
+ * ipa_pm_deferred_deactivate(): schedule a timer to deactivate client and
+ * devote clock. Can be called from atomic context (asynchronously)
+ * @hdl: index of the client in the array
+ *
+ * Returns: 0 on success, negative on failure
+ */
+int ipa_pm_deferred_deactivate(u32 hdl)
+{
+	struct ipa_pm_client *client;
+	unsigned long flags;
+
+	if (hdl >= IPA_PM_MAX_CLIENTS || ipa_pm_ctx->clients[hdl] == NULL) {
+		IPA_PM_ERR("Invalid Param\n");
+		return -EINVAL;
+	}
+
+	client = ipa_pm_ctx->clients[hdl];
+	IPA_PM_DBG_STATE(hdl, client->name, client->state);
+
+	spin_lock_irqsave(&client->state_lock, flags);
+	switch (client->state) {
+	case IPA_PM_ACTIVATE_IN_PROGRESS:
+		client->state = IPA_PM_DEACTIVATE_IN_PROGRESS;
+	case IPA_PM_DEACTIVATED:
+		IPA_PM_DBG_STATE(hdl, client->name, client->state);
+		spin_unlock_irqrestore(&client->state_lock, flags);
+		return 0;
+	case IPA_PM_ACTIVATED:
+		client->state = IPA_PM_ACTIVATED_PENDING_DEACTIVATION;
+		queue_delayed_work(ipa_pm_ctx->wq, &client->deactivate_work,
+			msecs_to_jiffies(IPA_PM_DEFERRED_TIMEOUT));
+		break;
+	case IPA_PM_ACTIVATED_TIMER_SET:
+	case IPA_PM_ACTIVATED_PENDING_DEACTIVATION:
+		client->state = IPA_PM_ACTIVATED_PENDING_RESCHEDULE;
+	case IPA_PM_DEACTIVATE_IN_PROGRESS:
+	case IPA_PM_ACTIVATED_PENDING_RESCHEDULE:
+		break;
+	}
+	IPA_PM_DBG_STATE(hdl, client->name, client->state);
+	spin_unlock_irqrestore(&client->state_lock, flags);
+
+	return 0;
+}
+
+/**
+ * ipa_pm_deactivate_all_deferred(): Cancel the deferred deactivation timer and
+ * immediately devotes for IPA clocks
+ *
+ * Returns: 0 on success, negative on failure
+ */
+int ipa_pm_deactivate_all_deferred(void)
+{
+	int i;
+	bool run_algorithm = false;
+	struct ipa_pm_client *client;
+	unsigned long flags;
+
+	for (i = 0; i < IPA_PM_MAX_CLIENTS; i++) {
+		client = ipa_pm_ctx->clients[i];
+
+		if (client == NULL)
+			continue;
+
+		cancel_delayed_work_sync(&client->deactivate_work);
+
+		if (IPA_PM_STATE_IN_PROGRESS(client->state)) {
+			wait_for_completion(&client->complete);
+			continue;
+		}
+
+		spin_lock_irqsave(&client->state_lock, flags);
+		IPA_PM_DBG_STATE(client->hdl, client->name, client->state);
+
+		if (client->state == IPA_PM_ACTIVATED_TIMER_SET) {
+			client->state = IPA_PM_ACTIVATED;
+			IPA_PM_DBG_STATE(client->hdl, client->name,
+				client->state);
+			spin_unlock_irqrestore(&client->state_lock, flags);
+		} else if (client->state ==
+			IPA_PM_ACTIVATED_PENDING_DEACTIVATION ||
+			IPA_PM_ACTIVATED_PENDING_RESCHEDULE) {
+			run_algorithm = true;
+			client->state = IPA_PM_DEACTIVATED;
+			IPA_PM_DBG_STATE(client->hdl, client->name,
+				client->state);
+			spin_unlock_irqrestore(&client->state_lock, flags);
+			ipa_set_tag_process_before_gating(true);
+			if (!client->skip_clk_vote)
+				IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name);
+			deactivate_client(client->hdl);
+		} else /* if activated or deactivated, we do nothing */
+			spin_unlock_irqrestore(&client->state_lock, flags);
+	}
+
+	if (run_algorithm)
+		do_clk_scaling();
+
+	return 0;
+}
+
+/**
+ * ipa_pm_deactivate_sync(): deactivate ipa client and devote clock. Cannot be
+ * called from atomic context.
+ * @hdl: index of the client in the array
+ *
+ * Returns: 0 on success, negative on failure
+ */
+int ipa_pm_deactivate_sync(u32 hdl)
+{
+	struct ipa_pm_client *client = ipa_pm_ctx->clients[hdl];
+	unsigned long flags;
+
+	if (hdl >= IPA_PM_MAX_CLIENTS || ipa_pm_ctx->clients[hdl] == NULL) {
+		IPA_PM_ERR("Invalid Param\n");
+		return -EINVAL;
+	}
+
+	cancel_delayed_work_sync(&client->deactivate_work);
+
+	if (IPA_PM_STATE_IN_PROGRESS(client->state))
+		wait_for_completion(&client->complete);
+
+	spin_lock_irqsave(&client->state_lock, flags);
+	IPA_PM_DBG_STATE(hdl, client->name, client->state);
+
+	if (client->state == IPA_PM_DEACTIVATED) {
+		spin_unlock_irqrestore(&client->state_lock, flags);
+		return 0;
+	}
+
+	spin_unlock_irqrestore(&client->state_lock, flags);
+
+	/* else case (Deactivates all Activated cases)*/
+	ipa_set_tag_process_before_gating(true);
+	if (!client->skip_clk_vote)
+		IPA_ACTIVE_CLIENTS_DEC_SPECIAL(client->name);
+
+	spin_lock_irqsave(&client->state_lock, flags);
+	client->state = IPA_PM_DEACTIVATED;
+	IPA_PM_DBG_STATE(hdl, client->name, client->state);
+	spin_unlock_irqrestore(&client->state_lock, flags);
+	deactivate_client(hdl);
+	do_clk_scaling();
+
+	return 0;
+}
+
+/**
+ * ipa_pm_handle_suspend(): calls the callbacks of suspended clients to wake up
+ * @pipe_bitmask: the bits represent the indexes of the clients to be woken up
+ *
+ * Returns: 0 on success, negative on failure
+ */
+int ipa_pm_handle_suspend(u32 pipe_bitmask)
+{
+	int i;
+	struct ipa_pm_client *client;
+	bool client_notified[IPA_PM_MAX_CLIENTS] = { false };
+
+	IPA_PM_DBG_LOW("bitmask: %d",  pipe_bitmask);
+
+	if (pipe_bitmask == 0)
+		return 0;
+
+	mutex_lock(&ipa_pm_ctx->client_mutex);
+	for (i = 0; i < IPA3_MAX_NUM_PIPES; i++) {
+		if (pipe_bitmask & (1 << i)) {
+			client = ipa_pm_ctx->clients_by_pipe[i];
+			if (client && client_notified[client->hdl] == false) {
+				client->callback(client->callback_params,
+					IPA_PM_REQUEST_WAKEUP);
+				client_notified[client->hdl] = true;
+			}
+		}
+	}
+	mutex_unlock(&ipa_pm_ctx->client_mutex);
+	return 0;
+}
+
+/**
+ * ipa_pm_set_perf_profile(): Adds/changes the throughput requirement to IPA PM
+ * to be used for clock scaling
+ * @hdl: index of the client in the array
+ * @throughput: the new throughput value to be set for that client
+ *
+ * Returns: 0 on success, negative on failure
+ */
+int ipa_pm_set_perf_profile(u32 hdl, int throughput)
+{
+	struct ipa_pm_client *client = ipa_pm_ctx->clients[hdl];
+	unsigned long flags;
+
+	if (hdl >= IPA_PM_MAX_CLIENTS || ipa_pm_ctx->clients[hdl] == NULL
+		|| throughput < 0) {
+		IPA_PM_ERR("Invalid Params\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&ipa_pm_ctx->client_mutex);
+	if (client->group == IPA_PM_GROUP_DEFAULT)
+		IPA_PM_DBG_LOW("Old throughput: %d\n",  client->throughput);
+	else
+		IPA_PM_DBG_LOW("old Group %d throughput: %d\n",
+			client->group, ipa_pm_ctx->group_tput[client->group]);
+
+	if (client->group == IPA_PM_GROUP_DEFAULT)
+		client->throughput = throughput;
+	else
+		ipa_pm_ctx->group_tput[client->group] = throughput;
+
+	if (client->group == IPA_PM_GROUP_DEFAULT)
+		IPA_PM_DBG_LOW("New throughput: %d\n",  client->throughput);
+	else
+		IPA_PM_DBG_LOW("New Group %d throughput: %d\n",
+			client->group, ipa_pm_ctx->group_tput[client->group]);
+	mutex_unlock(&ipa_pm_ctx->client_mutex);
+
+	spin_lock_irqsave(&client->state_lock, flags);
+	if (IPA_PM_STATE_ACTIVE(client->state || (client->group !=
+			IPA_PM_GROUP_DEFAULT))) {
+		spin_unlock_irqrestore(&client->state_lock, flags);
+		do_clk_scaling();
+		return 0;
+	}
+	spin_unlock_irqrestore(&client->state_lock, flags);
+
+	return 0;
+}
+
+/**
+ * ipa_pm_stat() - print PM stat
+ * @buf: [in] The user buff used to print
+ * @size: [in] The size of buf
+ * Returns: number of bytes used on success, negative on failure
+ *
+ * This function is called by ipa_debugfs in order to receive
+ * a picture of the clients in the PM and the throughput, threshold and cur vote
+ */
+int ipa_pm_stat(char *buf, int size)
+{
+	struct ipa_pm_client *client;
+	struct clk_scaling_db *clk = &ipa_pm_ctx->clk_scaling;
+	int i, j, tput, cnt = 0, result = 0;
+	unsigned long flags;
+
+	if (!buf || size < 0)
+		return -EINVAL;
+
+	mutex_lock(&ipa_pm_ctx->client_mutex);
+
+	result = scnprintf(buf + cnt, size - cnt, "\n\nCurrent threshold: [");
+	cnt += result;
+
+	for (i = 0; i < clk->threshold_size; i++) {
+		result = scnprintf(buf + cnt, size - cnt,
+			"%d, ", clk->current_threshold[i]);
+		cnt += result;
+	}
+
+	result = scnprintf(buf + cnt, size - cnt, "\b\b]\n");
+	cnt += result;
+
+	result = scnprintf(buf + cnt, size - cnt,
+		"Aggregated tput: %d, Cur vote: %d",
+		ipa_pm_ctx->aggregated_tput, clk->cur_vote);
+	cnt += result;
+
+	result = scnprintf(buf + cnt, size - cnt, "\n\nRegistered Clients:\n");
+	cnt += result;
+
+
+	for (i = 0; i < IPA_PM_MAX_CLIENTS; i++) {
+		client = ipa_pm_ctx->clients[i];
+
+		if (client == NULL)
+			continue;
+
+		spin_lock_irqsave(&client->state_lock, flags);
+		if (client->group == IPA_PM_GROUP_DEFAULT)
+			tput = client->throughput;
+		else
+			tput = ipa_pm_ctx->group_tput[client->group];
+
+		result = scnprintf(buf + cnt, size - cnt,
+		"Client[%d]: %s State:%s\nGroup: %s Throughput: %d Pipes: ",
+			i, client->name, client_state_to_str[client->state],
+			ipa_pm_group_to_str[client->group], tput);
+		cnt += result;
+
+		for (j = 0; j < IPA3_MAX_NUM_PIPES; j++) {
+			if (ipa_pm_ctx->clients_by_pipe[j] == client) {
+				result = scnprintf(buf + cnt, size - cnt,
+					"%d, ", j);
+				cnt += result;
+			}
+		}
+
+		result = scnprintf(buf + cnt, size - cnt, "\b\b\n\n");
+		cnt += result;
+		spin_unlock_irqrestore(&client->state_lock, flags);
+	}
+	mutex_unlock(&ipa_pm_ctx->client_mutex);
+
+	return cnt;
+}
+
+/**
+ * ipa_pm_exceptions_stat() - print PM exceptions stat
+ * @buf: [in] The user buff used to print
+ * @size: [in] The size of buf
+ * Returns: number of bytes used on success, negative on failure
+ *
+ * This function is called by ipa_debugfs in order to receive
+ * a full picture of the exceptions in the PM
+ */
+int ipa_pm_exceptions_stat(char *buf, int size)
+{
+	int i, j, cnt = 0, result = 0;
+	struct ipa_pm_exception_list *exception;
+
+	if (!buf || size < 0)
+		return -EINVAL;
+
+	result = scnprintf(buf + cnt, size - cnt, "\n");
+	cnt += result;
+
+	mutex_lock(&ipa_pm_ctx->client_mutex);
+	for (i = 0; i < ipa_pm_ctx->clk_scaling.exception_size; i++) {
+		exception = &ipa_pm_ctx->clk_scaling.exception_list[i];
+		if (exception == NULL) {
+			result = scnprintf(buf + cnt, size - cnt,
+			"Exception %d is NULL\n\n", i);
+			cnt += result;
+			continue;
+		}
+
+		result = scnprintf(buf + cnt, size - cnt,
+			"Exception %d: %s\nPending: %d Bitmask: %d Threshold: ["
+			, i, exception->clients, exception->pending,
+			exception->bitmask);
+		cnt += result;
+		for (j = 0; j < ipa_pm_ctx->clk_scaling.threshold_size; j++) {
+			result = scnprintf(buf + cnt, size - cnt,
+				"%d, ", exception->threshold[j]);
+			cnt += result;
+		}
+		result = scnprintf(buf + cnt, size - cnt, "\b\b]\n\n");
+		cnt += result;
+	}
+	mutex_unlock(&ipa_pm_ctx->client_mutex);
+
+	return cnt;
+}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h
new file mode 100644
index 0000000..ca022b5
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_pm.h
@@ -0,0 +1,110 @@
+/* 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 _IPA_PM_H_
+#define _IPA_PM_H_
+
+#include <linux/msm_ipa.h>
+
+/* internal to ipa */
+#define IPA_PM_MAX_CLIENTS 10
+#define IPA_PM_MAX_EX_CL 64
+#define IPA_PM_THRESHOLD_MAX 2
+#define IPA_PM_EXCEPTION_MAX 2
+#define IPA_PM_DEFERRED_TIMEOUT 100
+#define IPA_PM_STATE_MAX 7
+
+/*
+ * ipa_pm group names
+ *
+ * Default stands for individual clients while other groups share one throughput
+ * Some groups also have special flags like modem which do not vote for clock
+ * but is accounted for in clock scaling while activated
+ */
+enum ipa_pm_group {
+	IPA_PM_GROUP_DEFAULT,
+	IPA_PM_GROUP_APPS,
+	IPA_PM_GROUP_MODEM,
+	IPA_PM_GROUP_MAX,
+};
+
+/*
+ * ipa_pm_cb_event
+ *
+ * specifies what kind of callback is being called.
+ * IPA_PM_CLIENT_ACTIVATED: the client has completed asynchronous activation
+ * IPA_PM_REQUEST_WAKEUP: wake up the client after it has been suspended
+ */
+enum ipa_pm_cb_event {
+	IPA_PM_CLIENT_ACTIVATED,
+	IPA_PM_REQUEST_WAKEUP,
+	IPA_PM_CB_EVENT_MAX,
+};
+
+/*
+ * struct ipa_pm_exception - clients included in exception and its threshold
+ * @usecase: comma separated client names
+ * @threshold: the threshold values for the exception
+ */
+struct ipa_pm_exception {
+	const char *usecase;
+	int threshold[IPA_PM_THRESHOLD_MAX];
+};
+
+/*
+ * struct ipa_pm_init_params - parameters needed for initializng the pm
+ * @default_threshold: the thresholds used if no exception passes
+ * @threshold_size: size of the threshold
+ * @exceptions: list of exceptions  for the pm
+ * @exception_size: size of the exception_list
+ */
+struct ipa_pm_init_params {
+	int default_threshold[IPA_PM_THRESHOLD_MAX];
+	int threshold_size;
+	struct ipa_pm_exception exceptions[IPA_PM_EXCEPTION_MAX];
+	int exception_size;
+};
+
+/*
+ * struct ipa_pm_register_params - parameters needed to register a client
+ * @name: name of the client
+ * @callback: pointer to the client's callback function
+ * @user_data: pointer to the client's callback parameters
+ * @group: group number of the client
+ * @skip_clk_vote: 0 if client votes for clock when activated, 1 if no vote
+ */
+struct ipa_pm_register_params {
+	const char *name;
+	void (*callback)(void*, enum ipa_pm_cb_event);
+	void *user_data;
+	enum ipa_pm_group group;
+	bool skip_clk_vote;
+};
+
+int ipa_pm_register(struct ipa_pm_register_params *params, u32 *hdl);
+int ipa_pm_associate_ipa_cons_to_client(u32 hdl, enum ipa_client_type consumer);
+int ipa_pm_activate(u32 hdl);
+int ipa_pm_activate_sync(u32 hdl);
+int ipa_pm_deferred_deactivate(u32 hdl);
+int ipa_pm_deactivate_sync(u32 hdl);
+int ipa_pm_set_perf_profile(u32 hdl, int throughput);
+int ipa_pm_deregister(u32 hdl);
+
+/* IPA Internal Functions */
+int ipa_pm_init(struct ipa_pm_init_params *params);
+int ipa_pm_destroy(void);
+int ipa_pm_handle_suspend(u32 pipe_bitmask);
+int ipa_pm_deactivate_all_deferred(void);
+int ipa_pm_stat(char *buf, int size);
+int ipa_pm_exceptions_stat(char *buf, int size);
+
+#endif /* _IPA_PM_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
index 61bccc6..4e8c233 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
@@ -1214,7 +1214,6 @@
 /* voting for bus BW to ipa_rm*/
 int ipa3_vote_for_bus_bw(uint32_t *bw_mbps)
 {
-	struct ipa_rm_perf_profile profile;
 	int ret;
 
 	if (bw_mbps == NULL) {
@@ -1222,16 +1221,13 @@
 		return -EINVAL;
 	}
 
-	memset(&profile, 0, sizeof(profile));
-	profile.max_supported_bandwidth_mbps = *bw_mbps;
-	ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_Q6_PROD,
-			&profile);
+	ret = ipa3_wwan_set_modem_perf_profile(*bw_mbps);
 	if (ret)
 		IPAWANERR("Failed to set perf profile to BW %u\n",
-			profile.max_supported_bandwidth_mbps);
+			*bw_mbps);
 	else
 		IPAWANDBG("Succeeded to set perf profile to BW %u\n",
-			profile.max_supported_bandwidth_mbps);
+			*bw_mbps);
 
 	return ret;
 }
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
index d5d8503..d3a4ba0 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
@@ -207,6 +207,10 @@
 
 void ipa3_q6_handshake_complete(bool ssr_bootup);
 
+int ipa3_wwan_set_modem_perf_profile(int throughput);
+
+int ipa3_wwan_set_modem_state(struct wan_ioctl_notify_wan_state *state);
+
 void ipa3_qmi_init(void);
 
 void ipa3_qmi_cleanup(void);
@@ -323,6 +327,11 @@
 
 static inline void ipa3_q6_handshake_complete(bool ssr_bootup) { }
 
+static inline int ipa3_wwan_set_modem_perf_profile(int throughput)
+{
+	return -EPERM;
+}
+
 static inline void ipa3_qmi_init(void)
 {
 }
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 5206337..f717264 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -4855,11 +4855,8 @@
 		IPADBG("ch %ld not empty\n", ep->gsi_chan_hdl);
 		/* queue a work to start polling if don't have one */
 		atomic_set(&ipa3_ctx->transport_pm.eot_activity, 1);
-		if (!atomic_read(&ep->sys->curr_polling_state)) {
-			ipa3_inc_acquire_wakelock();
-			atomic_set(&ep->sys->curr_polling_state, 1);
-			queue_work(ep->sys->wq, &ep->sys->work);
-		}
+		if (!atomic_read(&ep->sys->curr_polling_state))
+			__ipa_gsi_irq_rx_scedule_poll(ep->sys);
 	}
 }
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index dc71414..74f5bbd 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -1961,20 +1961,3 @@
 
 	valmask->mask = valmask->val;
 }
-
-void ipahal_get_status_ep_valmask(int pipe_num,
-	struct ipahal_reg_valmask *valmask)
-{
-	if (!valmask) {
-		IPAHAL_ERR("Input error\n");
-		return;
-	}
-
-	valmask->val =
-		(pipe_num & IPA_ENDP_STATUS_n_STATUS_ENDP_BMSK) <<
-		IPA_ENDP_STATUS_n_STATUS_ENDP_SHFT;
-
-	valmask->mask =
-		IPA_ENDP_STATUS_n_STATUS_ENDP_BMSK <<
-		IPA_ENDP_STATUS_n_STATUS_ENDP_SHFT;
-}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
index a2864cd..df3c976 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
@@ -541,8 +541,6 @@
 void ipahal_get_fltrt_hash_flush_valmask(
 	struct ipahal_reg_fltrt_hash_flush *flush,
 	struct ipahal_reg_valmask *valmask);
-void ipahal_get_status_ep_valmask(int pipe_num,
-	struct ipahal_reg_valmask *valmask);
 
 #endif /* _IPAHAL_REG_H_ */
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index 5095e1f..f08e1e3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -142,6 +142,9 @@
 	u32 ipa3_to_apps_hdl;
 	struct mutex pipe_handle_guard;
 	struct mutex add_mux_channel_lock;
+	u32 pm_hdl;
+	u32 q6_pm_hdl;
+	u32 q6_teth_pm_hdl;
 };
 
 static struct rmnet_ipa3_context *rmnet_ipa3_ctx;
@@ -1134,8 +1137,14 @@
 
 send:
 	/* IPA_RM checking start */
-	ret = ipa_rm_inactivity_timer_request_resource(
-		IPA_RM_RESOURCE_WWAN_0_PROD);
+	if (ipa3_ctx->use_ipa_pm) {
+		/* activate the modem pm for clock scaling */
+		ipa_pm_activate(rmnet_ipa3_ctx->q6_pm_hdl);
+		ret = ipa_pm_activate(rmnet_ipa3_ctx->pm_hdl);
+	} else {
+		ret = ipa_rm_inactivity_timer_request_resource(
+			IPA_RM_RESOURCE_WWAN_0_PROD);
+	}
 	if (ret == -EINPROGRESS) {
 		netif_stop_queue(dev);
 		return NETDEV_TX_BUSY;
@@ -1164,9 +1173,15 @@
 	dev->stats.tx_bytes += skb->len;
 	ret = NETDEV_TX_OK;
 out:
-	if (atomic_read(&wwan_ptr->outstanding_pkts) == 0)
-		ipa_rm_inactivity_timer_release_resource(
-			IPA_RM_RESOURCE_WWAN_0_PROD);
+	if (atomic_read(&wwan_ptr->outstanding_pkts) == 0) {
+		if (ipa3_ctx->use_ipa_pm) {
+			ipa_pm_deferred_deactivate(rmnet_ipa3_ctx->pm_hdl);
+			ipa_pm_deferred_deactivate(rmnet_ipa3_ctx->q6_pm_hdl);
+		} else {
+			ipa_rm_inactivity_timer_release_resource(
+				IPA_RM_RESOURCE_WWAN_0_PROD);
+		}
+	}
 	return ret;
 }
 
@@ -1218,9 +1233,15 @@
 		netif_wake_queue(wwan_ptr->net);
 	}
 
-	if (atomic_read(&wwan_ptr->outstanding_pkts) == 0)
-		ipa_rm_inactivity_timer_release_resource(
+	if (atomic_read(&wwan_ptr->outstanding_pkts) == 0) {
+		if (ipa3_ctx->use_ipa_pm) {
+			ipa_pm_deferred_deactivate(rmnet_ipa3_ctx->pm_hdl);
+			ipa_pm_deferred_deactivate(rmnet_ipa3_ctx->q6_pm_hdl);
+		} else {
+			ipa_rm_inactivity_timer_release_resource(
 			IPA_RM_RESOURCE_WWAN_0_PROD);
+		}
+	}
 	__netif_tx_unlock_bh(netdev_get_tx_queue(dev, 0));
 	dev_kfree_skb_any(skb);
 }
@@ -1858,6 +1879,91 @@
 		return;
 	}
 }
+
+int ipa3_wwan_set_modem_state(struct wan_ioctl_notify_wan_state *state)
+{
+	if (!state)
+		return -EINVAL;
+
+	if (!ipa_pm_is_used())
+		return 0;
+
+	if (state->up)
+		return ipa_pm_activate_sync(rmnet_ipa3_ctx->q6_teth_pm_hdl);
+	else
+		return ipa_pm_deactivate_sync(rmnet_ipa3_ctx->q6_teth_pm_hdl);
+}
+
+/**
+ * ipa3_q6_register_pm - Register modem clients for PM
+ *
+ * This function will register 2 client with IPA PM to represent modem
+ * in clock scaling calculation:
+ *	- "EMB MODEM" - this client will be activated with embedded traffic
+	- "TETH MODEM" - this client we be activated by IPACM on offload to
+	  modem.
+*/
+static int ipa3_q6_register_pm(void)
+{
+	int result;
+	struct ipa_pm_register_params pm_reg;
+
+	memset(&pm_reg, 0, sizeof(pm_reg));
+	pm_reg.name = "EMB MODEM";
+	pm_reg.group = IPA_PM_GROUP_MODEM;
+	pm_reg.skip_clk_vote = true;
+	result = ipa_pm_register(&pm_reg, &rmnet_ipa3_ctx->q6_pm_hdl);
+	if (result) {
+		IPAERR("failed to create IPA PM client %d\n", result);
+		return result;
+	}
+
+	pm_reg.name = "TETH MODEM";
+	pm_reg.group = IPA_PM_GROUP_MODEM;
+	pm_reg.skip_clk_vote = true;
+	result = ipa_pm_register(&pm_reg, &rmnet_ipa3_ctx->q6_teth_pm_hdl);
+	if (result) {
+		IPAERR("failed to create IPA PM client %d\n", result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void ipa3_q6_deregister_pm(void)
+{
+	ipa_pm_deactivate_sync(rmnet_ipa3_ctx->q6_pm_hdl);
+	ipa_pm_deregister(rmnet_ipa3_ctx->q6_pm_hdl);
+}
+
+int ipa3_wwan_set_modem_perf_profile(int throughput)
+{
+	struct ipa_rm_perf_profile profile;
+	int ret;
+
+	ret = ipa_pm_set_perf_profile(rmnet_ipa3_ctx->q6_pm_hdl, throughput);
+	if (ret)
+		return ret;
+	return ipa_pm_set_perf_profile(rmnet_ipa3_ctx->q6_teth_pm_hdl,
+		throughput);
+
+	if (ipa3_ctx->use_ipa_pm) {
+		ret = ipa_pm_set_perf_profile(rmnet_ipa3_ctx->q6_pm_hdl,
+			throughput);
+		if (ret)
+			return ret;
+		ret = ipa_pm_set_perf_profile(rmnet_ipa3_ctx->q6_teth_pm_hdl,
+			throughput);
+	} else {
+		memset(&profile, 0, sizeof(profile));
+		profile.max_supported_bandwidth_mbps = throughput;
+		ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_Q6_PROD,
+			&profile);
+	}
+
+	return ret;
+}
+
 static int ipa3_q6_initialize_rm(void)
 {
 	struct ipa_rm_create_params create_params;
@@ -2075,6 +2181,120 @@
 	schedule_work(&ipa3_scheduled_probe);
 }
 
+static void ipa_pm_wwan_pm_cb(void *p, enum ipa_pm_cb_event event)
+{
+	struct net_device *dev = (struct net_device *)p;
+	struct ipa3_wwan_private *wwan_ptr = netdev_priv(dev);
+
+	IPAWANDBG_LOW("event %d\n", event);
+	switch (event) {
+	case IPA_PM_CLIENT_ACTIVATED:
+		if (wwan_ptr->device_status == WWAN_DEVICE_INACTIVE) {
+			complete_all(&wwan_ptr->resource_granted_completion);
+			break;
+		}
+		ipa3_rm_resource_granted(dev);
+		break;
+	default:
+		pr_err("%s: unknown event %d\n", __func__, event);
+		break;
+	}
+}
+
+static int ipa3_wwan_register_netdev_pm_client(struct net_device *dev)
+{
+	int result;
+	struct ipa_pm_register_params pm_reg;
+
+	memset(&pm_reg, 0, sizeof(pm_reg));
+	pm_reg.name = IPA_NETDEV()->name;
+	pm_reg.user_data = dev;
+	pm_reg.callback = ipa_pm_wwan_pm_cb;
+	pm_reg.group = IPA_PM_GROUP_APPS;
+	result = ipa_pm_register(&pm_reg, &rmnet_ipa3_ctx->pm_hdl);
+	if (result) {
+		IPAERR("failed to create IPA PM client %d\n", result);
+			return result;
+	}
+	return 0;
+}
+
+static void ipa3_wwan_deregister_netdev_pm_client(void)
+{
+	ipa_pm_deactivate_sync(rmnet_ipa3_ctx->pm_hdl);
+	ipa_pm_deregister(rmnet_ipa3_ctx->pm_hdl);
+}
+
+static int ipa3_wwan_create_wwan_rm_resource(struct net_device *dev)
+{
+	struct ipa_rm_create_params ipa_rm_params;
+	struct ipa_rm_perf_profile profile;
+	int ret;
+
+	memset(&ipa_rm_params, 0, sizeof(struct ipa_rm_create_params));
+	ipa_rm_params.name = IPA_RM_RESOURCE_WWAN_0_PROD;
+	ipa_rm_params.reg_params.user_data = dev;
+	ipa_rm_params.reg_params.notify_cb = ipa3_rm_notify;
+	ret = ipa_rm_create_resource(&ipa_rm_params);
+	if (ret) {
+		pr_err("%s: unable to create resourse %d in IPA RM\n",
+			__func__, IPA_RM_RESOURCE_WWAN_0_PROD);
+		return ret;
+	}
+	ret = ipa_rm_inactivity_timer_init(IPA_RM_RESOURCE_WWAN_0_PROD,
+		IPA_RM_INACTIVITY_TIMER);
+	if (ret) {
+		pr_err("%s: ipa rm timer init failed %d on resourse %d\n",
+			__func__, ret, IPA_RM_RESOURCE_WWAN_0_PROD);
+		goto timer_init_err;
+	}
+	/* add dependency */
+	ret = ipa_rm_add_dependency(IPA_RM_RESOURCE_WWAN_0_PROD,
+		IPA_RM_RESOURCE_Q6_CONS);
+	if (ret)
+		goto add_dpnd_err;
+	/* setup Performance profile */
+	memset(&profile, 0, sizeof(profile));
+	profile.max_supported_bandwidth_mbps = IPA_APPS_MAX_BW_IN_MBPS;
+	ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WWAN_0_PROD,
+		&profile);
+	if (ret)
+		goto set_perf_err;
+
+	return 0;
+
+set_perf_err:
+	ipa_rm_delete_dependency(IPA_RM_RESOURCE_WWAN_0_PROD,
+		IPA_RM_RESOURCE_Q6_CONS);
+add_dpnd_err:
+	ipa_rm_inactivity_timer_destroy(
+		IPA_RM_RESOURCE_WWAN_0_PROD); /* IPA_RM */
+timer_init_err:
+	ipa_rm_delete_resource(IPA_RM_RESOURCE_WWAN_0_PROD);
+	return ret;
+}
+
+static void ipa3_wwan_delete_wwan_rm_resource(void)
+{
+	int ret;
+
+	ret = ipa_rm_delete_dependency(IPA_RM_RESOURCE_WWAN_0_PROD,
+		IPA_RM_RESOURCE_Q6_CONS);
+	if (ret < 0)
+		IPAWANERR("Error deleting dependency %d->%d, ret=%d\n",
+		IPA_RM_RESOURCE_WWAN_0_PROD, IPA_RM_RESOURCE_Q6_CONS,
+		ret);
+	ret = ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WWAN_0_PROD);
+	if (ret < 0)
+		IPAWANERR(
+		"Error ipa_rm_inactivity_timer_destroy resource %d, ret=%d\n",
+		IPA_RM_RESOURCE_WWAN_0_PROD, ret);
+	ret = ipa_rm_delete_resource(IPA_RM_RESOURCE_WWAN_0_PROD);
+	if (ret < 0)
+		IPAWANERR("Error deleting resource %d, ret=%d\n",
+		IPA_RM_RESOURCE_WWAN_0_PROD, ret);
+}
+
 /**
  * ipa3_wwan_probe() - Initialized the module and registers as a
  * network interface to the network stack
@@ -2092,8 +2312,6 @@
 {
 	int ret, i;
 	struct net_device *dev;
-	struct ipa_rm_create_params ipa_rm_params;	/* IPA_RM */
-	struct ipa_rm_perf_profile profile;			/* IPA_RM */
 
 	pr_info("rmnet_ipa3 started initialization\n");
 
@@ -2187,7 +2405,10 @@
 
 	if (!atomic_read(&rmnet_ipa3_ctx->is_ssr)) {
 		/* IPA_RM configuration starts */
-		ret = ipa3_q6_initialize_rm();
+		if (ipa3_ctx->use_ipa_pm)
+			ret = ipa3_q6_register_pm();
+		else
+			ret = ipa3_q6_initialize_rm();
 		if (ret) {
 			IPAWANERR("%s: ipa3_q6_initialize_rm failed, ret: %d\n",
 				__func__, ret);
@@ -2195,36 +2416,14 @@
 		}
 	}
 
-	memset(&ipa_rm_params, 0, sizeof(struct ipa_rm_create_params));
-	ipa_rm_params.name = IPA_RM_RESOURCE_WWAN_0_PROD;
-	ipa_rm_params.reg_params.user_data = dev;
-	ipa_rm_params.reg_params.notify_cb = ipa3_rm_notify;
-	ret = ipa_rm_create_resource(&ipa_rm_params);
+	if (ipa3_ctx->use_ipa_pm)
+		ret = ipa3_wwan_register_netdev_pm_client(dev);
+	else
+		ret = ipa3_wwan_create_wwan_rm_resource(dev);
 	if (ret) {
-		pr_err("%s: unable to create resourse %d in IPA RM\n",
-		       __func__, IPA_RM_RESOURCE_WWAN_0_PROD);
-		goto create_rsrc_err;
+		IPAWANERR("fail to create/register pm resources\n");
+		goto fail_pm;
 	}
-	ret = ipa_rm_inactivity_timer_init(IPA_RM_RESOURCE_WWAN_0_PROD,
-					   IPA_RM_INACTIVITY_TIMER);
-	if (ret) {
-		pr_err("%s: ipa rm timer init failed %d on resourse %d\n",
-		       __func__, ret, IPA_RM_RESOURCE_WWAN_0_PROD);
-		goto timer_init_err;
-	}
-	/* add dependency */
-	ret = ipa_rm_add_dependency(IPA_RM_RESOURCE_WWAN_0_PROD,
-			IPA_RM_RESOURCE_Q6_CONS);
-	if (ret)
-		goto add_dpnd_err;
-	/* setup Performance profile */
-	memset(&profile, 0, sizeof(profile));
-	profile.max_supported_bandwidth_mbps = IPA_APPS_MAX_BW_IN_MBPS;
-	ret = ipa_rm_set_perf_profile(IPA_RM_RESOURCE_WWAN_0_PROD,
-			&profile);
-	if (ret)
-		goto set_perf_err;
-	/* IPA_RM configuration ends */
 
 	/* Enable SG support in netdevice. */
 	if (ipa3_rmnet_res.ipa_advertise_sg_support)
@@ -2260,28 +2459,18 @@
 		netif_napi_del(&(rmnet_ipa3_ctx->wwan_priv->napi));
 	unregister_netdev(dev);
 set_perf_err:
-	ret = ipa_rm_delete_dependency(IPA_RM_RESOURCE_WWAN_0_PROD,
-		IPA_RM_RESOURCE_Q6_CONS);
-	if (ret)
-		IPAWANERR("Error deleting dependency %d->%d, ret=%d\n",
-			IPA_RM_RESOURCE_WWAN_0_PROD, IPA_RM_RESOURCE_Q6_CONS,
-			ret);
-add_dpnd_err:
-	ret = ipa_rm_inactivity_timer_destroy(
-		IPA_RM_RESOURCE_WWAN_0_PROD); /* IPA_RM */
-	if (ret)
-		IPAWANERR("Error ipa_rm_inactivity_timer_destroy %d, ret=%d\n",
-		IPA_RM_RESOURCE_WWAN_0_PROD, ret);
-timer_init_err:
-	ret = ipa_rm_delete_resource(IPA_RM_RESOURCE_WWAN_0_PROD);
-	if (ret)
-		IPAWANERR("Error deleting resource %d, ret=%d\n",
-		IPA_RM_RESOURCE_WWAN_0_PROD, ret);
-create_rsrc_err:
-
-	if (!atomic_read(&rmnet_ipa3_ctx->is_ssr))
-		ipa3_q6_deinitialize_rm();
-
+	if (ipa3_ctx->use_ipa_pm)
+		ipa3_wwan_deregister_netdev_pm_client();
+	else
+		ipa3_wwan_delete_wwan_rm_resource();
+fail_pm:
+	if (ipa3_ctx->use_ipa_pm) {
+		if (!atomic_read(&rmnet_ipa3_ctx->is_ssr))
+			ipa3_q6_deregister_pm();
+	} else {
+		if (!atomic_read(&rmnet_ipa3_ctx->is_ssr))
+			ipa3_q6_deinitialize_rm();
+	}
 q6_init_err:
 	free_netdev(dev);
 	rmnet_ipa3_ctx->wwan_priv = NULL;
@@ -2317,21 +2506,10 @@
 		netif_napi_del(&(rmnet_ipa3_ctx->wwan_priv->napi));
 	mutex_unlock(&rmnet_ipa3_ctx->pipe_handle_guard);
 	unregister_netdev(IPA_NETDEV());
-	ret = ipa_rm_delete_dependency(IPA_RM_RESOURCE_WWAN_0_PROD,
-		IPA_RM_RESOURCE_Q6_CONS);
-	if (ret < 0)
-		IPAWANERR("Error deleting dependency %d->%d, ret=%d\n",
-			IPA_RM_RESOURCE_WWAN_0_PROD, IPA_RM_RESOURCE_Q6_CONS,
-			ret);
-	ret = ipa_rm_inactivity_timer_destroy(IPA_RM_RESOURCE_WWAN_0_PROD);
-	if (ret < 0)
-		IPAWANERR(
-		"Error ipa_rm_inactivity_timer_destroy resource %d, ret=%d\n",
-		IPA_RM_RESOURCE_WWAN_0_PROD, ret);
-	ret = ipa_rm_delete_resource(IPA_RM_RESOURCE_WWAN_0_PROD);
-	if (ret < 0)
-		IPAWANERR("Error deleting resource %d, ret=%d\n",
-		IPA_RM_RESOURCE_WWAN_0_PROD, ret);
+	if (ipa3_ctx->use_ipa_pm)
+		ipa3_wwan_deregister_netdev_pm_client();
+	else
+		ipa3_wwan_delete_wwan_rm_resource();
 	cancel_work_sync(&ipa3_tx_wakequeue_work);
 	cancel_delayed_work(&ipa_tether_stats_poll_wakequeue_work);
 	if (IPA_NETDEV())
@@ -2385,23 +2563,26 @@
 	if (wwan_ptr == NULL) {
 		IPAWANERR("wwan_ptr is NULL.\n");
 		ret = 0;
-		goto unlock_and_bail;
+		netif_tx_unlock_bh(netdev);
+		goto bail;
 	}
 
 	/* Do not allow A7 to suspend in case there are oustanding packets */
 	if (atomic_read(&wwan_ptr->outstanding_pkts) != 0) {
 		IPAWANDBG("Outstanding packets, postponing AP suspend.\n");
 		ret = -EAGAIN;
-		goto unlock_and_bail;
+		netif_tx_unlock_bh(netdev);
+		goto bail;
 	}
 
 	/* Make sure that there is no Tx operation ongoing */
 	netif_stop_queue(netdev);
-	ipa_rm_release_resource(IPA_RM_RESOURCE_WWAN_0_PROD);
-	ret = 0;
-
-unlock_and_bail:
 	netif_tx_unlock_bh(netdev);
+	if (ipa3_ctx->use_ipa_pm)
+		ipa_pm_deactivate_sync(rmnet_ipa3_ctx->pm_hdl);
+	else
+		ipa_rm_release_resource(IPA_RM_RESOURCE_WWAN_0_PROD);
+	ret = 0;
 bail:
 	IPAWANDBG("Exit with %d\n", ret);
 	return ret;
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c
index c7a6186..2e43abf 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c
@@ -50,6 +50,9 @@
 #define WAN_IOC_QUERY_TETHER_STATS_ALL32 _IOWR(WAN_IOC_MAGIC, \
 		WAN_IOCTL_QUERY_TETHER_STATS_ALL, \
 		compat_uptr_t)
+#define WAN_IOC_NOTIFY_WAN_STATE32 _IOWR(WAN_IOC_MAGIC, \
+		WAN_IOCTL_NOTIFY_WAN_STATE, \
+		compat_uptr_t)
 #endif
 
 static unsigned int dev_num = 1;
@@ -316,6 +319,27 @@
 		}
 		break;
 
+	case WAN_IOC_NOTIFY_WAN_STATE:
+		IPAWANDBG_LOW("device %s got WAN_IOC_NOTIFY_WAN_STATE :>>>\n",
+			DRIVER_NAME);
+		pyld_sz = sizeof(struct wan_ioctl_notify_wan_state);
+		param = kzalloc(pyld_sz, GFP_KERNEL);
+		if (!param) {
+			retval = -ENOMEM;
+			break;
+		}
+		if (copy_from_user(param, (u8 __user *)arg, pyld_sz)) {
+			retval = -EFAULT;
+			break;
+		}
+
+		if (ipa3_wwan_set_modem_state(
+			(struct wan_ioctl_notify_wan_state *)param)) {
+			IPAWANERR("WAN_IOC_NOTIFY_WAN_STATE failed\n");
+			retval = -EFAULT;
+			break;
+		}
+		break;
 	default:
 		retval = -ENOTTY;
 	}
diff --git a/drivers/platform/msm/ipa/ipa_v3/teth_bridge.c b/drivers/platform/msm/ipa/ipa_v3/teth_bridge.c
index 297f932..7496f28 100644
--- a/drivers/platform/msm/ipa/ipa_v3/teth_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_v3/teth_bridge.c
@@ -50,6 +50,7 @@
 	dev_t dev_num;
 	struct device *dev;
 	struct cdev cdev;
+	u32 modem_pm_hdl;
 };
 static struct ipa3_teth_bridge_ctx *ipa3_teth_ctx;
 
@@ -118,14 +119,25 @@
 */
 int ipa3_teth_bridge_disconnect(enum ipa_client_type client)
 {
+	int res = 0;
+
 	TETH_DBG_FUNC_ENTRY();
-	ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_PROD,
-				 IPA_RM_RESOURCE_Q6_CONS);
-	ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
-				 IPA_RM_RESOURCE_USB_CONS);
+	if (ipa_pm_is_used()) {
+		res = ipa_pm_deactivate_sync(ipa3_teth_ctx->modem_pm_hdl);
+		if (res) {
+			TETH_ERR("fail to deactivate modem %d\n", res);
+			return res;
+		}
+		res = ipa_pm_destroy();
+	} else {
+		ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_PROD,
+					IPA_RM_RESOURCE_Q6_CONS);
+		ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
+					IPA_RM_RESOURCE_USB_CONS);
+	}
 	TETH_DBG_FUNC_EXIT();
 
-	return 0;
+	return res;
 }
 
 /**
@@ -140,9 +152,27 @@
 int ipa3_teth_bridge_connect(struct teth_bridge_connect_params *connect_params)
 {
 	int res = 0;
+	struct ipa_pm_register_params reg_params;
+
+	memset(&reg_params, 0, sizeof(reg_params));
 
 	TETH_DBG_FUNC_ENTRY();
 
+	if (ipa_pm_is_used()) {
+		reg_params.name = "MODEM (USB RMNET)";
+		reg_params.group = IPA_PM_GROUP_MODEM;
+		reg_params.skip_clk_vote = true;
+		res = ipa_pm_register(&reg_params,
+			&ipa3_teth_ctx->modem_pm_hdl);
+		if (res) {
+			TETH_ERR("fail to register with PM %d\n", res);
+			return res;
+		}
+
+		res = ipa_pm_activate_sync(ipa3_teth_ctx->modem_pm_hdl);
+		goto bail;
+	}
+
 	/* Build the dependency graph, first add_dependency call is sync
 	 * in order to make sure the IPA clocks are up before we continue
 	 * and notify the USB driver it may continue.
@@ -234,6 +264,8 @@
 		res = -ENODEV;
 		goto fail_cdev_add;
 	}
+
+	ipa3_teth_ctx->modem_pm_hdl = ~0;
 	TETH_DBG("Tethering bridge driver init OK\n");
 
 	return 0;
diff --git a/drivers/platform/msm/qcom-geni-se.c b/drivers/platform/msm/qcom-geni-se.c
index aafb8fc..707c95e 100644
--- a/drivers/platform/msm/qcom-geni-se.c
+++ b/drivers/platform/msm/qcom-geni-se.c
@@ -1247,6 +1247,79 @@
 }
 EXPORT_SYMBOL(geni_se_iommu_free_buf);
 
+/**
+ * geni_se_dump_dbg_regs() - Print relevant registers that capture most
+ *			accurately the state of an SE.
+ * @_dev:		Pointer to the SE's device.
+ * @iomem:		Base address of the SE's register space.
+ * @ipc:		IPC log context handle.
+ *
+ * This function is used to print out all the registers that capture the state
+ * of an SE to help debug any errors.
+ *
+ * Return:	None
+ */
+void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base,
+				void *ipc)
+{
+	u32 m_cmd0 = 0;
+	u32 m_irq_status = 0;
+	u32 geni_status = 0;
+	u32 geni_ios = 0;
+	u32 dma_rx_irq = 0;
+	u32 dma_tx_irq = 0;
+	u32 rx_fifo_status = 0;
+	u32 tx_fifo_status = 0;
+	u32 se_dma_dbg = 0;
+	u32 m_cmd_ctrl = 0;
+	u32 se_dma_rx_len = 0;
+	u32 se_dma_rx_len_in = 0;
+	u32 se_dma_tx_len = 0;
+	u32 se_dma_tx_len_in = 0;
+	struct geni_se_device *geni_se_dev;
+
+	if (!ipc)
+		return;
+
+	geni_se_dev = dev_get_drvdata(rsc->wrapper_dev);
+	if (unlikely(!geni_se_dev || !geni_se_dev->bus_bw))
+		return;
+	mutex_lock(&geni_se_dev->ab_ib_lock);
+	if (unlikely(list_empty(&rsc->ab_list) || list_empty(&rsc->ib_list))) {
+		GENI_SE_DBG(ipc, false, NULL, "%s: Clocks not on\n", __func__);
+		goto exit_geni_se_dump_dbg_regs;
+	}
+	m_cmd0 = geni_read_reg(base, SE_GENI_M_CMD0);
+	m_irq_status = geni_read_reg(base, SE_GENI_M_IRQ_STATUS);
+	geni_status = geni_read_reg(base, SE_GENI_STATUS);
+	geni_ios = geni_read_reg(base, SE_GENI_IOS);
+	dma_rx_irq = geni_read_reg(base, SE_DMA_TX_IRQ_STAT);
+	dma_tx_irq = geni_read_reg(base, SE_DMA_RX_IRQ_STAT);
+	rx_fifo_status = geni_read_reg(base, SE_GENI_RX_FIFO_STATUS);
+	tx_fifo_status = geni_read_reg(base, SE_GENI_TX_FIFO_STATUS);
+	se_dma_dbg = geni_read_reg(base, SE_DMA_DEBUG_REG0);
+	m_cmd_ctrl = geni_read_reg(base, SE_GENI_M_CMD_CTRL_REG);
+	se_dma_rx_len = geni_read_reg(base, SE_DMA_RX_LEN);
+	se_dma_rx_len_in = geni_read_reg(base, SE_DMA_RX_LEN_IN);
+	se_dma_tx_len = geni_read_reg(base, SE_DMA_TX_LEN);
+	se_dma_tx_len_in = geni_read_reg(base, SE_DMA_TX_LEN_IN);
+
+	GENI_SE_DBG(ipc, false, NULL,
+	"%s: m_cmd0:0x%x, m_irq_status:0x%x, geni_status:0x%x, geni_ios:0x%x\n",
+	__func__, m_cmd0, m_irq_status, geni_status, geni_ios);
+	GENI_SE_DBG(ipc, false, NULL,
+	"dma_rx_irq:0x%x, dma_tx_irq:0x%x, rx_fifo_sts:0x%x, tx_fifo_sts:0x%x\n"
+	, dma_rx_irq, dma_tx_irq, rx_fifo_status, tx_fifo_status);
+	GENI_SE_DBG(ipc, false, NULL,
+	"se_dma_dbg:0x%x, m_cmd_ctrl:0x%x, dma_rxlen:0x%x, dma_rxlen_in:0x%x\n",
+	se_dma_dbg, m_cmd_ctrl, se_dma_rx_len, se_dma_rx_len_in);
+	GENI_SE_DBG(ipc, false, NULL,
+	"dma_txlen:0x%x, dma_txlen_in:0x%x\n", se_dma_tx_len, se_dma_tx_len_in);
+exit_geni_se_dump_dbg_regs:
+	mutex_unlock(&geni_se_dev->ab_ib_lock);
+}
+EXPORT_SYMBOL(geni_se_dump_dbg_regs);
+
 static const struct of_device_id geni_se_dt_match[] = {
 	{ .compatible = "qcom,qupv3-geni-se", },
 	{ .compatible = "qcom,qupv3-geni-se-cb", },
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index 7f6d346..f6e81d8 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -348,7 +348,7 @@
 }
 
 #define MINIMUM_PARALLEL_FCC_UA		500000
-#define PL_TAPER_WORK_DELAY_MS		100
+#define PL_TAPER_WORK_DELAY_MS		500
 #define TAPER_RESIDUAL_PCT		90
 static void pl_taper_work(struct work_struct *work)
 {
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 1b890d5..60f4df8 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -2250,12 +2250,6 @@
 int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
 				    union power_supply_propval *val)
 {
-	int rc = 0;
-
-	rc = smblib_get_prop_usb_present(chg, val);
-	if (rc < 0 || !val->intval)
-		return rc;
-
 	if (!chg->iio.usbin_v_chan ||
 		PTR_ERR(chg->iio.usbin_v_chan) == -EPROBE_DEFER)
 		chg->iio.usbin_v_chan = iio_channel_get(chg->dev, "usbin_v");
diff --git a/drivers/pwm/pwm-qpnp.c b/drivers/pwm/pwm-qpnp.c
index 86f08d2..e7267de 100644
--- a/drivers/pwm/pwm-qpnp.c
+++ b/drivers/pwm/pwm-qpnp.c
@@ -317,6 +317,7 @@
 	struct pwm_period_config	period;
 	int				supported_sizes;
 	int				force_pwm_size;
+	bool				update_period;
 };
 
 /* Public facing structure */
@@ -327,6 +328,7 @@
 	bool			enabled;
 	struct _qpnp_pwm_config	pwm_config;
 	struct	qpnp_lpg_config	lpg_config;
+	enum pm_pwm_mode	pwm_mode;
 	spinlock_t		lpg_lock;
 	enum qpnp_lpg_revision	revision;
 	u8			sub_type;
@@ -1211,28 +1213,32 @@
 	rc = qpnp_lpg_save_pwm_value(chip);
 	if (rc)
 		goto out;
-	rc = qpnp_lpg_configure_pwm(chip);
-	if (rc)
-		goto out;
-	rc = qpnp_configure_pwm_control(chip);
-	if (rc)
-		goto out;
 
-	if (!rc && chip->enabled) {
-		rc = qpnp_lpg_configure_pwm_state(chip, QPNP_PWM_ENABLE);
-		if (rc) {
-			pr_err("Error in configuring pwm state, rc=%d\n", rc);
-			return rc;
-		}
+	if (pwm_config->update_period) {
+		rc = qpnp_lpg_configure_pwm(chip);
+		if (rc)
+			goto out;
+		rc = qpnp_configure_pwm_control(chip);
+		if (rc)
+			goto out;
+		if (!rc && chip->enabled) {
+			rc = qpnp_lpg_configure_pwm_state(chip,
+					QPNP_PWM_ENABLE);
+			if (rc) {
+				pr_err("Error in configuring pwm state, rc=%d\n",
+						rc);
+				return rc;
+			}
 
-		/* Enable the glitch removal after PWM is enabled */
-		rc = qpnp_lpg_glitch_removal(chip, true);
-		if (rc) {
-			pr_err("Error in enabling glitch control, rc=%d\n", rc);
-			return rc;
+			/* Enable the glitch removal after PWM is enabled */
+			rc = qpnp_lpg_glitch_removal(chip, true);
+			if (rc) {
+				pr_err("Error in enabling glitch control, rc=%d\n",
+						rc);
+				return rc;
+			}
 		}
 	}
-
 	pr_debug("duty/period=%u/%u %s: pwm_value=%d (of %d)\n",
 		 (unsigned int)duty_value, (unsigned int)period_value,
 		 (tm_lvl == LVL_USEC) ? "usec" : "nsec",
@@ -1309,12 +1315,10 @@
 	return rc;
 }
 
+/* lpg_lock should be held while calling _pwm_enable() */
 static int _pwm_enable(struct qpnp_pwm_chip *chip)
 {
 	int rc = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chip->lpg_lock, flags);
 
 	if (QPNP_IS_PWM_CONFIG_SELECTED(
 		chip->qpnp_lpg_registers[QPNP_ENABLE_CONTROL]) ||
@@ -1327,8 +1331,21 @@
 	if (!rc)
 		chip->enabled = true;
 
-	spin_unlock_irqrestore(&chip->lpg_lock, flags);
+	return rc;
+}
 
+/* lpg_lock should be held while calling _pwm_change_mode() */
+static int _pwm_change_mode(struct qpnp_pwm_chip *chip, enum pm_pwm_mode mode)
+{
+	int rc;
+
+	if (mode == PM_PWM_MODE_LPG)
+		rc = qpnp_configure_lpg_control(chip);
+	else
+		rc = qpnp_configure_pwm_control(chip);
+
+	if (rc)
+		pr_err("Failed to change the mode\n");
 	return rc;
 }
 
@@ -1375,12 +1392,14 @@
 
 	spin_lock_irqsave(&chip->lpg_lock, flags);
 
+	chip->pwm_config.update_period = false;
 	if (prev_period_us > INT_MAX / NSEC_PER_USEC ||
 			prev_period_us * NSEC_PER_USEC != period_ns) {
 		qpnp_lpg_calc_period(LVL_NSEC, period_ns, chip);
 		qpnp_lpg_save_period(chip);
 		pwm->state.period = period_ns;
 		chip->pwm_config.pwm_period = period_ns / NSEC_PER_USEC;
+		chip->pwm_config.update_period = true;
 	}
 
 	rc = _pwm_config(chip, LVL_NSEC, duty_ns, period_ns);
@@ -1403,11 +1422,15 @@
 {
 	int rc;
 	struct qpnp_pwm_chip *chip = qpnp_pwm_from_pwm_chip(pwm_chip);
+	unsigned long flags;
 
+	spin_lock_irqsave(&chip->lpg_lock, flags);
 	rc = _pwm_enable(chip);
 	if (rc)
 		pr_err("Failed to enable PWM channel: %d\n", chip->channel_id);
 
+	spin_unlock_irqrestore(&chip->lpg_lock, flags);
+
 	return rc;
 }
 
@@ -1445,20 +1468,6 @@
 					chip->channel_id);
 }
 
-static int _pwm_change_mode(struct qpnp_pwm_chip *chip, enum pm_pwm_mode mode)
-{
-	int rc;
-
-	if (mode)
-		rc = qpnp_configure_lpg_control(chip);
-	else
-		rc = qpnp_configure_pwm_control(chip);
-
-	if (rc)
-		pr_err("Failed to change the mode\n");
-	return rc;
-}
-
 /**
  * pwm_change_mode - Change the PWM mode configuration
  * @pwm: the PWM device
@@ -1466,7 +1475,7 @@
  */
 int pwm_change_mode(struct pwm_device *pwm, enum pm_pwm_mode mode)
 {
-	int rc;
+	int rc = 0;
 	unsigned long flags;
 	struct qpnp_pwm_chip *chip;
 
@@ -1483,7 +1492,22 @@
 	chip = qpnp_pwm_from_pwm_dev(pwm);
 
 	spin_lock_irqsave(&chip->lpg_lock, flags);
-	rc = _pwm_change_mode(chip, mode);
+	if (chip->pwm_mode != mode) {
+		rc = _pwm_change_mode(chip, mode);
+		if (rc) {
+			pr_err("Failed to change mode: %d, rc=%d\n", mode, rc);
+			goto unlock;
+		}
+		chip->pwm_mode = mode;
+		if (chip->enabled) {
+			rc = _pwm_enable(chip);
+			if (rc) {
+				pr_err("Failed to enable PWM, rc=%d\n", rc);
+				goto unlock;
+			}
+		}
+	}
+unlock:
 	spin_unlock_irqrestore(&chip->lpg_lock, flags);
 
 	return rc;
@@ -1619,6 +1643,7 @@
 
 	spin_lock_irqsave(&chip->lpg_lock, flags);
 
+	chip->pwm_config.update_period = false;
 	if (chip->pwm_config.pwm_period != period_us) {
 		qpnp_lpg_calc_period(LVL_USEC, period_us, chip);
 		qpnp_lpg_save_period(chip);
@@ -1629,6 +1654,7 @@
 		else
 			pwm->state.period
 				= (unsigned int)period_us * NSEC_PER_USEC;
+		chip->pwm_config.update_period = true;
 	}
 
 	rc = _pwm_config(chip, LVL_USEC, duty_us, period_us);
@@ -1735,6 +1761,7 @@
 	qpnp_lpg_calc_period(LVL_USEC, period, chip);
 	qpnp_lpg_save_period(chip);
 	chip->pwm_config.pwm_period = period;
+	chip->pwm_config.update_period = true;
 
 	rc = _pwm_config(chip, LVL_USEC, chip->pwm_config.pwm_duty, period);
 
@@ -1885,7 +1912,7 @@
 static int qpnp_parse_dt_config(struct platform_device *pdev,
 					struct qpnp_pwm_chip *chip)
 {
-	int			rc, enable, lut_entry_size, list_size, i;
+	int			rc, mode, lut_entry_size, list_size, i;
 	const char		*label;
 	const __be32		*prop;
 	u32			size;
@@ -2069,18 +2096,20 @@
 		}
 	}
 
-	rc = of_property_read_u32(of_node, "qcom,mode-select", &enable);
+	rc = of_property_read_u32(of_node, "qcom,mode-select", &mode);
 	if (rc)
 		goto read_opt_props;
 
-	if ((enable == PM_PWM_MODE_PWM && found_pwm_subnode == 0) ||
-		(enable == PM_PWM_MODE_LPG && found_lpg_subnode == 0)) {
+	if (mode > PM_PWM_MODE_LPG ||
+		(mode == PM_PWM_MODE_PWM && found_pwm_subnode == 0) ||
+		(mode == PM_PWM_MODE_LPG && found_lpg_subnode == 0)) {
 		dev_err(&pdev->dev, "%s: Invalid mode select\n", __func__);
 		rc = -EINVAL;
 		goto out;
 	}
 
-	_pwm_change_mode(chip, enable);
+	chip->pwm_mode = mode;
+	_pwm_change_mode(chip, mode);
 	_pwm_enable(chip);
 
 read_opt_props:
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index ecc6aad..c5118b4 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1248,6 +1248,7 @@
 	unsigned long req_sz, len, sa;
 	Sg_scatter_hold *rsv_schp;
 	int k, length;
+	int ret = 0;
 
 	if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data)))
 		return -ENXIO;
@@ -1258,8 +1259,11 @@
 	if (vma->vm_pgoff)
 		return -EINVAL;	/* want no offset */
 	rsv_schp = &sfp->reserve;
-	if (req_sz > rsv_schp->bufflen)
-		return -ENOMEM;	/* cannot map more than reserved buffer */
+	mutex_lock(&sfp->f_mutex);
+	if (req_sz > rsv_schp->bufflen) {
+		ret = -ENOMEM;	/* cannot map more than reserved buffer */
+		goto out;
+	}
 
 	sa = vma->vm_start;
 	length = 1 << (PAGE_SHIFT + rsv_schp->page_order);
@@ -1273,7 +1277,9 @@
 	vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
 	vma->vm_private_data = sfp;
 	vma->vm_ops = &sg_mmap_vm_ops;
-	return 0;
+out:
+	mutex_unlock(&sfp->f_mutex);
+	return ret;
 }
 
 static void
@@ -1742,9 +1748,12 @@
 		    !sfp->res_in_use) {
 			sfp->res_in_use = 1;
 			sg_link_reserve(sfp, srp, dxfer_len);
-		} else if ((hp->flags & SG_FLAG_MMAP_IO) && sfp->res_in_use) {
+		} else if (hp->flags & SG_FLAG_MMAP_IO) {
+			res = -EBUSY; /* sfp->res_in_use == 1 */
+			if (dxfer_len > rsv_schp->bufflen)
+				res = -ENOMEM;
 			mutex_unlock(&sfp->f_mutex);
-			return -EBUSY;
+			return res;
 		} else {
 			res = sg_build_indirect(req_schp, sfp, dxfer_len);
 			if (res) {
diff --git a/drivers/scsi/ufs/ufs-debugfs.c b/drivers/scsi/ufs/ufs-debugfs.c
index 557ca19..11e11e4 100644
--- a/drivers/scsi/ufs/ufs-debugfs.c
+++ b/drivers/scsi/ufs/ufs-debugfs.c
@@ -950,6 +950,10 @@
 	seq_printf(file, "hba->saved_err = 0x%x\n", hba->saved_err);
 	seq_printf(file, "hba->saved_uic_err = 0x%x\n", hba->saved_uic_err);
 
+	seq_printf(file, "power_mode_change_cnt = %d\n",
+			hba->ufs_stats.power_mode_change_cnt);
+	seq_printf(file, "hibern8_exit_cnt = %d\n",
+			hba->ufs_stats.hibern8_exit_cnt);
 	return 0;
 }
 
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index e1e9402..b6ba4c4 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -4875,6 +4875,7 @@
 
 		memcpy(&hba->pwr_info, pwr_mode,
 			sizeof(struct ufs_pa_layer_attr));
+		hba->ufs_stats.power_mode_change_cnt++;
 	}
 
 	return ret;
@@ -7170,6 +7171,12 @@
 	} while (err && --retries);
 
 	/*
+	 * There is no point proceeding even after failing
+	 * to recover after multiple retries.
+	 */
+	if (err && ufshcd_is_embedded_dev(hba))
+		BUG();
+	/*
 	 * After reset the door-bell might be cleared, complete
 	 * outstanding requests in s/w here.
 	 */
@@ -7634,9 +7641,6 @@
 {
 	int err_reg_hist_size = sizeof(struct ufs_uic_err_reg_hist);
 
-	hba->ufs_stats.hibern8_exit_cnt = 0;
-	hba->ufs_stats.last_hibern8_exit_tstamp = ktime_set(0, 0);
-
 	memset(&hba->ufs_stats.pa_err, 0, err_reg_hist_size);
 	memset(&hba->ufs_stats.dl_err, 0, err_reg_hist_size);
 	memset(&hba->ufs_stats.nl_err, 0, err_reg_hist_size);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index fc855db..1b21238 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -644,6 +644,7 @@
 	struct ufshcd_clk_ctx clk_rel;
 	u32 hibern8_exit_cnt;
 	ktime_t last_hibern8_exit_tstamp;
+	u32 power_mode_change_cnt;
 	struct ufs_uic_err_reg_hist pa_err;
 	struct ufs_uic_err_reg_hist dl_err;
 	struct ufs_uic_err_reg_hist nl_err;
@@ -1198,6 +1199,14 @@
 		pwr_info->pwr_tx == FASTAUTO_MODE);
 }
 
+static inline bool ufshcd_is_embedded_dev(struct ufs_hba *hba)
+{
+	if ((hba->dev_info.b_device_sub_class == UFS_DEV_EMBEDDED_BOOTABLE) ||
+	    (hba->dev_info.b_device_sub_class == UFS_DEV_EMBEDDED_NON_BOOTABLE))
+		return true;
+	return false;
+}
+
 #ifdef CONFIG_DEBUG_FS
 static inline void ufshcd_init_req_stats(struct ufs_hba *hba)
 {
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index 567f290..3ae9a10 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -2397,6 +2397,8 @@
 		bool opensl1valid = false;
 		int maxctrlw1, maxctrlw3, i;
 
+		/* intitalize array to zero */
+		memset(opensl1, 0x0, sizeof(opensl1));
 		finalexp = (ctrl->sched.chc3[last3])->rootexp;
 		if (last1 >= 0) {
 			slc1 = ctrl->sched.chc1[coeff1];
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
index 3863b09..5234580 100644
--- a/drivers/soc/qcom/llcc-sdm845.c
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -73,7 +73,7 @@
 	SCT_ENTRY("display",     16, 16, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
 	SCT_ENTRY("videofw",     17, 17, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
 	SCT_ENTRY("modemhp_fix", 20, 20, 1024, 2, 1, 0x0,  0xF00, 0, 0, 1, 1, 0),
-	SCT_ENTRY("modem_paging", 21, 21, 1024, 0, 1, 0x0,  0xF, 0, 0, 1, 1, 0),
+	SCT_ENTRY("modem_paging", 21, 21, 1024, 0, 1, 0x1e, 0x0, 0, 0, 1, 1, 0),
 	SCT_ENTRY("audiohw",     22, 22, 1024, 1, 1, 0xFFC, 0x2, 0, 0, 1, 1, 0),
 };
 
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_bimc_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_bimc_rpmh.c
index c1e8feb..dafae4c 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_bimc_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_bimc_rpmh.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
@@ -242,7 +242,7 @@
 	(M_BKE_GC_GC_BMSK >> \
 	(M_BKE_GC_GC_SHFT + 1))
 
-static int bimc_div(int64_t *a, uint32_t b)
+static int bimc_div(uint64_t *a, uint32_t b)
 {
 	if ((*a > 0) && (*a < b)) {
 		*a = 0;
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
index 077d8cd..5a110bb 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
@@ -566,6 +566,11 @@
 		bcm_clist_add(node);
 	}
 
+	if (!cur_rsc) {
+		MSM_BUS_ERR("%s: Error for cur_rsc is NULL.\n", __func__);
+		return ret;
+	}
+
 	cur_mbox = cur_rsc->rscdev->mbox;
 	cur_bcm_clist = cur_rsc->rscdev->bcm_clist;
 
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index 417b0b2..c35119c 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -572,6 +572,12 @@
 	/* SDM670 ID */
 	[336] = {MSM_CPU_SDM670, "SDM670"},
 
+	/* QCS605 ID */
+	[347] = {MSM_CPU_QCS605, "QCS605"},
+
+	/* SDA670 ID */
+	[337] = {MSM_CPU_SDA670, "SDA670"},
+
 	/* Uninitialized IDs are not known to run Linux.
 	 * MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
 	 * considered as unknown CPU.
@@ -1434,6 +1440,14 @@
 		dummy_socinfo.id = 336;
 		strlcpy(dummy_socinfo.build_id, "sdm670 - ",
 			sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_sda670()) {
+		dummy_socinfo.id = 337;
+		strlcpy(dummy_socinfo.build_id, "sda670 - ",
+			sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_qcs605()) {
+		dummy_socinfo.id = 347;
+		strlcpy(dummy_socinfo.build_id, "qcs605 - ",
+			sizeof(dummy_socinfo.build_id));
 	} else if (early_machine_is_sdxpoorwills()) {
 		dummy_socinfo.id = 334;
 		strlcpy(dummy_socinfo.build_id, "sdxpoorwills - ",
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index de3dc69..e46bc98 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -298,7 +298,7 @@
 	 */
 	if (fifo_disable && !dma_chan_valid)
 		mode = -EINVAL;
-	else if (fifo_disable)
+	else if (dma_chan_valid)
 		mode = GSI_DMA;
 	else
 		mode = FIFO_MODE;
@@ -617,30 +617,32 @@
 				struct spi_message *msg)
 {
 	struct spi_transfer *xfer;
-	struct device *gsi_dev = mas->dev;
+	int ret = 0;
 
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		if (xfer->rx_buf) {
-			xfer->rx_dma = dma_map_single(gsi_dev, xfer->rx_buf,
+			ret = geni_se_iommu_map_buf(mas->wrapper_dev,
+						&xfer->rx_dma, xfer->rx_buf,
 						xfer->len, DMA_FROM_DEVICE);
-			if (dma_mapping_error(mas->dev, xfer->rx_dma)) {
-				dev_err(mas->dev, "Err mapping buf\n");
-				return -ENOMEM;
+			if (ret) {
+				GENI_SE_ERR(mas->ipc, true, mas->dev,
+				"%s: Mapping Rx buffer %d\n", __func__, ret);
+				return ret;
 			}
 		}
 
 		if (xfer->tx_buf) {
-			xfer->tx_dma = dma_map_single(gsi_dev,
-				(void *)xfer->tx_buf, xfer->len, DMA_TO_DEVICE);
-			if (dma_mapping_error(gsi_dev, xfer->tx_dma)) {
-				dev_err(mas->dev, "Err mapping buf\n");
-				dma_unmap_single(gsi_dev, xfer->rx_dma,
-						xfer->len, DMA_FROM_DEVICE);
-				return -ENOMEM;
+			ret = geni_se_iommu_map_buf(mas->wrapper_dev,
+						&xfer->tx_dma,
+						(void *)xfer->tx_buf,
+						xfer->len, DMA_TO_DEVICE);
+			if (ret) {
+				GENI_SE_ERR(mas->ipc, true, mas->dev,
+				"%s: Mapping Tx buffer %d\n", __func__, ret);
+				return ret;
 			}
 		}
 	};
-
 	return 0;
 }
 
@@ -648,14 +650,13 @@
 				struct spi_message *msg)
 {
 	struct spi_transfer *xfer;
-	struct device *gsi_dev = mas->dev;
 
 	list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 		if (xfer->rx_buf)
-			dma_unmap_single(gsi_dev, xfer->rx_dma,
+			geni_se_iommu_unmap_buf(mas->wrapper_dev, &xfer->rx_dma,
 						xfer->len, DMA_FROM_DEVICE);
 		if (xfer->tx_buf)
-			dma_unmap_single(gsi_dev, xfer->tx_dma,
+			geni_se_iommu_unmap_buf(mas->wrapper_dev, &xfer->tx_dma,
 						xfer->len, DMA_TO_DEVICE);
 	};
 }
@@ -709,7 +710,12 @@
 {
 	struct spi_geni_master *mas = spi_master_get_devdata(spi);
 	int ret = 0;
+	u32 max_speed = spi->cur_msg->spi->max_speed_hz;
+	struct se_geni_rsc *rsc = &mas->spi_rsc;
 
+	/* Adjust the AB/IB based on the max speed of the slave.*/
+	rsc->ib = max_speed * DEFAULT_BUS_WIDTH;
+	rsc->ab = max_speed * DEFAULT_BUS_WIDTH;
 	ret = pm_runtime_get_sync(mas->dev);
 	if (ret < 0) {
 		dev_err(mas->dev, "Error enabling SE resources\n");
@@ -900,6 +906,7 @@
 {
 	unsigned long timeout;
 
+	geni_se_dump_dbg_regs(&mas->spi_rsc, mas->base, mas->ipc);
 	reinit_completion(&mas->xfer_done);
 	geni_cancel_m_cmd(mas->base);
 	geni_write_reg(0, mas->base, SE_GENI_TX_WATERMARK_REG);
@@ -986,6 +993,7 @@
 	}
 	return ret;
 err_gsi_geni_transfer_one:
+	geni_se_dump_dbg_regs(&mas->spi_rsc, mas->base, mas->ipc);
 	dmaengine_terminate_all(mas->tx);
 	return ret;
 err_fifo_geni_transfer_one:
diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c
index 01438fa..f50076d 100644
--- a/drivers/staging/rts5208/rtsx_scsi.c
+++ b/drivers/staging/rts5208/rtsx_scsi.c
@@ -414,7 +414,7 @@
 	sense->ascq = ascq;
 	if (sns_key_info0 != 0) {
 		sense->sns_key_info[0] = SKSV | sns_key_info0;
-		sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 8;
+		sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 4;
 		sense->sns_key_info[2] = sns_key_info1 & 0x0f;
 	}
 }
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index c5e2703..79788eb 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -1264,6 +1264,13 @@
 		goto exit_geni_serial_isr;
 	}
 
+	if (s_irq_status & S_RX_FIFO_WR_ERR_EN) {
+		uport->icount.buf_overrun++;
+		IPC_LOG_MSG(msm_port->ipc_log_misc,
+			"%s.sirq 0x%x buf_overrun:%d\n",
+			__func__, s_irq_status, uport->icount.buf_overrun);
+	}
+
 	if (!dma) {
 		if ((m_irq_status & m_irq_en) &
 		    (M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN))
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 840930b0..c8075eb 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -629,6 +629,8 @@
 	if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET &&
 			as->status != -ENOENT)
 		cancel_bulk_urbs(ps, as->bulk_addr);
+
+	wake_up(&ps->wait);
 	spin_unlock(&ps->lock);
 
 	if (signr) {
@@ -636,8 +638,6 @@
 		put_pid(pid);
 		put_cred(cred);
 	}
-
-	wake_up(&ps->wait);
 }
 
 static void destroy_async(struct usb_dev_state *ps, struct list_head *list)
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 574da2b..82806e3 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -57,8 +57,9 @@
 	/* Microsoft LifeCam-VX700 v2.0 */
 	{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
 
-	/* Logitech HD Pro Webcams C920 and C930e */
+	/* Logitech HD Pro Webcams C920, C920-C and C930e */
 	{ USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
+	{ USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT },
 	{ USB_DEVICE(0x046d, 0x0843), .driver_info = USB_QUIRK_DELAY_INIT },
 
 	/* Logitech ConferenceCam CC3000e */
@@ -217,6 +218,9 @@
 	{ USB_DEVICE(0x1a0a, 0x0200), .driver_info =
 			USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
 
+	/* Corsair Strafe RGB */
+	{ USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT },
+
 	/* Acer C120 LED Projector */
 	{ USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM },
 
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 8a6ae0b..02adc93 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -2155,7 +2155,7 @@
 	struct usb_gadget *gadget = dev_to_usb_gadget(dev);
 	struct usb_composite_dev *cdev = get_gadget_data(gadget);
 
-	return sprintf(buf, "%d\n", cdev->suspended);
+	return snprintf(buf, PAGE_SIZE, "%d\n", cdev->suspended);
 }
 static DEVICE_ATTR_RO(suspended);
 
diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h
index 48454b7..a560083 100644
--- a/drivers/usb/gadget/function/f_gsi.h
+++ b/drivers/usb/gadget/function/f_gsi.h
@@ -1393,7 +1393,7 @@
 
 /* string descriptors: */
 static struct usb_string qdss_gsi_string_defs[] = {
-	[0].s = "QDSS DATA",
+	[0].s = "Qualcomm DPL Data",
 	{}, /* end of list */
 };
 
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 5f4ca78..58b9685 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -142,29 +142,30 @@
 			pinfo->sb_type.gen = AMD_CHIPSET_SB700;
 		else if (rev >= 0x40 && rev <= 0x4f)
 			pinfo->sb_type.gen = AMD_CHIPSET_SB800;
-	}
-	pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
-					  0x145c, NULL);
-	if (pinfo->smbus_dev) {
-		pinfo->sb_type.gen = AMD_CHIPSET_TAISHAN;
 	} else {
 		pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
 				PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, NULL);
 
-		if (!pinfo->smbus_dev) {
-			pinfo->sb_type.gen = NOT_AMD_CHIPSET;
-			return 0;
+		if (pinfo->smbus_dev) {
+			rev = pinfo->smbus_dev->revision;
+			if (rev >= 0x11 && rev <= 0x14)
+				pinfo->sb_type.gen = AMD_CHIPSET_HUDSON2;
+			else if (rev >= 0x15 && rev <= 0x18)
+				pinfo->sb_type.gen = AMD_CHIPSET_BOLTON;
+			else if (rev >= 0x39 && rev <= 0x3a)
+				pinfo->sb_type.gen = AMD_CHIPSET_YANGTZE;
+		} else {
+			pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+							  0x145c, NULL);
+			if (pinfo->smbus_dev) {
+				rev = pinfo->smbus_dev->revision;
+				pinfo->sb_type.gen = AMD_CHIPSET_TAISHAN;
+			} else {
+				pinfo->sb_type.gen = NOT_AMD_CHIPSET;
+				return 0;
+			}
 		}
-
-		rev = pinfo->smbus_dev->revision;
-		if (rev >= 0x11 && rev <= 0x14)
-			pinfo->sb_type.gen = AMD_CHIPSET_HUDSON2;
-		else if (rev >= 0x15 && rev <= 0x18)
-			pinfo->sb_type.gen = AMD_CHIPSET_BOLTON;
-		else if (rev >= 0x39 && rev <= 0x3a)
-			pinfo->sb_type.gen = AMD_CHIPSET_YANGTZE;
 	}
-
 	pinfo->sb_type.rev = rev;
 	return 1;
 }
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 261ed2c..a6b6b1c 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2655,6 +2655,13 @@
 {
 	struct musb	*musb = dev_to_musb(dev);
 	unsigned long	flags;
+	int ret;
+
+	ret = pm_runtime_get_sync(dev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(dev);
+		return ret;
+	}
 
 	musb_platform_disable(musb);
 	musb_generic_disable(musb);
@@ -2703,14 +2710,6 @@
 	if ((devctl & mask) != (musb->context.devctl & mask))
 		musb->port1_status = 0;
 
-	/*
-	 * The USB HUB code expects the device to be in RPM_ACTIVE once it came
-	 * out of suspend
-	 */
-	pm_runtime_disable(dev);
-	pm_runtime_set_active(dev);
-	pm_runtime_enable(dev);
-
 	musb_start(musb);
 
 	spin_lock_irqsave(&musb->lock, flags);
@@ -2720,6 +2719,9 @@
 			error);
 	spin_unlock_irqrestore(&musb->lock, flags);
 
+	pm_runtime_mark_last_busy(dev);
+	pm_runtime_put_autosuspend(dev);
+
 	return 0;
 }
 
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index fe12315..2a99443 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -2023,6 +2023,7 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) },
 	{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d04, 0xff) },			/* D-Link DWM-158 */
+	{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7d0e, 0xff) },			/* D-Link DWM-157 C1 */
 	{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e19, 0xff),			/* D-Link DWM-221 B1 */
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_INTERFACE_CLASS(0x2001, 0x7e35, 0xff),			/* D-Link DWM-222 */
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 74ed5aa..f6e1119 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -1834,6 +1834,8 @@
 			goto restore;
 		}
 
+		btrfs_qgroup_rescan_resume(fs_info);
+
 		if (!fs_info->uuid_root) {
 			btrfs_info(fs_info, "creating UUID tree");
 			ret = btrfs_create_uuid_tree(fs_info);
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index 58c2f4a..9ac6591 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -355,6 +355,10 @@
 	error = misc_register(&ls->ls_device);
 	if (error) {
 		kfree(ls->ls_device.name);
+		/* this has to be set to NULL
+		 * to avoid a double-free in dlm_device_deregister
+		 */
+		ls->ls_device.name = NULL;
 	}
 fail:
 	return error;
diff --git a/fs/namespace.c b/fs/namespace.c
index 7731f77..2160bb9 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -227,6 +227,7 @@
 		mnt->mnt_count = 1;
 		mnt->mnt_writers = 0;
 #endif
+		mnt->mnt.data = NULL;
 
 		INIT_HLIST_NODE(&mnt->mnt_hash);
 		INIT_LIST_HEAD(&mnt->mnt_child);
@@ -976,7 +977,6 @@
 	if (!mnt)
 		return ERR_PTR(-ENOMEM);
 
-	mnt->mnt.data = NULL;
 	if (type->alloc_mnt_data) {
 		mnt->mnt.data = type->alloc_mnt_data();
 		if (!mnt->mnt.data) {
@@ -990,7 +990,6 @@
 
 	root = mount_fs(type, flags, name, &mnt->mnt, data);
 	if (IS_ERR(root)) {
-		kfree(mnt->mnt.data);
 		mnt_free_id(mnt);
 		free_vfsmnt(mnt);
 		return ERR_CAST(root);
@@ -1109,7 +1108,6 @@
 	return mnt;
 
  out_free:
-	kfree(mnt->mnt.data);
 	mnt_free_id(mnt);
 	free_vfsmnt(mnt);
 	return ERR_PTR(err);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 84c1cb9..1eec947 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -636,11 +636,11 @@
 	if (result <= 0)
 		goto out;
 
-	result = generic_write_sync(iocb, result);
-	if (result < 0)
-		goto out;
 	written = result;
 	iocb->ki_pos += written;
+	result = generic_write_sync(iocb, written);
+	if (result < 0)
+		goto out;
 
 	/* Return error values */
 	if (nfs_need_check_write(file, inode)) {
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 80bcc0b..52ea41b 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -248,7 +248,6 @@
 extern const struct nfs_pageio_ops nfs_pgio_rw_ops;
 struct nfs_pgio_header *nfs_pgio_header_alloc(const struct nfs_rw_ops *);
 void nfs_pgio_header_free(struct nfs_pgio_header *);
-void nfs_pgio_data_destroy(struct nfs_pgio_header *);
 int nfs_generic_pgio(struct nfs_pageio_descriptor *, struct nfs_pgio_header *);
 int nfs_initiate_pgio(struct rpc_clnt *clnt, struct nfs_pgio_header *hdr,
 		      struct rpc_cred *cred, const struct nfs_rpc_ops *rpc_ops,
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 142a74f..3d17fc8 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -497,16 +497,6 @@
 }
 EXPORT_SYMBOL_GPL(nfs_pgio_header_alloc);
 
-/*
- * nfs_pgio_header_free - Free a read or write header
- * @hdr: The header to free
- */
-void nfs_pgio_header_free(struct nfs_pgio_header *hdr)
-{
-	hdr->rw_ops->rw_free_header(hdr);
-}
-EXPORT_SYMBOL_GPL(nfs_pgio_header_free);
-
 /**
  * nfs_pgio_data_destroy - make @hdr suitable for reuse
  *
@@ -515,14 +505,24 @@
  *
  * @hdr: A header that has had nfs_generic_pgio called
  */
-void nfs_pgio_data_destroy(struct nfs_pgio_header *hdr)
+static void nfs_pgio_data_destroy(struct nfs_pgio_header *hdr)
 {
 	if (hdr->args.context)
 		put_nfs_open_context(hdr->args.context);
 	if (hdr->page_array.pagevec != hdr->page_array.page_array)
 		kfree(hdr->page_array.pagevec);
 }
-EXPORT_SYMBOL_GPL(nfs_pgio_data_destroy);
+
+/*
+ * nfs_pgio_header_free - Free a read or write header
+ * @hdr: The header to free
+ */
+void nfs_pgio_header_free(struct nfs_pgio_header *hdr)
+{
+	nfs_pgio_data_destroy(hdr);
+	hdr->rw_ops->rw_free_header(hdr);
+}
+EXPORT_SYMBOL_GPL(nfs_pgio_header_free);
 
 /**
  * nfs_pgio_rpcsetup - Set up arguments for a pageio call
@@ -636,7 +636,6 @@
 static void nfs_pgio_error(struct nfs_pgio_header *hdr)
 {
 	set_bit(NFS_IOHDR_REDO, &hdr->flags);
-	nfs_pgio_data_destroy(hdr);
 	hdr->completion_ops->completion(hdr);
 }
 
@@ -647,7 +646,6 @@
 static void nfs_pgio_release(void *calldata)
 {
 	struct nfs_pgio_header *hdr = calldata;
-	nfs_pgio_data_destroy(hdr);
 	hdr->completion_ops->completion(hdr);
 }
 
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 415d7e6..b7a07ba 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -2145,7 +2145,6 @@
 		nfs_pageio_reset_write_mds(desc);
 		mirror->pg_recoalesce = 1;
 	}
-	nfs_pgio_data_destroy(hdr);
 	hdr->release(hdr);
 }
 
@@ -2257,7 +2256,6 @@
 		nfs_pageio_reset_read_mds(desc);
 		mirror->pg_recoalesce = 1;
 	}
-	nfs_pgio_data_destroy(hdr);
 	hdr->release(hdr);
 }
 
diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c
index 1239d1c..fffaad4 100644
--- a/fs/sdcardfs/derived_perm.c
+++ b/fs/sdcardfs/derived_perm.c
@@ -176,6 +176,9 @@
 	gid_t gid = sbi->options.fs_low_gid;
 	struct iattr newattrs;
 
+	if (!sbi->options.gid_derivation)
+		return;
+
 	info = SDCARDFS_I(d_inode(dentry));
 	info_d = info->data;
 	perm = info_d->perm;
diff --git a/fs/sdcardfs/inode.c b/fs/sdcardfs/inode.c
index 683b492..4a971e2 100644
--- a/fs/sdcardfs/inode.c
+++ b/fs/sdcardfs/inode.c
@@ -34,10 +34,14 @@
 	if (!cred)
 		return NULL;
 
-	if (data->under_obb)
-		uid = AID_MEDIA_OBB;
-	else
-		uid = multiuser_get_uid(data->userid, sbi->options.fs_low_uid);
+	if (sbi->options.gid_derivation) {
+		if (data->under_obb)
+			uid = AID_MEDIA_OBB;
+		else
+			uid = multiuser_get_uid(data->userid, sbi->options.fs_low_uid);
+	} else {
+		uid = sbi->options.fs_low_uid;
+	}
 	cred->fsuid = make_kuid(&init_user_ns, uid);
 	cred->fsgid = make_kgid(&init_user_ns, sbi->options.fs_low_gid);
 
diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c
index 80825b2..0a2b516 100644
--- a/fs/sdcardfs/main.c
+++ b/fs/sdcardfs/main.c
@@ -32,6 +32,7 @@
 	Opt_multiuser,
 	Opt_userid,
 	Opt_reserved_mb,
+	Opt_gid_derivation,
 	Opt_err,
 };
 
@@ -43,6 +44,7 @@
 	{Opt_mask, "mask=%u"},
 	{Opt_userid, "userid=%d"},
 	{Opt_multiuser, "multiuser"},
+	{Opt_gid_derivation, "derive_gid"},
 	{Opt_reserved_mb, "reserved_mb=%u"},
 	{Opt_err, NULL}
 };
@@ -64,6 +66,8 @@
 	vfsopts->gid = 0;
 	/* by default, 0MB is reserved */
 	opts->reserved_mb = 0;
+	/* by default, gid derivation is off */
+	opts->gid_derivation = false;
 
 	*debug = 0;
 
@@ -115,6 +119,9 @@
 				return 0;
 			opts->reserved_mb = option;
 			break;
+		case Opt_gid_derivation:
+			opts->gid_derivation = true;
+			break;
 		/* unknown option */
 		default:
 			if (!silent)
diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h
index 4e0ce49..d1d8bab 100644
--- a/fs/sdcardfs/sdcardfs.h
+++ b/fs/sdcardfs/sdcardfs.h
@@ -219,6 +219,7 @@
 	gid_t fs_low_gid;
 	userid_t fs_user_id;
 	bool multiuser;
+	bool gid_derivation;
 	unsigned int reserved_mb;
 };
 
diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c
index 7f4539b..b89947d 100644
--- a/fs/sdcardfs/super.c
+++ b/fs/sdcardfs/super.c
@@ -302,6 +302,8 @@
 		seq_printf(m, ",mask=%u", vfsopts->mask);
 	if (opts->fs_user_id)
 		seq_printf(m, ",userid=%u", opts->fs_user_id);
+	if (opts->gid_derivation)
+		seq_puts(m, ",derive_gid");
 	if (opts->reserved_mb != 0)
 		seq_printf(m, ",reserved=%uMB", opts->reserved_mb);
 
diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h
index 1455b2520..3ebed16 100644
--- a/fs/xfs/xfs_linux.h
+++ b/fs/xfs/xfs_linux.h
@@ -363,7 +363,14 @@
 #endif /* DEBUG */
 
 #ifdef CONFIG_XFS_RT
-#define XFS_IS_REALTIME_INODE(ip) ((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME)
+
+/*
+ * make sure we ignore the inode flag if the filesystem doesn't have a
+ * configured realtime device.
+ */
+#define XFS_IS_REALTIME_INODE(ip)			\
+	(((ip)->i_d.di_flags & XFS_DIFLAG_REALTIME) &&	\
+	 (ip)->i_mount->m_rtdev_targp)
 #else
 #define XFS_IS_REALTIME_INODE(ip) (0)
 #endif
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 3e5dbbe..4308204 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -574,6 +574,7 @@
 #define PCI_DEVICE_ID_AMD_CS5536_EHC    0x2095
 #define PCI_DEVICE_ID_AMD_CS5536_UDC    0x2096
 #define PCI_DEVICE_ID_AMD_CS5536_UOC    0x2097
+#define PCI_DEVICE_ID_AMD_CS5536_DEV_IDE    0x2092
 #define PCI_DEVICE_ID_AMD_CS5536_IDE    0x209A
 #define PCI_DEVICE_ID_AMD_LX_VIDEO  0x2081
 #define PCI_DEVICE_ID_AMD_LX_AES    0x2082
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index aa4c1ed..463785d 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -117,6 +117,7 @@
 #define SE_HW_PARAM_0			(0xE24)
 #define SE_HW_PARAM_1			(0xE28)
 #define SE_DMA_GENERAL_CFG		(0xE30)
+#define SE_DMA_DEBUG_REG0		(0xE40)
 
 /* GENI_OUTPUT_CTRL fields */
 #define DEFAULT_IO_OUTPUT_CTRL_MSK	(GENMASK(6, 0))
@@ -736,6 +737,22 @@
 int geni_se_iommu_free_buf(struct device *wrapper_dev, dma_addr_t *iova,
 			   void *buf, size_t size);
 
+
+/**
+ * geni_se_dump_dbg_regs() - Print relevant registers that capture most
+ *			accurately the state of an SE; meant to be called
+ *			in case of errors to help debug.
+ * @_dev:		Pointer to the SE's device.
+ * @iomem:		Base address of the SE's register space.
+ * @ipc:		IPC log context handle.
+ *
+ * This function is used to print out all the registers that capture the state
+ * of an SE to help debug any errors.
+ *
+ * Return:	None
+ */
+void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base,
+				void *ipc);
 #else
 static inline unsigned int geni_read_reg_nolog(void __iomem *base, int offset)
 {
@@ -907,5 +924,10 @@
 	return -ENXIO;
 }
 
+void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base,
+				void *ipc)
+{
+}
+
 #endif
 #endif
diff --git a/include/linux/string.h b/include/linux/string.h
index 4e510df..0463dfb 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -178,17 +178,6 @@
 void __write_overflow(void) __compiletime_error("detected write beyond size of object passed as 1st parameter");
 
 #if !defined(__NO_FORTIFY) && defined(__OPTIMIZE__) && defined(CONFIG_FORTIFY_SOURCE)
-__FORTIFY_INLINE char *strcpy(char *p, const char *q)
-{
-	size_t p_size = __builtin_object_size(p, 0);
-	size_t q_size = __builtin_object_size(q, 0);
-	if (p_size == (size_t)-1 && q_size == (size_t)-1)
-		return __builtin_strcpy(p, q);
-	if (strscpy(p, q, p_size < q_size ? p_size : q_size) < 0)
-		fortify_panic(__func__);
-	return p;
-}
-
 __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
 {
 	size_t p_size = __builtin_object_size(p, 0);
@@ -367,6 +356,18 @@
 		fortify_panic(__func__);
 	return __real_kmemdup(p, size, gfp);
 }
+
+/* defined after fortified strlen and memcpy to reuse them */
+__FORTIFY_INLINE char *strcpy(char *p, const char *q)
+{
+	size_t p_size = __builtin_object_size(p, 0);
+	size_t q_size = __builtin_object_size(q, 0);
+	if (p_size == (size_t)-1 && q_size == (size_t)-1)
+		return __builtin_strcpy(p, q);
+	memcpy(p, q, strlen(q) + 1);
+	return p;
+}
+
 #endif
 
 #endif /* _LINUX_STRING_H_ */
diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h
index 733a21e..1061add 100644
--- a/include/linux/workqueue.h
+++ b/include/linux/workqueue.h
@@ -311,8 +311,8 @@
 
 	__WQ_DRAINING		= 1 << 16, /* internal: workqueue is draining */
 	__WQ_ORDERED		= 1 << 17, /* internal: workqueue is ordered */
-	__WQ_ORDERED_EXPLICIT	= 1 << 18, /* internal: alloc_ordered_workqueue() */
 	__WQ_LEGACY		= 1 << 18, /* internal: create*_workqueue() */
+	__WQ_ORDERED_EXPLICIT	= 1 << 19, /* internal: alloc_ordered_workqueue() */
 
 	WQ_MAX_ACTIVE		= 512,	  /* I like 512, better ideas? */
 	WQ_MAX_UNBOUND_PER_CPU	= 4,	  /* 4 * #cpus for unbound wq */
diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h
index f196d40..71bd075 100644
--- a/include/soc/qcom/socinfo.h
+++ b/include/soc/qcom/socinfo.h
@@ -102,6 +102,10 @@
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdm845")
 #define early_machine_is_sdm670()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdm670")
+#define early_machine_is_qcs605()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,qcs605")
+#define early_machine_is_sda670()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sda670")
 #else
 #define of_board_is_sim()		0
 #define of_board_is_rumi()		0
@@ -142,6 +146,8 @@
 #define early_machine_is_sdxpoorwills()	0
 #define early_machine_is_sdm845()	0
 #define early_machine_is_sdm670()	0
+#define early_machine_is_qcs605()	0
+#define early_machine_is_sda670()	0
 #endif
 
 #define PLATFORM_SUBTYPE_MDM	1
@@ -204,6 +210,8 @@
 	SDX_CPU_SDXPOORWILLS,
 	MSM_CPU_SDM845,
 	MSM_CPU_SDM670,
+	MSM_CPU_QCS605,
+	MSM_CPU_SDA670,
 };
 
 struct msm_soc_info {
diff --git a/include/uapi/linux/rmnet_ipa_fd_ioctl.h b/include/uapi/linux/rmnet_ipa_fd_ioctl.h
index f04ac49..04aaaad 100644
--- a/include/uapi/linux/rmnet_ipa_fd_ioctl.h
+++ b/include/uapi/linux/rmnet_ipa_fd_ioctl.h
@@ -33,6 +33,7 @@
 #define WAN_IOCTL_QUERY_DL_FILTER_STATS  8
 #define WAN_IOCTL_ADD_FLT_RULE_EX        9
 #define WAN_IOCTL_QUERY_TETHER_STATS_ALL  10
+#define WAN_IOCTL_NOTIFY_WAN_STATE  11
 
 /* User space may not have this defined. */
 #ifndef IFNAMSIZ
@@ -126,6 +127,10 @@
 	uint32_t index;
 };
 
+struct wan_ioctl_notify_wan_state {
+	uint8_t up;
+};
+
 #define WAN_IOC_ADD_FLT_RULE _IOWR(WAN_IOC_MAGIC, \
 		WAN_IOCTL_ADD_FLT_RULE, \
 		struct ipa_install_fltr_rule_req_msg_v01 *)
@@ -170,4 +175,8 @@
 		WAN_IOCTL_QUERY_TETHER_STATS_ALL, \
 		struct wan_ioctl_query_tether_stats_all *)
 
+#define WAN_IOC_NOTIFY_WAN_STATE _IOWR(WAN_IOC_MAGIC, \
+		WAN_IOCTL_NOTIFY_WAN_STATE, \
+		struct wan_ioctl_notify_wan_state *)
+
 #endif /* _RMNET_IPA_FD_IOCTL_H */
diff --git a/kernel/configs/android-base.config b/kernel/configs/android-base.config
index 7dc5b07..cf1d104 100644
--- a/kernel/configs/android-base.config
+++ b/kernel/configs/android-base.config
@@ -150,6 +150,7 @@
 CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_STAGING=y
+CONFIG_SYNC_FILE=y
 CONFIG_TUN=y
 CONFIG_UID_SYS_STATS=y
 CONFIG_UNIX=y
diff --git a/kernel/kcov.c b/kernel/kcov.c
index 3cbb0c8..f8f3f4c 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -14,6 +14,7 @@
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <linux/kcov.h>
+#include <asm/setup.h>
 
 /*
  * kcov descriptor (one per opened debugfs file).
@@ -68,6 +69,11 @@
 	if (mode == KCOV_MODE_TRACE) {
 		unsigned long *area;
 		unsigned long pos;
+		unsigned long ip = _RET_IP_;
+
+#ifdef CONFIG_RANDOMIZE_BASE
+		ip -= kaslr_offset();
+#endif
 
 		/*
 		 * There is some code that runs in interrupts but for which
@@ -81,7 +87,7 @@
 		/* The first word is number of subsequent PCs. */
 		pos = READ_ONCE(area[0]) + 1;
 		if (likely(pos < t->kcov_size)) {
-			area[pos] = _RET_IP_;
+			area[pos] = ip;
 			WRITE_ONCE(area[0], pos);
 		}
 	}
diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c
index f8c5af5..d3de04b 100644
--- a/kernel/locking/locktorture.c
+++ b/kernel/locking/locktorture.c
@@ -780,6 +780,10 @@
 	else
 		lock_torture_print_module_parms(cxt.cur_ops,
 						"End of test: SUCCESS");
+
+	kfree(cxt.lwsa);
+	kfree(cxt.lrsa);
+
 end:
 	torture_cleanup_end();
 }
@@ -924,6 +928,8 @@
 				       GFP_KERNEL);
 		if (reader_tasks == NULL) {
 			VERBOSE_TOROUT_ERRSTRING("reader_tasks: Out of memory");
+			kfree(writer_tasks);
+			writer_tasks = NULL;
 			firsterr = -ENOMEM;
 			goto unwind;
 		}
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index ccfb9bf..352cfca 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -9620,4 +9620,4 @@
 }
 #endif /* CONFIG_SCHED_WALT */
 
-__read_mostly bool sched_predl;
+__read_mostly bool sched_predl = 1;
diff --git a/kernel/sched/tune.c b/kernel/sched/tune.c
index 217bafe..93643ba 100644
--- a/kernel/sched/tune.c
+++ b/kernel/sched/tune.c
@@ -838,7 +838,6 @@
 		bg = &per_cpu(cpu_boost_groups, cpu);
 		bg->group[st->idx].boost = 0;
 		bg->group[st->idx].tasks = 0;
-		raw_spin_lock_init(&bg->lock);
 	}
 
 	return 0;
diff --git a/mm/memory.c b/mm/memory.c
index b5e0ed3..378ebc0 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3596,6 +3596,11 @@
 	/* do counter updates before entering really critical section. */
 	check_sync_rss_stat(current);
 
+	if (!arch_vma_access_permitted(vma, flags & FAULT_FLAG_WRITE,
+					    flags & FAULT_FLAG_INSTRUCTION,
+					    flags & FAULT_FLAG_REMOTE))
+		return VM_FAULT_SIGSEGV;
+
 	/*
 	 * Enable the memcg OOM handling for faults triggered in user
 	 * space.  Kernel faults are handled more gracefully.
@@ -3603,11 +3608,6 @@
 	if (flags & FAULT_FLAG_USER)
 		mem_cgroup_oom_enable();
 
-	if (!arch_vma_access_permitted(vma, flags & FAULT_FLAG_WRITE,
-					    flags & FAULT_FLAG_INSTRUCTION,
-					    flags & FAULT_FLAG_REMOTE))
-		return VM_FAULT_SIGSEGV;
-
 	if (unlikely(is_vm_hugetlb_page(vma)))
 		ret = hugetlb_fault(vma->vm_mm, vma, address, flags);
 	else
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 577f1c0..ffd09c1 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -58,7 +58,7 @@
 				       u8 code, u8 ident, u16 dlen, void *data);
 static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
 			   void *data);
-static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
+static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size);
 static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
 
 static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
@@ -1473,7 +1473,7 @@
 
 			set_bit(CONF_REQ_SENT, &chan->conf_state);
 			l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-				       l2cap_build_conf_req(chan, buf), buf);
+				       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
 			chan->num_conf_req++;
 		}
 
@@ -2977,12 +2977,15 @@
 	return len;
 }
 
-static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
+static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
 {
 	struct l2cap_conf_opt *opt = *ptr;
 
 	BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
 
+	if (size < L2CAP_CONF_OPT_SIZE + len)
+		return;
+
 	opt->type = type;
 	opt->len  = len;
 
@@ -3007,7 +3010,7 @@
 	*ptr += L2CAP_CONF_OPT_SIZE + len;
 }
 
-static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
+static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size)
 {
 	struct l2cap_conf_efs efs;
 
@@ -3035,7 +3038,7 @@
 	}
 
 	l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
-			   (unsigned long) &efs);
+			   (unsigned long) &efs, size);
 }
 
 static void l2cap_ack_timeout(struct work_struct *work)
@@ -3181,11 +3184,12 @@
 	chan->ack_win = chan->tx_win;
 }
 
-static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
+static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
 {
 	struct l2cap_conf_req *req = data;
 	struct l2cap_conf_rfc rfc = { .mode = chan->mode };
 	void *ptr = req->data;
+	void *endptr = data + data_size;
 	u16 size;
 
 	BT_DBG("chan %p", chan);
@@ -3210,7 +3214,7 @@
 
 done:
 	if (chan->imtu != L2CAP_DEFAULT_MTU)
-		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr);
 
 	switch (chan->mode) {
 	case L2CAP_MODE_BASIC:
@@ -3229,7 +3233,7 @@
 		rfc.max_pdu_size    = 0;
 
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
-				   (unsigned long) &rfc);
+				   (unsigned long) &rfc, endptr - ptr);
 		break;
 
 	case L2CAP_MODE_ERTM:
@@ -3249,21 +3253,21 @@
 				       L2CAP_DEFAULT_TX_WINDOW);
 
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
-				   (unsigned long) &rfc);
+				   (unsigned long) &rfc, endptr - ptr);
 
 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
-			l2cap_add_opt_efs(&ptr, chan);
+			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
 
 		if (test_bit(FLAG_EXT_CTRL, &chan->flags))
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
-					   chan->tx_win);
+					   chan->tx_win, endptr - ptr);
 
 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
 			if (chan->fcs == L2CAP_FCS_NONE ||
 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
 				chan->fcs = L2CAP_FCS_NONE;
 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
-						   chan->fcs);
+						   chan->fcs, endptr - ptr);
 			}
 		break;
 
@@ -3281,17 +3285,17 @@
 		rfc.max_pdu_size = cpu_to_le16(size);
 
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
-				   (unsigned long) &rfc);
+				   (unsigned long) &rfc, endptr - ptr);
 
 		if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
-			l2cap_add_opt_efs(&ptr, chan);
+			l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
 
 		if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
 			if (chan->fcs == L2CAP_FCS_NONE ||
 			    test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
 				chan->fcs = L2CAP_FCS_NONE;
 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
-						   chan->fcs);
+						   chan->fcs, endptr - ptr);
 			}
 		break;
 	}
@@ -3302,10 +3306,11 @@
 	return ptr - data;
 }
 
-static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
+static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
 {
 	struct l2cap_conf_rsp *rsp = data;
 	void *ptr = rsp->data;
+	void *endptr = data + data_size;
 	void *req = chan->conf_req;
 	int len = chan->conf_len;
 	int type, hint, olen;
@@ -3407,7 +3412,7 @@
 			return -ECONNREFUSED;
 
 		l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
-				   (unsigned long) &rfc);
+				   (unsigned long) &rfc, endptr - ptr);
 	}
 
 	if (result == L2CAP_CONF_SUCCESS) {
@@ -3420,7 +3425,7 @@
 			chan->omtu = mtu;
 			set_bit(CONF_MTU_DONE, &chan->conf_state);
 		}
-		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
+		l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr);
 
 		if (remote_efs) {
 			if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
@@ -3434,7 +3439,7 @@
 
 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
 						   sizeof(efs),
-						   (unsigned long) &efs);
+						   (unsigned long) &efs, endptr - ptr);
 			} else {
 				/* Send PENDING Conf Rsp */
 				result = L2CAP_CONF_PENDING;
@@ -3467,7 +3472,7 @@
 			set_bit(CONF_MODE_DONE, &chan->conf_state);
 
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
-					   sizeof(rfc), (unsigned long) &rfc);
+					   sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
 
 			if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
 				chan->remote_id = efs.id;
@@ -3481,7 +3486,7 @@
 					le32_to_cpu(efs.sdu_itime);
 				l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
 						   sizeof(efs),
-						   (unsigned long) &efs);
+						   (unsigned long) &efs, endptr - ptr);
 			}
 			break;
 
@@ -3495,7 +3500,7 @@
 			set_bit(CONF_MODE_DONE, &chan->conf_state);
 
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
-					   (unsigned long) &rfc);
+					   (unsigned long) &rfc, endptr - ptr);
 
 			break;
 
@@ -3517,10 +3522,11 @@
 }
 
 static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
-				void *data, u16 *result)
+				void *data, size_t size, u16 *result)
 {
 	struct l2cap_conf_req *req = data;
 	void *ptr = req->data;
+	void *endptr = data + size;
 	int type, olen;
 	unsigned long val;
 	struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
@@ -3538,13 +3544,13 @@
 				chan->imtu = L2CAP_DEFAULT_MIN_MTU;
 			} else
 				chan->imtu = val;
-			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
+			l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr);
 			break;
 
 		case L2CAP_CONF_FLUSH_TO:
 			chan->flush_to = val;
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
-					   2, chan->flush_to);
+					   2, chan->flush_to, endptr - ptr);
 			break;
 
 		case L2CAP_CONF_RFC:
@@ -3558,13 +3564,13 @@
 			chan->fcs = 0;
 
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
-					   sizeof(rfc), (unsigned long) &rfc);
+					   sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
 			break;
 
 		case L2CAP_CONF_EWS:
 			chan->ack_win = min_t(u16, val, chan->ack_win);
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
-					   chan->tx_win);
+					   chan->tx_win, endptr - ptr);
 			break;
 
 		case L2CAP_CONF_EFS:
@@ -3577,7 +3583,7 @@
 				return -ECONNREFUSED;
 
 			l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
-					   (unsigned long) &efs);
+					   (unsigned long) &efs, endptr - ptr);
 			break;
 
 		case L2CAP_CONF_FCS:
@@ -3682,7 +3688,7 @@
 		return;
 
 	l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-		       l2cap_build_conf_req(chan, buf), buf);
+		       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
 	chan->num_conf_req++;
 }
 
@@ -3890,7 +3896,7 @@
 		u8 buf[128];
 		set_bit(CONF_REQ_SENT, &chan->conf_state);
 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-			       l2cap_build_conf_req(chan, buf), buf);
+			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
 		chan->num_conf_req++;
 	}
 
@@ -3968,7 +3974,7 @@
 			break;
 
 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-			       l2cap_build_conf_req(chan, req), req);
+			       l2cap_build_conf_req(chan, req, sizeof(req)), req);
 		chan->num_conf_req++;
 		break;
 
@@ -4080,7 +4086,7 @@
 	}
 
 	/* Complete config. */
-	len = l2cap_parse_conf_req(chan, rsp);
+	len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp));
 	if (len < 0) {
 		l2cap_send_disconn_req(chan, ECONNRESET);
 		goto unlock;
@@ -4114,7 +4120,7 @@
 	if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
 		u8 buf[64];
 		l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
-			       l2cap_build_conf_req(chan, buf), buf);
+			       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
 		chan->num_conf_req++;
 	}
 
@@ -4174,7 +4180,7 @@
 			char buf[64];
 
 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
-						   buf, &result);
+						   buf, sizeof(buf), &result);
 			if (len < 0) {
 				l2cap_send_disconn_req(chan, ECONNRESET);
 				goto done;
@@ -4204,7 +4210,7 @@
 			/* throw out any old stored conf requests */
 			result = L2CAP_CONF_SUCCESS;
 			len = l2cap_parse_conf_rsp(chan, rsp->data, len,
-						   req, &result);
+						   req, sizeof(req), &result);
 			if (len < 0) {
 				l2cap_send_disconn_req(chan, ECONNRESET);
 				goto done;
@@ -4781,7 +4787,7 @@
 			set_bit(CONF_REQ_SENT, &chan->conf_state);
 			l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
 				       L2CAP_CONF_REQ,
-				       l2cap_build_conf_req(chan, buf), buf);
+				       l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
 			chan->num_conf_req++;
 		}
 	}
@@ -7457,7 +7463,7 @@
 				set_bit(CONF_REQ_SENT, &chan->conf_state);
 				l2cap_send_cmd(conn, l2cap_get_ident(conn),
 					       L2CAP_CONF_REQ,
-					       l2cap_build_conf_req(chan, buf),
+					       l2cap_build_conf_req(chan, buf, sizeof(buf)),
 					       buf);
 				chan->num_conf_req++;
 			}
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index ade9306..1cf2874 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -1772,7 +1772,7 @@
 		kgid_t gid_max = make_kgid(&init_user_ns, info->gid_max);
 		set_sk_callback_lock = true;
 		read_lock_bh(&sk->sk_callback_lock);
-		MT_DEBUG("qtaguid[%d]: sk=%p->sk_socket=%p->file=%p\n",
+		MT_DEBUG("qtaguid[%d]: sk=%pK->sk_socket=%pK->file=%pK\n",
 			par->hooknum, sk, sk->sk_socket,
 			sk->sk_socket ? sk->sk_socket->file : (void *)-1LL);
 		filp = sk->sk_socket ? sk->sk_socket->file : NULL;
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 413deff..cad82a4 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -223,17 +223,16 @@
 	(5490 - 5710 @ 160), (30), DFS
 
 country BZ:
-	(2402 - 2482 @ 40), (36)
-	(5170 - 5330 @ 160), (27)
-	(5490 - 5730 @ 160), (36)
-	(5735 - 5835 @ 80), (36)
+	(2402 - 2482 @ 40), (20)
+	(5170 - 5330 @ 160), (23)
+	(5490 - 5730 @ 160), (30)
+	(5735 - 5835 @ 80), (30)
 
 country CA: DFS-FCC
 	(2402 - 2472 @ 40), (30)
 	(5170 - 5250 @ 80), (24), AUTO-BW
 	(5250 - 5330 @ 80), (24), DFS, AUTO-BW
-	(5490 - 5590 @ 80), (24), DFS
-	(5650 - 5730 @ 80), (24), DFS
+	(5490 - 5730 @ 160), (24), DFS
 	(5735 - 5835 @ 80), (30)
 	# 60 gHz band channels 1-3
 	(57240 - 63720 @ 2160), (40)
@@ -682,7 +681,13 @@
 country IN:
 	(2402 - 2482 @ 40), (20)
 	(5170 - 5330 @ 160), (23)
-	(5735 - 5835 @ 80), (30)
+	(5735 - 5835 @ 80), (33)
+
+country IQ: DFS-ETSI
+	(2402 - 2482 @ 40), (20)
+	(5170 - 5250 @ 80), (23), AUTO-BW
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5490 - 5710 @ 160), (30), DFS
 
 country IS: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
@@ -736,7 +741,6 @@
 
 country JP: DFS-JP
 	(2402 - 2482 @ 40), (20)
-	(2474 - 2494 @ 20), (20), NO-OFDM
 	(5170 - 5250 @ 80), (20), AUTO-BW, NO-OUTDOOR
 	(5250 - 5330 @ 80), (20), DFS, AUTO-BW, NO-OUTDOOR
 	(5490 - 5710 @ 160), (20), DFS
@@ -758,7 +762,7 @@
 country KN: DFS-FCC
 	(2402 - 2482 @ 40), (20)
 	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5250 - 5330 @ 80), (30), DFS, AUTO-BW
 	(5490 - 5710 @ 160), (30), DFS
 	(5735 - 5815 @ 80), (30)
 
@@ -1009,7 +1013,7 @@
 	(5170 - 5250 @ 80), (24), AUTO-BW
 	(5250 - 5330 @ 80), (24), DFS, AUTO-BW
 	(5490 - 5650 @ 160), (24), DFS
-	(5735 - 5815 @ 80), (24)
+	(5735 - 5835 @ 80), (24)
 	# 60 gHz band channels 1-3
 	(57240 - 63720 @ 2160), (40)
 
@@ -1089,7 +1093,7 @@
 	(5490 - 5710 @ 160), (30), DFS
 
 country PA:
-	(2402 - 2472 @ 40), (30)
+	(2402 - 2472 @ 40), (36)
 	(5170 - 5250 @ 80), (23), AUT0-BW
 	(5250 - 5330 @ 80), (30), AUTO-BW
 	(5735 - 5835 @ 80), (36)
@@ -1374,9 +1378,9 @@
 
 country TT:
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5330 @ 160), (27)
-	(5490 - 5730 @ 160), (36)
-	(5735 - 5835 @ 80), (36)
+	(5170 - 5330 @ 160), (24)
+	(5490 - 5730 @ 160), (24)
+	(5735 - 5835 @ 80), (30)
 	# 60 gHz band channels 1-3, FCC
 	(57240 - 63720 @ 2160), (40)
 
@@ -1450,7 +1454,7 @@
 country UZ: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
 	(5170 - 5250 @ 80), (23), AUTO-BW
-	(5250 - 5330 @ 80), (20), DFS, AUTO-BW
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
 
 country VC: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
diff --git a/security/commoncap.c b/security/commoncap.c
index 3e44d01..b5aca42 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -58,7 +58,7 @@
 }
 
 /**
- * cap_capable - Determine whether a task has a particular effective capability
+ * __cap_capable - Determine whether a task has a particular effective capability
  * @cred: The credentials to use
  * @ns:  The user namespace in which we need the capability
  * @cap: The capability to check for
@@ -72,18 +72,11 @@
  * cap_has_capability() returns 0 when a task has a capability, but the
  * kernel's capable() and has_capability() returns 1 for this case.
  */
-int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
+int __cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
 		int cap, int audit)
 {
 	struct user_namespace *ns = targ_ns;
 
-#ifdef CONFIG_ANDROID_PARANOID_NETWORK
-	if (cap == CAP_NET_RAW && in_egroup_p(AID_NET_RAW))
-		return 0;
-	if (cap == CAP_NET_ADMIN && in_egroup_p(AID_NET_ADMIN))
-		return 0;
-#endif
-
 	/* See if cred has the capability in the target user namespace
 	 * by examining the target user namespace and all of the target
 	 * user namespace's parents.
@@ -114,6 +107,27 @@
 	/* We never get here */
 }
 
+int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
+		int cap, int audit)
+{
+	int ret = __cap_capable(cred, targ_ns, cap, audit);
+
+#ifdef CONFIG_ANDROID_PARANOID_NETWORK
+	if (ret != 0 && cap == CAP_NET_RAW && in_egroup_p(AID_NET_RAW)) {
+		printk("Process %s granted CAP_NET_RAW from Android group net_raw.\n", current->comm);
+		printk("  Please update the .rc file to explictly set 'capabilities NET_RAW'\n");
+		printk("  Implicit grants are deprecated and will be removed in the future.\n");
+		return 0;
+	}
+	if (ret != 0 && cap == CAP_NET_ADMIN && in_egroup_p(AID_NET_ADMIN)) {
+		printk("Process %s granted CAP_NET_ADMIN from Android group net_admin.\n", current->comm);
+		printk("  Please update the .rc file to explictly set 'capabilities NET_ADMIN'\n");
+		printk("  Implicit grants are deprecated and will be removed in the future.\n");
+		return 0;
+	}
+#endif
+	return ret;
+}
 /**
  * cap_settime - Determine whether the current process may set the system clock
  * @ts: The time to set
diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c
index ffc67fd..58e59cd 100644
--- a/sound/isa/msnd/msnd_midi.c
+++ b/sound/isa/msnd/msnd_midi.c
@@ -120,24 +120,24 @@
 	unsigned long flags;
 	struct snd_msndmidi *mpu = mpuv;
 	void *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF;
+	u16 head, tail, size;
 
 	spin_lock_irqsave(&mpu->input_lock, flags);
-	while (readw(mpu->dev->MIDQ + JQS_wTail) !=
-	       readw(mpu->dev->MIDQ + JQS_wHead)) {
-		u16 wTmp, val;
-		val = readw(pwMIDQData + 2 * readw(mpu->dev->MIDQ + JQS_wHead));
+	head = readw(mpu->dev->MIDQ + JQS_wHead);
+	tail = readw(mpu->dev->MIDQ + JQS_wTail);
+	size = readw(mpu->dev->MIDQ + JQS_wSize);
+	if (head > size || tail > size)
+		goto out;
+	while (head != tail) {
+		unsigned char val = readw(pwMIDQData + 2 * head);
 
-			if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER,
-				     &mpu->mode))
-				snd_rawmidi_receive(mpu->substream_input,
-						    (unsigned char *)&val, 1);
-
-		wTmp = readw(mpu->dev->MIDQ + JQS_wHead) + 1;
-		if (wTmp > readw(mpu->dev->MIDQ + JQS_wSize))
-			writew(0,  mpu->dev->MIDQ + JQS_wHead);
-		else
-			writew(wTmp,  mpu->dev->MIDQ + JQS_wHead);
+		if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
+			snd_rawmidi_receive(mpu->substream_input, &val, 1);
+		if (++head > size)
+			head = 0;
+		writew(head, mpu->dev->MIDQ + JQS_wHead);
 	}
+ out:
 	spin_unlock_irqrestore(&mpu->input_lock, flags);
 }
 EXPORT_SYMBOL(snd_msndmidi_input_read);
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
index 4c07266..a31ea6c 100644
--- a/sound/isa/msnd/msnd_pinnacle.c
+++ b/sound/isa/msnd/msnd_pinnacle.c
@@ -170,23 +170,24 @@
 {
 	struct snd_msnd *chip = dev_id;
 	void *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF;
+	u16 head, tail, size;
 
 	/* Send ack to DSP */
 	/* inb(chip->io + HP_RXL); */
 
 	/* Evaluate queued DSP messages */
-	while (readw(chip->DSPQ + JQS_wTail) != readw(chip->DSPQ + JQS_wHead)) {
-		u16 wTmp;
-
-		snd_msnd_eval_dsp_msg(chip,
-			readw(pwDSPQData + 2 * readw(chip->DSPQ + JQS_wHead)));
-
-		wTmp = readw(chip->DSPQ + JQS_wHead) + 1;
-		if (wTmp > readw(chip->DSPQ + JQS_wSize))
-			writew(0, chip->DSPQ + JQS_wHead);
-		else
-			writew(wTmp, chip->DSPQ + JQS_wHead);
+	head = readw(chip->DSPQ + JQS_wHead);
+	tail = readw(chip->DSPQ + JQS_wTail);
+	size = readw(chip->DSPQ + JQS_wSize);
+	if (head > size || tail > size)
+		goto out;
+	while (head != tail) {
+		snd_msnd_eval_dsp_msg(chip, readw(pwDSPQData + 2 * head));
+		if (++head > size)
+			head = 0;
+		writew(head, chip->DSPQ + JQS_wHead);
 	}
+ out:
 	/* Send ack to DSP */
 	inb(chip->io + HP_RXL);
 	return IRQ_HANDLED;
diff --git a/tools/testing/selftests/x86/fsgsbase.c b/tools/testing/selftests/x86/fsgsbase.c
index 5b2b4b3..9b4610c 100644
--- a/tools/testing/selftests/x86/fsgsbase.c
+++ b/tools/testing/selftests/x86/fsgsbase.c
@@ -285,9 +285,12 @@
 	}
 }
 
-static void set_gs_and_switch_to(unsigned long local, unsigned long remote)
+static void set_gs_and_switch_to(unsigned long local,
+				 unsigned short force_sel,
+				 unsigned long remote)
 {
 	unsigned long base;
+	unsigned short sel_pre_sched, sel_post_sched;
 
 	bool hard_zero = false;
 	if (local == HARD_ZERO) {
@@ -297,6 +300,8 @@
 
 	printf("[RUN]\tARCH_SET_GS(0x%lx)%s, then schedule to 0x%lx\n",
 	       local, hard_zero ? " and clear gs" : "", remote);
+	if (force_sel)
+		printf("\tBefore schedule, set selector to 0x%hx\n", force_sel);
 	if (syscall(SYS_arch_prctl, ARCH_SET_GS, local) != 0)
 		err(1, "ARCH_SET_GS");
 	if (hard_zero)
@@ -307,18 +312,35 @@
 		printf("[FAIL]\tGSBASE wasn't set as expected\n");
 	}
 
+	if (force_sel) {
+		asm volatile ("mov %0, %%gs" : : "rm" (force_sel));
+		sel_pre_sched = force_sel;
+		local = read_base(GS);
+
+		/*
+		 * Signal delivery seems to mess up weird selectors.  Put it
+		 * back.
+		 */
+		asm volatile ("mov %0, %%gs" : : "rm" (force_sel));
+	} else {
+		asm volatile ("mov %%gs, %0" : "=rm" (sel_pre_sched));
+	}
+
 	remote_base = remote;
 	ftx = 1;
 	syscall(SYS_futex, &ftx, FUTEX_WAKE, 0, NULL, NULL, 0);
 	while (ftx != 0)
 		syscall(SYS_futex, &ftx, FUTEX_WAIT, 1, NULL, NULL, 0);
 
+	asm volatile ("mov %%gs, %0" : "=rm" (sel_post_sched));
 	base = read_base(GS);
-	if (base == local) {
-		printf("[OK]\tGSBASE remained 0x%lx\n", local);
+	if (base == local && sel_pre_sched == sel_post_sched) {
+		printf("[OK]\tGS/BASE remained 0x%hx/0x%lx\n",
+		       sel_pre_sched, local);
 	} else {
 		nerrs++;
-		printf("[FAIL]\tGSBASE changed to 0x%lx\n", base);
+		printf("[FAIL]\tGS/BASE changed from 0x%hx/0x%lx to 0x%hx/0x%lx\n",
+		       sel_pre_sched, local, sel_post_sched, base);
 	}
 }
 
@@ -381,8 +403,15 @@
 
 	for (int local = 0; local < 4; local++) {
 		for (int remote = 0; remote < 4; remote++) {
-			set_gs_and_switch_to(bases_with_hard_zero[local],
-					     bases_with_hard_zero[remote]);
+			for (unsigned short s = 0; s < 5; s++) {
+				unsigned short sel = s;
+				if (s == 4)
+					asm ("mov %%ss, %0" : "=rm" (sel));
+				set_gs_and_switch_to(
+					bases_with_hard_zero[local],
+					sel,
+					bases_with_hard_zero[remote]);
+			}
 		}
 	}