Merge "ARM: dts: msm: Add support for clocks for SDM632"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index 9bc8168..d150116 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -328,6 +328,9 @@
 compatible = "qcom,sdm450-cdp"
 compatible = "qcom,sdm450-qrd"
 compatible = "qcom,sdm632-rumi"
+compatible = "qcom,sdm632-cdp"
+compatible = "qcom,sdm632-mtp"
+compatible = "qcom,sdm632-qrd"
 compatible = "qcom,mdm9640-cdp"
 compatible = "qcom,mdm9640-mtp"
 compatible = "qcom,mdm9640-rumi"
diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
index 07667a4..8d6fad0 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
@@ -31,6 +31,7 @@
 	* "qcom,pdc-sdm845": For sdm845 pin data
 	* "qcom,pdc-sdm845-v2": For sdm845 v2 pin data
 	* "qcom,pdc-sdm670": For sdm670 pin data
+	* "qcom,pdc-sdxpoorwills": For sdxpoorwills pin data
 
 - reg:
 	Usage: required
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-haptics.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-haptics.txt
index b7ce662..1a76d5d 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp-haptics.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp-haptics.txt
@@ -118,6 +118,18 @@
 
 Following properties are specific only to LRA vibrators.
 
+- qcom,lra-auto-mode
+  Usage:      optional
+  Value type: <empty>
+  Definition: If specified, a set of pre-configured settings will be applied
+		based on the pattern duration. For example, for a duration of
+		< 20 ms (short duration), one set of settings will be applied
+		and for a duration of >= 20 ms (long duration), another set of
+		settings will be applied. The parameters configured in the
+		driver when this property is specified is based on the LRA
+		tested internally. Those parameters should be fine-tuned or
+		adjusted based on the LRA used on different hardware platforms.
+
 - qcom,lra-auto-res-mode
   Usage:      optional
   Value type: <string>
@@ -200,9 +212,13 @@
 - qcom,wave-samples
   Usage:      optional
   Value type: <prop-encoded-array>
-  Definition: Wave samples in an array of 8 elements. Each element takes the
+  Definition: Wave samples in an array of 32 elements. Each element takes the
 		following representation, bit 0: unused, bits[5:1] : amplitude,
 		bit 6: overdrive, bit 7: sign. Default sample value is 0x3E.
+		Since the hardware supports configuring upto 8 samples, a set
+		of 8 samples will be configured initially and the next set will
+		be configured upon the play interrupt until all the samples are
+		configured and played.
 
 Following properties are applicable only when "qcom,play-mode" is set to
 "pwm".
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8937-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8937-pinctrl.txt
new file mode 100644
index 0000000..f697704
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8937-pinctrl.txt
@@ -0,0 +1,204 @@
+Qualcomm Technologies, Inc. MSM8937 TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+MSM8937 platform.
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be "qcom,msm8937-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-gpio133,
+		    sdc1_clk,
+		    sdc1_cmd,
+		    sdc1_data,
+		    sdc1_rclk,
+		    sdc2_clk,
+		    sdc2_cmd,
+		    sdc2_data,
+		    qdsd_clk,
+		    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:
+        qdss_tracedata_b, blsp_uart1, gpio, blsp_spi1, adsp_ext, blsp_i2c1, prng_rosc,
+        qdss_cti_trig_out_b0, blsp_spi2, blsp_uart2, blsp_uart3, pbs0, pbs1,
+        pwr_modem_enabled_b, blsp_i2c3, gcc_gp2_clk_b, ldo_update,
+        atest_combodac_to_gpio_native, ldo_en, blsp_i2c2, gcc_gp1_clk_b, pbs2,
+        atest_gpsadc_dtest0_native, blsp_spi3, gcc_gp3_clk_b, blsp_spi4, blsp_uart4,
+        sec_mi2s, pwr_nav_enabled_b, codec_mad, pwr_crypto_enabled_b, blsp_i2c4,
+        blsp_spi5, blsp_uart5, qdss_traceclk_a, atest_bbrx1, m_voc,
+        qdss_cti_trig_in_a0, qdss_cti_trig_in_b0, blsp_i2c6, qdss_traceclk_b,
+        atest_wlan0, atest_wlan1, atest_bbrx0, blsp_i2c5, qdss_tracectl_a,
+        atest_gpsadc_dtest1_native, qdss_tracedata_a, blsp_spi6, blsp_uart6,
+        qdss_tracectl_b, mdp_vsync, pri_mi2s_mclk_a, sec_mi2s_mclk_a, cam_mclk,
+        cci_i2c, pwr_modem_enabled_a, cci_timer0, cci_timer1, cam1_standby,
+        pwr_nav_enabled_a, cam1_rst, pwr_crypto_enabled_a, forced_usb,
+        qdss_cti_trig_out_b1, cam2_rst, webcam_standby, cci_async, webcam_rst,
+        ov_ldo, sd_write, accel_int, gcc_gp1_clk_a, alsp_int, gcc_gp2_clk_a,
+        mag_int, gcc_gp3_clk_a, blsp6_spi, fp_int, qdss_cti_trig_in_b1, uim_batt,
+        cam2_standby, uim1_data, uim1_clk, uim1_reset, uim1_present, uim2_data,
+        uim2_clk, uim2_reset, uim2_present, sensor_rst, mipi_dsi0, smb_int,
+        cam0_ldo, us_euro, atest_char3, dbg_out, bimc_dte0, ts_resout, ts_sample,
+        sec_mi2s_mclk_b, pri_mi2s, sdcard_det, atest_char1, ebi_cdc, audio_reset,
+        atest_char0, audio_ref, cdc_pdm0, 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, cri_trng, cri_trng1, cri_trng0, blsp_spi7, blsp_uart7,
+        pri_mi2s_ws, blsp_i2c7, gcc_tlmm, dmic0_clk, dmic0_data, key_volp,
+        qdss_cti_trig_in_a1, us_emitter, wsa_irq, wsa_io, wsa_reset, blsp_spi8,
+        blsp_uart8, blsp_i2c8, gcc_plltest, nav_pps_in_a, pa_indicator, modem_tsync,
+        nav_tsync, nav_pps_in_b, nav_pps, gsm0_tx, atest_char, atest_tsens,
+        bimc_dte1, ssbi_wtr1, fp_gpio, coex_uart, key_snapshot, key_focus, nfc_pwr,
+        blsp8_spi, qdss_cti_trig_out_a0, qdss_cti_trig_out_a1
+
+- 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,msm8937-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/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
index f50fd88..75996a5 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
@@ -104,6 +104,13 @@
 		    this property is not specified, then the default value used
 		    will be 75mA.
 
+- qcom,fg-cutoff-current
+	Usage:      optional
+	Value type: <u32>
+	Definition: Minimum Battery current (in mA) used for cutoff SOC
+		    estimate. If this property is not specified, then a default
+		    value of 500 mA will be applied.
+
 - qcom,fg-delta-soc-thr
 	Usage:      optional
 	Value type: <u32>
diff --git a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
index be8c2f0..e64599c 100644
--- a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
+++ b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
@@ -74,9 +74,11 @@
 Required properties:
 - compatible : Must be "qcom,msm-adsprpc-mem-region"
 - memory-region : CMA region which is owned by this device
+- restrict-access : Blocking vote for hyp_assign_phys function call
 
 Example:
        qcom,adsprpc-mem {
                compatible = "qcom,msm-adsprpc-mem-region";
                memory-region = <&adsp_mem>;
+               restrict-access;
        };
diff --git a/Documentation/devicetree/bindings/usb/msm-phy.txt b/Documentation/devicetree/bindings/usb/msm-phy.txt
index f8c8a69..f7f4ced 100644
--- a/Documentation/devicetree/bindings/usb/msm-phy.txt
+++ b/Documentation/devicetree/bindings/usb/msm-phy.txt
@@ -184,6 +184,10 @@
    state when attached in host mode and "suspend" state when detached.
  - qcom,tune2-efuse-correction: The value to be adjusted from fused value for
    improved rise/fall times.
+ - nvmem-cells: specifies the handle to represent the SoC revision.
+   usually it is defined by qfprom device node.
+ - nvmem-cell-names: specifies the given nvmem cell name as defined in
+   qfprom node.
 
 Example:
 	qusb_phy: qusb@f9b39000 {
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d8d8b82..41245ce 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -12,6 +12,7 @@
 	select ARCH_USE_BUILTIN_BSWAP
 	select ARCH_USE_CMPXCHG_LOCKREF
 	select ARCH_WANT_IPC_PARSE_VERSION
+	select ARM_PSCI_FW if PM
 	select BUILDTIME_EXTABLE_SORT if MMU
 	select CLONE_BACKWARDS
 	select CPU_PM if (SUSPEND || CPU_IDLE)
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi
new file mode 100644
index 0000000..f8baa04
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi
@@ -0,0 +1,1070 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	csr: csr@6001000 {
+		compatible = "qcom,coresight-csr";
+		reg = <0x6001000 0x1000>;
+		reg-names = "csr-base";
+
+		coresight-name = "coresight-csr";
+
+		qcom,blk-size = <1>;
+	};
+
+	tmc_etr: tmc@6048000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b961>;
+
+		reg = <0x6048000 0x1000>,
+		      <0x6064000 0x15000>;
+		reg-names = "tmc-base", "bam-base";
+
+		arm,buffer-size = <0x400000>;
+		arm,sg-enable;
+
+		coresight-name = "coresight-tmc-etr";
+		coresight-ctis = <&cti0 &cti8>;
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		interrupts = <GIC_SPI 251 IRQ_TYPE_EDGE_RISING>;
+		interrupt-names = "byte-cntr-irq";
+
+		port {
+			tmc_etr_in_replicator: endpoint {
+				slave-mode;
+				remote-endpoint = <&replicator_out_tmc_etr>;
+			};
+		};
+	};
+
+	replicator_qdss: replicator@6046000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b909>;
+
+		reg = <0x6046000 0x1000>;
+		reg-names = "replicator-base";
+
+		coresight-name = "coresight-replicator";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				replicator_out_tmc_etr: endpoint {
+					remote-endpoint=
+						<&tmc_etr_in_replicator>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				replicator_in_tmc_etf: endpoint {
+					slave-mode;
+					remote-endpoint=
+						<&tmc_etf_out_replicator>;
+				};
+			};
+		};
+	};
+
+	tmc_etf: tmc@6047000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b961>;
+
+		reg = <0x6047000 0x1000>;
+		reg-names = "tmc-base";
+
+		coresight-name = "coresight-tmc-etf";
+		coresight-ctis = <&cti0 &cti8>;
+		arm,default-sink;
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				tmc_etf_out_replicator: endpoint {
+					remote-endpoint =
+						<&replicator_in_tmc_etf>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				tmc_etf_in_funnel_merg: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_merg_out_tmc_etf>;
+				};
+			};
+		};
+	};
+
+	funnel_merg: funnel@6045000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6045000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-merg";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_merg_out_tmc_etf: endpoint {
+					remote-endpoint =
+						<&tmc_etf_in_funnel_merg>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				funnel_merg_in_funnel_in0: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_in0_out_funnel_merg>;
+				};
+			};
+
+			port@2 {
+				reg = <1>;
+				funnel_merg_in_funnel_in1: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_in1_out_funnel_merg>;
+				};
+			};
+		};
+	};
+
+	funnel_in0: funnel@6041000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6041000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-in0";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_in0_out_funnel_merg: endpoint {
+					remote-endpoint =
+						<&funnel_merg_in_funnel_in0>;
+				};
+			};
+
+			port@1 {
+				reg = <6>;
+				funnel_in0_in_funnel_qatb: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_qatb_out_funnel_in0>;
+				};
+			};
+
+			port@2 {
+				reg = <7>;
+				funnel_in0_in_stm: endpoint {
+					slave-mode;
+					remote-endpoint = <&stm_out_funnel_in0>;
+				};
+			};
+		};
+	};
+
+	stm: stm@6002000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b962>;
+
+		reg = <0x6002000 0x1000>,
+		      <0x16280000 0x180000>;
+		reg-names = "stm-base", "stm-stimulus-base";
+
+		coresight-name = "coresight-stm";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		port {
+			stm_out_funnel_in0: endpoint {
+				remote-endpoint = <&funnel_in0_in_stm>;
+			};
+		};
+
+	};
+
+	funnel_qatb: funnel@6005000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6005000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-qatb";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_qatb_out_funnel_in0: endpoint {
+					remote-endpoint =
+						<&funnel_in0_in_funnel_qatb>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				funnel_qatb_in_tpda: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpda_out_funnel_qatb>;
+				};
+			};
+		};
+	};
+
+	tpda: tpda@6004000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
+		reg = <0x6004000 0x1000>;
+		reg-names = "tpda-base";
+
+		coresight-name = "coresight-tpda";
+
+		qcom,tpda-atid = <65>;
+		qcom,bc-elem-size = <10 32>,
+				    <13 32>;
+		qcom,tc-elem-size = <13 32>;
+		qcom,dsb-elem-size = <0 32>,
+				     <2 32>,
+				     <3 32>,
+				     <5 32>,
+				     <6 32>,
+				     <10 32>,
+				     <11 32>,
+				     <13 32>;
+		qcom,cmb-elem-size = <3 64>,
+				     <7 64>,
+				     <9 64>,
+				     <13 64>;
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				tpda_out_funnel_qatb: endpoint {
+					remote-endpoint =
+						<&funnel_qatb_in_tpda>;
+				};
+
+			};
+
+			port@1 {
+				reg = <0>;
+				tpda_in_funnel_ddr_0: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_ddr_0_out_tpda>;
+				};
+			};
+
+			port@2 {
+				reg = <1>;
+				tpda_in_tpdm_vsense: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_vsense_out_tpda>;
+				};
+			};
+
+			port@3 {
+				reg = <2>;
+				tpda_in_tpdm_dcc: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_dcc_out_tpda>;
+				};
+			};
+
+			port@4 {
+				reg = <5>;
+				tpda_in_tpdm_center: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_center_out_tpda>;
+				};
+			};
+		};
+	};
+
+	funnel_ddr_0: funnel@69e2000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x69e2000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-ddr-0";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_ddr_0_out_tpda: endpoint {
+					remote-endpoint =
+					    <&tpda_in_funnel_ddr_0>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				funnel_ddr_0_in_tpdm_ddr: endpoint {
+					slave-mode;
+					remote-endpoint =
+					    <&tpdm_ddr_out_funnel_ddr_0>;
+				};
+			};
+		};
+	};
+
+	tpdm_dcc: tpdm@6870280 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
+		reg = <0x6870280 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-dcc";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		port{
+			tpdm_dcc_out_tpda: endpoint {
+				remote-endpoint = <&tpda_in_tpdm_dcc>;
+			};
+		};
+	};
+
+	tpdm_vsense: tpdm@6840000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
+		reg = <0x6840000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-vsense";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		port{
+			tpdm_vsense_out_tpda: endpoint {
+				remote-endpoint = <&tpda_in_tpdm_vsense>;
+			};
+		};
+	};
+
+	tpdm_center: tpdm@6c28000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
+		reg = <0x6c28000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-center";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		port{
+			tpdm_center_out_tpda: endpoint {
+				remote-endpoint = <&tpda_in_tpdm_center>;
+			};
+		};
+	};
+
+	tpdm_ddr: tpdm@69e0000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
+		reg = <0x69e0000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-ddr";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		qcom,msr-fix-req;
+
+		port {
+			tpdm_ddr_out_funnel_ddr_0: endpoint {
+				remote-endpoint = <&funnel_ddr_0_in_tpdm_ddr>;
+			};
+		};
+	};
+
+	funnel_in1: funnel@6042000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6042000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-in1";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_in1_out_funnel_merg: endpoint {
+					remote-endpoint =
+						<&funnel_merg_in_funnel_in1>;
+				};
+			};
+
+			port@1 {
+				reg = <2>;
+				funnel_in1_in_funnel_swao: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_swao_out_funnel_in1>;
+				};
+			};
+
+			port@2 {
+				reg = <3>;
+				funnel_in1_in_modem_etm0: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&modem_etm0_out_funnel_in1>;
+				};
+			};
+
+			port@3 {
+				reg = <7>;
+				funnel_in1_in_tpda_modem: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpda_modem_out_funnel_in1>;
+				};
+			};
+		};
+	};
+
+	modem_etm0 {
+		compatible = "qcom,coresight-remote-etm";
+
+		coresight-name = "coresight-modem-etm0";
+		qcom,inst-id = <2>;
+
+		port {
+			modem_etm0_out_funnel_in1: endpoint {
+				remote-endpoint =
+					<&funnel_in1_in_modem_etm0>;
+			};
+		};
+	};
+
+	funnel_swao:funnel@6b08000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6b08000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-swao";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				funnel_swao_out_funnel_in1: endpoint {
+					remote-endpoint =
+						<&funnel_in1_in_funnel_swao>;
+				};
+			};
+
+			port@1 {
+				reg = <7>;
+				funnel_swao_in_tpda_swao: endpoint {
+					slave-mode;
+					remote-endpoint=
+						<&tpda_swao_out_funnel_swao>;
+				};
+			};
+		};
+	};
+
+	tpda_modem: tpda@6832000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
+		reg = <0x6832000 0x1000>;
+		reg-names = "tpda-base";
+
+		coresight-name = "coresight-tpda-modem";
+
+		qcom,tpda-atid = <67>;
+		qcom,dsb-elem-size = <0 32>;
+		qcom,cmb-elem-size = <0 64>;
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			port@0 {
+				reg = <0>;
+				tpda_modem_out_funnel_in1: endpoint {
+					remote-endpoint =
+						<&funnel_in1_in_tpda_modem>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				tpda_modem_in_tpdm_modem: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_modem_out_tpda_modem>;
+				};
+			};
+		};
+	};
+
+	tpdm_modem: tpdm@6830000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
+		reg = <0x6830000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-modem";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		port {
+			tpdm_modem_out_tpda_modem: endpoint {
+				remote-endpoint = <&tpda_modem_in_tpdm_modem>;
+			};
+		};
+	};
+
+	tpda_swao: tpda@6b01000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
+		reg = <0x6b01000 0x1000>;
+		reg-names = "tpda-base";
+
+		coresight-name = "coresight-tpda-swao";
+
+		qcom,tpda-atid = <71>;
+		qcom,dsb-elem-size = <1 32>;
+		qcom,cmb-elem-size = <0 64>;
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				tpda_swao_out_funnel_swao: endpoint {
+					remote-endpoint =
+						<&funnel_swao_in_tpda_swao>;
+				};
+
+			};
+
+			port@1 {
+				reg = <0>;
+				tpda_swao_in_tpdm_swao0: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_swao0_out_tpda_swao>;
+				};
+			};
+
+			port@2 {
+				reg = <1>;
+				tpda_swao_in_tpdm_swao1: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpdm_swao1_out_tpda_swao>;
+				};
+
+			};
+		};
+	};
+
+	tpdm_swao0: tpdm@6b02000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
+
+		reg = <0x6b02000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name = "coresight-tpdm-swao-0";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		port {
+			tpdm_swao0_out_tpda_swao: endpoint {
+				remote-endpoint = <&tpda_swao_in_tpdm_swao0>;
+			};
+		};
+	};
+
+	tpdm_swao1: tpdm@6b03000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
+		reg = <0x6b03000 0x1000>;
+		reg-names = "tpdm-base";
+
+		coresight-name="coresight-tpdm-swao-1";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		qcom,msr-fix-req;
+
+		port {
+			tpdm_swao1_out_tpda_swao: endpoint {
+				remote-endpoint = <&tpda_swao_in_tpdm_swao1>;
+			};
+		};
+	};
+
+	ipcb_tgu: tgu@6b0c000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b999>;
+		reg = <0x6b0c000 0x1000>;
+		reg-names = "tgu-base";
+		tgu-steps = <3>;
+		tgu-conditions = <4>;
+		tgu-regs = <4>;
+		tgu-timer-counters = <8>;
+
+		coresight-name = "coresight-tgu-ipcb";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti0: cti@6010000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6010000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti0";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti1: cti@6011000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6011000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti1";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti2: cti@6012000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6012000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti2";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti3: cti@6013000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6013000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti3";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti4: cti@6014000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6014000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti4";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti5: cti@6015000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6015000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti5";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti6: cti@6016000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6016000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti6";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti7: cti@6017000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6017000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti7";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti8: cti@6018000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6018000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti8";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti9: cti@6019000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6019000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti9";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti10: cti@601a000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x601a000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti10";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti11: cti@601b000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x601b000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti11";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti12: cti@601c000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x601c000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti12";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti13: cti@601d000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x601d000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti13";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti14: cti@601e000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x601e000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti14";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti15: cti@601f000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x601f000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti15";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti_cpu0: cti@7003000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x7003000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-cpu0";
+		cpu = <&CPU0>;
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+	};
+
+	cti_modem_cpu0:cti@6837000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6837000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-modem-cpu0";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_modem_cpu1:cti@683b000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x683b000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-modem-cpu1";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti0_swao:cti@6b04000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6b04000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-swao_cti0";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti1_swao:cti@6b05000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6b05000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-swao_cti1";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti2_swao:cti@6b06000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6b06000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-swao_cti2";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti3_swao:cti@6b07000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x6b07000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-swao_cti3";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti0_ddr0: cti@69e1000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x69e1000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-ddr_dl_0_cti";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti0_ddr1: cti@69e4000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x69e4000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-ddr_dl_1_cti0";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti1_ddr1: cti@69e5000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x69e5000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-ddr_dl_1_cti1";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	cti2_ddr1: cti@69e6000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+		reg = <0x69e6000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-name = "coresight-cti-ddr_dl_1_cti2";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+
+	hwevent: hwevent@0x014066f0 {
+		compatible = "qcom,coresight-hwevent";
+		reg = <0x14066f0 0x4>,
+		      <0x14166f0 0x4>,
+		      <0x1406038 0x4>,
+		      <0x1416038 0x4>;
+		reg-names = "ddr-ch0-cfg", "ddr-ch23-cfg", "ddr-ch0-ctrl",
+			    "ddr-ch23-ctrl";
+
+		coresight-name = "coresight-hwevent";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
index 1e212b7..deed94d 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
@@ -13,11 +13,13 @@
 &soc {
 	tlmm: pinctrl@3900000 {
 		compatible = "qcom,sdxpoorwills-pinctrl";
-		reg = <0x3900000 0x300000>;
+		reg = <0x3900000 0x300000>,
+			<0xB204900 0x280>;
 		interrupts = <0 212 0>;
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
+		interrupt-parent = <&pdc>;
 		#interrupt-cells = <2>;
 
 		uart2_console_active: uart2_console_active {
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
new file mode 100644
index 0000000..eab887c
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
@@ -0,0 +1,95 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+&soc {
+
+	qcom,lpm-levels {
+		compatible = "qcom,lpm-levels";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,pm-cluster@0{
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			label = "system";
+			qcom,psci-mode-shift = <0>;
+			qcom,psci-mode-mask = <0xf>;
+
+			qcom,pm-cluster-level@0 {
+				reg = <0>;
+				label = "cx_active";
+				qcom,psci-mode = <0x0>;
+				qcom,latency-us = <270>;
+				qcom,ss-power = <455>;
+				qcom,energy-overhead = <270621>;
+				qcom,time-overhead = <500>;
+			};
+
+			qcom,pm-cluster-level@1 {
+				reg = <1>;
+				label = "cx_min";
+				qcom,psci-mode = <0x0>;
+				qcom,latency-us = <285>;
+				qcom,ss-power = <442>;
+				qcom,energy-overhead = <306621>;
+				qcom,time-overhead = <540>;
+				qcom,min-child-idx = <2>;
+				qcom,notify-rpm;
+				qcom,is-reset;
+			};
+
+			qcom,pm-cpu@0 {
+				#address-cells = <1>;
+				#size-cells = <0>;
+				qcom,psci-mode-shift = <0>;
+				qcom,psci-mode-mask = <0xf>;
+				qcom,cpu = <&CPU0>;
+
+				qcom,pm-cpu-level@0{
+					reg = <0>;
+					label = "wfi";
+					qcom,psci-cpu-mode = <0x1>;
+					qcom,latency-us = <1>;
+					qcom,ss-power = <473>;
+					qcom,energy-overhead = <100000>;
+					qcom,time-overhead = <25>;
+				};
+
+				qcom,pm-cpu-level@1 {
+					reg = <1>;
+					label ="standalone_pc";
+					qcom,psci-cpu-mode = <0x4>;
+					qcom,latency-us = <240>;
+					qcom,ss-power = <467>;
+					qcom,energy-overhead = <202781>;
+					qcom,time-overhead = <420>;
+					qcom,use-broadcast-timer;
+					qcom,is-reset;
+				};
+
+				qcom,pm-cpu-level@2 {
+					reg = <2>;
+					label = "system-pc";
+					qcom,psci-cpu-mode = <0x8>;
+					qcom,latency-us = <270>;
+					qcom,ss-power = <455>;
+					qcom,energy-overhead = <270621>;
+					qcom,time-overhead = <500>;
+					qcom,use-broadcast-timer;
+					qcom,is-reset;
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index 5829942..13d50f8 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -23,7 +23,7 @@
 	model = "Qualcomm Technologies, Inc. SDX POORWILLS";
 	compatible = "qcom,sdxpoorwills";
 	qcom,msm-id = <334 0x0>, <335 0x0>;
-	interrupt-parent = <&intc>;
+	interrupt-parent = <&pdc>;
 
 	reserved-memory {
 		#address-cells = <1>;
@@ -70,6 +70,7 @@
 		CPU0: cpu@0 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a7";
+			enable-method = "psci";
 			reg = <0x0>;
 			#cooling-cells = <2>;
 		};
@@ -81,6 +82,11 @@
 		sdhc1 = &sdhc_1; /* SDC1 eMMC/SD/SDIO slot */
 	};
 
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
 	soc: soc { };
 };
 
@@ -96,6 +102,15 @@
 		#interrupt-cells = <3>;
 		reg = <0x17800000 0x1000>,
 		      <0x17802000 0x1000>;
+		interrupt-parent = <&intc>;
+	};
+
+	pdc: interrupt-controller@b210000{
+		compatible = "qcom,pdc-sdxpoorwills";
+		reg = <0xb210000 0x30000>;
+		#interrupt-cells = <3>;
+		interrupt-parent = <&intc>;
+		interrupt-controller;
 	};
 
 	timer {
@@ -591,6 +606,8 @@
 		qcom,mhi-event-ring-id-limits = <9 10>; /* start and end */
 		qcom,modem-cfg-emb-pipe-flt;
 		qcom,use-ipa-pm;
+		qcom,arm-smmu;
+		qcom,smmu-fast-map;
 		qcom,bandwidth-vote-for-ipa;
 		qcom,msm-bus,name = "ipa";
 		qcom,msm-bus,num-cases = <5>;
@@ -729,6 +746,29 @@
 			compatible = "qcom,smp2pgpio-map-ipa-1-in";
 			gpios = <&smp2pgpio_ipa_1_in 0 0>;
 		};
+
+		ipa_smmu_ap: ipa_smmu_ap {
+			compatible = "qcom,ipa-smmu-ap-cb";
+			iommus = <&apps_smmu 0x5E0 0x0>;
+			qcom,iova-mapping = <0x20000000 0x40000000>;
+			qcom,additional-mapping =
+			/* modem tables in IMEM */
+			<0x14686000 0x14686000 0x3000>;
+		};
+
+		ipa_smmu_wlan: ipa_smmu_wlan {
+			compatible = "qcom,ipa-smmu-wlan-cb";
+			iommus = <&apps_smmu 0x5E1 0x0>;
+			qcom,additional-mapping =
+			/* ipa-uc ram */
+			<0x1E60000 0x1E60000 0xA000>;
+		};
+
+		ipa_smmu_uc: ipa_smmu_uc {
+			compatible = "qcom,ipa-smmu-uc-cb";
+			iommus = <&apps_smmu 0x5E2 0x0>;
+			qcom,iova-mapping = <0x40000000 0x20000000>;
+		};
 	};
 
 	qmp_aop: qcom,qmp-aop@c300000 {
@@ -764,6 +804,7 @@
 #include "sdxpoorwills-audio.dtsi"
 #include "sdxpoorwills-ion.dtsi"
 #include "msm-arm-smmu-sdxpoorwills.dtsi"
+#include "sdxpoorwills-coresight.dtsi"
 
 &soc {
 	emac_hw: qcom,emac@00020000 {
@@ -809,3 +850,16 @@
 		};
 	};
 };
+
+#include "pmxpoorwills.dtsi"
+#include "sdxpoorwills-blsp.dtsi"
+#include "sdxpoorwills-regulator.dtsi"
+#include "sdxpoorwills-smp2p.dtsi"
+#include "sdxpoorwills-usb.dtsi"
+#include "sdxpoorwills-pcie.dtsi"
+#include "sdxpoorwills-bus.dtsi"
+#include "sdxpoorwills-thermal.dtsi"
+#include "sdxpoorwills-audio.dtsi"
+#include "sdxpoorwills-ion.dtsi"
+#include "msm-arm-smmu-sdxpoorwills.dtsi"
+#include "sdxpoorwills-pm.dtsi"
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index d3500ae..a515e00 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -286,6 +286,7 @@
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_GADGET_VBUS_DRAW=500
 CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
 CONFIG_USB_CONFIGFS_MASS_STORAGE=y
 CONFIG_USB_CONFIGFS_F_FS=y
 CONFIG_USB_CONFIGFS_UEVENT=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index af75d1e..ba1acda 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -285,6 +285,7 @@
 CONFIG_USB_GADGET_DEBUG_FS=y
 CONFIG_USB_GADGET_VBUS_DRAW=500
 CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
 CONFIG_USB_CONFIGFS_MASS_STORAGE=y
 CONFIG_USB_CONFIGFS_F_FS=y
 CONFIG_USB_CONFIGFS_UEVENT=y
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index 4952b98..405e34d 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -51,6 +51,7 @@
 	select COMMON_CLK
 	select COMMON_CLK_QCOM
 	select QCOM_GDSC
+	select GENERIC_CLOCKEVENTS_BROADCAST
 
 config ARCH_MSM8953
 	bool "Enable support for MSM8953"
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index d35cecb..b7640d3 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -154,6 +154,15 @@
 	  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_MSM8937
+	bool "Enable Support for Qualcomm Technologies Inc. MSM8937"
+	depends on ARCH_QCOM
+	select CPU_FREQ_QCOM
+	select COMMON_CLK_MSM
+	help
+	  This enables support for the MSM8937 chipset. If you do not
+	  wish to build a kernel that runs on this chipset, say 'N' here.
+
 config ARCH_SDM450
 	bool "Enable Support for Qualcomm Technologies Inc. SDM450"
 	depends on ARCH_QCOM
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 80d3e82c..31386bd 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -287,7 +287,10 @@
 	sdm450-pmi632-cdp-s2.dtb \
 	sdm450-pmi632-mtp-s3.dtb
 
-dtb-$(CONFIG_ARCH_SDM632) += sdm632-rumi.dtb
+dtb-$(CONFIG_ARCH_SDM632) += sdm632-rumi.dtb \
+	sdm632-cdp-s2.dtb	\
+	sdm632-mtp-s3.dtb	\
+	sdm632-qrd-sku4.dtb
 
 endif
 
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dtsi
index a178aa1..a208e1a 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pmi8937.dtsi
@@ -24,6 +24,7 @@
 
 &usb3 {
 	vbus_dwc3-supply = <&smbcharger_charger_otg>;
+	extcon = <&pmi8937_charger>;
 };
 
 &pmi8937_charger {
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dtsi
index 71d6941..28fc0d7 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pmi8940.dtsi
@@ -24,6 +24,7 @@
 
 &usb3 {
 	vbus_dwc3-supply = <&smbcharger_charger_otg>;
+	extcon = <&pmi8940_charger>;
 };
 
 &labibb {
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pmi8950.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pmi8950.dtsi
index b9c2a18..944868b 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pmi8950.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pmi8950.dtsi
@@ -29,6 +29,7 @@
 
 &usb3 {
 	vbus_dwc3-supply = <&smbcharger_charger_otg>;
+	extcon = <&pmi8950_charger>;
 };
 
 &pmi8950_charger {
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index 69cd4fc..1f651fd 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -1281,6 +1281,22 @@
 		status = "disabled";
 	};
 
+	qcom,msm-adsprpc-mem {
+		compatible = "qcom,msm-adsprpc-mem-region";
+		memory-region = <&adsp_mem>;
+	};
+
+	qcom,msm_fastrpc {
+		compatible = "qcom,msm-fastrpc-legacy-compute";
+		qcom,msm_fastrpc_compute_cb {
+			compatible = "qcom,msm-fastrpc-legacy-compute-cb";
+			label = "adsprpc-smd";
+			iommus = <&apps_iommu 0x2408 0x7>;
+			sids = <0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf>;
+		};
+	};
+
+
 	ipa_hw: qcom,ipa@07900000 {
 		compatible = "qcom,ipa";
 		reg = <0x07900000 0x4effc>, <0x07904000 0x26934>;
diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi
index 4830af4..903f170a 100644
--- a/arch/arm64/boot/dts/qcom/pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660.dtsi
@@ -218,7 +218,6 @@
 				qcom,scale-function = <2>;
 				qcom,hw-settle-time = <2>;
 				qcom,fast-avg-setup = <0>;
-				qcom,vadc-thermal-node;
 			};
 
 			chan@4f {
@@ -230,7 +229,6 @@
 				qcom,scale-function = <2>;
 				qcom,hw-settle-time = <2>;
 				qcom,fast-avg-setup = <0>;
-				qcom,vadc-thermal-node;
 			};
 
 			chan@1d {
diff --git a/arch/arm64/boot/dts/qcom/pmi8950.dtsi b/arch/arm64/boot/dts/qcom/pmi8950.dtsi
index 97be32de..bab5774 100644
--- a/arch/arm64/boot/dts/qcom/pmi8950.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8950.dtsi
@@ -11,6 +11,8 @@
  */
 
 #include <dt-bindings/msm/power-on.h>
+#include <dt-bindings/spmi/spmi.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
 
 &spmi_bus {
 	qcom,pmi8950@2 {
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi
index 6cf9a82..fcde397 100644
--- a/arch/arm64/boot/dts/qcom/qcs605.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,30 @@
 	qcom,msm-id = <347 0x0>;
 };
 
+&pil_modem_mem {
+	reg = <0 0x8b000000 0 0x3c00000>;
+};
+
+&pil_video_mem {
+	reg = <0 0x8ec00000 0 0x500000>;
+};
+
+&wlan_msa_mem {
+	reg = <0 0x8f100000 0 0x100000>;
+};
+
+&pil_cdsp_mem {
+	reg = <0 0x8f200000 0 0x800000>;
+};
+
+&pil_mba_mem {
+	reg = <0 0x8fa00000 0 0x200000>;
+};
+
+&pil_adsp_mem {
+	reg = <0 0x8fc00000 0 0x1e00000>;
+};
+
 &soc {
 	qcom,rmnet-ipa {
 		status = "disabled";
diff --git a/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts b/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
new file mode 100644
index 0000000..903b432
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632-cdp-s2.dtsi"
+#include "sdm450-pmi632.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 CDP S2";
+	compatible = "qcom,sdm632-cdp", "qcom,sdm632", "qcom,cdp";
+	qcom,board-id = <1 2>;
+	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts b/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts
new file mode 100644
index 0000000..6339c3c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632-mtp-s3.dtsi"
+#include "sdm450-pmi632.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 MTP S3";
+	compatible = "qcom,sdm632-mtp", "qcom,sdm632", "qcom,mtp";
+	qcom,board-id = <8 3>;
+	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts b/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
new file mode 100644
index 0000000..9f33721
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-qrd-sku4.dtsi"
+#include "sdm450-pmi632.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 QRD SKU4";
+	compatible = "qcom,sdm632-qrd", "qcom,sdm632", "qcom,qrd";
+	qcom,board-id = <0xb 1>;
+	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm670-bus.dtsi b/arch/arm64/boot/dts/qcom/sdm670-bus.dtsi
index 4f5a9b1..aa7cc97 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-bus.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-bus.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -669,35 +669,6 @@
 			qcom,bcms = <&bcm_cn0>;
 		};
 
-		mas_qhm_tic: mas-qhm-tic {
-			cell-id = <MSM_BUS_MASTER_TIC>;
-			label = "mas-qhm-tic";
-			qcom,buswidth = <4>;
-			qcom,agg-ports = <1>;
-			qcom,connections = <&slv_qhs_tlmm_south
-				&slv_qhs_camera_cfg &slv_qhs_sdc4
-				&slv_qhs_sdc2 &slv_qhs_mnoc_cfg
-				&slv_qhs_ufs_mem_cfg &slv_qhs_glm
-				&slv_qhs_pdm &slv_qhs_a2_noc_cfg
-				&slv_qhs_qdss_cfg &slv_qhs_display_cfg
-				&slv_qhs_tcsr &slv_qhs_dcc_cfg
-				&slv_qhs_ddrss_cfg &slv_qns_cnoc_a2noc
-				&slv_qhs_snoc_cfg &slv_qhs_phy_refgen_south
-				&slv_qhs_gpuss_cfg &slv_qhs_venus_cfg
-				&slv_qhs_tsif &slv_qhs_compute_dsp_cfg
-				&slv_qhs_aop &slv_qhs_qupv3_north
-				&slv_srvc_cnoc &slv_qhs_usb3_0
-				&slv_qhs_ipa &slv_qhs_cpr_cx
-				&slv_qhs_a1_noc_cfg &slv_qhs_aoss
-				&slv_qhs_prng &slv_qhs_vsense_ctrl_cfg
-				&slv_qhs_emmc_cfg &slv_qhs_qupv3_south
-				&slv_qhs_spdm &slv_qhs_crypto0_cfg
-				&slv_qhs_pimem_cfg &slv_qhs_tlmm_north
-				&slv_qhs_clk_ctl &slv_qhs_imem_cfg>;
-			qcom,bus-dev = <&fab_config_noc>;
-			qcom,bcms = <&bcm_cn0>;
-		};
-
 		mas_qnm_snoc: mas-qnm-snoc {
 			cell-id = <MSM_BUS_SNOC_CNOC_MAS>;
 			label = "mas-qnm-snoc";
@@ -727,36 +698,6 @@
 			qcom,bcms = <&bcm_cn0>;
 		};
 
-		mas_xm_qdss_dap: mas-xm-qdss-dap {
-			cell-id = <MSM_BUS_MASTER_QDSS_DAP>;
-			label = "mas-xm-qdss-dap";
-			qcom,buswidth = <8>;
-			qcom,agg-ports = <1>;
-			qcom,connections = <&slv_qhs_tlmm_south
-				&slv_qhs_camera_cfg
-				&slv_qhs_sdc4
-				&slv_qhs_sdc2 &slv_qhs_mnoc_cfg
-				&slv_qhs_ufs_mem_cfg &slv_qhs_glm
-				&slv_qhs_pdm &slv_qhs_a2_noc_cfg
-				&slv_qhs_qdss_cfg &slv_qhs_display_cfg
-				&slv_qhs_tcsr &slv_qhs_dcc_cfg
-				&slv_qhs_ddrss_cfg &slv_qns_cnoc_a2noc
-				&slv_qhs_snoc_cfg &slv_qhs_phy_refgen_south
-				&slv_qhs_gpuss_cfg &slv_qhs_venus_cfg
-				&slv_qhs_tsif &slv_qhs_compute_dsp_cfg
-				&slv_qhs_aop &slv_qhs_qupv3_north
-				&slv_srvc_cnoc &slv_qhs_usb3_0
-				&slv_qhs_ipa &slv_qhs_cpr_cx
-				&slv_qhs_a1_noc_cfg &slv_qhs_aoss
-				&slv_qhs_prng &slv_qhs_vsense_ctrl_cfg
-				&slv_qhs_qupv3_south &slv_qhs_spdm
-				&slv_qhs_crypto0_cfg &slv_qhs_pimem_cfg
-				&slv_qhs_tlmm_north &slv_qhs_clk_ctl
-				&slv_qhs_imem_cfg>;
-			qcom,bus-dev = <&fab_config_noc>;
-			qcom,bcms = <&bcm_cn0>;
-		};
-
 		mas_qhm_cnoc: mas-qhm-cnoc {
 			cell-id = <MSM_BUS_MASTER_CNOC_DC_NOC>;
 			label = "mas-qhm-cnoc";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi
index 5d3975c..ab49970 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pmic-overlay.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -175,8 +175,8 @@
 		io-channel-names = "rradc_batt_id",
 				   "rradc_die_temp";
 		qcom,rradc-base = <0x4500>;
-		qcom,fg-esr-timer-awake = <96 96>;
-		qcom,fg-esr-timer-asleep = <256 256>;
+		qcom,fg-esr-timer-awake = <64 96>;
+		qcom,fg-esr-timer-asleep = <224 256>;
 		qcom,fg-esr-timer-charging = <0 96>;
 		qcom,cycle-counter-en;
 		qcom,hold-soc-while-full;
diff --git a/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi b/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi
index 32864a0..3df6d09 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi
@@ -27,8 +27,6 @@
 };
 
 &usb0 {
-	/delete-property/ iommus;
-	/delete-property/ qcom,smmu-s1-bypass;
 	qcom,pm-qos-latency = <601>; /* CPU-CLUSTER-WFI-LVL latency +1 */
 	extcon = <0>, <0>, <&eud>, <0>, <0>;
 };
@@ -57,6 +55,8 @@
 			    0x03 0x250 /* TUNE5 */
 			    0x00 0x23c /* CHG_CTRL2 */
 			    0x22 0x210>; /* PWR_CTRL1 */
+	nvmem-cells = <&minor_rev>;
+	nvmem-cell-names = "minor_rev";
 };
 
 &usb_qmp_dp_phy {
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 9bc083f..3cc0aa3 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -2139,6 +2139,7 @@
 		compatible = "qcom,pil-tz-generic";
 		qcom,pas-id = <0xf>;
 		qcom,firmware-name = "ipa_fws";
+		memory-region = <&pil_ipa_fw_mem>;
 	};
 
 	pil_modem: qcom,mss@4080000 {
@@ -2440,6 +2441,7 @@
 	qcom,msm-adsprpc-mem {
 		compatible = "qcom,msm-adsprpc-mem-region";
 		memory-region = <&adsp_mem>;
+		restrict-access;
 	};
 
 	qcom,msm_fastrpc {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
index 947d28b..1551952 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -51,6 +51,7 @@
 			compatible = "qcom,memshare-peripheral";
 			qcom,peripheral-size = <0x500000>;
 			qcom,client-id = <1>;
+			qcom,allocate-boot-time;
 			label = "modem";
 		};
 	};
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index 801c66a..34b6097 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -52,6 +52,7 @@
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_MSM8953=y
+CONFIG_ARCH_MSM8937=y
 CONFIG_ARCH_SDM450=y
 CONFIG_ARCH_SDM632=y
 CONFIG_SCHED_MC=y
@@ -295,6 +296,7 @@
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM_LEGACY=y
 CONFIG_MSM_SMD_PKT=y
+CONFIG_MSM_ADSPRPC=y
 CONFIG_MSM_RDBG=m
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MSM_V2=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index 009c420..ed222d2 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -56,6 +56,7 @@
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_MSM8953=y
+CONFIG_ARCH_MSM8937=y
 CONFIG_ARCH_SDM450=y
 CONFIG_ARCH_SDM632=y
 CONFIG_SCHED_MC=y
@@ -305,6 +306,7 @@
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM_LEGACY=y
 CONFIG_MSM_SMD_PKT=y
+CONFIG_MSM_ADSPRPC=y
 CONFIG_MSM_RDBG=m
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MSM_V2=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index 8022e88..667377f 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -621,7 +621,6 @@
 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
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index f7ef61e..11c95ea 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -290,6 +290,11 @@
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_HBTP_INPUT=y
 CONFIG_INPUT_QPNP_POWER_ON=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index a4f0ffa..6aa09e5 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -294,6 +294,11 @@
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_HBTP_INPUT=y
 CONFIG_INPUT_QPNP_POWER_ON=y
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 1ea2053..b0d0181 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -607,7 +607,7 @@
 
 config MSM_ADSPRPC
         tristate "QTI ADSP RPC driver"
-        depends on MSM_GLINK
+        depends on MSM_GLINK || MSM_SMD
         help
           Provides a communication mechanism that allows for clients to
           make remote method invocations across processor boundary to
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 3f35d54..9a0424a 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1381,7 +1381,7 @@
 	/* copy non ion buffers */
 	PERF(ctx->fl->profile, GET_COUNTER(perf_counter, PERF_COPY),
 	rlen = copylen - metalen;
-	for (oix = 0; oix < inbufs + outbufs; ++oix) {
+	for (oix = 0; rpra && oix < inbufs + outbufs; ++oix) {
 		int i = ctx->overps[oix]->raix;
 		struct fastrpc_mmap *map = ctx->maps[i];
 		size_t mlen;
@@ -1432,7 +1432,7 @@
 		if (map && (map->attr & FASTRPC_ATTR_COHERENT))
 			continue;
 
-		if (rpra[i].buf.len && ctx->overps[oix]->mstart)
+		if (rpra && rpra[i].buf.len && ctx->overps[oix]->mstart)
 			dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
 			uint64_to_ptr(rpra[i].buf.pv + rpra[i].buf.len));
 	}
@@ -3399,7 +3399,8 @@
 				break;
 			}
 		}
-		if (range.addr) {
+		if (range.addr && !of_property_read_bool(dev->of_node,
+							 "restrict-access")) {
 			int srcVM[1] = {VMID_HLOS};
 			int destVM[4] = {VMID_HLOS, VMID_MSS_MSA, VMID_SSC_Q6,
 						VMID_ADSP_Q6};
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index f510c14..223bc03 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -536,8 +536,7 @@
 }
 
 static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len,
-				   unsigned char *dest_buf, int dest_len,
-				   struct diag_md_session_t *info)
+			unsigned char *dest_buf, int dest_len, int pid)
 {
 	int i;
 	int write_len = 0;
@@ -545,23 +544,30 @@
 	struct diag_msg_ssid_query_t rsp;
 	struct diag_ssid_range_t ssid_range;
 	struct diag_mask_info *mask_info = NULL;
+	struct diag_md_session_t *info = NULL;
 
+	mutex_lock(&driver->md_session_lock);
+	info = diag_md_session_get_pid(pid);
 	mask_info = (!info) ? &msg_mask : info->msg_mask;
 	if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
 	    !mask_info) {
 		pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
 		       __func__, src_buf, src_len, dest_buf, dest_len,
 		       mask_info);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	if (!mask_info->ptr) {
 		pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
 			__func__, mask_info->ptr);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 
-	if (!diag_apps_responds())
+	if (!diag_apps_responds()) {
+		mutex_unlock(&driver->md_session_lock);
 		return 0;
+	}
 	mutex_lock(&driver->msg_mask_lock);
 	rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
 	rsp.sub_cmd = DIAG_CMD_OP_GET_SSID_RANGE;
@@ -583,12 +589,12 @@
 		write_len += sizeof(ssid_range);
 	}
 	mutex_unlock(&driver->msg_mask_lock);
+	mutex_unlock(&driver->md_session_lock);
 	return write_len;
 }
 
 static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
-				   unsigned char *dest_buf, int dest_len,
-				   struct diag_md_session_t *info)
+			unsigned char *dest_buf, int dest_len, int pid)
 {
 	int i = 0;
 	int write_len = 0;
@@ -641,8 +647,7 @@
 }
 
 static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
-				 unsigned char *dest_buf, int dest_len,
-				 struct diag_md_session_t *info)
+			unsigned char *dest_buf, int dest_len, int pid)
 {
 	int i;
 	int write_len = 0;
@@ -651,6 +656,10 @@
 	struct diag_build_mask_req_t *req = NULL;
 	struct diag_msg_build_mask_t rsp;
 	struct diag_mask_info *mask_info = NULL;
+	struct diag_md_session_t *info = NULL;
+
+	mutex_lock(&driver->md_session_lock);
+	info = diag_md_session_get_pid(pid);
 
 	mask_info = (!info) ? &msg_mask : info->msg_mask;
 	if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -658,15 +667,19 @@
 		pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
 		       __func__, src_buf, src_len, dest_buf, dest_len,
 		       mask_info);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	if (!mask_info->ptr) {
 		pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
 			__func__, mask_info->ptr);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
-	if (!diag_apps_responds())
+	if (!diag_apps_responds()) {
+		mutex_unlock(&driver->md_session_lock);
 		return 0;
+	}
 
 	mutex_lock(&driver->msg_mask_lock);
 	req = (struct diag_build_mask_req_t *)src_buf;
@@ -681,6 +694,7 @@
 		pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
 			__func__, mask->ptr);
 		mutex_unlock(&driver->msg_mask_lock);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
@@ -700,12 +714,12 @@
 	memcpy(dest_buf, &rsp, sizeof(rsp));
 	write_len += sizeof(rsp);
 	mutex_unlock(&driver->msg_mask_lock);
+	mutex_unlock(&driver->md_session_lock);
 	return write_len;
 }
 
 static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
-				 unsigned char *dest_buf, int dest_len,
-				 struct diag_md_session_t *info)
+			unsigned char *dest_buf, int dest_len, int pid)
 {
 	uint32_t mask_size = 0, offset = 0;
 	uint32_t *temp = NULL;
@@ -716,6 +730,10 @@
 	struct diag_msg_build_mask_t rsp;
 	struct diag_mask_info *mask_info = NULL;
 	struct diag_msg_mask_t *mask_next = NULL;
+	struct diag_md_session_t *info = NULL;
+
+	mutex_lock(&driver->md_session_lock);
+	info = diag_md_session_get_pid(pid);
 
 	mask_info = (!info) ? &msg_mask : info->msg_mask;
 	if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -723,11 +741,13 @@
 		pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
 		       __func__, src_buf, src_len, dest_buf, dest_len,
 		       mask_info);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	if (!mask_info->ptr) {
 		pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
 			__func__, mask_info->ptr);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 
@@ -740,6 +760,7 @@
 			__func__, mask->ptr);
 		mutex_unlock(&driver->msg_mask_lock);
 		mutex_unlock(&mask_info->lock);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
@@ -782,6 +803,7 @@
 				mutex_unlock(&mask->lock);
 				mutex_unlock(&driver->msg_mask_lock);
 				mutex_unlock(&mask_info->lock);
+				mutex_unlock(&driver->md_session_lock);
 				return -ENOMEM;
 			}
 			mask->ptr = temp;
@@ -802,6 +824,7 @@
 	}
 	mutex_unlock(&driver->msg_mask_lock);
 	mutex_unlock(&mask_info->lock);
+	mutex_unlock(&driver->md_session_lock);
 	if (diag_check_update(APPS_DATA))
 		diag_update_userspace_clients(MSG_MASKS_TYPE);
 
@@ -842,8 +865,7 @@
 }
 
 static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
-				     unsigned char *dest_buf, int dest_len,
-				     struct diag_md_session_t *info)
+			unsigned char *dest_buf, int dest_len, int pid)
 {
 	int i, write_len = 0, peripheral;
 	int header_len = sizeof(struct diag_msg_config_rsp_t);
@@ -851,6 +873,10 @@
 	struct diag_msg_config_rsp_t *req = NULL;
 	struct diag_msg_mask_t *mask = NULL;
 	struct diag_mask_info *mask_info = NULL;
+	struct diag_md_session_t *info = NULL;
+
+	mutex_lock(&driver->md_session_lock);
+	info = diag_md_session_get_pid(pid);
 
 	mask_info = (!info) ? &msg_mask : info->msg_mask;
 	if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -858,11 +884,13 @@
 		pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
 		       __func__, src_buf, src_len, dest_buf, dest_len,
 		       mask_info);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	if (!mask_info->ptr) {
 		pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
 			__func__, mask_info->ptr);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 
@@ -877,6 +905,7 @@
 			__func__, mask->ptr);
 		mutex_unlock(&driver->msg_mask_lock);
 		mutex_unlock(&mask_info->lock);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	mask_info->status = (req->rt_mask) ? DIAG_CTRL_MASK_ALL_ENABLED :
@@ -889,7 +918,7 @@
 	}
 	mutex_unlock(&driver->msg_mask_lock);
 	mutex_unlock(&mask_info->lock);
-
+	mutex_unlock(&driver->md_session_lock);
 	if (diag_check_update(APPS_DATA))
 		diag_update_userspace_clients(MSG_MASKS_TYPE);
 
@@ -923,8 +952,7 @@
 }
 
 static int diag_cmd_get_event_mask(unsigned char *src_buf, int src_len,
-				   unsigned char *dest_buf, int dest_len,
-				   struct diag_md_session_t *info)
+			unsigned char *dest_buf, int dest_len, int pid)
 {
 	int write_len = 0;
 	uint32_t mask_size;
@@ -959,26 +987,30 @@
 }
 
 static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len,
-				      unsigned char *dest_buf, int dest_len,
-				      struct diag_md_session_t *info)
+			unsigned char *dest_buf, int dest_len, int pid)
 {
 	int i, write_len = 0, mask_len = 0, peripheral;
 	int header_len = sizeof(struct diag_event_mask_config_t);
 	struct diag_event_mask_config_t rsp;
 	struct diag_event_mask_config_t *req;
 	struct diag_mask_info *mask_info = NULL;
+	struct diag_md_session_t *info = NULL;
 
+	mutex_lock(&driver->md_session_lock);
+	info = diag_md_session_get_pid(pid);
 	mask_info = (!info) ? &event_mask : info->event_mask;
 	if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
 	    !mask_info) {
 		pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
 		       __func__, src_buf, src_len, dest_buf, dest_len,
 		       mask_info);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	if (!mask_info->ptr) {
 		pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
 			__func__, mask_info->ptr);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	req = (struct diag_event_mask_config_t *)src_buf;
@@ -986,6 +1018,7 @@
 	if (mask_len <= 0 || mask_len > event_mask.mask_len) {
 		pr_err("diag: In %s, invalid event mask len: %d\n", __func__,
 		       mask_len);
+		mutex_unlock(&driver->md_session_lock);
 		return -EIO;
 	}
 
@@ -993,6 +1026,7 @@
 	memcpy(mask_info->ptr, src_buf + header_len, mask_len);
 	mask_info->status = DIAG_CTRL_MASK_VALID;
 	mutex_unlock(&mask_info->lock);
+	mutex_unlock(&driver->md_session_lock);
 	if (diag_check_update(APPS_DATA))
 		diag_update_userspace_clients(EVENT_MASKS_TYPE);
 
@@ -1027,25 +1061,29 @@
 }
 
 static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len,
-				  unsigned char *dest_buf, int dest_len,
-				  struct diag_md_session_t *info)
+			unsigned char *dest_buf, int dest_len, int pid)
 {
 	int write_len = 0, i, peripheral;
 	uint8_t toggle = 0;
 	struct diag_event_report_t header;
 	struct diag_mask_info *mask_info = NULL;
+	struct diag_md_session_t *info = NULL;
 
+	mutex_lock(&driver->md_session_lock);
+	info = diag_md_session_get_pid(pid);
 	mask_info = (!info) ? &event_mask : info->event_mask;
 	if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
 	    !mask_info) {
 		pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
 		       __func__, src_buf, src_len, dest_buf, dest_len,
 		       mask_info);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	if (!mask_info->ptr) {
 		pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
 			__func__, mask_info->ptr);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 
@@ -1059,6 +1097,7 @@
 		memset(mask_info->ptr, 0, mask_info->mask_len);
 	}
 	mutex_unlock(&mask_info->lock);
+	mutex_unlock(&driver->md_session_lock);
 	if (diag_check_update(APPS_DATA))
 		diag_update_userspace_clients(EVENT_MASKS_TYPE);
 
@@ -1088,8 +1127,7 @@
 }
 
 static int diag_cmd_get_log_mask(unsigned char *src_buf, int src_len,
-				 unsigned char *dest_buf, int dest_len,
-				 struct diag_md_session_t *info)
+			unsigned char *dest_buf, int dest_len, int pid)
 {
 	int i;
 	int status = LOG_STATUS_INVALID;
@@ -1102,6 +1140,10 @@
 	struct diag_log_config_req_t *req;
 	struct diag_log_config_rsp_t rsp;
 	struct diag_mask_info *mask_info = NULL;
+	struct diag_md_session_t *info = NULL;
+
+	mutex_lock(&driver->md_session_lock);
+	info = diag_md_session_get_pid(pid);
 
 	mask_info = (!info) ? &log_mask : info->log_mask;
 	if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -1109,16 +1151,20 @@
 		pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
 		       __func__, src_buf, src_len, dest_buf, dest_len,
 		       mask_info);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	if (!mask_info->ptr) {
 		pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
 			__func__, mask_info->ptr);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 
-	if (!diag_apps_responds())
+	if (!diag_apps_responds()) {
+		mutex_unlock(&driver->md_session_lock);
 		return 0;
+	}
 
 	req = (struct diag_log_config_req_t *)src_buf;
 	read_len += req_header_len;
@@ -1138,6 +1184,7 @@
 	if (!log_item->ptr) {
 		pr_err("diag: Invalid input in %s, mask: %pK\n",
 			__func__, log_item);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	for (i = 0; i < MAX_EQUIP_ID; i++, log_item++) {
@@ -1179,28 +1226,27 @@
 	rsp.status = status;
 	memcpy(dest_buf, &rsp, rsp_header_len);
 
+	mutex_unlock(&driver->md_session_lock);
 	return write_len;
 }
 
 static int diag_cmd_get_log_range(unsigned char *src_buf, int src_len,
-				  unsigned char *dest_buf, int dest_len,
-				  struct diag_md_session_t *info)
+			unsigned char *dest_buf, int dest_len, int pid)
 {
 	int i;
 	int write_len = 0;
 	struct diag_log_config_rsp_t rsp;
-	struct diag_mask_info *mask_info = NULL;
 	struct diag_log_mask_t *mask = (struct diag_log_mask_t *)log_mask.ptr;
 
+	if (!mask)
+		return -EINVAL;
+
 	if (!diag_apps_responds())
 		return 0;
 
-	mask_info = (!info) ? &log_mask : info->log_mask;
-	if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
-	    !mask_info) {
-		pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
-		       __func__, src_buf, src_len, dest_buf, dest_len,
-		       mask_info);
+	if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0) {
+		pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d\n",
+		       __func__, src_buf, src_len, dest_buf, dest_len);
 		return -EINVAL;
 	}
 
@@ -1223,7 +1269,7 @@
 
 static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len,
 				 unsigned char *dest_buf, int dest_len,
-				 struct diag_md_session_t *info)
+				 int pid)
 {
 	int i, peripheral, write_len = 0;
 	int status = LOG_STATUS_SUCCESS;
@@ -1236,6 +1282,10 @@
 	struct diag_log_mask_t *mask = NULL;
 	struct diag_mask_info *mask_info = NULL;
 	unsigned char *temp_buf = NULL;
+	struct diag_md_session_t *info = NULL;
+
+	mutex_lock(&driver->md_session_lock);
+	info = diag_md_session_get_pid(pid);
 
 	mask_info = (!info) ? &log_mask : info->log_mask;
 	if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -1243,11 +1293,13 @@
 		pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
 		       __func__, src_buf, src_len, dest_buf, dest_len,
 		       mask_info);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	if (!mask_info->ptr) {
 		pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
 			__func__, mask_info->ptr);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 
@@ -1257,6 +1309,7 @@
 	if (!mask->ptr) {
 		pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
 			__func__, mask->ptr);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	if (req->equip_id >= MAX_EQUIP_ID) {
@@ -1319,6 +1372,7 @@
 		break;
 	}
 	mutex_unlock(&mask_info->lock);
+	mutex_unlock(&driver->md_session_lock);
 	if (diag_check_update(APPS_DATA))
 		diag_update_userspace_clients(LOG_MASKS_TYPE);
 
@@ -1365,13 +1419,16 @@
 }
 
 static int diag_cmd_disable_log_mask(unsigned char *src_buf, int src_len,
-				     unsigned char *dest_buf, int dest_len,
-				     struct diag_md_session_t *info)
+			unsigned char *dest_buf, int dest_len, int pid)
 {
 	struct diag_mask_info *mask_info = NULL;
 	struct diag_log_mask_t *mask = NULL;
 	struct diag_log_config_rsp_t header;
 	int write_len = 0, i, peripheral;
+	struct diag_md_session_t *info = NULL;
+
+	mutex_lock(&driver->md_session_lock);
+	info = diag_md_session_get_pid(pid);
 
 	mask_info = (!info) ? &log_mask : info->log_mask;
 	if (!src_buf || !dest_buf || src_len <= 0 || dest_len <= 0 ||
@@ -1379,17 +1436,20 @@
 		pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
 		       __func__, src_buf, src_len, dest_buf, dest_len,
 		       mask_info);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	if (!mask_info->ptr) {
 		pr_err("diag: In %s, invalid input mask_info->ptr: %pK\n",
 			__func__, mask_info->ptr);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	mask = (struct diag_log_mask_t *)mask_info->ptr;
 	if (!mask->ptr) {
 		pr_err("diag: Invalid input in %s, mask->ptr: %pK\n",
 			__func__, mask->ptr);
+		mutex_unlock(&driver->md_session_lock);
 		return -EINVAL;
 	}
 	for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
@@ -1398,6 +1458,7 @@
 		mutex_unlock(&mask->lock);
 	}
 	mask_info->status = DIAG_CTRL_MASK_ALL_DISABLED;
+	mutex_unlock(&driver->md_session_lock);
 	if (diag_check_update(APPS_DATA))
 		diag_update_userspace_clients(LOG_MASKS_TYPE);
 
@@ -2144,13 +2205,11 @@
 	}
 }
 
-int diag_process_apps_masks(unsigned char *buf, int len,
-			    struct diag_md_session_t *info)
+int diag_process_apps_masks(unsigned char *buf, int len, int pid)
 {
 	int size = 0, sub_cmd = 0;
 	int (*hdlr)(unsigned char *src_buf, int src_len,
-		    unsigned char *dest_buf, int dest_len,
-		    struct diag_md_session_t *info) = NULL;
+		    unsigned char *dest_buf, int dest_len, int pid) = NULL;
 
 	if (!buf || len <= 0)
 		return -EINVAL;
@@ -2200,7 +2259,7 @@
 
 	if (hdlr)
 		size = hdlr(buf, len, driver->apps_rsp_buf,
-			    DIAG_MAX_RSP_SIZE, info);
+			    DIAG_MAX_RSP_SIZE, pid);
 
 	return (size > 0) ? size : 0;
 }
diff --git a/drivers/char/diag/diag_masks.h b/drivers/char/diag/diag_masks.h
index 1a52f94..6edeee9 100644
--- a/drivers/char/diag/diag_masks.h
+++ b/drivers/char/diag/diag_masks.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 2018 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -167,8 +167,7 @@
 void diag_log_mask_free(struct diag_mask_info *mask_info);
 void diag_msg_mask_free(struct diag_mask_info *mask_info);
 void diag_event_mask_free(struct diag_mask_info *mask_info);
-int diag_process_apps_masks(unsigned char *buf, int len,
-			    struct diag_md_session_t *info);
+int diag_process_apps_masks(unsigned char *buf, int len, int pid);
 void diag_send_updates_peripheral(uint8_t peripheral);
 
 extern int diag_create_msg_mask_table_entry(struct diag_msg_mask_t *msg_mask,
diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c
index 9cecb03..ce0c7bb 100644
--- a/drivers/char/diag/diag_memorydevice.c
+++ b/drivers/char/diag/diag_memorydevice.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -129,11 +129,10 @@
 
 int diag_md_write(int id, unsigned char *buf, int len, int ctx)
 {
-	int i;
+	int i, peripheral, pid = 0;
 	uint8_t found = 0;
 	unsigned long flags;
 	struct diag_md_info *ch = NULL;
-	int peripheral;
 	struct diag_md_session_t *session_info = NULL;
 
 	if (id < 0 || id >= NUM_DIAG_MD_DEV || id >= DIAG_NUM_PROC)
@@ -146,10 +145,14 @@
 	if (peripheral < 0)
 		return -EINVAL;
 
-	session_info =
-		diag_md_session_get_peripheral(peripheral);
-	if (!session_info)
+	mutex_lock(&driver->md_session_lock);
+	session_info = diag_md_session_get_peripheral(peripheral);
+	if (!session_info) {
+		mutex_unlock(&driver->md_session_lock);
 		return -EIO;
+	}
+	pid = session_info->pid;
+	mutex_unlock(&driver->md_session_lock);
 
 	ch = &diag_md[id];
 	if (!ch)
@@ -192,8 +195,7 @@
 
 	found = 0;
 	for (i = 0; i < driver->num_clients && !found; i++) {
-		if ((driver->client_map[i].pid !=
-		     session_info->pid) ||
+		if ((driver->client_map[i].pid != pid) ||
 		    (driver->client_map[i].pid == 0))
 			continue;
 
diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c
index 1cf7f52..060f03f 100644
--- a/drivers/char/diag/diag_usb.c
+++ b/drivers/char/diag/diag_usb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2016, 2018 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -221,7 +221,7 @@
 
 	if (!atomic_read(&ch->connected) &&
 		driver->usb_connected && diag_mask_param())
-		diag_clear_masks(NULL);
+		diag_clear_masks(0);
 
 	if (ch && ch->ops && ch->ops->close)
 		ch->ops->close(ch->ctxt, DIAG_USB_MODE);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 9de40b0..3cecebf 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -714,7 +714,7 @@
 void diag_cmd_remove_reg_by_proc(int proc);
 int diag_cmd_chk_polling(struct diag_cmd_reg_entry_t *entry);
 int diag_mask_param(void);
-void diag_clear_masks(struct diag_md_session_t *info);
+void diag_clear_masks(int pid);
 uint8_t diag_mask_to_pd_value(uint32_t peripheral_mask);
 int diag_query_pd(char *process_name);
 int diag_search_peripheral_by_pd(uint8_t pd_val);
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 0158549..694b483 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -167,7 +167,7 @@
 void *diag_ipc_log;
 #endif
 
-static void diag_md_session_close(struct diag_md_session_t *session_info);
+static void diag_md_session_close(int pid);
 
 /*
  * Returns the next delayed rsp id. If wrapping is enabled,
@@ -243,12 +243,13 @@
 
 	timer_in_progress = 0;
 	mutex_lock(&apps_data_mutex);
+	mutex_lock(&driver->md_session_lock);
 	session_info = diag_md_session_get_peripheral(APPS_DATA);
 	if (session_info)
 		hdlc_disabled = session_info->hdlc_disabled;
 	else
 		hdlc_disabled = driver->hdlc_disabled;
-
+	mutex_unlock(&driver->md_session_lock);
 	if (!hdlc_disabled)
 		diag_drain_apps_data(&hdlc_data);
 	else
@@ -422,7 +423,7 @@
 {
 	return diag_mask_clear_param;
 }
-void diag_clear_masks(struct diag_md_session_t *info)
+void diag_clear_masks(int pid)
 {
 	int ret;
 	char cmd_disable_log_mask[] = { 0x73, 0, 0, 0, 0, 0, 0, 0};
@@ -431,14 +432,14 @@
 
 	DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
 	"diag: %s: masks clear request upon %s\n", __func__,
-	((info) ? "ODL exit" : "USB Disconnection"));
+	((pid) ? "ODL exit" : "USB Disconnection"));
 
 	ret = diag_process_apps_masks(cmd_disable_log_mask,
-			sizeof(cmd_disable_log_mask), info);
+			sizeof(cmd_disable_log_mask), pid);
 	ret = diag_process_apps_masks(cmd_disable_msg_mask,
-			sizeof(cmd_disable_msg_mask), info);
+			sizeof(cmd_disable_msg_mask), pid);
 	ret = diag_process_apps_masks(cmd_disable_event_mask,
-			sizeof(cmd_disable_event_mask), info);
+			sizeof(cmd_disable_event_mask), pid);
 	DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
 	"diag:%s: masks cleared successfully\n", __func__);
 }
@@ -451,21 +452,23 @@
 	struct diag_md_session_t *session_info = NULL;
 	struct diag_logging_mode_param_t params;
 
+	mutex_lock(&driver->md_session_lock);
 	session_info = diag_md_session_get_pid(pid);
-	if (!session_info)
+	if (!session_info) {
+		mutex_unlock(&driver->md_session_lock);
 		return;
+	}
+	session_mask = session_info->peripheral_mask;
+	mutex_unlock(&driver->md_session_lock);
 
 	if (diag_mask_clear_param)
-		diag_clear_masks(session_info);
+		diag_clear_masks(pid);
 
 	mutex_lock(&driver->diag_maskclear_mutex);
 	driver->mask_clear = 1;
 	mutex_unlock(&driver->diag_maskclear_mutex);
 
 	mutex_lock(&driver->diagchar_mutex);
-	session_mask = session_info->peripheral_mask;
-	diag_md_session_close(session_info);
-
 	p_mask =
 	diag_translate_kernel_to_user_mask(session_mask);
 
@@ -489,7 +492,9 @@
 			}
 		}
 	}
-
+	mutex_lock(&driver->md_session_lock);
+	diag_md_session_close(pid);
+	mutex_unlock(&driver->md_session_lock);
 	diag_switch_logging(&params);
 	mutex_unlock(&driver->diagchar_mutex);
 }
@@ -1024,11 +1029,13 @@
 
 	if (driver->hdlc_encode_buf_len != 0)
 		return -EAGAIN;
+	mutex_lock(&driver->md_session_lock);
 	session_info = diag_md_session_get_peripheral(APPS_DATA);
 	if (session_info)
 		hdlc_disabled = session_info->hdlc_disabled;
 	else
 		hdlc_disabled = driver->hdlc_disabled;
+	mutex_unlock(&driver->md_session_lock);
 	if (hdlc_disabled) {
 		if (len < 4) {
 			pr_err("diag: In %s, invalid len: %d of non_hdlc pkt",
@@ -1386,15 +1393,16 @@
 	return err;
 }
 
-static void diag_md_session_close(struct diag_md_session_t *session_info)
+static void diag_md_session_close(int pid)
 {
 	int i;
 	uint8_t found = 0;
+	struct diag_md_session_t *session_info = NULL;
 
+	session_info = diag_md_session_get_pid(pid);
 	if (!session_info)
 		return;
 
-	mutex_lock(&driver->md_session_lock);
 	for (i = 0; i < NUM_MD_SESSIONS; i++) {
 		if (driver->md_session_map[i] != session_info)
 			continue;
@@ -1420,13 +1428,14 @@
 	driver->md_session_mode = (found) ? DIAG_MD_PERIPHERAL : DIAG_MD_NONE;
 	kfree(session_info);
 	session_info = NULL;
-	mutex_unlock(&driver->md_session_lock);
 	DIAG_LOG(DIAG_DEBUG_USERSPACE, "cleared up session\n");
 }
 
 struct diag_md_session_t *diag_md_session_get_pid(int pid)
 {
 	int i;
+	if (pid <= 0)
+		return NULL;
 	for (i = 0; i < NUM_MD_SESSIONS; i++) {
 		if (driver->md_session_map[i] &&
 		    driver->md_session_map[i]->pid == pid)
@@ -1442,10 +1451,12 @@
 	return driver->md_session_map[peripheral];
 }
 
-static int diag_md_peripheral_switch(struct diag_md_session_t *session_info,
+static int diag_md_peripheral_switch(int pid,
 				int peripheral_mask, int req_mode) {
 	int i, bit = 0;
+	struct diag_md_session_t *session_info = NULL;
 
+	session_info = diag_md_session_get_pid(pid);
 	if (!session_info)
 		return -EINVAL;
 	if (req_mode != DIAG_USB_MODE || req_mode != DIAG_MEMORY_DEVICE_MODE)
@@ -1455,25 +1466,20 @@
 	 * check that md_session_map for i == session_info,
 	 * if not then race condition occurred and bail
 	 */
-	mutex_lock(&driver->md_session_lock);
 	for (i = 0; i < NUM_MD_SESSIONS; i++) {
 		bit = MD_PERIPHERAL_MASK(i) & peripheral_mask;
 		if (!bit)
 			continue;
 		if (req_mode == DIAG_USB_MODE) {
-			if (driver->md_session_map[i] != session_info) {
-				mutex_unlock(&driver->md_session_lock);
+			if (driver->md_session_map[i] != session_info)
 				return -EINVAL;
-			}
 			driver->md_session_map[i] = NULL;
 			driver->md_session_mask &= ~bit;
 			session_info->peripheral_mask &= ~bit;
 
 		} else {
-			if (driver->md_session_map[i] != NULL) {
-				mutex_unlock(&driver->md_session_lock);
+			if (driver->md_session_map[i] != NULL)
 				return -EINVAL;
-			}
 			driver->md_session_map[i] = session_info;
 			driver->md_session_mask |= bit;
 			session_info->peripheral_mask |= bit;
@@ -1482,7 +1488,6 @@
 	}
 
 	driver->md_session_mode = DIAG_MD_PERIPHERAL;
-	mutex_unlock(&driver->md_session_lock);
 	DIAG_LOG(DIAG_DEBUG_USERSPACE, "Changed Peripherals:0x%x to mode:%d\n",
 		peripheral_mask, req_mode);
 }
@@ -1491,7 +1496,7 @@
 				 const struct diag_logging_mode_param_t *param,
 				 uint8_t *change_mode)
 {
-	int i, bit = 0, err = 0;
+	int i, bit = 0, err = 0, peripheral_mask = 0;
 	int change_mask = 0;
 	struct diag_md_session_t *session_info = NULL;
 
@@ -1515,12 +1520,13 @@
 	if (req_mode == DIAG_USB_MODE) {
 		if (curr_mode == DIAG_USB_MODE)
 			return 0;
+		mutex_lock(&driver->md_session_lock);
 		if (driver->md_session_mode == DIAG_MD_NONE
 		    && driver->md_session_mask == 0 && driver->logging_mask) {
 			*change_mode = 1;
+			mutex_unlock(&driver->md_session_lock);
 			return 0;
 		}
-
 		/*
 		 * curr_mode is either DIAG_MULTI_MODE or DIAG_MD_MODE
 		 * Check if requested peripherals are already in usb mode
@@ -1532,8 +1538,10 @@
 			if (bit & driver->logging_mask)
 				change_mask |= bit;
 		}
-		if (!change_mask)
+		if (!change_mask) {
+			mutex_unlock(&driver->md_session_lock);
 			return 0;
+		}
 
 		/*
 		 * Change is needed. Check if this md_session has set all the
@@ -1542,29 +1550,29 @@
 		 * If this session owns all the requested peripherals, then
 		 * call function to switch the modes/masks for the md_session
 		 */
-		mutex_lock(&driver->md_session_lock);
 		session_info = diag_md_session_get_pid(current->tgid);
-		mutex_unlock(&driver->md_session_lock);
-
 		if (!session_info) {
 			*change_mode = 1;
+			mutex_unlock(&driver->md_session_lock);
 			return 0;
 		}
-		if ((change_mask & session_info->peripheral_mask)
+		peripheral_mask = session_info->peripheral_mask;
+		if ((change_mask & peripheral_mask)
 							!= change_mask) {
 			DIAG_LOG(DIAG_DEBUG_USERSPACE,
 			    "Another MD Session owns a requested peripheral\n");
+			mutex_unlock(&driver->md_session_lock);
 			return -EINVAL;
 		}
 		*change_mode = 1;
 
 		/* If all peripherals are being set to USB Mode, call close */
-		if (~change_mask & session_info->peripheral_mask) {
-			err = diag_md_peripheral_switch(session_info,
+		if (~change_mask & peripheral_mask) {
+			err = diag_md_peripheral_switch(current->tgid,
 					change_mask, DIAG_USB_MODE);
 		} else
-			diag_md_session_close(session_info);
-
+			diag_md_session_close(current->tgid);
+		mutex_unlock(&driver->md_session_lock);
 		return err;
 
 	} else if (req_mode == DIAG_MEMORY_DEVICE_MODE) {
@@ -1573,21 +1581,23 @@
 		 * been set. Check that requested peripherals already set are
 		 * owned by this md session
 		 */
-		change_mask = driver->md_session_mask & param->peripheral_mask;
 		mutex_lock(&driver->md_session_lock);
+		change_mask = driver->md_session_mask & param->peripheral_mask;
 		session_info = diag_md_session_get_pid(current->tgid);
-		mutex_unlock(&driver->md_session_lock);
 
 		if (session_info) {
 			if ((session_info->peripheral_mask & change_mask)
 							!= change_mask) {
 				DIAG_LOG(DIAG_DEBUG_USERSPACE,
 				    "Another MD Session owns a requested peripheral\n");
+				mutex_unlock(&driver->md_session_lock);
 				return -EINVAL;
 			}
-			err = diag_md_peripheral_switch(session_info,
+			err = diag_md_peripheral_switch(current->tgid,
 					change_mask, DIAG_USB_MODE);
+			mutex_unlock(&driver->md_session_lock);
 		} else {
+			mutex_unlock(&driver->md_session_lock);
 			if (change_mask) {
 				DIAG_LOG(DIAG_DEBUG_USERSPACE,
 				    "Another MD Session owns a requested peripheral\n");
@@ -2047,19 +2057,17 @@
 {
 	uint8_t hdlc_support;
 	struct diag_md_session_t *session_info = NULL;
-	mutex_lock(&driver->md_session_lock);
-	session_info = diag_md_session_get_pid(current->tgid);
-	mutex_unlock(&driver->md_session_lock);
 	if (copy_from_user(&hdlc_support, (void __user *)ioarg,
 				sizeof(uint8_t)))
 		return -EFAULT;
 	mutex_lock(&driver->hdlc_disable_mutex);
-	if (session_info) {
-		mutex_lock(&driver->md_session_lock);
+	mutex_lock(&driver->md_session_lock);
+	session_info = diag_md_session_get_pid(current->tgid);
+	if (session_info)
 		session_info->hdlc_disabled = hdlc_support;
-		mutex_unlock(&driver->md_session_lock);
-	} else
+	else
 		driver->hdlc_disabled = hdlc_support;
+	mutex_unlock(&driver->md_session_lock);
 	mutex_unlock(&driver->hdlc_disable_mutex);
 	diag_update_md_clients(HDLC_SUPPORT_TYPE);
 
@@ -2885,7 +2893,6 @@
 	int remote_proc = 0;
 	const int mempool = POOL_TYPE_COPY;
 	unsigned char *user_space_data = NULL;
-	struct diag_md_session_t *info = NULL;
 
 	if (!buf || len <= 0 || len > CALLBACK_BUF_SIZE) {
 		pr_err_ratelimited("diag: In %s, invalid buf %pK len: %d\n",
@@ -2936,13 +2943,11 @@
 	} else {
 		wait_event_interruptible(driver->wait_q,
 					 (driver->in_busy_pktdata == 0));
-		mutex_lock(&driver->md_session_lock);
-		info = diag_md_session_get_pid(current->tgid);
-		mutex_unlock(&driver->md_session_lock);
-		ret = diag_process_apps_pkt(user_space_data, len, info);
+		ret = diag_process_apps_pkt(user_space_data, len,
+			current->tgid);
 		if (ret == 1)
 			diag_send_error_rsp((void *)(user_space_data), len,
-						info);
+						current->tgid);
 	}
 fail:
 	diagmem_free(driver, user_space_data, mempool);
@@ -3008,24 +3013,25 @@
 	if (!remote_proc) {
 		mutex_lock(&driver->md_session_lock);
 		session_info = diag_md_session_get_pid(current->tgid);
-		mutex_unlock(&driver->md_session_lock);
 		if (!session_info) {
 			pr_err("diag:In %s request came from invalid md session pid:%d",
 				__func__, current->tgid);
+			mutex_unlock(&driver->md_session_lock);
 			return -EINVAL;
 		}
 		if (session_info)
 			hdlc_disabled = session_info->hdlc_disabled;
 		else
 			hdlc_disabled = driver->hdlc_disabled;
+		mutex_unlock(&driver->md_session_lock);
 		if (!hdlc_disabled)
 			diag_process_hdlc_pkt((void *)
 				(driver->user_space_data_buf),
-				len, session_info);
+				len, current->tgid);
 		else
 			diag_process_non_hdlc_pkt((char *)
 						(driver->user_space_data_buf),
-						len, session_info);
+						len, current->tgid);
 		return 0;
 	}
 
@@ -3102,11 +3108,13 @@
 
 	mutex_lock(&apps_data_mutex);
 	mutex_lock(&driver->hdlc_disable_mutex);
+	mutex_lock(&driver->md_session_lock);
 	session_info = diag_md_session_get_peripheral(APPS_DATA);
 	if (session_info)
 		hdlc_disabled = session_info->hdlc_disabled;
 	else
 		hdlc_disabled = driver->hdlc_disabled;
+	mutex_unlock(&driver->md_session_lock);
 	if (hdlc_disabled)
 		ret = diag_process_apps_data_non_hdlc(user_space_data, len,
 						      pkt_type);
@@ -3177,9 +3185,9 @@
 		ret += sizeof(int);
 		mutex_lock(&driver->md_session_lock);
 		session_info = diag_md_session_get_pid(current->tgid);
-		mutex_unlock(&driver->md_session_lock);
 		exit_stat = diag_md_copy_to_user(buf, &ret, count,
 						 session_info);
+		mutex_unlock(&driver->md_session_lock);
 		goto exit;
 	} else if (driver->data_ready[index] & USER_SPACE_DATA_TYPE) {
 		/* In case, the thread wakes up and the logging mode is not
@@ -3199,14 +3207,16 @@
 
 		mutex_lock(&driver->md_session_lock);
 		session_info = diag_md_session_get_pid(current->tgid);
-		mutex_unlock(&driver->md_session_lock);
 		if (session_info) {
 			COPY_USER_SPACE_OR_ERR(buf+4,
 					session_info->hdlc_disabled,
 					sizeof(uint8_t));
-			if (ret == -EFAULT)
+			if (ret == -EFAULT) {
+				mutex_unlock(&driver->md_session_lock);
 				goto exit;
+			}
 		}
+		mutex_unlock(&driver->md_session_lock);
 		goto exit;
 	}
 
@@ -3226,12 +3236,16 @@
 	if (driver->data_ready[index] & MSG_MASKS_TYPE) {
 		/*Copy the type of data being passed*/
 		data_type = driver->data_ready[index] & MSG_MASKS_TYPE;
+		mutex_lock(&driver->md_session_lock);
 		session_info = diag_md_session_get_peripheral(APPS_DATA);
 		COPY_USER_SPACE_OR_ERR(buf, data_type, sizeof(int));
-		if (ret == -EFAULT)
+		if (ret == -EFAULT) {
+			mutex_unlock(&driver->md_session_lock);
 			goto exit;
+		}
 		write_len = diag_copy_to_user_msg_mask(buf + ret, count,
 						       session_info);
+		mutex_unlock(&driver->md_session_lock);
 		if (write_len > 0)
 			ret += write_len;
 		driver->data_ready[index] ^= MSG_MASKS_TYPE;
@@ -3242,25 +3256,32 @@
 	if (driver->data_ready[index] & EVENT_MASKS_TYPE) {
 		/*Copy the type of data being passed*/
 		data_type = driver->data_ready[index] & EVENT_MASKS_TYPE;
+		mutex_lock(&driver->md_session_lock);
 		session_info = diag_md_session_get_peripheral(APPS_DATA);
 		COPY_USER_SPACE_OR_ERR(buf, data_type, 4);
-		if (ret == -EFAULT)
+		if (ret == -EFAULT) {
+			mutex_unlock(&driver->md_session_lock);
 			goto exit;
-
+		}
 		if (session_info && session_info->event_mask &&
 		    session_info->event_mask->ptr) {
 			COPY_USER_SPACE_OR_ERR(buf + sizeof(int),
 					*(session_info->event_mask->ptr),
 					session_info->event_mask->mask_len);
-			if (ret == -EFAULT)
+			if (ret == -EFAULT) {
+				mutex_unlock(&driver->md_session_lock);
 				goto exit;
+			}
 		} else {
 			COPY_USER_SPACE_OR_ERR(buf + sizeof(int),
 						*(event_mask.ptr),
 						event_mask.mask_len);
-			if (ret == -EFAULT)
+			if (ret == -EFAULT) {
+				mutex_unlock(&driver->md_session_lock);
 				goto exit;
+			}
 		}
+		mutex_unlock(&driver->md_session_lock);
 		driver->data_ready[index] ^= EVENT_MASKS_TYPE;
 		atomic_dec(&driver->data_ready_notif[index]);
 		goto exit;
@@ -3269,13 +3290,17 @@
 	if (driver->data_ready[index] & LOG_MASKS_TYPE) {
 		/*Copy the type of data being passed*/
 		data_type = driver->data_ready[index] & LOG_MASKS_TYPE;
+		mutex_lock(&driver->md_session_lock);
 		session_info = diag_md_session_get_peripheral(APPS_DATA);
 		COPY_USER_SPACE_OR_ERR(buf, data_type, sizeof(int));
-		if (ret == -EFAULT)
+		if (ret == -EFAULT) {
+			mutex_unlock(&driver->md_session_lock);
 			goto exit;
+		}
 
 		write_len = diag_copy_to_user_log_mask(buf + ret, count,
 						       session_info);
+		mutex_unlock(&driver->md_session_lock);
 		if (write_len > 0)
 			ret += write_len;
 		driver->data_ready[index] ^= LOG_MASKS_TYPE;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 1155087..33048e1 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -242,7 +242,7 @@
 }
 
 static void pack_rsp_and_send(unsigned char *buf, int len,
-				struct diag_md_session_t *info)
+				int pid)
 {
 	int err;
 	int retry_count = 0, i, rsp_ctxt;
@@ -250,6 +250,7 @@
 	unsigned long flags;
 	unsigned char *rsp_ptr = driver->encoded_rsp_buf;
 	struct diag_pkt_frame_t header;
+	struct diag_md_session_t *session_info = NULL, *info = NULL;
 
 	if (!rsp_ptr || !buf)
 		return;
@@ -260,6 +261,11 @@
 		return;
 	}
 
+	mutex_lock(&driver->md_session_lock);
+	session_info = diag_md_session_get_pid(pid);
+	info = (session_info) ? session_info :
+				diag_md_session_get_peripheral(APPS_DATA);
+
 	/*
 	 * Explicitly check for the Peripheral Modem here
 	 * is necessary till a way to identify a peripheral
@@ -279,6 +285,7 @@
 		}
 	} else
 		rsp_ctxt = driver->rsp_buf_ctxt;
+	mutex_unlock(&driver->md_session_lock);
 
 	/*
 	 * Keep trying till we get the buffer back. It should probably
@@ -302,8 +309,11 @@
 		 * draining responses when we are in Memory Device Mode.
 		 */
 		if (driver->logging_mode == DIAG_MEMORY_DEVICE_MODE ||
-				driver->logging_mode == DIAG_MULTI_MODE)
+				driver->logging_mode == DIAG_MULTI_MODE) {
+			mutex_lock(&driver->md_session_lock);
 			chk_logging_wakeup();
+			mutex_unlock(&driver->md_session_lock);
+		}
 	}
 	if (driver->rsp_buf_busy) {
 		pr_err("diag: unable to get hold of response buffer\n");
@@ -332,13 +342,14 @@
 }
 
 static void encode_rsp_and_send(unsigned char *buf, int len,
-				struct diag_md_session_t *info)
+				int pid)
 {
 	struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
 	struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
 	unsigned char *rsp_ptr = driver->encoded_rsp_buf;
 	int err, i, rsp_ctxt, retry_count = 0;
 	unsigned long flags;
+	struct diag_md_session_t *session_info = NULL, *info = NULL;
 
 	if (!rsp_ptr || !buf)
 		return;
@@ -349,6 +360,11 @@
 		return;
 	}
 
+	mutex_lock(&driver->md_session_lock);
+	session_info = diag_md_session_get_pid(pid);
+	info = (session_info) ? session_info :
+				diag_md_session_get_peripheral(APPS_DATA);
+
 	/*
 	 * Explicitly check for the Peripheral Modem here
 	 * is necessary till a way to identify a peripheral
@@ -368,7 +384,7 @@
 		}
 	} else
 		rsp_ctxt = driver->rsp_buf_ctxt;
-
+	mutex_unlock(&driver->md_session_lock);
 	/*
 	 * Keep trying till we get the buffer back. It should probably
 	 * take one or two iterations. When this loops till UINT_MAX, it
@@ -391,8 +407,11 @@
 		 * draining responses when we are in Memory Device Mode.
 		 */
 		if (driver->logging_mode == DIAG_MEMORY_DEVICE_MODE ||
-				driver->logging_mode == DIAG_MULTI_MODE)
+				driver->logging_mode == DIAG_MULTI_MODE) {
+			mutex_lock(&driver->md_session_lock);
 			chk_logging_wakeup();
+			mutex_unlock(&driver->md_session_lock);
+		}
 	}
 
 	if (driver->rsp_buf_busy) {
@@ -424,22 +443,23 @@
 }
 
 static void diag_send_rsp(unsigned char *buf, int len,
-	struct diag_md_session_t *info)
+	int pid)
 {
-	struct diag_md_session_t *session_info = NULL;
+	struct diag_md_session_t *session_info = NULL, *info = NULL;
 	uint8_t hdlc_disabled;
-
+	mutex_lock(&driver->md_session_lock);
+	info = diag_md_session_get_pid(pid);
 	session_info = (info) ? info :
 				diag_md_session_get_peripheral(APPS_DATA);
 	if (session_info)
 		hdlc_disabled = session_info->hdlc_disabled;
 	else
 		hdlc_disabled = driver->hdlc_disabled;
-
+	mutex_unlock(&driver->md_session_lock);
 	if (hdlc_disabled)
-		pack_rsp_and_send(buf, len, session_info);
+		pack_rsp_and_send(buf, len, pid);
 	else
-		encode_rsp_and_send(buf, len, session_info);
+		encode_rsp_and_send(buf, len, pid);
 }
 
 void diag_update_pkt_buffer(unsigned char *buf, uint32_t len, int type)
@@ -506,13 +526,14 @@
 	int i, j;
 
 	mutex_lock(&driver->diagchar_mutex);
+	mutex_lock(&driver->md_session_lock);
 	for (i = 0; i < NUM_MD_SESSIONS; i++) {
 		if (driver->md_session_map[i] != NULL)
 			for (j = 0; j < driver->num_clients; j++) {
 				if (driver->client_map[j].pid != 0 &&
 					driver->client_map[j].pid ==
 					driver->md_session_map[i]->pid) {
-					if (!(driver->data_ready[i] & type)) {
+					if (!(driver->data_ready[j] & type)) {
 						driver->data_ready[j] |= type;
 						atomic_inc(
 						&driver->data_ready_notif[j]);
@@ -521,6 +542,7 @@
 				}
 			}
 	}
+	mutex_unlock(&driver->md_session_lock);
 	wake_up_interruptible(&driver->wait_q);
 	mutex_unlock(&driver->diagchar_mutex);
 }
@@ -982,7 +1004,7 @@
 }
 
 void diag_send_error_rsp(unsigned char *buf, int len,
-			struct diag_md_session_t *info)
+			int pid)
 {
 	/* -1 to accommodate the first byte 0x13 */
 	if (len > (DIAG_MAX_RSP_SIZE - 1)) {
@@ -992,13 +1014,12 @@
 
 	*(uint8_t *)driver->apps_rsp_buf = DIAG_CMD_ERROR;
 	memcpy((driver->apps_rsp_buf + sizeof(uint8_t)), buf, len);
-	diag_send_rsp(driver->apps_rsp_buf, len + 1, info);
+	diag_send_rsp(driver->apps_rsp_buf, len + 1, pid);
 }
 
-int diag_process_apps_pkt(unsigned char *buf, int len,
-			struct diag_md_session_t *info)
+int diag_process_apps_pkt(unsigned char *buf, int len, int pid)
 {
-	int i;
+	int i, p_mask = 0;
 	int mask_ret;
 	int write_len = 0;
 	unsigned char *temp = NULL;
@@ -1007,14 +1028,15 @@
 	struct diag_cmd_reg_t *reg_item = NULL;
 	struct diagfwd_info *fwd_info = NULL;
 	uint32_t pd_mask = 0;
+	struct diag_md_session_t *info = NULL;
 
 	if (!buf)
 		return -EIO;
 
 	/* Check if the command is a supported mask command */
-	mask_ret = diag_process_apps_masks(buf, len, info);
+	mask_ret = diag_process_apps_masks(buf, len, pid);
 	if (mask_ret > 0) {
-		diag_send_rsp(driver->apps_rsp_buf, mask_ret, info);
+		diag_send_rsp(driver->apps_rsp_buf, mask_ret, pid);
 		return 0;
 	}
 
@@ -1036,7 +1058,7 @@
 						   driver->apps_rsp_buf,
 						   DIAG_MAX_RSP_SIZE);
 		if (write_len > 0)
-			diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+			diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
 		return 0;
 	}
 
@@ -1045,18 +1067,22 @@
 	if (temp_entry) {
 		reg_item = container_of(temp_entry, struct diag_cmd_reg_t,
 					entry);
+		mutex_lock(&driver->md_session_lock);
+		info = diag_md_session_get_pid(pid);
 		if (info) {
+			p_mask = info->peripheral_mask;
+			mutex_unlock(&driver->md_session_lock);
 			MD_PERIPHERAL_PD_MASK(TYPE_CMD, reg_item->proc,
 				pd_mask);
 			if ((MD_PERIPHERAL_MASK(reg_item->proc) &
-				info->peripheral_mask) ||
-				(pd_mask & info->peripheral_mask))
+				p_mask) || (pd_mask & p_mask))
 				write_len = diag_send_data(reg_item, buf, len);
 		} else {
+			mutex_unlock(&driver->md_session_lock);
 			if (MD_PERIPHERAL_MASK(reg_item->proc) &
 				driver->logging_mask) {
 				mutex_unlock(&driver->cmd_reg_mutex);
-				diag_send_error_rsp(buf, len, info);
+				diag_send_error_rsp(buf, len, pid);
 				return write_len;
 			}
 			else
@@ -1074,13 +1100,13 @@
 		for (i = 0; i < 4; i++)
 			*(driver->apps_rsp_buf+i) = *(buf+i);
 		*(uint32_t *)(driver->apps_rsp_buf+4) = DIAG_MAX_REQ_SIZE;
-		diag_send_rsp(driver->apps_rsp_buf, 8, info);
+		diag_send_rsp(driver->apps_rsp_buf, 8, pid);
 		return 0;
 	} else if ((*buf == 0x4b) && (*(buf+1) == 0x12) &&
 		(*(uint16_t *)(buf+2) == DIAG_DIAG_STM)) {
 		len = diag_process_stm_cmd(buf, driver->apps_rsp_buf);
 		if (len > 0) {
-			diag_send_rsp(driver->apps_rsp_buf, len, info);
+			diag_send_rsp(driver->apps_rsp_buf, len, pid);
 			return 0;
 		}
 		return len;
@@ -1093,7 +1119,7 @@
 							driver->apps_rsp_buf,
 							DIAG_MAX_RSP_SIZE);
 		if (write_len > 0)
-			diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+			diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
 		return 0;
 	}
 	/* Check for time sync switch command */
@@ -1104,7 +1130,7 @@
 							driver->apps_rsp_buf,
 							DIAG_MAX_RSP_SIZE);
 		if (write_len > 0)
-			diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+			diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
 		return 0;
 	}
 	/* Check for diag id command */
@@ -1115,14 +1141,14 @@
 							driver->apps_rsp_buf,
 							DIAG_MAX_RSP_SIZE);
 		if (write_len > 0)
-			diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+			diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
 		return 0;
 	}
 	/* Check for download command */
 	else if ((chk_apps_master()) && (*buf == 0x3A)) {
 		/* send response back */
 		driver->apps_rsp_buf[0] = *buf;
-		diag_send_rsp(driver->apps_rsp_buf, 1, info);
+		diag_send_rsp(driver->apps_rsp_buf, 1, pid);
 		msleep(5000);
 		/* call download API */
 		msm_set_restart_mode(RESTART_DLOAD);
@@ -1142,7 +1168,7 @@
 			for (i = 0; i < 13; i++)
 				driver->apps_rsp_buf[i+3] = 0;
 
-			diag_send_rsp(driver->apps_rsp_buf, 16, info);
+			diag_send_rsp(driver->apps_rsp_buf, 16, pid);
 			return 0;
 		}
 	}
@@ -1151,7 +1177,7 @@
 		(*(buf+2) == 0x04) && (*(buf+3) == 0x0)) {
 		memcpy(driver->apps_rsp_buf, buf, 4);
 		driver->apps_rsp_buf[4] = wrap_enabled;
-		diag_send_rsp(driver->apps_rsp_buf, 5, info);
+		diag_send_rsp(driver->apps_rsp_buf, 5, pid);
 		return 0;
 	}
 	/* Wrap the Delayed Rsp ID */
@@ -1160,7 +1186,7 @@
 		wrap_enabled = true;
 		memcpy(driver->apps_rsp_buf, buf, 4);
 		driver->apps_rsp_buf[4] = wrap_count;
-		diag_send_rsp(driver->apps_rsp_buf, 6, info);
+		diag_send_rsp(driver->apps_rsp_buf, 6, pid);
 		return 0;
 	}
 	/* Mobile ID Rsp */
@@ -1171,7 +1197,7 @@
 						   driver->apps_rsp_buf,
 						   DIAG_MAX_RSP_SIZE);
 		if (write_len > 0) {
-			diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+			diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
 			return 0;
 		}
 	}
@@ -1191,7 +1217,7 @@
 			for (i = 0; i < 55; i++)
 				driver->apps_rsp_buf[i] = 0;
 
-			diag_send_rsp(driver->apps_rsp_buf, 55, info);
+			diag_send_rsp(driver->apps_rsp_buf, 55, pid);
 			return 0;
 		}
 		/* respond to 0x7c command */
@@ -1204,14 +1230,14 @@
 							 chk_config_get_id();
 			*(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
 			*(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
-			diag_send_rsp(driver->apps_rsp_buf, 14, info);
+			diag_send_rsp(driver->apps_rsp_buf, 14, pid);
 			return 0;
 		}
 	}
 	write_len = diag_cmd_chk_stats(buf, len, driver->apps_rsp_buf,
 				       DIAG_MAX_RSP_SIZE);
 	if (write_len > 0) {
-		diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+		diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
 		return 0;
 	}
 	write_len = diag_cmd_disable_hdlc(buf, len, driver->apps_rsp_buf,
@@ -1223,7 +1249,7 @@
 		 * before disabling HDLC encoding on Apps processor.
 		 */
 		mutex_lock(&driver->hdlc_disable_mutex);
-		diag_send_rsp(driver->apps_rsp_buf, write_len, info);
+		diag_send_rsp(driver->apps_rsp_buf, write_len, pid);
 		/*
 		 * Set the value of hdlc_disabled after sending the response to
 		 * the tools. This is required since the tools is expecting a
@@ -1231,10 +1257,13 @@
 		 */
 		pr_debug("diag: In %s, disabling HDLC encoding\n",
 		       __func__);
+		mutex_lock(&driver->md_session_lock);
+		info = diag_md_session_get_pid(pid);
 		if (info)
 			info->hdlc_disabled = 1;
 		else
 			driver->hdlc_disabled = 1;
+		mutex_unlock(&driver->md_session_lock);
 		diag_update_md_clients(HDLC_SUPPORT_TYPE);
 		mutex_unlock(&driver->hdlc_disable_mutex);
 		return 0;
@@ -1243,13 +1272,12 @@
 
 	/* We have now come to the end of the function. */
 	if (chk_apps_only())
-		diag_send_error_rsp(buf, len, info);
+		diag_send_error_rsp(buf, len, pid);
 
 	return 0;
 }
 
-void diag_process_hdlc_pkt(void *data, unsigned int len,
-			   struct diag_md_session_t *info)
+void diag_process_hdlc_pkt(void *data, unsigned int len, int pid)
 {
 	int err = 0;
 	int ret = 0;
@@ -1309,7 +1337,7 @@
 		}
 
 		err = diag_process_apps_pkt(driver->hdlc_buf,
-					    driver->hdlc_buf_len, info);
+					    driver->hdlc_buf_len, pid);
 		if (err < 0)
 			goto fail;
 	} else {
@@ -1326,7 +1354,7 @@
 	 * recovery algorithm. Send an error response if the
 	 * packet is not in expected format.
 	 */
-	diag_send_error_rsp(driver->hdlc_buf, driver->hdlc_buf_len, info);
+	diag_send_error_rsp(driver->hdlc_buf, driver->hdlc_buf_len, pid);
 	driver->hdlc_buf_len = 0;
 end:
 	mutex_unlock(&driver->diag_hdlc_mutex);
@@ -1423,9 +1451,11 @@
 
 static uint8_t hdlc_reset;
 
-static void hdlc_reset_timer_start(struct diag_md_session_t *info)
+static void hdlc_reset_timer_start(int pid)
 {
+	struct diag_md_session_t *info = NULL;
 	mutex_lock(&driver->md_session_lock);
+	info = diag_md_session_get_pid(pid);
 	if (!hdlc_timer_in_progress) {
 		hdlc_timer_in_progress = 1;
 		if (info)
@@ -1467,15 +1497,16 @@
 }
 
 static void diag_hdlc_start_recovery(unsigned char *buf, int len,
-				     struct diag_md_session_t *info)
+				     int pid)
 {
 	int i;
 	static uint32_t bad_byte_counter;
 	unsigned char *start_ptr = NULL;
 	struct diag_pkt_frame_t *actual_pkt = NULL;
+	struct diag_md_session_t *info = NULL;
 
 	hdlc_reset = 1;
-	hdlc_reset_timer_start(info);
+	hdlc_reset_timer_start(pid);
 
 	actual_pkt = (struct diag_pkt_frame_t *)buf;
 	for (i = 0; i < len; i++) {
@@ -1495,10 +1526,13 @@
 			pr_err("diag: In %s, re-enabling HDLC encoding\n",
 					__func__);
 			mutex_lock(&driver->hdlc_disable_mutex);
+			mutex_lock(&driver->md_session_lock);
+			info = diag_md_session_get_pid(pid);
 			if (info)
 				info->hdlc_disabled = 0;
 			else
 				driver->hdlc_disabled = 0;
+			mutex_unlock(&driver->md_session_lock);
 			mutex_unlock(&driver->hdlc_disable_mutex);
 			diag_update_md_clients(HDLC_SUPPORT_TYPE);
 
@@ -1511,12 +1545,11 @@
 		mutex_lock(&driver->hdlc_recovery_mutex);
 		driver->incoming_pkt.processing = 0;
 		mutex_unlock(&driver->hdlc_recovery_mutex);
-		diag_process_non_hdlc_pkt(start_ptr, len - i, info);
+		diag_process_non_hdlc_pkt(start_ptr, len - i, pid);
 	}
 }
 
-void diag_process_non_hdlc_pkt(unsigned char *buf, int len,
-			       struct diag_md_session_t *info)
+void diag_process_non_hdlc_pkt(unsigned char *buf, int len, int pid)
 {
 	int err = 0;
 	uint16_t pkt_len = 0;
@@ -1572,11 +1605,11 @@
 		if (*(uint8_t *)(data_ptr + actual_pkt->length) !=
 						CONTROL_CHAR) {
 			mutex_unlock(&driver->hdlc_recovery_mutex);
-			diag_hdlc_start_recovery(buf, len, info);
+			diag_hdlc_start_recovery(buf, len, pid);
 			mutex_lock(&driver->hdlc_recovery_mutex);
 		}
 		err = diag_process_apps_pkt(data_ptr,
-					    actual_pkt->length, info);
+					    actual_pkt->length, pid);
 		if (err) {
 			pr_err("diag: In %s, unable to process incoming data packet, err: %d\n",
 			       __func__, err);
@@ -1598,8 +1631,8 @@
 		pkt_len = actual_pkt->length;
 
 		if (actual_pkt->start != CONTROL_CHAR) {
-			diag_hdlc_start_recovery(buf, len, info);
-			diag_send_error_rsp(buf, len, info);
+			diag_hdlc_start_recovery(buf, len, pid);
+			diag_send_error_rsp(buf, len, pid);
 			goto end;
 		}
 		mutex_lock(&driver->hdlc_recovery_mutex);
@@ -1607,7 +1640,7 @@
 			pr_err("diag: In %s, incoming data is too large for the request buffer %d\n",
 			       __func__, pkt_len);
 			mutex_unlock(&driver->hdlc_recovery_mutex);
-			diag_hdlc_start_recovery(buf, len, info);
+			diag_hdlc_start_recovery(buf, len, pid);
 			break;
 		}
 		if ((pkt_len + header_len) > (len - read_bytes)) {
@@ -1624,13 +1657,13 @@
 		if (*(uint8_t *)(data_ptr + actual_pkt->length) !=
 						CONTROL_CHAR) {
 			mutex_unlock(&driver->hdlc_recovery_mutex);
-			diag_hdlc_start_recovery(buf, len, info);
+			diag_hdlc_start_recovery(buf, len, pid);
 			mutex_lock(&driver->hdlc_recovery_mutex);
 		}
 		else
 			hdlc_reset = 0;
 		err = diag_process_apps_pkt(data_ptr,
-					    actual_pkt->length, info);
+					    actual_pkt->length, pid);
 		if (err) {
 			mutex_unlock(&driver->hdlc_recovery_mutex);
 			break;
@@ -1649,9 +1682,9 @@
 		return -EINVAL;
 
 	if (!driver->hdlc_disabled)
-		diag_process_hdlc_pkt(buf, len, NULL);
+		diag_process_hdlc_pkt(buf, len, 0);
 	else
-		diag_process_non_hdlc_pkt(buf, len, NULL);
+		diag_process_non_hdlc_pkt(buf, len, 0);
 
 	diag_mux_queue_read(ctxt);
 	return 0;
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 0e0bf2d..687aeb7 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -30,10 +30,8 @@
 
 int diagfwd_init(void);
 void diagfwd_exit(void);
-void diag_process_hdlc_pkt(void *data, unsigned int len,
-			   struct diag_md_session_t *info);
-void diag_process_non_hdlc_pkt(unsigned char *data, int len,
-			       struct diag_md_session_t *info);
+void diag_process_hdlc_pkt(void *data, unsigned int len, int pid);
+void diag_process_non_hdlc_pkt(unsigned char *data, int len, int pid);
 int chk_config_get_id(void);
 int chk_apps_only(void);
 int chk_apps_master(void);
@@ -45,10 +43,8 @@
 int diag_check_common_cmd(struct diag_pkt_header_t *header);
 void diag_update_userspace_clients(unsigned int type);
 void diag_update_sleeping_process(int process_id, int data_type);
-int diag_process_apps_pkt(unsigned char *buf, int len,
-			  struct diag_md_session_t *info);
-void diag_send_error_rsp(unsigned char *buf, int len,
-			 struct diag_md_session_t *info);
+int diag_process_apps_pkt(unsigned char *buf, int len, int pid);
+void diag_send_error_rsp(unsigned char *buf, int len, int pid);
 void diag_update_pkt_buffer(unsigned char *buf, uint32_t len, int type);
 int diag_process_stm_cmd(unsigned char *buf, unsigned char *dest_buf);
 void diag_md_hdlc_reset_timer_func(unsigned long pid);
diff --git a/drivers/char/diag/diagfwd_mhi.c b/drivers/char/diag/diagfwd_mhi.c
index f27f358..f8c3fde 100644
--- a/drivers/char/diag/diagfwd_mhi.c
+++ b/drivers/char/diag/diagfwd_mhi.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
@@ -552,6 +552,8 @@
 	struct mhi_result *result = NULL;
 	struct diag_mhi_ch_t *ch = NULL;
 	void *buf = NULL;
+	struct diag_mhi_info *mhi_info = NULL;
+	unsigned long flags;
 
 	if (!cb_info)
 		return;
@@ -603,13 +605,6 @@
 		queue_work(diag_mhi[index].mhi_wq,
 			   &(diag_mhi[index].open_work));
 		break;
-	case MHI_CB_MHI_DISABLED:
-		DIAG_LOG(DIAG_DEBUG_BRIDGE,
-			 "received mhi disabled notifiation port: %d ch: %d\n",
-			 index, ch->type);
-		atomic_set(&(ch->opened), 0);
-		__mhi_close(&diag_mhi[index], CHANNELS_CLOSED);
-		break;
 	case MHI_CB_XFER:
 		/*
 		 * If the channel is a read channel, this is a read
@@ -636,6 +631,24 @@
 					   result->bytes_xferd,
 					   diag_mhi[index].id);
 		break;
+	case MHI_CB_MHI_DISABLED:
+	case MHI_CB_SYS_ERROR:
+	case MHI_CB_MHI_SHUTDOWN:
+		DIAG_LOG(DIAG_DEBUG_BRIDGE,
+			 "received mhi link down cb: %d port: %d ch: %d\n",
+			 cb_info->cb_reason, index, ch->type);
+		mhi_info = &diag_mhi[index];
+		if (!mhi_info->enabled)
+			return;
+		spin_lock_irqsave(&mhi_info->lock, flags);
+		mhi_info->enabled = 0;
+		spin_unlock_irqrestore(&mhi_info->lock, flags);
+		atomic_set(&(mhi_info->read_ch.opened), 0);
+		atomic_set(&(mhi_info->write_ch.opened), 0);
+		flush_workqueue(mhi_info->mhi_wq);
+		mhi_buf_tbl_clear(mhi_info);
+		diag_remote_dev_close(mhi_info->dev_id);
+		break;
 	default:
 		pr_err("diag: In %s, invalid cb reason 0x%x\n", __func__,
 		       cb_info->cb_reason);
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index c7bd2205..c4e6107 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -343,14 +343,13 @@
 		diag_ws_release();
 		return;
 	}
-
-	session_info =
-		diag_md_session_get_peripheral(peripheral);
+	mutex_lock(&driver->md_session_lock);
+	session_info = diag_md_session_get_peripheral(peripheral);
 	if (session_info)
 		hdlc_disabled = session_info->hdlc_disabled;
 	else
 		hdlc_disabled = driver->hdlc_disabled;
-
+	mutex_unlock(&driver->md_session_lock);
 	if (hdlc_disabled) {
 		/* The data is raw and and on APPS side HDLC is disabled */
 		if (!buf) {
@@ -633,12 +632,13 @@
 
 	mutex_lock(&driver->hdlc_disable_mutex);
 	mutex_lock(&fwd_info->data_mutex);
+	mutex_lock(&driver->md_session_lock);
 	session_info = diag_md_session_get_peripheral(fwd_info->peripheral);
 	if (session_info)
 		hdlc_disabled = session_info->hdlc_disabled;
 	else
 		hdlc_disabled = driver->hdlc_disabled;
-
+	mutex_unlock(&driver->md_session_lock);
 	if (!driver->feature[fwd_info->peripheral].encode_hdlc) {
 		if (fwd_info->buf_1 && fwd_info->buf_1->data == buf) {
 			temp_buf = fwd_info->buf_1;
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
index 3f9fcd9..7290205 100644
--- a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -20,6 +20,8 @@
 #include "mdss-dsi-pll.h"
 #include "mdss-pll.h"
 #include <dt-bindings/clock/mdss-10nm-pll-clk.h>
+#define CREATE_TRACE_POINTS
+#include "mdss_pll_trace.h"
 
 #define VCO_DELAY_USEC 1
 
@@ -890,8 +892,13 @@
 		MDSS_PLL_REG_W(pll->pll_base, PLL_PLL_OUTDIV_RATE,
 					pll->cached_outdiv);
 	}
-
+	MDSS_PLL_ATRACE_BEGIN("pll_lock");
+	trace_mdss_pll_lock_start((u64)pll->vco_cached_rate,
+			pll->vco_current_rate,
+			pll->cached_cfg0, pll->cached_cfg1,
+			pll->cached_outdiv, pll->resource_ref_cnt);
 	rc = dsi_pll_enable(vco);
+	MDSS_PLL_ATRACE_END("pll_lock");
 	if (rc) {
 		mdss_pll_resource_enable(pll, false);
 		pr_err("pll(%d) enable failed, rc=%d\n", pll->index, rc);
diff --git a/drivers/clk/qcom/mdss/mdss_pll_trace.h b/drivers/clk/qcom/mdss/mdss_pll_trace.h
new file mode 100644
index 0000000..cd4fda6
--- /dev/null
+++ b/drivers/clk/qcom/mdss/mdss_pll_trace.h
@@ -0,0 +1,116 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#if !defined(_MDSS_PLL_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _MDSS_PLL_TRACE_H_
+
+#include <linux/stringify.h>
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM mdss_pll
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE mdss_pll_trace
+
+
+TRACE_EVENT(mdss_pll_lock_start,
+	TP_PROTO(
+			u64 vco_cached_rate,
+			s64 vco_current_rate,
+			u32 cached_cfg0,
+			u32 cached_cfg1,
+			u32 cached_outdiv,
+			u32 resource_ref_cnt),
+	TP_ARGS(
+			vco_cached_rate,
+			vco_current_rate,
+			cached_cfg0,
+			cached_cfg1,
+			cached_outdiv,
+			resource_ref_cnt),
+	TP_STRUCT__entry(
+			__field(u64, vco_cached_rate)
+			__field(s64, vco_current_rate)
+			__field(u32, cached_cfg0)
+			__field(u32, cached_cfg1)
+			__field(u32, cached_outdiv)
+			__field(u32, resource_ref_cnt)
+
+	),
+	TP_fast_assign(
+			__entry->vco_cached_rate = vco_cached_rate;
+			__entry->vco_current_rate = vco_current_rate;
+			__entry->cached_cfg0 = cached_cfg0;
+			__entry->cached_cfg1 = cached_cfg1;
+			__entry->cached_outdiv = cached_outdiv;
+			__entry->resource_ref_cnt = resource_ref_cnt;
+	),
+	 TP_printk(
+		"vco_cached_rate=%llu vco_current_rate=%lld cached_cfg0=%d cached_cfg1=%d cached_outdiv=%d resource_ref_cnt=%d",
+			__entry->vco_cached_rate,
+			__entry->vco_current_rate,
+			__entry->cached_cfg0,
+			__entry->cached_cfg1,
+			__entry->cached_outdiv,
+			__entry->resource_ref_cnt)
+);
+
+TRACE_EVENT(pll_tracing_mark_write,
+	TP_PROTO(int pid, const char *name, bool trace_begin),
+	TP_ARGS(pid, name, trace_begin),
+	TP_STRUCT__entry(
+			__field(int, pid)
+			__string(trace_name, name)
+			__field(bool, trace_begin)
+	),
+	TP_fast_assign(
+			__entry->pid = pid;
+			__assign_str(trace_name, name);
+			__entry->trace_begin = trace_begin;
+	),
+	TP_printk("%s|%d|%s", __entry->trace_begin ? "B" : "E",
+		__entry->pid, __get_str(trace_name))
+)
+
+TRACE_EVENT(mdss_pll_trace_counter,
+	TP_PROTO(int pid, char *name, int value),
+	TP_ARGS(pid, name, value),
+	TP_STRUCT__entry(
+			__field(int, pid)
+			__string(counter_name, name)
+			__field(int, value)
+	),
+	TP_fast_assign(
+			__entry->pid = current->tgid;
+			__assign_str(counter_name, name);
+			__entry->value = value;
+	),
+	TP_printk("%d|%s|%d", __entry->pid,
+			__get_str(counter_name), __entry->value)
+)
+
+#define MDSS_PLL_ATRACE_END(name) trace_pll_tracing_mark_write(current->tgid,\
+		name, 0)
+#define MDSS_PLL_ATRACE_BEGIN(name) trace_pll_tracing_mark_write(current->tgid,\
+		name, 1)
+#define MDSS_PLL_ATRACE_FUNC() MDSS_PLL_ATRACE_BEGIN(__func__)
+#define MDSS_PLL_ATRACE_INT(name, value) \
+	trace_mdss_pll_trace_counter(current->tgid, name, value)
+
+
+#endif /* _MDSS_PLL_TRACE_H_ */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#include <trace/define_trace.h>
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 19fe223..6c66b7f 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -1251,7 +1251,6 @@
 
 		state_id |= (level->psci_id & cluster->psci_mode_mask)
 					<< cluster->psci_mode_shift;
-		(*aff_lvl)++;
 
 		/*
 		 * We may have updated the broadcast timers, update
@@ -1259,6 +1258,8 @@
 		 */
 		if (level->notify_rpm)
 			system_sleep_update_wakeup();
+		if (level->psci_id)
+			(*aff_lvl)++;
 	}
 unlock_and_return:
 	spin_unlock(&cluster->sync_lock);
@@ -1731,6 +1732,18 @@
 {
 	int rc;
 
+#ifdef CONFIG_ARM
+	int cpu;
+
+	for_each_possible_cpu(cpu) {
+		rc = arm_cpuidle_init(smp_processor_id());
+		if (rc) {
+			pr_err("CPU%d ARM CPUidle init failed (%d)\n", cpu, rc);
+			return rc;
+		}
+	}
+#endif
+
 	rc = platform_driver_register(&lpm_driver);
 	if (rc) {
 		pr_info("Error registering %s\n", lpm_driver.driver.name);
diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c
index 2b6b112..3d50bae 100644
--- a/drivers/firmware/psci.c
+++ b/drivers/firmware/psci.c
@@ -249,8 +249,9 @@
 }
 
 #ifdef CONFIG_CPU_IDLE
-static DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
+static __maybe_unused DEFINE_PER_CPU_READ_MOSTLY(u32 *, psci_power_state);
 
+#ifdef CONFIG_DT_IDLE_STATES
 static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
 {
 	int i, ret, count = 0;
@@ -303,6 +304,10 @@
 	kfree(psci_states);
 	return ret;
 }
+#else
+static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
+{ return 0; }
+#endif
 
 #ifdef CONFIG_ACPI
 #include <acpi/processor.h>
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 79f2ec9..0a3fb24 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -29,22 +29,25 @@
 	struct dp_aux dp_aux;
 	struct dp_catalog_aux *catalog;
 	struct dp_aux_cfg *cfg;
-
 	struct mutex mutex;
 	struct completion comp;
+	struct drm_dp_aux drm_aux;
 
-	u32 aux_error_num;
-	u32 retry_cnt;
 	bool cmd_busy;
 	bool native;
 	bool read;
 	bool no_send_addr;
 	bool no_send_stop;
+
 	u32 offset;
 	u32 segment;
+	u32 aux_error_num;
+	u32 retry_cnt;
+
 	atomic_t aborted;
 
-	struct drm_dp_aux drm_aux;
+	u8 *dpcd;
+	u8 *edid;
 };
 
 static char *dp_aux_get_error(u32 aux_error)
@@ -320,6 +323,7 @@
  *
  * @aux: DP AUX private structure
  * @input_msg: input message from DRM upstream APIs
+ * @send_seg: send the seg to sink
  *
  * return: void
  *
@@ -327,7 +331,7 @@
  * sinks that do not handle the i2c middle-of-transaction flag correctly.
  */
 static void dp_aux_transfer_helper(struct dp_aux_private *aux,
-		struct drm_dp_aux_msg *input_msg)
+		struct drm_dp_aux_msg *input_msg, bool send_seg)
 {
 	struct drm_dp_aux_msg helper_msg;
 	u32 const message_size = 0x10;
@@ -346,7 +350,7 @@
 	 * duplicate AUX transactions related to this while reading the
 	 * first 16 bytes of each block.
 	 */
-	if (!(aux->offset % edid_block_length))
+	if (!(aux->offset % edid_block_length) || !send_seg)
 		goto end;
 
 	aux->read = false;
@@ -388,26 +392,16 @@
 		aux->segment = 0x0; /* reset segment at end of block */
 }
 
-/*
- * This function does the real job to process an AUX transaction.
- * It will call aux_reset() function to reset the AUX channel,
- * if the waiting is timeout.
- */
-static ssize_t dp_aux_transfer(struct drm_dp_aux *drm_aux,
-		struct drm_dp_aux_msg *msg)
+static int dp_aux_transfer_ready(struct dp_aux_private *aux,
+		struct drm_dp_aux_msg *msg, bool send_seg)
 {
-	ssize_t ret;
+	int ret = 0;
 	int const aux_cmd_native_max = 16;
 	int const aux_cmd_i2c_max = 128;
-	int const retry_count = 5;
-	struct dp_aux_private *aux = container_of(drm_aux,
-		struct dp_aux_private, drm_aux);
-
-	mutex_lock(&aux->mutex);
 
 	if (atomic_read(&aux->aborted)) {
 		ret = -ETIMEDOUT;
-		goto unlock_exit;
+		goto error;
 	}
 
 	aux->native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);
@@ -416,8 +410,7 @@
 	if ((msg->size == 0) || (msg->buffer == NULL)) {
 		msg->reply = aux->native ?
 			DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
-		ret = msg->size;
-		goto unlock_exit;
+		goto error;
 	}
 
 	/* msg sanity check */
@@ -426,14 +419,14 @@
 		pr_err("%s: invalid msg: size(%zu), request(%x)\n",
 			__func__, msg->size, msg->request);
 		ret = -EINVAL;
-		goto unlock_exit;
+		goto error;
 	}
 
 	dp_aux_update_offset_and_segment(aux, msg);
-	dp_aux_transfer_helper(aux, msg);
+
+	dp_aux_transfer_helper(aux, msg, send_seg);
 
 	aux->read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
-	aux->cmd_busy = true;
 
 	if (aux->read) {
 		aux->no_send_addr = true;
@@ -443,6 +436,98 @@
 		aux->no_send_stop = true;
 	}
 
+	aux->cmd_busy = true;
+error:
+	return ret;
+}
+
+static ssize_t dp_aux_transfer_debug(struct drm_dp_aux *drm_aux,
+		struct drm_dp_aux_msg *msg)
+{
+	u8 buf[SZ_64];
+	u32 timeout;
+	ssize_t ret;
+	struct dp_aux_private *aux = container_of(drm_aux,
+		struct dp_aux_private, drm_aux);
+
+	ret = dp_aux_transfer_ready(aux, msg, false);
+	if (ret)
+		goto end;
+
+	aux->aux_error_num = DP_AUX_ERR_NONE;
+
+	if (aux->native) {
+		if (aux->read && ((msg->address + msg->size) < SZ_1K)) {
+			aux->dp_aux.reg = msg->address;
+
+			reinit_completion(&aux->comp);
+			timeout = wait_for_completion_timeout(&aux->comp, HZ);
+			if (!timeout)
+				pr_err("aux timeout for 0x%x\n", msg->address);
+
+			aux->dp_aux.reg = 0xFFFF;
+
+			memcpy(msg->buffer, aux->dpcd + msg->address,
+				msg->size);
+			aux->aux_error_num = DP_AUX_ERR_NONE;
+		} else {
+			memset(msg->buffer, 0, msg->size);
+		}
+	} else {
+		if (aux->read && msg->address == 0x50) {
+			memcpy(msg->buffer,
+				aux->edid + aux->offset - 16,
+				msg->size);
+		}
+	}
+
+	if (aux->aux_error_num == DP_AUX_ERR_NONE) {
+		snprintf(buf, SZ_64, "[drm-dp] dbg: %5s %5s %5xh(%2zu): ",
+			aux->native ? "NATIVE" : "I2C",
+			aux->read ? "READ" : "WRITE",
+			msg->address, msg->size);
+
+		print_hex_dump(KERN_DEBUG, buf,
+			DUMP_PREFIX_NONE, 8, 1, msg->buffer, msg->size, false);
+
+		msg->reply = aux->native ?
+			DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
+	} else {
+		/* Reply defer to retry */
+		msg->reply = aux->native ?
+			DP_AUX_NATIVE_REPLY_DEFER : DP_AUX_I2C_REPLY_DEFER;
+	}
+
+	ret = msg->size;
+end:
+	return ret;
+}
+
+/*
+ * This function does the real job to process an AUX transaction.
+ * It will call aux_reset() function to reset the AUX channel,
+ * if the waiting is timeout.
+ */
+static ssize_t dp_aux_transfer(struct drm_dp_aux *drm_aux,
+		struct drm_dp_aux_msg *msg)
+{
+	u8 buf[SZ_64];
+	ssize_t ret;
+	int const retry_count = 5;
+	struct dp_aux_private *aux = container_of(drm_aux,
+		struct dp_aux_private, drm_aux);
+
+	mutex_lock(&aux->mutex);
+
+	ret = dp_aux_transfer_ready(aux, msg, true);
+	if (ret)
+		goto unlock_exit;
+
+	if (!aux->cmd_busy) {
+		ret = msg->size;
+		goto unlock_exit;
+	}
+
 	ret = dp_aux_cmd_fifo_tx(aux, msg);
 	if ((ret < 0) && aux->native && !atomic_read(&aux->aborted)) {
 		aux->retry_cnt++;
@@ -459,6 +544,14 @@
 		if (aux->read)
 			dp_aux_cmd_fifo_rx(aux, msg);
 
+		snprintf(buf, SZ_64, "[drm-dp] %5s %5s %5xh(%2zu): ",
+			aux->native ? "NATIVE" : "I2C",
+			aux->read ? "READ" : "WRITE",
+			msg->address, msg->size);
+
+		print_hex_dump(KERN_DEBUG, buf,
+			DUMP_PREFIX_NONE, 8, 1, msg->buffer, msg->size, false);
+
 		msg->reply = aux->native ?
 			DP_AUX_NATIVE_REPLY_ACK : DP_AUX_I2C_REPLY_ACK;
 	} else {
@@ -558,6 +651,41 @@
 	drm_dp_aux_unregister(&aux->drm_aux);
 }
 
+static void dp_aux_dpcd_updated(struct dp_aux *dp_aux)
+{
+	struct dp_aux_private *aux;
+
+	if (!dp_aux) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+	complete(&aux->comp);
+}
+
+static void dp_aux_set_sim_mode(struct dp_aux *dp_aux, bool en,
+		u8 *edid, u8 *dpcd)
+{
+	struct dp_aux_private *aux;
+
+	if (!dp_aux) {
+		pr_err("invalid input\n");
+		return;
+	}
+
+	aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+	aux->edid = edid;
+	aux->dpcd = dpcd;
+
+	if (en)
+		aux->drm_aux.transfer = dp_aux_transfer_debug;
+	else
+		aux->drm_aux.transfer = dp_aux_transfer;
+}
+
 struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
 		struct dp_aux_cfg *aux_cfg)
 {
@@ -586,6 +714,7 @@
 	aux->cfg = aux_cfg;
 	dp_aux = &aux->dp_aux;
 	aux->retry_cnt = 0;
+	aux->dp_aux.reg = 0xFFFF;
 
 	dp_aux->isr     = dp_aux_isr;
 	dp_aux->init    = dp_aux_init;
@@ -594,6 +723,8 @@
 	dp_aux->drm_aux_deregister = dp_aux_deregister;
 	dp_aux->reconfig = dp_aux_reconfig;
 	dp_aux->abort = dp_aux_abort_transaction;
+	dp_aux->dpcd_updated = dp_aux_dpcd_updated;
+	dp_aux->set_sim_mode = dp_aux_set_sim_mode;
 
 	return dp_aux;
 error:
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.h b/drivers/gpu/drm/msm/dp/dp_aux.h
index e8cb1cc..bf52d57 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.h
+++ b/drivers/gpu/drm/msm/dp/dp_aux.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,19 @@
 #include "dp_catalog.h"
 #include "drm_dp_helper.h"
 
+#define DP_STATE_NOTIFICATION_SENT          BIT(0)
+#define DP_STATE_TRAIN_1_STARTED            BIT(1)
+#define DP_STATE_TRAIN_1_SUCCEEDED          BIT(2)
+#define DP_STATE_TRAIN_1_FAILED             BIT(3)
+#define DP_STATE_TRAIN_2_STARTED            BIT(4)
+#define DP_STATE_TRAIN_2_SUCCEEDED          BIT(5)
+#define DP_STATE_TRAIN_2_FAILED             BIT(6)
+#define DP_STATE_CTRL_POWERED_ON            BIT(7)
+#define DP_STATE_CTRL_POWERED_OFF           BIT(8)
+#define DP_STATE_LINK_MAINTENANCE_STARTED   BIT(9)
+#define DP_STATE_LINK_MAINTENANCE_COMPLETED BIT(10)
+#define DP_STATE_LINK_MAINTENANCE_FAILED    BIT(11)
+
 enum dp_aux_error {
 	DP_AUX_ERR_NONE	= 0,
 	DP_AUX_ERR_ADDR	= -1,
@@ -29,6 +42,9 @@
 };
 
 struct dp_aux {
+	u32 reg;
+	u32 state;
+
 	struct drm_dp_aux *drm_aux;
 	int (*drm_aux_register)(struct dp_aux *aux);
 	void (*drm_aux_deregister)(struct dp_aux *aux);
@@ -37,6 +53,8 @@
 	void (*deinit)(struct dp_aux *aux);
 	void (*reconfig)(struct dp_aux *aux);
 	void (*abort)(struct dp_aux *aux);
+	void (*dpcd_updated)(struct dp_aux *aux);
+	void (*set_sim_mode)(struct dp_aux *aux, bool en, u8 *edid, u8 *dpcd);
 };
 
 struct dp_aux *dp_aux_get(struct device *dev, struct dp_catalog_aux *catalog,
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index cb54b5f..2e2887e 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -820,6 +820,10 @@
 	u8 link_status[DP_LINK_STATUS_SIZE];
 	int const maximum_retries = 5;
 
+	ctrl->aux->state &= ~DP_STATE_TRAIN_1_FAILED;
+	ctrl->aux->state &= ~DP_STATE_TRAIN_1_SUCCEEDED;
+	ctrl->aux->state |= DP_STATE_TRAIN_1_STARTED;
+
 	dp_ctrl_state_ctrl(ctrl, 0);
 	/* Make sure to clear the current pattern before starting a new one */
 	wmb();
@@ -829,13 +833,13 @@
 		DP_LINK_SCRAMBLING_DISABLE); /* train_1 */
 	if (ret <= 0) {
 		ret = -EINVAL;
-		return ret;
+		goto end;
 	}
 
 	ret = dp_ctrl_update_vx_px(ctrl);
 	if (ret <= 0) {
 		ret = -EINVAL;
-		return ret;
+		goto end;
 	}
 
 	tries = 0;
@@ -879,6 +883,13 @@
 			break;
 		}
 	}
+end:
+	ctrl->aux->state &= ~DP_STATE_TRAIN_1_STARTED;
+
+	if (ret)
+		ctrl->aux->state |= DP_STATE_TRAIN_1_FAILED;
+	else
+		ctrl->aux->state |= DP_STATE_TRAIN_1_SUCCEEDED;
 
 	return ret;
 }
@@ -922,6 +933,10 @@
 	int const maximum_retries = 5;
 	u8 link_status[DP_LINK_STATUS_SIZE];
 
+	ctrl->aux->state &= ~DP_STATE_TRAIN_2_FAILED;
+	ctrl->aux->state &= ~DP_STATE_TRAIN_2_SUCCEEDED;
+	ctrl->aux->state |= DP_STATE_TRAIN_2_STARTED;
+
 	dp_ctrl_state_ctrl(ctrl, 0);
 	/* Make sure to clear the current pattern before starting a new one */
 	wmb();
@@ -934,14 +949,14 @@
 	ret = dp_ctrl_update_vx_px(ctrl);
 	if (ret <= 0) {
 		ret = -EINVAL;
-		return ret;
+		goto end;
 	}
 	ctrl->catalog->set_pattern(ctrl->catalog, pattern);
 	ret = dp_ctrl_train_pattern_set(ctrl,
 		pattern | DP_RECOVERED_CLOCK_OUT_EN);
 	if (ret <= 0) {
 		ret = -EINVAL;
-		return ret;
+		goto end;
 	}
 
 	do  {
@@ -968,7 +983,13 @@
 			break;
 		}
 	} while (!atomic_read(&ctrl->aborted));
+end:
+	ctrl->aux->state &= ~DP_STATE_TRAIN_2_STARTED;
 
+	if (ret)
+		ctrl->aux->state |= DP_STATE_TRAIN_2_FAILED;
+	else
+		ctrl->aux->state |= DP_STATE_TRAIN_2_SUCCEEDED;
 	return ret;
 }
 
@@ -1109,8 +1130,7 @@
 	return ctrl->power->clk_enable(ctrl->power, DP_CTRL_PM, false);
 }
 
-static int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl,
-	bool flip, bool multi_func)
+static int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset)
 {
 	struct dp_ctrl_private *ctrl;
 	struct dp_catalog_ctrl *catalog;
@@ -1125,7 +1145,7 @@
 	ctrl->orientation = flip;
 	catalog = ctrl->catalog;
 
-	if (!multi_func) {
+	if (reset) {
 		catalog->usb_reset(ctrl->catalog, flip);
 		catalog->phy_reset(ctrl->catalog);
 	}
@@ -1192,6 +1212,10 @@
 		return -EINVAL;
 	}
 
+	ctrl->aux->state &= ~DP_STATE_LINK_MAINTENANCE_COMPLETED;
+	ctrl->aux->state &= ~DP_STATE_LINK_MAINTENANCE_FAILED;
+	ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_STARTED;
+
 	ctrl->dp_ctrl.push_idle(&ctrl->dp_ctrl);
 	ctrl->dp_ctrl.reset(&ctrl->dp_ctrl);
 
@@ -1231,6 +1255,13 @@
 		ret = dp_ctrl_setup_main_link(ctrl, true);
 	} while (ret == -EAGAIN);
 
+	ctrl->aux->state &= ~DP_STATE_LINK_MAINTENANCE_STARTED;
+
+	if (ret)
+		ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_FAILED;
+	else
+		ctrl->aux->state |= DP_STATE_LINK_MAINTENANCE_COMPLETED;
+
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index 229c779..31d8f07 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -23,7 +23,7 @@
 #include "dp_catalog.h"
 
 struct dp_ctrl {
-	int (*init)(struct dp_ctrl *dp_ctrl, bool flip, bool multi_func);
+	int (*init)(struct dp_ctrl *dp_ctrl, bool flip, bool reset);
 	void (*deinit)(struct dp_ctrl *dp_ctrl);
 	int (*on)(struct dp_ctrl *dp_ctrl);
 	void (*off)(struct dp_ctrl *dp_ctrl);
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index 054b3c8..a63b2c5 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -36,15 +36,52 @@
 	u8 *dpcd;
 	u32 dpcd_size;
 
+	int vdo;
+
 	struct dp_usbpd *usbpd;
 	struct dp_link *link;
 	struct dp_panel *panel;
+	struct dp_aux *aux;
 	struct drm_connector **connector;
 	struct device *dev;
-
+	struct work_struct sim_work;
 	struct dp_debug dp_debug;
 };
 
+static int dp_debug_get_edid_buf(struct dp_debug_private *debug)
+{
+	int rc = 0;
+
+	if (!debug->edid) {
+		debug->edid = devm_kzalloc(debug->dev, SZ_256, GFP_KERNEL);
+		if (!debug->edid) {
+			rc = -ENOMEM;
+			goto end;
+		}
+
+		debug->edid_size = SZ_256;
+	}
+end:
+	return rc;
+}
+
+static int dp_debug_get_dpcd_buf(struct dp_debug_private *debug)
+{
+	int rc = 0;
+
+	if (!debug->dpcd) {
+		debug->dpcd = devm_kzalloc(debug->dev, SZ_1K, GFP_KERNEL);
+		if (!debug->dpcd) {
+			rc = -ENOMEM;
+			goto end;
+		}
+
+		debug->dpcd_size = SZ_1K;
+	}
+end:
+	return rc;
+}
+
 static ssize_t dp_debug_write_edid(struct file *file,
 		const char __user *user_buff, size_t count, loff_t *ppos)
 {
@@ -75,7 +112,8 @@
 	edid_size = size / char_to_nib;
 	buf_t = buf;
 
-	memset(debug->edid, 0, debug->edid_size);
+	if (dp_debug_get_edid_buf(debug))
+		goto bail;
 
 	if (edid_size != debug->edid_size) {
 		pr_debug("clearing debug edid\n");
@@ -100,13 +138,13 @@
 		buf_t += char_to_nib;
 	}
 
-	print_hex_dump(KERN_DEBUG, "DEBUG EDID: ", DUMP_PREFIX_NONE,
-		16, 1, debug->edid, debug->edid_size, false);
-
 	edid = debug->edid;
 bail:
 	kfree(buf);
-	debug->panel->set_edid(debug->panel, edid);
+
+	if (!debug->dp_debug.sim_mode)
+		debug->panel->set_edid(debug->panel, edid);
+
 	return rc;
 }
 
@@ -119,8 +157,8 @@
 	size_t dpcd_size = 0;
 	size_t size = 0, dpcd_buf_index = 0;
 	ssize_t rc = count;
-
-	pr_debug("count=%zu\n", count);
+	char offset_ch[5];
+	u32 offset;
 
 	if (!debug)
 		return -ENODEV;
@@ -128,7 +166,7 @@
 	if (*ppos)
 		goto bail;
 
-	size = min_t(size_t, count, SZ_32);
+	size = min_t(size_t, count, SZ_2K);
 
 	buf = kzalloc(size, GFP_KERNEL);
 	if (!buf) {
@@ -139,16 +177,30 @@
 	if (copy_from_user(buf, user_buff, size))
 		goto bail;
 
-	dpcd_size = size / char_to_nib;
-	buf_t = buf;
+	memcpy(offset_ch, buf, 4);
+	offset_ch[4] = '\0';
 
-	memset(debug->dpcd, 0, debug->dpcd_size);
-
-	if (dpcd_size != debug->dpcd_size) {
-		pr_debug("clearing debug dpcd\n");
+	if (kstrtoint(offset_ch, 16, &offset)) {
+		pr_err("offset kstrtoint error\n");
 		goto bail;
 	}
 
+	if (dp_debug_get_dpcd_buf(debug))
+		goto bail;
+
+	if (offset == 0xFFFF) {
+		pr_err("clearing dpcd\n");
+		memset(debug->dpcd, 0, debug->dpcd_size);
+		goto bail;
+	}
+
+	size -= 4;
+
+	dpcd_size = size / char_to_nib;
+	buf_t = buf + 4;
+
+	dpcd_buf_index = offset;
+
 	while (dpcd_size--) {
 		char t[3];
 		int d;
@@ -167,16 +219,39 @@
 		buf_t += char_to_nib;
 	}
 
-	print_hex_dump(KERN_DEBUG, "DEBUG DPCD: ", DUMP_PREFIX_NONE,
-		8, 1, debug->dpcd, debug->dpcd_size, false);
-
 	dpcd = debug->dpcd;
 bail:
 	kfree(buf);
-	debug->panel->set_dpcd(debug->panel, dpcd);
+	if (debug->dp_debug.sim_mode)
+		debug->aux->dpcd_updated(debug->aux);
+	else
+		debug->panel->set_dpcd(debug->panel, dpcd);
+
 	return rc;
 }
 
+static ssize_t dp_debug_read_dpcd(struct file *file,
+		char __user *user_buff, size_t count, loff_t *ppos)
+{
+	struct dp_debug_private *debug = file->private_data;
+	char buf[SZ_8];
+	u32 len = 0;
+
+	if (!debug)
+		return -ENODEV;
+
+	if (*ppos)
+		return 0;
+
+	len += snprintf(buf, SZ_8, "0x%x\n", debug->aux->reg);
+
+	if (copy_to_user(user_buff, buf, len))
+		return -EFAULT;
+
+	*ppos += len;
+	return len;
+}
+
 static ssize_t dp_debug_write_hpd(struct file *file,
 		const char __user *user_buff, size_t count, loff_t *ppos)
 {
@@ -421,7 +496,6 @@
 	struct dp_debug_private *debug = file->private_data;
 	char *buf;
 	u32 len = 0, rc = 0;
-	u64 lclk = 0;
 	u32 max_size = SZ_4K;
 
 	if (!debug)
@@ -434,124 +508,60 @@
 	if (!buf)
 		return -ENOMEM;
 
-	rc = snprintf(buf + len, max_size, "\tname = %s\n", DEBUG_NAME);
+	rc = snprintf(buf + len, max_size, "\tstate=0x%x\n", debug->aux->state);
 	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
 		goto error;
 
-	rc = snprintf(buf + len, max_size,
-		"\tdp_panel\n\t\tmax_pclk_khz = %d\n",
-		debug->panel->max_pclk_khz);
-	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
-		goto error;
-
-	rc = snprintf(buf + len, max_size,
-		"\tdrm_dp_link\n\t\trate = %u\n",
+	rc = snprintf(buf + len, max_size, "\tlink_rate=%u\n",
 		debug->panel->link_info.rate);
 	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
 		goto error;
 
-	rc = snprintf(buf + len, max_size,
-		"\t\tnum_lanes = %u\n",
+	rc = snprintf(buf + len, max_size, "\tnum_lanes=%u\n",
 		debug->panel->link_info.num_lanes);
 	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
 		goto error;
 
-	rc = snprintf(buf + len, max_size,
-		"\t\tcapabilities = %lu\n",
-		debug->panel->link_info.capabilities);
-	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
-		goto error;
-
-	rc = snprintf(buf + len, max_size,
-		"\tdp_panel_info:\n\t\tactive = %dx%d\n",
+	rc = snprintf(buf + len, max_size, "\tresolution=%dx%d@%dHz\n",
 		debug->panel->pinfo.h_active,
-		debug->panel->pinfo.v_active);
-	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
-		goto error;
-
-	rc = snprintf(buf + len, max_size,
-		"\t\tback_porch = %dx%d\n",
-		debug->panel->pinfo.h_back_porch,
-		debug->panel->pinfo.v_back_porch);
-	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
-		goto error;
-
-	rc = snprintf(buf + len, max_size,
-		"\t\tfront_porch = %dx%d\n",
-		debug->panel->pinfo.h_front_porch,
-		debug->panel->pinfo.v_front_porch);
-	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
-		goto error;
-
-	rc = snprintf(buf + len, max_size,
-		"\t\tsync_width = %dx%d\n",
-		debug->panel->pinfo.h_sync_width,
-		debug->panel->pinfo.v_sync_width);
-	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
-		goto error;
-
-	rc = snprintf(buf + len, max_size,
-		"\t\tactive_low = %dx%d\n",
-		debug->panel->pinfo.h_active_low,
-		debug->panel->pinfo.v_active_low);
-	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
-		goto error;
-
-	rc = snprintf(buf + len, max_size,
-		"\t\th_skew = %d\n",
-		debug->panel->pinfo.h_skew);
-	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
-		goto error;
-
-	rc = snprintf(buf + len, max_size,
-		"\t\trefresh rate = %d\n",
+		debug->panel->pinfo.v_active,
 		debug->panel->pinfo.refresh_rate);
 	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
 		goto error;
 
-	rc = snprintf(buf + len, max_size,
-		"\t\tpixel clock khz = %d\n",
+	rc = snprintf(buf + len, max_size, "\tpclock=%dKHz\n",
 		debug->panel->pinfo.pixel_clk_khz);
 	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
 		goto error;
 
-	rc = snprintf(buf + len, max_size,
-		"\t\tbpp = %d\n",
+	rc = snprintf(buf + len, max_size, "\tbpp=%d\n",
 		debug->panel->pinfo.bpp);
 	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
 		goto error;
 
 	/* Link Information */
-	rc = snprintf(buf + len, max_size,
-		"\tdp_link:\n\t\ttest_requested = %d\n",
-		debug->link->sink_request);
+	rc = snprintf(buf + len, max_size, "\ttest_req=%s\n",
+		dp_link_get_test_name(debug->link->sink_request));
 	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
 		goto error;
 
 	rc = snprintf(buf + len, max_size,
-		"\t\tlane_count = %d\n", debug->link->link_params.lane_count);
+		"\tlane_count=%d\n", debug->link->link_params.lane_count);
 	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
 		goto error;
 
 	rc = snprintf(buf + len, max_size,
-		"\t\tbw_code = %d\n", debug->link->link_params.bw_code);
-	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
-		goto error;
-
-	lclk = drm_dp_bw_code_to_link_rate(
-			debug->link->link_params.bw_code) * 1000;
-	rc = snprintf(buf + len, max_size,
-		"\t\tlclk = %lld\n", lclk);
+		"\tbw_code=%d\n", debug->link->link_params.bw_code);
 	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
 		goto error;
 
 	rc = snprintf(buf + len, max_size,
-		"\t\tv_level = %d\n", debug->link->phy_params.v_level);
+		"\tv_level=%d\n", debug->link->phy_params.v_level);
 	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
 		goto error;
 
 	rc = snprintf(buf + len, max_size,
-		"\t\tp_level = %d\n", debug->link->phy_params.p_level);
+		"\tp_level=%d\n", debug->link->phy_params.p_level);
 	if (dp_debug_check_buffer_overflow(rc, &max_size, &len))
 		goto error;
 
@@ -816,6 +826,90 @@
 	return rc;
 }
 
+static ssize_t dp_debug_write_sim(struct file *file,
+		const char __user *user_buff, size_t count, loff_t *ppos)
+{
+	struct dp_debug_private *debug = file->private_data;
+	char buf[SZ_8];
+	size_t len = 0;
+	int sim;
+
+	if (!debug)
+		return -ENODEV;
+
+	if (*ppos)
+		return 0;
+
+	/* Leave room for termination char */
+	len = min_t(size_t, count, SZ_8 - 1);
+	if (copy_from_user(buf, user_buff, len))
+		goto end;
+
+	buf[len] = '\0';
+
+	if (kstrtoint(buf, 10, &sim) != 0)
+		goto end;
+
+	if (sim) {
+		if (dp_debug_get_edid_buf(debug))
+			goto end;
+
+		if (dp_debug_get_dpcd_buf(debug))
+			goto error;
+	} else {
+		if (debug->edid) {
+			devm_kfree(debug->dev, debug->edid);
+			debug->edid = NULL;
+		}
+
+		if (debug->dpcd) {
+			devm_kfree(debug->dev, debug->dpcd);
+			debug->dpcd = NULL;
+		}
+	}
+
+	debug->dp_debug.sim_mode = !!sim;
+
+	debug->aux->set_sim_mode(debug->aux, debug->dp_debug.sim_mode,
+			debug->edid, debug->dpcd);
+end:
+	return len;
+error:
+	devm_kfree(debug->dev, debug->edid);
+	return len;
+}
+
+static ssize_t dp_debug_write_attention(struct file *file,
+		const char __user *user_buff, size_t count, loff_t *ppos)
+{
+	struct dp_debug_private *debug = file->private_data;
+	char buf[SZ_8];
+	size_t len = 0;
+	int vdo;
+
+	if (!debug)
+		return -ENODEV;
+
+	if (*ppos)
+		return 0;
+
+	/* Leave room for termination char */
+	len = min_t(size_t, count, SZ_8 - 1);
+	if (copy_from_user(buf, user_buff, len))
+		goto end;
+
+	buf[len] = '\0';
+
+	if (kstrtoint(buf, 10, &vdo) != 0)
+		goto end;
+
+	debug->vdo = vdo;
+
+	schedule_work(&debug->sim_work);
+end:
+	return len;
+}
+
 static const struct file_operations dp_debug_fops = {
 	.open = simple_open,
 	.read = dp_debug_read_info,
@@ -840,6 +934,7 @@
 static const struct file_operations dpcd_fops = {
 	.open = simple_open,
 	.write = dp_debug_write_dpcd,
+	.read = dp_debug_read_dpcd,
 };
 
 static const struct file_operations connected_fops = {
@@ -865,6 +960,16 @@
 	.read = dp_debug_read_hdr,
 };
 
+static const struct file_operations sim_fops = {
+	.open = simple_open,
+	.write = dp_debug_write_sim,
+};
+
+static const struct file_operations attention_fops = {
+	.open = simple_open,
+	.write = dp_debug_write_attention,
+};
+
 static int dp_debug_init(struct dp_debug *dp_debug)
 {
 	int rc = 0;
@@ -967,6 +1072,26 @@
 		goto error_remove_dir;
 	}
 
+	file = debugfs_create_file("sim", 0644, dir,
+		debug, &sim_fops);
+
+	if (IS_ERR_OR_NULL(file)) {
+		rc = PTR_ERR(file);
+		pr_err("[%s] debugfs sim failed, rc=%d\n",
+			DEBUG_NAME, rc);
+		goto error_remove_dir;
+	}
+
+	file = debugfs_create_file("attention", 0644, dir,
+		debug, &attention_fops);
+
+	if (IS_ERR_OR_NULL(file)) {
+		rc = PTR_ERR(file);
+		pr_err("[%s] debugfs attention failed, rc=%d\n",
+			DEBUG_NAME, rc);
+		goto error_remove_dir;
+	}
+
 	return 0;
 
 error_remove_dir:
@@ -977,9 +1102,17 @@
 	return rc;
 }
 
+static void dp_debug_sim_work(struct work_struct *work)
+{
+	struct dp_debug_private *debug =
+		container_of(work, typeof(*debug), sim_work);
+
+	debug->usbpd->simulate_attention(debug->usbpd, debug->vdo);
+}
+
 struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
 			struct dp_usbpd *usbpd, struct dp_link *link,
-			struct drm_connector **connector)
+			struct dp_aux *aux, struct drm_connector **connector)
 {
 	int rc = 0;
 	struct dp_debug_private *debug;
@@ -997,28 +1130,13 @@
 		goto error;
 	}
 
-	debug->edid = devm_kzalloc(dev, SZ_256, GFP_KERNEL);
-	if (!debug->edid) {
-		rc = -ENOMEM;
-		kfree(debug);
-		goto error;
-	}
-
-	debug->edid_size = SZ_256;
-
-	debug->dpcd = devm_kzalloc(dev, SZ_16, GFP_KERNEL);
-	if (!debug->dpcd) {
-		rc = -ENOMEM;
-		kfree(debug);
-		goto error;
-	}
-
-	debug->dpcd_size = SZ_16;
+	INIT_WORK(&debug->sim_work, dp_debug_sim_work);
 
 	debug->dp_debug.debug_en = false;
 	debug->usbpd = usbpd;
 	debug->link = link;
 	debug->panel = panel;
+	debug->aux = aux;
 	debug->dev = dev;
 	debug->connector = connector;
 
@@ -1063,7 +1181,11 @@
 
 	dp_debug_deinit(dp_debug);
 
-	devm_kfree(debug->dev, debug->edid);
-	devm_kfree(debug->dev, debug->dpcd);
+	if (debug->edid)
+		devm_kfree(debug->dev, debug->edid);
+
+	if (debug->dpcd)
+		devm_kfree(debug->dev, debug->dpcd);
+
 	devm_kfree(debug->dev, debug);
 }
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.h b/drivers/gpu/drm/msm/dp/dp_debug.h
index 3b2d23e..5a5a786 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.h
+++ b/drivers/gpu/drm/msm/dp/dp_debug.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,7 @@
 #include "dp_panel.h"
 #include "dp_link.h"
 #include "dp_usbpd.h"
+#include "dp_aux.h"
 
 /**
  * struct dp_debug
@@ -29,6 +30,7 @@
  */
 struct dp_debug {
 	bool debug_en;
+	bool sim_mode;
 	bool psm_enabled;
 	int aspect_ratio;
 	int vdisplay;
@@ -52,7 +54,7 @@
  */
 struct dp_debug *dp_debug_get(struct device *dev, struct dp_panel *panel,
 			struct dp_usbpd *usbpd, struct dp_link *link,
-			struct drm_connector **connector);
+			struct dp_aux *aux, struct drm_connector **connector);
 /**
  * dp_debug_put()
  *
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index d19058f..053ee20 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -466,6 +466,7 @@
 		bool hpd)
 {
 	u32 timeout_sec;
+	int ret = 0;
 
 	dp->dp_display.is_connected = hpd;
 
@@ -474,16 +475,20 @@
 	else
 		timeout_sec = 10;
 
+	dp->aux->state |= DP_STATE_NOTIFICATION_SENT;
+
 	reinit_completion(&dp->notification_comp);
 	dp_display_send_hpd_event(dp);
 
 	if (!wait_for_completion_timeout(&dp->notification_comp,
 						HZ * timeout_sec)) {
 		pr_warn("%s timeout\n", hpd ? "connect" : "disconnect");
-		return -EINVAL;
+		ret = -EINVAL;
 	}
 
-	return 0;
+	dp->aux->state &= ~DP_STATE_NOTIFICATION_SENT;
+
+	return ret;
 }
 
 static int dp_display_process_hpd_high(struct dp_display_private *dp)
@@ -532,6 +537,7 @@
 static void dp_display_host_init(struct dp_display_private *dp)
 {
 	bool flip = false;
+	bool reset;
 
 	if (dp->core_initialized) {
 		pr_debug("DP core already initialized\n");
@@ -541,8 +547,10 @@
 	if (dp->usbpd->orientation == ORIENTATION_CC2)
 		flip = true;
 
+	reset = dp->debug->sim_mode ? false : !dp->usbpd->multi_func;
+
 	dp->power->init(dp->power, flip);
-	dp->ctrl->init(dp->ctrl, flip, dp->usbpd->multi_func);
+	dp->ctrl->init(dp->ctrl, flip, reset);
 	enable_irq(dp->irq);
 	dp->core_initialized = true;
 }
@@ -558,6 +566,7 @@
 	dp->power->deinit(dp->power);
 	disable_irq(dp->irq);
 	dp->core_initialized = false;
+	dp->aux->state = 0;
 }
 
 static int dp_display_process_hpd_low(struct dp_display_private *dp)
@@ -664,6 +673,13 @@
 		goto end;
 	}
 
+	/*
+	 * In case cable/dongle is disconnected during adb shell stop,
+	 * reset psm_enabled flag to false since it is no more needed
+	 */
+	if (dp->dp_display.post_open)
+		dp->debug->psm_enabled = false;
+
 	if (dp->debug->psm_enabled)
 		dp->link->psm_config(dp->link, &dp->panel->link_info, true);
 
@@ -929,7 +945,7 @@
 	}
 
 	dp->debug = dp_debug_get(dev, dp->panel, dp->usbpd,
-				dp->link, &dp->dp_display.connector);
+				dp->link, dp->aux, &dp->dp_display.connector);
 	if (IS_ERR(dp->debug)) {
 		rc = PTR_ERR(dp->debug);
 		pr_err("failed to initialize debug, rc = %d\n", rc);
@@ -1095,6 +1111,7 @@
 end:
 	/* clear framework event notifier */
 	dp_display->post_open = NULL;
+	dp->aux->state |= DP_STATE_CTRL_POWERED_ON;
 
 	complete_all(&dp->notification_comp);
 	mutex_unlock(&dp->session_lock);
@@ -1127,6 +1144,14 @@
 			dp->hdcp.ops->off(dp->hdcp.data);
 	}
 
+	if (dp->usbpd->hpd_high && dp->usbpd->alt_mode_cfg_done) {
+		if (dp->audio_supported)
+			dp->audio->off(dp->audio);
+
+		dp->link->psm_config(dp->link, &dp->panel->link_info, true);
+		dp->debug->psm_enabled = true;
+	}
+
 	dp->ctrl->push_idle(dp->ctrl);
 end:
 	mutex_unlock(&dp->session_lock);
@@ -1167,8 +1192,17 @@
 
 	memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta));
 
+	/*
+	 * In case of framework reboot, the DP off sequence is executed without
+	 * any notification from driver. Initialize post_open callback to notify
+	 * DP connection once framework restarts.
+	 */
+	if (dp->usbpd->hpd_high && dp->usbpd->alt_mode_cfg_done) {
+		dp_display->post_open = dp_display_post_open;
+		dp->dp_display.is_connected = false;
+	}
 	dp->power_on = false;
-
+	dp->aux->state = DP_STATE_CTRL_POWERED_OFF;
 end:
 	complete_all(&dp->notification_comp);
 	mutex_unlock(&dp->session_lock);
diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c
index 3ca247c..05629dd 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.c
+++ b/drivers/gpu/drm/msm/dp/dp_link.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -724,24 +724,6 @@
 	return ret;
 }
 
-static char *dp_link_get_test_name(u32 test_requested)
-{
-	switch (test_requested) {
-	case DP_TEST_LINK_TRAINING:
-		return DP_LINK_ENUM_STR(DP_TEST_LINK_TRAINING);
-	case DP_TEST_LINK_VIDEO_PATTERN:
-		return DP_LINK_ENUM_STR(DP_TEST_LINK_VIDEO_PATTERN);
-	case DP_TEST_LINK_EDID_READ:
-		return DP_LINK_ENUM_STR(DP_TEST_LINK_EDID_READ);
-	case DP_TEST_LINK_PHY_TEST_PATTERN:
-		return DP_LINK_ENUM_STR(DP_TEST_LINK_PHY_TEST_PATTERN);
-	case DP_TEST_LINK_AUDIO_PATTERN:
-		return DP_LINK_ENUM_STR(DP_TEST_LINK_AUDIO_PATTERN);
-	default:
-		return "unknown";
-	}
-}
-
 /**
  * dp_link_is_video_audio_test_requested() - checks for audio/video link request
  * @link: link requested by the sink
diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h
index 6f79b6a..46d30a7 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.h
+++ b/drivers/gpu/drm/msm/dp/dp_link.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -83,6 +83,24 @@
 	u32 bw_code;
 };
 
+static inline char *dp_link_get_test_name(u32 test_requested)
+{
+	switch (test_requested) {
+	case DP_TEST_LINK_TRAINING:
+		return DP_LINK_ENUM_STR(DP_TEST_LINK_TRAINING);
+	case DP_TEST_LINK_VIDEO_PATTERN:
+		return DP_LINK_ENUM_STR(DP_TEST_LINK_VIDEO_PATTERN);
+	case DP_TEST_LINK_EDID_READ:
+		return DP_LINK_ENUM_STR(DP_TEST_LINK_EDID_READ);
+	case DP_TEST_LINK_PHY_TEST_PATTERN:
+		return DP_LINK_ENUM_STR(DP_TEST_LINK_PHY_TEST_PATTERN);
+	case DP_TEST_LINK_AUDIO_PATTERN:
+		return DP_LINK_ENUM_STR(DP_TEST_LINK_AUDIO_PATTERN);
+	default:
+		return "unknown";
+	}
+}
+
 struct dp_link {
 	u32 sink_request;
 	u32 test_response;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index e0aedc0..7132699 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -136,9 +136,6 @@
 
 			goto end;
 		}
-
-		print_hex_dump(KERN_DEBUG, "[drm-dp] SINK DPCD: ",
-			DUMP_PREFIX_NONE, 8, 1, dp_panel->dpcd, rlen, false);
 	}
 
 	rlen = drm_dp_dpcd_read(panel->aux->drm_aux,
@@ -275,35 +272,31 @@
 static int dp_panel_read_edid(struct dp_panel *dp_panel,
 	struct drm_connector *connector)
 {
+	int ret = 0;
 	struct dp_panel_private *panel;
 
 	if (!dp_panel) {
 		pr_err("invalid input\n");
-		return -EINVAL;
+		ret = -EINVAL;
+		goto end;
 	}
 
 	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
 
 	if (panel->custom_edid) {
 		pr_debug("skip edid read in debug mode\n");
-		return 0;
+		goto end;
 	}
 
 	sde_get_edid(connector, &panel->aux->drm_aux->ddc,
 		(void **)&dp_panel->edid_ctrl);
 	if (!dp_panel->edid_ctrl->edid) {
 		pr_err("EDID read failed\n");
-	} else {
-		u8 *buf = (u8 *)dp_panel->edid_ctrl->edid;
-		u32 size = buf[0x7E] ? 256 : 128;
-
-		print_hex_dump(KERN_DEBUG, "[drm-dp] SINK EDID: ",
-			DUMP_PREFIX_NONE, 16, 1, buf, size, false);
-
-		return 0;
+		ret = -EINVAL;
+		goto end;
 	}
-
-	return -EINVAL;
+end:
+	return ret;
 }
 
 static int dp_panel_read_sink_caps(struct dp_panel *dp_panel,
diff --git a/drivers/gpu/drm/msm/dp/dp_usbpd.c b/drivers/gpu/drm/msm/dp/dp_usbpd.c
index 2bd3bd4..42eb9b0 100644
--- a/drivers/gpu/drm/msm/dp/dp_usbpd.c
+++ b/drivers/gpu/drm/msm/dp/dp_usbpd.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -426,6 +426,28 @@
 	return rc;
 }
 
+static int dp_usbpd_simulate_attention(struct dp_usbpd *dp_usbpd, int vdo)
+{
+	int rc = 0;
+	struct dp_usbpd_private *pd;
+
+	if (!dp_usbpd) {
+		pr_err("invalid input\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	pd = container_of(dp_usbpd, struct dp_usbpd_private, dp_usbpd);
+
+	pd->vdo = vdo;
+	dp_usbpd_get_status(pd);
+
+	if (pd->dp_cb && pd->dp_cb->attention)
+		pd->dp_cb->attention(pd->dev);
+error:
+	return rc;
+}
+
 struct dp_usbpd *dp_usbpd_get(struct device *dev, struct dp_usbpd_cb *cb)
 {
 	int rc = 0;
@@ -475,6 +497,7 @@
 
 	dp_usbpd = &usbpd->dp_usbpd;
 	dp_usbpd->simulate_connect = dp_usbpd_simulate_connect;
+	dp_usbpd->simulate_attention = dp_usbpd_simulate_attention;
 
 	return dp_usbpd;
 error:
diff --git a/drivers/gpu/drm/msm/dp/dp_usbpd.h b/drivers/gpu/drm/msm/dp/dp_usbpd.h
index e70ad7d..0a7efd9 100644
--- a/drivers/gpu/drm/msm/dp/dp_usbpd.h
+++ b/drivers/gpu/drm/msm/dp/dp_usbpd.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -50,6 +50,7 @@
  * @alt_mode_cfg_done: bool to specify alt mode status
  * @debug_en: bool to specify debug mode
  * @simulate_connect: simulate disconnect or connect for debug mode
+ * @simulate_attention: simulate attention messages for debug mode
  */
 struct dp_usbpd {
 	enum dp_usbpd_port port;
@@ -65,6 +66,7 @@
 	bool debug_en;
 
 	int (*simulate_connect)(struct dp_usbpd *dp_usbpd, bool hpd);
+	int (*simulate_attention)(struct dp_usbpd *dp_usbpd, int vdo);
 };
 
 /**
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c
index 42aea7e..3e084d5 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.c
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 as published by
@@ -613,6 +613,7 @@
 	if (!node)
 		return;
 
+	spin_lock_irqsave(&node->state_lock, flags);
 	if (node->state == IRQ_DISABLED) {
 		ret = sde_core_irq_enable(kms, &irq_idx, 1);
 		if (ret)
@@ -620,6 +621,7 @@
 		else
 			node->state = IRQ_ENABLED;
 	}
+	spin_unlock_irqrestore(&node->state_lock, flags);
 }
 
 static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node,
@@ -1623,6 +1625,7 @@
 	struct sde_crtc *crtc;
 	int i;
 	int irq_idx, ret;
+	unsigned long flags;
 	struct sde_cp_node prop_node;
 	struct sde_crtc_irq_info *node = NULL;
 
@@ -1673,6 +1676,7 @@
 
 	if (!en) {
 		if (node) {
+			spin_lock_irqsave(&node->state_lock, flags);
 			if (node->state == IRQ_ENABLED) {
 				ret = sde_core_irq_disable(kms, &irq_idx, 1);
 				if (ret)
@@ -1683,6 +1687,7 @@
 			} else {
 				node->state = IRQ_NOINIT;
 			}
+			spin_unlock_irqrestore(&node->state_lock, flags);
 		} else {
 			DRM_ERROR("failed to get node from crtc event list\n");
 		}
@@ -1701,6 +1706,7 @@
 
 	if (node) {
 		/* device resume or resume from IPC cases */
+		spin_lock_irqsave(&node->state_lock, flags);
 		if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) {
 			ret = sde_core_irq_enable(kms, &irq_idx, 1);
 			if (ret) {
@@ -1712,6 +1718,7 @@
 				node->state = IRQ_ENABLED;
 			}
 		}
+		spin_unlock_irqrestore(&node->state_lock, flags);
 	} else {
 		/* request from userspace to register the event
 		 * in this case, node has not been added into the event list
@@ -1807,14 +1814,17 @@
 		return;
 	}
 
+	spin_lock_irqsave(&node->state_lock, flags);
 	if (node->state == IRQ_ENABLED) {
 		if (sde_core_irq_disable_nolock(kms, irq_idx)) {
 			DRM_ERROR("failed to disable irq %d, ret %d\n",
 				irq_idx, ret);
+			spin_unlock_irqrestore(&node->state_lock, flags);
 			return;
 		}
 		node->state = IRQ_DISABLED;
 	}
+	spin_unlock_irqrestore(&node->state_lock, flags);
 
 	/* lock histogram buffer */
 	for (i = 0; i < crtc->num_mixers; i++) {
@@ -1886,6 +1896,7 @@
 	struct sde_crtc *crtc;
 	struct sde_crtc_irq_info *node = NULL;
 	int i, irq_idx, ret = 0;
+	unsigned long flags;
 
 	if (!crtc_drm || !hist_irq) {
 		DRM_ERROR("invalid crtc %pK irq %pK\n", crtc_drm, hist_irq);
@@ -1928,6 +1939,7 @@
 	if (!en) {
 		if (node) {
 			/* device suspend case or suspend to IPC cases */
+			spin_lock_irqsave(&node->state_lock, flags);
 			if (node->state == IRQ_ENABLED) {
 				ret = sde_core_irq_disable(kms, &irq_idx, 1);
 				if (ret)
@@ -1938,6 +1950,7 @@
 			} else {
 				node->state = IRQ_NOINIT;
 			}
+			spin_unlock_irqrestore(&node->state_lock, flags);
 		} else {
 			DRM_ERROR("failed to get node from crtc event list\n");
 		}
@@ -1957,6 +1970,7 @@
 
 	if (node) {
 		/* device resume or resume from IPC cases */
+		spin_lock_irqsave(&node->state_lock, flags);
 		if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) {
 			ret = sde_core_irq_enable(kms, &irq_idx, 1);
 			if (ret) {
@@ -1968,6 +1982,7 @@
 				node->state = IRQ_ENABLED;
 			}
 		}
+		spin_unlock_irqrestore(&node->state_lock, flags);
 	} else {
 		/* request from userspace to register the event
 		 * in this case, node has not been added into the event list
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index df0aad5e..655390b 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -471,8 +471,11 @@
 	}
 	c_conn->last_panel_power_mode = mode;
 
-	if (mode != SDE_MODE_DPMS_ON)
+	if (mode != SDE_MODE_DPMS_ON) {
+		mutex_unlock(&c_conn->lock);
 		sde_connector_schedule_status_work(connector, false);
+		mutex_lock(&c_conn->lock);
+	}
 
 	return rc;
 }
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 73e2af0..1ee75c4 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -2511,9 +2511,6 @@
 							SDE_EVTLOG_FUNC_CASE3);
 		}
 
-		if (fevent->event & SDE_ENCODER_FRAME_EVENT_DONE)
-			sde_core_perf_crtc_update(crtc, 0, false);
-
 		if (fevent->event & (SDE_ENCODER_FRAME_EVENT_DONE
 					| SDE_ENCODER_FRAME_EVENT_ERROR))
 			frame_done = true;
@@ -2597,6 +2594,8 @@
 	SDE_EVT32_VERBOSE(DRMID(crtc));
 	smmu_state = &sde_crtc->smmu_state;
 
+	sde_core_perf_crtc_update(crtc, 0, false);
+
 	/* complete secure transitions if any */
 	if (smmu_state->transition_type == POST_COMMIT)
 		sde_crtc_secure_ctrl(crtc, true);
@@ -6134,6 +6133,7 @@
 			INIT_LIST_HEAD(&node->list);
 			node->func = custom_events[i].func;
 			node->event = event;
+			spin_lock_init(&node->state_lock);
 			break;
 		}
 	}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 33d2b8fa..78f15ec 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -445,7 +445,8 @@
  * @event: event type of the interrupt
  * @func: function pointer to enable/disable the interrupt
  * @list: list of user customized event in crtc
- * @ref_count: reference count for the interrupt
+ * @state: state of the interrupt
+ * @state_lock: spin lock for interrupt state
  */
 struct sde_crtc_irq_info {
 	struct sde_irq_callback irq;
@@ -454,6 +455,7 @@
 			struct sde_irq_callback *irq);
 	struct list_head list;
 	enum sde_crtc_irq_state state;
+	spinlock_t state_lock;
 };
 
 #define to_sde_crtc_state(x) \
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index 69dc385..a3f09b6 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -405,7 +405,7 @@
 			to_sde_encoder_phys_vid(phys_enc);
 	struct sde_hw_ctl *hw_ctl;
 	unsigned long lock_flags;
-	u32 flush_register = 0;
+	u32 flush_register = ~0;
 	u32 reset_status = 0;
 	int new_cnt = -1, old_cnt = -1;
 	u32 event = 0;
@@ -419,42 +419,45 @@
 
 	SDE_ATRACE_BEGIN("vblank_irq");
 
-	/* signal only for master, where there is a pending kickoff */
-	if (sde_encoder_phys_vid_is_master(phys_enc)
-			&& atomic_add_unless(
-				&phys_enc->pending_retire_fence_cnt, -1, 0)) {
-		event = SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE
-				| SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE;
-
-		if (phys_enc->parent_ops.handle_frame_done)
-			phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
-				phys_enc, event);
-	}
-
-	if (phys_enc->parent_ops.handle_vblank_virt)
-		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
-				phys_enc);
-
-	old_cnt  = atomic_read(&phys_enc->pending_kickoff_cnt);
-
 	/*
 	 * only decrement the pending flush count if we've actually flushed
 	 * hardware. due to sw irq latency, vblank may have already happened
 	 * so we need to double-check with hw that it accepted the flush bits
 	 */
 	spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
+
+	old_cnt = atomic_read(&phys_enc->pending_kickoff_cnt);
+
 	if (hw_ctl && hw_ctl->ops.get_flush_register)
 		flush_register = hw_ctl->ops.get_flush_register(hw_ctl);
 
-	if (flush_register == 0)
-		new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt,
-				-1, 0);
+	if (flush_register)
+		goto not_flushed;
 
+	new_cnt = atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);
+
+	/* signal only for master, where there is a pending kickoff */
+	if (sde_encoder_phys_vid_is_master(phys_enc)) {
+		if (atomic_add_unless(&phys_enc->pending_retire_fence_cnt,
+					-1, 0))
+			event |= SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE |
+				SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
+	}
+
+not_flushed:
 	if (hw_ctl && hw_ctl->ops.get_reset)
 		reset_status = hw_ctl->ops.get_reset(hw_ctl);
 
 	spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
 
+	if (event && phys_enc->parent_ops.handle_frame_done)
+		phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
+			phys_enc, event);
+
+	if (phys_enc->parent_ops.handle_vblank_virt)
+		phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
+				phys_enc);
+
 	SDE_EVT32_IRQ(DRMID(phys_enc->parent), vid_enc->hw_intf->idx - INTF_0,
 			old_cnt, new_cnt, reset_status ? SDE_EVTLOG_ERROR : 0,
 			flush_register, event);
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index ed1079d..a1898ac 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -3257,7 +3257,8 @@
 
 	if (!fb || !old_fb) {
 		SDE_DEBUG_PLANE(psde, "can't compare fb handles\n");
-	} else if (fb->pixel_format != old_fb->pixel_format) {
+	} else if ((fb->pixel_format != old_fb->pixel_format) ||
+			pstate->const_alpha_en != old_pstate->const_alpha_en) {
 		SDE_DEBUG_PLANE(psde, "format change\n");
 		pstate->dirty |= SDE_PLANE_DIRTY_FORMAT | SDE_PLANE_DIRTY_RECTS;
 	} else {
diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c
index f9092e2..93304e16 100644
--- a/drivers/gpu/drm/msm/sde/sde_rm.c
+++ b/drivers/gpu/drm/msm/sde/sde_rm.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1129,17 +1129,29 @@
 	return ret;
 }
 
-/**
- * poll_intr_status - Gets HW interrupt status based on
- *			given lookup IRQ index.
- * @intr:	HW interrupt handle
- * @irq_idx:	Lookup irq index return from irq_idx_lookup
- * @msec:	Maximum delay allowed to check intr status
- * return:	return zero on success.
- */
-static u32 _sde_rm_poll_intr_status_for_cont_splash
-			(struct sde_hw_intr *intr,
-			int irq_idx, u32 const msec)
+static void _sde_rm_clear_irq_status(struct sde_hw_intr *hw_intr,
+	int irq_idx_pp_done, int irq_idx_autorefresh)
+{
+	u32 intr_value = 0;
+
+	if ((irq_idx_pp_done >= 0) && (hw_intr->ops.get_intr_status_nomask)) {
+		intr_value = hw_intr->ops.get_intr_status_nomask(hw_intr,
+			irq_idx_pp_done, false);
+		hw_intr->ops.clear_intr_status_force_mask(hw_intr,
+			irq_idx_pp_done, intr_value);
+	}
+
+	if ((irq_idx_autorefresh >= 0) &&
+			(hw_intr->ops.get_intr_status_nomask)) {
+		intr_value = hw_intr->ops.get_intr_status_nomask(hw_intr,
+			irq_idx_autorefresh, false);
+		hw_intr->ops.clear_intr_status_force_mask(hw_intr,
+			irq_idx_autorefresh, intr_value);
+	}
+}
+
+static u32 _sde_rm_poll_intr_status_for_cont_splash(struct sde_hw_intr *intr,
+	int irq_idx_pp_done, int irq_idx_autorefresh, u32 const msec)
 {
 	int i;
 	u32 status = 0;
@@ -1153,19 +1165,112 @@
 
 	for (i = 0; i < loop; i++) {
 		status = intr->ops.get_intr_status_nomask
-				(intr, irq_idx, false);
+				(intr, irq_idx_pp_done, false);
 
-		if (status & BIT(irq_idx)) {
-			SDE_DEBUG(" Poll success. i=%d, status=0x%x\n",
+		if (status & BIT(irq_idx_pp_done)) {
+			SDE_DEBUG("pp_done received i=%d, status=0x%x\n",
 							i, status);
-			return 0;
+			SDE_EVT32(status, i, irq_idx_pp_done);
+
+			if (status & BIT(irq_idx_autorefresh))
+				_sde_rm_clear_irq_status(intr,
+					irq_idx_pp_done, irq_idx_autorefresh);
+			else
+				return 0;
 		}
 		usleep_range(delay_us, delay_us + 10);
 	}
+
+	SDE_EVT32(status, irq_idx_pp_done, SDE_EVTLOG_ERROR);
 	SDE_ERROR("polling timed out. status = 0x%x\n", status);
 	return -ETIMEDOUT;
 }
 
+static int _sde_rm_autorefresh_disable(struct sde_hw_pingpong *pp,
+		struct sde_hw_intr *hw_intr)
+{
+	u32 const timeout_ms = 35; /* Max two vsyncs delay */
+	int rc = 0, i, loop = 3;
+	struct sde_hw_pp_vsync_info info;
+	int irq_idx_pp_done = -1, irq_idx_autorefresh = -1;
+	struct sde_hw_autorefresh cfg = {0};
+
+	if (!pp->ops.get_autorefresh || !pp->ops.setup_autorefresh ||
+		!pp->ops.connect_external_te || !pp->ops.get_vsync_info) {
+		SDE_ERROR("autorefresh update api not supported\n");
+		return 0;
+	}
+
+	/* read default autorefresh configuration */
+	pp->ops.get_autorefresh(pp, &cfg);
+	if (!cfg.enable) {
+		SDE_DEBUG("autorefresh already disabled\n");
+		SDE_EVT32(pp->idx - PINGPONG_0, SDE_EVTLOG_FUNC_CASE1);
+		return 0;
+	}
+
+	/* disable external TE first */
+	pp->ops.connect_external_te(pp, false);
+
+	/* get all IRQ indexes */
+	if (hw_intr->ops.irq_idx_lookup) {
+		irq_idx_pp_done = hw_intr->ops.irq_idx_lookup(
+				SDE_IRQ_TYPE_PING_PONG_COMP, pp->idx);
+		irq_idx_autorefresh = hw_intr->ops.irq_idx_lookup(
+				SDE_IRQ_TYPE_PING_PONG_AUTO_REF, pp->idx);
+		SDE_DEBUG("pp_done itr_idx = %d autorefresh irq_idx:%d\n",
+				irq_idx_pp_done, irq_idx_autorefresh);
+	}
+
+	/* disable autorefresh */
+	cfg.enable = false;
+	pp->ops.setup_autorefresh(pp, &cfg);
+
+	SDE_EVT32(pp->idx - PINGPONG_0, irq_idx_pp_done, irq_idx_autorefresh);
+	_sde_rm_clear_irq_status(hw_intr, irq_idx_pp_done, irq_idx_autorefresh);
+
+	/*
+	 * Check the line count again if
+	 * the line count is equal to the active
+	 * height to make sure their is no
+	 * additional frame updates
+	 */
+	for (i = 0; i < loop; i++) {
+		info.wr_ptr_line_count = 0;
+		info.rd_ptr_init_val = 0;
+		pp->ops.get_vsync_info(pp, &info);
+
+		SDE_EVT32(pp->idx - PINGPONG_0, info.wr_ptr_line_count,
+			info.rd_ptr_init_val, SDE_EVTLOG_FUNC_CASE1);
+
+		/* wait for read ptr intr */
+		rc = _sde_rm_poll_intr_status_for_cont_splash(hw_intr,
+			irq_idx_pp_done, irq_idx_autorefresh, timeout_ms);
+
+		info.wr_ptr_line_count = 0;
+		info.rd_ptr_init_val = 0;
+		pp->ops.get_vsync_info(pp, &info);
+		SDE_DEBUG("i=%d, line count=%d\n", i, info.wr_ptr_line_count);
+
+		SDE_EVT32(pp->idx - PINGPONG_0, info.wr_ptr_line_count,
+			info.rd_ptr_init_val, SDE_EVTLOG_FUNC_CASE2);
+
+		/* log line count and return */
+		if (!rc)
+			break;
+		/*
+		 * Wait for few milli seconds for line count
+		 * to increase if any frame transfer is
+		 * pending.
+		 */
+		usleep_range(3000, 4000);
+	}
+
+	pp->ops.connect_external_te(pp, true);
+
+	return rc;
+}
+
 /**
  * sde_rm_get_pp_dsc_for_cont_splash - retrieve the current dsc enabled blocks
  *	and disable autorefresh if enabled.
@@ -1181,9 +1286,7 @@
 {
 	int index = 0;
 	int value, dsc_cnt = 0;
-	struct sde_hw_autorefresh cfg;
 	struct sde_rm_hw_iter iter_pp;
-	int irq_idx_pp_done = -1;
 
 	if (!rm || !sde_kms || !dsc_ids) {
 		SDE_ERROR("invalid input parameters\n");
@@ -1195,11 +1298,7 @@
 	while (_sde_rm_get_hw_locked(rm, &iter_pp)) {
 		struct sde_hw_pingpong *pp =
 				to_sde_hw_pingpong(iter_pp.blk->hw);
-		u32 intr_value = 0;
-		u32 const timeout_ms = 35; /* Max two vsyncs delay */
-		int rc = 0, i, loop = 2;
 		struct sde_hw_intr *hw_intr = NULL;
-		struct sde_hw_pp_vsync_info info;
 
 		if (!pp->ops.get_dsc_status) {
 			SDE_ERROR("get_dsc_status ops not initialized\n");
@@ -1219,70 +1318,7 @@
 		}
 		index++;
 
-		if (!pp->ops.get_autorefresh) {
-			SDE_ERROR("get_autorefresh api not supported\n");
-			return 0;
-		}
-		memset(&cfg, 0, sizeof(cfg));
-		if (!pp->ops.get_autorefresh(pp, &cfg)
-				&& (cfg.enable)
-				&& (pp->ops.setup_autorefresh)) {
-			if (hw_intr->ops.irq_idx_lookup) {
-				irq_idx_pp_done = hw_intr->ops.irq_idx_lookup
-					(SDE_IRQ_TYPE_PING_PONG_COMP,
-								pp->idx);
-				SDE_DEBUG(" itr_idx = %d\n", irq_idx_pp_done);
-			}
-
-			if ((irq_idx_pp_done >= 0) &&
-					(hw_intr->ops.get_intr_status_nomask)) {
-				intr_value = hw_intr->ops.get_intr_status_nomask
-					(hw_intr, irq_idx_pp_done, false);
-				hw_intr->ops.clear_intr_status_force_mask
-					(hw_intr, irq_idx_pp_done, intr_value);
-			}
-			cfg.enable = false;
-			SDE_DEBUG("Disabling autorefresh\n");
-			pp->ops.setup_autorefresh(pp, &cfg);
-
-			/*
-			 * Check the line count again if
-			 * the line count is equal to the active
-			 * height to make sure their is no
-			 * additional frame updates
-			 */
-			for (i = 0; i < loop; i++) {
-				info.wr_ptr_line_count = 0;
-				info.rd_ptr_init_val = 0;
-				if (pp->ops.get_vsync_info)
-					pp->ops.get_vsync_info(pp, &info);
-				/*
-				 * For cmd-mode using external-TE logic,
-				 * the rd_ptr_init_val is equal to
-				 * active-height. Use this init_val to
-				 * compare that with lane count. Need
-				 * to implement a different check
-				 * if external-TE is not used.
-				 */
-				if (info.wr_ptr_line_count
-						< info.rd_ptr_init_val) {
-					/* wait for read ptr intr */
-					rc =
-					_sde_rm_poll_intr_status_for_cont_splash
-					(hw_intr, irq_idx_pp_done, timeout_ms);
-					if (!rc)
-						break;
-				}
-				SDE_DEBUG("i=%d, line count=%d\n",
-						i, info.wr_ptr_line_count);
-				/*
-				 * Wait for few milli seconds for line count
-				 * to increase if any frame transfer is
-				 * pending.
-				 */
-				usleep_range(3000, 4000);
-			}
-		}
+		_sde_rm_autorefresh_disable(pp, hw_intr);
 	}
 
 	return dsc_cnt;
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index 52d45bb..10446f7 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -1638,6 +1638,8 @@
 		unsigned int fence_mask)
 {
 	unsigned int status, i;
+	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
+	unsigned int reg_offset = gpudev->reg_offsets->offsets[offset];
 
 	adreno_writereg(adreno_dev, offset, val);
 
@@ -1662,6 +1664,6 @@
 	}
 
 	dev_err(adreno_dev->dev.dev,
-		"GMU fenced register write timed out: reg %x\n", offset);
+		"GMU fenced register write timed out: reg 0x%x\n", reg_offset);
 	return -ETIMEDOUT;
 }
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 4b11bbe..60c56a06 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -165,14 +165,19 @@
 }
 
 void kgsl_iommu_unmap_global_secure_pt_entry(struct kgsl_device *device,
-				struct kgsl_memdesc *entry)
+				struct kgsl_memdesc *memdesc)
 {
-	if (!kgsl_mmu_is_secured(&device->mmu))
+	if (!kgsl_mmu_is_secured(&device->mmu) || memdesc == NULL)
 		return;
 
-	if (entry != NULL && entry->pagetable->name == KGSL_MMU_SECURE_PT)
-		kgsl_mmu_unmap(entry->pagetable, entry);
+	/* Check if an empty memdesc got passed in */
+	if ((memdesc->gpuaddr == 0) || (memdesc->size == 0))
+		return;
 
+	if (memdesc->pagetable) {
+		if (memdesc->pagetable->name == KGSL_MMU_SECURE_PT)
+			kgsl_mmu_unmap(memdesc->pagetable, memdesc);
+	}
 }
 
 int kgsl_iommu_map_global_secure_pt_entry(struct kgsl_device *device,
diff --git a/drivers/hwtracing/coresight/coresight-byte-cntr.c b/drivers/hwtracing/coresight/coresight-byte-cntr.c
index 7ef2710..1393399 100644
--- a/drivers/hwtracing/coresight/coresight-byte-cntr.c
+++ b/drivers/hwtracing/coresight/coresight-byte-cntr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -23,17 +23,23 @@
 static struct tmc_drvdata *tmcdrvdata;
 
 static void tmc_etr_read_bytes(struct byte_cntr *byte_cntr_data, loff_t *ppos,
-			       size_t bytes, size_t *len)
+			       size_t bytes, size_t *len, char **bufp)
 {
-	if (*len >= bytes) {
-		atomic_dec(&byte_cntr_data->irq_cnt);
+
+	if (*bufp >= (char *)(tmcdrvdata->vaddr + tmcdrvdata->size))
+		*bufp = tmcdrvdata->vaddr;
+
+	if (*len >= bytes)
 		*len = bytes;
-	} else {
-		if (((uint32_t)*ppos % bytes) + *len > bytes)
-			*len = bytes - ((uint32_t)*ppos % bytes);
-		if ((*len + (uint32_t)*ppos) % bytes == 0)
-			atomic_dec(&byte_cntr_data->irq_cnt);
-	}
+	else if (((uint32_t)*ppos % bytes) + *len > bytes)
+		*len = bytes - ((uint32_t)*ppos % bytes);
+
+	if ((*bufp + *len) > (char *)(tmcdrvdata->vaddr +
+		tmcdrvdata->size))
+		*len = (char *)(tmcdrvdata->vaddr + tmcdrvdata->size) -
+			*bufp;
+	if (*len == bytes || (*len + (uint32_t)*ppos) % bytes == 0)
+		atomic_dec(&byte_cntr_data->irq_cnt);
 }
 
 static void tmc_etr_sg_read_pos(loff_t *ppos,
@@ -96,7 +102,7 @@
 		if (*len >= (bytes - ((uint32_t)*ppos % bytes)))
 			*len = bytes - ((uint32_t)*ppos % bytes);
 
-		if ((*len + (uint32_t)*ppos) % bytes == 0)
+		if (*len == bytes || (*len + (uint32_t)*ppos) % bytes == 0)
 			atomic_dec(&tmcdrvdata->byte_cntr->irq_cnt);
 	}
 
@@ -153,11 +159,12 @@
 			if (!byte_cntr_data->read_active)
 				goto err0;
 		}
-		bufp = (char *)(tmcdrvdata->vaddr + *ppos);
+		bufp = (char *)(tmcdrvdata->buf + *ppos);
 
 		if (tmcdrvdata->mem_type == TMC_ETR_MEM_TYPE_CONTIG)
 			tmc_etr_read_bytes(byte_cntr_data, ppos,
-					   byte_cntr_data->block_size, &len);
+					   byte_cntr_data->block_size, &len,
+					   &bufp);
 		else
 			tmc_etr_sg_read_pos(ppos, byte_cntr_data->block_size, 0,
 					    &len, &bufp);
@@ -179,7 +186,7 @@
 			if (tmcdrvdata->mem_type == TMC_ETR_MEM_TYPE_CONTIG)
 				tmc_etr_read_bytes(byte_cntr_data, ppos,
 						   byte_cntr_data->block_size,
-						   &len);
+						   &len, &bufp);
 			else
 				tmc_etr_sg_read_pos(ppos,
 						    byte_cntr_data->block_size,
diff --git a/drivers/input/touchscreen/synaptics_dsx/Kconfig b/drivers/input/touchscreen/synaptics_dsx/Kconfig
index b2fa115..b54e792 100644
--- a/drivers/input/touchscreen/synaptics_dsx/Kconfig
+++ b/drivers/input/touchscreen/synaptics_dsx/Kconfig
@@ -59,6 +59,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called synaptics_dsx_fw_update.
 
+config TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
+	bool "Synaptics DSX firmware update sysfs attributes"
+	depends on TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE
+	help
+	  Say Y here to enable support for sysfs attributes for
+	  performing firmware update in a development environment.
+	  This does not affect the core or other subsystem attributes.
+
+	  If unsure, say N.
+
 config TOUCHSCREEN_SYNAPTICS_DSX_TEST_REPORTING
 	tristate "Synaptics DSX test reporting module"
 	depends on TOUCHSCREEN_SYNAPTICS_DSX_CORE
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
index 7f62e01..395def9 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_fw_update.c
@@ -137,6 +137,7 @@
 
 static int fwu_recovery_check_status(void);
 
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
 static ssize_t fwu_sysfs_show_image(struct file *data_file,
 		struct kobject *kobj, struct bin_attribute *attributes,
 		char *buf, loff_t pos, size_t count);
@@ -201,6 +202,8 @@
 		struct device_attribute *attr, char *buf);
 #endif
 
+#endif
+
 enum f34_version {
 	F34_V0 = 0,
 	F34_V1,
@@ -757,6 +760,7 @@
 	struct work_struct fwu_work;
 };
 
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
 static struct bin_attribute dev_attr_data = {
 	.attr = {
 		.name = "data",
@@ -766,8 +770,10 @@
 	.read = fwu_sysfs_show_image,
 	.write = fwu_sysfs_store_image,
 };
+#endif
 
 static struct device_attribute attrs[] = {
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
 	__ATTR(dorecovery, 0220,
 			synaptics_rmi4_show_error,
 			fwu_sysfs_do_recovery_store),
@@ -821,13 +827,16 @@
 			fwu_sysfs_read_lockdown_code_show,
 			fwu_sysfs_write_lockdown_code_store),
 #endif
+#endif
 };
 
 static struct synaptics_rmi4_fwu_handle *fwu;
 
 DECLARE_COMPLETION(fwu_remove_complete);
 
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
 DEFINE_MUTEX(fwu_sysfs_mutex);
+#endif
 
 static void calculate_checksum(unsigned short *data, unsigned long len,
 		unsigned long *result)
@@ -3061,6 +3070,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
 static int fwu_check_pm_configuration_size(void)
 {
 	unsigned short block_count;
@@ -3077,6 +3087,7 @@
 
 	return 0;
 }
+#endif
 
 static int fwu_check_bl_configuration_size(void)
 {
@@ -3444,6 +3455,7 @@
 	return fwu_write_configuration();
 }
 
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
 static int fwu_write_pm_configuration(void)
 {
 	fwu->config_area = PM_CONFIG_AREA;
@@ -3469,6 +3481,7 @@
 	return 0;
 }
 #endif
+#endif
 
 static int fwu_write_flash_configuration(void)
 {
@@ -3757,6 +3770,7 @@
 	return retval;
 }
 
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
 static int fwu_do_read_config(void)
 {
 	int retval;
@@ -3984,6 +3998,7 @@
 	return retval;
 }
 #endif
+#endif
 
 static int fwu_do_lockdown_v7(void)
 {
@@ -4134,6 +4149,7 @@
 }
 #endif
 
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
 static int fwu_start_write_guest_code(void)
 {
 	int retval;
@@ -4339,6 +4355,7 @@
 
 	return retval;
 }
+#endif
 
 static int fwu_start_reflash(void)
 {
@@ -4970,6 +4987,7 @@
 }
 #endif
 
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
 static ssize_t fwu_sysfs_show_image(struct file *data_file,
 		struct kobject *kobj, struct bin_attribute *attributes,
 		char *buf, loff_t pos, size_t count)
@@ -5566,6 +5584,7 @@
 	return count;
 }
 #endif
+#endif
 static void synaptics_rmi4_fwu_attn(struct synaptics_rmi4_data *rmi4_data,
 		unsigned char intr_mask)
 {
@@ -5668,6 +5687,7 @@
 	if (ENABLE_SYS_REFLASH == false)
 		return 0;
 
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
 	retval = sysfs_create_bin_file(&rmi4_data->input_dev->dev.kobj,
 			&dev_attr_data);
 	if (retval < 0) {
@@ -5676,6 +5696,7 @@
 				__func__);
 		goto exit_free_mem;
 	}
+#endif
 
 	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
 		retval = sysfs_create_file(&rmi4_data->input_dev->dev.kobj,
@@ -5697,7 +5718,9 @@
 				&attrs[attr_count].attr);
 	}
 
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
 	sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
+#endif
 
 exit_free_mem:
 	kfree(fwu->image_name);
@@ -5739,7 +5762,9 @@
 				&attrs[attr_count].attr);
 	}
 
+#ifdef CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_EXTRA_SYSFS
 	sysfs_remove_bin_file(&rmi4_data->input_dev->dev.kobj, &dev_attr_data);
+#endif
 
 exit:
 	complete(&fwu_remove_complete);
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
index 8776d4a..7725cd3 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.c
@@ -402,11 +402,11 @@
 	struct i2c_client *i2c = to_i2c_client(rmi4_data->pdev->dev.parent);
 	struct i2c_msg msg[2];
 
+	mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+
 	retval = synaptics_rmi4_i2c_alloc_buf(rmi4_data, length + 1);
 	if (retval < 0)
-		return retval;
-
-	mutex_lock(&rmi4_data->rmi4_io_ctrl_mutex);
+		goto exit;
 
 	retval = synaptics_rmi4_i2c_set_page(rmi4_data, addr);
 	if (retval != PAGE_SELECT_LEN) {
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c
index 61cf979..331274e 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_rmi_dev.c
@@ -567,16 +567,22 @@
 		return -EBADF;
 	}
 
-	if (count == 0)
-		return 0;
+	mutex_lock(&(dev_data->file_mutex));
+
+	if (*f_pos > REG_ADDR_LIMIT) {
+		retval = -EFAULT;
+		goto clean_up;
+	}
 
 	if (count > (REG_ADDR_LIMIT - *f_pos))
 		count = REG_ADDR_LIMIT - *f_pos;
 
+	if (count == 0) {
+		retval = 0;
+		goto clean_up;
+	}
 	address = (unsigned short)(*f_pos);
 
-	mutex_lock(&(dev_data->file_mutex));
-
 	rmidev_allocate_buffer(count);
 
 	retval = synaptics_rmi4_reg_read(rmidev->rmi4_data,
@@ -638,18 +644,26 @@
 		return -EBADF;
 	}
 
-	if (count == 0)
-		return 0;
+	mutex_lock(&(dev_data->file_mutex));
+
+	if (*f_pos > REG_ADDR_LIMIT) {
+		retval = -EFAULT;
+		goto unlock;
+	}
 
 	if (count > (REG_ADDR_LIMIT - *f_pos))
 		count = REG_ADDR_LIMIT - *f_pos;
 
-	mutex_lock(&(dev_data->file_mutex));
-
+	if (count == 0) {
+		retval = 0;
+		goto unlock;
+	}
 	rmidev_allocate_buffer(count);
 
-	if (copy_from_user(rmidev->tmpbuf, buf, count))
+	if (copy_from_user(rmidev->tmpbuf, buf, count)) {
 		return -EFAULT;
+		goto unlock;
+	}
 
 	retval = synaptics_rmi4_reg_write(rmidev->rmi4_data,
 			*f_pos,
@@ -658,6 +672,7 @@
 	if (retval >= 0)
 		*f_pos += retval;
 
+unlock:
 	mutex_unlock(&(dev_data->file_mutex));
 
 	return retval;
diff --git a/drivers/irqchip/qcom/Kconfig b/drivers/irqchip/qcom/Kconfig
index b892109..0038047 100644
--- a/drivers/irqchip/qcom/Kconfig
+++ b/drivers/irqchip/qcom/Kconfig
@@ -20,3 +20,10 @@
         default y if ARCH_SDM670
         help
           QTI Power Domain Controller for SDM670
+
+config QTI_PDC_SDXPOORWILLS
+        bool "QTI PDC SDxPOORWILLS"
+        select QTI_PDC
+        default y if ARCH_SDXPOORWILLS
+        help
+          QTI Power Domain Controller for SDxPoorwills
diff --git a/drivers/irqchip/qcom/Makefile b/drivers/irqchip/qcom/Makefile
index 5e99040..c4ff9ef 100644
--- a/drivers/irqchip/qcom/Makefile
+++ b/drivers/irqchip/qcom/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_QTI_PDC)			+= pdc.o
 obj-$(CONFIG_QTI_PDC_SDM845)		+= pdc-sdm845.o
 obj-$(CONFIG_QTI_PDC_SDM670)		+= pdc-sdm670.o
+obj-$(CONFIG_QTI_PDC_SDXPOORWILLS)	+= pdc-sdxpoorwills.o
diff --git a/drivers/irqchip/qcom/pdc-sdxpoorwills.c b/drivers/irqchip/qcom/pdc-sdxpoorwills.c
new file mode 100644
index 0000000..5bbca03
--- /dev/null
+++ b/drivers/irqchip/qcom/pdc-sdxpoorwills.c
@@ -0,0 +1,76 @@
+/* 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/irqchip.h>
+#include "pdc.h"
+
+static struct pdc_pin sdxpoorwills_data[] = {
+	{0, 179}, /* rpmh_wake */
+	{1, 180}, /* ee0_apps_hlos_spmi_periph_irq */
+	{2, 181}, /* ee1_apps_trustzone_spmi_periph_irq */
+	{3, 182}, /* secure_wdog_expired */
+	{4, 183}, /* secure_wdog_bark_irq */
+	{5, 184}, /* aop_wdog_expired_irq */
+	{8, 187}, /* aoss_pmic_arb_mpu_xpu_summary_irq */
+	{9, 188}, /* rpmh_wake */
+	{12, 191}, /* pdc_apps_epcb_timeout_summary_irq	*/
+	{13, 192}, /* spmi_protocol_irq	*/
+	{14, 193}, /* tsense0_tsense_max_min_int */
+	{15, 194}, /* apps_pdc_irq_in_15 */
+	{16, 195}, /* tsense0_upper_lower_intr */
+	{17, 196}, /* apps_pdc_irq_in_17 */
+	{18, 197}, /* tsense0_critical_intr	*/
+	{19, 198}, /* apps_pdc_irq_in_19 */
+	{20, 199}, /* apps_pdc.gp_irq_mux[0] */
+	{21, 200}, /* apps_pdc.gp_irq_mux[1] */
+	{22, 201}, /* apps_pdc.gp_irq_mux[2] */
+	{23, 202}, /* apps_pdc.gp_irq_mux[3] */
+	{24, 203}, /* apps_pdc.gp_irq_mux[4] */
+	{25, 204}, /* apps_pdc.gp_irq_mux[5] */
+	{26, 205}, /* apps_pdc.gp_irq_mux[6] */
+	{27, 206}, /* apps_pdc.gp_irq_mux[7] */
+	{28, 207}, /* apps_pdc.gp_irq_mux[8] */
+	{29, 208}, /* apps_pdc.gp_irq_mux[9] */
+	{30, 209}, /* apps_pdc.gp_irq_mux[10] */
+	{31, 210}, /* apps_pdc.gp_irq_mux[11] */
+	{32, 211}, /* apps_pdc.gp_irq_mux[12] */
+	{33, 212}, /* apps_pdc.gp_irq_mux[13] */
+	{34, 213}, /* apps_pdc.gp_irq_mux[14] */
+	{35, 214}, /* apps_pdc.gp_irq_mux[15] */
+	{36, 215}, /* apps_pdc.gp_irq_mux[16] */
+	{37, 216}, /* apps_pdc.gp_irq_mux[17] */
+	{38, 217}, /* apps_pdc.gp_irq_mux[18] */
+	{39, 218}, /* apps_pdc.gp_irq_mux[19] */
+	{40, 219}, /* apps_pdc.gp_irq_mux[20] */
+	{41, 220}, /* apps_pdc.gp_irq_mux[21] */
+	{42, 221}, /* apps_pdc.gp_irq_mux[22] */
+	{43, 222}, /* apps_pdc.gp_irq_mux[23] */
+	{44, 223}, /* apps_pdc.gp_irq_mux[24] */
+	{45, 224}, /* apps_pdc.gp_irq_mux[25] */
+	{46, 225}, /* apps_pdc.gp_irq_mux[26] */
+	{47, 226}, /* apps_pdc.gp_irq_mux[27] */
+	{48, 227}, /* apps_pdc.gp_irq_mux[28] */
+	{49, 228}, /* apps_pdc.gp_irq_mux[29] */
+	{50, 229}, /* apps_pdc.gp_irq_mux[30] */
+	{51, 230}, /* apps_pdc.gp_irq_mux[31] */
+	{-1}
+};
+
+static int __init qcom_pdc_gic_init(struct device_node *node,
+		struct device_node *parent)
+{
+	pr_info("PDC sdxpoowills initialized\n");
+	return qcom_pdc_init(node, parent, sdxpoorwills_data);
+}
+
+IRQCHIP_DECLARE(pdc_sdxpoorwills, "qcom,pdc-sdxpoorwills", qcom_pdc_gic_init);
diff --git a/drivers/irqchip/qcom/pdc.c b/drivers/irqchip/qcom/pdc.c
index 923552f..f7284bd 100644
--- a/drivers/irqchip/qcom/pdc.c
+++ b/drivers/irqchip/qcom/pdc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/irqchip.h>
+#include <linux/interrupt.h>
 #include <linux/irqdomain.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -95,6 +96,20 @@
 	return 0;
 }
 
+static int qcom_pdc_gic_get_irqchip_state(struct irq_data *d,
+		enum irqchip_irq_state which, bool *state)
+{
+	return d->parent_data->chip->irq_get_irqchip_state(d,
+		which, state);
+}
+
+static int qcom_pdc_gic_set_irqchip_state(struct irq_data *d,
+		enum irqchip_irq_state which, bool value)
+{
+	return d->parent_data->chip->irq_set_irqchip_state(d,
+		which, value);
+}
+
 static void qcom_pdc_gic_mask(struct irq_data *d)
 {
 	pdc_enable_intr(d, false);
@@ -220,6 +235,8 @@
 #ifdef CONFIG_SMP
 	.irq_set_affinity	= irq_chip_set_affinity_parent,
 #endif
+	.irq_get_irqchip_state	= qcom_pdc_gic_get_irqchip_state,
+	.irq_set_irqchip_state	= qcom_pdc_gic_set_irqchip_state,
 };
 
 static int qcom_pdc_translate(struct irq_domain *d,
diff --git a/drivers/leds/leds-qpnp-haptics.c b/drivers/leds/leds-qpnp-haptics.c
index ebdff87..fad36ea 100644
--- a/drivers/leds/leds-qpnp-haptics.c
+++ b/drivers/leds/leds-qpnp-haptics.c
@@ -1,5 +1,4 @@
-/* Copyright (c) 2014-2015, 2017-2018, The Linux Foundation.
- * All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -275,6 +274,7 @@
  *  @ last_rate_cfg - Last rate config updated
  *  @ wave_rep_cnt - waveform repeat count
  *  @ wave_s_rep_cnt - waveform sample repeat count
+ *  @ wf_samp_len - waveform sample length
  *  @ ext_pwm_freq_khz - external pwm frequency in KHz
  *  @ ext_pwm_dtest_line - DTEST line for external pwm
  *  @ status_flags - status
@@ -330,6 +330,7 @@
 	u16				last_rate_cfg;
 	u32				wave_rep_cnt;
 	u32				wave_s_rep_cnt;
+	u32				wf_samp_len;
 	u32				ext_pwm_freq_khz;
 	u8				ext_pwm_dtest_line;
 	u32				status_flags;
@@ -445,6 +446,19 @@
 	return rc;
 }
 
+static inline int get_buffer_mode_duration(struct hap_chip *chip)
+{
+	int sample_count, sample_duration;
+
+	sample_count = chip->wave_rep_cnt * chip->wave_s_rep_cnt *
+			chip->wf_samp_len;
+	sample_duration = sample_count * chip->wave_play_rate_us;
+	pr_debug("sample_count: %d sample_duration: %d\n", sample_count,
+		sample_duration);
+
+	return (sample_duration / 1000);
+}
+
 static bool is_sw_lra_auto_resonance_control(struct hap_chip *chip)
 {
 	if (chip->act_type != HAP_LRA)
@@ -735,11 +749,12 @@
 			goto out;
 		}
 
-		if (chip->play_mode != HAP_BUFFER)
-			hrtimer_start(&chip->stop_timer,
-				ktime_set(time_ms / MSEC_PER_SEC,
-				(time_ms % MSEC_PER_SEC) * NSEC_PER_MSEC),
-				HRTIMER_MODE_REL);
+		if (chip->play_mode == HAP_BUFFER)
+			time_ms = get_buffer_mode_duration(chip);
+		hrtimer_start(&chip->stop_timer,
+			ktime_set(time_ms / MSEC_PER_SEC,
+			(time_ms % MSEC_PER_SEC) * NSEC_PER_MSEC),
+			HRTIMER_MODE_REL);
 
 		rc = qpnp_haptics_auto_res_enable(chip, true);
 		if (rc < 0) {
@@ -766,6 +781,9 @@
 
 		if (chip->play_mode == HAP_PWM)
 			pwm_disable(chip->pwm_data.pwm_dev);
+
+		if (chip->play_mode == HAP_BUFFER)
+			chip->wave_samp_idx = 0;
 	}
 
 out:
@@ -1182,8 +1200,11 @@
 	if (time_ms <= 20) {
 		wave_samp[0] = HAP_WF_SAMP_MAX;
 		wave_samp[1] = HAP_WF_SAMP_MAX;
-		if (time_ms > 15)
+		chip->wf_samp_len = 2;
+		if (time_ms > 15) {
 			wave_samp[2] = HAP_WF_SAMP_MAX;
+			chip->wf_samp_len = 3;
+		}
 
 		/* short pattern */
 		rc = qpnp_haptics_parse_buffer_dt(chip);
@@ -1302,33 +1323,20 @@
 		chip->wave_samp_idx += HAP_WAVE_SAMP_LEN;
 		if (chip->wave_samp_idx >= ARRAY_SIZE(chip->wave_samp)) {
 			pr_debug("Samples over\n");
-			/* fall through to stop playing */
 		} else {
 			pr_debug("moving to next sample set %d\n",
 				chip->wave_samp_idx);
 
+			/* Moving to next set of wave sample */
 			rc = qpnp_haptics_buffer_config(chip, NULL, false);
 			if (rc < 0) {
 				pr_err("Error in configuring buffer, rc=%d\n",
 					rc);
 				goto irq_handled;
 			}
-
-			/*
-			 * Moving to next set of wave sample. No need to stop
-			 * or change the play control. Just return.
-			 */
-			goto irq_handled;
 		}
 	}
 
-	rc = qpnp_haptics_play_control(chip, HAP_STOP);
-	if (rc < 0) {
-		pr_err("Error in disabling play, rc=%d\n", rc);
-		goto irq_handled;
-	}
-	chip->wave_samp_idx = 0;
-
 irq_handled:
 	return IRQ_HANDLED;
 }
@@ -1638,6 +1646,7 @@
 		pos += bytes_read;
 	}
 
+	chip->wf_samp_len = i;
 	for (i = 0; i < ARRAY_SIZE(chip->wave_samp); i++)
 		chip->wave_samp[i] = samp[i];
 
@@ -1986,7 +1995,10 @@
 		/* Use default values */
 		for (i = 0; i < HAP_WAVE_SAMP_LEN; i++)
 			chip->wave_samp[i] = HAP_WF_SAMP_MAX;
+
+		wf_samp_len = HAP_WAVE_SAMP_LEN;
 	}
+	chip->wf_samp_len = wf_samp_len;
 
 	return 0;
 }
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.c b/drivers/media/platform/msm/camera/cam_core/cam_context.c
index 7e6d999..d1222aa 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -196,6 +196,30 @@
 	return rc;
 }
 
+int cam_context_handle_crm_process_evt(struct cam_context *ctx,
+	struct cam_req_mgr_link_evt_data *process_evt)
+{
+	int rc = 0;
+
+	if (!ctx->state_machine) {
+		CAM_ERR(CAM_CORE, "Context is not ready");
+		return -EINVAL;
+	}
+
+	mutex_lock(&ctx->ctx_mutex);
+	if (ctx->state_machine[ctx->state].crm_ops.process_evt) {
+		rc = ctx->state_machine[ctx->state].crm_ops.process_evt(ctx,
+			process_evt);
+	} else {
+		/* handling of this message is optional */
+		CAM_DBG(CAM_CORE, "No crm process evt in dev %d, state %d",
+			ctx->dev_hdl, ctx->state);
+	}
+	mutex_unlock(&ctx->ctx_mutex);
+
+	return rc;
+}
+
 int cam_context_handle_acquire_dev(struct cam_context *ctx,
 	struct cam_acquire_dev_cmd *cmd)
 {
@@ -257,10 +281,10 @@
 int cam_context_handle_flush_dev(struct cam_context *ctx,
 	struct cam_flush_dev_cmd *cmd)
 {
-	int rc;
+	int rc = 0;
 
 	if (!ctx->state_machine) {
-		CAM_ERR(CAM_CORE, "context is not ready");
+		CAM_ERR(CAM_CORE, "Context is not ready");
 		return -EINVAL;
 	}
 
@@ -274,9 +298,8 @@
 		rc = ctx->state_machine[ctx->state].ioctl_ops.flush_dev(
 			ctx, cmd);
 	} else {
-		CAM_ERR(CAM_CORE, "No flush device in dev %d, state %d",
+		CAM_WARN(CAM_CORE, "No flush device in dev %d, state %d",
 			ctx->dev_hdl, ctx->state);
-		rc = -EPROTO;
 	}
 	mutex_unlock(&ctx->ctx_mutex);
 
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.h b/drivers/media/platform/msm/camera/cam_core/cam_context.h
index c823b7a..af92b7e 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.h
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -110,6 +110,7 @@
  * @unlink:                Unlink the context
  * @apply_req:             Apply setting for the context
  * @flush_req:             Flush request to remove request ids
+ * @process_evt:           Handle event notification from CRM.(optional)
  *
  */
 struct cam_ctx_crm_ops {
@@ -123,6 +124,8 @@
 			struct cam_req_mgr_apply_request *apply);
 	int (*flush_req)(struct cam_context *ctx,
 			struct cam_req_mgr_flush_request *flush);
+	int (*process_evt)(struct cam_context *ctx,
+			struct cam_req_mgr_link_evt_data *evt_data);
 };
 
 
@@ -273,6 +276,18 @@
 		struct cam_req_mgr_flush_request *apply);
 
 /**
+ * cam_context_handle_crm_process_evt()
+ *
+ * @brief:        Handle process event command
+ *
+ * @ctx:          Object pointer for cam_context
+ * @process_evt:  process event command payload
+ *
+ */
+int cam_context_handle_crm_process_evt(struct cam_context *ctx,
+	struct cam_req_mgr_link_evt_data *process_evt);
+
+/**
  * cam_context_handle_acquire_dev()
  *
  * @brief:        Handle acquire device command
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
index aab1a1a..8ea920d 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -430,6 +430,8 @@
 	uint32_t i;
 	int rc = 0;
 
+	CAM_DBG(CAM_CTXT, "E: NRT flush ctx");
+
 	/*
 	 * flush pending requests, take the sync lock to synchronize with the
 	 * sync callback thread so that the sync cb thread does not try to
@@ -444,23 +446,33 @@
 	while (!list_empty(&temp_list)) {
 		req = list_first_entry(&temp_list,
 				struct cam_ctx_request, list);
+
 		list_del_init(&req->list);
 		req->flushed = 1;
+
 		flush_args.flush_req_pending[flush_args.num_req_pending++] =
 			req->req_priv;
 		for (i = 0; i < req->num_out_map_entries; i++)
-			if (req->out_map_entries[i].sync_id != -1)
-				cam_sync_signal(req->out_map_entries[i].sync_id,
+			if (req->out_map_entries[i].sync_id != -1) {
+				rc = cam_sync_signal(
+					req->out_map_entries[i].sync_id,
 					CAM_SYNC_STATE_SIGNALED_ERROR);
+				if (rc == -EALREADY) {
+					CAM_ERR(CAM_CTXT,
+						"Req: %llu already signalled, sync_id:%d",
+						req->request_id,
+						req->out_map_entries[i].
+						sync_id);
+					break;
+				}
+			}
 	}
 	mutex_unlock(&ctx->sync_mutex);
 
 	if (ctx->hw_mgr_intf->hw_flush) {
 		flush_args.num_req_active = 0;
 		spin_lock(&ctx->lock);
-		INIT_LIST_HEAD(&temp_list);
-		list_splice_init(&ctx->active_req_list, &temp_list);
-		list_for_each_entry(req, &temp_list, list) {
+		list_for_each_entry(req, &ctx->active_req_list, list) {
 			flush_args.flush_req_active[flush_args.num_req_active++]
 				= req->req_priv;
 		}
@@ -474,24 +486,42 @@
 		}
 	}
 
+	INIT_LIST_HEAD(&temp_list);
+	spin_lock(&ctx->lock);
+	list_splice_init(&ctx->active_req_list, &temp_list);
+	INIT_LIST_HEAD(&ctx->active_req_list);
+	spin_unlock(&ctx->lock);
+
 	while (!list_empty(&temp_list)) {
 		req = list_first_entry(&temp_list,
 			struct cam_ctx_request, list);
 		list_del_init(&req->list);
-		for (i = 0; i < req->num_out_map_entries; i++)
+		for (i = 0; i < req->num_out_map_entries; i++) {
 			if (req->out_map_entries[i].sync_id != -1) {
-				cam_sync_signal(req->out_map_entries[i].sync_id,
+				rc = cam_sync_signal(
+					req->out_map_entries[i].sync_id,
 					CAM_SYNC_STATE_SIGNALED_ERROR);
+				if (rc == -EALREADY) {
+					CAM_ERR(CAM_CTXT,
+						"Req: %llu already signalled ctx: %pK dev_name: %s dev_handle: %d ctx_state: %d",
+						req->request_id, req->ctx,
+						req->ctx->dev_name,
+						req->ctx->dev_hdl,
+						req->ctx->state);
+					break;
+				}
 			}
+		}
 
 		spin_lock(&ctx->lock);
 		list_add_tail(&req->list, &ctx->free_req_list);
 		spin_unlock(&ctx->lock);
 		req->ctx = NULL;
 	}
-	INIT_LIST_HEAD(&ctx->active_req_list);
 
-	return rc;
+	CAM_DBG(CAM_CTXT, "X: NRT flush ctx");
+
+	return 0;
 }
 
 int32_t cam_context_flush_req_to_hw(struct cam_context *ctx,
@@ -502,6 +532,8 @@
 	uint32_t i;
 	int rc = 0;
 
+	CAM_DBG(CAM_CTXT, "E: NRT flush req");
+
 	flush_args.num_req_pending = 0;
 	flush_args.num_req_active = 0;
 	mutex_lock(&ctx->sync_mutex);
@@ -510,7 +542,9 @@
 		if (req->request_id != cmd->req_id)
 			continue;
 
+		list_del_init(&req->list);
 		req->flushed = 1;
+
 		flush_args.flush_req_pending[flush_args.num_req_pending++] =
 			req->req_priv;
 		break;
@@ -525,6 +559,8 @@
 				if (req->request_id != cmd->req_id)
 					continue;
 
+				list_del_init(&req->list);
+
 				flush_args.flush_req_active[
 					flush_args.num_req_active++] =
 					req->req_priv;
@@ -543,20 +579,31 @@
 
 	if (req) {
 		if (flush_args.num_req_pending || flush_args.num_req_active) {
-			list_del_init(&req->list);
 			for (i = 0; i < req->num_out_map_entries; i++)
-				if (req->out_map_entries[i].sync_id != -1)
-					cam_sync_signal(
+				if (req->out_map_entries[i].sync_id != -1) {
+					rc = cam_sync_signal(
 						req->out_map_entries[i].sync_id,
 						CAM_SYNC_STATE_SIGNALED_ERROR);
-			spin_lock(&ctx->lock);
-			list_add_tail(&req->list, &ctx->free_req_list);
-			spin_unlock(&ctx->lock);
-			req->ctx = NULL;
+					if (rc == -EALREADY) {
+						CAM_ERR(CAM_CTXT,
+							"Req: %llu already signalled, sync_id:%d",
+							req->request_id,
+							req->out_map_entries[i].
+							sync_id);
+						break;
+					}
+				}
+			if (flush_args.num_req_active) {
+				spin_lock(&ctx->lock);
+				list_add_tail(&req->list, &ctx->free_req_list);
+				spin_unlock(&ctx->lock);
+				req->ctx = NULL;
+			}
 		}
 	}
+	CAM_DBG(CAM_CTXT, "X: NRT flush req");
 
-	return rc;
+	return 0;
 }
 
 int32_t cam_context_flush_dev_to_hw(struct cam_context *ctx,
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_node.c b/drivers/media/platform/msm/camera/cam_core/cam_node.c
index a5977b3..4e9034e 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_node.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -220,7 +220,7 @@
 
 	rc = cam_context_handle_flush_dev(ctx, flush);
 	if (rc)
-		CAM_ERR(CAM_CORE, "FLush failure for node %s", node->name);
+		CAM_ERR(CAM_CORE, "Flush failure for node %s", node->name);
 
 	return rc;
 }
@@ -342,6 +342,25 @@
 	return cam_context_handle_crm_flush_req(ctx, flush);
 }
 
+static int __cam_node_crm_process_evt(
+	struct cam_req_mgr_link_evt_data *evt_data)
+{
+	struct cam_context *ctx = NULL;
+
+	if (!evt_data) {
+		CAM_ERR(CAM_CORE, "Invalid process event request payload");
+		return -EINVAL;
+	}
+
+	ctx = (struct cam_context *) cam_get_device_priv(evt_data->dev_hdl);
+	if (!ctx) {
+		CAM_ERR(CAM_CORE, "Can not get context for handle %d",
+			evt_data->dev_hdl);
+		return -EINVAL;
+	}
+	return cam_context_handle_crm_process_evt(ctx, evt_data);
+}
+
 int cam_node_deinit(struct cam_node *node)
 {
 	if (node)
@@ -394,6 +413,7 @@
 	node->crm_node_intf.get_dev_info = __cam_node_crm_get_dev_info;
 	node->crm_node_intf.link_setup = __cam_node_crm_link_setup;
 	node->crm_node_intf.flush_req = __cam_node_crm_flush_req;
+	node->crm_node_intf.process_evt = __cam_node_crm_process_evt;
 
 	mutex_init(&node->list_mutex);
 	INIT_LIST_HEAD(&node->free_ctx_list);
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
index 3ebe7a1..b04bc23 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -16,12 +16,19 @@
 #include <linux/msm-bus.h>
 #include <linux/pm_opp.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include "cam_cpas_hw.h"
 #include "cam_cpas_hw_intf.h"
 #include "cam_cpas_soc.h"
 
-#define CAM_CPAS_AXI_MIN_BW (2048 * 1024)
+#define CAM_CPAS_AXI_MIN_MNOC_AB_BW   (2048 * 1024)
+#define CAM_CPAS_AXI_MIN_MNOC_IB_BW   (2048 * 1024)
+#define CAM_CPAS_AXI_MIN_CAMNOC_AB_BW (2048 * 1024)
+#define CAM_CPAS_AXI_MIN_CAMNOC_IB_BW (3000000000L)
+
+static uint cam_min_camnoc_ib_bw;
+module_param(cam_min_camnoc_ib_bw, uint, 0644);
 
 int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw,
 	enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info)
@@ -84,11 +91,19 @@
 }
 
 static int cam_cpas_util_vote_bus_client_bw(
-	struct cam_cpas_bus_client *bus_client, uint64_t ab, uint64_t ib)
+	struct cam_cpas_bus_client *bus_client, uint64_t ab, uint64_t ib,
+	bool camnoc_bw)
 {
 	struct msm_bus_paths *path;
 	struct msm_bus_scale_pdata *pdata;
 	int idx = 0;
+	uint64_t min_camnoc_ib_bw = CAM_CPAS_AXI_MIN_CAMNOC_IB_BW;
+
+	if (cam_min_camnoc_ib_bw > 0)
+		min_camnoc_ib_bw = (uint64_t)cam_min_camnoc_ib_bw * 1000000L;
+
+	CAM_DBG(CAM_CPAS, "cam_min_camnoc_ib_bw = %d, min_camnoc_ib_bw=%llu",
+		cam_min_camnoc_ib_bw, min_camnoc_ib_bw);
 
 	if (!bus_client->valid) {
 		CAM_ERR(CAM_CPAS, "bus client not valid");
@@ -118,11 +133,19 @@
 	bus_client->curr_vote_level = idx;
 	mutex_unlock(&bus_client->lock);
 
-	if ((ab > 0) && (ab < CAM_CPAS_AXI_MIN_BW))
-		ab = CAM_CPAS_AXI_MIN_BW;
+	if (camnoc_bw == true) {
+		if ((ab > 0) && (ab < CAM_CPAS_AXI_MIN_CAMNOC_AB_BW))
+			ab = CAM_CPAS_AXI_MIN_CAMNOC_AB_BW;
 
-	if ((ib > 0) && (ib < CAM_CPAS_AXI_MIN_BW))
-		ib = CAM_CPAS_AXI_MIN_BW;
+		if ((ib > 0) && (ib < min_camnoc_ib_bw))
+			ib = min_camnoc_ib_bw;
+	} else {
+		if ((ab > 0) && (ab < CAM_CPAS_AXI_MIN_MNOC_AB_BW))
+			ab = CAM_CPAS_AXI_MIN_MNOC_AB_BW;
+
+		if ((ib > 0) && (ib < CAM_CPAS_AXI_MIN_MNOC_IB_BW))
+			ib = CAM_CPAS_AXI_MIN_MNOC_IB_BW;
+	}
 
 	pdata = bus_client->pdata;
 	path = &(pdata->usecase[idx]);
@@ -205,7 +228,7 @@
 		return -EINVAL;
 
 	if (bus_client->dyn_vote)
-		cam_cpas_util_vote_bus_client_bw(bus_client, 0, 0);
+		cam_cpas_util_vote_bus_client_bw(bus_client, 0, 0, false);
 	else
 		cam_cpas_util_vote_bus_client_level(bus_client, 0);
 
@@ -370,7 +393,7 @@
 	list_for_each_entry_safe(curr_port, temp_port,
 		&cpas_core->axi_ports_list_head, sibling_port) {
 		rc = cam_cpas_util_vote_bus_client_bw(&curr_port->mnoc_bus,
-			mnoc_bw, mnoc_bw);
+			mnoc_bw, mnoc_bw, false);
 		if (rc) {
 			CAM_ERR(CAM_CPAS,
 				"Failed in mnoc vote, enable=%d, rc=%d",
@@ -380,13 +403,13 @@
 
 		if (soc_private->axi_camnoc_based) {
 			cam_cpas_util_vote_bus_client_bw(
-				&curr_port->camnoc_bus, 0, camnoc_bw);
+				&curr_port->camnoc_bus, 0, camnoc_bw, true);
 			if (rc) {
 				CAM_ERR(CAM_CPAS,
 					"Failed in mnoc vote, enable=%d, %d",
 					enable, rc);
 				cam_cpas_util_vote_bus_client_bw(
-					&curr_port->mnoc_bus, 0, 0);
+					&curr_port->mnoc_bus, 0, 0, false);
 				goto remove_ahb_vote;
 			}
 		}
@@ -571,7 +594,7 @@
 		camnoc_bw, mnoc_bw);
 
 	rc = cam_cpas_util_vote_bus_client_bw(&axi_port->mnoc_bus,
-		mnoc_bw, mnoc_bw);
+		mnoc_bw, mnoc_bw, false);
 	if (rc) {
 		CAM_ERR(CAM_CPAS,
 			"Failed in mnoc vote ab[%llu] ib[%llu] rc=%d",
@@ -581,7 +604,7 @@
 
 	if (soc_private->axi_camnoc_based) {
 		rc = cam_cpas_util_vote_bus_client_bw(&axi_port->camnoc_bus,
-			0, camnoc_bw);
+			0, camnoc_bw, true);
 		if (rc) {
 			CAM_ERR(CAM_CPAS,
 				"Failed camnoc vote ab[%llu] ib[%llu] rc=%d",
@@ -880,9 +903,11 @@
 		goto done;
 
 	if (cpas_core->streamon_clients == 0) {
+		atomic_set(&cpas_core->irq_count, 1);
 		rc = cam_cpas_soc_enable_resources(&cpas_hw->soc_info,
 			applied_level);
 		if (rc) {
+			atomic_set(&cpas_core->irq_count, 0);
 			CAM_ERR(CAM_CPAS, "enable_resorce failed, rc=%d", rc);
 			goto done;
 		}
@@ -890,14 +915,17 @@
 		if (cpas_core->internal_ops.power_on) {
 			rc = cpas_core->internal_ops.power_on(cpas_hw);
 			if (rc) {
+				atomic_set(&cpas_core->irq_count, 0);
 				cam_cpas_soc_disable_resources(
-					&cpas_hw->soc_info);
+					&cpas_hw->soc_info, true, true);
 				CAM_ERR(CAM_CPAS,
 					"failed in power_on settings rc=%d",
 					rc);
 				goto done;
 			}
 		}
+		CAM_DBG(CAM_CPAS, "irq_count=%d\n",
+			atomic_read(&cpas_core->irq_count));
 		cpas_hw->hw_state = CAM_HW_STATE_POWER_UP;
 	}
 
@@ -912,6 +940,10 @@
 	return rc;
 }
 
+static int _check_irq_count(struct cam_cpas *cpas_core)
+{
+	return (atomic_read(&cpas_core->irq_count) > 0) ? 0 : 1;
+}
 
 static int cam_cpas_hw_stop(void *hw_priv, void *stop_args,
 	uint32_t arg_size)
@@ -924,6 +956,7 @@
 	struct cam_ahb_vote ahb_vote;
 	struct cam_axi_vote axi_vote;
 	int rc = 0;
+	long result;
 
 	if (!hw_priv || !stop_args) {
 		CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK",
@@ -972,11 +1005,29 @@
 			}
 		}
 
-		rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info);
+		rc = cam_cpas_soc_disable_irq(&cpas_hw->soc_info);
+		if (rc) {
+			CAM_ERR(CAM_CPAS, "disable_irq failed, rc=%d", rc);
+			goto done;
+		}
+
+		/* Wait for any IRQs still being handled */
+		atomic_dec(&cpas_core->irq_count);
+		result = wait_event_timeout(cpas_core->irq_count_wq,
+			_check_irq_count(cpas_core), HZ);
+		if (result == 0) {
+			CAM_ERR(CAM_CPAS, "Wait failed: irq_count=%d",
+				atomic_read(&cpas_core->irq_count));
+		}
+
+		rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info,
+			true, false);
 		if (rc) {
 			CAM_ERR(CAM_CPAS, "disable_resorce failed, rc=%d", rc);
 			goto done;
 		}
+		CAM_DBG(CAM_CPAS, "Disabled all the resources: irq_count=%d\n",
+			atomic_read(&cpas_core->irq_count));
 		cpas_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
 	}
 
@@ -1427,6 +1478,8 @@
 	soc_private = (struct cam_cpas_private_soc *)
 		cpas_hw->soc_info.soc_private;
 	cpas_core->num_clients = soc_private->num_clients;
+	atomic_set(&cpas_core->irq_count, 0);
+	init_waitqueue_head(&cpas_core->irq_count_wq);
 
 	if (internal_ops->setup_regbase) {
 		rc = internal_ops->setup_regbase(&cpas_hw->soc_info,
@@ -1482,7 +1535,7 @@
 	if (rc)
 		goto disable_soc_res;
 
-	rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info);
+	rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true);
 	if (rc) {
 		CAM_ERR(CAM_CPAS, "failed in soc_disable_resources, rc=%d", rc);
 		goto remove_default_vote;
@@ -1500,7 +1553,7 @@
 	return 0;
 
 disable_soc_res:
-	cam_cpas_soc_disable_resources(&cpas_hw->soc_info);
+	cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true);
 remove_default_vote:
 	cam_cpas_util_vote_default_ahb_axi(cpas_hw, false);
 axi_cleanup:
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h
index aa3663d..05840bb 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -187,6 +187,8 @@
 	struct list_head axi_ports_list_head;
 	struct cam_cpas_internal_ops internal_ops;
 	struct workqueue_struct *work_queue;
+	atomic_t irq_count;
+	wait_queue_head_t irq_count_wq;
 };
 
 int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops);
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
index f85f461..b18af0a 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -209,13 +209,26 @@
 	return rc;
 }
 
-int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info)
+int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info,
+	bool disable_clocks, bool disble_irq)
 {
 	int rc = 0;
 
-	rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
+	rc = cam_soc_util_disable_platform_resource(soc_info,
+		disable_clocks, disble_irq);
 	if (rc)
 		CAM_ERR(CAM_CPAS, "disable platform failed, rc=%d", rc);
 
 	return rc;
 }
+
+int cam_cpas_soc_disable_irq(struct cam_hw_soc_info *soc_info)
+{
+	int rc = 0;
+
+	rc = cam_soc_util_irq_disable(soc_info);
+	if (rc)
+		CAM_ERR(CAM_CPAS, "disable irq failed, rc=%d", rc);
+
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h
index d4fc039..fe0187e 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -61,5 +61,7 @@
 int cam_cpas_soc_deinit_resources(struct cam_hw_soc_info *soc_info);
 int cam_cpas_soc_enable_resources(struct cam_hw_soc_info *soc_info,
 	enum cam_vote_level default_level);
-int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info);
+int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info,
+	bool disable_clocks, bool disble_irq);
+int cam_cpas_soc_disable_irq(struct cam_hw_soc_info *soc_info);
 #endif /* _CAM_CPAS_SOC_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
index 0e5ce85..0533ed8 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -354,6 +354,11 @@
 	cpas_core = (struct cam_cpas *) cpas_hw->core_info;
 	soc_info = &cpas_hw->soc_info;
 
+	if (!atomic_inc_not_zero(&cpas_core->irq_count)) {
+		CAM_ERR(CAM_CPAS, "CPAS off");
+		return;
+	}
+
 	for (i = 0; i < camnoc_info->irq_err_size; i++) {
 		if ((payload->irq_status & camnoc_info->irq_err[i].sbm_port) &&
 			(camnoc_info->irq_err[i].enable)) {
@@ -398,6 +403,9 @@
 				~camnoc_info->irq_err[i].sbm_port;
 		}
 	}
+	atomic_dec(&cpas_core->irq_count);
+	wake_up(&cpas_core->irq_count_wq);
+	CAM_DBG(CAM_CPAS, "irq_count=%d\n", atomic_read(&cpas_core->irq_count));
 
 	if (payload->irq_status)
 		CAM_ERR(CAM_CPAS, "IRQ not handled irq_status=0x%x",
@@ -414,9 +422,14 @@
 	int camnoc_index = cpas_core->regbase_index[CAM_CPAS_REG_CAMNOC];
 	struct cam_cpas_work_payload *payload;
 
+	if (!atomic_inc_not_zero(&cpas_core->irq_count)) {
+		CAM_ERR(CAM_CPAS, "CPAS off");
+		return IRQ_HANDLED;
+	}
+
 	payload = kzalloc(sizeof(struct cam_cpas_work_payload), GFP_ATOMIC);
 	if (!payload)
-		return IRQ_HANDLED;
+		goto done;
 
 	payload->irq_status = cam_io_r_mb(
 		soc_info->reg_map[camnoc_index].mem_base +
@@ -433,6 +446,9 @@
 	cam_cpastop_reset_irq(cpas_hw);
 
 	queue_work(cpas_core->work_queue, &payload->work);
+done:
+	atomic_dec(&cpas_core->irq_count);
+	wake_up(&cpas_core->irq_count_wq);
 
 	return IRQ_HANDLED;
 }
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c
index b7b636c..d2314c4 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -138,9 +138,22 @@
 int cam_bps_update_clk_rate(struct cam_hw_soc_info *soc_info,
 	uint32_t clk_rate)
 {
+	int32_t src_clk_idx;
+
 	if (!soc_info)
 		return -EINVAL;
 
+	src_clk_idx = soc_info->src_clk_idx;
+
+	if ((soc_info->clk_level_valid[CAM_TURBO_VOTE] == true) &&
+		(soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx] != 0) &&
+		(clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) {
+		CAM_DBG(CAM_ICP, "clk_rate %d greater than max, reset to %d",
+			clk_rate,
+			soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]);
+		clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx];
+	}
+
 	return cam_soc_util_set_clk_rate(soc_info->clk[soc_info->src_clk_idx],
 		soc_info->clk_name[soc_info->src_clk_idx], clk_rate);
 }
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index 0012b34..3bbb8d3 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -116,7 +116,12 @@
 		if (ctx_data->clk_info.clk_rate[i] >= base_clk)
 			return i;
 
-	return 0;
+	/*
+	 * Caller has to ensure returned index is within array
+	 * size bounds while accessing that index.
+	 */
+
+	return i;
 }
 
 static bool cam_icp_is_over_clk(struct cam_icp_hw_mgr *hw_mgr,
@@ -132,7 +137,7 @@
 	curr_clk_idx = cam_icp_get_actual_clk_rate_idx(ctx_data,
 		hw_mgr_clk_info->curr_clk);
 
-	CAM_DBG(CAM_ICP, "bc_idx = %d cc_idx = %d %lld %lld",
+	CAM_DBG(CAM_ICP, "bc_idx = %d cc_idx = %d %d %d",
 		base_clk_idx, curr_clk_idx, hw_mgr_clk_info->base_clk,
 		hw_mgr_clk_info->curr_clk);
 
@@ -192,9 +197,9 @@
 	struct cam_hw_info *dev = NULL;
 
 	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS)
-		dev_intf = hw_mgr->devices[CAM_ICP_DEV_BPS][0];
+		dev_intf = hw_mgr->bps_dev_intf;
 	else
-		dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][0];
+		dev_intf = hw_mgr->ipe0_dev_intf;
 
 	if (!dev_intf) {
 		CAM_ERR(CAM_ICP, "dev_intf is invalid");
@@ -254,9 +259,9 @@
 	struct cam_hw_intf *dev_intf = NULL;
 	struct cam_a5_clk_update_cmd clk_upd_cmd;
 
-	ipe0_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][0];
-	ipe1_dev_intf = hw_mgr->devices[CAM_ICP_DEV_IPE][1];
-	bps_dev_intf = hw_mgr->devices[CAM_ICP_DEV_BPS][0];
+	ipe0_dev_intf = hw_mgr->ipe0_dev_intf;
+	ipe1_dev_intf = hw_mgr->ipe1_dev_intf;
+	bps_dev_intf = hw_mgr->bps_dev_intf;
 
 	clk_info->base_clk = 0;
 	clk_info->curr_clk = 0;
@@ -305,7 +310,120 @@
 	return 0;
 }
 
-static void cam_icp_timer_cb(unsigned long data)
+static int32_t cam_icp_ctx_timer(void *priv, void *data)
+{
+	struct clk_work_data *task_data = (struct clk_work_data *)data;
+	struct cam_icp_hw_ctx_data *ctx_data =
+		(struct cam_icp_hw_ctx_data *)task_data->data;
+	struct cam_icp_hw_mgr *hw_mgr = &icp_hw_mgr;
+	uint32_t id;
+	struct cam_hw_intf *ipe0_dev_intf = NULL;
+	struct cam_hw_intf *ipe1_dev_intf = NULL;
+	struct cam_hw_intf *bps_dev_intf = NULL;
+	struct cam_hw_intf *dev_intf = NULL;
+	struct cam_icp_clk_info *clk_info;
+	struct cam_icp_cpas_vote clk_update;
+
+	if (!ctx_data) {
+		CAM_ERR(CAM_ICP, "ctx_data is NULL, failed to update clk");
+		return -EINVAL;
+	}
+
+	mutex_lock(&ctx_data->ctx_mutex);
+	if ((ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) ||
+		(ctx_data->watch_dog_reset_counter == 0)) {
+		CAM_DBG(CAM_ICP, "state %d, counter=%d",
+			ctx_data->state, ctx_data->watch_dog_reset_counter);
+		mutex_unlock(&ctx_data->ctx_mutex);
+		return 0;
+	}
+
+	CAM_DBG(CAM_ICP,
+		"E :ctx_id = %d ubw = %lld cbw = %lld curr_fc = %u bc = %u",
+		ctx_data->ctx_id,
+		ctx_data->clk_info.uncompressed_bw,
+		ctx_data->clk_info.compressed_bw,
+		ctx_data->clk_info.curr_fc, ctx_data->clk_info.base_clk);
+
+	ipe0_dev_intf = hw_mgr->ipe0_dev_intf;
+	ipe1_dev_intf = hw_mgr->ipe1_dev_intf;
+	bps_dev_intf = hw_mgr->bps_dev_intf;
+
+	if ((!ipe0_dev_intf) || (!bps_dev_intf)) {
+		CAM_ERR(CAM_ICP, "dev intfs are wrong, failed to update clk");
+		mutex_unlock(&ctx_data->ctx_mutex);
+		return -EINVAL;
+	}
+
+	if (!ctx_data->icp_dev_acquire_info) {
+		CAM_WARN(CAM_ICP, "NULL acquire info");
+		mutex_unlock(&ctx_data->ctx_mutex);
+		return -EINVAL;
+	}
+
+	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) {
+		dev_intf = bps_dev_intf;
+		clk_info = &hw_mgr->clk_info[ICP_CLK_HW_BPS];
+		id = CAM_ICP_BPS_CMD_VOTE_CPAS;
+	} else {
+		dev_intf = ipe0_dev_intf;
+		clk_info = &hw_mgr->clk_info[ICP_CLK_HW_IPE];
+		id = CAM_ICP_IPE_CMD_VOTE_CPAS;
+	}
+
+	clk_info->compressed_bw -= ctx_data->clk_info.compressed_bw;
+	clk_info->uncompressed_bw -= ctx_data->clk_info.uncompressed_bw;
+	ctx_data->clk_info.uncompressed_bw = 0;
+	ctx_data->clk_info.compressed_bw = 0;
+	ctx_data->clk_info.curr_fc = 0;
+	ctx_data->clk_info.base_clk = 0;
+
+	clk_update.ahb_vote.type = CAM_VOTE_DYNAMIC;
+	clk_update.ahb_vote.vote.freq = clk_info->curr_clk;
+	clk_update.ahb_vote_valid = true;
+	clk_update.axi_vote.compressed_bw = clk_info->compressed_bw;
+	clk_update.axi_vote.uncompressed_bw = clk_info->uncompressed_bw;
+	clk_update.axi_vote_valid = true;
+	dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id,
+		&clk_update, sizeof(clk_update));
+
+	CAM_DBG(CAM_ICP,
+		"X :ctx_id = %d ubw = %lld cbw = %lld curr_fc = %u bc = %u",
+		ctx_data->ctx_id,
+		ctx_data->clk_info.uncompressed_bw,
+		ctx_data->clk_info.compressed_bw,
+		ctx_data->clk_info.curr_fc, ctx_data->clk_info.base_clk);
+
+	mutex_unlock(&ctx_data->ctx_mutex);
+
+	return 0;
+}
+
+static void cam_icp_ctx_timer_cb(unsigned long data)
+{
+	unsigned long flags;
+	struct crm_workq_task *task;
+	struct clk_work_data *task_data;
+	struct cam_req_mgr_timer *timer = (struct cam_req_mgr_timer *)data;
+
+	spin_lock_irqsave(&icp_hw_mgr.hw_mgr_lock, flags);
+	task = cam_req_mgr_workq_get_task(icp_hw_mgr.msg_work);
+	if (!task) {
+		CAM_ERR(CAM_ICP, "no empty task");
+		spin_unlock_irqrestore(&icp_hw_mgr.hw_mgr_lock, flags);
+		return;
+	}
+
+	task_data = (struct clk_work_data *)task->payload;
+	task_data->data = timer->parent;
+	task_data->type = ICP_WORKQ_TASK_MSG_TYPE;
+	task->process_cb = cam_icp_ctx_timer;
+	cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
+		CRM_TASK_PRIORITY_0);
+	spin_unlock_irqrestore(&icp_hw_mgr.hw_mgr_lock, flags);
+}
+
+static void cam_icp_device_timer_cb(unsigned long data)
 {
 	unsigned long flags;
 	struct crm_workq_task *task;
@@ -342,13 +460,29 @@
 		hw_mgr->clk_info[i].uncompressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
 		hw_mgr->clk_info[i].compressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
 		hw_mgr->clk_info[i].hw_type = i;
+		hw_mgr->clk_info[i].watch_dog_reset_counter = 0;
 	}
 	hw_mgr->icp_default_clk = ICP_CLK_SVS_HZ;
 
 	return 0;
 }
 
-static int cam_icp_timer_start(struct cam_icp_hw_mgr *hw_mgr)
+static int cam_icp_ctx_timer_start(struct cam_icp_hw_ctx_data *ctx_data)
+{
+	int rc = 0;
+
+	rc = crm_timer_init(&ctx_data->watch_dog,
+		2000, ctx_data, &cam_icp_ctx_timer_cb);
+	if (rc)
+		CAM_ERR(CAM_ICP, "Failed to start timer");
+
+	ctx_data->watch_dog_reset_counter = 0;
+
+	CAM_DBG(CAM_ICP, "stop timer : ctx_id = %d", ctx_data->ctx_id);
+	return rc;
+}
+
+static int cam_icp_device_timer_start(struct cam_icp_hw_mgr *hw_mgr)
 {
 	int rc = 0;
 	int i;
@@ -356,21 +490,70 @@
 	for (i = 0; i < ICP_CLK_HW_MAX; i++)  {
 		if (!hw_mgr->clk_info[i].watch_dog) {
 			rc = crm_timer_init(&hw_mgr->clk_info[i].watch_dog,
-				3000, &hw_mgr->clk_info[i], &cam_icp_timer_cb);
+				3000, &hw_mgr->clk_info[i],
+				&cam_icp_device_timer_cb);
+
 			if (rc)
 				CAM_ERR(CAM_ICP, "Failed to start timer %d", i);
+
+			hw_mgr->clk_info[i].watch_dog_reset_counter = 0;
 		}
 	}
 
 	return rc;
 }
 
-static void cam_icp_timer_stop(struct cam_icp_hw_mgr *hw_mgr)
+static int cam_icp_ctx_timer_stop(struct cam_icp_hw_ctx_data *ctx_data)
 {
-	if (!hw_mgr->bps_ctxt_cnt)
+	if (ctx_data->watch_dog) {
+		CAM_DBG(CAM_ICP, "stop timer : ctx_id = %d", ctx_data->ctx_id);
+		ctx_data->watch_dog_reset_counter = 0;
+		crm_timer_exit(&ctx_data->watch_dog);
+		ctx_data->watch_dog = NULL;
+	}
+
+	return 0;
+}
+
+static void cam_icp_device_timer_stop(struct cam_icp_hw_mgr *hw_mgr)
+{
+	if (!hw_mgr->bps_ctxt_cnt &&
+		hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog) {
+		hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog_reset_counter = 0;
 		crm_timer_exit(&hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog);
-	else if (!hw_mgr->ipe_ctxt_cnt)
+		hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog = NULL;
+	}
+
+	if (!hw_mgr->ipe_ctxt_cnt &&
+		hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog) {
+		hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog_reset_counter = 0;
 		crm_timer_exit(&hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog);
+		hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog = NULL;
+	}
+}
+
+static int cam_icp_ctx_timer_reset(struct cam_icp_hw_ctx_data *ctx_data)
+{
+	if (ctx_data && ctx_data->watch_dog) {
+		ctx_data->watch_dog_reset_counter++;
+		CAM_DBG(CAM_ICP, "reset timer : ctx_id = %d, counter=%d",
+			ctx_data->ctx_id, ctx_data->watch_dog_reset_counter);
+		crm_timer_reset(ctx_data->watch_dog);
+	}
+
+	return 0;
+}
+
+static void cam_icp_device_timer_reset(struct cam_icp_hw_mgr *hw_mgr,
+	int device_index)
+{
+	if ((device_index >= ICP_CLK_HW_MAX) || (!hw_mgr))
+		return;
+
+	if (hw_mgr->clk_info[device_index].watch_dog) {
+		crm_timer_reset(hw_mgr->clk_info[device_index].watch_dog);
+		hw_mgr->clk_info[device_index].watch_dog_reset_counter++;
+	}
 }
 
 static uint32_t cam_icp_mgr_calc_base_clk(uint32_t frame_cycles,
@@ -420,7 +603,9 @@
 	for (i = 0; i < CAM_ICP_CTX_MAX; i++) {
 		ctx_data = &hw_mgr->ctx_data[i];
 		if (ctx_data->state == CAM_ICP_CTX_STATE_ACQUIRED &&
-			ctx_data->icp_dev_acquire_info->dev_type == dev_type)
+			ICP_DEV_TYPE_TO_CLK_TYPE(
+			ctx_data->icp_dev_acquire_info->dev_type) ==
+			ICP_DEV_TYPE_TO_CLK_TYPE(dev_type))
 			hw_mgr_clk_info->base_clk +=
 				ctx_data->clk_info.base_clk;
 	}
@@ -575,7 +760,8 @@
 		hw_mgr_clk_info->over_clked = 0;
 		rc = false;
 	}  else if (hw_mgr_clk_info->curr_clk < hw_mgr_clk_info->base_clk) {
-		hw_mgr_clk_info->curr_clk = hw_mgr_clk_info->base_clk;
+		hw_mgr_clk_info->curr_clk = cam_icp_get_actual_clk_rate(hw_mgr,
+			ctx_data, hw_mgr_clk_info->base_clk);
 		rc = true;
 	}
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
@@ -633,7 +819,13 @@
 	 * recalculate bandwidth of all contexts of same hardware and update
 	 * voting of bandwidth
 	 */
-	if (clk_info->uncompressed_bw == ctx_data->clk_info.uncompressed_bw)
+	CAM_DBG(CAM_ICP, "ubw ctx = %lld clk_info ubw = %lld busy = %d",
+		ctx_data->clk_info.uncompressed_bw,
+		clk_info->uncompressed_bw, busy);
+
+	if ((clk_info->uncompressed_bw == ctx_data->clk_info.uncompressed_bw) &&
+		(ctx_data->clk_info.uncompressed_bw ==
+		hw_mgr_clk_info->uncompressed_bw))
 		return false;
 
 	if (busy &&
@@ -647,13 +839,18 @@
 	for (i = 0; i < CAM_ICP_CTX_MAX; i++) {
 		ctx = &hw_mgr->ctx_data[i];
 		if (ctx->state == CAM_ICP_CTX_STATE_ACQUIRED &&
-			ctx->icp_dev_acquire_info->dev_type ==
-			ctx_data->icp_dev_acquire_info->dev_type) {
+			ICP_DEV_TYPE_TO_CLK_TYPE(
+			ctx->icp_dev_acquire_info->dev_type) ==
+			ICP_DEV_TYPE_TO_CLK_TYPE(
+			ctx_data->icp_dev_acquire_info->dev_type)) {
 			mutex_lock(&hw_mgr->hw_mgr_mutex);
 			hw_mgr_clk_info->uncompressed_bw +=
 				ctx->clk_info.uncompressed_bw;
 			hw_mgr_clk_info->compressed_bw +=
 				ctx->clk_info.compressed_bw;
+			CAM_DBG(CAM_ICP, "ubw = %lld, cbw = %lld",
+				hw_mgr_clk_info->uncompressed_bw,
+				hw_mgr_clk_info->compressed_bw);
 			mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		}
 	}
@@ -671,12 +868,13 @@
 	uint64_t req_id;
 	struct cam_icp_clk_info *hw_mgr_clk_info;
 
+	cam_icp_ctx_timer_reset(ctx_data);
 	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS) {
-		crm_timer_reset(hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog);
+		cam_icp_device_timer_reset(hw_mgr, ICP_CLK_HW_BPS);
 		hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_BPS];
 		CAM_DBG(CAM_ICP, "Reset bps timer");
 	} else {
-		crm_timer_reset(hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog);
+		cam_icp_device_timer_reset(hw_mgr, ICP_CLK_HW_IPE);
 		hw_mgr_clk_info = &hw_mgr->clk_info[ICP_CLK_HW_IPE];
 		CAM_DBG(CAM_ICP, "Reset ipe timer");
 	}
@@ -827,11 +1025,13 @@
 	dev_intf->hw_ops.process_cmd(dev_intf->hw_priv, id,
 		&clk_update, sizeof(clk_update));
 
-	if (ctx_data->icp_dev_acquire_info->dev_type != CAM_ICP_RES_TYPE_BPS)
-		if (ipe1_dev_intf)
-			ipe1_dev_intf->hw_ops.process_cmd(
-				ipe1_dev_intf->hw_priv, id,
-				&clk_update, sizeof(clk_update));
+	/*
+	 * Consolidated bw needs to be voted on only one IPE client. Otherwise
+	 * total bw that we vote at bus client would be doubled. So either
+	 * remove voting on IPE1 or divide the vote for each IPE client
+	 * and vote to cpas - cpas will add up and vote full bw to sf client
+	 * anyway.
+	 */
 
 	return 0;
 }
@@ -1174,9 +1374,10 @@
 
 	clk_type = ICP_DEV_TYPE_TO_CLK_TYPE(ctx_data->icp_dev_acquire_info->
 		dev_type);
-	crm_timer_reset(icp_hw_mgr.clk_info[clk_type].watch_dog);
+	cam_icp_device_timer_reset(&icp_hw_mgr, clk_type);
 
 	mutex_lock(&ctx_data->ctx_mutex);
+	cam_icp_ctx_timer_reset(ctx_data);
 	if (ctx_data->state != CAM_ICP_CTX_STATE_ACQUIRED) {
 		CAM_DBG(CAM_ICP, "ctx %u is in %d state",
 			ctx_data->ctx_id, ctx_data->state);
@@ -2063,6 +2264,7 @@
 	kfree(hw_mgr->ctx_data[ctx_id].icp_dev_acquire_info);
 	hw_mgr->ctx_data[ctx_id].icp_dev_acquire_info = NULL;
 	hw_mgr->ctx_data[ctx_id].state = CAM_ICP_CTX_STATE_FREE;
+	cam_icp_ctx_timer_stop(&hw_mgr->ctx_data[ctx_id]);
 	mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
 
 	CAM_DBG(CAM_ICP, "X: ctx_id = %d", ctx_id);
@@ -2386,34 +2588,24 @@
 	}
 	a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv;
 	rc = cam_icp_allocate_hfi_mem();
-	if (rc) {
-		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+	if (rc)
 		goto alloc_hfi_mem_failed;
-	}
 
 	rc = cam_icp_mgr_device_init(hw_mgr);
-	if (rc) {
-		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+	if (rc)
 		goto dev_init_fail;
-	}
 
 	rc = cam_icp_mgr_fw_download(hw_mgr);
-	if (rc) {
-		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+	if (rc)
 		goto fw_download_failed;
-	}
 
 	rc = cam_icp_mgr_hfi_init(hw_mgr);
-	if (rc) {
-		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+	if (rc)
 		goto hfi_init_failed;
-	}
 
 	rc = cam_icp_mgr_send_fw_init(hw_mgr);
-	if (rc) {
-		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+	if (rc)
 		goto fw_init_failed;
-	}
 
 	hw_mgr->ctxt_cnt = 0;
 	hw_mgr->fw_download = true;
@@ -2444,6 +2636,7 @@
 dev_init_fail:
 	cam_icp_free_hfi_mem();
 alloc_hfi_mem_failed:
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 	return rc;
 }
 
@@ -3177,7 +3370,7 @@
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 
 	if (!hw_mgr->bps_ctxt_cnt || !hw_mgr->ipe_ctxt_cnt)
-		cam_icp_timer_stop(hw_mgr);
+		cam_icp_device_timer_stop(hw_mgr);
 
 	CAM_DBG(CAM_ICP, "Exit");
 	return rc;
@@ -3464,6 +3657,9 @@
 			goto get_io_buf_failed;
 		}
 
+		if (icp_hw_mgr.a5_debug_q)
+			hfi_set_debug_level(icp_hw_mgr.a5_dbg_lvl);
+
 		rc = cam_icp_send_ubwc_cfg(hw_mgr);
 		if (rc) {
 			mutex_unlock(&hw_mgr->hw_mgr_mutex);
@@ -3472,7 +3668,9 @@
 	}
 
 	if (!hw_mgr->bps_ctxt_cnt || !hw_mgr->ipe_ctxt_cnt)
-		cam_icp_timer_start(hw_mgr);
+		cam_icp_device_timer_start(hw_mgr);
+
+	cam_icp_ctx_timer_start(ctx_data);
 
 	rc = cam_icp_mgr_ipe_bps_resume(hw_mgr, ctx_data);
 	if (rc) {
@@ -3539,6 +3737,7 @@
 send_ping_failed:
 	cam_icp_mgr_ipe_bps_power_collapse(hw_mgr, ctx_data, 0);
 ipe_bps_resume_failed:
+	cam_icp_ctx_timer_stop(&hw_mgr->ctx_data[ctx_id]);
 ubwc_cfg_failed:
 	if (!hw_mgr->ctxt_cnt)
 		cam_icp_mgr_icp_power_collapse(hw_mgr);
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
index 85f5b550..4d181f0 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -183,6 +183,8 @@
  * @temp_payload: Payload for destroy handle data
  * @ctx_id: Context Id
  * @clk_info: Current clock info of a context
+ * @watch_dog: watchdog timer handle
+ * @watch_dog_reset_counter: Counter for watch dog reset
  */
 struct cam_icp_hw_ctx_data {
 	void *context_priv;
@@ -200,6 +202,8 @@
 	struct ipe_bps_destroy temp_payload;
 	uint32_t ctx_id;
 	struct cam_ctx_clk_info clk_info;
+	struct cam_req_mgr_timer *watch_dog;
+	uint32_t watch_dog_reset_counter;
 };
 
 /**
@@ -222,6 +226,7 @@
  * @compressed_bw: Current compressed bandwidth voting
  * @hw_type: IPE/BPS device type
  * @watch_dog: watchdog timer handle
+ * @watch_dog_reset_counter: Counter for watch dog reset
  */
 struct cam_icp_clk_info {
 	uint32_t base_clk;
@@ -232,6 +237,7 @@
 	uint64_t compressed_bw;
 	uint32_t hw_type;
 	struct cam_req_mgr_timer *watch_dog;
+	uint32_t watch_dog_reset_counter;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
index d2e04ef..771c4ed 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/include/cam_icp_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -21,7 +21,7 @@
 #define ICP_CLK_TURBO_HZ         600000000
 #define ICP_CLK_SVS_HZ           400000000
 
-#define CAM_ICP_A5_BW_BYTES_VOTE 100000000
+#define CAM_ICP_A5_BW_BYTES_VOTE 40000000
 
 #define CAM_ICP_CTX_MAX          36
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c
index 289d7d4..d24305a 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -141,9 +141,22 @@
 int cam_ipe_update_clk_rate(struct cam_hw_soc_info *soc_info,
 	uint32_t clk_rate)
 {
+	int32_t src_clk_idx;
+
 	if (!soc_info)
 		return -EINVAL;
 
+	src_clk_idx = soc_info->src_clk_idx;
+
+	if ((soc_info->clk_level_valid[CAM_TURBO_VOTE] == true) &&
+		(soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx] != 0) &&
+		(clk_rate > soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx])) {
+		CAM_DBG(CAM_ICP, "clk_rate %d greater than max, reset to %d",
+			clk_rate,
+			soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx]);
+		clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx];
+	}
+
 	return cam_soc_util_set_clk_rate(soc_info->clk[soc_info->src_clk_idx],
 		soc_info->clk_name[soc_info->src_clk_idx], clk_rate);
 }
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
index d1153ba..46c4c6a 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -896,6 +896,29 @@
 	return rc;
 }
 
+static int __cam_isp_ctx_sof_in_flush(
+	struct cam_isp_context *ctx_isp, void *evt_data)
+{
+	int rc = 0;
+	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
+
+	if (!evt_data) {
+		CAM_ERR(CAM_ISP, "in valid sof event data");
+		return -EINVAL;
+	}
+	ctx_isp->frame_id++;
+	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
+		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
+
+	if (--ctx_isp->frame_skip_count == 0)
+		ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
+	else
+		CAM_ERR(CAM_ISP, "Skip currect SOF");
+
+	return rc;
+}
+
 static struct cam_isp_ctx_irq_ops
 	cam_isp_ctx_activated_state_machine_irq[CAM_ISP_CTX_ACTIVATED_MAX] = {
 	/* SOF */
@@ -967,6 +990,17 @@
 	/* HALT */
 	{
 	},
+	/* FLUSH */
+	{
+		.irq_ops = {
+			NULL,
+			__cam_isp_ctx_sof_in_flush,
+			NULL,
+			NULL,
+			NULL,
+			__cam_isp_ctx_buf_done_in_applied,
+		},
+	},
 };
 
 static int __cam_isp_ctx_apply_req_in_activated_state(
@@ -1170,6 +1204,24 @@
 	return rc;
 }
 
+static int __cam_isp_ctx_flush_req_in_activated(
+	struct cam_context *ctx,
+	struct cam_req_mgr_flush_request *flush_req)
+{
+	int rc = 0;
+	struct cam_isp_context *ctx_isp;
+
+	ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
+	spin_lock_bh(&ctx->lock);
+	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_FLUSH;
+	ctx_isp->frame_skip_count = 2;
+	spin_unlock_bh(&ctx->lock);
+
+	CAM_DBG(CAM_ISP, "Flush request in state %d", ctx->state);
+	rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
+	return rc;
+}
+
 static int __cam_isp_ctx_flush_req_in_ready(
 	struct cam_context *ctx,
 	struct cam_req_mgr_flush_request *flush_req)
@@ -1230,12 +1282,24 @@
 		.crm_ops = {},
 		.irq_ops = NULL,
 	},
+	/* HW ERROR */
+	{
+		.ioctl_ops = {},
+		.crm_ops = {},
+		.irq_ops = NULL,
+	},
 	/* HALT */
 	{
 		.ioctl_ops = {},
 		.crm_ops = {},
 		.irq_ops = NULL,
 	},
+	/* FLUSH */
+	{
+		.ioctl_ops = {},
+		.crm_ops = {},
+		.irq_ops = NULL,
+	},
 };
 
 static int __cam_isp_ctx_rdi_only_sof_in_top_state(
@@ -1601,10 +1665,23 @@
 			__cam_isp_ctx_buf_done_in_bubble_applied,
 		},
 	},
-
+	/* HW ERROR */
+	{
+	},
 	/* HALT */
 	{
 	},
+	/* FLUSH */
+	{
+		.irq_ops = {
+			NULL,
+			__cam_isp_ctx_sof_in_flush,
+			NULL,
+			NULL,
+			NULL,
+			__cam_isp_ctx_buf_done_in_applied,
+		},
+	},
 };
 
 static int __cam_isp_ctx_rdi_only_apply_req_top_state(
@@ -1660,15 +1737,26 @@
 		.crm_ops = {},
 		.irq_ops = NULL,
 	},
+	/* HW ERROR */
+	{
+		.ioctl_ops = {},
+		.crm_ops = {},
+		.irq_ops = NULL,
+	},
 	/* HALT */
 	{
 		.ioctl_ops = {},
 		.crm_ops = {},
 		.irq_ops = NULL,
 	},
+	/* FLUSHED */
+	{
+		.ioctl_ops = {},
+		.crm_ops = {},
+		.irq_ops = NULL,
+	},
 };
 
-
 /* top level state machine */
 static int __cam_isp_ctx_release_dev_in_top_state(struct cam_context *ctx,
 	struct cam_release_dev_cmd *cmd)
@@ -2212,6 +2300,58 @@
 	return rc;
 }
 
+static int __cam_isp_ctx_link_pause(struct cam_context *ctx)
+{
+	int rc = 0;
+	struct cam_isp_hw_cmd_args   hw_cmd_args;
+	struct cam_isp_context      *ctx_isp =
+		(struct cam_isp_context *) ctx->ctx_priv;
+
+	hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
+	hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_PAUSE_HW;
+	rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
+		&hw_cmd_args);
+
+	return rc;
+}
+
+static int __cam_isp_ctx_link_resume(struct cam_context *ctx)
+{
+	int rc = 0;
+	struct cam_isp_hw_cmd_args   hw_cmd_args;
+	struct cam_isp_context      *ctx_isp =
+		(struct cam_isp_context *) ctx->ctx_priv;
+
+	hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
+	hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_RESUME_HW;
+	rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
+		&hw_cmd_args);
+
+	return rc;
+}
+
+static int __cam_isp_ctx_process_evt(struct cam_context *ctx,
+	struct cam_req_mgr_link_evt_data *link_evt_data)
+{
+	int rc = 0;
+
+	switch (link_evt_data->evt_type) {
+	case CAM_REQ_MGR_LINK_EVT_ERR:
+		/* No need to handle this message now */
+		break;
+	case CAM_REQ_MGR_LINK_EVT_PAUSE:
+		__cam_isp_ctx_link_pause(ctx);
+		break;
+	case CAM_REQ_MGR_LINK_EVT_RESUME:
+		__cam_isp_ctx_link_resume(ctx);
+		break;
+	default:
+		CAM_WARN(CAM_ISP, "Unknown event from CRM");
+		break;
+	}
+	return rc;
+}
+
 static int __cam_isp_ctx_unlink_in_activated(struct cam_context *ctx,
 	struct cam_req_mgr_core_dev_link_setup *unlink)
 {
@@ -2343,7 +2483,8 @@
 		.crm_ops = {
 			.unlink = __cam_isp_ctx_unlink_in_activated,
 			.apply_req = __cam_isp_ctx_apply_req,
-			.flush_req = __cam_isp_ctx_flush_req_in_top_state,
+			.flush_req = __cam_isp_ctx_flush_req_in_activated,
+			.process_evt = __cam_isp_ctx_process_evt,
 		},
 		.irq_ops = __cam_isp_ctx_handle_irq_in_activated,
 	},
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
index 88ebc03..b0b7ae9 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -52,6 +52,7 @@
 	CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED,
 	CAM_ISP_CTX_ACTIVATED_HW_ERROR,
 	CAM_ISP_CTX_ACTIVATED_HALT,
+	CAM_ISP_CTX_ACTIVATED_FLUSH,
 	CAM_ISP_CTX_ACTIVATED_MAX,
 };
 
@@ -116,6 +117,7 @@
  * @subscribe_event:       The irq event mask that CRM subscribes to, IFE will
  *                         invoke CRM cb at those event.
  * @last_applied_req_id:   Last applied request id
+ * @frame_skip_count:      Number of frame to skip before change state
  *
  */
 struct cam_isp_context {
@@ -135,6 +137,7 @@
 	int64_t                          reported_req_id;
 	uint32_t                         subscribe_event;
 	int64_t                          last_applied_req_id;
+	uint32_t                         frame_skip_count;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index 8d41ae7..fda6427 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -860,10 +860,95 @@
 	return rc;
 }
 
-static int cam_ife_hw_mgr_acquire_res_ife_csid_ipp(
+static int cam_ife_mgr_acquire_cid_res(
 	struct cam_ife_hw_mgr_ctx          *ife_ctx,
 	struct cam_isp_in_port_info        *in_port,
-	uint32_t                            cid_res_id)
+	uint32_t                           *cid_res_id,
+	enum cam_ife_pix_path_res_id        csid_path)
+{
+	int rc = -1;
+	int i, j;
+	struct cam_ife_hw_mgr               *ife_hw_mgr;
+	struct cam_ife_hw_mgr_res           *cid_res;
+	struct cam_hw_intf                  *hw_intf;
+	struct cam_csid_hw_reserve_resource_args  csid_acquire;
+
+	ife_hw_mgr = ife_ctx->hw_mgr;
+
+	rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &cid_res);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "No more free hw mgr resource");
+		goto err;
+	}
+	cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_cid, &cid_res);
+
+	csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
+	csid_acquire.in_port = in_port;
+	csid_acquire.res_id =  csid_path;
+
+	for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
+		if (!ife_hw_mgr->csid_devices[i])
+			continue;
+
+		hw_intf = ife_hw_mgr->csid_devices[i];
+		rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &csid_acquire,
+			sizeof(csid_acquire));
+		if (rc)
+			continue;
+		else
+			break;
+	}
+
+	if (i == CAM_IFE_CSID_HW_NUM_MAX || !csid_acquire.node_res) {
+		CAM_ERR(CAM_ISP, "Can not acquire ife csid rdi resource");
+		goto err;
+	}
+
+	cid_res->res_type = CAM_IFE_HW_MGR_RES_CID;
+	cid_res->res_id = csid_acquire.node_res->res_id;
+	cid_res->is_dual_vfe = in_port->usage_type;
+	cid_res->hw_res[0] = csid_acquire.node_res;
+	cid_res->hw_res[1] = NULL;
+	/* CID(DT_ID) value of acquire device, require for path */
+	*cid_res_id = csid_acquire.node_res->res_id;
+
+	if (cid_res->is_dual_vfe) {
+		csid_acquire.node_res = NULL;
+		csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
+		csid_acquire.in_port = in_port;
+		for (j = i + 1; j < CAM_IFE_CSID_HW_NUM_MAX; j++) {
+			if (!ife_hw_mgr->csid_devices[j])
+				continue;
+
+			hw_intf = ife_hw_mgr->csid_devices[j];
+			rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+				&csid_acquire, sizeof(csid_acquire));
+			if (rc)
+				continue;
+			else
+				break;
+		}
+
+		if (j == CAM_IFE_CSID_HW_NUM_MAX) {
+			CAM_ERR(CAM_ISP,
+				"Can not acquire ife csid rdi resource");
+			goto err;
+		}
+		cid_res->hw_res[1] = csid_acquire.node_res;
+	}
+	cid_res->parent = &ife_ctx->res_list_ife_in;
+	ife_ctx->res_list_ife_in.child[
+		ife_ctx->res_list_ife_in.num_children++] = cid_res;
+
+	return 0;
+err:
+	return rc;
+
+}
+
+static int cam_ife_hw_mgr_acquire_res_ife_csid_ipp(
+	struct cam_ife_hw_mgr_ctx          *ife_ctx,
+	struct cam_isp_in_port_info        *in_port)
 {
 	int rc = -1;
 	int i;
@@ -872,8 +957,17 @@
 	struct cam_ife_hw_mgr_res           *csid_res;
 	struct cam_ife_hw_mgr_res           *cid_res;
 	struct cam_hw_intf                  *hw_intf;
+	uint32_t                             cid_res_id;
 	struct cam_csid_hw_reserve_resource_args  csid_acquire;
 
+	/* get cid resource */
+	rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res_id,
+		CAM_IFE_PIX_PATH_RES_IPP);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed");
+		goto err;
+	}
+
 	ife_hw_mgr = ife_ctx->hw_mgr;
 
 	rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &csid_res);
@@ -985,8 +1079,7 @@
 
 static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi(
 	struct cam_ife_hw_mgr_ctx     *ife_ctx,
-	struct cam_isp_in_port_info   *in_port,
-	uint32_t                       cid_res_id)
+	struct cam_isp_in_port_info   *in_port)
 {
 	int rc = -1;
 	int i, j;
@@ -996,6 +1089,7 @@
 	struct cam_ife_hw_mgr_res           *cid_res;
 	struct cam_hw_intf                  *hw_intf;
 	struct cam_isp_out_port_info        *out_port;
+	uint32_t                            cid_res_id;
 	struct cam_csid_hw_reserve_resource_args  csid_acquire;
 
 	ife_hw_mgr = ife_ctx->hw_mgr;
@@ -1005,6 +1099,15 @@
 		if (!cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
 			continue;
 
+		/* get cid resource */
+		rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res_id,
+			cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
+			out_port->res_type));
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed");
+			goto err;
+		}
+
 		rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
 			&csid_res);
 		if (rc) {
@@ -1135,91 +1238,6 @@
 	return 0;
 }
 
-static int cam_ife_mgr_acquire_cid_res(
-	struct cam_ife_hw_mgr_ctx          *ife_ctx,
-	struct cam_isp_in_port_info        *in_port,
-	uint32_t                           *cid_res_id,
-	int                                 pixel_count)
-{
-	int rc = -1;
-	int i, j;
-	struct cam_ife_hw_mgr               *ife_hw_mgr;
-	struct cam_ife_hw_mgr_res           *cid_res;
-	struct cam_hw_intf                  *hw_intf;
-	struct cam_csid_hw_reserve_resource_args  csid_acquire;
-
-	ife_hw_mgr = ife_ctx->hw_mgr;
-
-	rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &cid_res);
-	if (rc) {
-		CAM_ERR(CAM_ISP, "No more free hw mgr resource");
-		goto err;
-	}
-	cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_cid, &cid_res);
-
-	csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
-	csid_acquire.in_port = in_port;
-	csid_acquire.pixel_count = pixel_count;
-
-	for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
-		if (!ife_hw_mgr->csid_devices[i])
-			continue;
-
-		hw_intf = ife_hw_mgr->csid_devices[i];
-		rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv, &csid_acquire,
-			sizeof(csid_acquire));
-		if (rc)
-			continue;
-		else
-			break;
-	}
-
-	if (i == CAM_IFE_CSID_HW_NUM_MAX || !csid_acquire.node_res) {
-		CAM_ERR(CAM_ISP, "Can not acquire ife csid rdi resource");
-		goto err;
-	}
-
-	cid_res->res_type = CAM_IFE_HW_MGR_RES_CID;
-	cid_res->res_id = csid_acquire.node_res->res_id;
-	cid_res->is_dual_vfe = in_port->usage_type;
-	cid_res->hw_res[0] = csid_acquire.node_res;
-	cid_res->hw_res[1] = NULL;
-	/* CID(DT_ID) value of acquire device, require for path */
-	*cid_res_id = csid_acquire.node_res->res_id;
-
-	if (cid_res->is_dual_vfe) {
-		csid_acquire.node_res = NULL;
-		csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
-		csid_acquire.in_port = in_port;
-		for (j = i + 1; j < CAM_IFE_CSID_HW_NUM_MAX; j++) {
-			if (!ife_hw_mgr->csid_devices[j])
-				continue;
-
-			hw_intf = ife_hw_mgr->csid_devices[j];
-			rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
-				&csid_acquire, sizeof(csid_acquire));
-			if (rc)
-				continue;
-			else
-				break;
-		}
-
-		if (j == CAM_IFE_CSID_HW_NUM_MAX) {
-			CAM_ERR(CAM_ISP,
-				"Can not acquire ife csid rdi resource");
-			goto err;
-		}
-		cid_res->hw_res[1] = csid_acquire.node_res;
-	}
-	cid_res->parent = &ife_ctx->res_list_ife_in;
-	ife_ctx->res_list_ife_in.child[
-		ife_ctx->res_list_ife_in.num_children++] = cid_res;
-
-	return 0;
-err:
-	return rc;
-
-}
 static int cam_ife_mgr_acquire_hw_for_ctx(
 	struct cam_ife_hw_mgr_ctx          *ife_ctx,
 	struct cam_isp_in_port_info        *in_port,
@@ -1229,7 +1247,6 @@
 	int is_dual_vfe                           = 0;
 	int pixel_count                           = 0;
 	int rdi_count                             = 0;
-	uint32_t                                cid_res_id = 0;
 
 	is_dual_vfe = in_port->usage_type;
 
@@ -1248,18 +1265,9 @@
 		return -EINVAL;
 	}
 
-	/* get cid resource */
-	rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res_id,
-		pixel_count);
-	if (rc) {
-		CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed");
-		goto err;
-	}
-
 	if (pixel_count) {
 		/* get ife csid IPP resrouce */
-		rc = cam_ife_hw_mgr_acquire_res_ife_csid_ipp(ife_ctx, in_port,
-				cid_res_id);
+		rc = cam_ife_hw_mgr_acquire_res_ife_csid_ipp(ife_ctx, in_port);
 		if (rc) {
 			CAM_ERR(CAM_ISP,
 				"Acquire IFE CSID IPP resource Failed");
@@ -1269,8 +1277,7 @@
 
 	if (rdi_count) {
 		/* get ife csid rdi resource */
-		rc = cam_ife_hw_mgr_acquire_res_ife_csid_rdi(ife_ctx, in_port,
-			cid_res_id);
+		rc = cam_ife_hw_mgr_acquire_res_ife_csid_rdi(ife_ctx, in_port);
 		if (rc) {
 			CAM_ERR(CAM_ISP,
 				"Acquire IFE CSID RDI resource Failed");
@@ -2488,6 +2495,53 @@
 	return rc;
 }
 
+static int cam_ife_mgr_bw_control(struct cam_ife_hw_mgr_ctx *ctx,
+	enum cam_vfe_bw_control_action action)
+{
+	struct cam_ife_hw_mgr_res             *hw_mgr_res;
+	struct cam_hw_intf                    *hw_intf;
+	struct cam_vfe_bw_control_args         bw_ctrl_args;
+	int                                    rc = -EINVAL;
+	uint32_t                               i;
+
+	CAM_DBG(CAM_ISP, "Enter...ctx id:%d", ctx->ctx_index);
+
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+			if (!hw_mgr_res->hw_res[i])
+				continue;
+
+			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+			if (hw_intf && hw_intf->hw_ops.process_cmd) {
+				bw_ctrl_args.node_res =
+					hw_mgr_res->hw_res[i];
+				bw_ctrl_args.action = action;
+
+				rc = hw_intf->hw_ops.process_cmd(
+					hw_intf->hw_priv,
+					CAM_ISP_HW_CMD_BW_CONTROL,
+					&bw_ctrl_args,
+					sizeof(struct cam_vfe_bw_control_args));
+				if (rc)
+					CAM_ERR(CAM_ISP, "BW Update failed");
+			} else
+				CAM_WARN(CAM_ISP, "NULL hw_intf!");
+		}
+	}
+
+	return rc;
+}
+
+static int cam_ife_mgr_pause_hw(struct cam_ife_hw_mgr_ctx *ctx)
+{
+	return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_EXCLUDE);
+}
+
+static int cam_ife_mgr_resume_hw(struct cam_ife_hw_mgr_ctx *ctx)
+{
+	return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_INCLUDE);
+}
+
 static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 {
 	int rc = 0;
@@ -2513,6 +2567,12 @@
 			hw_cmd_args->u.is_rdi_only_context = 0;
 
 		break;
+	case CAM_ISP_HW_MGR_CMD_PAUSE_HW:
+		cam_ife_mgr_pause_hw(ctx);
+		break;
+	case CAM_ISP_HW_MGR_CMD_RESUME_HW:
+		cam_ife_mgr_resume_hw(ctx);
+		break;
 	default:
 		CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x",
 			hw_cmd_args->cmd_type);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
index cf044eb..56f2d68 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -130,6 +130,8 @@
 /* enum cam_isp_hw_mgr_command - Hardware manager command type */
 enum cam_isp_hw_mgr_command {
 	CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT,
+	CAM_ISP_HW_MGR_CMD_PAUSE_HW,
+	CAM_ISP_HW_MGR_CMD_RESUME_HW,
 	CAM_ISP_HW_MGR_CMD_MAX,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index bce0374..ff0c91f 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -287,7 +287,7 @@
 
 static int cam_ife_csid_cid_get(struct cam_ife_csid_hw *csid_hw,
 	struct cam_isp_resource_node **res, int32_t vc, uint32_t dt,
-	uint32_t res_type, int pixel_count)
+	uint32_t res_type)
 {
 	int  rc = 0;
 	struct cam_ife_csid_cid_data    *cid_data;
@@ -305,8 +305,7 @@
 					break;
 				}
 			} else {
-				if (cid_data->vc == vc && cid_data->dt == dt &&
-					cid_data->pixel_count == pixel_count) {
+				if (cid_data->vc == vc && cid_data->dt == dt) {
 					cid_data->cnt++;
 					*res = &csid_hw->cid_res[i];
 					break;
@@ -330,7 +329,6 @@
 				cid_data->vc  = vc;
 				cid_data->dt  = dt;
 				cid_data->cnt = 1;
-				cid_data->pixel_count = pixel_count;
 				csid_hw->cid_res[j].res_state =
 					CAM_ISP_RESOURCE_STATE_RESERVED;
 				*res = &csid_hw->cid_res[j];
@@ -570,7 +568,6 @@
 	struct cam_csid_hw_reserve_resource_args  *cid_reserv)
 {
 	int rc = 0;
-	uint32_t i;
 	struct cam_ife_csid_cid_data       *cid_data;
 
 	CAM_DBG(CAM_ISP,
@@ -728,7 +725,6 @@
 		cid_data->vc = cid_reserv->in_port->vc;
 		cid_data->dt = cid_reserv->in_port->dt;
 		cid_data->cnt = 1;
-		cid_data->pixel_count = cid_reserv->pixel_count;
 		cid_reserv->node_res = &csid_hw->cid_res[0];
 		csid_hw->csi2_reserve_cnt++;
 
@@ -737,27 +733,43 @@
 			csid_hw->hw_intf->hw_idx,
 			cid_reserv->node_res->res_id);
 	} else {
-		if (cid_reserv->pixel_count > 0) {
-			for (i = 0; i < CAM_IFE_CSID_CID_RES_MAX; i++) {
-				cid_data = (struct cam_ife_csid_cid_data *)
-					csid_hw->cid_res[i].res_priv;
-				if ((csid_hw->cid_res[i].res_state >=
-					CAM_ISP_RESOURCE_STATE_RESERVED) &&
-					cid_data->pixel_count > 0) {
-					CAM_DBG(CAM_ISP,
-						"CSID:%d IPP resource is full");
-					rc = -EINVAL;
-					goto end;
-				}
+		switch (cid_reserv->res_id) {
+		case CAM_IFE_PIX_PATH_RES_IPP:
+			if (csid_hw->ipp_res.res_state !=
+				CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+				CAM_DBG(CAM_ISP,
+					"CSID:%d IPP resource not available",
+					csid_hw->hw_intf->hw_idx);
+				rc = -EINVAL;
+				goto end;
 			}
+			break;
+		case CAM_IFE_PIX_PATH_RES_RDI_0:
+		case CAM_IFE_PIX_PATH_RES_RDI_1:
+		case CAM_IFE_PIX_PATH_RES_RDI_2:
+		case CAM_IFE_PIX_PATH_RES_RDI_3:
+			if (csid_hw->rdi_res[cid_reserv->res_id].res_state !=
+				CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+				CAM_DBG(CAM_ISP,
+					"CSID:%d RDI:%d resource not available",
+					csid_hw->hw_intf->hw_idx,
+					cid_reserv->res_id);
+				rc = -EINVAL;
+				goto end;
+			}
+			break;
+		default:
+			CAM_ERR(CAM_ISP, "CSID%d: Invalid csid path",
+				csid_hw->hw_intf->hw_idx);
+			rc = -EINVAL;
+			goto end;
 		}
 
 		rc = cam_ife_csid_cid_get(csid_hw,
 			&cid_reserv->node_res,
 			cid_reserv->in_port->vc,
 			cid_reserv->in_port->dt,
-			cid_reserv->in_port->res_type,
-			cid_reserv->pixel_count);
+			cid_reserv->in_port->res_type);
 		/* if success then increment the reserve count */
 		if (!rc) {
 			if (csid_hw->csi2_reserve_cnt == UINT_MAX) {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
index b400d14..4b546ea 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -368,7 +368,6 @@
 	uint32_t                     dt;
 	uint32_t                     cnt;
 	uint32_t                     tpg_set;
-	int                          pixel_count;
 };
 
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
index df97bd6..ceeacbe 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -75,7 +75,6 @@
  * @cid:          cid (DT_ID) value for path, this is applicable for CSID path
  *                reserve
  * @node_res :    Reserved resource structure pointer
- * @pixel_count:  Number of pixel resources
  *
  */
 struct cam_csid_hw_reserve_resource_args {
@@ -87,7 +86,6 @@
 	uint32_t                                  master_idx;
 	uint32_t                                  cid;
 	struct cam_isp_resource_node             *node_res;
-	int                                       pixel_count;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
index 257a5ac..b9f6d77 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -92,6 +92,7 @@
 	CAM_ISP_HW_CMD_STRIPE_UPDATE,
 	CAM_ISP_HW_CMD_CLOCK_UPDATE,
 	CAM_ISP_HW_CMD_BW_UPDATE,
+	CAM_ISP_HW_CMD_BW_CONTROL,
 	CAM_ISP_HW_CMD_MAX,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
index b771ec6..8927d6a 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -185,6 +185,22 @@
 	uint64_t                           external_bw_bytes;
 };
 
+enum cam_vfe_bw_control_action {
+	CAM_VFE_BW_CONTROL_EXCLUDE       = 0,
+	CAM_VFE_BW_CONTROL_INCLUDE       = 1
+};
+
+/*
+ * struct cam_vfe_bw_control_args:
+ *
+ * @node_res:             Resource to get the time stamp
+ * @action:               Bandwidth control action
+ */
+struct cam_vfe_bw_control_args {
+	struct cam_isp_resource_node      *node_res;
+	enum cam_vfe_bw_control_action     action;
+};
+
 /*
  * struct cam_vfe_top_irq_evt_payload:
  *
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
index 02fec28..2c4fe9d 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -697,6 +697,7 @@
 	case CAM_ISP_HW_CMD_GET_REG_UPDATE:
 	case CAM_ISP_HW_CMD_CLOCK_UPDATE:
 	case CAM_ISP_HW_CMD_BW_UPDATE:
+	case CAM_ISP_HW_CMD_BW_CONTROL:
 		rc = core_info->vfe_top->hw_ops.process_cmd(
 			core_info->vfe_top->top_priv, cmd_type, cmd_args,
 			arg_size);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
index f166025..842cfc7 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,9 @@
 	struct cam_isp_resource_node        mux_rsrc[CAM_VFE_TOP_VER2_MUX_MAX];
 	unsigned long                       hw_clk_rate;
 	struct cam_axi_vote                 hw_axi_vote;
+	enum cam_vfe_bw_control_action      axi_vote_control[
+						CAM_VFE_TOP_VER2_MUX_MAX];
+
 	struct cam_axi_vote             req_axi_vote[CAM_VFE_TOP_VER2_MUX_MAX];
 	unsigned long                   req_clk_rate[CAM_VFE_TOP_VER2_MUX_MAX];
 };
@@ -134,10 +137,13 @@
 	}
 
 	for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
-		sum.uncompressed_bw +=
-			top_priv->req_axi_vote[i].uncompressed_bw;
-		sum.compressed_bw +=
-			top_priv->req_axi_vote[i].compressed_bw;
+		if (top_priv->axi_vote_control[i] ==
+			CAM_VFE_BW_CONTROL_INCLUDE) {
+			sum.uncompressed_bw +=
+				top_priv->req_axi_vote[i].uncompressed_bw;
+			sum.compressed_bw +=
+				top_priv->req_axi_vote[i].compressed_bw;
+		}
 	}
 
 	CAM_DBG(CAM_ISP, "BW Vote: u=%lld c=%lld",
@@ -239,6 +245,8 @@
 				bw_update->camnoc_bw_bytes;
 			top_priv->req_axi_vote[i].compressed_bw =
 				bw_update->external_bw_bytes;
+			top_priv->axi_vote_control[i] =
+				CAM_VFE_BW_CONTROL_INCLUDE;
 			break;
 		}
 	}
@@ -253,6 +261,50 @@
 	return rc;
 }
 
+static int cam_vfe_top_bw_control(
+	struct cam_vfe_top_ver2_priv *top_priv,
+	 void *cmd_args, uint32_t arg_size)
+{
+	struct cam_vfe_bw_control_args       *bw_ctrl = NULL;
+	struct cam_isp_resource_node         *res = NULL;
+	struct cam_hw_info                   *hw_info = NULL;
+	int                                   rc = 0;
+	int                                   i;
+
+	bw_ctrl = (struct cam_vfe_bw_control_args *)cmd_args;
+	res = bw_ctrl->node_res;
+
+	if (!res || !res->hw_intf->hw_priv)
+		return -EINVAL;
+
+	hw_info = res->hw_intf->hw_priv;
+
+	if (res->res_type != CAM_ISP_RESOURCE_VFE_IN ||
+		res->res_id >= CAM_ISP_HW_VFE_IN_MAX) {
+		CAM_ERR(CAM_ISP, "VFE:%d Invalid res_type:%d res id%d",
+			res->hw_intf->hw_idx, res->res_type,
+			res->res_id);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
+		if (top_priv->mux_rsrc[i].res_id == res->res_id) {
+			top_priv->axi_vote_control[i] = bw_ctrl->action;
+			break;
+		}
+	}
+
+	if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
+		CAM_DBG(CAM_ISP, "VFE:%d Not ready to set BW yet :%d",
+			res->hw_intf->hw_idx,
+			hw_info->hw_state);
+	} else {
+		rc = cam_vfe_top_set_axi_bw_vote(top_priv);
+	}
+
+	return rc;
+}
+
 static int cam_vfe_top_mux_get_reg_update(
 	struct cam_vfe_top_ver2_priv *top_priv,
 	void *cmd_args, uint32_t arg_size)
@@ -458,6 +510,8 @@
 				top_priv->req_clk_rate[i] = 0;
 				top_priv->req_axi_vote[i].compressed_bw = 0;
 				top_priv->req_axi_vote[i].uncompressed_bw = 0;
+				top_priv->axi_vote_control[i] =
+					CAM_VFE_BW_CONTROL_EXCLUDE;
 				break;
 			}
 		}
@@ -518,6 +572,9 @@
 		rc = cam_vfe_top_bw_update(top_priv, cmd_args,
 			arg_size);
 		break;
+	case CAM_ISP_HW_CMD_BW_CONTROL:
+		rc = cam_vfe_top_bw_control(top_priv, cmd_args, arg_size);
+		break;
 	default:
 		rc = -EINVAL;
 		CAM_ERR(CAM_ISP, "Error! Invalid cmd:%d", cmd_type);
@@ -565,6 +622,8 @@
 		top_priv->req_clk_rate[i] = 0;
 		top_priv->req_axi_vote[i].compressed_bw = 0;
 		top_priv->req_axi_vote[i].uncompressed_bw = 0;
+		top_priv->axi_vote_control[i] = CAM_VFE_BW_CONTROL_EXCLUDE;
+
 
 		if (ver2_hw_info->mux_type[i] == CAM_VFE_CAMIF_VER_2_0) {
 			top_priv->mux_rsrc[i].res_id =
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
index bb952e6..21e66a2 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
@@ -68,6 +68,10 @@
 		cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd,
 			hw_info->bus_rd_reg.bus_client_reg[index].unpack_cfg_0,
 			0x1);
+	else if (io_buf->io_cfg->format == CAM_FORMAT_PLAIN16_10)
+		cam_lrme_cdm_write_reg_val_pair(reg_val_pair, num_cmd,
+			hw_info->bus_rd_reg.bus_client_reg[index].unpack_cfg_0,
+			0x22);
 	else
 		CAM_ERR(CAM_LRME, "Unsupported format %d",
 			io_buf->io_cfg->format);
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index d7662f1..92f708b 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -2607,9 +2607,12 @@
 int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control)
 {
 	int                               rc = 0;
-	int                               i;
+	int                               i, j;
 	struct cam_req_mgr_core_link     *link = NULL;
 
+	struct cam_req_mgr_connected_device *dev = NULL;
+	struct cam_req_mgr_link_evt_data     evt_data;
+
 	if (!control) {
 		CAM_ERR(CAM_CRM, "Control command is NULL");
 		rc = -EINVAL;
@@ -2639,9 +2642,29 @@
 					link->link_hdl);
 				rc = -EFAULT;
 			}
+			/* notify nodes */
+			for (j = 0; j < link->num_devs; j++) {
+				dev = &link->l_dev[j];
+				evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_RESUME;
+				evt_data.link_hdl =  link->link_hdl;
+				evt_data.dev_hdl = dev->dev_hdl;
+				evt_data.req_id = 0;
+				if (dev->ops && dev->ops->process_evt)
+					dev->ops->process_evt(&evt_data);
+			}
 		} else if (control->ops == CAM_REQ_MGR_LINK_DEACTIVATE) {
 			/* Destroy SOF watchdog timer */
 			crm_timer_exit(&link->watchdog);
+			/* notify nodes */
+			for (j = 0; j < link->num_devs; j++) {
+				dev = &link->l_dev[j];
+				evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_PAUSE;
+				evt_data.link_hdl =  link->link_hdl;
+				evt_data.dev_hdl = dev->dev_hdl;
+				evt_data.req_id = 0;
+				if (dev->ops && dev->ops->process_evt)
+					dev->ops->process_evt(&evt_data);
+			}
 		} else {
 			CAM_ERR(CAM_CRM, "Invalid link control command");
 			rc = -EINVAL;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
index ce8dfa7..45ebc69 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
@@ -81,9 +81,9 @@
  * @process_evt  : payload to generic event
  */
 struct cam_req_mgr_kmd_ops {
-	cam_req_mgr_get_dev_info      get_dev_info;
-	cam_req_mgr_link_setup        link_setup;
-	cam_req_mgr_apply_req         apply_req;
+	cam_req_mgr_get_dev_info     get_dev_info;
+	cam_req_mgr_link_setup       link_setup;
+	cam_req_mgr_apply_req        apply_req;
 	cam_req_mgr_flush_req        flush_req;
 	cam_req_mgr_process_evt      process_evt;
 };
@@ -182,6 +182,8 @@
  */
 enum cam_req_mgr_link_evt_type {
 	CAM_REQ_MGR_LINK_EVT_ERR,
+	CAM_REQ_MGR_LINK_EVT_PAUSE,
+	CAM_REQ_MGR_LINK_EVT_RESUME,
 	CAM_REQ_MGR_LINK_EVT_MAX,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index 9894ca3..d5bb1b0 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -191,14 +191,16 @@
 			CAM_ERR(CAM_SENSOR,
 				"Already some pkt in offset req : %lld",
 				csl_packet->header.request_id);
-			rc = delete_request(i2c_reg_settings);
-			if (rc < 0) {
-				CAM_ERR(CAM_SENSOR,
-				"Failed in Deleting the err: %d", rc);
-				return rc;
-			}
+			/*
+			 * Update req mgr even in case of failure.
+			 * This will help not to wait indefinitely
+			 * and freeze. If this log is triggered then
+			 * fix it.
+			 */
+			cam_sensor_update_req_mgr(s_ctrl, csl_packet);
+			return 0;
 		}
-	break;
+		break;
 	}
 	case CAM_SENSOR_PACKET_OPCODE_SENSOR_NOP: {
 		if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) ||
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c
index 7a6d7fd..89aad4e 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_io.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -98,6 +98,11 @@
 		return -EINVAL;
 	}
 
+	if (!write_setting->reg_setting) {
+		CAM_ERR(CAM_SENSOR, "Invalid Register Settings");
+		return -EINVAL;
+	}
+
 	if (io_master_info->master_type == CCI_MASTER) {
 		return cam_cci_i2c_write_table(io_master_info,
 			write_setting);
@@ -125,6 +130,11 @@
 		return -EINVAL;
 	}
 
+	if (!write_setting->reg_setting) {
+		CAM_ERR(CAM_SENSOR, "Invalid Register Settings");
+		return -EINVAL;
+	}
+
 	if (io_master_info->master_type == CCI_MASTER) {
 		return cam_cci_i2c_write_continuous_table(io_master_info,
 			write_setting, cam_sensor_i2c_write_flag);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
index 72ca737..622dae6 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -26,7 +26,7 @@
 #define MAX_REGULATOR 5
 #define MAX_POWER_CONFIG 12
 
-#define MAX_PER_FRAME_ARRAY 8
+#define MAX_PER_FRAME_ARRAY 32
 
 #define CAM_SENSOR_NAME    "cam-sensor"
 #define CAM_ACTUATOR_NAME  "cam-actuator"
diff --git a/drivers/mmc/host/cmdq_hci.c b/drivers/mmc/host/cmdq_hci.c
index 55ce946..01811d9 100644
--- a/drivers/mmc/host/cmdq_hci.c
+++ b/drivers/mmc/host/cmdq_hci.c
@@ -357,7 +357,7 @@
 	if (!cq_host->desc_base || !cq_host->trans_desc_base)
 		return -ENOMEM;
 
-	pr_info("desc-base: 0x%p trans-base: 0x%p\n desc_dma 0x%llx trans_dma: 0x%llx\n",
+	pr_debug("desc-base: 0x%pK trans-base: 0x%pK\n desc_dma 0x%llx trans_dma: 0x%llx\n",
 		 cq_host->desc_base, cq_host->trans_desc_base,
 		(unsigned long long)cq_host->desc_dma_base,
 		(unsigned long long) cq_host->trans_desc_dma_base);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 0d6f263..5ed9b72 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -4237,11 +4237,10 @@
 		group->latency = PM_QOS_DEFAULT_VALUE;
 		pm_qos_add_request(&group->req, PM_QOS_CPU_DMA_LATENCY,
 			group->latency);
-		pr_info("%s (): voted for group #%d (mask=0x%lx) latency=%d (0x%p)\n",
+		pr_info("%s (): voted for group #%d (mask=0x%lx) latency=%d\n",
 			__func__, i,
 			group->req.cpus_affine.bits[0],
-			group->latency,
-			&latency[i].latency[SDHCI_PERFORMANCE_MODE]);
+			group->latency);
 	}
 	msm_host->pm_qos_prev_cpu = -1;
 	msm_host->pm_qos_group_enable = true;
@@ -4808,8 +4807,6 @@
 			goto vreg_deinit;
 		}
 		writel_relaxed(readl_relaxed(tlmm_mem) | 0x2, tlmm_mem);
-		dev_dbg(&pdev->dev, "tlmm reg %pa value 0x%08x\n",
-				&tlmm_memres->start, readl_relaxed(tlmm_mem));
 	}
 
 	/*
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 566be69..b674b38 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -3068,13 +3068,13 @@
 		struct sdhci_adma2_64_desc *dma_desc = desc;
 
 		if (host->flags & SDHCI_USE_64_BIT_DMA)
-			DBG("%s: %p: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n",
+			DBG("%s: %pK: DMA 0x%08x%08x, LEN 0x%04x,Attr=0x%02x\n",
 			    name, desc, le32_to_cpu(dma_desc->addr_hi),
 			    le32_to_cpu(dma_desc->addr_lo),
 			    le16_to_cpu(dma_desc->len),
 			    le16_to_cpu(dma_desc->cmd));
 		else
-			DBG("%s: %p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
+			DBG("%s: %pK: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n",
 			    name, desc, le32_to_cpu(dma_desc->addr_lo),
 			    le16_to_cpu(dma_desc->len),
 			    le16_to_cpu(dma_desc->cmd));
diff --git a/drivers/nfc/nq-nci.c b/drivers/nfc/nq-nci.c
index ea4bedf..59197d1 100644
--- a/drivers/nfc/nq-nci.c
+++ b/drivers/nfc/nq-nci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -469,39 +469,43 @@
 		dev_dbg(&nqx_dev->client->dev,
 			"gpio_set_value disable: %s: info: %p\n",
 			__func__, nqx_dev);
-		if (gpio_is_valid(nqx_dev->firm_gpio))
+		if (gpio_is_valid(nqx_dev->firm_gpio)) {
 			gpio_set_value(nqx_dev->firm_gpio, 0);
+			usleep_range(10000, 10100);
+		}
 
 		if (gpio_is_valid(nqx_dev->ese_gpio)) {
 			if (!gpio_get_value(nqx_dev->ese_gpio)) {
 				dev_dbg(&nqx_dev->client->dev, "disabling en_gpio\n");
 				gpio_set_value(nqx_dev->en_gpio, 0);
+				usleep_range(10000, 10100);
 			} else {
 				dev_dbg(&nqx_dev->client->dev, "keeping en_gpio high\n");
 			}
 		} else {
 			dev_dbg(&nqx_dev->client->dev, "ese_gpio invalid, set en_gpio to low\n");
 			gpio_set_value(nqx_dev->en_gpio, 0);
+			usleep_range(10000, 10100);
 		}
 		r = nqx_clock_deselect(nqx_dev);
 		if (r < 0)
 			dev_err(&nqx_dev->client->dev, "unable to disable clock\n");
 		nqx_dev->nfc_ven_enabled = false;
-		/* hardware dependent delay */
-		msleep(100);
 	} else if (arg == 1) {
 		nqx_enable_irq(nqx_dev);
 		dev_dbg(&nqx_dev->client->dev,
 			"gpio_set_value enable: %s: info: %p\n",
 			__func__, nqx_dev);
-		if (gpio_is_valid(nqx_dev->firm_gpio))
+		if (gpio_is_valid(nqx_dev->firm_gpio)) {
 			gpio_set_value(nqx_dev->firm_gpio, 0);
+			usleep_range(10000, 10100);
+		}
 		gpio_set_value(nqx_dev->en_gpio, 1);
+		usleep_range(10000, 10100);
 		r = nqx_clock_select(nqx_dev);
 		if (r < 0)
 			dev_err(&nqx_dev->client->dev, "unable to enable clock\n");
 		nqx_dev->nfc_ven_enabled = true;
-		msleep(20);
 	} else if (arg == 2) {
 		/*
 		 * We are switching to Dowload Mode, toggle the enable pin
@@ -515,14 +519,15 @@
 			}
 		}
 		gpio_set_value(nqx_dev->en_gpio, 1);
-		msleep(20);
-		if (gpio_is_valid(nqx_dev->firm_gpio))
+		usleep_range(10000, 10100);
+		if (gpio_is_valid(nqx_dev->firm_gpio)) {
 			gpio_set_value(nqx_dev->firm_gpio, 1);
-		msleep(20);
+			usleep_range(10000, 10100);
+		}
 		gpio_set_value(nqx_dev->en_gpio, 0);
-		msleep(100);
+		usleep_range(10000, 10100);
 		gpio_set_value(nqx_dev->en_gpio, 1);
-		msleep(20);
+		usleep_range(10000, 10100);
 	} else {
 		r = -ENOIOCTLCMD;
 	}
@@ -648,13 +653,14 @@
 	unsigned char nci_reset_rsp[6];
 	unsigned char init_rsp_len = 0;
 	unsigned int enable_gpio = nqx_dev->en_gpio;
+
 	/* making sure that the NFCC starts in a clean state. */
 	gpio_set_value(enable_gpio, 0);/* ULPM: Disable */
 	/* hardware dependent delay */
-	msleep(20);
+	usleep_range(10000, 10100);
 	gpio_set_value(enable_gpio, 1);/* HPD : Enable*/
 	/* hardware dependent delay */
-	msleep(20);
+	usleep_range(10000, 10100);
 
 	/* send NCI CORE RESET CMD with Keep Config parameters */
 	ret = i2c_master_send(client, raw_nci_reset_cmd,
@@ -670,21 +676,17 @@
 	/* Read Response of RESET command */
 	ret = i2c_master_recv(client, nci_reset_rsp,
 		sizeof(nci_reset_rsp));
-	dev_err(&client->dev,
-	"%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n",
-	__func__, nci_reset_rsp[0],
-	nci_reset_rsp[1], nci_reset_rsp[2]);
 	if (ret < 0) {
 		dev_err(&client->dev,
 		"%s: - i2c_master_recv Error\n", __func__);
 		goto err_nfcc_hw_check;
 	}
-	ret = i2c_master_send(client, raw_nci_init_cmd,
-		sizeof(raw_nci_init_cmd));
+	ret = nqx_standby_write(nqx_dev, raw_nci_init_cmd,
+				sizeof(raw_nci_init_cmd));
 	if (ret < 0) {
 		dev_err(&client->dev,
 		"%s: - i2c_master_send Error\n", __func__);
-		goto err_nfcc_hw_check;
+		goto err_nfcc_core_init_fail;
 	}
 	/* hardware dependent delay */
 	msleep(30);
@@ -694,7 +696,7 @@
 	if (ret < 0) {
 		dev_err(&client->dev,
 		"%s: - i2c_master_recv Error\n", __func__);
-		goto err_nfcc_hw_check;
+		goto err_nfcc_core_init_fail;
 	}
 	init_rsp_len = 2 + nci_init_rsp[2]; /*payload + len*/
 	if (init_rsp_len > PAYLOAD_HEADER_LENGTH) {
@@ -707,6 +709,11 @@
 		nqx_dev->nqx_info.info.fw_minor =
 				nci_init_rsp[init_rsp_len];
 	}
+	dev_dbg(&client->dev,
+		"%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n",
+		__func__, nci_reset_rsp[0],
+		nci_reset_rsp[1], nci_reset_rsp[2]);
+
 	dev_dbg(&nqx_dev->client->dev, "NQ NFCC chip_type = %x\n",
 		nqx_dev->nqx_info.info.chip_type);
 	dev_dbg(&nqx_dev->client->dev, "NQ fw version = %x.%x.%x\n",
@@ -746,6 +753,12 @@
 	ret = 0;
 	goto done;
 
+err_nfcc_core_init_fail:
+	dev_err(&client->dev,
+	"%s: - nq - reset cmd answer : NfcNciRx %x %x %x\n",
+	__func__, nci_reset_rsp[0],
+	nci_reset_rsp[1], nci_reset_rsp[2]);
+
 err_nfcc_hw_check:
 	ret = -ENXIO;
 	dev_err(&client->dev,
@@ -1213,6 +1226,7 @@
 		.owner = THIS_MODULE,
 		.name = "nq-nci",
 		.of_match_table = msm_match_table,
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
 		.pm = &nfc_pm_ops,
 	},
 };
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index d39a17f..6515ce4 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -89,6 +89,16 @@
 	  Technologies Inc MSM8953 platform.
 	  If unsure say N.
 
+config PINCTRL_MSM8937
+	tristate "Qualcomm Technologies Inc MSM8937 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 MSM8937 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 d92db11..db71677 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -12,6 +12,7 @@
 obj-$(CONFIG_PINCTRL_QDF2XXX)	+= pinctrl-qdf2xxx.o
 obj-$(CONFIG_PINCTRL_MDM9615)	+= pinctrl-mdm9615.o
 obj-$(CONFIG_PINCTRL_MSM8953)   += pinctrl-msm8953.o
+obj-$(CONFIG_PINCTRL_MSM8937)   += pinctrl-msm8937.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-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index bf95849..1441678 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2013, Sony Mobile Communications AB.
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -70,6 +70,7 @@
 
 	const struct msm_pinctrl_soc_data *soc;
 	void __iomem *regs;
+	void __iomem *pdc_regs;
 };
 
 static int msm_get_groups_count(struct pinctrl_dev *pctldev)
@@ -777,6 +778,102 @@
 	.irq_set_wake   = msm_gpio_irq_set_wake,
 };
 
+static struct irq_chip msm_dirconn_irq_chip;
+
+static void msm_gpio_dirconn_handler(struct irq_desc *desc)
+{
+	struct irq_data *irqd = irq_desc_get_handler_data(desc);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+
+	chained_irq_enter(chip, desc);
+	generic_handle_irq(irqd->irq);
+	chained_irq_exit(chip, desc);
+}
+
+static void setup_pdc_gpio(struct irq_domain *domain,
+			unsigned int parent_irq, unsigned int gpio)
+{
+	int irq;
+
+	if (gpio != 0) {
+		irq = irq_find_mapping(domain, gpio);
+		irq_set_parent(irq, parent_irq);
+		irq_set_chip(irq, &msm_dirconn_irq_chip);
+		irq_set_handler_data(parent_irq, irq_get_irq_data(irq));
+	}
+
+	__irq_set_handler(parent_irq, msm_gpio_dirconn_handler, false, NULL);
+}
+
+static void request_dc_interrupt(struct irq_domain *domain,
+			struct irq_domain *parent, irq_hw_number_t hwirq,
+			unsigned int gpio)
+{
+	struct irq_fwspec fwspec;
+	unsigned int parent_irq;
+
+	fwspec.fwnode = parent->fwnode;
+	fwspec.param[0] = 0; /* SPI */
+	fwspec.param[1] = hwirq;
+	fwspec.param[2] = IRQ_TYPE_NONE;
+	fwspec.param_count = 3;
+
+	parent_irq = irq_create_fwspec_mapping(&fwspec);
+
+	setup_pdc_gpio(domain, parent_irq, gpio);
+}
+
+/**
+ * gpio_muxed_to_pdc: Mux the GPIO to a PDC IRQ
+ *
+ * @pdc_domain: the PDC's domain
+ * @d: the GPIO's IRQ data
+ *
+ * Find a free PDC port for the GPIO and map the GPIO's mux information to the
+ * PDC registers; so the GPIO can be used a wakeup source.
+ */
+static void gpio_muxed_to_pdc(struct irq_domain *pdc_domain, struct irq_data *d)
+{
+	int i, j;
+	unsigned int mux;
+	struct irq_desc *desc = irq_data_to_desc(d);
+	struct irq_data *parent_data = irq_get_irq_data(desc->parent_irq);
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	unsigned int gpio = d->hwirq;
+	struct msm_pinctrl *pctrl;
+	unsigned int irq;
+
+	if (!gc || !parent_data)
+		return;
+
+	pctrl = gpiochip_get_data(gc);
+
+	for (i = 0; i < pctrl->soc->n_gpio_mux_in; i++) {
+		if (gpio != pctrl->soc->gpio_mux_in[i].gpio)
+			continue;
+		mux = pctrl->soc->gpio_mux_in[i].mux;
+		for (j = 0; j < pctrl->soc->n_pdc_mux_out; j++) {
+			struct msm_pdc_mux_output *pdc_out =
+						&pctrl->soc->pdc_mux_out[j];
+
+			if (pdc_out->mux == mux)
+				break;
+			if (pdc_out->mux)
+				continue;
+			pdc_out->mux = gpio;
+			irq = irq_find_mapping(pdc_domain, pdc_out->hwirq + 32);
+			/* setup the IRQ parent for the GPIO */
+			setup_pdc_gpio(pctrl->chip.irqdomain, irq, gpio);
+			/* program pdc select grp register */
+			writel_relaxed((mux & 0x3F), pctrl->pdc_regs +
+				(0x14 * j));
+			break;
+		}
+		/* We have no more PDC port available */
+		WARN_ON(j == pctrl->soc->n_pdc_mux_out);
+	}
+}
+
 static bool is_gpio_dual_edge(struct irq_data *d, irq_hw_number_t *dir_conn_irq)
 {
 	struct irq_desc *desc = irq_data_to_desc(d);
@@ -797,6 +894,17 @@
 			return true;
 		}
 	}
+
+	for (i = 0; i < pctrl->soc->n_pdc_mux_out; i++) {
+		struct msm_pdc_mux_output *dir_conn =
+					&pctrl->soc->pdc_mux_out[i];
+
+		if (dir_conn->mux == d->hwirq && (dir_conn->hwirq + 32)
+				!= parent_data->hwirq) {
+			*dir_conn_irq = dir_conn->hwirq + 32;
+			return true;
+		}
+	}
 	return false;
 }
 
@@ -814,13 +922,48 @@
 			irq_get_irq_data(irq_find_mapping(parent_data->domain,
 						dir_conn_irq));
 
-		if (dir_conn_data && dir_conn_data->chip->irq_mask)
+		if (!dir_conn_data)
+			return;
+		if (dir_conn_data->chip->irq_mask)
 			dir_conn_data->chip->irq_mask(dir_conn_data);
 	}
+
 	if (parent_data->chip->irq_mask)
 		parent_data->chip->irq_mask(parent_data);
 }
 
+static void msm_dirconn_irq_enable(struct irq_data *d)
+{
+	struct irq_desc *desc = irq_data_to_desc(d);
+	struct irq_data *parent_data = irq_get_irq_data(desc->parent_irq);
+	irq_hw_number_t dir_conn_irq = 0;
+
+	if (!parent_data)
+		return;
+
+	if (is_gpio_dual_edge(d, &dir_conn_irq)) {
+		struct irq_data *dir_conn_data =
+			irq_get_irq_data(irq_find_mapping(parent_data->domain,
+						dir_conn_irq));
+
+		if (dir_conn_data &&
+				dir_conn_data->chip->irq_set_irqchip_state)
+			dir_conn_data->chip->irq_set_irqchip_state(
+					dir_conn_data,
+					IRQCHIP_STATE_PENDING, 0);
+
+		if (dir_conn_data && dir_conn_data->chip->irq_unmask)
+			dir_conn_data->chip->irq_unmask(dir_conn_data);
+	}
+
+	if (parent_data->chip->irq_set_irqchip_state)
+		parent_data->chip->irq_set_irqchip_state(parent_data,
+						IRQCHIP_STATE_PENDING, 0);
+
+	if (parent_data->chip->irq_unmask)
+		parent_data->chip->irq_unmask(parent_data);
+}
+
 static void msm_dirconn_irq_unmask(struct irq_data *d)
 {
 	struct irq_desc *desc = irq_data_to_desc(d);
@@ -835,7 +978,9 @@
 			irq_get_irq_data(irq_find_mapping(parent_data->domain,
 						dir_conn_irq));
 
-		if (dir_conn_data && dir_conn_data->chip->irq_unmask)
+		if (!dir_conn_data)
+			return;
+		if (dir_conn_data->chip->irq_unmask)
 			dir_conn_data->chip->irq_unmask(dir_conn_data);
 	}
 	if (parent_data->chip->irq_unmask)
@@ -1058,6 +1203,7 @@
 static struct irq_chip msm_dirconn_irq_chip = {
 	.name			= "msmgpio-dc",
 	.irq_mask		= msm_dirconn_irq_mask,
+	.irq_enable		= msm_dirconn_irq_enable,
 	.irq_unmask		= msm_dirconn_irq_unmask,
 	.irq_eoi		= msm_dirconn_irq_eoi,
 	.irq_ack		= msm_dirconn_irq_ack,
@@ -1103,57 +1249,53 @@
 	chained_irq_exit(chip, desc);
 }
 
-static void msm_gpio_dirconn_handler(struct irq_desc *desc)
-{
-	struct irq_data *irqd = irq_desc_get_handler_data(desc);
-	struct irq_chip *chip = irq_desc_get_chip(desc);
-
-	chained_irq_enter(chip, desc);
-	generic_handle_irq(irqd->irq);
-	chained_irq_exit(chip, desc);
-}
-
 static void msm_gpio_setup_dir_connects(struct msm_pinctrl *pctrl)
 {
 	struct device_node *parent_node;
-	struct irq_domain *parent_domain;
-	struct irq_fwspec fwspec;
+	struct irq_domain *pdc_domain;
 	unsigned int i;
 
 	parent_node = of_irq_find_parent(pctrl->dev->of_node);
-
 	if (!parent_node)
 		return;
 
-	parent_domain = irq_find_host(parent_node);
-	if (!parent_domain)
+	pdc_domain = irq_find_host(parent_node);
+	if (!pdc_domain)
 		return;
 
-	fwspec.fwnode = parent_domain->fwnode;
 	for (i = 0; i < pctrl->soc->n_dir_conns; i++) {
 		const struct msm_dir_conn *dirconn = &pctrl->soc->dir_conn[i];
-		unsigned int parent_irq;
-		int irq;
 
-		fwspec.param[0] = 0; /* SPI */
-		fwspec.param[1] = dirconn->hwirq;
-		fwspec.param[2] = IRQ_TYPE_NONE;
-		fwspec.param_count = 3;
-		parent_irq = irq_create_fwspec_mapping(&fwspec);
+		request_dc_interrupt(pctrl->chip.irqdomain, pdc_domain,
+					dirconn->hwirq, dirconn->gpio);
+	}
 
-		if (dirconn->gpio != 0) {
-			irq = irq_find_mapping(pctrl->chip.irqdomain,
-					dirconn->gpio);
+	for (i = 0; i < pctrl->soc->n_pdc_mux_out; i++) {
+		struct msm_pdc_mux_output *pdc_out =
+					&pctrl->soc->pdc_mux_out[i];
 
-			irq_set_parent(irq, parent_irq);
-			irq_set_chip(irq, &msm_dirconn_irq_chip);
-			__irq_set_handler(parent_irq, msm_gpio_dirconn_handler,
-				false, NULL);
-			irq_set_handler_data(parent_irq, irq_get_irq_data(irq));
-		} else {
-			__irq_set_handler(parent_irq, msm_gpio_dirconn_handler,
-				false, NULL);
-		}
+		request_dc_interrupt(pctrl->chip.irqdomain, pdc_domain,
+					pdc_out->hwirq, 0);
+	}
+
+	/*
+	 * Statically choose the GPIOs for mapping to PDC. Dynamic mux mapping
+	 * is very difficult.
+	 */
+	for (i = 0; i < pctrl->soc->n_pdc_mux_out; i++) {
+		unsigned int irq;
+		struct irq_data *d;
+		struct msm_gpio_mux_input *gpio_in =
+					&pctrl->soc->gpio_mux_in[i];
+		if (!gpio_in->init)
+			continue;
+
+		irq = irq_find_mapping(pctrl->chip.irqdomain, gpio_in->gpio);
+		d = irq_get_irq_data(irq);
+		if (!d)
+			continue;
+
+		gpio_muxed_to_pdc(pdc_domain, d);
 	}
 }
 
@@ -1263,6 +1405,9 @@
 	if (IS_ERR(pctrl->regs))
 		return PTR_ERR(pctrl->regs);
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	pctrl->pdc_regs = devm_ioremap_resource(&pdev->dev, res);
+
 	msm_pinctrl_setup_pm_reset(pctrl);
 
 	pctrl->irq = platform_get_irq(pdev, 0);
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
index 1c6df2f..9fc6660 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.h
+++ b/drivers/pinctrl/qcom/pinctrl-msm.h
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2013, Sony Mobile Communications AB.
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -99,13 +100,35 @@
 	unsigned intr_detection_bit:5;
 	unsigned intr_detection_width:5;
 	unsigned dir_conn_en_bit:8;
-}
+};
+
+/**
+ * struct msm_gpio_mux_input - Map GPIO to Mux pin
+ * @mux::	The mux pin to which the GPIO is connected to
+ * @gpio:	GPIO pin number
+ * @init:	Setup PDC connection at probe
+ */
+struct msm_gpio_mux_input {
+	unsigned int mux;
+	unsigned int gpio;
+	bool init;
+};
+
+/**
+ * struct msm_pdc_mux_output - GPIO mux pin to PDC port
+ * @mux:	GPIO mux pin number
+ * @hwirq:	The PDC port (hwirq) that GPIO is connected to
+ */
+struct msm_pdc_mux_output {
+	unsigned int mux;
+	irq_hw_number_t hwirq;
+};
 
 /**
  * struct msm_dir_conn - Direct GPIO connect configuration
  * @gpio:	GPIO pin number
  * @hwirq:	The GIC interrupt that the pin is connected to
- */;
+ */
 struct msm_dir_conn {
 	unsigned int gpio;
 	irq_hw_number_t hwirq;
@@ -122,8 +145,12 @@
  * @ngpio:      The number of pingroups the driver should expose as GPIOs.
  * @dir_conn:   An array describing all the pins directly connected to GIC.
  * @ndirconns:  The number of pins directly connected to GIC
- * @dir_conn_offsets:   Direct connect register offsets for each tile.
  * @dir_conn_irq_base:  Direct connect interrupt base register for kpss.
+ * @gpio_mux_in:	Map of GPIO pin to the hwirq.
+ * @n_gpioc_mux_in:	The number of entries in @pdc_mux_in.
+ * @pdc_mux_out:	Map of GPIO mux to PDC port.
+ * @n_pdc_mux_out:	The number of entries in @pdc_mux_out.
+ * @n_pdc_offset:	The offset for the PDC mux pins
  */
 struct msm_pinctrl_soc_data {
 	const struct pinctrl_pin_desc *pins;
@@ -136,6 +163,11 @@
 	const struct msm_dir_conn *dir_conn;
 	unsigned int n_dir_conns;
 	unsigned int dir_conn_irq_base;
+	struct msm_pdc_mux_output *pdc_mux_out;
+	unsigned int n_pdc_mux_out;
+	struct msm_gpio_mux_input *gpio_mux_in;
+	unsigned int n_gpio_mux_in;
+	unsigned int n_pdc_mux_offset;
 };
 
 int msm_pinctrl_probe(struct platform_device *pdev,
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8937.c b/drivers/pinctrl/qcom/pinctrl-msm8937.c
new file mode 100644
index 0000000..2b72c54
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-msm8937.c
@@ -0,0 +1,1479 @@
+/* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <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_BASE 0x0
+#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_BASE + REG_SIZE * id,			\
+		.io_reg = REG_BASE + 0x4 + REG_SIZE * id,		\
+		.intr_cfg_reg = REG_BASE + 0x8 + REG_SIZE * id,		\
+		.intr_status_reg = REG_BASE + 0xc + REG_SIZE * id,	\
+		.intr_target_reg = REG_BASE + 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 msm8937_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, "SDC1_CLK"),
+	PINCTRL_PIN(135, "SDC1_CMD"),
+	PINCTRL_PIN(136, "SDC1_DATA"),
+	PINCTRL_PIN(137, "SDC1_RCLK"),
+	PINCTRL_PIN(138, "SDC2_CLK"),
+	PINCTRL_PIN(139, "SDC2_CMD"),
+	PINCTRL_PIN(140, "SDC2_DATA"),
+	PINCTRL_PIN(141, "QDSD_CLK"),
+	PINCTRL_PIN(142, "QDSD_CMD"),
+	PINCTRL_PIN(143, "QDSD_DATA0"),
+	PINCTRL_PIN(144, "QDSD_DATA1"),
+	PINCTRL_PIN(145, "QDSD_DATA2"),
+	PINCTRL_PIN(146, "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);
+
+static const unsigned int sdc1_clk_pins[] = { 134 };
+static const unsigned int sdc1_cmd_pins[] = { 135 };
+static const unsigned int sdc1_data_pins[] = { 136 };
+static const unsigned int sdc1_rclk_pins[] = { 137 };
+static const unsigned int sdc2_clk_pins[] = { 138 };
+static const unsigned int sdc2_cmd_pins[] = { 139 };
+static const unsigned int sdc2_data_pins[] = { 140 };
+static const unsigned int qdsd_clk_pins[] = { 141 };
+static const unsigned int qdsd_cmd_pins[] = { 142 };
+static const unsigned int qdsd_data0_pins[] = { 143 };
+static const unsigned int qdsd_data1_pins[] = { 144 };
+static const unsigned int qdsd_data2_pins[] = { 145 };
+static const unsigned int qdsd_data3_pins[] = { 146 };
+
+enum msm8937_functions {
+	msm_mux_qdss_tracedata_b,
+	msm_mux_blsp_uart1,
+	msm_mux_gpio,
+	msm_mux_blsp_spi1,
+	msm_mux_adsp_ext,
+	msm_mux_blsp_i2c1,
+	msm_mux_prng_rosc,
+	msm_mux_qdss_cti_trig_out_b0,
+	msm_mux_blsp_spi2,
+	msm_mux_blsp_uart2,
+	msm_mux_blsp_uart3,
+	msm_mux_pbs0,
+	msm_mux_pbs1,
+	msm_mux_pwr_modem_enabled_b,
+	msm_mux_blsp_i2c3,
+	msm_mux_gcc_gp2_clk_b,
+	msm_mux_ldo_update,
+	msm_mux_atest_combodac_to_gpio_native,
+	msm_mux_ldo_en,
+	msm_mux_blsp_i2c2,
+	msm_mux_gcc_gp1_clk_b,
+	msm_mux_pbs2,
+	msm_mux_atest_gpsadc_dtest0_native,
+	msm_mux_blsp_spi3,
+	msm_mux_gcc_gp3_clk_b,
+	msm_mux_blsp_spi4,
+	msm_mux_blsp_uart4,
+	msm_mux_sec_mi2s,
+	msm_mux_pwr_nav_enabled_b,
+	msm_mux_codec_mad,
+	msm_mux_pwr_crypto_enabled_b,
+	msm_mux_blsp_i2c4,
+	msm_mux_blsp_spi5,
+	msm_mux_blsp_uart5,
+	msm_mux_qdss_traceclk_a,
+	msm_mux_atest_bbrx1,
+	msm_mux_m_voc,
+	msm_mux_qdss_cti_trig_in_a0,
+	msm_mux_qdss_cti_trig_in_b0,
+	msm_mux_blsp_i2c6,
+	msm_mux_qdss_traceclk_b,
+	msm_mux_atest_wlan0,
+	msm_mux_atest_wlan1,
+	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_mdp_vsync,
+	msm_mux_pri_mi2s_mclk_a,
+	msm_mux_sec_mi2s_mclk_a,
+	msm_mux_cam_mclk,
+	msm_mux_cci_i2c,
+	msm_mux_pwr_modem_enabled_a,
+	msm_mux_cci_timer0,
+	msm_mux_cci_timer1,
+	msm_mux_cam1_standby,
+	msm_mux_pwr_nav_enabled_a,
+	msm_mux_cam1_rst,
+	msm_mux_pwr_crypto_enabled_a,
+	msm_mux_forced_usb,
+	msm_mux_qdss_cti_trig_out_b1,
+	msm_mux_cam2_rst,
+	msm_mux_webcam_standby,
+	msm_mux_cci_async,
+	msm_mux_webcam_rst,
+	msm_mux_ov_ldo,
+	msm_mux_sd_write,
+	msm_mux_accel_int,
+	msm_mux_gcc_gp1_clk_a,
+	msm_mux_alsp_int,
+	msm_mux_gcc_gp2_clk_a,
+	msm_mux_mag_int,
+	msm_mux_gcc_gp3_clk_a,
+	msm_mux_blsp6_spi,
+	msm_mux_fp_int,
+	msm_mux_qdss_cti_trig_in_b1,
+	msm_mux_uim_batt,
+	msm_mux_cam2_standby,
+	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_sensor_rst,
+	msm_mux_mipi_dsi0,
+	msm_mux_smb_int,
+	msm_mux_cam0_ldo,
+	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_sdcard_det,
+	msm_mux_atest_char1,
+	msm_mux_ebi_cdc,
+	msm_mux_audio_reset,
+	msm_mux_atest_char0,
+	msm_mux_audio_ref,
+	msm_mux_cdc_pdm0,
+	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_cri_trng,
+	msm_mux_cri_trng1,
+	msm_mux_cri_trng0,
+	msm_mux_blsp_spi7,
+	msm_mux_blsp_uart7,
+	msm_mux_pri_mi2s_ws,
+	msm_mux_blsp_i2c7,
+	msm_mux_gcc_tlmm,
+	msm_mux_dmic0_clk,
+	msm_mux_dmic0_data,
+	msm_mux_key_volp,
+	msm_mux_qdss_cti_trig_in_a1,
+	msm_mux_us_emitter,
+	msm_mux_wsa_irq,
+	msm_mux_wsa_io,
+	msm_mux_wsa_reset,
+	msm_mux_blsp_spi8,
+	msm_mux_blsp_uart8,
+	msm_mux_blsp_i2c8,
+	msm_mux_gcc_plltest,
+	msm_mux_nav_pps_in_a,
+	msm_mux_pa_indicator,
+	msm_mux_modem_tsync,
+	msm_mux_nav_tsync,
+	msm_mux_nav_pps_in_b,
+	msm_mux_nav_pps,
+	msm_mux_gsm0_tx,
+	msm_mux_atest_char,
+	msm_mux_atest_tsens,
+	msm_mux_bimc_dte1,
+	msm_mux_ssbi_wtr1,
+	msm_mux_fp_gpio,
+	msm_mux_coex_uart,
+	msm_mux_key_snapshot,
+	msm_mux_key_focus,
+	msm_mux_nfc_pwr,
+	msm_mux_blsp8_spi,
+	msm_mux_qdss_cti_trig_out_a0,
+	msm_mux_qdss_cti_trig_out_a1,
+	msm_mux_NA,
+};
+
+static const char * const qdss_tracedata_b_groups[] = {
+	"gpio0", "gpio1", "gpio6", "gpio7", "gpio12", "gpio13", "gpio23",
+	"gpio42", "gpio43", "gpio44", "gpio47", "gpio66", "gpio86", "gpio87",
+	"gpio88", "gpio92",
+};
+static const char * const blsp_uart1_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3",
+};
+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",
+};
+static const char * const blsp_spi1_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const adsp_ext_groups[] = {
+	"gpio1",
+};
+static const char * const blsp_i2c1_groups[] = {
+	"gpio2", "gpio3",
+};
+static const char * const prng_rosc_groups[] = {
+	"gpio2",
+};
+static const char * const qdss_cti_trig_out_b0_groups[] = {
+	"gpio2",
+};
+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 blsp_uart3_groups[] = {
+	"gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const pbs0_groups[] = {
+	"gpio8",
+};
+static const char * const pbs1_groups[] = {
+	"gpio9",
+};
+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 ldo_update_groups[] = {
+	"gpio4",
+};
+static const char * const atest_combodac_to_gpio_native_groups[] = {
+	"gpio4", "gpio12", "gpio13", "gpio20", "gpio21", "gpio28", "gpio29",
+	"gpio30", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43", "gpio44",
+	"gpio45", "gpio46", "gpio47", "gpio48", "gpio67", "gpio115",
+};
+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",
+};
+static const char * const pbs2_groups[] = {
+	"gpio7",
+};
+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 gcc_gp3_clk_b_groups[] = {
+	"gpio11",
+};
+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 sec_mi2s_groups[] = {
+	"gpio12", "gpio13", "gpio94", "gpio95",
+};
+static const char * const pwr_nav_enabled_b_groups[] = {
+	"gpio12",
+};
+static const char * const codec_mad_groups[] = {
+	"gpio13",
+};
+static const char * const pwr_crypto_enabled_b_groups[] = {
+	"gpio13",
+};
+static const char * const blsp_i2c4_groups[] = {
+	"gpio14", "gpio15",
+};
+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 m_voc_groups[] = {
+	"gpio17", "gpio21",
+};
+static const char * const qdss_cti_trig_in_a0_groups[] = {
+	"gpio17",
+};
+static const char * const qdss_cti_trig_in_b0_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 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 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 cam_mclk_groups[] = {
+	"gpio26", "gpio27", "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 cci_timer0_groups[] = {
+	"gpio33",
+};
+static const char * const cci_timer1_groups[] = {
+	"gpio34",
+};
+static const char * const cam1_standby_groups[] = {
+	"gpio35",
+};
+static const char * const pwr_nav_enabled_a_groups[] = {
+	"gpio35",
+};
+static const char * const cam1_rst_groups[] = {
+	"gpio36",
+};
+static const char * const pwr_crypto_enabled_a_groups[] = {
+	"gpio36",
+};
+static const char * const forced_usb_groups[] = {
+	"gpio37",
+};
+static const char * const qdss_cti_trig_out_b1_groups[] = {
+	"gpio37",
+};
+static const char * const cam2_rst_groups[] = {
+	"gpio38",
+};
+static const char * const webcam_standby_groups[] = {
+	"gpio39",
+};
+static const char * const cci_async_groups[] = {
+	"gpio39",
+};
+static const char * const webcam_rst_groups[] = {
+	"gpio40",
+};
+static const char * const ov_ldo_groups[] = {
+	"gpio41",
+};
+static const char * const sd_write_groups[] = {
+	"gpio41",
+};
+static const char * const accel_int_groups[] = {
+	"gpio42",
+};
+static const char * const gcc_gp1_clk_a_groups[] = {
+	"gpio42",
+};
+static const char * const alsp_int_groups[] = {
+	"gpio43",
+};
+static const char * const gcc_gp2_clk_a_groups[] = {
+	"gpio43",
+};
+static const char * const mag_int_groups[] = {
+	"gpio44",
+};
+static const char * const gcc_gp3_clk_a_groups[] = {
+	"gpio44",
+};
+static const char * const blsp6_spi_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 uim_batt_groups[] = {
+	"gpio49",
+};
+static const char * const cam2_standby_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 sensor_rst_groups[] = {
+	"gpio59",
+};
+static const char * const mipi_dsi0_groups[] = {
+	"gpio60",
+};
+static const char * const smb_int_groups[] = {
+	"gpio61",
+};
+static const char * const cam0_ldo_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", "gpio85", "gpio86", "gpio88", "gpio94", "gpio95",
+};
+static const char * const sdcard_det_groups[] = {
+	"gpio67",
+};
+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 audio_reset_groups[] = {
+	"gpio68",
+};
+static const char * const atest_char0_groups[] = {
+	"gpio68",
+};
+static const char * const audio_ref_groups[] = {
+	"gpio69",
+};
+static const char * const cdc_pdm0_groups[] = {
+	"gpio69", "gpio70", "gpio71", "gpio72", "gpio73", "gpio74",
+};
+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 cri_trng_groups[] = {
+	"gpio82",
+};
+static const char * const cri_trng1_groups[] = {
+	"gpio83",
+};
+static const char * const cri_trng0_groups[] = {
+	"gpio84",
+};
+static const char * const blsp_spi7_groups[] = {
+	"gpio85", "gpio86", "gpio87", "gpio88",
+};
+static const char * const blsp_uart7_groups[] = {
+	"gpio85", "gpio86", "gpio87", "gpio88",
+};
+static const char * const pri_mi2s_ws_groups[] = {
+	"gpio87",
+};
+static const char * const blsp_i2c7_groups[] = {
+	"gpio87", "gpio88",
+};
+static const char * const gcc_tlmm_groups[] = {
+	"gpio87",
+};
+static const char * const dmic0_clk_groups[] = {
+	"gpio89",
+};
+static const char * const dmic0_data_groups[] = {
+	"gpio90",
+};
+static const char * const key_volp_groups[] = {
+	"gpio91",
+};
+static const char * const qdss_cti_trig_in_a1_groups[] = {
+	"gpio91",
+};
+static const char * const us_emitter_groups[] = {
+	"gpio92",
+};
+static const char * const wsa_irq_groups[] = {
+	"gpio93",
+};
+static const char * const wsa_io_groups[] = {
+	"gpio94", "gpio95",
+};
+static const char * const wsa_reset_groups[] = {
+	"gpio96",
+};
+static const char * const blsp_spi8_groups[] = {
+	"gpio96", "gpio97", "gpio98", "gpio99",
+};
+static const char * const blsp_uart8_groups[] = {
+	"gpio96", "gpio97", "gpio98", "gpio99",
+};
+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[] = {
+	"gpio115",
+};
+static const char * const pa_indicator_groups[] = {
+	"gpio116",
+};
+static const char * const modem_tsync_groups[] = {
+	"gpio117",
+};
+static const char * const nav_tsync_groups[] = {
+	"gpio117",
+};
+static const char * const nav_pps_in_b_groups[] = {
+	"gpio117",
+};
+static const char * const nav_pps_groups[] = {
+	"gpio117",
+};
+static const char * const gsm0_tx_groups[] = {
+	"gpio119",
+};
+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 ssbi_wtr1_groups[] = {
+	"gpio122", "gpio123",
+};
+static const char * const fp_gpio_groups[] = {
+	"gpio124",
+};
+static const char * const coex_uart_groups[] = {
+	"gpio124", "gpio127",
+};
+static const char * const key_snapshot_groups[] = {
+	"gpio127",
+};
+static const char * const key_focus_groups[] = {
+	"gpio128",
+};
+static const char * const nfc_pwr_groups[] = {
+	"gpio129",
+};
+static const char * const blsp8_spi_groups[] = {
+	"gpio130",
+};
+static const char * const qdss_cti_trig_out_a0_groups[] = {
+	"gpio132",
+};
+static const char * const qdss_cti_trig_out_a1_groups[] = {
+	"gpio133",
+};
+
+static const struct msm_function msm8937_functions[] = {
+	FUNCTION(qdss_tracedata_b),
+	FUNCTION(blsp_uart1),
+	FUNCTION(gpio),
+	FUNCTION(blsp_spi1),
+	FUNCTION(adsp_ext),
+	FUNCTION(blsp_i2c1),
+	FUNCTION(prng_rosc),
+	FUNCTION(qdss_cti_trig_out_b0),
+	FUNCTION(blsp_spi2),
+	FUNCTION(blsp_uart2),
+	FUNCTION(blsp_uart3),
+	FUNCTION(pbs0),
+	FUNCTION(pbs1),
+	FUNCTION(pwr_modem_enabled_b),
+	FUNCTION(blsp_i2c3),
+	FUNCTION(gcc_gp2_clk_b),
+	FUNCTION(ldo_update),
+	FUNCTION(atest_combodac_to_gpio_native),
+	FUNCTION(ldo_en),
+	FUNCTION(blsp_i2c2),
+	FUNCTION(gcc_gp1_clk_b),
+	FUNCTION(pbs2),
+	FUNCTION(atest_gpsadc_dtest0_native),
+	FUNCTION(blsp_spi3),
+	FUNCTION(gcc_gp3_clk_b),
+	FUNCTION(blsp_spi4),
+	FUNCTION(blsp_uart4),
+	FUNCTION(sec_mi2s),
+	FUNCTION(pwr_nav_enabled_b),
+	FUNCTION(codec_mad),
+	FUNCTION(pwr_crypto_enabled_b),
+	FUNCTION(blsp_i2c4),
+	FUNCTION(blsp_spi5),
+	FUNCTION(blsp_uart5),
+	FUNCTION(qdss_traceclk_a),
+	FUNCTION(atest_bbrx1),
+	FUNCTION(m_voc),
+	FUNCTION(qdss_cti_trig_in_a0),
+	FUNCTION(qdss_cti_trig_in_b0),
+	FUNCTION(blsp_i2c6),
+	FUNCTION(qdss_traceclk_b),
+	FUNCTION(atest_wlan0),
+	FUNCTION(atest_wlan1),
+	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(mdp_vsync),
+	FUNCTION(pri_mi2s_mclk_a),
+	FUNCTION(sec_mi2s_mclk_a),
+	FUNCTION(cam_mclk),
+	FUNCTION(cci_i2c),
+	FUNCTION(pwr_modem_enabled_a),
+	FUNCTION(cci_timer0),
+	FUNCTION(cci_timer1),
+	FUNCTION(cam1_standby),
+	FUNCTION(pwr_nav_enabled_a),
+	FUNCTION(cam1_rst),
+	FUNCTION(pwr_crypto_enabled_a),
+	FUNCTION(forced_usb),
+	FUNCTION(qdss_cti_trig_out_b1),
+	FUNCTION(cam2_rst),
+	FUNCTION(webcam_standby),
+	FUNCTION(cci_async),
+	FUNCTION(webcam_rst),
+	FUNCTION(ov_ldo),
+	FUNCTION(sd_write),
+	FUNCTION(accel_int),
+	FUNCTION(gcc_gp1_clk_a),
+	FUNCTION(alsp_int),
+	FUNCTION(gcc_gp2_clk_a),
+	FUNCTION(mag_int),
+	FUNCTION(gcc_gp3_clk_a),
+	FUNCTION(blsp6_spi),
+	FUNCTION(fp_int),
+	FUNCTION(qdss_cti_trig_in_b1),
+	FUNCTION(uim_batt),
+	FUNCTION(cam2_standby),
+	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(sensor_rst),
+	FUNCTION(mipi_dsi0),
+	FUNCTION(smb_int),
+	FUNCTION(cam0_ldo),
+	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(sdcard_det),
+	FUNCTION(atest_char1),
+	FUNCTION(ebi_cdc),
+	FUNCTION(audio_reset),
+	FUNCTION(atest_char0),
+	FUNCTION(audio_ref),
+	FUNCTION(cdc_pdm0),
+	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(cri_trng),
+	FUNCTION(cri_trng1),
+	FUNCTION(cri_trng0),
+	FUNCTION(blsp_spi7),
+	FUNCTION(blsp_uart7),
+	FUNCTION(pri_mi2s_ws),
+	FUNCTION(blsp_i2c7),
+	FUNCTION(gcc_tlmm),
+	FUNCTION(dmic0_clk),
+	FUNCTION(dmic0_data),
+	FUNCTION(key_volp),
+	FUNCTION(qdss_cti_trig_in_a1),
+	FUNCTION(us_emitter),
+	FUNCTION(wsa_irq),
+	FUNCTION(wsa_io),
+	FUNCTION(wsa_reset),
+	FUNCTION(blsp_spi8),
+	FUNCTION(blsp_uart8),
+	FUNCTION(blsp_i2c8),
+	FUNCTION(gcc_plltest),
+	FUNCTION(nav_pps_in_a),
+	FUNCTION(pa_indicator),
+	FUNCTION(modem_tsync),
+	FUNCTION(nav_tsync),
+	FUNCTION(nav_pps_in_b),
+	FUNCTION(nav_pps),
+	FUNCTION(gsm0_tx),
+	FUNCTION(atest_char),
+	FUNCTION(atest_tsens),
+	FUNCTION(bimc_dte1),
+	FUNCTION(ssbi_wtr1),
+	FUNCTION(fp_gpio),
+	FUNCTION(coex_uart),
+	FUNCTION(key_snapshot),
+	FUNCTION(key_focus),
+	FUNCTION(nfc_pwr),
+	FUNCTION(blsp8_spi),
+	FUNCTION(qdss_cti_trig_out_a0),
+	FUNCTION(qdss_cti_trig_out_a1),
+};
+
+static const struct msm_pingroup msm8937_groups[] = {
+	PINGROUP(0, blsp_spi1, blsp_uart1, qdss_tracedata_b, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(1, blsp_spi1, blsp_uart1, adsp_ext, NA, NA, NA, NA, NA,
+		 qdss_tracedata_b),
+	PINGROUP(2, blsp_spi1, blsp_uart1, blsp_i2c1, prng_rosc, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(3, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA),
+	PINGROUP(4, blsp_spi2, blsp_uart2, ldo_update, NA,
+		 atest_combodac_to_gpio_native, 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,
+		 qdss_tracedata_b, NA, NA, NA, NA),
+	PINGROUP(7, blsp_spi2, blsp_uart2, blsp_i2c2, pbs2, NA,
+		 qdss_tracedata_b, NA, atest_gpsadc_dtest0_native, NA),
+	PINGROUP(8, blsp_spi3, blsp_uart3, pbs0, NA, NA, NA, NA, NA, NA),
+	PINGROUP(9, blsp_spi3, blsp_uart3, pbs1, pwr_modem_enabled_b, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(10, blsp_spi3, blsp_uart3, blsp_i2c3, gcc_gp2_clk_b, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(11, blsp_spi3, blsp_uart3, blsp_i2c3, gcc_gp3_clk_b, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(12, blsp_spi4, blsp_uart4, sec_mi2s, pwr_nav_enabled_b, NA,
+		 NA, NA, NA, NA),
+	PINGROUP(13, blsp_spi4, blsp_uart4, sec_mi2s, pwr_crypto_enabled_b, NA,
+		 NA, NA, NA, NA),
+	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, NA, NA, qdss_traceclk_a,
+		 NA, atest_bbrx1),
+	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, NA, NA, NA,
+		 qdss_tracectl_b),
+	PINGROUP(21, blsp_spi6, blsp_uart6, m_voc, NA, NA, NA, NA, NA,
+		 qdss_cti_trig_in_b0),
+	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, NA, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(26, cam_mclk, NA, NA, NA, NA, NA, qdss_tracedata_a, NA, NA),
+	PINGROUP(27, cam_mclk, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_a),
+	PINGROUP(28, cam_mclk, NA, NA, NA, NA, NA, qdss_tracedata_a, NA,
+		 atest_combodac_to_gpio_native),
+	PINGROUP(29, cci_i2c, pwr_modem_enabled_a, NA, NA, NA, NA, NA,
+		 qdss_tracedata_a, NA),
+	PINGROUP(30, cci_i2c, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_a),
+	PINGROUP(31, cci_i2c, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_a),
+	PINGROUP(32, cci_i2c, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_a),
+	PINGROUP(33, cci_timer0, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_a),
+	PINGROUP(34, cci_timer1, NA, NA, NA, NA, NA, NA, NA, qdss_tracedata_a),
+	PINGROUP(35, pwr_nav_enabled_a, NA, NA, NA, NA, NA, NA, NA,
+		 qdss_tracedata_a),
+	PINGROUP(36, pwr_crypto_enabled_a, NA, NA, NA, NA, NA, NA, NA,
+		 qdss_tracedata_a),
+	PINGROUP(37, NA, NA, NA, NA, NA, qdss_cti_trig_out_b1, NA, NA, NA),
+	PINGROUP(38, NA, qdss_tracedata_a, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(39, cci_async, NA, NA, NA, NA, NA, qdss_tracedata_a, NA,
+		 atest_combodac_to_gpio_native),
+	PINGROUP(40, NA, NA, NA, NA, qdss_tracedata_a, NA,
+		 atest_combodac_to_gpio_native, NA, NA),
+	PINGROUP(41, sd_write, NA, NA, NA, NA, NA, NA, NA,
+		 atest_combodac_to_gpio_native),
+	PINGROUP(42, gcc_gp1_clk_a, qdss_tracedata_b, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+	PINGROUP(43, gcc_gp2_clk_a, qdss_tracedata_b, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+	PINGROUP(44, gcc_gp3_clk_a, qdss_tracedata_b, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+	PINGROUP(45, NA, NA, atest_combodac_to_gpio_native, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(46, NA, NA, atest_combodac_to_gpio_native, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(47, blsp6_spi, NA, qdss_tracedata_b, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA),
+	PINGROUP(48, NA, qdss_cti_trig_in_b1, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+	PINGROUP(49, uim_batt, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(50, qdss_tracedata_a, NA, NA, NA, NA, NA, 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, atest_char1, ebi_cdc, NA, atest_combodac_to_gpio_native,
+		 NA, NA, NA, NA, NA),
+	PINGROUP(68, atest_char0, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(69, audio_ref, cdc_pdm0, pri_mi2s_mclk_b, ebi_cdc, 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, cri_trng, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(83, wcss_bt, cri_trng1, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(84, wcss_bt, cri_trng0, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(85, pri_mi2s, blsp_spi7, blsp_uart7, NA, NA, NA, NA, NA, NA),
+	PINGROUP(86, pri_mi2s, blsp_spi7, blsp_uart7, qdss_tracedata_b, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(87, pri_mi2s_ws, blsp_spi7, blsp_uart7, blsp_i2c7,
+		 qdss_tracedata_b, gcc_tlmm, NA, NA, NA),
+	PINGROUP(88, pri_mi2s, blsp_spi7, blsp_uart7, blsp_i2c7, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(89, dmic0_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(90, dmic0_data, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(91, NA, NA, NA, NA, NA, qdss_cti_trig_in_a1, NA, NA, NA),
+	PINGROUP(92, NA, NA, NA, NA, NA, qdss_tracedata_b, NA, NA, NA),
+	PINGROUP(93, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(94, wsa_io, sec_mi2s, pri_mi2s, NA, NA, NA, NA, NA, NA),
+	PINGROUP(95, wsa_io, sec_mi2s, pri_mi2s, NA, NA, NA, NA, NA, NA),
+	PINGROUP(96, blsp_spi8, blsp_uart8, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(97, blsp_spi8, blsp_uart8, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(98, blsp_spi8, blsp_uart8, blsp_i2c8, gcc_plltest, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(99, blsp_spi8, blsp_uart8, blsp_i2c8, gcc_plltest, 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, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(112, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(113, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(114, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(115, NA, NA, nav_pps_in_a, NA, atest_combodac_to_gpio_native,
+		 NA, NA, NA, NA),
+	PINGROUP(116, NA, pa_indicator, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(117, NA, modem_tsync, nav_tsync, nav_pps_in_b, nav_pps, NA,
+		 NA, NA, NA),
+	PINGROUP(118, NA, ebi_cdc, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(119, gsm0_tx, NA, ebi_cdc, 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, ssbi_wtr1, NA, NA, bimc_dte1, NA, NA, NA, NA),
+	PINGROUP(123, NA, ssbi_wtr1, ebi_cdc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(124, coex_uart, 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, coex_uart, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(128, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(129, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(130, blsp8_spi, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(131, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(132, qdss_cti_trig_out_a0, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(133, qdss_cti_trig_out_a1, 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 msm8937_pinctrl = {
+	.pins = msm8937_pins,
+	.npins = ARRAY_SIZE(msm8937_pins),
+	.functions = msm8937_functions,
+	.nfunctions = ARRAY_SIZE(msm8937_functions),
+	.groups = msm8937_groups,
+	.ngroups = ARRAY_SIZE(msm8937_groups),
+	.ngpios = 134,
+};
+
+static int msm8937_pinctrl_probe(struct platform_device *pdev)
+{
+	return msm_pinctrl_probe(pdev, &msm8937_pinctrl);
+}
+
+static const struct of_device_id msm8937_pinctrl_of_match[] = {
+	{ .compatible = "qcom,msm8937-pinctrl", },
+	{ },
+};
+
+static struct platform_driver msm8937_pinctrl_driver = {
+	.driver = {
+		.name = "msm8937-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = msm8937_pinctrl_of_match,
+	},
+	.probe = msm8937_pinctrl_probe,
+	.remove = msm_pinctrl_remove,
+};
+
+static int __init msm8937_pinctrl_init(void)
+{
+	return platform_driver_register(&msm8937_pinctrl_driver);
+}
+arch_initcall(msm8937_pinctrl_init);
+
+static void __exit msm8937_pinctrl_exit(void)
+{
+	platform_driver_unregister(&msm8937_pinctrl_driver);
+}
+module_exit(msm8937_pinctrl_exit);
+
+MODULE_DESCRIPTION("QTI msm8937 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, msm8937_pinctrl_of_match);
diff --git a/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
index 6ceb39a..c5f1307 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1105,6 +1105,97 @@
 	[106] = SDC_QDSD_PINGROUP(sdc2_data, 0x0, 9, 0),
 };
 
+static struct msm_gpio_mux_input sdxpoorwills_mux_in[] = {
+	{0, 1},
+	{1, 2},
+	{2, 5},
+	{3, 6},
+	{4, 9},
+	{5, 10},
+	{6, 11},
+	{7, 12},
+	{8, 13},
+	{9, 14},
+	{10, 15},
+	{11, 16},
+	{12, 17},
+	{13, 18},
+	{14, 19},
+	{15, 21},
+	{16, 22},
+	{17, 24},
+	{18, 25},
+	{19, 35},
+	{20, 42, 1},
+	{21, 43},
+	{22, 45},
+	{23, 46},
+	{24, 48},
+	{25, 50},
+	{26, 52},
+	{27, 53},
+	{28, 54},
+	{29, 55},
+	{30, 56},
+	{31, 57},
+	{32, 60},
+	{33, 61},
+	{34, 64},
+	{35, 65},
+	{36, 68},
+	{37, 71},
+	{38, 75},
+	{39, 76},
+	{40, 78},
+	{41, 79},
+	{42, 80},
+	{43, 82},
+	{44, 83},
+	{45, 84},
+	{46, 86},
+	{47, 87},
+	{48, 88},
+	{49, 89},
+	{50, 90},
+	{51, 93},
+	{52, 94},
+	{53, 95},
+	{54, 97},
+	{55, 98},
+};
+
+static struct msm_pdc_mux_output sdxpoorwills_mux_out[] = {
+	{0, 167},
+	{0, 168},
+	{0, 169},
+	{0, 170},
+	{0, 171},
+	{0, 172},
+	{0, 173},
+	{0, 174},
+	{0, 175},
+	{0, 176},
+	{0, 177},
+	{0, 178},
+	{0, 179},
+	{0, 180},
+	{0, 181},
+	{0, 182},
+	{0, 183},
+	{0, 184},
+	{0, 185},
+	{0, 186},
+	{0, 187},
+	{0, 188},
+	{0, 189},
+	{0, 190},
+	{0, 191},
+	{0, 192},
+	{0, 193},
+	{0, 194},
+	{0, 195},
+};
+
 static const struct msm_pinctrl_soc_data sdxpoorwills_pinctrl = {
 	.pins = sdxpoorwills_pins,
 	.npins = ARRAY_SIZE(sdxpoorwills_pins),
@@ -1112,6 +1203,11 @@
 	.nfunctions = ARRAY_SIZE(sdxpoorwills_functions),
 	.groups = sdxpoorwills_groups,
 	.ngroups = ARRAY_SIZE(sdxpoorwills_groups),
+	.gpio_mux_in = sdxpoorwills_mux_in,
+	.n_gpio_mux_in = ARRAY_SIZE(sdxpoorwills_mux_in),
+	.pdc_mux_out = sdxpoorwills_mux_out,
+	.n_pdc_mux_out = ARRAY_SIZE(sdxpoorwills_mux_out),
+	.n_pdc_mux_offset = 20,
 	.ngpios = 100,
 };
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index ae24675..01c0736 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -4394,6 +4394,8 @@
 	/* Prevent consequent calls from trying to load the FW again. */
 	if (ipa3_ctx->ipa_initialization_complete)
 		return 0;
+	/* move proxy vote for modem on ipa3_post_init */
+	IPA_ACTIVE_CLIENTS_INC_SPECIAL("PROXY_CLK_VOTE");
 
 	/*
 	 * indication whether working in MHI config or non MHI config is given
@@ -4858,7 +4860,6 @@
 	int result = 0;
 	int i;
 	struct ipa3_rt_tbl_set *rset;
-	struct ipa_active_client_logging_info log_info;
 
 	IPADBG("IPA Driver initialization started\n");
 
@@ -5049,8 +5050,7 @@
 	}
 
 	mutex_init(&ipa3_ctx->ipa3_active_clients.mutex);
-	IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, "PROXY_CLK_VOTE");
-	ipa3_active_clients_log_inc(&log_info, false);
+	/* move proxy vote for modem to ipa3_post_init() */
 	atomic_set(&ipa3_ctx->ipa3_active_clients.cnt, 1);
 
 	/* Create workqueues for power management */
@@ -5296,6 +5296,8 @@
 	IPADBG("ipa cdev added successful. major:%d minor:%d\n",
 			MAJOR(ipa3_ctx->dev_num),
 			MINOR(ipa3_ctx->dev_num));
+	/* proxy vote for modem is added in ipa3_post_init() phase */
+	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 	return 0;
 
 fail_cdev_add:
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
index 941e489..648db5e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1209,8 +1209,6 @@
 		IPADBG("Skipping endpoint configuration.\n");
 	}
 
-	ipa3_enable_data_path(ipa_ep_idx);
-
 	out->clnt_hdl = ipa_ep_idx;
 
 	if (!ep->skip_ep_cfg && IPA_CLIENT_IS_PROD(in->sys.client))
@@ -1316,6 +1314,7 @@
 	struct ipa3_ep_context *ep;
 	union IpaHwWdiCommonChCmdData_t enable;
 	struct ipa_ep_cfg_holb holb_cfg;
+	struct ipahal_reg_endp_init_rsrc_grp rsrc_grp;
 
 	if (clnt_hdl >= ipa3_ctx->ipa_num_pipes ||
 	    ipa3_ctx->ep[clnt_hdl].valid == 0) {
@@ -1348,6 +1347,20 @@
 		goto uc_timeout;
 	}
 
+	/* Assign the resource group for pipe */
+	memset(&rsrc_grp, 0, sizeof(rsrc_grp));
+	rsrc_grp.rsrc_grp = ipa_get_ep_group(ep->client);
+	if (rsrc_grp.rsrc_grp == -1) {
+		IPAERR("invalid group for client %d\n", ep->client);
+		WARN_ON(1);
+		return -EFAULT;
+	}
+
+	IPADBG("Setting group %d for pipe %d\n",
+		rsrc_grp.rsrc_grp, clnt_hdl);
+	ipahal_write_reg_n_fields(IPA_ENDP_INIT_RSRC_GRP_n, clnt_hdl,
+		&rsrc_grp);
+
 	if (IPA_CLIENT_IS_CONS(ep->client)) {
 		memset(&holb_cfg, 0, sizeof(holb_cfg));
 		holb_cfg.en = IPA_HOLB_TMR_DIS;
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 95e3782..dec698f 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -3139,7 +3139,8 @@
 	}
 
 	dev = &ctx->usb_bam_pdev->dev;
-	if (dev && dev->parent && !device_property_present(dev->parent,
+	if (dev && dev->parent && device_property_present(dev->parent, "iommus")
+		&& !device_property_present(dev->parent,
 						"qcom,smmu-s1-bypass")) {
 		pr_info("%s: setting SPS_BAM_SMMU_EN flag with (%s)\n",
 						__func__, dev_name(dev));
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index 99120f4..a2a35c6 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -170,6 +170,7 @@
 	FG_SRAM_SYS_TERM_CURR,
 	FG_SRAM_CHG_TERM_CURR,
 	FG_SRAM_CHG_TERM_BASE_CURR,
+	FG_SRAM_CUTOFF_CURR,
 	FG_SRAM_DELTA_MSOC_THR,
 	FG_SRAM_DELTA_BSOC_THR,
 	FG_SRAM_RECHARGE_SOC_THR,
@@ -262,6 +263,7 @@
 	int	chg_term_curr_ma;
 	int	chg_term_base_curr_ma;
 	int	sys_term_curr_ma;
+	int	cutoff_curr_ma;
 	int	delta_soc_thr;
 	int	recharge_soc_thr;
 	int	recharge_volt_thr_mv;
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 2c62218..0894f37 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -35,6 +35,8 @@
 #define ESR_PULSE_THRESH_OFFSET		3
 #define SLOPE_LIMIT_WORD		3
 #define SLOPE_LIMIT_OFFSET		0
+#define CUTOFF_CURR_WORD		4
+#define CUTOFF_CURR_OFFSET		0
 #define CUTOFF_VOLT_WORD		5
 #define CUTOFF_VOLT_OFFSET		0
 #define SYS_TERM_CURR_WORD		6
@@ -208,6 +210,8 @@
 		1000000, 122070, 0, fg_encode_current, NULL),
 	PARAM(CHG_TERM_CURR, CHG_TERM_CURR_WORD, CHG_TERM_CURR_OFFSET, 1,
 		100000, 390625, 0, fg_encode_current, NULL),
+	PARAM(CUTOFF_CURR, CUTOFF_CURR_WORD, CUTOFF_CURR_OFFSET, 3,
+		1000000, 122070, 0, fg_encode_current, NULL),
 	PARAM(DELTA_MSOC_THR, DELTA_MSOC_THR_WORD, DELTA_MSOC_THR_OFFSET, 1,
 		2048, 100, 0, fg_encode_default, NULL),
 	PARAM(DELTA_BSOC_THR, DELTA_BSOC_THR_WORD, DELTA_BSOC_THR_OFFSET, 1,
@@ -284,6 +288,8 @@
 	PARAM(CHG_TERM_BASE_CURR, CHG_TERM_CURR_v2_WORD,
 		CHG_TERM_BASE_CURR_v2_OFFSET, 1, 1024, 1000, 0,
 		fg_encode_current, NULL),
+	PARAM(CUTOFF_CURR, CUTOFF_CURR_WORD, CUTOFF_CURR_OFFSET, 3,
+		1000000, 122070, 0, fg_encode_current, NULL),
 	PARAM(DELTA_MSOC_THR, DELTA_MSOC_THR_v2_WORD, DELTA_MSOC_THR_v2_OFFSET,
 		1, 2048, 100, 0, fg_encode_default, NULL),
 	PARAM(DELTA_BSOC_THR, DELTA_BSOC_THR_v2_WORD, DELTA_BSOC_THR_v2_OFFSET,
@@ -3974,6 +3980,16 @@
 		return rc;
 	}
 
+	fg_encode(chip->sp, FG_SRAM_CUTOFF_CURR, chip->dt.cutoff_curr_ma,
+		buf);
+	rc = fg_sram_write(chip, chip->sp[FG_SRAM_CUTOFF_CURR].addr_word,
+			chip->sp[FG_SRAM_CUTOFF_CURR].addr_byte, buf,
+			chip->sp[FG_SRAM_CUTOFF_CURR].len, FG_IMA_DEFAULT);
+	if (rc < 0) {
+		pr_err("Error in writing cutoff_curr, rc=%d\n", rc);
+		return rc;
+	}
+
 	if (!(chip->wa_flags & PMI8998_V1_REV_WA)) {
 		fg_encode(chip->sp, FG_SRAM_CHG_TERM_BASE_CURR,
 			chip->dt.chg_term_base_curr_ma, buf);
@@ -4697,6 +4713,7 @@
 #define DEFAULT_CHG_TERM_CURR_MA	100
 #define DEFAULT_CHG_TERM_BASE_CURR_MA	75
 #define DEFAULT_SYS_TERM_CURR_MA	-125
+#define DEFAULT_CUTOFF_CURR_MA		500
 #define DEFAULT_DELTA_SOC_THR		1
 #define DEFAULT_RECHARGE_SOC_THR	95
 #define DEFAULT_BATT_TEMP_COLD		0
@@ -4860,6 +4877,12 @@
 	else
 		chip->dt.chg_term_base_curr_ma = temp;
 
+	rc = of_property_read_u32(node, "qcom,fg-cutoff-current", &temp);
+	if (rc < 0)
+		chip->dt.cutoff_curr_ma = DEFAULT_CUTOFF_CURR_MA;
+	else
+		chip->dt.cutoff_curr_ma = temp;
+
 	rc = of_property_read_u32(node, "qcom,fg-delta-soc-thr", &temp);
 	if (rc < 0)
 		chip->dt.delta_soc_thr = DEFAULT_DELTA_SOC_THR;
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index d8cc2c4..59897ea 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -376,7 +376,7 @@
 
 static struct channel_ctx *ch_name_to_ch_ctx_create(
 					struct glink_core_xprt_ctx *xprt_ctx,
-					const char *name);
+					const char *name, bool local);
 
 static void ch_push_remote_rx_intent(struct channel_ctx *ctx, size_t size,
 					uint32_t riid, void *cookie);
@@ -1836,13 +1836,14 @@
  *                              it is not found and get reference of context.
  * @xprt_ctx:	Transport to search for a matching channel.
  * @name:	Name of the desired channel.
+ * @local:	If called from local open or not
  *
  * Return: The channel corresponding to @name, NULL if a matching channel was
  *         not found AND a new channel could not be created.
  */
 static struct channel_ctx *ch_name_to_ch_ctx_create(
 					struct glink_core_xprt_ctx *xprt_ctx,
-					const char *name)
+					const char *name, bool local)
 {
 	struct channel_ctx *entry;
 	struct channel_ctx *ctx;
@@ -1886,10 +1887,23 @@
 	list_for_each_entry_safe(entry, temp, &xprt_ctx->channels,
 		    port_list_node)
 		if (!strcmp(entry->name, name) && !entry->pending_delete) {
+			rwref_get(&entry->ch_state_lhb2);
+			/* port already exists */
+			if (entry->local_open_state != GLINK_CHANNEL_CLOSED
+								&& local) {
+				/* not ready to be re-opened */
+				GLINK_INFO_CH_XPRT(entry, xprt_ctx,
+					"%s: Ch not ready. State: %u\n",
+					__func__, entry->local_open_state);
+				rwref_put(&entry->ch_state_lhb2);
+				entry = NULL;
+			} else if (local) {
+				entry->local_open_state =
+						GLINK_CHANNEL_OPENING;
+			}
 			spin_unlock_irqrestore(&xprt_ctx->xprt_ctx_lock_lhb1,
 					flags);
 			kfree(ctx);
-			rwref_get(&entry->ch_state_lhb2);
 			rwref_write_put(&xprt_ctx->xprt_state_lhb0);
 			return entry;
 		}
@@ -1919,6 +1933,8 @@
 
 		ctx->transport_ptr = xprt_ctx;
 		rwref_get(&ctx->ch_state_lhb2);
+		if (local)
+			ctx->local_open_state = GLINK_CHANNEL_OPENING;
 		list_add_tail(&ctx->port_list_node, &xprt_ctx->channels);
 
 		GLINK_INFO_PERF_CH_XPRT(ctx, xprt_ctx,
@@ -2604,23 +2620,13 @@
 	 * look for an existing port structure which can occur in
 	 * reopen and remote-open-first cases
 	 */
-	ctx = ch_name_to_ch_ctx_create(transport_ptr, cfg->name);
+	ctx = ch_name_to_ch_ctx_create(transport_ptr, cfg->name, true);
 	if (ctx == NULL) {
 		GLINK_ERR("%s:%s %s: Error - unable to allocate new channel\n",
 				cfg->transport, cfg->edge, __func__);
 		return ERR_PTR(-ENOMEM);
 	}
 
-	/* port already exists */
-	if (ctx->local_open_state != GLINK_CHANNEL_CLOSED) {
-		/* not ready to be re-opened */
-		GLINK_INFO_CH_XPRT(ctx, transport_ptr,
-		"%s: Channel not ready to be re-opened. State: %u\n",
-		__func__, ctx->local_open_state);
-		rwref_put(&ctx->ch_state_lhb2);
-		return ERR_PTR(-EBUSY);
-	}
-
 	/* initialize port structure */
 	ctx->user_priv = cfg->priv;
 	ctx->rx_intent_req_timeout_jiffies =
@@ -2651,7 +2657,6 @@
 	ctx->local_xprt_req = best_id;
 	ctx->no_migrate = cfg->transport &&
 				!(cfg->options & GLINK_OPT_INITIAL_XPORT);
-	ctx->local_open_state = GLINK_CHANNEL_OPENING;
 	GLINK_INFO_PERF_CH(ctx,
 		"%s: local:GLINK_CHANNEL_CLOSED->GLINK_CHANNEL_OPENING\n",
 		__func__);
@@ -4912,7 +4917,7 @@
 	bool do_migrate;
 
 	glink_core_migration_edge_lock(if_ptr->glink_core_priv);
-	ctx = ch_name_to_ch_ctx_create(if_ptr->glink_core_priv, name);
+	ctx = ch_name_to_ch_ctx_create(if_ptr->glink_core_priv, name, false);
 	if (ctx == NULL) {
 		GLINK_ERR_XPRT(if_ptr->glink_core_priv,
 		       "%s: invalid rcid %u received, name '%s'\n",
@@ -5015,6 +5020,7 @@
 	struct channel_ctx *ctx;
 	bool is_ch_fully_closed;
 	struct glink_core_xprt_ctx *xprt_ptr = if_ptr->glink_core_priv;
+	unsigned long flags;
 
 	ctx = xprt_rcid_to_ch_ctx_get(if_ptr->glink_core_priv, rcid);
 	if (!ctx) {
@@ -5032,11 +5038,13 @@
 		rwref_put(&ctx->ch_state_lhb2);
 		return;
 	}
+	spin_lock_irqsave(&ctx->transport_ptr->xprt_ctx_lock_lhb1, flags);
+	ctx->pending_delete = true;
+	spin_unlock_irqrestore(&ctx->transport_ptr->xprt_ctx_lock_lhb1, flags);
 	GLINK_INFO_CH(ctx, "%s: remote: OPENED->CLOSED\n", __func__);
 
 	is_ch_fully_closed = glink_core_remote_close_common(ctx, false);
 
-	ctx->pending_delete = true;
 	if_ptr->tx_cmd_ch_remote_close_ack(if_ptr, rcid);
 
 	if (is_ch_fully_closed) {
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 2fb95fe..e3a50e3 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -2354,29 +2354,6 @@
 	return 0;
 }
 
-static int icnss_call_driver_remove(struct icnss_priv *priv)
-{
-	icnss_pr_dbg("Calling driver remove state: 0x%lx\n", priv->state);
-
-	clear_bit(ICNSS_FW_READY, &priv->state);
-
-	if (!test_bit(ICNSS_DRIVER_PROBED, &penv->state))
-		return 0;
-
-	if (!priv->ops || !priv->ops->remove)
-		return 0;
-
-	set_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
-	penv->ops->remove(&priv->pdev->dev);
-
-	clear_bit(ICNSS_DRIVER_UNLOADING, &penv->state);
-	clear_bit(ICNSS_DRIVER_PROBED, &priv->state);
-
-	icnss_hw_power_off(penv);
-
-	return 0;
-}
-
 static int icnss_fw_crashed(struct icnss_priv *priv,
 			    struct icnss_event_pd_service_down_data *event_data)
 {
@@ -2416,10 +2393,7 @@
 	if (priv->force_err_fatal)
 		ICNSS_ASSERT(0);
 
-	if (event_data->crashed)
-		icnss_fw_crashed(priv, event_data);
-	else
-		icnss_call_driver_remove(priv);
+	icnss_fw_crashed(priv, event_data);
 
 out:
 	kfree(data);
@@ -3102,6 +3076,12 @@
 	if (!dev)
 		return -ENODEV;
 
+	if (test_bit(ICNSS_FW_DOWN, &penv->state)) {
+		icnss_pr_err("FW down, ignoring fw_log_mode state: 0x%lx\n",
+			     penv->state);
+		return -EINVAL;
+	}
+
 	icnss_pr_dbg("FW log mode: %u\n", fw_log_mode);
 
 	ret = wlfw_ini_send_sync_msg(fw_log_mode);
@@ -3195,6 +3175,12 @@
 	if (!dev)
 		return -ENODEV;
 
+	if (test_bit(ICNSS_FW_DOWN, &penv->state)) {
+		icnss_pr_err("FW down, ignoring wlan_enable state: 0x%lx\n",
+			     penv->state);
+		return -EINVAL;
+	}
+
 	icnss_pr_dbg("Mode: %d, config: %p, host_version: %s\n",
 		     mode, config, host_version);
 
diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c
index 1bc9239..3b6c0bd 100644
--- a/drivers/soc/qcom/peripheral-loader.c
+++ b/drivers/soc/qcom/peripheral-loader.c
@@ -161,7 +161,7 @@
 	region_info = (struct md_ss_region __iomem *)subsys_segtable_base;
 	if (!region_info)
 		return -EINVAL;
-	pr_debug("Segments in minidump 0x%x\n", ss_mdump_seg_cnt);
+	pr_info("Minidump : Segments in minidump 0x%x\n", ss_mdump_seg_cnt);
 	ramdump_segs = kcalloc(ss_mdump_seg_cnt,
 			       sizeof(*ramdump_segs), GFP_KERNEL);
 	if (!ramdump_segs)
@@ -184,7 +184,7 @@
 			offset = offset +
 				sizeof(region_info->region_base_address);
 			s->size = __raw_readl(offset);
-			pr_debug("Minidump : Dumping segment %s with address 0x%lx and size 0x%x\n",
+			pr_info("Minidump : Dumping segment %s with address 0x%lx and size 0x%x\n",
 				s->name, s->address, (unsigned int)s->size);
 		} else
 			ss_valid_seg_cnt--;
@@ -220,15 +220,15 @@
 	int count = 0, ret;
 
 	if (desc->minidump) {
-		pr_debug("Minidump : md_ss_toc->md_ss_toc_init is 0x%x\n",
+		pr_info("Minidump : md_ss_toc->md_ss_toc_init is 0x%x\n",
 			(unsigned int)desc->minidump->md_ss_toc_init);
-		pr_debug("Minidump : md_ss_toc->md_ss_enable_status is 0x%x\n",
+		pr_info("Minidump : md_ss_toc->md_ss_enable_status is 0x%x\n",
 			(unsigned int)desc->minidump->md_ss_enable_status);
-		pr_debug("Minidump : md_ss_toc->encryption_status is 0x%x\n",
+		pr_info("Minidump : md_ss_toc->encryption_status is 0x%x\n",
 			(unsigned int)desc->minidump->encryption_status);
-		pr_debug("Minidump : md_ss_toc->ss_region_count is 0x%x\n",
+		pr_info("Minidump : md_ss_toc->ss_region_count is 0x%x\n",
 			(unsigned int)desc->minidump->ss_region_count);
-		pr_debug("Minidump : md_ss_toc->md_ss_smem_regions_baseptr is 0x%x\n",
+		pr_info("Minidump : md_ss_toc->md_ss_smem_regions_baseptr is 0x%x\n",
 			(unsigned int)
 			desc->minidump->md_ss_smem_regions_baseptr);
 		/**
@@ -241,11 +241,11 @@
 				MD_SS_ENABLED)) {
 			if (desc->minidump->encryption_status ==
 				MD_SS_ENCR_DONE) {
-				pr_debug("Dumping Minidump for %s\n",
+				pr_info("Minidump : Dumping for %s\n",
 					desc->name);
 				return pil_do_minidump(desc, minidump_dev);
 			}
-			pr_debug("Minidump aborted for %s\n", desc->name);
+			pr_info("Minidump : aborted for %s\n", desc->name);
 			return -EINVAL;
 		}
 	}
diff --git a/drivers/soc/qcom/pil-msa.c b/drivers/soc/qcom/pil-msa.c
index 68ff0f3..bc47a95 100644
--- a/drivers/soc/qcom/pil-msa.c
+++ b/drivers/soc/qcom/pil-msa.c
@@ -557,7 +557,7 @@
 {
 	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
 	phys_addr_t start_addr = pil_get_entry_addr(pil);
-	u32 debug_val;
+	u32 debug_val = 0;
 	int ret;
 
 	trace_pil_func(__func__);
@@ -576,8 +576,10 @@
 	if (ret)
 		goto err_clks;
 
-	/* Save state of modem debug register before full reset */
-	debug_val = readl_relaxed(drv->reg_base + QDSP6SS_DBG_CFG);
+	if (!pil->minidump || !pil->modem_ssr) {
+		/* Save state of modem debug register before full reset */
+		debug_val = readl_relaxed(drv->reg_base + QDSP6SS_DBG_CFG);
+	}
 
 	/* Assert reset to subsystem */
 	pil_mss_assert_resets(drv);
@@ -587,9 +589,12 @@
 	if (ret)
 		goto err_restart;
 
-	writel_relaxed(debug_val, drv->reg_base + QDSP6SS_DBG_CFG);
-	if (modem_dbg_cfg)
-		writel_relaxed(modem_dbg_cfg, drv->reg_base + QDSP6SS_DBG_CFG);
+	if (!pil->minidump || !pil->modem_ssr) {
+		writel_relaxed(debug_val, drv->reg_base + QDSP6SS_DBG_CFG);
+		if (modem_dbg_cfg)
+			writel_relaxed(modem_dbg_cfg,
+				drv->reg_base + QDSP6SS_DBG_CFG);
+	}
 
 	/* Program Image Address */
 	if (drv->self_auth) {
@@ -819,8 +824,8 @@
 	 * Need to Wait for timeout for debug reset sequence to
 	 * complete before returning
 	 */
-	pr_debug("Minidump: waiting encryption to complete\n");
-	msleep(30000);
+	pr_info("Minidump: waiting encryption to complete\n");
+	msleep(10000);
 	if (pil->minidump) {
 		writel_relaxed(0x2, drv->reg_base + QDSP6SS_NMI_CFG);
 		/* Let write complete before proceeding */
diff --git a/drivers/soc/qcom/pil-q6v5-mss.c b/drivers/soc/qcom/pil-q6v5-mss.c
index 721124c..ac322f8 100644
--- a/drivers/soc/qcom/pil-q6v5-mss.c
+++ b/drivers/soc/qcom/pil-q6v5-mss.c
@@ -167,6 +167,11 @@
 	if (ret)
 		return ret;
 
+	pil_mss_remove_proxy_votes(&drv->q6->desc);
+	ret = pil_mss_make_proxy_votes(&drv->q6->desc);
+	if (ret)
+		return ret;
+
 	ret = pil_mss_reset_load_mba(&drv->q6->desc);
 	if (ret)
 		return ret;
diff --git a/drivers/soc/qcom/scm.c b/drivers/soc/qcom/scm.c
index cab7178..fec6f17 100644
--- a/drivers/soc/qcom/scm.c
+++ b/drivers/soc/qcom/scm.c
@@ -185,9 +185,8 @@
 	case SCM_ENOMEM:
 		return -ENOMEM;
 	case SCM_EBUSY:
-		return SCM_EBUSY;
 	case SCM_V2_EBUSY:
-		return SCM_V2_EBUSY;
+		return -EBUSY;
 	}
 	return -EINVAL;
 }
@@ -338,13 +337,13 @@
 	do {
 		ret = scm_call_common(svc_id, cmd_id, cmd_buf, cmd_len,
 					resp_buf, resp_len, cmd, len);
-		if (ret == SCM_EBUSY)
+		if (ret == -EBUSY)
 			msleep(SCM_EBUSY_WAIT_MS);
 		if (retry_count == 33)
 			pr_warn("scm: secure world has been busy for 1 second!\n");
-	} while (ret == SCM_EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY));
+	} while (ret == -EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY));
 
-	if (ret == SCM_EBUSY)
+	if (ret == -EBUSY)
 		pr_err("scm: secure world busy (rc = SCM_EBUSY)\n");
 
 	return ret;
@@ -799,7 +798,7 @@
 
 	ret = scm_call_common(svc_id, cmd_id, cmd_buf, cmd_len, resp_buf,
 				resp_len, cmd, len);
-	if (unlikely(ret == SCM_EBUSY))
+	if (unlikely(ret == -EBUSY))
 		ret = _scm_call_retry(svc_id, cmd_id, cmd_buf, cmd_len,
 				      resp_buf, resp_len, cmd, PAGE_ALIGN(len));
 	kfree(cmd);
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 41f1a19..83b46d4 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -561,13 +561,15 @@
 
 		task_lock(selected);
 		send_sig(SIGKILL, selected, 0);
-		if (selected->mm)
+		if (selected->mm) {
 			task_set_lmk_waiting(selected);
-		if (oom_reaper)
-			mark_lmk_victim(selected);
+			if (!test_bit(MMF_OOM_SKIP, &selected->mm->flags) &&
+			    oom_reaper) {
+				mark_lmk_victim(selected);
+				wake_oom_reaper(selected);
+			}
+		}
 		task_unlock(selected);
-		if (oom_reaper)
-			wake_oom_reaper(selected);
 		trace_lowmemory_kill(selected, cache_size, cache_limit, free);
 		lowmem_print(1, "Killing '%s' (%d) (tgid %d), adj %hd,\n"
 			"to free %ldkB on behalf of '%s' (%d) because\n"
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 5c4a24d..89bf6b7 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -1061,6 +1061,8 @@
 	struct dwc3_trb *trb;
 	int num_trbs = (dep->direction) ? (2 * (req->num_bufs) + 2)
 					: (req->num_bufs + 2);
+	struct scatterlist *sg;
+	struct sg_table *sgt;
 
 	dep->trb_pool = dma_zalloc_coherent(dwc->sysdev,
 				num_trbs * sizeof(struct dwc3_trb),
@@ -1073,6 +1075,19 @@
 	}
 
 	dep->num_trbs = num_trbs;
+	dma_get_sgtable(dwc->sysdev, &req->sgt_trb_xfer_ring, dep->trb_pool,
+		dep->trb_pool_dma, num_trbs * sizeof(struct dwc3_trb));
+
+	sgt = &req->sgt_trb_xfer_ring;
+	dev_dbg(dwc->dev, "%s(): trb_pool:%pK trb_pool_dma:%lx\n",
+		__func__, dep->trb_pool, (unsigned long)dep->trb_pool_dma);
+
+	for_each_sg(sgt->sgl, sg, sgt->nents, i)
+		dev_dbg(dwc->dev,
+			"%i: page_link:%lx offset:%x length:%x address:%lx\n",
+			i, sg->page_link, sg->offset, sg->length,
+			(unsigned long)sg->dma_address);
+
 	/* IN direction */
 	if (dep->direction) {
 		for (i = 0; i < num_trbs ; i++) {
@@ -1138,11 +1153,13 @@
 		}
 	}
 
-	pr_debug("%s: Initialized TRB Ring for %s\n", __func__, dep->name);
+	dev_dbg(dwc->dev, "%s: Initialized TRB Ring for %s\n",
+					__func__, dep->name);
 	trb = &dep->trb_pool[0];
 	if (trb) {
 		for (i = 0; i < num_trbs; i++) {
-			pr_debug("TRB(%d): ADDRESS:%lx bpl:%x bph:%x size:%x ctrl:%x\n",
+			dev_dbg(dwc->dev,
+				"TRB %d: ADDR:%lx bpl:%x bph:%x sz:%x ctl:%x\n",
 				i, (unsigned long)dwc3_trb_dma_offset(dep,
 				&dep->trb_pool[i]), trb->bpl, trb->bph,
 				trb->size, trb->ctrl);
@@ -1159,7 +1176,7 @@
 * @usb_ep - pointer to usb_ep instance.
 *
 */
-static void gsi_free_trbs(struct usb_ep *ep)
+static void gsi_free_trbs(struct usb_ep *ep, struct usb_gsi_request *req)
 {
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
 	struct dwc3 *dwc = dep->dwc;
@@ -1176,6 +1193,7 @@
 		dep->trb_pool = NULL;
 		dep->trb_pool_dma = 0;
 	}
+	sg_free_table(&req->sgt_trb_xfer_ring);
 }
 /*
 * Configures GSI EPs. For GSI EPs we need to set interrupter numbers.
@@ -1365,7 +1383,8 @@
 		break;
 	case GSI_EP_OP_FREE_TRBS:
 		dev_dbg(mdwc->dev, "EP_OP_FREE_TRBS for %s\n", ep->name);
-		gsi_free_trbs(ep);
+		request = (struct usb_gsi_request *)op_data;
+		gsi_free_trbs(ep, request);
 		break;
 	case GSI_EP_OP_CONFIG:
 		request = (struct usb_gsi_request *)op_data;
diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index 4911253..1f75b58 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -76,7 +76,7 @@
 	writel_relaxed(write_val, base + offset - DWC3_GLOBALS_REGS_START);
 
 	/* Read back to see if value was written */
-	tmp = readl_relaxed(base + offset);
+	tmp = readl_relaxed(base + offset - DWC3_GLOBALS_REGS_START);
 
 	dwc3_trace(trace_dwc3_masked_write_readback,
 			"addr %p readback val %08x",
diff --git a/drivers/usb/gadget/function/f_audio_source.c b/drivers/usb/gadget/function/f_audio_source.c
index 9f7a29a..05a66b2 100644
--- a/drivers/usb/gadget/function/f_audio_source.c
+++ b/drivers/usb/gadget/function/f_audio_source.c
@@ -158,6 +158,13 @@
 	.bInterval =		4, /* poll 1 per millisecond */
 };
 
+static struct usb_ss_ep_comp_descriptor ss_as_in_comp_desc = {
+	 .bLength =		 sizeof(ss_as_in_comp_desc),
+	 .bDescriptorType =	 USB_DT_SS_ENDPOINT_COMP,
+
+	 .wBytesPerInterval =	cpu_to_le16(IN_EP_MAX_PACKET_SIZE),
+};
+
 /* Standard ISO IN Endpoint Descriptor for highspeed */
 static struct usb_endpoint_descriptor fs_as_in_ep_desc  = {
 	.bLength =		USB_DT_ENDPOINT_AUDIO_SIZE,
@@ -198,6 +205,26 @@
 	NULL,
 };
 
+static struct usb_descriptor_header *ss_audio_desc[] = {
+	(struct usb_descriptor_header *)&ac_interface_desc,
+	(struct usb_descriptor_header *)&ac_header_desc,
+
+	(struct usb_descriptor_header *)&input_terminal_desc,
+	(struct usb_descriptor_header *)&output_terminal_desc,
+	(struct usb_descriptor_header *)&feature_unit_desc,
+
+	(struct usb_descriptor_header *)&as_interface_alt_0_desc,
+	(struct usb_descriptor_header *)&as_interface_alt_1_desc,
+	(struct usb_descriptor_header *)&as_header_desc,
+
+	(struct usb_descriptor_header *)&as_type_i_desc,
+
+	(struct usb_descriptor_header *)&hs_as_in_ep_desc,
+	(struct usb_descriptor_header *)&ss_as_in_comp_desc,
+	(struct usb_descriptor_header *)&as_iso_in_desc,
+	NULL,
+};
+
 static struct usb_descriptor_header *fs_audio_desc[] = {
 	(struct usb_descriptor_header *)&ac_interface_desc,
 	(struct usb_descriptor_header *)&ac_header_desc,
@@ -673,6 +700,7 @@
 
 	f->fs_descriptors = fs_audio_desc;
 	f->hs_descriptors = hs_audio_desc;
+	f->ss_descriptors = ss_audio_desc;
 
 	for (i = 0, status = 0; i < IN_EP_REQ_COUNT && status == 0; i++) {
 		req = audio_request_new(ep, IN_EP_MAX_PACKET_SIZE);
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 37903f9..4bdfadf 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -307,6 +307,10 @@
 	in_params->data_buff_base_len = d_port->in_request.buf_len *
 					d_port->in_request.num_bufs;
 	in_params->data_buff_base_addr_iova = d_port->in_request.dma;
+	in_params->sgt_xfer_rings = &d_port->in_request.sgt_trb_xfer_ring;
+	in_params->sgt_data_buff = &d_port->in_request.sgt_data_buff;
+	log_event_dbg("%s(): IN: sgt_xfer_rings:%pK sgt_data_buff:%pK\n",
+		__func__, in_params->sgt_xfer_rings, in_params->sgt_data_buff);
 	in_params->xfer_scratch.const_buffer_size =
 		gsi_channel_info.const_buffer_size;
 	in_params->xfer_scratch.depcmd_low_addr =
@@ -344,6 +348,13 @@
 			d_port->out_request.num_bufs;
 		out_params->data_buff_base_addr_iova =
 			d_port->out_request.dma;
+		out_params->sgt_xfer_rings =
+			&d_port->out_request.sgt_trb_xfer_ring;
+		out_params->sgt_data_buff = &d_port->out_request.sgt_data_buff;
+		log_event_dbg("%s(): OUT: sgt_xfer_rings:%pK sgt_data_buff:%pK\n",
+			__func__, out_params->sgt_xfer_rings,
+			out_params->sgt_data_buff);
+
 		out_params->xfer_scratch.last_trb_addr_iova =
 			gsi_channel_info.last_trb_addr;
 		out_params->xfer_scratch.const_buffer_size =
@@ -497,10 +508,12 @@
 	gsi->d_port.in_channel_handle = -EINVAL;
 	gsi->d_port.out_channel_handle = -EINVAL;
 
-	usb_gsi_ep_op(gsi->d_port.in_ep, NULL, GSI_EP_OP_FREE_TRBS);
+	usb_gsi_ep_op(gsi->d_port.in_ep, &gsi->d_port.in_request,
+							GSI_EP_OP_FREE_TRBS);
 
 	if (gsi->d_port.out_ep)
-		usb_gsi_ep_op(gsi->d_port.out_ep, NULL, GSI_EP_OP_FREE_TRBS);
+		usb_gsi_ep_op(gsi->d_port.out_ep, &gsi->d_port.out_request,
+							GSI_EP_OP_FREE_TRBS);
 
 	/* free buffers allocated with each TRB */
 	gsi_free_trb_buffer(gsi);
@@ -1945,6 +1958,11 @@
 			ret = -ENOMEM;
 			goto fail1;
 		}
+
+		dma_get_sgtable(dev->parent,
+			&gsi->d_port.in_request.sgt_data_buff,
+			gsi->d_port.in_request.buf_base_addr,
+			gsi->d_port.in_request.dma, len_in);
 	}
 
 	if (gsi->d_port.out_ep && !gsi->d_port.out_request.buf_base_addr) {
@@ -1964,6 +1982,11 @@
 			ret = -ENOMEM;
 			goto fail;
 		}
+
+		dma_get_sgtable(dev->parent,
+			&gsi->d_port.out_request.sgt_data_buff,
+			gsi->d_port.out_request.buf_base_addr,
+			gsi->d_port.out_request.dma, len_out);
 	}
 
 	log_event_dbg("finished allocating trb's buffer\n");
@@ -1994,6 +2017,7 @@
 			gsi->d_port.out_request.buf_base_addr,
 			gsi->d_port.out_request.dma);
 		gsi->d_port.out_request.buf_base_addr = NULL;
+		sg_free_table(&gsi->d_port.out_request.sgt_data_buff);
 	}
 
 	if (gsi->d_port.in_ep &&
@@ -2004,6 +2028,7 @@
 			gsi->d_port.in_request.buf_base_addr,
 			gsi->d_port.in_request.dma);
 		gsi->d_port.in_request.buf_base_addr = NULL;
+		sg_free_table(&gsi->d_port.in_request.sgt_data_buff);
 	}
 }
 
diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c
index cb00ada..9625248 100644
--- a/drivers/usb/gadget/function/f_serial.c
+++ b/drivers/usb/gadget/function/f_serial.c
@@ -31,13 +31,43 @@
 	struct gserial			port;
 	u8				data_id;
 	u8				port_num;
+	spinlock_t			lock;
+
+	struct usb_ep			*notify;
+	struct usb_request		*notify_req;
+
+	u8				online;
+	u8				pending;
+	struct usb_cdc_line_coding	port_line_coding;
+
+	/* SetControlLineState request */
+	u16				port_handshake_bits;
+#define ACM_CTRL_RTS	(1 << 1)	/* unused with full duplex */
+#define ACM_CTRL_DTR	(1 << 0)	/* host is ready for data r/w */
+
+	/* SerialState notification */
+	u16				serial_state;
+#define ACM_CTRL_OVERRUN	(1 << 6)
+#define ACM_CTRL_PARITY		(1 << 5)
+#define ACM_CTRL_FRAMING	(1 << 4)
+#define ACM_CTRL_RI		(1 << 3)
+#define ACM_CTRL_BRK		(1 << 2)
+#define ACM_CTRL_DSR		(1 << 1)
+#define ACM_CTRL_DCD		(1 << 0)
 };
 
+static inline struct f_gser *port_to_gser(struct gserial *p)
+{
+	return container_of(p, struct f_gser, port);
+}
+
 static inline struct f_gser *func_to_gser(struct usb_function *f)
 {
 	return container_of(f, struct f_gser, port.func);
 }
 
+#define GS_LOG2_NOTIFY_INTERVAL		5	/* 1 << 5 == 32 msec */
+#define GS_NOTIFY_MAXPACKET		10	/* notification + 2 bytes */
 /*-------------------------------------------------------------------------*/
 
 /* interface descriptor: */
@@ -46,15 +76,55 @@
 	.bLength =		USB_DT_INTERFACE_SIZE,
 	.bDescriptorType =	USB_DT_INTERFACE,
 	/* .bInterfaceNumber = DYNAMIC */
-	.bNumEndpoints =	2,
+	.bNumEndpoints =	3,
 	.bInterfaceClass =	USB_CLASS_VENDOR_SPEC,
 	.bInterfaceSubClass =	0,
 	.bInterfaceProtocol =	0,
 	/* .iInterface = DYNAMIC */
 };
 
+static struct usb_cdc_header_desc gser_header_desc  = {
+	.bLength =		sizeof(gser_header_desc),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
+	.bcdCDC =		cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_call_mgmt_descriptor
+gser_call_mgmt_descriptor  = {
+	.bLength =		sizeof(gser_call_mgmt_descriptor),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_CALL_MANAGEMENT_TYPE,
+	.bmCapabilities =	0,
+	/* .bDataInterface = DYNAMIC */
+};
+
+static struct usb_cdc_acm_descriptor gser_descriptor  = {
+	.bLength =		sizeof(gser_descriptor),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_ACM_TYPE,
+	.bmCapabilities =	USB_CDC_CAP_LINE,
+};
+
+static struct usb_cdc_union_desc gser_union_desc  = {
+	.bLength =		sizeof(gser_union_desc),
+	.bDescriptorType =	USB_DT_CS_INTERFACE,
+	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
+	/* .bMasterInterface0 =	DYNAMIC */
+	/* .bSlaveInterface0 =	DYNAMIC */
+};
+
 /* full speed support: */
 
+static struct usb_endpoint_descriptor gser_fs_notify_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	cpu_to_le16(GS_NOTIFY_MAXPACKET),
+	.bInterval =		1 << GS_LOG2_NOTIFY_INTERVAL,
+};
+
 static struct usb_endpoint_descriptor gser_fs_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
 	.bDescriptorType =	USB_DT_ENDPOINT,
@@ -71,12 +141,25 @@
 
 static struct usb_descriptor_header *gser_fs_function[] = {
 	(struct usb_descriptor_header *) &gser_interface_desc,
+	(struct usb_descriptor_header *) &gser_header_desc,
+	(struct usb_descriptor_header *) &gser_call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &gser_descriptor,
+	(struct usb_descriptor_header *) &gser_union_desc,
+	(struct usb_descriptor_header *) &gser_fs_notify_desc,
 	(struct usb_descriptor_header *) &gser_fs_in_desc,
 	(struct usb_descriptor_header *) &gser_fs_out_desc,
 	NULL,
 };
 
 /* high speed support: */
+static struct usb_endpoint_descriptor gser_hs_notify_desc  = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	cpu_to_le16(GS_NOTIFY_MAXPACKET),
+	.bInterval =		GS_LOG2_NOTIFY_INTERVAL+4,
+};
 
 static struct usb_endpoint_descriptor gser_hs_in_desc = {
 	.bLength =		USB_DT_ENDPOINT_SIZE,
@@ -94,6 +177,11 @@
 
 static struct usb_descriptor_header *gser_hs_function[] = {
 	(struct usb_descriptor_header *) &gser_interface_desc,
+	(struct usb_descriptor_header *) &gser_header_desc,
+	(struct usb_descriptor_header *) &gser_call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &gser_descriptor,
+	(struct usb_descriptor_header *) &gser_union_desc,
+	(struct usb_descriptor_header *) &gser_hs_notify_desc,
 	(struct usb_descriptor_header *) &gser_hs_in_desc,
 	(struct usb_descriptor_header *) &gser_hs_out_desc,
 	NULL,
@@ -118,8 +206,33 @@
 	.bDescriptorType =      USB_DT_SS_ENDPOINT_COMP,
 };
 
+static struct usb_endpoint_descriptor gser_ss_notify_desc  = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT,
+	.bEndpointAddress =	USB_DIR_IN,
+	.bmAttributes =		USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	cpu_to_le16(GS_NOTIFY_MAXPACKET),
+	.bInterval =		GS_LOG2_NOTIFY_INTERVAL+4,
+};
+
+static struct usb_ss_ep_comp_descriptor gser_ss_notify_comp_desc = {
+	.bLength =		sizeof(gser_ss_notify_comp_desc),
+	.bDescriptorType =	USB_DT_SS_ENDPOINT_COMP,
+
+	/* the following 2 values can be tweaked if necessary */
+	/* .bMaxBurst =		0, */
+	/* .bmAttributes =	0, */
+	.wBytesPerInterval =	cpu_to_le16(GS_NOTIFY_MAXPACKET),
+};
+
 static struct usb_descriptor_header *gser_ss_function[] = {
 	(struct usb_descriptor_header *) &gser_interface_desc,
+	(struct usb_descriptor_header *) &gser_header_desc,
+	(struct usb_descriptor_header *) &gser_call_mgmt_descriptor,
+	(struct usb_descriptor_header *) &gser_descriptor,
+	(struct usb_descriptor_header *) &gser_union_desc,
+	(struct usb_descriptor_header *) &gser_ss_notify_desc,
+	(struct usb_descriptor_header *) &gser_ss_notify_comp_desc,
 	(struct usb_descriptor_header *) &gser_ss_in_desc,
 	(struct usb_descriptor_header *) &gser_ss_bulk_comp_desc,
 	(struct usb_descriptor_header *) &gser_ss_out_desc,
@@ -130,7 +243,7 @@
 /* string descriptors: */
 
 static struct usb_string gser_string_defs[] = {
-	[0].s = "Generic Serial",
+	[0].s = "DUN over Serial",
 	{  } /* end of list */
 };
 
@@ -145,13 +258,131 @@
 };
 
 /*-------------------------------------------------------------------------*/
+static void gser_complete_set_line_coding(struct usb_ep *ep,
+					struct usb_request *req)
+{
+	struct f_gser            *gser = ep->driver_data;
+	struct usb_composite_dev *cdev = gser->port.func.config->cdev;
+
+	if (req->status != 0) {
+		dev_dbg(&cdev->gadget->dev, "gser ttyGS%d completion, err %d\n",
+				gser->port_num, req->status);
+		return;
+	}
+
+	/* normal completion */
+	if (req->actual != sizeof(gser->port_line_coding)) {
+		dev_dbg(&cdev->gadget->dev, "gser ttyGS%d short resp, len %d\n",
+				gser->port_num, req->actual);
+		usb_ep_set_halt(ep);
+	} else {
+		struct usb_cdc_line_coding *value = req->buf;
+
+		gser->port_line_coding = *value;
+	}
+}
+
+static int
+gser_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct f_gser            *gser = func_to_gser(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct usb_request       *req = cdev->req;
+	int                      value = -EOPNOTSUPP;
+	u16                      w_index = le16_to_cpu(ctrl->wIndex);
+	u16                      w_value = le16_to_cpu(ctrl->wValue);
+	u16                      w_length = le16_to_cpu(ctrl->wLength);
+
+
+	switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+
+	/* SET_LINE_CODING ... just read and save what the host sends */
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_REQ_SET_LINE_CODING:
+		if (w_length != sizeof(struct usb_cdc_line_coding))
+			goto invalid;
+
+		value = w_length;
+		cdev->gadget->ep0->driver_data = gser;
+		req->complete = gser_complete_set_line_coding;
+		break;
+
+	/* GET_LINE_CODING ... return what host sent, or initial value */
+	case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_REQ_GET_LINE_CODING:
+		value = min_t(unsigned int, w_length,
+				sizeof(struct usb_cdc_line_coding));
+		memcpy(req->buf, &gser->port_line_coding, value);
+		break;
+
+	/* SET_CONTROL_LINE_STATE ... save what the host sent */
+	case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+			| USB_CDC_REQ_SET_CONTROL_LINE_STATE:
+
+		value = 0;
+		gser->port_handshake_bits = w_value;
+		pr_debug("%s: USB_CDC_REQ_SET_CONTROL_LINE_STATE: DTR:%d RST:%d\n",
+			__func__, w_value & ACM_CTRL_DTR ? 1 : 0,
+			w_value & ACM_CTRL_RTS ? 1 : 0);
+
+		if (gser->port.notify_modem)
+			gser->port.notify_modem(&gser->port, 0, w_value);
+
+		break;
+
+	default:
+invalid:
+		dev_dbg(&cdev->gadget->dev,
+			"invalid control req%02x.%02x v%04x i%04x l%d\n",
+			ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+	}
+
+	/* respond with data transfer or status phase? */
+	if (value >= 0) {
+		dev_dbg(&cdev->gadget->dev,
+			"gser ttyGS%d req%02x.%02x v%04x i%04x l%d\n",
+			gser->port_num, ctrl->bRequestType, ctrl->bRequest,
+			w_value, w_index, w_length);
+		req->zero = 0;
+		req->length = value;
+		value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+		if (value < 0)
+			ERROR(cdev, "gser response on ttyGS%d, err %d\n",
+					gser->port_num, value);
+	}
+
+	/* device either stalls (value < 0) or reports success */
+	return value;
+}
 
 static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 {
 	struct f_gser		*gser = func_to_gser(f);
 	struct usb_composite_dev *cdev = f->config->cdev;
+	int rc = 0;
 
 	/* we know alt == 0, so this is an activation or a reset */
+	if (gser->notify->driver_data) {
+		dev_dbg(&cdev->gadget->dev,
+			"reset generic ctl ttyGS%d\n", gser->port_num);
+		usb_ep_disable(gser->notify);
+	}
+
+	if (!gser->notify->desc) {
+		if (config_ep_by_speed(cdev->gadget, f, gser->notify)) {
+			gser->notify->desc = NULL;
+			return -EINVAL;
+		}
+	}
+
+	rc = usb_ep_enable(gser->notify);
+	if (rc) {
+		ERROR(cdev, "can't enable %s, result %d\n",
+			gser->notify->name, rc);
+		return rc;
+	}
+	gser->notify->driver_data = gser;
 
 	if (gser->port.in->enabled) {
 		dev_dbg(&cdev->gadget->dev,
@@ -169,7 +400,9 @@
 		}
 	}
 	gserial_connect(&gser->port, gser->port_num);
-	return 0;
+	gser->online = 1;
+
+	return rc;
 }
 
 static void gser_disable(struct usb_function *f)
@@ -180,6 +413,178 @@
 	dev_dbg(&cdev->gadget->dev,
 		"generic ttyGS%d deactivated\n", gser->port_num);
 	gserial_disconnect(&gser->port);
+	usb_ep_disable(gser->notify);
+	gser->notify->driver_data = NULL;
+	gser->online = 0;
+}
+
+static int gser_notify(struct f_gser *gser, u8 type, u16 value,
+		void *data, unsigned int length)
+{
+	struct usb_ep			*ep = gser->notify;
+	struct usb_request		*req;
+	struct usb_cdc_notification	*notify;
+	const unsigned int		len = sizeof(*notify) + length;
+	void                            *buf;
+	int                             status;
+	struct usb_composite_dev *cdev = gser->port.func.config->cdev;
+
+	req = gser->notify_req;
+	gser->notify_req = NULL;
+	gser->pending = false;
+
+	req->length = len;
+	notify = req->buf;
+	buf = notify + 1;
+
+	notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
+			| USB_RECIP_INTERFACE;
+	notify->bNotificationType = type;
+	notify->wValue = cpu_to_le16(value);
+	notify->wIndex = cpu_to_le16(gser->data_id);
+	notify->wLength = cpu_to_le16(length);
+	memcpy(buf, data, length);
+
+	status = usb_ep_queue(ep, req, GFP_ATOMIC);
+	if (status < 0) {
+		ERROR(cdev, "gser ttyGS%d can't notify serial state, %d\n",
+				gser->port_num, status);
+		gser->notify_req = req;
+	}
+
+	return status;
+}
+
+static int gser_notify_serial_state(struct f_gser *gser)
+{
+	int		status;
+	unsigned long	flags;
+	struct usb_composite_dev *cdev = gser->port.func.config->cdev;
+
+	spin_lock_irqsave(&gser->lock, flags);
+	if (gser->notify_req) {
+		DBG(cdev, "gser ttyGS%d serial state %04x\n",
+				gser->port_num, gser->serial_state);
+		status = gser_notify(gser, USB_CDC_NOTIFY_SERIAL_STATE,
+				0, &gser->serial_state,
+				sizeof(gser->serial_state));
+	} else {
+		gser->pending = true;
+		status = 0;
+	}
+
+	spin_unlock_irqrestore(&gser->lock, flags);
+	return status;
+}
+
+static void gser_notify_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_gser *gser = req->context;
+	u8            doit = false;
+	unsigned long flags;
+
+	/* on this call path we do NOT hold the port spinlock,
+	 * which is why ACM needs its own spinlock
+	 */
+
+	spin_lock_irqsave(&gser->lock, flags);
+	if (req->status != -ESHUTDOWN)
+		doit = gser->pending;
+
+	gser->notify_req = req;
+	spin_unlock_irqrestore(&gser->lock, flags);
+
+	if (doit && gser->online)
+		gser_notify_serial_state(gser);
+}
+
+static void gser_connect(struct gserial *port)
+{
+	struct f_gser *gser = port_to_gser(port);
+
+	gser->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD;
+	gser_notify_serial_state(gser);
+}
+
+static unsigned int gser_get_dtr(struct gserial *port)
+{
+	struct f_gser *gser = port_to_gser(port);
+
+	if (gser->port_handshake_bits & ACM_CTRL_DTR)
+		return 1;
+	else
+		return 0;
+}
+
+static unsigned int gser_get_rts(struct gserial *port)
+{
+	struct f_gser *gser = port_to_gser(port);
+
+	if (gser->port_handshake_bits & ACM_CTRL_RTS)
+		return 1;
+	else
+		return 0;
+}
+
+static unsigned int gser_send_carrier_detect(struct gserial *port,
+	unsigned int yes)
+{
+	u16	state;
+	struct f_gser *gser = port_to_gser(port);
+
+	state = gser->serial_state;
+	state &= ~ACM_CTRL_DCD;
+	if (yes)
+		state |= ACM_CTRL_DCD;
+
+	gser->serial_state = state;
+	return gser_notify_serial_state(gser);
+}
+
+static unsigned int gser_send_ring_indicator(struct gserial *port,
+	unsigned int yes)
+{
+	u16	state;
+	struct f_gser *gser = port_to_gser(port);
+
+	state = gser->serial_state;
+	state &= ~ACM_CTRL_RI;
+	if (yes)
+		state |= ACM_CTRL_RI;
+
+	gser->serial_state = state;
+	return gser_notify_serial_state(gser);
+}
+
+static void gser_disconnect(struct gserial *port)
+{
+	struct f_gser *gser = port_to_gser(port);
+
+	gser->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD);
+	gser_notify_serial_state(gser);
+}
+
+static int gser_send_break(struct gserial *port, int duration)
+{
+	u16	state;
+	struct f_gser *gser = port_to_gser(port);
+
+	state = gser->serial_state;
+	state &= ~ACM_CTRL_BRK;
+	if (duration)
+		state |= ACM_CTRL_BRK;
+
+	gser->serial_state = state;
+	return gser_notify_serial_state(gser);
+}
+
+static int gser_send_modem_ctrl_bits(struct gserial *port, int ctrl_bits)
+{
+	struct f_gser *gser = port_to_gser(port);
+
+	gser->serial_state = ctrl_bits;
+
+	return gser_notify_serial_state(gser);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -225,6 +630,21 @@
 		goto fail;
 	gser->port.out = ep;
 
+	ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_notify_desc);
+	if (!ep)
+		goto fail;
+	gser->notify = ep;
+	ep->driver_data = cdev;	/* claim */
+	/* allocate notification */
+	gser->notify_req = gs_alloc_req(ep,
+			sizeof(struct usb_cdc_notification) + 2,
+			GFP_KERNEL);
+	if (!gser->notify_req)
+		goto fail;
+
+	gser->notify_req->complete = gser_notify_complete;
+	gser->notify_req->context = gser;
+
 	/* support all relevant hardware speeds... we expect that when
 	 * hardware is dual speed, all bulk-capable endpoints work at
 	 * both speeds
@@ -235,6 +655,15 @@
 	gser_ss_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress;
 	gser_ss_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress;
 
+	if (gadget_is_dualspeed(c->cdev->gadget)) {
+		gser_hs_notify_desc.bEndpointAddress =
+				gser_fs_notify_desc.bEndpointAddress;
+	}
+	if (gadget_is_superspeed(c->cdev->gadget)) {
+		gser_ss_notify_desc.bEndpointAddress =
+				gser_fs_notify_desc.bEndpointAddress;
+	}
+
 	status = usb_assign_descriptors(f, gser_fs_function, gser_hs_function,
 			gser_ss_function, NULL);
 	if (status)
@@ -247,6 +676,18 @@
 	return 0;
 
 fail:
+	if (gser->notify_req)
+		gs_free_req(gser->notify, gser->notify_req);
+
+	/* we might as well release our claims on endpoints */
+	if (gser->notify)
+		gser->notify->driver_data = NULL;
+	/* we might as well release our claims on endpoints */
+	if (gser->port.out)
+		gser->port.out->driver_data = NULL;
+	if (gser->port.in)
+		gser->port.in->driver_data = NULL;
+
 	ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
 
 	return status;
@@ -327,7 +768,10 @@
 
 static void gser_unbind(struct usb_configuration *c, struct usb_function *f)
 {
+	struct f_gser *gser = func_to_gser(f);
+
 	usb_free_all_descriptors(f);
+	gs_free_req(gser->notify, gser->notify_req);
 }
 
 static struct usb_function *gser_alloc(struct usb_function_instance *fi)
@@ -342,6 +786,7 @@
 
 	opts = container_of(fi, struct f_serial_opts, func_inst);
 
+	spin_lock_init(&gser->lock);
 	gser->port_num = opts->port_num;
 
 	gser->port.func.name = "gser";
@@ -351,6 +796,15 @@
 	gser->port.func.set_alt = gser_set_alt;
 	gser->port.func.disable = gser_disable;
 	gser->port.func.free_func = gser_free;
+	gser->port.func.setup = gser_setup;
+	gser->port.connect = gser_connect;
+	gser->port.get_dtr = gser_get_dtr;
+	gser->port.get_rts = gser_get_rts;
+	gser->port.send_carrier_detect = gser_send_carrier_detect;
+	gser->port.send_ring_indicator = gser_send_ring_indicator;
+	gser->port.send_modem_ctrl_bits = gser_send_modem_ctrl_bits;
+	gser->port.disconnect = gser_disconnect;
+	gser->port.send_break = gser_send_break;
 
 	return &gser->port.func;
 }
diff --git a/drivers/usb/gadget/function/u_serial.h b/drivers/usb/gadget/function/u_serial.h
index c20210c..f367dc5 100644
--- a/drivers/usb/gadget/function/u_serial.h
+++ b/drivers/usb/gadget/function/u_serial.h
@@ -45,11 +45,23 @@
 
 	/* REVISIT avoid this CDC-ACM support harder ... */
 	struct usb_cdc_line_coding port_line_coding;	/* 9600-8-N-1 etc */
+	u16				serial_state;
+
+	/* control signal callbacks*/
+	unsigned int (*get_dtr)(struct gserial *p);
+	unsigned int (*get_rts)(struct gserial *p);
 
 	/* notification callbacks */
 	void (*connect)(struct gserial *p);
 	void (*disconnect)(struct gserial *p);
 	int (*send_break)(struct gserial *p, int duration);
+	unsigned int (*send_carrier_detect)(struct gserial *p,
+			unsigned int yes);
+	unsigned int (*send_ring_indicator)(struct gserial *p,
+			unsigned int yes);
+	int (*send_modem_ctrl_bits)(struct gserial *p, int ctrl_bits);
+	/* notification changes to modem */
+	void (*notify_modem)(void *gser, u8 portno, int ctrl_bits);
 };
 
 /* utilities to allocate/free request and buffer */
diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c
index cce17e0..cc1a0ea 100644
--- a/drivers/usb/phy/phy-msm-qusb-v2.c
+++ b/drivers/usb/phy/phy-msm-qusb-v2.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/usb/phy.h>
 #include <linux/reset.h>
+#include <linux/nvmem-consumer.h>
 #include <linux/debugfs.h>
 #include <linux/hrtimer.h>
 
@@ -146,8 +147,65 @@
 	u8			tune[5];
 
 	struct hrtimer		timer;
+	int			soc_min_rev;
 };
 
+#ifdef CONFIG_NVMEM
+/* Parse qfprom data for deciding on errata work-arounds */
+static long qfprom_read(struct device *dev, const char *name)
+{
+	struct nvmem_cell *cell;
+	ssize_t len = 0;
+	u32 *buf, val = 0;
+	long err = 0;
+
+	cell = nvmem_cell_get(dev, name);
+	if (IS_ERR(cell)) {
+		err = PTR_ERR(cell);
+		dev_err(dev, "failed opening nvmem cell err : %ld\n", err);
+		/* If entry does not exist, then that is not an error */
+		if (err == -ENOENT)
+			err = 0;
+		return err;
+	}
+
+	buf = (u32 *)nvmem_cell_read(cell, &len);
+	if (IS_ERR(buf) || !len) {
+		dev_err(dev, "Failed reading nvmem cell, err: %u, bytes fetched: %zd\n",
+				*buf, len);
+		if (!IS_ERR(buf)) {
+			kfree(buf);
+			err = -EINVAL;
+		} else {
+			err = PTR_ERR(buf);
+		}
+	} else {
+		val = *buf;
+		kfree(buf);
+	}
+
+	nvmem_cell_put(cell);
+	return err ? err : (long) val;
+}
+
+/* Reads the SoC version */
+static int qusb_phy_get_socrev(struct device *dev, struct qusb_phy *qphy)
+{
+	qphy->soc_min_rev  = qfprom_read(dev, "minor_rev");
+	if (qphy->soc_min_rev < 0)
+		dev_err(dev, "failed getting soc_min_rev, err : %d\n",
+				qphy->soc_min_rev);
+
+	return qphy->soc_min_rev;
+};
+#else
+/* Reads the SoC version */
+static int qusb_phy_get_socrev(struct device *dev, struct qusb_phy *qphy)
+{
+	return 0;
+}
+#endif
+
 static void qusb_phy_enable_clocks(struct qusb_phy *qphy, bool on)
 {
 	dev_dbg(qphy->phy.dev, "%s(): clocks_enabled:%d on:%d\n",
@@ -1125,6 +1183,11 @@
 		return PTR_ERR(qphy->vdda18);
 	}
 
+	ret = qusb_phy_get_socrev(&pdev->dev, qphy);
+	if (ret == -EPROBE_DEFER) {
+		dev_err(&pdev->dev, "SoC version rd: fail: defer for now\n");
+		return ret;
+	}
 	qphy->pinctrl = devm_pinctrl_get(dev);
 	if (IS_ERR(qphy->pinctrl)) {
 		ret = PTR_ERR(qphy->pinctrl);
@@ -1159,7 +1222,14 @@
 	qphy->phy.type			= USB_PHY_TYPE_USB2;
 	qphy->phy.notify_connect        = qusb_phy_notify_connect;
 	qphy->phy.notify_disconnect     = qusb_phy_notify_disconnect;
-	qphy->phy.disable_chirp		= qusb_phy_disable_chirp;
+
+	/*
+	 * qusb_phy_disable_chirp is not required if soc version is
+	 * mentioned and is not base version.
+	 */
+	if (qphy->soc_min_rev == 0)
+		qphy->phy.disable_chirp	= qusb_phy_disable_chirp;
+
 	qphy->phy.start_port_reset	= qusb_phy_enable_ext_pulldown;
 
 	ret = usb_add_phy_dev(&qphy->phy);
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index 0d442e3..47f5ba6 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -199,7 +199,7 @@
 extern void clockevents_resume(void);
 
 # ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
-#  ifdef CONFIG_ARCH_HAS_TICK_BROADCAST
+#  if defined(CONFIG_ARCH_HAS_TICK_BROADCAST) && defined(CONFIG_SMP)
 extern void tick_broadcast(const struct cpumask *mask);
 #  else
 #   define tick_broadcast	NULL
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 972dabc..3fda92f 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -84,6 +84,8 @@
  * @db_reg_phs_addr_lsb: IPA channel doorbell register's physical address LSB
  * @mapped_db_reg_phs_addr_lsb: doorbell LSB IOVA address mapped with IOMMU
  * @db_reg_phs_addr_msb: IPA channel doorbell register's physical address MSB
+ * @sgt_trb_xfer_ring: USB TRB ring related sgtable entries
+ * @sgt_data_buff: Data buffer related sgtable entries
  */
 struct usb_gsi_request {
 	void *buf_base_addr;
@@ -93,6 +95,8 @@
 	u32 db_reg_phs_addr_lsb;
 	dma_addr_t mapped_db_reg_phs_addr_lsb;
 	u32 db_reg_phs_addr_msb;
+	struct sg_table sgt_trb_xfer_ring;
+	struct sg_table sgt_data_buff;
 };
 
 /*
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 5edfe66..64ec233 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -263,6 +263,7 @@
 			 * this case. -DaveM
 			 */
 			pr_debug("end of fragment not rounded to 8 bytes.\n");
+			inet_frag_kill(&fq->q, &nf_frags);
 			return -EPROTO;
 		}
 		if (end > fq->q.len) {
diff --git a/net/rmnet_data/rmnet_data_handlers.c b/net/rmnet_data/rmnet_data_handlers.c
index 8faf7a7..50dd516 100644
--- a/net/rmnet_data/rmnet_data_handlers.c
+++ b/net/rmnet_data/rmnet_data_handlers.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -453,6 +453,13 @@
 	}
 
 	ep = &config->muxed_ep[mux_id];
+	if (!ep->refcount) {
+		LOGD("Packet on %s:%d; has no logical endpoint config",
+		     skb->dev->name, mux_id);
+
+		rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_MAPINGRESS_MUX_NO_EP);
+		return RX_HANDLER_CONSUMED;
+	}
 
 	skb->dev = ep->egress_dev;
 
diff --git a/net/rmnet_data/rmnet_data_stats.h b/net/rmnet_data/rmnet_data_stats.h
index 366e486..75ed434 100644
--- a/net/rmnet_data/rmnet_data_stats.h
+++ b/net/rmnet_data/rmnet_data_stats.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016, 2018 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,6 +39,7 @@
 	RMNET_STATS_SKBFREE_DEAGG_DATA_LEN_0,
 	RMNET_STATS_SKBFREE_INGRESS_BAD_MAP_CKSUM,
 	RMNET_STATS_SKBFREE_MAPC_UNSUPPORTED,
+	RMNET_STATS_SKBFREE_MAPINGRESS_MUX_NO_EP,
 	RMNET_STATS_SKBFREE_MAX
 };
 
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index ff9887f..7fe91b1 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -54,7 +54,8 @@
 
 country AR:
 	(2402 - 2482 @ 40), (36)
-	(5170 - 5330 @ 160), (23)
+	(5170 - 5250 @ 80), (23), AUTO-BW
+	(5250 - 5330 @ 80), (36), AUTO-BW
 	(5490 - 5590 @ 80), (36)
 	(5650 - 5730 @ 80), (36)
 	(5735 - 5835 @ 80), (36)
diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index 7712e2b..4783648 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -122,7 +122,7 @@
 	case USB_SPEED_SUPER:
 	case USB_SPEED_SUPER_PLUS:
 		if (get_endpoint(alts, 0)->bInterval >= 1 &&
-		    get_endpoint(alts, 0)->bInterval <= 4)
+		    get_endpoint(alts, 0)->bInterval <= 16)
 			return get_endpoint(alts, 0)->bInterval - 1;
 		break;
 	default: