Merge "mm: vmalloc: don't print lowmem information"
diff --git a/Documentation/devicetree/bindings/input/qti-haptics.txt b/Documentation/devicetree/bindings/input/qti-haptics.txt
new file mode 100644
index 0000000..2c4f4f0
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/qti-haptics.txt
@@ -0,0 +1,202 @@
+Qualcomm Technologies, Inc. Haptics driver
+
+Haptics peripheral in QTI PMICs can support different type of actuators or
+vibrators:
+  1) Eccentric Rotation Mass (ERM);
+  2) Linear Resonant Actuator (LRA).
+This binding document describes the properties for this module.
+
+Properties:
+
+- compatible
+  Usage:      required
+  Value type: <string>
+  Definition: It can be one of the following:
+		"qcom,haptics",
+		"qcom,pm660-haptics",
+		"qcom,pm8150b-haptics".
+
+- reg
+  Usage:      required
+  Value type: <u32>
+  Definition: Base address of haptics peripheral.
+
+- interrupts
+  Usage:      required
+  Value type: <prop-encoded-array>
+  Definition: Peripheral interrupt specifier.
+
+- interrupt-names
+  Usage:      required
+  Value type: <stringlist>
+  Definition: Interrupt names.  This list must match up 1-to-1 with the
+		interrupts specified in the 'interrupts' property. Following
+		interrupts are required: "hap_play_irq", "hap_sc_irq".
+
+- qcom,actuator-type
+  Usage:      optional
+  Value type: <string>
+  Definition: Specifies the type of the actuator connected on the output of
+		haptics module. Allowed values: "erm", "lra". If this is
+		not specified, then LRA type will be used by default.
+
+- qcom,vmax-mv
+  Usage:      optional
+  Value type: <u32>
+  Definition: Specifies the maximum allowed output voltage in millivolts
+		for the actuator. Value specified here will be rounded
+		off to the closest multiple of 116 mV. Allowed values:
+		0 to 3596. If this is not specified, then 1800 mV will be
+		used by default.
+
+- qcom,ilim-ma
+  Usage:      optional
+  Value type: <u32>
+  Definition: Specifies the maximum allowed output current in mA for the
+		actuator. Allowed values: 400 or 800. If this is not
+		specified, 400 mA will be used by default.
+
+- qcom,play-rate-us
+  Usage:      optional
+  Value type: <u32>
+  Definition: Specifies the period at which each sample of the 8-byte waveform
+		registers is played. For ERM, this period is flexible and it
+		can be chosen based on the desired shape of the pattern.
+		For LRA, it should be set equal to the resonance period
+		specified in the LRA actuator datasheet. Allowed values are:
+		0 to 20475. If this is not specified, 5715us play rate is used.
+
+- qcom,external-waveform-source
+  Usage:      optional
+  Value type: <string>
+  Definition: The haptics module supports to play with internal constant
+		Vmax strength or play with patterns specified in its internal
+		8-bytes waveform buffer. It can also play with the audio
+		LINE-IN signal or PWM waveform coming from LINE-IN/PWM pin.
+		This property specify the kind of the waveform resources
+		on the LINE-IN/PWM pins. Allowed values are: "audio", "pwm".
+		If this is not specified, internal signals (Vmax or buffer)
+		will be selected according to the requriement of the playing
+		waveforms.
+
+- vdd-supply
+  Usage:      optional
+  Value type: <phandle>
+  Definition: Specifies the phandle of the regulator device which supplies
+		haptics module through VDD_HAP pin. This is only needed if VDD_HAP
+		is supplied from an external boost regulator instead of VPH_PWR.
+
+Following properties are specific only when LRA actuator is used:
+
+- qcom,lra-resonance-sig-shape
+  Usage:      optional
+  Value type: <string>
+  Definition: Specifies the shape of the LRA resonance drive signal. Allowed
+		values: "sine", "square". If this is not specified, sinusoid
+		resonance driver signal is used.
+
+- qcom,lra-allow-variable-play-rate
+  Usage:      optional
+  Value type: <empty>
+  Definition: If specified, "qcom,wf-play-rate-us" for LRA defined in each
+		effect could be different with the resonance period of the
+		LRA actuator.
+
+- qcom,lra-auto-resonance-mode
+  Usage:      optional
+  Value type: <string>
+  Definition: Specifies the auto resonance technique for LRA. Allowed values are:
+		"zxd": zero crossing based discontinuous method;
+		"qwd": quarter wave drive method;
+
+Following properties could be specified in child nodes for defining vibrating
+waveforms/effects:
+
+- qcom,effect-id
+  Usage:      required
+  Value type: <u32>
+  Definition: Specifies the effect ID that the client can request to play the
+		corresponding waveform defined in this child node. The ID is
+		normaly defined and sent from userspace for certain user
+		notification event.
+
+- qcom,wf-pattern
+  Usage:      required
+  Value type: <prop-encoded-array>
+  Definition: Specifies the waveform pattern in a byte array that will be
+		played for the effect-id. The bit fields of each byte are:
+		 [7]: drive direction, 0 - forward; 1 - reverse
+		 [6]: overdrive, 0 -- 1x drive; 1 -- 2x drive
+		 [5:1]: waveform amplitude
+		 [0]: reserved.
+
+- qcom,wf-play-rate-us
+  Usage:      optional
+  Value type: <u32>
+  Definition: Specifies the play period in microseconds for each byte pattern.
+		Allowed values are: 0 to 20475. For LRA actuator, if
+		"qcom,lra-allow-variable-play-rate" is defined, it could be
+		set to other values not equal to the resonance period of the
+		LRA actuator.
+
+- qcom,wf-repeat-count
+  Usage:      optional
+  Value type: <u32>
+  Definition: Specifies the repeat times for the waveform pattern. Allowed
+		values are: 1, 2, 4, 8, 16, 32, 64, 128.
+
+- qcom,wf-s-repeat-count
+  Usage:      optional
+  Value type: <u32>
+  Definition: Specifies the repeat times for each sample defined in
+		qcom,wf-pattern. Allowed values are: 1, 2, 4, 8.
+
+- qcom,wf-brake-pattern
+  Usage:      optional
+  Value type: <prop-encoded-array>
+  Definition: Specifies the brake pattern with 4 elements used to enable the
+		internal reverse braking. Allowed values for each element are:
+			0: no brake
+			1: brake with (Vmax / 2) strength
+			2: brake with Vmax strength
+			3: brake with (2 * Vmax) strength
+		If this property is specified with an array of non-zero values,
+		then the brake pattern is applied at the end of the playing
+		waveform.
+
+- qcom,lra-auto-resonance-disable
+  Usage:      optional
+  Value type: <empty>
+  Definition: If specified, the hardware feature of LRA auto resonance detection
+		is disabled.
+
+Example:
+  qcom,haptics@c000 {
+	compatible = "qcom,haptics";
+	reg = <0xc000 0x100>;
+	interrupts = <0x3 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
+		     <0x3 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
+	interrupt-names = "hap-sc-irq", "hap-play-irq";
+	qcom,actuator-type = "lra";
+	qcom,vmax-mv = <1800>;
+	qcom,ilim-ma = <400>;
+	qcom,play-rate-us = <8000>;
+	qcom,lra-resonance-sig-shape = "sine";
+	qcom,lra-auto-resonance-mode = "qwd";
+	qcom,lra-allow-variable-play-rate;
+
+	wf_0 {
+		/* CLICK effect */
+		qcom,effect-id = <0>;
+		qcom,wf-play-rate-us = <6250>;
+		qcom,wf-pattern = [3e 3e 3e];
+		qcom,lra-auto-resonance-disable;
+	};
+
+	wf_5 {
+		/* HEAVY_CLICK effect */
+		qcom,effect-id = <5>;
+		qcom,wf-play-rate-us = <6250>;
+		qcom,wf-pattern = [7e 7e 7e];
+	};
+  };
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
index 54ff110..c8fa87c 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp-flash-v2.txt
@@ -24,11 +24,11 @@
 			  128, 192. Unit is uS.
 - qcom,short-circuit-det	: Boolean property which enables short circuit fault detection.
 - qcom,open-circuit-det		: Boolean property which enables open circuit fault detection.
-- qcom,vph-droop-det	: Boolean property which enables VPH droop detection.
-- qcom,vph-droop-hys-mv	: Integer property to specify VPH droop hysteresis. It is only used if
-			  qcom,vph-droop-det is specified. Valid values are 0, 25, 50 and 75.
-			  Unit is mV.
-- qcom,vph-droop-thresh-mv	: Integer property to specify VPH droop threshold. It is only used if
+- qcom,vph-droop-det		: Boolean property which enables VPH droop detection.
+- qcom,vph-droop-hysteresis-mv	: Integer property to specify VPH droop hysteresis. It is only used if
+				  qcom,vph-droop-det is specified. Valid values are 0, 25, 50 and 75.
+				  Unit is mV.
+- qcom,vph-droop-threshold-mv	: Integer property to specify VPH droop threshold. It is only used if
 				  qcom,vph-droop-det is specified. Valid values are
 				  2500 to 3200 with step size of 100. Unit is mV.
 - qcom,vph-droop-debounce-us	: Integer property to specify VPH droop debounce time. It is only used
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index 1670708..ddcb90c 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -306,6 +306,7 @@
   devm_request_any_context_irq()
   devm_request_irq()
   devm_request_threaded_irq()
+  devm_irq_sim_init()
 
 LED
   devm_led_classdev_register()
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index 824eefa..b5734c5 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -11,7 +11,9 @@
 	sdxpoorwills-pcie-ep-cdp-256.dtb \
 	sdxpoorwills-pcie-ep-mtp-256.dtb \
 	sdxpoorwills-pcie-ep-cdp.dtb \
-	sdxpoorwills-pcie-ep-mtp.dtb
+	sdxpoorwills-pcie-ep-mtp.dtb \
+	sdxpoorwills-v2-mtp.dtb \
+	sdxpoorwills-v2-cdp.dtb
 
 dtb-$(CONFIG_ARCH_MDM9650) += mdm9650-nand-mtp.dtb \
 	mdm9650-ttp.dtb \
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
index 642a541..0d36f2a 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
@@ -33,6 +33,7 @@
 		qcom,dwc-usb3-msm-tx-fifo-size = <21288>;
 		qcom,num-gsi-evt-buffs = <0x3>;
 		qcom,use-pdc-interrupts;
+		qcom,pm-qos-latency = <2 241 271>;
 
 		clocks = <&clock_gcc GCC_USB30_MASTER_CLK>,
 			 <&clock_gcc GCC_SYS_NOC_USB3_CLK>,
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-v2-cdp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-v2-cdp.dts
new file mode 100644
index 0000000..4ac0117
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-v2-cdp.dts
@@ -0,0 +1,29 @@
+/* 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 "sdxpoorwills-cdp.dtsi"
+#include "sdxpoorwills-v2.dtsi"
+#include "sdxpoorwills-display.dtsi"
+#include "qpic-panel-ili-hvga.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDXPOORWILLS CDP V2";
+	compatible = "qcom,sdxpoorwills-cdp",
+		"qcom,sdxpoorwills", "qcom,cdp";
+	qcom,board-id = <1 0x102>;
+};
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-v2-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-v2-mtp.dts
new file mode 100644
index 0000000..29f77de
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-v2-mtp.dts
@@ -0,0 +1,31 @@
+/* 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 "sdxpoorwills-mtp.dtsi"
+#include "sdxpoorwills-v2.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDXPOORWILLS MTP V2";
+	compatible = "qcom,sdxpoorwills-mtp",
+		"qcom,sdxpoorwills", "qcom,mtp";
+	qcom,board-id = <8 0x102>;
+};
+
+&qcom_seecom {
+	status = "okay";
+};
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi
new file mode 100644
index 0000000..eef2ffb
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-v2.dtsi
@@ -0,0 +1,22 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDXPOORWILLS V2";
+	compatible = "qcom,sdxpoorwills";
+	qcom,msm-id = <334 0x20000>, <335 0x20000>;
+};
+
+&emac_hw {
+	emac-core-version = <5>;
+};
diff --git a/arch/arm/configs/msm8909-perf_defconfig b/arch/arm/configs/msm8909-perf_defconfig
index b4ae846..3d30af6 100644
--- a/arch/arm/configs/msm8909-perf_defconfig
+++ b/arch/arm/configs/msm8909-perf_defconfig
@@ -300,6 +300,7 @@
 CONFIG_REGULATOR_COOLING_DEVICE=y
 CONFIG_MFD_QCOM_RPM=y
 CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_PROXY_CONSUMER=y
@@ -424,6 +425,7 @@
 CONFIG_MSM_PIL_SSR_GENERIC=y
 CONFIG_MSM_PIL_MSS_QDSP6V5=y
 CONFIG_MSM_EVENT_TIMER=y
+CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_MSM_BAM_DMUX=y
 CONFIG_WCNSS_CORE=y
@@ -437,6 +439,7 @@
 CONFIG_QTI_MPM=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_IPC_32BIT=y
 CONFIG_STM=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
diff --git a/arch/arm/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig
index 4d1bda0..787b38e 100644
--- a/arch/arm/configs/msm8909_defconfig
+++ b/arch/arm/configs/msm8909_defconfig
@@ -479,6 +479,7 @@
 CONFIG_QTI_MPM=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_IPC_32BIT=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
 CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index 0e56f7f..4ee0854 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -80,6 +80,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPVTI=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
@@ -91,6 +92,7 @@
 CONFIG_INET6_ESP=y
 CONFIG_INET6_IPCOMP=y
 CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_VTI=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_NETFILTER=y
@@ -122,6 +124,7 @@
 CONFIG_NETFILTER_XT_TARGET_TRACE=y
 CONFIG_NETFILTER_XT_TARGET_SECMARK=y
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_BPF=y
 CONFIG_NETFILTER_XT_MATCH_COMMENT=y
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -468,6 +471,7 @@
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
 CONFIG_FRAME_WARN=2048
+CONFIG_MAGIC_SYSRQ=y
 CONFIG_PAGE_EXTENSION=y
 CONFIG_PANIC_ON_RECURSIVE_FAULT=y
 CONFIG_WQ_WATCHDOG=y
@@ -486,6 +490,7 @@
 CONFIG_HARDENED_USERCOPY=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_GCM=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm/configs/msm8909w_defconfig b/arch/arm/configs/msm8909w_defconfig
index 8351322..848c256 100644
--- a/arch/arm/configs/msm8909w_defconfig
+++ b/arch/arm/configs/msm8909w_defconfig
@@ -81,6 +81,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPVTI=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
@@ -92,6 +93,7 @@
 CONFIG_INET6_ESP=y
 CONFIG_INET6_IPCOMP=y
 CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_VTI=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_NETFILTER=y
@@ -124,6 +126,7 @@
 CONFIG_NETFILTER_XT_TARGET_TRACE=y
 CONFIG_NETFILTER_XT_TARGET_SECMARK=y
 CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_BPF=y
 CONFIG_NETFILTER_XT_MATCH_COMMENT=y
 CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
 CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -343,6 +346,8 @@
 CONFIG_USB_CONFIGFS_RMNET_BAM=y
 CONFIG_USB_CONFIGFS_MASS_STORAGE=y
 CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
 CONFIG_USB_CONFIGFS_F_ACC=y
 CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
 CONFIG_USB_CONFIGFS_UEVENT=y
@@ -463,6 +468,7 @@
 CONFIG_FRAME_WARN=2048
 CONFIG_PAGE_OWNER=y
 CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
+CONFIG_MAGIC_SYSRQ=y
 CONFIG_SLUB_DEBUG_PANIC_ON=y
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_MEMORY_INIT=y
@@ -513,7 +519,7 @@
 CONFIG_HARDENED_USERCOPY=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SMACK=y
-CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_GCM=y
 CONFIG_CRYPTO_XTS=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
diff --git a/arch/arm/configs/msm8937-perf_defconfig b/arch/arm/configs/msm8937-perf_defconfig
index e9a5237..26d0d06 100644
--- a/arch/arm/configs/msm8937-perf_defconfig
+++ b/arch/arm/configs/msm8937-perf_defconfig
@@ -41,6 +41,7 @@
 CONFIG_BPF_SYSCALL=y
 # CONFIG_MEMBARRIER is not set
 CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
 CONFIG_CC_STACKPROTECTOR_STRONG=y
diff --git a/arch/arm/configs/sdm670-perf_defconfig b/arch/arm/configs/sdm670-perf_defconfig
new file mode 100644
index 0000000..2f003b9
--- /dev/null
+++ b/arch/arm/configs/sdm670-perf_defconfig
@@ -0,0 +1,567 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_FHANDLE is not set
+CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_SCHED_WALT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_RCU_EXPERT=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_ALL=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHEDTUNE=y
+CONFIG_BLK_CGROUP=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_BPF=y
+CONFIG_SCHED_CORE_CTL=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_AIO is not set
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_SDM670=y
+CONFIG_PCI_MSM=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_NR_CPUS=8
+CONFIG_ARM_PSCI=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
+CONFIG_CMA=y
+CONFIG_ZSMALLOC=y
+CONFIG_BALANCE_ANON_FILE_RECLAIM=y
+CONFIG_SECCOMP=y
+CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_KERNEL_MODE_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TEE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_RPFILTER=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RPFILTER=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_L2TP=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_SKBEDIT=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_BT=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+# CONFIG_CFG80211_CRDA_SUPPORT is not set
+CONFIG_RFKILL=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_AQT_REGMAP=y
+CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
+CONFIG_DMA_CMA=y
+CONFIG_ZRAM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_QPNP_MISC=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_GENL=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_QPNP_POWER_ON=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM_GENI=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QCOM_GENI=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_QCOM_GENI=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
+CONFIG_PINCTRL_SDM670=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_QPNP_FG_GEN3=y
+CONFIG_SMB1355_SLAVE_CHARGER=y
+CONFIG_QPNP_SMB2=y
+CONFIG_QPNP_QNOVO=y
+CONFIG_SMB1390_CHARGE_PUMP=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
+CONFIG_QCOM_SPMI_TEMP_ALARM=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_MFD_I2C_PMIC=y
+CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_PROXY_CONSUMER=y
+CONFIG_REGULATOR_QPNP_LABIBB=y
+CONFIG_REGULATOR_QPNP_LCDB=y
+CONFIG_REGULATOR_QPNP_OLEDB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_REFGEN=y
+CONFIG_REGULATOR_RPMH=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_FIXED_MINOR_RANGES=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_GOVERNORS=y
+CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_QCOM_KGSL=y
+CONFIG_DRM=y
+CONFIG_DRM_SDE_EVTLOG_DEBUG=y
+CONFIG_DRM_SDE_RSC=y
+CONFIG_DRM_LT_LT9611=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_AUDIO_QMI=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_ISP1760=y
+CONFIG_USB_ISP1760_HOST_ROLE=y
+CONFIG_USB_PD_POLICY=y
+CONFIG_QPNP_USB_PDPHY=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_DUAL_ROLE_USB_INTF=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_QUSB_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_DIAG=y
+CONFIG_USB_CONFIGFS_F_CDEV=y
+CONFIG_USB_CONFIGFS_F_CCID=y
+CONFIG_USB_CONFIGFS_F_GSI=y
+CONFIG_USB_CONFIGFS_F_QDSS=y
+CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_QPNP_FLASH_V2=y
+CONFIG_LEDS_QPNP_WLED=y
+CONFIG_LEDS_QPNP_HAPTICS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_DMADEVICES=y
+CONFIG_QCOM_GPI_DMA=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_GSI=y
+CONFIG_IPA3=y
+CONFIG_RMNET_IPA3=y
+CONFIG_RNDIS_IPA=y
+CONFIG_IPA_UT=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_COINCELL=y
+CONFIG_QPNP_REVID=y
+CONFIG_USB_BAM=y
+CONFIG_QCOM_GENI_SE=y
+CONFIG_MSM_GCC_SDM845=y
+CONFIG_MSM_VIDEOCC_SDM845=y
+CONFIG_MSM_CAMCC_SDM845=y
+CONFIG_MSM_DISPCC_SDM845=y
+CONFIG_CLOCK_QPNP_DIV=y
+CONFIG_MSM_CLK_RPMH=y
+CONFIG_CLOCK_CPU_OSM=y
+CONFIG_MSM_GPUCC_SDM845=y
+CONFIG_MSM_CLK_AOP_QMP=y
+CONFIG_QCOM_MDSS_PLL=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MSM_QMP=y
+CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
+CONFIG_QCOM_LLCC=y
+CONFIG_QCOM_SDM670_LLCC=y
+CONFIG_QCOM_LLCC_PERFMON=m
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_QCOM_EUD=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QPNP_PBS=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_QCOM_BUS_SCALING=y
+CONFIG_QCOM_BUS_CONFIG_RPMH=y
+CONFIG_QCOM_SECURE_BUFFER=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_MSM_SMEM=y
+CONFIG_MSM_GLINK=y
+CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
+CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
+CONFIG_MSM_GLINK_SPI_XPRT=y
+CONFIG_MSM_SPCOM=y
+CONFIG_MSM_SPSS_UTILS=y
+CONFIG_QTI_RPMH_API=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_GLINK_PKT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_SYSMON_GLINK_COMM=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_ICNSS=y
+CONFIG_QCOM_COMMAND_DB=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_MSM_CDSP_LOADER=y
+CONFIG_QCOM_SMCINVOKE=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_QBT1000=y
+CONFIG_QTI_RPM_STATS_LOG=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_QMP_DEBUGFS_CLIENT=y
+CONFIG_MSM_REMOTEQDSS=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y
+CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_QCOM_RRADC=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
+CONFIG_ARM_GIC_V3_ACL=y
+CONFIG_RAS=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_IPC_32BIT=y
+CONFIG_SENSORS_SSC=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_WARN=2048
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PAGE_EXTENSION=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_IPC_LOGGING=y
+CONFIG_TRACER_SNAPSHOT=y
+CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_QCOM_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
+CONFIG_CORESIGHT_CTI=y
+CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_CORESIGHT_DUMMY=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
diff --git a/arch/arm/configs/sdm670_defconfig b/arch/arm/configs/sdm670_defconfig
index 949b279..702f622 100644
--- a/arch/arm/configs/sdm670_defconfig
+++ b/arch/arm/configs/sdm670_defconfig
@@ -352,9 +352,12 @@
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
 CONFIG_VIDEO_ADV_DEBUG=y
 CONFIG_VIDEO_FIXED_MINOR_RANGES=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_GOVERNORS=y
 CONFIG_MSM_SDE_ROTATOR=y
 CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
 CONFIG_QCOM_KGSL=y
@@ -517,7 +520,6 @@
 CONFIG_QCOM_SMCINVOKE=y
 CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_QBT1000=y
-CONFIG_QCOM_DCC_V2=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_QMP_DEBUGFS_CLIENT=y
@@ -533,6 +535,7 @@
 CONFIG_ARM_GIC_V3_ACL=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_IPC_32BIT=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
 CONFIG_EXT2_FS=y
@@ -552,6 +555,7 @@
 CONFIG_PRINTK_TIME=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_WARN=2048
 CONFIG_PAGE_OWNER=y
 CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
 CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index e1fed15..cdbfebd 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -366,6 +366,8 @@
 CONFIG_IOMMU_DEBUG=y
 CONFIG_IOMMU_DEBUG_TRACKING=y
 CONFIG_IOMMU_TESTS=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
 CONFIG_QCOM_SCM=y
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_QCOM_WATCHDOG_V2=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index 54072cc..b3fef2f 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -371,6 +371,8 @@
 CONFIG_IOMMU_DEBUG=y
 CONFIG_IOMMU_DEBUG_TRACKING=y
 CONFIG_IOMMU_TESTS=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
 CONFIG_QCOM_SCM=y
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_QCOM_WATCHDOG_V2=y
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index 7ca9180..6b43733 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -107,8 +107,8 @@
 	select PM_OPP
 	select MSM_DEVFREQ_DEVBW
 	select DEVFREQ_SIMPLE_DEV
-	select DEVFREQ_GOV_MSM_BW_HWMON
-	select MSM_BIMC_BWMON
+	select DEVFREQ_GOV_QCOM_BW_HWMON
+	select QCOM_BIMC_BWMON
 	select CLKDEV_LOOKUP
 	select HAVE_CLK
 	select HAVE_CLK_PREPARE
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index a8f8d46..e5a8a57 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1965,6 +1965,8 @@
 		total_length += s->length;
 
 	iova = __alloc_iova(mapping, total_length);
+	if (iova == DMA_ERROR_CODE)
+		return 0;
 	ret = iommu_map_sg(mapping->domain, iova, sg, nents, prot);
 	if (ret != total_length) {
 		__free_iova(mapping, iova, total_length);
diff --git a/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi b/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
index c8330bd..4f9c9f7 100644
--- a/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
@@ -521,6 +521,13 @@
 
 &pm660_fg {
 	qcom,battery-data = <&mtp_batterydata>;
+	qcom,fg-rsense-sel = <1>;	/* External rsense */
+	qcom,fg-cutoff-voltage = <3400>;
+	qcom,fg-recharge-voltage = <4100>;
+	qcom,fg-use-sw-esr;
+	qcom,fg-esr-pulse-thresh-ma = <40>;
+	qcom,fg-esr-meas-curr-ma = <60>;
+	qcom,fg-cutoff-current = <50>;
 };
 
 &pm660_pdphy {
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 15f53ee..ef0ac4d 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -223,7 +223,7 @@
 qcs605-mtp-overlay.dtbo-base := qcs605.dtb
 qcs605-external-codec-mtp-overlay.dtbo-base := qcs605.dtb
 qcs605-lc-mtp-overlay.dtbo-base := qcs605-lc.dtb
-qcs605-lc-ipcamera-overlay.dtbo-base := qcs605-lc.dtb
+qcs605-lc-ipcamera-overlay.dtbo-base := qcs605-lc-ipcamera-base.dtb
 qcs605-360camera-overlay.dtbo-base := qcs605.dtb
 qcs605-lc-cdp-overlay.dtbo-base := qcs605-lc-cdp-base.dtb
 sdm710-cdp-overlay.dtbo-base := sdm710.dtb
@@ -499,8 +499,11 @@
 	apq8053-lite-dragon-v2.0.dtb \
 	apq8053-lite-dragon-v2.1.dtb \
 	apq8053-lite-dragon-v2.2.dtb \
+	apq8053-lite-dragon-v2.2.1.dtb \
 	apq8053-lite-dragon-v2.3.dtb \
 	apq8053-lite-dragon-v2.4.dtb \
+	apq8053-lat-concam-dev.dtb \
+	apq8053-lat-concam-proto.dtb \
 	msm8953-pmi8940-cdp.dtb \
 	msm8953-pmi8940-mtp.dtb \
 	msm8953-pmi8937-cdp.dtb \
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts
index 0ac8a31..4a625f8 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts
@@ -15,7 +15,6 @@
 #include "msm8909-mtp.dtsi"
 #include "8909-pm8916.dtsi"
 #include "msm8909-pm8916-mtp.dtsi"
-#include "apq8009-audio-external_codec.dtsi"
 #include "apq8009-memory.dtsi"
 #include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
 #include "msm8909-pm8916-camera.dtsi"
@@ -29,7 +28,46 @@
 };
 
 &audio_codec_mtp {
-	status = "disabled";
+	qcom,model = "msm8909-pm8916-snd-card";
+	asoc-codec = <&stub_codec>, <&msm_digital_codec>,
+			<&pmic_analog_codec>;
+	asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+			"analog-codec";
+
+	qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+	asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+			<&loopback>, <&compress>, <&hostless>,
+			<&afe>, <&lsm>, <&routing>, <&lpa>,
+			<&voice_svc>,<&pcm_noirq>;
+
+	asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+			      "msm-pcm-dsp.2", "msm-voip-dsp",
+			      "msm-pcm-voice", "msm-pcm-loopback",
+			      "msm-compress-dsp", "msm-pcm-hostless",
+			      "msm-pcm-afe", "msm-lsm-client",
+			      "msm-pcm-routing", "msm-pcm-lpa",
+			      "msm-voice-svc", "msm-pcm-dsp-noirq";
+
+	asoc-cpu = <&dai_pri_auxpcm>,
+			<&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>,
+			<&dai_mi2s3>, <&dai_mi2s4>, <&dai_mi2s5>,
+			<&bt_sco_rx>, <&bt_sco_tx>, <&bt_a2dp_rx>,
+			<&int_fm_rx>, <&int_fm_tx>, <&afe_pcm_rx>,
+			<&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
+			<&incall_record_rx>, <&incall_record_tx>,
+			<&incall_music_rx>, <&incall_music_2_rx>;
+
+	asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+			"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+			"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+			"msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.6",
+			"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+			"msm-dai-q6-dev.12290", "msm-dai-q6-dev.12292",
+			"msm-dai-q6-dev.12293", "msm-dai-q6-dev.224",
+			"msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
+			"msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
+			"msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773",
+			"msm-dai-q6-dev.32770";
 };
 
 &pm8916_gpios {
@@ -94,40 +132,79 @@
 	};
 };
 
+&spmi_bus {
+	pm8916@1 {
+		pmic_analog_codec: analog-codec@f000 {
+			status = "okay";
+			compatible = "qcom,pmic-analog-codec";
+			reg = <0xf000 0x200>;
+			#address-cells = <2>;
+			#size-cells = <0>;
+			interrupt-parent = <&spmi_bus>;
+			interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x1 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x2 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x3 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x4 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x5 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x6 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x7 IRQ_TYPE_NONE>,
+				<0x1 0xf1 0x0 IRQ_TYPE_NONE>,
+				<0x1 0xf1 0x1 IRQ_TYPE_NONE>,
+				<0x1 0xf1 0x2 IRQ_TYPE_NONE>,
+				<0x1 0xf1 0x3 IRQ_TYPE_NONE>,
+				<0x1 0xf1 0x4 IRQ_TYPE_NONE>,
+				<0x1 0xf1 0x5 IRQ_TYPE_NONE>;
+			interrupt-names = "spk_cnp_int",
+					"spk_clip_int",
+					"spk_ocp_int",
+					"ins_rem_det1",
+					"but_rel_det",
+					"but_press_det",
+					"ins_rem_det",
+					"mbhc_int",
+					"ear_ocp_int",
+					"hphr_ocp_int",
+					"hphl_ocp_det",
+					"ear_cnp_int",
+					"hphr_cnp_int",
+					"hphl_cnp_int";
+
+			cdc-vdda-cp-supply = <&pm8916_s4>;
+			qcom,cdc-vdda-cp-voltage = <1800000 2100000>;
+			qcom,cdc-vdda-cp-current = <1800000>;
+
+			cdc-vdd-io-supply = <&pm8916_l5>;
+			qcom,cdc-vdd-io-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-io-current = <5000>;
+
+			cdc-vdd-pa-supply = <&pm8916_s4>;
+			qcom,cdc-vdd-pa-voltage = <1800000 2100000>;
+			qcom,cdc-vdd-pa-current = <1800000>;
+
+			cdc-vdd-mic-bias-supply = <&pm8916_l13>;
+			qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+			qcom,cdc-vdd-mic-bias-current = <5000>;
+
+			qcom,cdc-mclk-clk-rate = <9600000>;
+
+			qcom,cdc-static-supplies = "cdc-vdd-io",
+						"cdc-vdd-pa",
+						"cdc-vdda-cp";
+
+			qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+
+			msm_digital_codec: msm-dig-codec {
+				compatible = "qcom,msm-digital-codec";
+				reg = <0x0771c000 0x0>;
+			};
+		};
+	};
+};
+
 &soc {
 	ext_codec: sound-9335 {
-		qcom,audio-routing =
-			"AIF4 VI", "MCLK",
-			"RX_BIAS", "MCLK",
-			"MADINPUT", "MCLK",
-			"AMIC2", "MIC BIAS2",
-			"MIC BIAS2", "Headset Mic",
-			"DMIC0", "MIC BIAS1",
-			"MIC BIAS1", "Digital Mic0",
-			"DMIC1", "MIC BIAS1",
-			"MIC BIAS1", "Digital Mic1",
-			"DMIC2", "MIC BIAS3",
-			"MIC BIAS3", "Digital Mic2",
-			"DMIC3", "MIC BIAS3",
-			"MIC BIAS3", "Digital Mic3",
-			"SpkrLeft IN", "SPK1 OUT",
-			"SpkrRight IN", "SPK2 OUT";
-
-		qcom,msm-gpios =
-			"us_eu_gpio";
-		qcom,pinctrl-names =
-			"all_off",
-			"us_eu_gpio_act";
-		pinctrl-names =
-			"all_off",
-			"us_eu_gpio_act";
-		pinctrl-0 = <&cross_conn_det_sus>;
-		pinctrl-1 = <&cross_conn_det_act>;
-		qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
-		qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
-
-		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
-					"SpkrLeft", "SpkrRight";
+		status = "disabled";
 	};
 
 	i2c@78b9000 {
@@ -176,6 +253,7 @@
 	};
 
 	cnss_sdio: qcom,cnss_sdio {
+		status = "disabled";
 		compatible = "qcom,cnss_sdio";
 		subsys-name = "AR6320";
 		/**
@@ -210,37 +288,16 @@
 
 	i2c@78b8000 {
 		wcd9xxx_codec@d {
-			status = "okay";
-			qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+			status = "disabled";
 		};
 	};
 
 	cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
 		compatible = "qcom,msm-cdc-pinctrl";
 		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&pri_mi2s_active &pri_mi2s_ws_active
-		     &pri_mi2s_dout_active &pri_mi2s_din_active>;
-		pinctrl-1 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
-		     &pri_mi2s_dout_sleep &pri_mi2s_din_sleep>;
+		pinctrl-0 = <&cdc_pdm_lines_act>;
+		pinctrl-1 = <&cdc_pdm_lines_sus>;
 	};
-
-	cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
-		compatible = "qcom,msm-cdc-pinctrl";
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
-		pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
-	};
-
-	wcd_rst_gpio: wcd_gpio_ctrl {
-		compatible = "qcom,msm-cdc-pinctrl";
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&cdc_reset_active>;
-		pinctrl-1 = <&cdc_reset_sleep>;
-	};
-};
-
-&wcnss {
-	status = "disabled";
 };
 
 &msm_gpio {
@@ -298,7 +355,7 @@
 	&sdc2_wlan_gpio_off>;
 	qcom,nonremovable;
 	qcom,core_3_0v_support;
-	status = "ok";
+	status = "disabled";
 };
 
 &i2c_4 {
@@ -365,14 +422,6 @@
 	status = "disabled";
 };
 
-&wcd_rst_gpio {
-	status = "okay";
-};
-
-&ext_codec {
-	status = "okay";
-};
-
 &blsp1_uart2_hs {
 	status = "disabled";
 };
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-rome-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-rome-refboard.dts
index 4677448..0938d86 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-robot-rome-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-rome-refboard.dts
@@ -15,7 +15,6 @@
 #include "msm8909-mtp.dtsi"
 #include "8909-pm8916.dtsi"
 #include "msm8909-pm8916-mtp.dtsi"
-#include "apq8009-audio-external_codec.dtsi"
 #include "apq8009-memory.dtsi"
 #include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
 #include "msm8909-pm8916-camera.dtsi"
@@ -29,7 +28,43 @@
 };
 
 &audio_codec_mtp {
-	status = "disabled";
+	qcom,model = "msm8909-pm8916-snd-card";
+	asoc-codec = <&stub_codec>, <&msm_digital_codec>,
+			<&pmic_analog_codec>;
+	asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+				"analog-codec";
+
+	qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+	asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+			<&loopback>, <&compress>, <&hostless>,
+			<&afe>, <&lsm>, <&routing>, <&lpa>,
+			<&voice_svc>,<&pcm_noirq>;
+	asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+			"msm-pcm-dsp.2", "msm-voip-dsp",
+			"msm-pcm-voice", "msm-pcm-loopback",
+			"msm-compress-dsp", "msm-pcm-hostless",
+			"msm-pcm-afe", "msm-lsm-client",
+			"msm-pcm-routing", "msm-pcm-lpa",
+			"msm-voice-svc","msm-pcm-dsp-noirq";
+	asoc-cpu = <&dai_pri_auxpcm>,
+		<&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>,
+		<&dai_mi2s3>, <&dai_mi2s4>, <&dai_mi2s5>,
+		<&bt_sco_rx>, <&bt_sco_tx>, <&bt_a2dp_rx>,
+		<&int_fm_rx>, <&int_fm_tx>, <&afe_pcm_rx>,
+		<&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
+		<&incall_record_rx>, <&incall_record_tx>,
+		<&incall_music_rx>, <&incall_music_2_rx>;
+	asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+			"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+			"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+			"msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.6",
+			"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+			"msm-dai-q6-dev.12290", "msm-dai-q6-dev.12292",
+			"msm-dai-q6-dev.12293", "msm-dai-q6-dev.224",
+			"msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
+			"msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
+			"msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773",
+			"msm-dai-q6-dev.32770";
 };
 
 &pm8916_gpios {
@@ -93,41 +128,79 @@
 		};
 	};
 };
+&spmi_bus {
+	pm8916@1 {
+		pmic_analog_codec: analog-codec@f000 {
+			status = "okay";
+			compatible = "qcom,pmic-analog-codec";
+			reg = <0xf000 0x200>;
+			#address-cells = <2>;
+			#size-cells = <0>;
+			interrupt-parent = <&spmi_bus>;
+			interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x1 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x2 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x3 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x4 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x5 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x6 IRQ_TYPE_NONE>,
+				<0x1 0xf0 0x7 IRQ_TYPE_NONE>,
+				<0x1 0xf1 0x0 IRQ_TYPE_NONE>,
+				<0x1 0xf1 0x1 IRQ_TYPE_NONE>,
+				<0x1 0xf1 0x2 IRQ_TYPE_NONE>,
+				<0x1 0xf1 0x3 IRQ_TYPE_NONE>,
+				<0x1 0xf1 0x4 IRQ_TYPE_NONE>,
+				<0x1 0xf1 0x5 IRQ_TYPE_NONE>;
+			interrupt-names = "spk_cnp_int",
+					"spk_clip_int",
+					"spk_ocp_int",
+					"ins_rem_det1",
+					"but_rel_det",
+					"but_press_det",
+					"ins_rem_det",
+					"mbhc_int",
+					"ear_ocp_int",
+					"hphr_ocp_int",
+					"hphl_ocp_det",
+					"ear_cnp_int",
+					"hphr_cnp_int",
+					"hphl_cnp_int";
+
+			cdc-vdda-cp-supply = <&pm8916_s4>;
+			qcom,cdc-vdda-cp-voltage = <1800000 2100000>;
+			qcom,cdc-vdda-cp-current = <1800000>;
+
+			cdc-vdd-io-supply = <&pm8916_l5>;
+			qcom,cdc-vdd-io-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-io-current = <5000>;
+
+			cdc-vdd-pa-supply = <&pm8916_s4>;
+			qcom,cdc-vdd-pa-voltage = <1800000 2100000>;
+			qcom,cdc-vdd-pa-current = <1800000>;
+
+			cdc-vdd-mic-bias-supply = <&pm8916_l13>;
+			qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+			qcom,cdc-vdd-mic-bias-current = <5000>;
+
+			qcom,cdc-mclk-clk-rate = <9600000>;
+
+			qcom,cdc-static-supplies = "cdc-vdd-io",
+						"cdc-vdd-pa",
+						"cdc-vdda-cp";
+
+			qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+
+			msm_digital_codec: msm-dig-codec {
+				compatible = "qcom,msm-digital-codec";
+				reg = <0x0771c000 0x0>;
+			};
+		};
+	};
+};
 
 &soc {
 	ext_codec: sound-9335 {
-		qcom,audio-routing =
-			"AIF4 VI", "MCLK",
-			"RX_BIAS", "MCLK",
-			"MADINPUT", "MCLK",
-			"AMIC2", "MIC BIAS2",
-			"MIC BIAS2", "Headset Mic",
-			"DMIC0", "MIC BIAS1",
-			"MIC BIAS1", "Digital Mic0",
-			"DMIC1", "MIC BIAS1",
-			"MIC BIAS1", "Digital Mic1",
-			"DMIC2", "MIC BIAS3",
-			"MIC BIAS3", "Digital Mic2",
-			"DMIC3", "MIC BIAS3",
-			"MIC BIAS3", "Digital Mic3",
-			"SpkrLeft IN", "SPK1 OUT",
-			"SpkrRight IN", "SPK2 OUT";
-
-		qcom,msm-gpios =
-			"us_eu_gpio";
-		qcom,pinctrl-names =
-			"all_off",
-			"us_eu_gpio_act";
-		pinctrl-names =
-			"all_off",
-			"us_eu_gpio_act";
-		pinctrl-0 = <&cross_conn_det_sus>;
-		pinctrl-1 = <&cross_conn_det_act>;
-		qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
-		qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
-
-		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
-					"SpkrLeft", "SpkrRight";
+		status = "disabled";
 	};
 
 	i2c@78b9000 {
@@ -210,32 +283,15 @@
 
 	i2c@78b8000 {
 		wcd9xxx_codec@d {
-			status = "okay";
-			qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+			status = "disabled";
 		};
 	};
 
 	cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
 		compatible = "qcom,msm-cdc-pinctrl";
 		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&pri_mi2s_active &pri_mi2s_ws_active
-		     &pri_mi2s_dout_active &pri_mi2s_din_active>;
-		pinctrl-1 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
-		     &pri_mi2s_dout_sleep &pri_mi2s_din_sleep>;
-	};
-
-	cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
-		compatible = "qcom,msm-cdc-pinctrl";
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
-		pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
-	};
-
-	wcd_rst_gpio: wcd_gpio_ctrl {
-		compatible = "qcom,msm-cdc-pinctrl";
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&cdc_reset_active>;
-		pinctrl-1 = <&cdc_reset_sleep>;
+		pinctrl-0 = <&cdc_pdm_lines_act>;
+		pinctrl-1 = <&cdc_pdm_lines_sus>;
 	};
 };
 
@@ -365,16 +421,8 @@
 	status = "disabled";
 };
 
-&wcd_rst_gpio {
-	status = "okay";
-};
-
-&ext_codec {
-	status = "okay";
-};
-
 &blsp1_uart2_hs {
-	status = "okay";
+	status= "okay";
 };
 
 /delete-node/ &cont_splash_mem;
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
index ab711dd..8efa0c5 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
@@ -256,6 +256,7 @@
 		compatible = "st,stmvl53l0";
 		reg = <0x29>;
 		status = "ok";
+		tof-id = <2>;
 	};
 };
 
@@ -354,12 +355,12 @@
 	status = "ok";
 };
 
-&i2c_1 {
-	status = "okay";
+&i2c_3 {
 	vl53l0x@52 {
 		compatible = "st,stmvl53l0";
 		reg = <0x29>;
 		status = "ok";
+		tof-id = <1>;
 	};
 };
 
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam-audio.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-audio.dtsi
new file mode 100644
index 0000000..b0fee57
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-audio.dtsi
@@ -0,0 +1,645 @@
+/*
+ * 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.
+ */
+
+/* picked up from base file msm8953-audio.dtsi, enables internal codec config */
+
+&soc {
+	&i2c_2 {
+		status = "okay";
+		wsa881x_i2c_f: wsa881x-i2c-codec@f {
+			status = "okay";
+
+			compatible = "qcom,wsa881x-i2c-codec";
+			reg = <0x0f>;
+			qcom,msm-gpios = "wsa_clk",
+					"wsa_reset",
+					"wsa_vi";
+			qcom,pinctrl-names = "all_off",
+					"wsa_clk",
+					"wsa_active",
+					"wsa_clk_active",
+					"wsa_vi",
+					"wsa_clk_vi",
+					"wsa_active_vi",
+					"wsa_all";
+			pinctrl-names = "all_off",
+					"wsa_clk",
+					"wsa_active",
+					"wsa_clk_active",
+					"wsa_vi",
+					"wsa_clk_vi",
+					"wsa_active_vi",
+					"wsa_all";
+			pinctrl-0 = <&wsa_clk_off &wsa_reset_off &wsa_vi_off>;
+			pinctrl-1 = <&wsa_clk_on &wsa_reset_off &wsa_vi_off>;
+			pinctrl-2 = <&wsa_clk_off &wsa_reset_on &wsa_vi_off>;
+			pinctrl-3 = <&wsa_clk_on &wsa_reset_on &wsa_vi_off>;
+			pinctrl-4 = <&wsa_clk_off &wsa_reset_off &wsa_vi_on>;
+			pinctrl-5 = <&wsa_clk_on &wsa_reset_off &wsa_vi_on>;
+			pinctrl-6 = <&wsa_clk_off &wsa_reset_on &wsa_vi_on>;
+			pinctrl-7 = <&wsa_clk_on &wsa_reset_on &wsa_vi_on>;
+		};
+
+		wsa881x_i2c_45: wsa881x-i2c-codec@45 {
+			status = "okay";
+
+			compatible = "qcom,wsa881x-i2c-codec";
+			reg = <0x45>;
+			qcom,msm-gpios = "wsa_clk",
+					"wsa_reset",
+					"wsa_vi";
+			qcom,pinctrl-names = "all_off",
+					"wsa_clk",
+					"wsa_active",
+					"wsa_clk_active",
+					"wsa_vi",
+					"wsa_clk_vi",
+					"wsa_active_vi",
+					"wsa_all";
+			pinctrl-names = "all_off",
+					"wsa_clk",
+					"wsa_active",
+					"wsa_clk_active",
+					"wsa_vi",
+					"wsa_clk_vi",
+					"wsa_active_vi",
+					"wsa_all";
+			pinctrl-0 = <&wsa_clk_off &wsa_reset_off &wsa_vi_off>;
+			pinctrl-1 = <&wsa_clk_on &wsa_reset_off &wsa_vi_off>;
+			pinctrl-2 = <&wsa_clk_off &wsa_reset_on &wsa_vi_off>;
+			pinctrl-3 = <&wsa_clk_on &wsa_reset_on &wsa_vi_off>;
+			pinctrl-4 = <&wsa_clk_off &wsa_reset_off &wsa_vi_on>;
+			pinctrl-5 = <&wsa_clk_on &wsa_reset_off &wsa_vi_on>;
+			pinctrl-6 = <&wsa_clk_off &wsa_reset_on &wsa_vi_on>;
+			pinctrl-7 = <&wsa_clk_on &wsa_reset_on &wsa_vi_on>;
+		};
+	};
+
+	pcm0: qcom,msm-pcm {
+		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <0>;
+	};
+
+	routing: qcom,msm-pcm-routing {
+		compatible = "qcom,msm-pcm-routing";
+	};
+
+	pcm2: qcom,msm-ultra-low-latency {
+		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <2>;
+		qcom,msm-pcm-low-latency;
+		qcom,latency-level = "ultra";
+	};
+
+	pcm1: qcom,msm-pcm-low-latency {
+		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <1>;
+		qcom,msm-pcm-low-latency;
+		qcom,latency-level = "regular";
+	};
+
+	pcm2: qcom,msm-ultra-low-latency {
+		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <2>;
+		qcom,msm-pcm-low-latency;
+		qcom,latency-level = "ultra";
+	};
+
+	cpe: qcom,msm-cpe-lsm {
+		compatible = "qcom,msm-cpe-lsm";
+	};
+
+	lpa: qcom,msm-pcm-lpa {
+		compatible = "qcom,msm-pcm-lpa";
+	};
+
+	compress: qcom,msm-compress-dsp {
+		compatible = "qcom,msm-compress-dsp";
+	};
+
+	voip: qcom,msm-voip-dsp {
+		compatible = "qcom,msm-voip-dsp";
+	};
+
+	voice: qcom,msm-pcm-voice {
+		compatible = "qcom,msm-pcm-voice";
+		qcom,destroy-cvd;
+	};
+
+	stub_codec: qcom,msm-stub-codec {
+		compatible = "qcom,msm-stub-codec";
+	};
+
+	qcom,msm-dai-fe {
+		compatible = "qcom,msm-dai-fe";
+	};
+
+	afe: qcom,msm-pcm-afe {
+		compatible = "qcom,msm-pcm-afe";
+	};
+
+	loopback: qcom,msm-pcm-loopback {
+		compatible = "qcom,msm-pcm-loopback";
+	};
+
+	qcom,msm-dai-mi2s {
+		compatible = "qcom,msm-dai-mi2s";
+		dai_mi2s0: qcom,msm-dai-q6-mi2s-prim {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <0>;
+			qcom,msm-mi2s-rx-lines = <3>;
+			qcom,msm-mi2s-tx-lines = <0>;
+		};
+
+		dai_mi2s1: qcom,msm-dai-q6-mi2s-sec {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <1>;
+			qcom,msm-mi2s-rx-lines = <1>;
+			qcom,msm-mi2s-tx-lines = <0>;
+		};
+
+		dai_mi2s3: qcom,msm-dai-q6-mi2s-quat {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <3>;
+			qcom,msm-mi2s-rx-lines = <1>;
+			qcom,msm-mi2s-tx-lines = <2>;
+		};
+
+		dai_mi2s2: qcom,msm-dai-q6-mi2s-tert {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <2>;
+			qcom,msm-mi2s-rx-lines = <0>;
+			qcom,msm-mi2s-tx-lines = <3>;
+		};
+
+		dai_mi2s5: qcom,msm-dai-q6-mi2s-quin {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <5>;
+			qcom,msm-mi2s-rx-lines = <1>;
+			qcom,msm-mi2s-tx-lines = <2>;
+		};
+
+		dai_mi2s6: qcom,msm-dai-q6-mi2s-senary {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <6>;
+			qcom,msm-mi2s-rx-lines = <0>;
+			qcom,msm-mi2s-tx-lines = <3>;
+		};
+	};
+
+	lsm: qcom,msm-lsm-client {
+		compatible = "qcom,msm-lsm-client";
+	};
+
+	qcom,msm-dai-q6 {
+		compatible = "qcom,msm-dai-q6";
+		sb_0_rx: qcom,msm-dai-q6-sb-0-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16384>;
+		};
+
+		sb_0_tx: qcom,msm-dai-q6-sb-0-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16385>;
+		};
+
+		sb_1_rx: qcom,msm-dai-q6-sb-1-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16386>;
+		};
+
+		sb_1_tx: qcom,msm-dai-q6-sb-1-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16387>;
+		};
+
+		sb_2_rx: qcom,msm-dai-q6-sb-2-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16388>;
+		};
+
+		sb_2_tx: qcom,msm-dai-q6-sb-2-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16389>;
+		};
+
+
+		sb_3_rx: qcom,msm-dai-q6-sb-3-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16390>;
+		};
+
+		sb_3_tx: qcom,msm-dai-q6-sb-3-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16391>;
+		};
+
+		sb_4_rx: qcom,msm-dai-q6-sb-4-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16392>;
+		};
+
+		sb_4_tx: qcom,msm-dai-q6-sb-4-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16393>;
+		};
+
+		sb_5_tx: qcom,msm-dai-q6-sb-5-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16395>;
+		};
+
+		sb_5_rx: qcom,msm-dai-q6-sb-5-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16394>;
+		};
+
+		bt_sco_rx: qcom,msm-dai-q6-bt-sco-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12288>;
+		};
+
+		bt_sco_tx: qcom,msm-dai-q6-bt-sco-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12289>;
+		};
+
+		int_fm_rx: qcom,msm-dai-q6-int-fm-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12292>;
+		};
+
+		int_fm_tx: qcom,msm-dai-q6-int-fm-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12293>;
+		};
+
+		afe_pcm_rx: qcom,msm-dai-q6-be-afe-pcm-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <224>;
+		};
+
+		afe_pcm_tx: qcom,msm-dai-q6-be-afe-pcm-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <225>;
+		};
+
+		afe_proxy_rx: qcom,msm-dai-q6-afe-proxy-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <241>;
+		};
+
+		afe_proxy_tx: qcom,msm-dai-q6-afe-proxy-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <240>;
+		};
+
+		incall_record_rx: qcom,msm-dai-q6-incall-record-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32771>;
+		};
+
+		incall_record_tx: qcom,msm-dai-q6-incall-record-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32772>;
+		};
+
+		incall_music_rx: qcom,msm-dai-q6-incall-music-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32773>;
+		};
+
+		incall_music_2_rx: qcom,msm-dai-q6-incall-music-2-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32770>;
+		};
+
+		sb_6_rx: qcom,msm-dai-q6-sb-6-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16396>;
+		};
+	};
+
+	hostless: qcom,msm-pcm-hostless {
+		compatible = "qcom,msm-pcm-hostless";
+	};
+
+	dai_pri_auxpcm: qcom,msm-pri-auxpcm {
+		compatible = "qcom,msm-auxpcm-dev";
+		qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
+		qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
+		qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
+		qcom,msm-cpudai-auxpcm-num-slots = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-slot-mapping = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-data = <0>, <0>;
+		qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+		qcom,msm-auxpcm-interface = "primary";
+	};
+
+	hdmi_dba: qcom,msm-hdmi-dba-codec-rx {
+		compatible = "qcom,msm-hdmi-dba-codec-rx";
+		qcom,dba-bridge-chip = "adv7533";
+	};
+
+	qcom,msm-audio-ion {
+		compatible = "qcom,msm-audio-ion";
+		qcom,smmu-version = <1>;
+		qcom,smmu-enabled;
+		iommus = <&adsp_io 1>;
+	};
+
+	qcom,msm-adsp-loader {
+		compatible = "qcom,adsp-loader";
+		qcom,adsp-state = <0>;
+	};
+
+	qcom,avtimer@c0a300c {
+		compatible = "qcom,avtimer";
+		reg = <0x0c0a300c 0x4>,
+			<0x0c0a3010 0x4>;
+		reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
+		qcom,clk-div = <27>;
+	};
+
+	int_codec: sound {
+		status = "okay";
+		compatible = "qcom,msm8952-audio-codec";
+		qcom,model = "msm8953-snd-card";
+		reg = <0xc051000 0x4>,
+		      <0xc051004 0x4>,
+		      <0xc055000 0x4>,
+		      <0xc052000 0x4>;
+		reg-names = "csr_gp_io_mux_mic_ctl",
+			    "csr_gp_io_mux_spkr_ctl",
+			    "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel",
+			    "csr_gp_io_mux_quin_ctl";
+
+		qcom,msm-ext-pa = "primary";
+		qcom,msm-mclk-freq = <9600000>;
+		qcom,msm-mbhc-hphl-swh = <0>;
+		qcom,msm-mbhc-gnd-swh = <0>;
+		qcom,msm-hs-micbias-type = "external";
+		qcom,msm-micbias1-ext-cap;
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"SPK_RX_BIAS", "MCLK",
+			"INT_LDO_H", "MCLK",
+			"MIC BIAS External", "Handset Mic",
+			"MIC BIAS External2", "Headset Mic",
+			"MIC BIAS External", "Secondary Mic",
+			"AMIC1", "MIC BIAS External",
+			"AMIC2", "MIC BIAS External2",
+			"AMIC3", "MIC BIAS External",
+			"DMIC1", "MIC BIAS Internal1",
+			"MIC BIAS Internal1", "Digital Mic1",
+			"DMIC2", "MIC BIAS Internal1",
+			"MIC BIAS Internal1", "Digital Mic2",
+			"WSA_SPK OUT", "VDD_WSA_SWITCH",
+			"SpkrMono WSA_IN", "WSA_SPK OUT";
+
+		qcom,hdmi-dba-codec-rx;
+
+		qcom,msm-gpios =
+			"pri_i2s",
+			"dmic_gpio",
+			"quin_i2s",
+			"comp_gpio";
+		qcom,pinctrl-names =
+			"all_off",
+			"pri_i2s_act",
+			"dmic_gpio_act",
+			"pri_i2s_dmic_gpio_act",
+			"quin_act",
+			"quin_pri_i2s_act",
+			"quin_dmic_gpio_act",
+			"quin_dmic_gpio_pri_i2s_act",
+			"comp_gpio_act",
+			"comp_gpio_pri_i2s_act",
+			"comp_gpio_dmic_gpio_act",
+			"comp_gpio_pri_i2s_dmic_gpio_act",
+			"comp_gpio_quin_act",
+			"comp_gpio_quin_pri_i2s_act",
+			"comp_gpio_quin_dmic_gpio_act",
+			"comp_gpio_quin_dmic_gpio_pri_i2s_act";
+
+		pinctrl-names =
+			"all_off",
+			"pri_i2s_act",
+			"dmic_gpio_act",
+			"pri_i2s_dmic_gpio_act",
+			"quin_act",
+			"quin_pri_i2s_act",
+			"quin_dmic_gpio_act",
+			"quin_dmic_gpio_pri_i2s_act",
+			"comp_gpio_act",
+			"comp_gpio_pri_i2s_act",
+			"comp_gpio_dmic_gpio_act",
+			"comp_gpio_pri_i2s_dmic_gpio_act",
+			"comp_gpio_quin_act",
+			"comp_gpio_quin_pri_i2s_act",
+			"comp_gpio_quin_dmic_gpio_act",
+			"comp_gpio_quin_dmic_gpio_pri_i2s_act";
+
+		pinctrl-0 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus
+			&cdc_pdm_lines_2_sus &cdc_dmic_lines_sus
+			&cdc_dmic_clk_sus &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+		pinctrl-1 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus
+			&cdc_pdm_lines_2_act &cdc_dmic_lines_sus
+			&cdc_dmic_clk_sus &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+		pinctrl-2 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus
+			&cdc_pdm_lines_2_sus &cdc_dmic_lines_act
+			&cdc_dmic_clk_act &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+		pinctrl-3 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus
+			&cdc_pdm_lines_2_act &cdc_dmic_lines_act
+			&cdc_dmic_clk_act &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+		pinctrl-4 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus
+			&cdc_pdm_lines_2_sus &cdc_dmic_lines_sus
+			&cdc_dmic_clk_sus &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+		pinctrl-5 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus
+			&cdc_pdm_lines_2_act &cdc_dmic_lines_sus
+			&cdc_dmic_clk_sus &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+		pinctrl-6 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_sus
+			&cdc_pdm_lines_2_sus &cdc_dmic_lines_act
+			&cdc_dmic_clk_act &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+		pinctrl-7 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_sus
+			&cdc_pdm_lines_2_act &cdc_dmic_lines_act
+			&cdc_dmic_clk_act &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+		pinctrl-8 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act
+			&cdc_pdm_lines_2_sus &cdc_dmic_lines_sus
+			&cdc_dmic_clk_sus &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+		pinctrl-9 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act
+			&cdc_pdm_lines_2_act &cdc_dmic_lines_sus
+			&cdc_dmic_clk_sus &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+		pinctrl-10 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act
+			&cdc_pdm_lines_2_sus &cdc_dmic_lines_act
+			&cdc_dmic_clk_act &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+		pinctrl-11 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act
+			&cdc_pdm_lines_2_act &cdc_dmic_lines_act
+			&cdc_dmic_clk_act &pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+		pinctrl-12 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act
+			&cdc_pdm_lines_2_sus &cdc_dmic_lines_sus
+			&cdc_dmic_clk_sus &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+		pinctrl-13 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act
+			&cdc_pdm_lines_2_act &cdc_dmic_lines_sus
+			&cdc_dmic_clk_sus &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+		pinctrl-14 = <&cdc_pdm_lines_sus &cdc_pdm_comp_lines_act
+			&cdc_pdm_lines_2_sus &cdc_dmic_lines_act
+			&cdc_dmic_clk_act &pri_tlmm_lines_act &pri_tlmm_ws_act>;
+		pinctrl-15 = <&cdc_pdm_lines_act &cdc_pdm_comp_lines_act
+			&cdc_pdm_lines_2_act &cdc_dmic_lines_act
+			&cdc_dmic_lines_act &pri_tlmm_lines_act
+			&pri_tlmm_ws_act>;
+
+		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+				<&loopback>, <&compress>, <&hostless>,
+				<&afe>, <&lsm>, <&routing>, <&lpa>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+				"msm-pcm-dsp.2", "msm-voip-dsp",
+				"msm-pcm-voice", "msm-pcm-loopback",
+				"msm-compress-dsp", "msm-pcm-hostless",
+				"msm-pcm-afe", "msm-lsm-client",
+				"msm-pcm-routing", "msm-pcm-lpa";
+		asoc-cpu = <&dai_pri_auxpcm>,
+				<&dai_mi2s0>, <&dai_mi2s1>,
+				<&dai_mi2s2>, <&dai_mi2s3>,
+				<&dai_mi2s5>, <&dai_mi2s6>,
+				<&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+				<&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>,
+				<&bt_sco_rx>, <&bt_sco_tx>,
+				<&int_fm_rx>, <&int_fm_tx>,
+				<&afe_pcm_rx>, <&afe_pcm_tx>,
+				<&afe_proxy_rx>, <&afe_proxy_tx>,
+				<&incall_record_rx>, <&incall_record_tx>,
+				<&incall_music_rx>, <&incall_music_2_rx>;
+		asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+				"msm-dai-q6-mi2s.5", "msm-dai-q6-mi2s.6",
+				"msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
+				"msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+				"msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+				"msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+				"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+				"msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293",
+				"msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
+				"msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
+				"msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
+				"msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770";
+
+		asoc-codec = <&stub_codec>, <&pm8953_diangu_dig>, <&hdmi_dba>;
+		asoc-codec-names = "msm-stub-codec.1", "cajon_codec",
+							"msm-hdmi-dba-codec-rx";
+		asoc-wsa-codec-names = "wsa881x-i2c-codec.2-000f";
+		asoc-wsa-codec-prefixes = "SpkrMono";
+
+		msm-vdd-wsa-switch-supply = <&pm8953_l5>;
+		qcom,msm-vdd-wsa-switch-voltage = <1800000>;
+		qcom,msm-vdd-wsa-switch-current = <10000>;
+	};
+
+	clock_audio: audio_ext_clk {
+		status = "disabled";
+		compatible = "qcom,audio-ref-clk";
+		clock-names = "osr_clk";
+		qcom,node_has_rpm_clock;
+		#clock-cells = <1>;
+	};
+
+};
+
+&adsp_io {
+	qcom,virtual-addr-pool = <0x10000000 0x0fffffff>;
+	#iommu-cells = <1>;
+};
+
+&clock_audio {
+	status = "okay";
+	qcom,audio-ref-clk-gpio = <&pm8953_gpios 1 0>;
+	qcom,lpass-mclk-id = "pri_mclk";
+	clocks = <&clock_gcc clk_div_clk2>;
+	pinctrl-names = "sleep", "active";
+	pinctrl-0 = <&cdc_mclk2_sleep>;
+	pinctrl-1 = <&cdc_mclk2_active>;
+};
+
+&pm8953_1 {
+	status = "okay";
+	pm8953_diangu_dig: 8953_wcd_codec@f000 {
+		status = "okay";
+		compatible = "qcom,msm8x16_wcd_codec";
+		reg = <0xf000 0x100>;
+		interrupt-parent = <&spmi_bus>;
+		interrupts = <0x1 0xf0 0x0>,
+			     <0x1 0xf0 0x1>,
+			     <0x1 0xf0 0x2>,
+			     <0x1 0xf0 0x3>,
+			     <0x1 0xf0 0x4>,
+			     <0x1 0xf0 0x5>,
+			     <0x1 0xf0 0x6>,
+			     <0x1 0xf0 0x7>;
+		interrupt-names = "spk_cnp_int",
+				  "spk_clip_int",
+				  "spk_ocp_int",
+				  "ins_rem_det1",
+				  "but_rel_det",
+				  "but_press_det",
+				  "ins_rem_det",
+				  "mbhc_int";
+
+		cdc-vdda-cp-supply = <&pm8953_s4>;
+		qcom,cdc-vdda-cp-voltage = <1900000 2050000>;
+		qcom,cdc-vdda-cp-current = <500000>;
+
+		cdc-vdd-io-supply = <&pm8953_l5>;
+		qcom,cdc-vdd-io-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-io-current = <5000>;
+
+		cdc-vdd-pa-supply = <&pm8953_s4>;
+		qcom,cdc-vdd-pa-voltage = <1900000 2050000>;
+		qcom,cdc-vdd-pa-current = <260000>;
+
+		cdc-vdd-mic-bias-supply = <&pm8953_l13>;
+		qcom,cdc-vdd-mic-bias-voltage = <3125000 3125000>;
+		qcom,cdc-vdd-mic-bias-current = <5000>;
+
+		qcom,cdc-mclk-clk-rate = <9600000>;
+
+		qcom,cdc-static-supplies =  "cdc-vdd-io",
+					   "cdc-vdd-pa",
+					   "cdc-vdda-cp";
+
+		qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+		qcom,dig-cdc-base-addr = <0xc0f0000>;
+	};
+
+	pm8953_diangu_analog: 8953_wcd_codec@f100 {
+		status = "okay";
+		compatible = "qcom,msm8x16_wcd_codec";
+		reg = <0xf100 0x100>;
+		interrupt-parent = <&spmi_bus>;
+		interrupts = <0x1 0xf1 0x0>,
+			     <0x1 0xf1 0x1>,
+			     <0x1 0xf1 0x2>,
+			     <0x1 0xf1 0x3>,
+			     <0x1 0xf1 0x4>,
+			     <0x1 0xf1 0x5>;
+		interrupt-names = "ear_ocp_int",
+				  "hphr_ocp_int",
+				  "hphl_ocp_det",
+				  "ear_cnp_int",
+				  "hphr_cnp_int",
+				  "hphl_cnp_int";
+		qcom,dig-cdc-base-addr = <0xc0f0000>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam-dev.dts b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-dev.dts
new file mode 100644
index 0000000..7947008
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-dev.dts
@@ -0,0 +1,159 @@
+/*
+ * 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 "apq8053-lat-concam.dtsi"
+#include "apq8053-camera-sensor-mtp.dtsi"
+#include "apq8053-lat-concam-regulator.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8053 LAT Concam Dev board";
+	compatible = "qcom,apq8053-mtp", "qcom,apq8053", "qcom,mtp";
+	qcom,board-id= <0x56 0x30>;
+};
+
+&pm8953_mpps {
+	mpp@a100 {
+		reg = <0xa100 0x100>;
+		qcom,pin-num = <2>;
+		qcom,mode = <4>; // A-input
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <1>; // QPNP_PIN_AIN_AMUX_CH6 = 1 for MPP2
+		qcom,master-en = <1>; //Enable MPP
+		qcom,src-sel = <0>; /* Function constant */
+		status = "okay";
+	};
+
+	mpp@a200 {
+		/* MPP3 - PA_THERM config */
+		reg = <0xa200 0x100>;
+		com,pin-num = <3>;
+		qcom,mode = <4>; /* AIN input */
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <2>; /* AMUX 7 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+		status = "okay";
+	};
+
+	mpp@a300 {
+		/* MPP4 - CASE_THERM config */
+		reg = <0xa300 0x100>;
+		com,pin-num = <4>;
+		qcom,mode = <4>; /* AIN input */
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <3>; /* AMUX 8 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+		status = "okay";
+	};
+};
+
+&tlmm {
+	button_active: button_active {
+		mux {
+			pins = "gpio57";
+			function = "gpio";
+		};
+
+		config {
+			pins = "gpio57";
+			drive-strength = <8>;
+			bias-pull-up;
+		};
+	};
+
+	icr_int {
+		qcom,pins = <&tlmm 53>;
+		qcom,num-grp-pins = <1>;
+		qcom,pin-func = <0>;
+		label = "icr-int";
+		icr_int_default: icr_int_default {
+			drive-strength = <2>;	/* 2 MA */
+			bias-pull-up;		/* PULL UP*/
+		};
+	};
+
+	gcc_gp1_clk_pin {
+		qcom,pins = <&tlmm 33>;
+		qcom,num-grp-pins = <1>;
+		qcom,pin-func = <2>;
+		label = "gp1-clk-pin";
+		gcc_gp1_clk_pin: gcc_gp1_clk_pin {
+			drive-strength = <2>;	/* 2 MA */
+			bias-disable;
+		};
+	};
+
+	bt_host_wake_default: bt_host_wake_default {
+		mux {
+			pins = "gpio52";
+			function = "gpio";
+		};
+		config {
+			pins = "gpio52";
+			bias-disable; /* No PULL */
+			drive-strength = <2>;
+		};
+	};
+};
+
+&soc {
+	usb_detect: usb_detect {
+		compatible = "linux,extcon-usb-gpio";
+		vbus-gpio = <&tlmm 57 GPIO_ACTIVE_HIGH>;
+		qcom,enable-button-mode;
+
+		pinctrl-names = "button_active";
+		pinctrl-0 = <&button_active>;
+	};
+
+	hbtp {
+		status = "disabled";
+	};
+};
+
+&usb3 {
+	extcon = <&usb_detect>;
+};
+
+&firmware {
+	android {
+		vbmeta {
+			compatible = "android,vbmeta";
+			parts = "vbmeta,boot,system,vendor,bluetooth,modem,oem";
+		};
+		fstab {
+			/delete-node/ system;
+			vendor {
+				fsmgr_flags = "wait,slotselect,avb";
+			};
+		};
+	};
+};
+
+&modem_mem {
+	reg = <0x0 0x86c00000 0x0 0x1e00000>;
+};
+
+&wcnss_fw_mem {
+	reg = <0x0 0x89b00000 0x0 0x700000>;
+};
+
+&gpio_key_suspend {
+	config {
+		/delete-property/ bias-pull-up;
+		bias-pull-down;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam-proto.dts b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-proto.dts
new file mode 100644
index 0000000..f3124bc
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-proto.dts
@@ -0,0 +1,161 @@
+/*
+ * 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 "apq8053-lat-concam.dtsi"
+#include "apq8053-camera-sensor-mtp.dtsi"
+#include "apq8053-lat-concam-regulator.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8053 LAT Concam Dev board";
+	compatible = "qcom,apq8053-mtp", "qcom,apq8053", "qcom,mtp";
+	qcom,board-id= <0x56 0x31>;
+};
+
+
+
+&pm8953_mpps {
+	mpp@a100 {
+		reg = <0xa100 0x100>;
+		qcom,pin-num = <2>;
+		qcom,mode = <4>; // A-input
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <1>; // QPNP_PIN_AIN_AMUX_CH6 = 1 for MPP2
+		qcom,master-en = <1>; //Enable MPP
+		qcom,src-sel = <0>; /* Function constant */
+		status = "okay";
+	};
+
+	mpp@a200 {
+		/* MPP3 - PA_THERM config */
+		reg = <0xa200 0x100>;
+		com,pin-num = <3>;
+		qcom,mode = <4>; /* AIN input */
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <2>; /* AMUX 7 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+		status = "okay";
+	};
+
+	mpp@a300 {
+		/* MPP4 - CASE_THERM config */
+		reg = <0xa300 0x100>;
+		com,pin-num = <4>;
+		qcom,mode = <4>; /* AIN input */
+		qcom,invert = <1>; /* Enable MPP */
+		qcom,ain-route = <3>; /* AMUX 8 */
+		qcom,master-en = <1>;
+		qcom,src-sel = <0>; /* Function constant */
+		status = "okay";
+	};
+};
+
+&tlmm {
+	button_active: button_active {
+		mux {
+			pins = "gpio57";
+			function = "gpio";
+		};
+
+		config {
+			pins = "gpio57";
+			drive-strength = <8>;
+			bias-pull-up;
+		};
+	};
+
+	icr_int {
+		qcom,pins = <&tlmm 53>;
+		qcom,num-grp-pins = <1>;
+		qcom,pin-func = <0>;
+		label = "icr-int";
+		icr_int_default: icr_int_default {
+			drive-strength = <2>;	/* 2 MA */
+			bias-pull-up;		/* PULL UP*/
+		};
+	};
+
+	gcc_gp1_clk_pin {
+		qcom,pins = <&tlmm 33>;
+		qcom,num-grp-pins = <1>;
+		qcom,pin-func = <2>;
+		label = "gp1-clk-pin";
+		gcc_gp1_clk_pin: gcc_gp1_clk_pin {
+			drive-strength = <2>;	/* 2 MA */
+			bias-disable;
+		};
+	};
+
+	bt_host_wake_default: bt_host_wake_default {
+		mux {
+			pins = "gpio52";
+			function = "gpio";
+		};
+		config {
+			pins = "gpio52";
+			bias-disable; /* No PULL */
+			drive-strength = <2>;
+		};
+	};
+};
+
+&soc {
+	usb_detect: usb_detect {
+		compatible = "linux,extcon-usb-gpio";
+		vbus-gpio = <&tlmm 57 GPIO_ACTIVE_HIGH>;
+		qcom,enable-button-mode;
+
+		pinctrl-names = "button_active";
+		pinctrl-0 = <&button_active>;
+	};
+
+	hbtp {
+		status = "disabled";
+	};
+};
+
+&usb3 {
+	extcon = <&usb_detect>;
+};
+
+&firmware {
+	android {
+		vbmeta {
+			compatible = "android,vbmeta";
+			parts = "vbmeta,boot,system,vendor,bluetooth,modem,oem";
+		};
+		fstab {
+			/delete-node/ system;
+			vendor {
+				fsmgr_flags = "wait,slotselect,avb";
+			};
+		};
+	};
+};
+
+&modem_mem {
+	reg = <0x0 0x86c00000 0x0 0x1e00000>;
+};
+
+&wcnss_fw_mem {
+	reg = <0x0 0x89b00000 0x0 0x700000>;
+};
+
+&gpio_key_suspend {
+	config {
+		/delete-property/ bias-pull-up;
+		bias-pull-down;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam-regulator.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-regulator.dtsi
new file mode 100644
index 0000000..8fae286
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam-regulator.dtsi
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+
+&rpm_bus {
+	rpm-regulator-ldoa18 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <18>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		pm8953_l18: regulator-l18 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_l18";
+			qcom,set = <3>;
+			regulator-min-microvolt = <2700000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <2700000>;
+		};
+
+	};
+
+	rpm-regulator-ldoa9 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <9>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "okay";
+		regulator-boot-on;
+		regulator-always-on;
+		regulator-l9 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_l9";
+			qcom,set = <3>;
+			regulator-boot-on;
+			regulator-always-on;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <10>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		regulator-boot-on;
+		regulator-always-on;
+		pm8953_l10: regulator-l10 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_l10";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			regulator-boot-on;
+			regulator-always-on;
+		};
+	};
+
+	/* L4 for ALS, TMP, Moisture, Image Sensor, PD Control, Thermistor */
+	rpm-regulator-ldoa4 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		regulator-boot-on;
+		regulator-l4 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_l4";
+			qcom,set = <3>;
+			regulator-always-on;
+			regulator-boot-on;
+			status = "okay";
+		};
+	};
+
+	/* l2, l7 and l17 for cci */
+	rpm-regulator-ldoa2 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "okay";
+		regulator-l2 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_l2";
+			qcom,set = <3>;
+			regulator-always-on;
+			regulator-boot-on;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <7>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "okay";
+		regulator-l7 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_l7";
+			qcom,set = <3>;
+			regulator-always-on;
+			regulator-boot-on;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <17>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "okay";
+
+		regulator-l17 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_l17";
+			qcom,set = <3>;
+			regulator-always-on;
+			regulator-boot-on;
+			status = "okay";
+		};
+	};
+
+	/* l6 for eeprom/ Image sensor */
+
+	rpm-regulator-ldoa6 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <6>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "okay";
+		regulator-l6 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_l6";
+			qcom,set = <3>;
+			regulator-always-on;
+			regulator-boot-on;
+			status = "okay";
+		};
+	};
+
+	/* l5 for WSA8815 Speaker amp */
+	rpm-regulator-ldoa5 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <5>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "okay";
+		regulator-always-on;
+		regulator-boot-on;
+		regulator-l5 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_l5";
+			qcom,set = <3>;
+			regulator-always-on;
+			regulator-boot-on;
+			status = "okay";
+		};
+	};
+
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lat-concam.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lat-concam.dtsi
new file mode 100644
index 0000000..b359db3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lat-concam.dtsi
@@ -0,0 +1,580 @@
+/*
+ * 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 "msm8953.dtsi"
+#include "msm8953-pinctrl.dtsi"
+/ {
+	model = "Qualcomm Technologies, Inc. APQ 8953";
+	compatible = "qcom,apq8053";
+	qcom,msm-id = <304 0x0>;
+};
+
+/ {
+	/delete-property/ aliases;
+
+	aliases {
+		/* smdtty devices */
+		smd1 = &smdtty_apps_fm;
+		smd2 = &smdtty_apps_riva_bt_acl;
+		smd3 = &smdtty_apps_riva_bt_cmd;
+		smd4 = &smdtty_mbalbridge;
+		smd5 = &smdtty_apps_riva_ant_cmd;
+		smd6 = &smdtty_apps_riva_ant_data;
+		smd7 = &smdtty_data1;
+		smd8 = &smdtty_data4;
+		smd11 = &smdtty_data11;
+		smd21 = &smdtty_data21;
+		smd36 = &smdtty_loopback;
+		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
+		sdhc2 = &sdhc_2; /* SDC2 for SD card */
+		i2c1 = &i2c_1;
+		i2c2 = &i2c_2;
+		i2c3 = &i2c_3;
+		i2c4 = &i2c_4;
+		i2c5 = &i2c_5;
+		i2c7 = &i2c_7;
+		i2c8 = &i2c_8;
+		spi3 = &spi_3;
+	};
+
+};
+
+&sdhc_2 {
+	nest,workaround-ocr-add-vio = "VIO_3_3";
+};
+
+&soc {
+	i2c_4: i2c@78b8000 { /* BLSP1 QUP3 */
+		compatible = "qcom,i2c-msm-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0x78b8000 0x600>;
+		interrupt-names = "qup_irq";
+		interrupts = <0 98 0>;
+		qcom,clk-freq-out = <400000>;
+		qcom,clk-freq-in  = <19200000>;
+		clock-names = "iface_clk", "core_clk";
+		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+			<&clock_gcc clk_gcc_blsp1_qup4_i2c_apps_clk>;
+
+		pinctrl-names = "i2c_active", "i2c_sleep";
+		pinctrl-0 = <&i2c_4_active>;
+		pinctrl-1 = <&i2c_4_sleep>;
+		qcom,noise-rjct-scl = <0>;
+		qcom,noise-rjct-sda = <0>;
+		qcom,master-id = <86>;
+		dmas = <&dma_blsp1 10 64 0x20000020 0x20>,
+			<&dma_blsp1 11 32 0x20000020 0x20>;
+		dma-names = "tx", "rx";
+		status = "disabled";
+	};
+
+	i2c_7: i2c@7AF7000 { /* BLSP2 QUP2 */
+		compatible = "qcom,i2c-msm-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0x7AF7000 0x600>;
+		interrupt-names = "qup_irq";
+		interrupts = <0 301 0>;
+		qcom,clk-freq-out = <400000>;
+		qcom,clk-freq-in  = <19200000>;
+		clock-names = "iface_clk", "core_clk";
+		clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>,
+			<&clock_gcc clk_gcc_blsp2_qup3_i2c_apps_clk>;
+
+		pinctrl-names = "i2c_active", "i2c_sleep";
+		pinctrl-0 = <&i2c_7_active>;
+		pinctrl-1 = <&i2c_7_sleep>;
+		qcom,noise-rjct-scl = <0>;
+		qcom,noise-rjct-sda = <0>;
+		qcom,master-id = <84>;
+		dmas = <&dma_blsp1 8 64 0x20000020 0x20>,
+			<&dma_blsp1 9 32 0x20000020 0x20>;
+		dma-names = "tx", "rx";
+		status = "disabled";
+	};
+
+	i2c_8: i2c@7AF8000 { /* BLSP2 QUP3 */
+		compatible = "qcom,i2c-msm-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0x7AF8000 0x600>;
+		interrupt-names = "qup_irq";
+		interrupts = <0 302 0>;
+		qcom,clk-freq-out = <400000>;
+		qcom,clk-freq-in  = <19200000>;
+		clock-names = "iface_clk", "core_clk";
+		clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>,
+			<&clock_gcc clk_gcc_blsp2_qup4_i2c_apps_clk>;
+
+		pinctrl-names = "i2c_active", "i2c_sleep";
+		pinctrl-0 = <&i2c_8_active>;
+		pinctrl-1 = <&i2c_8_sleep>;
+		qcom,noise-rjct-scl = <0>;
+		qcom,noise-rjct-sda = <0>;
+		qcom,master-id = <84>;
+		dmas = <&dma_blsp1 10 64 0x20000020 0x20>,
+			<&dma_blsp1 11 32 0x20000020 0x20>;
+		dma-names = "tx", "rx";
+		status = "disabled";
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "gpio-keys";
+		pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
+		pinctrl-0 = <&gpio_key_active>;
+		pinctrl-1 = <&gpio_key_suspend>;
+
+		camera_focus {
+			label = "camera_focus";
+			gpios = <&tlmm 87 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x210>;
+			debounce-interval = <15>;
+		};
+
+		camera_snapshot {
+			label = "camera_snapshot";
+			gpios = <&tlmm 86 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x2fe>;
+			debounce-interval = <15>;
+		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&tlmm 85 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			debounce-interval = <15>;
+		};
+	};
+
+	hbtp {
+		compatible = "qcom,hbtp-input";
+		vcc_ana-supply = <&pm8953_l10>;
+		vcc_dig-supply = <&pm8953_l5>;
+		qcom,afe-load = <50000>;
+		qcom,afe-vtg-min = <2850000>;
+		qcom,afe-vtg-max = <2850000>;
+		qcom,dig-load = <15000>;
+		qcom,dig-vtg-min = <1800000>;
+		qcom,dig-vtg-max = <1800000>;
+	};
+};
+
+&soc {
+	qcom,rmnet-ipa {
+		status = "disabled";
+	};
+};
+
+&ipa_hw {
+	status = "disabled";
+};
+
+&secure_mem {
+	status = "disabled";
+};
+
+&tlmm {
+	i2c_4 {
+		i2c_4_active: i2c_4_active {
+			/* active state */
+			mux {
+				pins = "gpio14", "gpio15";
+				function = "blsp_i2c4";
+			};
+
+			config {
+				pins = "gpio14", "gpio15";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		i2c_4_sleep: i2c_4_sleep {
+			/* suspended state */
+			mux {
+				pins = "gpio14", "gpio15";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio14", "gpio15";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+	};
+
+	i2c_7 {
+		i2c_7_active: i2c_7_active {
+			/* active state */
+			mux {
+				pins = "gpio135", "gpio136";
+				function = "blsp_i2c7";
+			};
+
+			config {
+				pins = "gpio135", "gpio136";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		i2c_7_sleep: i2c_7_sleep {
+			/* suspended state */
+			mux {
+				pins = "gpio135", "gpio136";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio135", "gpio136";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+	};
+
+	i2c_8 {
+		i2c_8_active: i2c_8_active {
+			/* active state */
+			mux {
+				pins = "gpio98", "gpio99";
+				function = "blsp_i2c8";
+			};
+
+			config {
+				pins = "gpio98", "gpio99";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		i2c_8_sleep: i2c_8_sleep {
+			/* suspended state */
+			mux {
+				pins = "gpio98", "gpio99";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio98", "gpio99";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+	};
+};
+
+&blsp1_uart0 {
+	status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console_active>;
+};
+
+&i2c_4 {
+	status = "ok";
+
+	opt3001@44 {
+		compatible = "ti,opt3001";
+		reg = <0x44>; /* ALS_ADDR connected to ground */
+		status = "okay";
+	};
+
+	ina231@40 {
+		compatible = "ti,ina231";
+		reg = <0x40>;
+		shunt-resistor = <10000>;
+	};
+};
+
+&sdhc_1 {
+	/* device core power supply */
+	vdd-supply = <&pm8953_l8>;
+	qcom,vdd-voltage-level = <2900000 2900000>;
+	qcom,vdd-current-level = <200 570000>;
+
+	/* device communication power supply */
+	vdd-io-supply = <&pm8953_l5>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-lpm-sup;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 325000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on  &sdc1_rclk_on>;
+	pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000
+								384000000>;
+	qcom,nonremovable;
+	qcom,bus-speed-mode = "HS200_1p8v";
+
+	status = "ok";
+};
+
+&i2c_8 {
+	status = "ok";
+
+	tlc59108@42 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#gpio-cells = <2>;
+		enable-gpio = <&tlmm 61 GPIO_ACTIVE_HIGH>;
+		compatible = "ti,tlc59108";
+		label = "tlc59108";
+		reg = <0x42>;
+
+		chan0@0 {
+			label = "tlc59108:chan0";
+			reg = <0x0>;
+		};
+
+		chan1@1 {
+			label = "tlc59108:chan1";
+			reg = <0x1>;
+		};
+
+		chan2@2 {
+			label = "tlc59108:chan2";
+			reg = <0x2>;
+		};
+
+		chan3@3 {
+			label = "tlc59108:chan3";
+			reg = <0x3>;
+		};
+
+		chan4@4 {
+			label = "tlc59108:chan4";
+			reg = <0x4>;
+		};
+
+		chan5@5 {
+			label = "tlc59108:chan5";
+			reg = <0x5>;
+		};
+
+		chan6@6 {
+			label = "tlc59108:chan6";
+			reg = <0x6>;
+		};
+
+		chan7@7 {
+			label = "tlc59108:chan7";
+			reg = <0x7>;
+		};
+	};
+
+	tlc59116@68 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#gpio-cells = <2>;
+		enable-gpio = <&tlmm 61 GPIO_ACTIVE_HIGH>;
+		compatible = "ti,tlc59116";
+		label = "tlc59116";
+		reg = <0x68>;
+
+		chan0@0 {
+			label = "tlc59116:chan0";
+			reg = <0x0>;
+		};
+
+		chan1@1 {
+			label = "tlc59116:chan1";
+			reg = <0x1>;
+		};
+
+		chan2@2 {
+			label = "tlc59116:chan2";
+			reg = <0x2>;
+		};
+
+		chan3@3 {
+			label = "tlc59116:chan3";
+			reg = <0x3>;
+		};
+
+		chan4@4 {
+			label = "tlc59116:chan4";
+			reg = <0x4>;
+		};
+
+		chan5@5 {
+			label = "tlc59116:chan5";
+			reg = <0x5>;
+		};
+
+		chan6@6 {
+			label = "tlc59116:chan6";
+			reg = <0x6>;
+		};
+
+		chan7@7 {
+			label = "tlc59116:chan7";
+			reg = <0x7>;
+		};
+
+		chan8@8 {
+			label = "tlc59116:chan8";
+			reg = <0x8>;
+		};
+
+		chan9@9 {
+			label = "tlc59116:chan9";
+			reg = <0x9>;
+		};
+
+		chan10@10 {
+			label = "tlc59116:chan10";
+			reg = <0xa>;
+		};
+
+		chan11@11 {
+			label = "tlc59116:chan11";
+			reg = <0xb>;
+		};
+
+		chan12@12 {
+			label = "tlc59116:chan12";
+			reg = <0xc>;
+		};
+
+		chan13@13 {
+			label = "tlc59116:chan13";
+			reg = <0xd>;
+		};
+
+		chan14@14 {
+			label = "tlc59116:chan14";
+			reg = <0xe>;
+		};
+
+		chan15@15 {
+			label = "tlc59116:chan15";
+			reg = <0xf>;
+		};
+	};
+
+};
+
+&i2c_3 {
+	status = "ok";
+	eeprom0: qcom,eeprom@0 {
+		cell-index = <0>;
+		reg = <0x56>;
+		qcom,eeprom-name = "cat24c512";
+		compatible = "qcom,eeprom";
+		qcom,slave-addr = <0x56>;
+		qcom,cci-master = <0>;
+		/* For 512 Kb eeprom chip
+		 * add 8 logic eeprom blcoks each is 8KB
+		 */
+		qcom,num-blocks = <8>;
+
+		qcom,page0 = <0 0 0 0 0 0>;
+		qcom,poll0 = <0 0 0 0 0 0>;
+		qcom,saddr0 = <0x56>;
+		qcom,mem0 = <8192 0x0000 2 0 1 0>;
+
+		qcom,page1 = <0 0 0 0 0 0>;
+		qcom,poll1 = <0 0 0 0 0 0>;
+		qcom,saddr1 = <0x56>;
+		qcom,mem1 = <8192 0x2000 2 0 1 0>;
+
+		qcom,page2 = <0 0 0 0 0 0>;
+		qcom,poll2 = <0 0 0 0 0 0>;
+		qcom,saddr2 = <0x56>;
+		qcom,mem2 = <8192 0x4000 2 0 1 0>;
+
+		qcom,page3 = <0 0 0 0 0 0>;
+		qcom,poll3 = <0 0 0 0 0 0>;
+		qcom,saddr3 = <0x56>;
+		qcom,mem3 = <8192 0x6000 2 0 1 0>;
+
+		qcom,page4 = <0 0 0 0 0 0>;
+		qcom,poll4 = <0 0 0 0 0 0>;
+		qcom,saddr4 = <0x56>;
+		qcom,mem4 = <8192 0x8000 2 0 1 0>;
+
+		qcom,page5 = <0 0 0 0 0 0>;
+		qcom,poll5 = <0 0 0 0 0 0>;
+		qcom,saddr5 = <0x56>;
+		qcom,mem5 = <8192 0xA000 2 0 1 0>;
+
+		qcom,page6 = <0 0 0 0 0 0>;
+		qcom,poll6 = <0 0 0 0 0 0>;
+		qcom,saddr6 = <0x56>;
+		qcom,mem6 = <8192 0xC000 2 0 1 0>;
+
+		qcom,page7 = <0 0 0 0 0 0>;
+		qcom,poll7 = <0 0 0 0 0 0>;
+		qcom,saddr7 = <0x56>;
+		qcom,mem7 = <8192 0xE000 2 0 1 0>;
+
+		cam_vio-supply = <&pm8953_l6>;
+		qcom,cam-vreg-name = "cam_vio";
+		qcom,cam-vreg-min-voltage = <0>;
+		qcom,cam-vreg-max-voltage = <0>;
+		qcom,cam-vreg-op-mode = <0>;
+		qcom,cam-power-seq-type = "sensor_vreg";
+		qcom,cam-power-seq-val = "cam_vio";
+		qcom,cam-power-seq-cfg-val = <1>;
+		qcom,cam-power-seq-delay = <1>;
+		status = "ok";
+	};
+};
+
+&sdhc_2 {
+	/* device core power supply */
+	vdd-supply = <&pm8953_l10>;
+	qcom,vdd-voltage-level = <18000000 1800000>;
+	qcom,vdd-current-level = <200 22000>;
+
+	/* device communication power supply */
+	vdd-io-supply = <&pm8953_l12>;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 22000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>;
+	pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
+
+	#address-cells = <0>;
+	interrupt-parent = <&sdhc_2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+		1 &intc 0 221 0
+		2 &tlmm 45 0>;
+	interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+	/*cd-gpios = <&tlmm 45 0x1>;*/
+
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+								200000000>;
+	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+	status = "ok";
+};
+
+&pm8953_typec {
+	status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dts
index 63a364a..6c9c266 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dts
@@ -25,17 +25,3 @@
 &blsp2_uart0 {
 	status = "okay";
 };
-
-&i2c_3 {
-	status = "okay";
-	elan_ktf@10 {
-		compatible = "elan,ekth3500";
-		reg = <0x10>;
-		vdd-supply = <&pm8953_l10>;
-		vccio-supply = <&pm8953_l6>;
-		interrupt-parent = <&tlmm>;
-		reset-gpio = <&tlmm 64 GPIO_ACTIVE_LOW>;
-		elan,irq-gpio = <&tlmm 65 0x2008>;
-		interrupts = <65 0x2>;
-	};
-};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi
index 993799b..de707b8 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi
@@ -13,10 +13,23 @@
 
 #include "apq8053-lite-dragon.dtsi"
 
+&rpm_bus {
+	rpm-regulator-ldoa10 {
+		status = "okay";
+		pm8953_l10: regulator-l10 {
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <3300000>;
+			status = "okay";
+		};
+	};
+};
+
 &mdss_dsi0 {
 	qcom,ext-vdd-gpio = <&tlmm 100 0>;
 	qcom,platform-bklight-en-gpio = <&tlmm 95 0>;
 
+	/delete-property/ vdd-supply;
 	qcom,platform-lane-config = [00 00 ff 0f
 				00 00 ff 0f
 				00 00 ff 0f
@@ -66,3 +79,17 @@
 &camera2{
 	qcom,mount-angle = <270>;
 };
+
+&i2c_3 {
+	status = "okay";
+	elan_ktf@10 {
+		compatible = "elan,ekth3500";
+		reg = <0x10>;
+		vdd-supply = <&pm8953_l10>;
+		vccio-supply = <&pm8953_l6>;
+		interrupt-parent = <&tlmm>;
+		reset-gpio = <&tlmm 64 GPIO_ACTIVE_LOW>;
+		elan,irq-gpio = <&tlmm 65 0x2008>;
+		interrupts = <65 0x2>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.1.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.1.dts
new file mode 100644
index 0000000..ef4c7a1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.1.dts
@@ -0,0 +1,32 @@
+/*
+ * 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 "apq8053-lite.dtsi"
+#include "apq8053-lite-dragon-v2.2.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8053 Lite DragonBoard V2.2.1";
+	compatible = "qcom,apq8053-lite-dragonboard", "qcom,apq8053",
+			"qcom,dragonboard";
+	qcom,board-id = <0x01010320 0>;
+};
+
+&blsp2_uart0 {
+	status = "okay";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_inxnt51021_1200p_video>;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts
index 8b5dd2b..ecc4fea 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts
@@ -25,81 +25,3 @@
 &blsp2_uart0 {
 	status = "okay";
 };
-
-&i2c_3 {
-	status = "okay";
-	/delete-node/ himax_ts@48;
-	gt9xx-i2c@14 {
-		compatible = "goodix,gt9xx";
-		status = "okay";
-		reg = <0x14>;
-		vdd_ana-supply = <&pm8953_l10>;
-		vcc_i2c-supply = <&pm8953_l6>;
-		interrupt-parent = <&tlmm>;
-		interrupts = <65 0x2008>;
-		pinctrl-names = "gdix_ts_int_default", "gdix_ts_int_output_low",
-			"gdix_ts_int_output_high", "gdix_ts_int_input",
-			"gdix_ts_rst_default", "gdix_ts_rst_output_low",
-			"gdix_ts_rst_output_high", "gdix_ts_rst_input";
-		pinctrl-0 = <&ts_int_default>;
-		pinctrl-1 = <&ts_int_output_low>;
-		pinctrl-2 = <&ts_int_output_high>;
-		pinctrl-3 = <&ts_int_input>;
-		pinctrl-4 = <&ts_rst_default>;
-		pinctrl-5 = <&ts_rst_output_low>;
-		pinctrl-6 = <&ts_rst_output_high>;
-		pinctrl-7 = <&ts_rst_input>;
-
-		reset-gpios = <&tlmm 64 0x00>;
-		irq-gpios = <&tlmm 65 0x2008>;
-		irq-flags = <2>;
-
-		touchscreen-max-id = <11>;
-		touchscreen-size-x = <1200>;
-		touchscreen-size-y = <1920>;
-		touchscreen-max-w = <1024>;
-		touchscreen-max-p = <1024>;
-
-		goodix,type-a-report = <0>;
-		goodix,driver-send-cfg = <1>;
-		goodix,wakeup-with-reset = <0>;
-		goodix,resume-in-workqueue = <0>;
-		goodix,int-sync = <1>;
-		goodix,swap-x2y = <0>;
-		goodix,esd-protect = <1>;
-		goodix,pen-suppress-finger = <0>;
-		goodix,auto-update = <1>;
-		goodix,auto-update-cfg = <0>;
-		goodix,power-off-sleep = <0>;
-
-		goodix,cfg-group0 = [
-			5A B0 04 80 07 0A 35 10 22 08 32 0D 50 3C 0A 04
-			01 01 00 B4 11 11 44 15 19 1B 14 95 35 FF 3A 3C
-			39 13 00 00 00 98 03 1C 00 00 00 00 03 00 00 00
-			00 80 0A 37 46 40 E5 52 23 28 00 04 81 38 00 7F
-			3B 00 7D 3E 00 7C 41 00 7A 44 0C 7A 00 50 33 50
-			0B 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-			00 00 00 00 00 00 00 55 00 01 00 00 02 00 00 00
-			1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E
-			0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00 2A 29
-			28 27 26 25 24 23 22 21 20 1F 1E 1D 1C 1B 19 18
-			17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08
-			07 06 05 04 03 02 01 00 08 01
-		];
-
-		goodix,cfg-group2 = [
-			5B B0 04 80 07 0A 35 10 22 08 32 0D 50 32 0A 04
-			01 01 00 B4 11 11 44 2B 31 36 28 95 35 FF 3E 40
-			39 13 00 00 00 DA 03 1C 00 00 00 00 03 00 00 00
-			00 80 0A 32 42 40 E5 52 23 28 00 04 7D 33 00 7D
-			36 00 7E 39 00 7F 3C 00 80 40 0C 80 00 50 33 50
-			0B 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
-			00 00 00 00 00 00 00 55 00 01 00 00 02 00 00 00
-			1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E
-			0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00 2A 29
-			28 27 26 25 24 23 22 21 20 1F 1E 1D 1C 1B 19 18
-			17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08
-			07 06 05 04 03 02 01 00 81 01
-		];
-	};
-};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi
index 1744c90..d4dbc9e 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi
@@ -13,9 +13,94 @@
 
 #include "apq8053-lite-dragon.dtsi"
 
+&rpm_bus {
+	rpm-regulator-ldoa10 {
+		status = "okay";
+		pm8953_l10: regulator-l10 {
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <3300000>;
+			status = "okay";
+		};
+	};
+};
+
 &i2c_3 {
 	status = "okay";
 	/delete-node/ himax_ts@48;
+	gt9xx-i2c@14 {
+		compatible = "goodix,gt9xx";
+		status = "okay";
+		reg = <0x14>;
+		vdd_ana-supply = <&pm8953_l10>;
+		vcc_i2c-supply = <&pm8953_l6>;
+		interrupt-parent = <&tlmm>;
+		interrupts = <65 0x2008>;
+		pinctrl-names = "gdix_ts_int_default", "gdix_ts_int_output_low",
+			"gdix_ts_int_output_high", "gdix_ts_int_input",
+			"gdix_ts_rst_default", "gdix_ts_rst_output_low",
+			"gdix_ts_rst_output_high", "gdix_ts_rst_input";
+		pinctrl-0 = <&ts_int_default>;
+		pinctrl-1 = <&ts_int_output_low>;
+		pinctrl-2 = <&ts_int_output_high>;
+		pinctrl-3 = <&ts_int_input>;
+		pinctrl-4 = <&ts_rst_default>;
+		pinctrl-5 = <&ts_rst_output_low>;
+		pinctrl-6 = <&ts_rst_output_high>;
+		pinctrl-7 = <&ts_rst_input>;
+
+		reset-gpios = <&tlmm 64 0x00>;
+		irq-gpios = <&tlmm 65 0x2008>;
+		irq-flags = <2>;
+
+		touchscreen-max-id = <11>;
+		touchscreen-size-x = <1200>;
+		touchscreen-size-y = <1920>;
+		touchscreen-max-w = <1024>;
+		touchscreen-max-p = <1024>;
+
+		goodix,type-a-report = <0>;
+		goodix,driver-send-cfg = <1>;
+		goodix,wakeup-with-reset = <0>;
+		goodix,resume-in-workqueue = <0>;
+		goodix,int-sync = <1>;
+		goodix,swap-x2y = <0>;
+		goodix,esd-protect = <1>;
+		goodix,pen-suppress-finger = <0>;
+		goodix,auto-update = <1>;
+		goodix,auto-update-cfg = <0>;
+		goodix,power-off-sleep = <0>;
+
+		goodix,cfg-group0 = [
+			5A B0 04 80 07 0A 35 10 22 08 32 0D 50 3C 0A 04
+			01 01 00 B4 11 11 44 15 19 1B 14 95 35 FF 3A 3C
+			39 13 00 00 00 98 03 1C 00 00 00 00 03 00 00 00
+			00 80 0A 37 46 40 E5 52 23 28 00 04 81 38 00 7F
+			3B 00 7D 3E 00 7C 41 00 7A 44 0C 7A 00 50 33 50
+			0B 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+			00 00 00 00 00 00 00 55 00 01 00 00 02 00 00 00
+			1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E
+			0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00 2A 29
+			28 27 26 25 24 23 22 21 20 1F 1E 1D 1C 1B 19 18
+			17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08
+			07 06 05 04 03 02 01 00 08 01
+		];
+
+		goodix,cfg-group2 = [
+			5B B0 04 80 07 0A 35 10 22 08 32 0D 50 32 0A 04
+			01 01 00 B4 11 11 44 2B 31 36 28 95 35 FF 3E 40
+			39 13 00 00 00 DA 03 1C 00 00 00 00 03 00 00 00
+			00 80 0A 32 42 40 E5 52 23 28 00 04 7D 33 00 7D
+			36 00 7E 39 00 7F 3C 00 80 40 0C 80 00 50 33 50
+			0B 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+			00 00 00 00 00 00 00 55 00 01 00 00 02 00 00 00
+			1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E
+			0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00 2A 29
+			28 27 26 25 24 23 22 21 20 1F 1E 1D 1C 1B 19 18
+			17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08
+			07 06 05 04 03 02 01 00 81 01
+		];
+	};
 };
 
 &mdss_mdp {
@@ -32,7 +117,7 @@
 	pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
 	pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
 
-	vdd-supply = <&pm8953_l10>;
+	/delete-property/ vdd-supply;
 	vddio-supply = <&pm8953_l6>;
 	lab-supply = <&lab_regulator>;
 	ibb-supply = <&ibb_regulator>;
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.3.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.3.dtsi
index c682f58..830cb17 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.3.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.3.dtsi
@@ -13,6 +13,15 @@
 
 #include "apq8053-lite-dragon.dtsi"
 
+&soc {
+	cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&sec_tlmm_lines_act>;
+		pinctrl-1 = <&sec_tlmm_lines_sus>;
+	};
+};
+
 &pm8953_l4 {
 	status = "okay";
 	regulator-always-on;
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
index 186d6ef..6638aac 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
@@ -100,8 +100,8 @@
 	cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
 		compatible = "qcom,msm-cdc-pinctrl";
 		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&sec_tlmm_lines_act>;
-		pinctrl-1 = <&sec_tlmm_lines_sus>;
+		pinctrl-0 = <&sec_tlmm_lines_act &ext_amp_ctrl_active>;
+		pinctrl-1 = <&sec_tlmm_lines_sus &ext_amp_ctrl_sleep>;
 	};
 
 	gpio_keys {
@@ -130,11 +130,36 @@
 	};
 };
 
+&cdc_pdm_comp_lines_act {
+	mux {
+		pins = "gpio67";
+		function = "cdc_pdm0";
+	};
+
+	config {
+		pins = "gpio67";
+		drive-strength = <8>;
+	};
+};
+
+&cdc_pdm_comp_lines_sus {
+	mux {
+		pins = "gpio67";
+		function = "cdc_pdm0";
+	};
+
+	config {
+		pins = "gpio67";
+		drive-strength = <2>;
+		bias-disable;
+	};
+};
+
 &firmware {
 	android {
 		vbmeta {
 			compatible = "android,vbmeta";
-			parts = "vbmeta,boot,system,vendor,bluetooth,modem,oem";
+			parts = "vbmeta,boot,system,vendor,bluetooth,modem,dsp,oem";
 		};
 		fstab {
 			/delete-node/ system;
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-som.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-som.dts
new file mode 100644
index 0000000..eae1118
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-som.dts
@@ -0,0 +1,443 @@
+/*
+ * 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 "apq8053-lite.dtsi"
+#include "msm8953-pinctrl.dtsi"
+#include "pmi8950.dtsi"
+#include "msm8953-pmi8950.dtsi"
+#include "msm8953-mdss-panels.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8053 Lite SoM";
+};
+
+&soc {
+	vreg_5p0: vreg_5p0 {
+		compatible = "regulator-fixed";
+		regulator-name = "vreg_5p0";
+		status = "ok";
+		enable-active-high;
+	};
+
+	eldo_cam0_vreg: eldo_cam0_vreg {
+		compatible = "regulator-fixed";
+		regulator-name = "eldo_cam0_vreg";
+		regulator-min-microvolt = <1100000>;
+		regulator-max-microvolt = <1100000>;
+		status = "ok";
+		enable-active-high;
+		vin-supply = <&pm8953_l5>;
+	};
+
+	eldo_cam1_vreg: eldo_cam1_vreg {
+		compatible = "regulator-fixed";
+		regulator-name = "eldo_cam1_vreg";
+		regulator-min-microvolt = <1100000>;
+		regulator-max-microvolt = <1100000>;
+		status = "ok";
+		enable-active-high;
+		vin-supply = <&pm8953_l5>;
+	};
+
+	eldo_cam2_vreg: eldo_cam2_vreg {
+		compatible = "regulator-fixed";
+		regulator-name = "eldo_cam2_vreg";
+		regulator-min-microvolt = <1100000>;
+		regulator-max-microvolt = <1100000>;
+		status = "ok";
+		enable-active-high;
+		vin-supply = <&pm8953_l5>;
+	};
+
+	eldo_cam1_vcm_vreg: eldo_cam1_vcm_vreg {
+		compatible = "regulator-fixed";
+		regulator-name = "eldo_cam1_vcm_vreg";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		status = "ok";
+		enable-active-high;
+	};
+
+	cnss_sdio: qcom,cnss_sdio {
+		compatible = "qcom,cnss_sdio";
+		subsys-name = "AR6320";
+
+		/**
+		 * There is no vdd-wlan on board and this is not for DSRC.
+		 * IO and XTAL share the same vreg.
+		 */
+		vdd-wlan-io-supply = <&pm8953_l6>;
+		qcom,wlan-ramdump-dynamic = <0x200000>;
+		qcom,msm-bus,name = "msm-cnss";
+		qcom,msm-bus,num-cases = <4>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<79 512 0 0>,             /* No vote */
+			<79 512 6250 200000>,     /* 50 Mbps */
+			<79 512 25000 200000>,    /* 200 Mbps */
+			<79 512 2048000 4096000>; /* MAX */
+	};
+
+	bluetooth: bt_qca9379 {
+		compatible = "qca,qca6174";
+		qca,bt-reset-gpio = <&tlmm 76 0>; /* BT_EN */
+	};
+
+	cdc_dmic_gpios: cdc_dmic_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_dmic0_clk_act &cdc_dmic0_data_act>;
+		pinctrl-1 = <&cdc_dmic0_clk_sus &cdc_dmic0_data_sus>;
+	};
+
+	cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&sec_tlmm_lines_act &ext_amp_ctrl_active>;
+		pinctrl-1 = <&sec_tlmm_lines_sus &ext_amp_ctrl_sleep>;
+	};
+};
+
+&cdc_pdm_comp_lines_act {
+	mux {
+		pins = "gpio67";
+		function = "cdc_pdm0";
+	};
+
+	config {
+		pins = "gpio67";
+		drive-strength = <8>;
+	};
+};
+
+&cdc_pdm_comp_lines_sus {
+	mux {
+		pins = "gpio67";
+		function = "cdc_pdm0";
+	};
+
+	config {
+		pins = "gpio67";
+		drive-strength = <2>;
+		bias-disable;
+	};
+};
+
+&firmware {
+	android {
+		vbmeta {
+			compatible = "android,vbmeta";
+
+			parts = "vbmeta,boot,system,vendor,bluetooth,modem,oem";
+		};
+		fstab {
+			/delete-node/ system;
+			vendor {
+				fsmgr_flags = "wait,slotselect,avb";
+			};
+		};
+	};
+};
+
+&rpm_bus {
+	rpm-regulator-ldoa4 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "okay";
+
+		pm8953_l4: regulator-l4 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_l4";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+};
+
+&int_codec {
+	status = "ok";
+	qcom,model = "msm8953-openq624-snd-card";
+
+	/delete-property/ qcom,cdc-us-euro-gpios;
+	qcom,msm-hs-micbias-type = "internal";
+
+	qcom,audio-routing =
+		"RX_BIAS", "MCLK",
+		"SPK_RX_BIAS", "MCLK",
+		"INT_LDO_H", "MCLK",
+		"MIC BIAS Internal1", "Handset Mic",
+		"MIC BIAS Internal2", "Headset Mic",
+		"MIC BIAS Internal1", "Secondary Mic",
+		"AMIC1", "MIC BIAS Internal1",
+		"AMIC2", "MIC BIAS Internal2",
+		"AMIC3", "MIC BIAS Internal1",
+		"DMIC1", "MIC BIAS Internal1",
+		"MIC BIAS Internal1", "Digital Mic1",
+		"DMIC2", "MIC BIAS Internal1",
+		"MIC BIAS Internal1", "Digital Mic2";
+
+	qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
+	qcom,cdc-dmic-gpios = <&cdc_dmic_gpios>;
+
+	/delete-property/ asoc-wsa-codec-names;
+	/delete-property/ asoc-wsa-codec-prefixes;
+	/delete-property/ msm-vdd-wsa-switch-supply;
+	/delete-property/ qcom,msm-vdd-wsa-switch-voltage;
+	/delete-property/ qcom,msm-vdd-wsa-switch-current;
+};
+
+&soc {
+	/delete-node/ hbtp;
+};
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_boyi_hx83100a_800p_video>;
+};
+
+&blsp1_uart0 {
+	status = "okay";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console_active>;
+};
+
+
+&blsp2_uart0 {
+	status = "okay";
+};
+
+&sdhc_1 {
+	/* device core power supply */
+	vdd-supply = <&pm8953_l8>;
+	qcom,vdd-voltage-level = <2900000 2900000>;
+	qcom,vdd-current-level = <200 570000>;
+
+	/* device communication power supply */
+	vdd-io-supply = <&pm8953_l5>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-lpm-sup;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 325000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+	pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000
+								384000000>;
+	qcom,nonremovable;
+	qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
+
+	status = "ok";
+};
+
+&tlmm {
+	sdc2_wlan_gpio_on: sdc2_wlan_gpio_on {
+		mux {
+			pins = "gpio75";
+			function = "gpio";
+		};
+
+		config {
+			pins = "gpio75";
+			drive-strength = <10>;
+			bias-pull-up;
+			output-high;
+		};
+	};
+	sdc2_wlan_gpio_off: sdc2_wlan_gpio_off {
+		mux {
+			pins = "gpio75";
+			function = "gpio";
+		};
+
+		config {
+			pins = "gpio75";
+			drive-strength = <2>;
+			bias-disable;
+			output-low;
+		};
+	};
+};
+
+&sdhc_2 {
+	/* device communication power supply */
+	vdd-io-supply = <&pm8953_l12>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 22000>;
+
+	qcom,core_3_0v_support;
+	qcom,nonremovable;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on
+			&sdc2_wlan_gpio_on>;
+	pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off
+			&sdc2_wlan_gpio_off>;
+
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000>;
+	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+	status = "ok";
+};
+
+&spmi_bus {
+	qcom,pm8953@0 {
+		qcom,power-on@800 {
+			qcom,resin-gpiobase = <1019>;
+			qcom,pon_2 {
+				/delete-property/ linux,code;
+			};
+		};
+	};
+	qcom,pmi8950@2 {
+		qcom,leds@a100 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xa100 0x100>;
+			label = "mpp";
+
+			qcom,led_mpp_2 {
+				label = "mpp";
+				linux,name = "green";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode = "manual";
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x60>;
+			};
+		};
+
+		qcom,leds@a300 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xa300 0x100>;
+			label = "mpp";
+
+			qcom,led_mpp_4 {
+				label = "mpp";
+				linux,name = "blue";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode = "manual";
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x60>;
+			};
+		};
+	};
+};
+
+&pm8953_typec {
+	ss-mux-supply = <&pm8953_l13>;
+	qcom,ssmux-gpio = <&tlmm 139 GPIO_ACTIVE_HIGH>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&typec_ssmux_config>;
+};
+
+/{
+	mtp_batterydata: qcom,battery-data {
+		qcom,batt-id-range-pct = <15>;
+		#include "batterydata-itech-3000mah.dtsi"
+		#include "batterydata-ascent-3450mAh.dtsi"
+	};
+};
+
+&pmi_haptic{
+	status = "disabled";
+	qcom,actuator-type = "lra";
+	qcom,lra-auto-res-mode="qwd";
+	qcom,lra-high-z="opt1";
+	qcom,lra-res-cal-period = <0>;
+	qcom,wave-play-rate-us = <4165>;
+};
+
+&flash_led {
+	status = "disabled";
+};
+
+&pm8953_pwm {
+	status = "ok";
+};
+
+&pm8953_vadc {
+	/delete-node/ chan@13;
+};
+
+&pmi8950_gpios {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pmi_gpio1_default>;
+	pmi_gpio1_default: pmi8950_gpio1 {
+		pins = "gpio1";
+		function = "normal";
+		input-enable;
+		power-source = <0>;
+		status = "okay";
+	};
+};
+
+&pmi8950_mpps {
+	pinctrl-names = "default";
+	pinctrl-0 = <&ext_fet_wled_pwr_en_default>;
+	ext_fet_wled_pwr_en_default: pmi8950_mpp3 {
+		pins = "mpp3";  /* MPP_3 */
+		function = "digital"; /* Digital */
+		output-high; /* Output */
+		drive-strength = <2>; /* 1.8 mA */
+		power-source = <1>;
+		bias-disable = <0>; /* no pull */
+		status = "okay";
+	};
+};
+
+&pm8953_gpios {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pm_gpio1_div_clk2_default>;
+	pm_gpio1_div_clk2_default: pm8953_gpio1 {
+		pins = "gpio1";
+		function = "normal";
+		output-high;
+		power-source = <1>;
+		status = "okay";
+	};
+};
+
+&pm8953_mpps {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pm_mpp4_wled_pwm_ctrl_default>;
+	pm_mpp4_wled_pwm_ctrl_default: pm8953_mpp4 {
+		pins = "mpp4"; /* WLED_PWM_CTRL */
+		function = "digital"; /* Digital */
+		output-high;	/* Output */
+		drive-strength = <2>; /* 1.8 mA */
+		power-source = <0>; /* VPH_PWR */
+		qcom,dtest = <1>; /* DTEST1 */
+		bias-disable = <0>; /* no pull */
+		status = "okay";
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi
index 03c3659..995ca4d 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi
@@ -41,16 +41,6 @@
 			39 01 00 00 78 00 02 11 00
 			/*set display on and delay 20ms*/
 			39 01 00 00 14 00 02 29 00
-			/*enable extended command set*/
-			39 01 00 00 00 00 04 b9 83 10 0a
-			/*32KHZ PWM*/
-			39 01 00 00 00 00 08 c9 1f 00 08 1e 81 1e 00
-			/*backlight enable*/
-			39 01 00 00 00 00 02 53 24
-			/*still picture and delay 5ms*/
-			39 01 00 00 05 00 02 55 02
-			/*about 80% duty ratio*/
-			39 01 00 00 00 00 0a ca 40 3c 38 34 33 32 30 2c 28
 		];
 		qcom,mdss-dsi-off-command = [05 01 00 00 96 00 02 28 00
 					     05 01 00 00 00 00 02 10 00];
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-inxnt51021-1200p-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-inxnt51021-1200p-video.dtsi
new file mode 100644
index 0000000..2131aec
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-inxnt51021-1200p-video.dtsi
@@ -0,0 +1,106 @@
+/* Novatek Android Driver Sample Code for Novatek chipset
+*
+* Copyright (C) 2015 Novatek Microelectronics Corp.
+*
+* This software is licensed under the terms of the GNU General Public
+* License version 2, as published by the Free Software Foundation, and
+* may be copied, distributed, and modified under those terms.
+*
+* 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.
+*
+*/
+
+&mdss_mdp {
+        dsi_inxnt51021_1200p_video: qcom,mdss_dsi_inxnt51021_1200p_video {
+		qcom,mdss-dsi-panel-name = "inxnt51021 1200p video mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <1200>;
+		qcom,mdss-dsi-panel-height = <1920>;
+		qcom,mdss-dsi-h-front-porch = <100>;
+		qcom,mdss-dsi-h-back-porch = <32>;
+		qcom,mdss-dsi-h-pulse-width = <1>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <14>;
+		qcom,mdss-dsi-v-front-porch = <25>;
+		qcom,mdss-dsi-v-pulse-width = <1>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [
+			23 01 00 00 01 00 02 8F A5
+			23 01 00 00 00 00 02 83 00
+			23 01 00 00 00 00 02 84 00
+			23 01 00 00 00 00 02 8C 84
+			23 01 00 00 00 00 02 C5 50
+			23 01 00 00 00 00 02 C7 50
+			23 01 00 00 00 00 02 85 04
+			23 01 00 00 00 00 02 86 08
+			23 01 00 00 00 00 02 83 AA
+			23 01 00 00 00 00 02 84 11
+			23 01 00 00 00 00 02 9C 10
+			23 01 00 00 00 00 02 A9 4B
+			23 01 00 00 00 00 02 A0 36
+			23 01 00 00 00 00 02 A1 36
+			23 01 00 00 00 00 02 C0 00
+			23 01 00 00 00 00 02 E0 3D
+			23 01 00 00 00 00 02 83 BB
+			23 01 00 00 00 00 02 84 22
+			23 01 00 00 00 00 02 C0 00
+			23 01 00 00 00 00 02 E0 3D
+			23 01 00 00 00 00 02 83 CC
+			23 01 00 00 00 00 02 84 33
+			23 01 00 00 00 00 02 C0 00
+			23 01 00 00 00 00 02 E0 3D
+			23 01 00 00 00 00 02 8F 00
+		];
+		qcom,mdss-dsi-off-command = [
+			23 01 00 00 01 00 02 8F A5
+			23 01 00 00 00 00 02 83 00
+			23 01 00 00 78 00 02 84 00
+			05 01 00 00 78 00 02 10 00
+		];
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+		//qcom,cont-splash-enabled;
+		qcom,mdss-dsi-h-sync-pulse = <1>;
+		qcom,mdss-dsi-traffic-mode = "burst_mode";
+		qcom,mdss-dsi-lane-map = "lane_map_0123";
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-lane-2-state;
+		qcom,mdss-dsi-lane-3-state;
+		qcom,mdss-dsi-panel-timings = [f2 3a 28 00 6c 70 2c 3e 2e 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x0e>;
+		qcom,mdss-dsi-t-clk-pre = <0x33>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+		qcom,mdss-dsi-dma-trigger = "trigger_sw";
+		qcom,mdss-dsi-mdp-trigger = "none";
+		qcom,mdss-dsi-force-clock-lane-hs;
+		//qcom,platform-bklight-en-gpio = <&tlmm 46 0>;
+		//qcom,mdss-dsi-lcden-ctrl = <&tlmm 61 0>;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+		//qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+		//qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+		//qcom,mdss-dsi-pwm-gpio = <&pm8953_mpps 4 0>;
+		qcom,mdss-pan-physical-width-dimension = <135>;
+		qcom,mdss-pan-physical-height-dimension = <216>;
+		//qcom,mdss-dsi-reset-sequence = <1 10>, <0 5>, <1 50>;
+		qcom,mdss-dsi-lp11-init;
+		qcom,mdss-dsi-post-init-delay = <1>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-audio-bg_codec.dtsi b/arch/arm64/boot/dts/qcom/msm8909-audio-bg_codec.dtsi
index fa6498e..ae3900e 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-audio-bg_codec.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-audio-bg_codec.dtsi
@@ -50,7 +50,7 @@
 				"msm-voice-svc";
 		asoc-cpu = <&dai_pri_auxpcm>,
 				<&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>,
-				<&dai_mi2s3>, <&dai_mi2s5>, <&dai_mi2s6>,
+				<&dai_mi2s3>, <&dai_mi2s4>, <&dai_mi2s5>,
 				<&bt_sco_rx>, <&bt_sco_tx>, <&bt_a2dp_rx>,
 				<&int_fm_rx>, <&int_fm_tx>, <&afe_pcm_rx>,
 				<&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
@@ -63,7 +63,7 @@
 		asoc-cpu-names = "msm-dai-q6-auxpcm.1",
 				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
 				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
-				"msm-dai-q6-mi2s.5", "msm-dai-q6-mi2s.6",
+				"msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.6",
 				"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
 				"msm-dai-q6-dev.12290", "msm-dai-q6-dev.12292",
 				"msm-dai-q6-dev.12293", "msm-dai-q6-dev.224",
diff --git a/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
index e2fbc9e..48448862 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
@@ -113,17 +113,17 @@
 	gpio_keys {
 		compatible = "gpio-keys";
 		input-name = "gpio-keys";
-		pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
+		pinctrl-names = "default";
 		pinctrl-0 = <&gpio_key_active>;
-		pinctrl-1 = <&gpio_key_suspend>;
 
 		camera_focus {
 			label = "camera_focus";
 			gpios = <&msm_gpio 91 0x1>;
 			linux,input-type = <1>;
 			linux,code = <0x210>;
-			gpio-key,wakeup;
 			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
 		};
 
 		camera_snapshot {
@@ -131,8 +131,9 @@
 			gpios = <&msm_gpio 92 0x1>;
 			linux,input-type = <1>;
 			linux,code = <0x2fe>;
-			gpio-key,wakeup;
 			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
 		};
 
 		vol_up {
@@ -140,8 +141,9 @@
 			gpios = <&msm_gpio 90 0x1>;
 			linux,input-type = <1>;
 			linux,code = <115>;
-			gpio-key,wakeup;
 			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
 		};
 	};
 
@@ -209,7 +211,7 @@
 				"msm-voice-svc";
 		asoc-cpu = <&dai_pri_auxpcm>,
 				<&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>,
-				<&dai_mi2s3>, <&dai_mi2s5>, <&dai_mi2s6>,
+				<&dai_mi2s3>, <&dai_mi2s4>, <&dai_mi2s5>,
 				<&bt_sco_rx>, <&bt_sco_tx>, <&bt_a2dp_rx>,
 				<&int_fm_rx>, <&int_fm_tx>, <&afe_pcm_rx>,
 				<&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
@@ -218,7 +220,7 @@
 		asoc-cpu-names = "msm-dai-q6-auxpcm.1",
 				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
 				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
-				"msm-dai-q6-mi2s.5", "msm-dai-q6-mi2s.6",
+				"msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.6",
 				"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
 				"msm-dai-q6-dev.12290", "msm-dai-q6-dev.12292",
 				"msm-dai-q6-dev.12293", "msm-dai-q6-dev.224",
diff --git a/arch/arm64/boot/dts/qcom/msm8909.dtsi b/arch/arm64/boot/dts/qcom/msm8909.dtsi
index 8c06c93..15c6424 100644
--- a/arch/arm64/boot/dts/qcom/msm8909.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909.dtsi
@@ -1421,6 +1421,12 @@
 		qcom,latency-level = "ultra";
 	};
 
+	pcm_noirq: qcom,msm-pcm-dsp-noirq {
+		compatible = "qcom,msm-pcm-dsp-noirq";
+		qcom,msm-pcm-low-latency;
+		qcom,latency-level = "ultra";
+	};
+
 	lpa: qcom,msm-pcm-lpa {
 		compatible = "qcom,msm-pcm-lpa";
 	};
@@ -1475,20 +1481,6 @@
 			qcom,msm-mi2s-tx-lines = <0>;
 		};
 
-		dai_mi2s3: qcom,msm-dai-q6-mi2s-quat {
-			compatible = "qcom,msm-dai-q6-mi2s";
-			qcom,msm-dai-q6-mi2s-dev-id = <3>;
-			qcom,msm-mi2s-rx-lines = <0>;
-			qcom,msm-mi2s-tx-lines = <3>;
-		};
-
-		dai_mi2s5: qcom,msm-dai-q6-mi2s-quin {
-			compatible = "qcom,msm-dai-q6-mi2s";
-			qcom,msm-dai-q6-mi2s-dev-id = <5>;
-			qcom,msm-mi2s-rx-lines = <1>;
-			qcom,msm-mi2s-tx-lines = <2>;
-		};
-
 		dai_mi2s2: qcom,msm-dai-q6-mi2s-tert {
 			compatible = "qcom,msm-dai-q6-mi2s";
 			qcom,msm-dai-q6-mi2s-dev-id = <2>;
@@ -1496,7 +1488,21 @@
 			qcom,msm-mi2s-tx-lines = <3>;
 		};
 
-		dai_mi2s6: qcom,msm-dai-q6-mi2s-senary {
+		dai_mi2s3: qcom,msm-dai-q6-mi2s-quat {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <3>;
+			qcom,msm-mi2s-rx-lines = <0>;
+			qcom,msm-mi2s-tx-lines = <3>;
+		};
+
+		dai_mi2s4: qcom,msm-dai-q6-mi2s-quin {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <4>;
+			qcom,msm-mi2s-rx-lines = <1>;
+			qcom,msm-mi2s-tx-lines = <2>;
+		};
+
+		dai_mi2s5: qcom,msm-dai-q6-mi2s-senary {
 			compatible = "qcom,msm-dai-q6-mi2s";
 			qcom,msm-dai-q6-mi2s-dev-id = <6>;
 			qcom,msm-mi2s-rx-lines = <0>;
@@ -1647,6 +1653,13 @@
 		compatible = "qcom,msm-audio-ion";
 	};
 
+	qcom,msm-audio-apr {
+		compatible = "qcom,msm-audio-apr";
+		msm_audio_apr_dummy {
+			compatible = "qcom,msm-audio-apr-dummy";
+		};
+	};
+
 	qcom,mdsprpc-mem {
 		compatible = "qcom,msm-mdsprpc-mem-region";
 		memory-region = <&adsp_mem>;
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
index 9b9cd47..9212d2d 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
@@ -33,3 +33,13 @@
 		qcom,switch-source = <&pmi8940_switch>;
 	};
 };
+
+&labibb {
+	status = "ok";
+	qpnp,qpnp-labibb-mode = "lcd";
+};
+
+&mdss_dsi0 {
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dtsi
index e86b9d7..95e003b 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dtsi
@@ -22,3 +22,13 @@
 &usb_otg {
 	extcon = <&qpnp_smbcharger>;
 };
+
+&labibb {
+	status = "ok";
+	qpnp,qpnp-labibb-mode = "lcd";
+};
+
+&mdss_dsi0 {
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917.dtsi b/arch/arm64/boot/dts/qcom/msm8917.dtsi
index d5f5243..8494aef 100644
--- a/arch/arm64/boot/dts/qcom/msm8917.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917.dtsi
@@ -86,19 +86,19 @@
 		modem_mem: modem_region@0 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0x0 0x86800000 0x0 0x5000000>;
+			reg = <0x0 0x86800000 0x0 0x5500000>;
 		};
 
 		adsp_fw_mem: adsp_fw_region@0 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0x0 0x8b800000 0x0 0x1100000>;
+			reg = <0x0 0x8bd00000 0x0 0x1100000>;
 		};
 
 		wcnss_fw_mem: wcnss_fw_region@0 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0x0 0x8c900000 0x0 0x700000>;
+			reg = <0x0 0x8ce00000 0x0 0x700000>;
 		};
 
 		venus_mem: venus_region@0 {
diff --git a/arch/arm64/boot/dts/qcom/msm8937.dtsi b/arch/arm64/boot/dts/qcom/msm8937.dtsi
index 5180d1a..e328b4b 100644
--- a/arch/arm64/boot/dts/qcom/msm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937.dtsi
@@ -914,6 +914,7 @@
 		qcom,vdd-voltage-level = <0 1200000 1200000>;
 		vbus_otg-supply = <&smbcharger_charger_otg>;
 
+		qcom,hsusb-otg-phy-init-seq = <0x06 0x82 0xffffffff>;
 		qcom,hsusb-otg-phy-type = <3>; /* SNPS Femto PHY */
 		qcom,hsusb-otg-mode = <3>; /* OTG mode */
 		qcom,hsusb-otg-otg-control = <2>; /* PMIC */
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
index be6ab79..fa218ca 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
@@ -27,6 +27,7 @@
 #include "dsi-panel-hx83100a-800p-video.dtsi"
 #include "dsi-panel-boent51021-1200p-video.dtsi"
 #include "dsi-panel-hx8394d-wxga-video.dtsi"
+#include "dsi-panel-inxnt51021-1200p-video.dtsi"
 
 &soc {
 	dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -187,9 +188,17 @@
 };
 
 &dsi_hx8394d_kingdisplay_vid {
-    qcom,mdss-dsi-panel-timings-phy-v2 = [1c 19 02 03 01 03 04 a0
-        1c 19 02 03 01 03 04 a0
-        1c 19 02 03 01 03 04 a0
-        1c 19 02 03 01 03 04 a0
-        1c 07 02 03 01 03 04 a0];
+	qcom,mdss-dsi-panel-timings-phy-v2 = [1c 19 02 03 01 03 04 a0
+		1c 19 02 03 01 03 04 a0
+		1c 19 02 03 01 03 04 a0
+		1c 19 02 03 01 03 04 a0
+		1c 07 02 03 01 03 04 a0];
+};
+
+&dsi_inxnt51021_1200p_video {
+	qcom,mdss-dsi-panel-timings-phy-v2 = [25 20 08 0A 06 03 04 a0
+		25 20 08 0A 06 03 04 a0
+		25 20 08 0A 06 03 04 a0
+		25 20 08 0A 06 03 04 a0
+		25 1D 08 0A 06 03 04 a0];
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
index c58d82e..72513e1 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
@@ -466,6 +466,34 @@
 			};
 		};
 
+		ext_amp_ctrl {
+			label = "ext_amp_ctrl";
+			ext_amp_ctrl_active: ext_amp_ctrl_active {
+				mux {
+					pins = "gpio68";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio68";
+					drive-strength = <8>;   /* 8 MA */
+					bias-pull-up;           /*  PULL UP */
+					output-high;
+				};
+			};
+
+			ext_amp_ctrl_sleep: ext_amp_ctrl_sleep {
+				mux {
+					pins = "gpio68";
+					function = "gpio";
+				};
+				configs {
+					pins = "gpio68";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;         /* PULL DOWN */
+				};
+			};
+		};
+
 		cdc_dmic0_clk_act: cdc_dmic0_clk_act_default {
 				mux {
 						pins = "gpio89";
diff --git a/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi b/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
index 63bb25f..0d47ba6 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
@@ -138,15 +138,13 @@
 	};
 };
 
-&soc {
-	qcom,dsi-display@17 {
-		qcom,dsi-display-active;
+&ext_dsi_bridge_display {
+	qcom,dsi-display-active;
 
-		ports {
-			port@0 {
-				endpoint {
-					remote-endpoint = <&lt9611_in>;
-				};
+	ports {
+		port@0 {
+			endpoint {
+				remote-endpoint = <&lt9611_in>;
 			};
 		};
 	};
@@ -184,6 +182,8 @@
 		"MIC BIAS External2", "Digital Mic3",
 		"DMIC4", "MIC BIAS External2",
 		"MIC BIAS External2", "Digital Mic4",
+		"MICBIAS_REGULATOR", "VDDA18_L10_REGULATOR",
+		"VDDA18_L10_REGULATOR", "VDD_L1_REGULATOR",
 		"PDM_IN_RX1", "PDM_OUT_RX1",
 		"PDM_IN_RX2", "PDM_OUT_RX2",
 		"PDM_IN_RX3", "PDM_OUT_RX3",
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-base.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-base.dts
new file mode 100644
index 0000000..622230c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-base.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "qcs605-lc.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS605 LC SoC Ipcam base";
+	compatible = "qcom,qcs605";
+	qcom,board-id = <0 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts
index c7912d6..0cb7c33 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts
@@ -26,5 +26,5 @@
 	model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 IPC";
 	compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
 	qcom,msm-id = <347 0x0>;
-	qcom,board-id = <8 6>;
+	qcom,board-id = <0x020208 4>;
 };
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts
index 90dcd7b..37dc8e0 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts
@@ -20,5 +20,5 @@
 / {
 	model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 IPC";
 	compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
-	qcom,board-id = <8 6>;
+	qcom,board-id = <0x020208 4>;
 };
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi
index d6d9a17..51e9e1b 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi
@@ -194,3 +194,7 @@
 &wcd9335 {
 	/delete-property/ cdc-vdd-mic-bias-supply;
 };
+
+&int_codec {
+	status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-sde-display.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-sde-display.dtsi
index 654f3a1..99bf1e5 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-sde-display.dtsi
@@ -10,9 +10,45 @@
  * GNU General Public License for more details.
  */
 
+#include "dsi-panel-nt35597-truly-dualmipi-wqxga-video.dtsi"
 #include <dt-bindings/clock/mdss-10nm-pll-clk.h>
 
 &soc {
+
+	dsi_panel_pwr_supply: dsi_panel_pwr_supply {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,panel-supply-entry@0 {
+			reg = <0>;
+			qcom,supply-name = "vddio";
+			qcom,supply-min-voltage = <1800000>;
+			qcom,supply-max-voltage = <1800000>;
+			qcom,supply-enable-load = <62000>;
+			qcom,supply-disable-load = <80>;
+			qcom,supply-post-on-sleep = <20>;
+		};
+
+		qcom,panel-supply-entry@1 {
+			reg = <1>;
+			qcom,supply-name = "lab";
+			qcom,supply-min-voltage = <4600000>;
+			qcom,supply-max-voltage = <6000000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+		};
+
+		qcom,panel-supply-entry@2 {
+			reg = <2>;
+			qcom,supply-name = "ibb";
+			qcom,supply-min-voltage = <4600000>;
+			qcom,supply-max-voltage = <6000000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-post-on-sleep = <20>;
+		};
+	};
+
 	ext_dsi_bridge_display: qcom,dsi-display@0 {
 		compatible = "qcom,dsi-display";
 		label = "ext_dsi_bridge_display";
@@ -36,6 +72,28 @@
 		};
 	};
 
+	dsi_dual_nt35597_truly_video_display: qcom,dsi-display@1 {
+		compatible = "qcom,dsi-display";
+		label = "dsi_dual_nt35597_truly_video_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>;
+		qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>;
+		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+			<&mdss_dsi0_pll PCLK_MUX_0_CLK>;
+		clock-names = "src_byte_clk", "src_pixel_clk";
+
+		pinctrl-names = "panel_active", "panel_suspend";
+		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+		qcom,platform-reset-gpio = <&tlmm 93 0>;
+		qcom,panel-mode-gpio = <&tlmm 76 0>;
+		qcom,platform-en-gpio = <&tlmm 121 0>;
+
+		qcom,dsi-panel = <&dsi_dual_nt35597_truly_video>;
+		vddio-supply = <&pm660_l13>;
+	};
+
 	sde_wb: qcom,wb-display@0 {
 		compatible = "qcom,wb-display";
 		cell-index = <0>;
@@ -51,6 +109,32 @@
 	};
 };
 
+&dsi_dual_nt35597_truly_video {
+	qcom,mdss-dsi-t-clk-post = <0x0D>;
+	qcom,mdss-dsi-t-clk-pre = <0x2D>;
+	qcom,mdss-dsi-min-refresh-rate = <53>;
+	qcom,mdss-dsi-max-refresh-rate = <60>;
+	qcom,mdss-dsi-pan-enable-dynamic-fps;
+	qcom,mdss-dsi-pan-fps-update =
+		"dfps_immediate_porch_mode_vfp";
+	qcom,esd-check-enabled;
+	qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+	qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+	qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+	qcom,mdss-dsi-panel-status-value = <0x9c>;
+	qcom,mdss-dsi-panel-on-check-value = <0x9c>;
+	qcom,mdss-dsi-panel-status-read-length = <1>;
+	qcom,mdss-dsi-display-timings {
+		timing@0{
+			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
+				07 05 03 04 00];
+			qcom,display-topology = <2 0 2>,
+						<1 0 2>;
+			qcom,default-topology-index = <0>;
+		};
+	};
+};
+
 &mdss_dsi0 {
 	vdda-1p2-supply = <&pm660_l2>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sda845-v2-hdk.dtsi b/arch/arm64/boot/dts/qcom/sda845-v2-hdk.dtsi
index 378c4a1..d89a60e 100644
--- a/arch/arm64/boot/dts/qcom/sda845-v2-hdk.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda845-v2-hdk.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* 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
@@ -91,3 +91,8 @@
 		qcom,afe-power-off-delay-us = <6>;
 	};
 };
+
+&qupv3_se5_i2c {
+	status = "disabled";
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi
index eae8c56..2987d67 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi
@@ -30,7 +30,7 @@
 		cell-index = <1>;
 		reg = <0x1>;
 		compatible = "qcom,actuator";
-		qcom,cci-master = <0>;
+		qcom,cci-master = <1>;
 		cam_vaf-supply = <&pm8953_l17>;
 		qcom,cam-vreg-name = "cam_vaf";
 		qcom,cam-vreg-min-voltage = <2850000>;
@@ -156,6 +156,43 @@
 		qcom,clock-rates = <19200000 0>;
 	};
 
+	eeprom2: qcom,eeprom@2 {
+		cell-index = <2>;
+		compatible = "qcom,eeprom";
+		qcom,cci-master = <1>;
+		reg = <0x2>;
+		cam_vdig-supply = <&pm8953_l3>;
+		cam_vana-supply = <&pm8953_l22>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vaf-supply = <&pm8953_l17>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+					"cam_vaf";
+		qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk2_default
+				&cam_sensor_front1_default>;
+		pinctrl-1 = <&cam_sensor_mclk2_sleep
+				&cam_sensor_front1_sleep>;
+		gpios = <&tlmm 28 0>,
+			<&tlmm 40 0>,
+			<&tlmm 39 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+					  "CAM_RESET2",
+					  "CAM_STANDBY2";
+		status = "ok";
+		clocks = <&clock_gcc clk_mclk2_clk_src>,
+				<&clock_gcc clk_gcc_camss_mclk2_clk>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <19200000 0>;
+	};
+
 	qcom,camera@0 {
 		cell-index = <0>;
 		compatible = "qcom,camera";
@@ -249,9 +286,9 @@
 		qcom,csiphy-sd-index = <1>;
 		qcom,csid-sd-index = <1>;
 		qcom,mount-angle = <90>;
-		qcom,eeprom-src = <&eeprom1>;
+		qcom,eeprom-src = <&eeprom2>;
 		qcom,actuator-src = <&actuator1>;
-		cam_vdig-supply = <&pm8953_l23>;
+		cam_vdig-supply = <&pm8953_l3>;
 		cam_vana-supply = <&pm8953_l22>;
 		cam_vio-supply = <&pm8953_l6>;
 		cam_vaf-supply = <&pm8953_l17>;
@@ -278,7 +315,7 @@
 					  "CAM_STANDBY2";
 		qcom,sensor-position = <1>;
 		qcom,sensor-mode = <0>;
-		qcom,cci-master = <0>;
+		qcom,cci-master = <1>;
 		status = "ok";
 		clocks = <&clock_gcc clk_mclk2_clk_src>,
 			<&clock_gcc clk_gcc_camss_mclk2_clk>;
diff --git a/arch/arm64/boot/dts/qcom/sdm439.dtsi b/arch/arm64/boot/dts/qcom/sdm439.dtsi
index 9067bc9..ef8ea1f3 100644
--- a/arch/arm64/boot/dts/qcom/sdm439.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439.dtsi
@@ -238,6 +238,18 @@
 	};
 };
 
+&modem_mem {
+	reg = <0x0 0x86800000 0x0 0x5500000>;
+};
+
+&adsp_fw_mem {
+	reg = <0x0 0x8bd00000 0x0 0x1100000>;
+};
+
+&wcnss_fw_mem {
+	reg = <0x0 0x8ce00000 0x0 0x700000>;
+};
+
 &soc {
 	pil_gpu: qcom,kgsl-hyp {
 		compatible = "qcom,pil-tz-generic";
diff --git a/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi
index 4d6b32f..f55c050 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi
@@ -124,6 +124,8 @@
 		"MIC BIAS External", "Digital Mic3",
 		"DMIC4", "MIC BIAS External",
 		"MIC BIAS External", "Digital Mic4",
+		"MICBIAS_REGULATOR", "VDDA18_L10_REGULATOR",
+		"VDDA18_L10_REGULATOR", "VDD_L1_REGULATOR",
 		"SpkrLeft IN", "SPK1 OUT",
 		"SpkrRight IN", "SPK2 OUT",
 		"PDM_IN_RX1", "PDM_OUT_RX1",
@@ -501,12 +503,22 @@
 		qcom,cdc-vdd-mic-bias-voltage = <3088000 3088000>;
 		qcom,cdc-vdd-mic-bias-current = <5000>;
 
+		cdc-vdda18-l10-supply = <&pm660_l10>;
+		qcom,cdc-vdda18-l10-voltage = <1800000 1800000>;
+		qcom,cdc-vdda18-l10-current = <30000>;
+
+		cdc-vdd-l1-supply = <&pm660l_l1>;
+		qcom,cdc-vdd-l1-voltage = <880000 880000>;
+		qcom,cdc-vdd-l1-current = <30000>;
+
 		qcom,cdc-mclk-clk-rate = <9600000>;
 
 		qcom,cdc-static-supplies = "cdc-vdda-cp",
 					   "cdc-vdd-pa";
 
-		qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+		qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias",
+					      "cdc-vdda18-l10",
+					      "cdc-vdd-l1";
 
 		/*
 		 * Not marking address @ as driver searches this child
diff --git a/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi
index 5ff2c32..2b6b641 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-qrd.dtsi
@@ -195,6 +195,8 @@
 		"AMIC1", "MIC BIAS External",
 		"MIC BIAS External", "Secondary Mic",
 		"AMIC3", "MIC BIAS External",
+		"MICBIAS_REGULATOR", "VDDA18_L10_REGULATOR",
+		"VDDA18_L10_REGULATOR", "VDD_L1_REGULATOR",
 		"SpkrLeft IN", "SPK1 OUT",
 		"PDM_IN_RX1", "PDM_OUT_RX1",
 		"PDM_IN_RX2", "PDM_OUT_RX2",
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index bb07c04..5c40ecc 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -1875,7 +1875,7 @@
 		ufs-qcom-crypto = <&ufs_ice>;
 
 		lanes-per-direction = <1>;
-		spm-level = <5>;
+
 		dev-ref-clk-freq = <0>; /* 19.2 MHz */
 
 		clock-names =
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-qvr.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-qvr.dtsi
index 71566d0..6052074 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-qvr.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera-sensor-qvr.dtsi
@@ -493,6 +493,48 @@
 		clock-rates = <24000000>;
 	};
 
+	eeprom_depth: qcom,eeprom@4 {
+		cell-index = <4>;
+		reg = <0x4>;
+		compatible = "qcom,eeprom";
+		cam_vio-supply = <&pm8998_lvs1>; /* checked, MTP845 */
+		cam_vana-supply = <&pmi8998_bob>;
+		cam_vdig-supply = <&camera_eyetracking_force>;
+		cam_clk-supply = <&titan_top_gdsc>;
+		regulator-names = "cam_vio", "cam_vana", "cam_vdig", "cam_clk";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <0 3312000 1050000 0>;
+		rgltr-max-voltage = <0 3600000 1050000 0>;
+		rgltr-load-current = <0 80000 105000 0>;
+		gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_active
+				&cam_sensor_depth_active>;
+		pinctrl-1 = <&cam_sensor_mclk1_suspend
+				&cam_sensor_depth_suspend>;
+		gpios = <&tlmm 14 0>,
+			<&tlmm 28 0>,
+			<&tlmm 23 0>,
+			<&tlmm 24 0>;
+		gpio-reset = <1>;   //RESET
+		gpio-vana = <2>;
+		gpio-vdig = <3>;
+		gpio-req-tbl-num = <0 1 2 3> ;
+		gpio-req-tbl-flags = <1 0 0 0>;
+		gpio-req-tbl-label = "CAMIF_MCLK1",
+					"CAM_RESET1",
+					"CAM_VANA1",
+					"CAM_VDIG1";
+		sensor-position = <0>;
+		sensor-mode = <0>;
+		cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
+		clock-rates = <24000000>;
+	};
+
 	qcom,cam-sensor@4 {
 		cell-index = <4>;
 		compatible = "qcom,cam-sensor";
@@ -501,6 +543,7 @@
 		sensor-position-roll = <270>; /* checked, MTP845 */
 		sensor-position-pitch = <0>; /* checked, MTP845 */
 		sensor-position-yaw = <180>; /* checked, MTP845 */
+		eeprom-src = <&eeprom_depth>;
 		cam_vio-supply = <&pm8998_lvs1>; /* checked, MTP845 */
 		cam_vana-supply = <&pmi8998_bob>;
 		cam_vdig-supply = <&camera_eyetracking_force>;
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi
index 270aa0e..8e543ff 100644
--- a/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi
@@ -12,3 +12,20 @@
  */
 
 #include "qcs605-lc-mtp.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+&sde_dsi_active {
+	pins = "gpio93", "gpio121", "gpio76";
+};
+
+&sde_dsi_suspend {
+	pins = "gpio93", "gpio121", "gpio76";
+};
+
+&sde_te_active {
+	pins = "gpio10";
+};
+
+&sde_te_suspend {
+	pins = "gpio10";
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi b/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi
index 1413e2c..c5d393c 100644
--- a/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi
@@ -18,3 +18,33 @@
 	compatible = "qcom,sxr1120";
 	qcom,msm-id = <370 0x0>;
 };
+
+&soc {
+	qcom,qbt1000 {
+		/delete-property/ qcom,ipc-gpio;
+	};
+};
+
+&ext_dsi_bridge_display {
+	/delete-property/ qcom,dsi-display-active;
+};
+
+&mdss_mdp {
+	/delete-property/ bridges;
+	#cooling-cells = <2>;
+};
+
+&dsi_dual_nt35597_truly_video {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "dual_port";
+	qcom,panel-mode-gpio = <&tlmm 76 0>;
+	qcom,platform-reset-gpio = <&tlmm 93 0>;
+	qcom,platform-en-gpio = <&tlmm 121 0>;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+	qcom,dsi-display-active;
+};
diff --git a/arch/arm64/configs/msm8937-perf_defconfig b/arch/arm64/configs/msm8937-perf_defconfig
index 6420837..385714b 100644
--- a/arch/arm64/configs/msm8937-perf_defconfig
+++ b/arch/arm64/configs/msm8937-perf_defconfig
@@ -72,6 +72,7 @@
 CONFIG_SWP_EMULATION=y
 CONFIG_CP15_BARRIER_EMULATION=y
 CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
 # CONFIG_ARM64_VHE is not set
 CONFIG_RANDOMIZE_BASE=y
 CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
@@ -315,6 +316,7 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y
 CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26=y
+CONFIG_TOUCHSCREEN_FT5X06=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_HBTP_INPUT=y
 CONFIG_INPUT_QPNP_POWER_ON=y
diff --git a/arch/arm64/configs/msm8937_defconfig b/arch/arm64/configs/msm8937_defconfig
index 4040863..cbf89b2 100644
--- a/arch/arm64/configs/msm8937_defconfig
+++ b/arch/arm64/configs/msm8937_defconfig
@@ -75,6 +75,7 @@
 CONFIG_SWP_EMULATION=y
 CONFIG_CP15_BARRIER_EMULATION=y
 CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
 # CONFIG_ARM64_VHE is not set
 CONFIG_RANDOMIZE_BASE=y
 CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
@@ -321,6 +322,7 @@
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y
 CONFIG_SECURE_TOUCH_SYNAPTICS_DSX_V26=y
+CONFIG_TOUCHSCREEN_FT5X06=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_HBTP_INPUT=y
 CONFIG_INPUT_QPNP_POWER_ON=y
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index f3c1e7b..698857a 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -73,6 +73,7 @@
 CONFIG_SWP_EMULATION=y
 CONFIG_CP15_BARRIER_EMULATION=y
 CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
 # CONFIG_ARM64_VHE is not set
 CONFIG_RANDOMIZE_BASE=y
 CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index 8401173c..6434a8e 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -76,6 +76,7 @@
 CONFIG_SWP_EMULATION=y
 CONFIG_CP15_BARRIER_EMULATION=y
 CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
 # CONFIG_ARM64_VHE is not set
 CONFIG_RANDOMIZE_BASE=y
 CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 0c54182..358b37b 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -516,6 +516,8 @@
 CONFIG_QCOM_LLCC_PERFMON=m
 CONFIG_MSM_SERVICE_LOCATOR=y
 CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_SETUP_SSR_NOTIF_TIMEOUTS=y
+CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT=y
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_QCOM_EUD=y
 CONFIG_QCOM_WATCHDOG_V2=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index ab983e0..c9f60b5 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -528,6 +528,8 @@
 CONFIG_QCOM_LLCC_PERFMON=m
 CONFIG_MSM_SERVICE_LOCATOR=y
 CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_SETUP_SSR_NOTIF_TIMEOUTS=y
+CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT=y
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_MSM_CORE_HANG_DETECT=y
 CONFIG_MSM_GLADIATOR_HANG_DETECT=y
diff --git a/block/blk-core.c b/block/blk-core.c
index 404629f..ff2e4fd 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -1529,6 +1529,7 @@
 	bio->bi_next = req->bio;
 	req->bio = bio;
 
+	WARN_ON(req->__dun || bio->bi_iter.bi_dun);
 	req->__sector = bio->bi_iter.bi_sector;
 	req->__data_len += bio->bi_iter.bi_size;
 	req->ioprio = ioprio_best(req->ioprio, bio_prio(bio));
@@ -1644,6 +1645,7 @@
 
 	req->errors = 0;
 	req->__sector = bio->bi_iter.bi_sector;
+	req->__dun = bio->bi_iter.bi_dun;
 	req->ioprio = bio_prio(bio);
 	blk_rq_bio_prep(req->q, req, bio);
 }
@@ -2646,8 +2648,11 @@
 	req->__data_len -= total_bytes;
 
 	/* update sector only for requests with clear definition of sector */
-	if (req->cmd_type == REQ_TYPE_FS)
+	if (req->cmd_type == REQ_TYPE_FS) {
 		req->__sector += total_bytes >> 9;
+		if (req->__dun)
+			req->__dun += total_bytes >> 12;
+	}
 
 	/* mixed attributes always follow the first bio */
 	if (req->cmd_flags & REQ_MIXED_MERGE) {
@@ -3048,6 +3053,7 @@
 			 (src->cmd_flags & REQ_CLONE_MASK) | REQ_NOMERGE);
 	dst->cmd_type = src->cmd_type;
 	dst->__sector = blk_rq_pos(src);
+	dst->__dun = blk_rq_dun(src);
 	dst->__data_len = blk_rq_bytes(src);
 	dst->nr_phys_segments = src->nr_phys_segments;
 	dst->ioprio = src->ioprio;
diff --git a/block/blk-merge.c b/block/blk-merge.c
index f44daa1..c71d1cb 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -876,6 +876,8 @@
 
 int blk_try_merge(struct request *rq, struct bio *bio)
 {
+	if (blk_rq_dun(rq) || bio_dun(bio))
+		return ELEVATOR_NO_MERGE;
 	if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_iter.bi_sector)
 		return ELEVATOR_BACK_MERGE;
 	else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_iter.bi_sector)
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index b7e61c8..f60978be 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -61,7 +61,9 @@
 #define FASTRPC_ENOSUCH 39
 #define VMID_SSC_Q6     5
 #define VMID_ADSP_Q6    6
-#define DEBUGFS_SIZE 1024
+#define DEBUGFS_SIZE 3072
+#define UL_SIZE 25
+#define PID_SIZE 10
 
 #define AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME   "audio_pdr_adsprpc"
 #define AUDIO_PDR_ADSP_SERVICE_NAME              "avs/audio"
@@ -313,6 +315,7 @@
 	unsigned int latency;
 	bool glink;
 	bool legacy;
+	bool secure_flag;
 	spinlock_t ctxlock;
 	struct smq_invoke_ctx *ctxtable[FASTRPC_CTX_MAX];
 };
@@ -394,6 +397,7 @@
 	int refcount;
 	/* Identifies the device (MINOR_NUM_DEV / MINOR_NUM_SECURE_DEV) */
 	int dev_minor;
+	char *debug_buf;
 };
 
 static struct fastrpc_apps gfa;
@@ -2781,6 +2785,7 @@
 	spin_lock(&fl->apps->hlock);
 	hlist_del_init(&fl->hn);
 	spin_unlock(&fl->apps->hlock);
+	kfree(fl->debug_buf);
 
 	if (!fl->sctx) {
 		kfree(fl);
@@ -2966,101 +2971,225 @@
 static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
 					 size_t count, loff_t *position)
 {
+	struct fastrpc_apps *me = &gfa;
 	struct fastrpc_file *fl = filp->private_data;
 	struct hlist_node *n;
 	struct fastrpc_buf *buf = NULL;
 	struct fastrpc_mmap *map = NULL;
+	struct fastrpc_mmap *gmaps = NULL;
 	struct smq_invoke_ctx *ictx = NULL;
-	struct fastrpc_channel_ctx *chan;
-	struct fastrpc_session_ctx *sess;
+	struct fastrpc_channel_ctx *chan = NULL;
 	unsigned int len = 0;
-	int i, j, ret = 0;
+	int i, j, sess_used = 0, ret = 0;
 	char *fileinfo = NULL;
+	char single_line[UL_SIZE] = "----------------";
+	char title[UL_SIZE] = "=========================";
 
 	fileinfo = kzalloc(DEBUGFS_SIZE, GFP_KERNEL);
 	if (!fileinfo)
 		goto bail;
 	if (fl == NULL) {
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"\n%s %s %s\n", title, " CHANNEL INFO ", title);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%-8s|%-9s|%-9s|%-14s|%-9s|%-13s\n",
+			"susbsys", "refcount", "sesscount", "issubsystemup",
+			"ssrcount", "session_used");
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"-%s%s%s%s-\n", single_line, single_line,
+			single_line, single_line);
 		for (i = 0; i < NUM_CHANNELS; i++) {
+			sess_used = 0;
 			chan = &gcinfo[i];
 			len += scnprintf(fileinfo + len,
-					DEBUGFS_SIZE - len, "%s\n\n",
-					chan->name);
+				 DEBUGFS_SIZE - len, "%-8s", chan->subsys);
 			len += scnprintf(fileinfo + len,
-					DEBUGFS_SIZE - len, "%s %d\n",
-					"secure:", chan->secure);
+				 DEBUGFS_SIZE - len, "|%-9d",
+				 chan->kref.refcount.counter);
 			len += scnprintf(fileinfo + len,
-					DEBUGFS_SIZE - len, "%s %d\n",
-					"sesscount:", chan->sesscount);
+				 DEBUGFS_SIZE - len, "|%-9d",
+				 chan->sesscount);
+			len += scnprintf(fileinfo + len,
+				 DEBUGFS_SIZE - len, "|%-14d",
+				 chan->issubsystemup);
+			len += scnprintf(fileinfo + len,
+				 DEBUGFS_SIZE - len, "|%-9d",
+				 chan->ssrcount);
 			for (j = 0; j < chan->sesscount; j++) {
-				sess = &chan->session[j];
-				len += scnprintf(fileinfo + len,
-						DEBUGFS_SIZE - len,
-						"%s%d\n\n", "SESSION", j);
-				len += scnprintf(fileinfo + len,
-						DEBUGFS_SIZE - len,
-						"%s %d\n", "sid:",
-						sess->smmu.cb);
-				len += scnprintf(fileinfo + len,
-						DEBUGFS_SIZE - len,
-						"%s %d\n", "SECURE:",
-						sess->smmu.secure);
-			}
+				sess_used += chan->session[j].used;
+				}
+			len += scnprintf(fileinfo + len,
+			DEBUGFS_SIZE - len, "|%-13d\n", sess_used);
+
+		}
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"\n%s%s%s\n", "=============",
+			" CMA HEAP ", "==============");
+		len += scnprintf(fileinfo + len,
+			DEBUGFS_SIZE - len, "%-20s|%-20s\n", "addr", "size");
+		len += scnprintf(fileinfo + len,
+			DEBUGFS_SIZE - len, "--%s%s---\n",
+			single_line, single_line);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			 "0x%-18llX", me->range.addr);
+		len += scnprintf(fileinfo + len,
+			DEBUGFS_SIZE - len, "|0x%-18llX\n", me->range.size);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"\n==========%s %s %s===========\n",
+			title, " GMAPS ", title);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%-20s|%-20s|%-20s|%-20s\n",
+			"fd", "phys", "size", "va");
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s%s%s%s%s\n", single_line, single_line,
+			single_line, single_line, single_line);
+		hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) {
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%-20d|0x%-18llX|0x%-18X|0x%-20lX\n\n",
+			gmaps->fd, gmaps->phys,
+			(uint32_t)gmaps->size,
+			gmaps->va);
+		}
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%-20s|%-20s|%-20s|%-20s\n",
+			"len", "refs", "raddr", "flags");
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s%s%s%s%s\n", single_line, single_line,
+			single_line, single_line, single_line);
+		hlist_for_each_entry_safe(gmaps, n, &me->maps, hn) {
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"0x%-18X|%-20d|%-20lu|%-20u\n",
+			(uint32_t)gmaps->len, gmaps->refs,
+			gmaps->raddr, gmaps->flags);
 		}
 	} else {
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-				"%s %d\n\n",
-				"PROCESS_ID:", fl->tgid);
+			 "\n%s %13s %d\n", "cid", ":", fl->cid);
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-				"%s %d\n\n",
-				"CHANNEL_ID:", fl->cid);
+			"%s %12s %d\n", "tgid", ":", fl->tgid);
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-				"%s %d\n\n",
-				"SSRCOUNT:", fl->ssrcount);
+			"%s %7s %d\n", "sessionid", ":", fl->sessionid);
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-				"%s %d\n\n",
-				"DEV_MINOR:", fl->dev_minor);
+			"%s %8s %d\n", "ssrcount", ":", fl->ssrcount);
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-				"%s\n",
-				"LIST OF BUFS:");
-		spin_lock(&fl->hlock);
-		hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) {
-			len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-					"%s %pK %s %pK %s %llx\n", "buf:",
-					buf, "buf->virt:", buf->virt,
-					"buf->phys:", buf->phys);
-		}
+			"%s %8s %d\n", "refcount", ":", fl->refcount);
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-					"\n%s\n",
-					"LIST OF MAPS:");
+			"%s %14s %d\n", "pd", ":", fl->pd);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s %9s %s\n", "spdname", ":", fl->spdname);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s %6s %d\n", "file_close", ":", fl->file_close);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s %8s %d\n", "sharedcb", ":", fl->sharedcb);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s %9s %d\n", "profile", ":", fl->profile);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s %3s %d\n", "smmu.coherent", ":",
+			fl->sctx->smmu.coherent);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s %4s %d\n", "smmu.enabled", ":",
+			fl->sctx->smmu.enabled);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s %9s %d\n", "smmu.cb", ":", fl->sctx->smmu.cb);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s %5s %d\n", "smmu.secure", ":",
+			fl->sctx->smmu.secure);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s %5s %d\n", "smmu.faults", ":",
+			fl->sctx->smmu.faults);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s %s %d\n", "link.link_state",
+		 ":", *&me->channel[fl->cid].link.link_state);
+
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"\n=======%s %s %s======\n", title,
+			" LIST OF MAPS ", title);
+
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%-20s|%-20s|%-20s\n", "va", "phys", "size");
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s%s%s%s%s\n",
+			single_line, single_line, single_line,
+			single_line, single_line);
 		hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
-			len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-						"%s %pK %s %lx %s %llx\n",
-						"map:", map,
-						"map->va:", map->va,
-						"map->phys:", map->phys);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"0x%-20lX|0x%-20llX|0x%-20zu\n\n",
+			map->va, map->phys,
+			map->size);
 		}
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-					"\n%s\n",
-					"LIST OF PENDING SMQCONTEXTS:");
+			"%-20s|%-20s|%-20s|%-20s\n",
+			"len", "refs",
+			"raddr", "uncached");
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s%s%s%s%s\n",
+			single_line, single_line, single_line,
+			single_line, single_line);
+		hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%-20zu|%-20d|0x%-20lX|%-20d\n\n",
+			map->len, map->refs, map->raddr,
+			map->uncached);
+		}
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%-20s|%-20s\n", "secure", "attr");
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s%s%s%s%s\n",
+			single_line, single_line, single_line,
+			single_line, single_line);
+		hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%-20d|0x%-20lX\n\n",
+			map->secure, map->attr);
+		}
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"\n======%s %s %s======\n", title,
+			" LIST OF BUFS ", title);
+		spin_lock(&fl->hlock);
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%-19s|%-19s|%-19s\n",
+			"virt", "phys", "size");
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s%s%s%s%s\n", single_line, single_line,
+			single_line, single_line, single_line);
+		hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) {
+			len += scnprintf(fileinfo + len,
+			DEBUGFS_SIZE - len,
+			"0x%-17p|0x%-17llX|%-19zu\n",
+			buf->virt, (uint64_t)buf->phys, buf->size);
+		}
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"\n%s %s %s\n", title,
+			" LIST OF PENDING SMQCONTEXTS ", title);
+
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%-20s|%-10s|%-10s|%-10s|%-20s\n",
+			"sc", "pid", "tgid", "used", "ctxid");
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s%s%s%s%s\n", single_line, single_line,
+			single_line, single_line, single_line);
 		hlist_for_each_entry_safe(ictx, n, &fl->clst.pending, hn) {
 			len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-						"%s %pK %s %u %s %u %s %u\n",
-						"smqcontext:", ictx,
-						"sc:", ictx->sc,
-						"tid:", ictx->pid,
-						"handle", ictx->rpra->h);
+				"0x%-18X|%-10d|%-10d|%-10zu|0x%-20llX\n\n",
+				ictx->sc, ictx->pid, ictx->tgid,
+				ictx->used, ictx->ctxid);
 		}
+
 		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-					"\n%s\n",
-					"LIST OF INTERRUPTED SMQCONTEXTS:");
+			"\n%s %s %s\n", title,
+			" LIST OF INTERRUPTED SMQCONTEXTS ", title);
+
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%-20s|%-10s|%-10s|%-10s|%-20s\n",
+			"sc", "pid", "tgid", "used", "ctxid");
+		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%s%s%s%s%s\n", single_line, single_line,
+			single_line, single_line, single_line);
 		hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) {
-		len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
-					"%s %pK %s %u %s %u %s %u\n",
-					"smqcontext:", ictx,
-					"sc:", ictx->sc,
-					"tid:", ictx->pid,
-					"handle", ictx->rpra->h);
+			len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
+			"%-20u|%-20d|%-20d|%-20zu|0x%-20llX\n\n",
+			ictx->sc, ictx->pid, ictx->tgid,
+			ictx->used, ictx->ctxid);
 		}
 		spin_unlock(&fl->hlock);
 	}
@@ -3155,6 +3284,8 @@
 	struct dentry *debugfs_file;
 	struct fastrpc_file *fl = NULL;
 	struct fastrpc_apps *me = &gfa;
+	char strpid[PID_SIZE];
+	int buf_size = 0;
 
 	/*
 	 * Indicates the device node opened
@@ -3172,8 +3303,14 @@
 	VERIFY(err, NULL != (fl = kzalloc(sizeof(*fl), GFP_KERNEL)));
 	if (err)
 		return err;
-	debugfs_file = debugfs_create_file(current->comm, 0644, debugfs_root,
-						fl, &debugfs_fops);
+	snprintf(strpid, PID_SIZE, "%d", current->pid);
+	buf_size = strlen(current->comm) + strlen(strpid) + 1;
+	fl->debug_buf = kzalloc(buf_size, GFP_KERNEL);
+	snprintf(fl->debug_buf, UL_SIZE, "%.10s%s%d",
+	current->comm, "_", current->pid);
+	debugfs_file = debugfs_create_file(fl->debug_buf, 0644,
+	debugfs_root, fl, &debugfs_fops);
+
 	context_list_ctor(&fl->clst);
 	spin_lock_init(&fl->hlock);
 	INIT_HLIST_HEAD(&fl->maps);
@@ -3215,7 +3352,8 @@
 		if (err)
 			goto bail;
 		/* Check to see if the device node is non-secure */
-		if (fl->dev_minor == MINOR_NUM_DEV) {
+		if (fl->dev_minor == MINOR_NUM_DEV &&
+			fl->apps->secure_flag == true) {
 			/*
 			 * For non secure device node check and make sure that
 			 * the channel allows non-secure access
@@ -3863,10 +4001,13 @@
 			VERIFY(err, !of_property_read_u32(dev->of_node,
 					  "qcom,secure-domains",
 			      &secure_domains));
-			if (!err)
+			if (!err) {
+				me->secure_flag = true;
 				configure_secure_channels(secure_domains);
-			else
+			} else {
+				me->secure_flag = false;
 				pr_info("adsprpc: unable to read the domain configuration from dts\n");
+			}
 		}
 	}
 	if (of_device_is_compatible(dev->of_node,
@@ -4016,11 +4157,12 @@
 	struct device *secure_dev = NULL;
 	int err = 0, i;
 
+	debugfs_root = debugfs_create_dir("adsprpc", NULL);
 	memset(me, 0, sizeof(*me));
-
 	fastrpc_init(me);
 	me->dev = NULL;
 	me->glink = true;
+	me->secure_flag = false;
 	VERIFY(err, 0 == platform_driver_register(&fastrpc_driver));
 	if (err)
 		goto register_bail;
@@ -4073,12 +4215,11 @@
 							gcinfo[i].subsys,
 							&me->channel[i].nb);
 	}
-
 	me->client = msm_ion_client_create(DEVICE_NAME);
 	VERIFY(err, !IS_ERR_OR_NULL(me->client));
 	if (err)
 		goto device_create_bail;
-	debugfs_root = debugfs_create_dir("adsprpc", NULL);
+
 	return 0;
 device_create_bail:
 	for (i = 0; i < NUM_CHANNELS; i++) {
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index e692f660..3c75997 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -83,7 +83,7 @@
 };
 
 static struct system_pm_ops *sys_pm_ops;
-
+static DEFINE_SPINLOCK(bc_timer_lock);
 
 struct lpm_cluster *lpm_root_node;
 
@@ -1029,6 +1029,7 @@
 	struct lpm_cluster_level *level = &cluster->levels[idx];
 	struct cpumask online_cpus, cpumask;
 	unsigned int cpu;
+	int ret = 0;
 
 	cpumask_and(&online_cpus, &cluster->num_children_in_sync,
 					cpu_online_mask);
@@ -1067,9 +1068,13 @@
 
 		clear_predict_history();
 		clear_cl_predict_history();
-		if (sys_pm_ops && sys_pm_ops->enter)
-			if ((sys_pm_ops->enter(&cpumask)))
+		if (sys_pm_ops && sys_pm_ops->enter) {
+			spin_lock(&bc_timer_lock);
+			ret = sys_pm_ops->enter(&cpumask);
+			spin_unlock(&bc_timer_lock);
+			if (ret)
 				return -EBUSY;
+		}
 	}
 	/* Notify cluster enter event after successfully config completion */
 	cluster_notify(cluster, level, true);
@@ -1202,8 +1207,11 @@
 	level = &cluster->levels[cluster->last_level];
 
 	if (level->notify_rpm)
-		if (sys_pm_ops && sys_pm_ops->exit)
+		if (sys_pm_ops && sys_pm_ops->exit) {
+			spin_lock(&bc_timer_lock);
 			sys_pm_ops->exit();
+			spin_unlock(&bc_timer_lock);
+		}
 
 	update_debug_pc_event(CLUSTER_EXIT, cluster->last_level,
 			cluster->num_children_in_sync.bits[0],
@@ -1298,6 +1306,7 @@
 {
 	int affinity_level = 0, state_id = 0, power_state = 0;
 	bool success = false;
+	int ret = 0;
 	/*
 	 * idx = 0 is the default LPM state
 	 */
@@ -1310,7 +1319,17 @@
 	}
 
 	if (from_idle && cpu->levels[idx].use_bc_timer) {
-		if (tick_broadcast_enter())
+		/*
+		 * tick_broadcast_enter can change the affinity of the
+		 * broadcast timer interrupt, during which interrupt will
+		 * be disabled and enabled back. To avoid system pm ops
+		 * doing any interrupt state save or restore in between
+		 * this window hold the lock.
+		 */
+		spin_lock(&bc_timer_lock);
+		ret = tick_broadcast_enter();
+		spin_unlock(&bc_timer_lock);
+		if (ret)
 			return success;
 	}
 
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index c5a1a9f..9e251da 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -1161,7 +1161,7 @@
 		goto error;
 	}
 
-	if (copy_to_user(user_buf, buf, len)) {
+	if (copy_to_user(user_buf, buf, max_len)) {
 		rc = -EFAULT;
 		goto error;
 	}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index bf511e3..85b92f59 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -1559,14 +1559,14 @@
 	return rc;
 error_free_payloads:
 	for (i = i - 1; i >= 0; i--) {
-		cmd--;
-		kfree(cmd->msg.tx_buf);
+		kfree(cmd[i].msg.tx_buf);
+		cmd[i].msg.tx_buf = NULL;
 	}
 
 	return rc;
 }
 
-static void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set)
+static void dsi_panel_destroy_cmds_packets_buf(struct dsi_panel_cmd_set *set)
 {
 	u32 i = 0;
 	struct dsi_cmd_desc *cmd;
@@ -1574,12 +1574,15 @@
 	for (i = 0; i < set->count; i++) {
 		cmd = &set->cmds[i];
 		kfree(cmd->msg.tx_buf);
+		cmd->msg.tx_buf = NULL;
 	}
 }
 
-static void dsi_panel_dealloc_cmd_packets(struct dsi_panel_cmd_set *set)
+static void dsi_panel_destroy_cmd_packets(struct dsi_panel_cmd_set *set)
 {
+	dsi_panel_destroy_cmds_packets_buf(set);
 	kfree(set->cmds);
+	set->count = 0;
 }
 
 static int dsi_panel_alloc_cmd_packets(struct dsi_panel_cmd_set *cmd,
@@ -3163,12 +3166,13 @@
 	if (!mode->priv_info)
 		return;
 
-	for (i = 0; i < DSI_CMD_SET_MAX; i++) {
+	kfree(mode->priv_info->phy_timing_val);
+
+	for (i = 0; i < DSI_CMD_SET_MAX; i++)
 		dsi_panel_destroy_cmd_packets(&mode->priv_info->cmd_sets[i]);
-		dsi_panel_dealloc_cmd_packets(&mode->priv_info->cmd_sets[i]);
-	}
 
 	kfree(mode->priv_info);
+	mode->priv_info = NULL;
 }
 
 int dsi_panel_get_mode(struct dsi_panel *panel,
@@ -3370,7 +3374,7 @@
 			panel->name, rc);
 	}
 
-	dsi_panel_destroy_cmd_packets(set);
+	dsi_panel_destroy_cmds_packets_buf(set);
 error:
 	mutex_unlock(&panel->panel_lock);
 	return rc;
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index ddd4607..00f9707 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -80,6 +80,9 @@
 {
 	struct msm_gem_object *msm_obj = to_msm_bo(obj);
 
+	if (obj->import_attach)
+		return msm_obj->pages;
+
 	if (!msm_obj->pages) {
 		struct drm_device *dev = obj->dev;
 		struct page **p;
@@ -572,8 +575,13 @@
 		struct page **pages = get_pages(obj);
 		if (IS_ERR(pages))
 			return ERR_CAST(pages);
-		msm_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT,
+		if (obj->import_attach)
+			msm_obj->vaddr = dma_buf_vmap(
+				      obj->import_attach->dmabuf);
+		else
+			msm_obj->vaddr = vmap(pages, obj->size >> PAGE_SHIFT,
 				VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+
 		if (msm_obj->vaddr == NULL)
 			return ERR_PTR(-ENOMEM);
 	}
@@ -659,7 +667,11 @@
 	if (!msm_obj->vaddr || WARN_ON(!is_vunmapable(msm_obj)))
 		return;
 
-	vunmap(msm_obj->vaddr);
+	if (obj->import_attach)
+		dma_buf_vunmap(obj->import_attach->dmabuf, msm_obj->vaddr);
+	else
+		vunmap(msm_obj->vaddr);
+
 	msm_obj->vaddr = NULL;
 }
 
@@ -1012,7 +1024,7 @@
 	struct msm_gem_object *msm_obj;
 	struct drm_gem_object *obj = NULL;
 	uint32_t size;
-	int ret, npages;
+	int ret;
 
 	/* if we don't have IOMMU, don't bother pretending we can import: */
 	if (!iommu_present(&platform_bus_type)) {
@@ -1033,19 +1045,9 @@
 
 	drm_gem_private_object_init(dev, obj, size);
 
-	npages = size / PAGE_SIZE;
-
 	msm_obj = to_msm_bo(obj);
 	msm_obj->sgt = sgt;
-	msm_obj->pages = drm_malloc_ab(npages, sizeof(struct page *));
-	if (!msm_obj->pages) {
-		ret = -ENOMEM;
-		goto fail;
-	}
-
-	ret = drm_prime_sg_to_page_addr_arrays(sgt, msm_obj->pages, NULL, npages);
-	if (ret)
-		goto fail;
+	msm_obj->pages = NULL;
 
 	return obj;
 
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 763993c8..e7b7a6e 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -259,6 +259,7 @@
 	struct kthread_work input_event_work;
 	struct kthread_work esd_trigger_work;
 	struct input_handler *input_handler;
+	bool input_handler_registered;
 	struct msm_display_topology topology;
 	bool vblank_enabled;
 
@@ -743,6 +744,7 @@
 	if (sde_enc->input_handler) {
 		kfree(sde_enc->input_handler);
 		sde_enc->input_handler = NULL;
+		sde_enc->input_handler_registered = false;
 	}
 
 	kfree(sde_enc);
@@ -2634,6 +2636,7 @@
 	input_handler->private = sde_enc;
 
 	sde_enc->input_handler = input_handler;
+	sde_enc->input_handler_registered = false;
 
 	return rc;
 }
@@ -2755,12 +2758,14 @@
 		return;
 	}
 
-	if (sde_enc->input_handler) {
+	if (sde_enc->input_handler && !sde_enc->input_handler_registered) {
 		ret = _sde_encoder_input_handler_register(
 				sde_enc->input_handler);
 		if (ret)
 			SDE_ERROR(
 			"input handler registration failed, rc = %d\n", ret);
+		else
+			sde_enc->input_handler_registered = true;
 	}
 
 	ret = sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF);
@@ -2838,8 +2843,11 @@
 
 	SDE_EVT32(DRMID(drm_enc));
 
-	if (sde_enc->input_handler)
+	if (sde_enc->input_handler && sde_enc->input_handler_registered) {
 		input_unregister_handler(sde_enc->input_handler);
+		sde_enc->input_handler_registered = false;
+	}
+
 
 	/* wait for idle */
 	sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 572dc40..d3bbea3 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -541,7 +541,7 @@
 	 */
 	spin_lock(&proc_priv->ctxt_count_lock);
 	if (atomic_read(&proc_priv->ctxt_count) > KGSL_MAX_CONTEXTS_PER_PROC) {
-		KGSL_DRV_ERR(device,
+		KGSL_DRV_ERR_RATELIMIT(device,
 			"Per process context limit reached for pid %u",
 			dev_priv->process_priv->pid);
 		spin_unlock(&proc_priv->ctxt_count_lock);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index f8a987a..ee32e1a 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -184,6 +184,15 @@
 	  reporting the change in status of the KPDPWR_N line (connected to the
 	  power-key) as well as reset features.
 
+config INPUT_QTI_HAPTICS
+	tristate "Haptics support for QTI PMIC"
+	depends on MFD_SPMI_PMIC
+	help
+	  This option enables device driver support for the haptics peripheral
+	  found on Qualcomm Technologies, Inc. PMICs.  The haptics peripheral
+	  is capable of driving both LRA and ERM vibrators.  This module provides
+	  haptic feedback for user actions such as a long press on the touch screen.
+
 config INPUT_SPARCSPKR
 	tristate "SPARC Speaker support"
 	depends on PCI && SPARC64
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 149273c..c08ee8f 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -61,6 +61,7 @@
 obj-$(CONFIG_INPUT_PM8XXX_VIBRATOR)	+= pm8xxx-vibrator.o
 obj-$(CONFIG_INPUT_PMIC8XXX_PWRKEY)	+= pmic8xxx-pwrkey.o
 obj-$(CONFIG_INPUT_QPNP_POWER_ON)	+= qpnp-power-on.o
+obj-$(CONFIG_INPUT_QTI_HAPTICS)		+= qti-haptics.o
 obj-$(CONFIG_INPUT_POWERMATE)		+= powermate.o
 obj-$(CONFIG_INPUT_PWM_BEEPER)		+= pwm-beeper.o
 obj-$(CONFIG_INPUT_RB532_BUTTON)	+= rb532_button.o
diff --git a/drivers/input/misc/qti-haptics.c b/drivers/input/misc/qti-haptics.c
new file mode 100644
index 0000000..310eb41
--- /dev/null
+++ b/drivers/input/misc/qti-haptics.c
@@ -0,0 +1,1471 @@
+/* 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 <linux/device.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/uaccess.h>
+#include <linux/types.h>
+
+enum actutor_type {
+	ACT_LRA,
+	ACT_ERM,
+};
+
+enum lra_res_sig_shape {
+	RES_SIG_SINE,
+	RES_SIG_SQUARE,
+};
+
+enum lra_auto_res_mode {
+	AUTO_RES_MODE_ZXD,
+	AUTO_RES_MODE_QWD,
+};
+
+enum wf_src {
+	INT_WF_VMAX,
+	INT_WF_BUFFER,
+	EXT_WF_AUDIO,
+	EXT_WF_PWM,
+};
+
+enum haptics_custom_effect_param {
+	CUSTOM_DATA_EFFECT_IDX,
+	CUSTOM_DATA_TIMEOUT_SEC_IDX,
+	CUSTOM_DATA_TIMEOUT_MSEC_IDX,
+	CUSTOM_DATA_LEN,
+};
+
+/* common definitions */
+#define HAP_BRAKE_PATTERN_MAX		4
+#define HAP_WAVEFORM_BUFFER_MAX		8
+#define HAP_VMAX_MV_DEFAULT		1800
+#define HAP_VMAX_MV_MAX			3596
+#define HAP_ILIM_MA_DEFAULT		400
+#define HAP_ILIM_MA_MAX			800
+#define HAP_PLAY_RATE_US_DEFAULT	5715
+#define HAP_PLAY_RATE_US_MAX		20475
+#define HAP_PLAY_RATE_US_LSB		5
+#define VMAX_MIN_PLAY_TIME_US		20000
+#define HAP_SC_DET_MAX_COUNT		5
+#define HAP_SC_DET_TIME_US		1000000
+#define FF_EFFECT_COUNT_MAX		32
+
+/* haptics module register definitions */
+#define REG_HAP_STATUS1			0x0A
+#define HAP_SC_DET_BIT			BIT(3)
+#define HAP_BUSY_BIT			BIT(1)
+
+#define REG_HAP_EN_CTL1			0x46
+#define HAP_EN_BIT			BIT(7)
+
+#define REG_HAP_EN_CTL2			0x48
+#define HAP_AUTO_STANDBY_EN_BIT		BIT(1)
+#define HAP_BRAKE_EN_BIT		BIT(0)
+
+#define REG_HAP_EN_CTL3			0x4A
+#define HAP_HBRIDGE_EN_BIT		BIT(7)
+#define HAP_PWM_SIGNAL_EN_BIT		BIT(6)
+#define HAP_ILIM_EN_BIT			BIT(5)
+#define HAP_ILIM_CC_EN_BIT		BIT(4)
+#define HAP_AUTO_RES_RBIAS_EN_BIT	BIT(3)
+#define HAP_DAC_EN_BIT			BIT(2)
+#define HAP_ZX_HYST_EN_BIT		BIT(1)
+#define HAP_PWM_CTL_EN_BIT		BIT(0)
+
+#define REG_HAP_AUTO_RES_CTRL		0x4B
+#define HAP_AUTO_RES_EN_BIT		BIT(7)
+#define HAP_SEL_AUTO_RES_PERIOD		BIT(6)
+#define HAP_AUTO_RES_CNT_ERR_DELTA_MASK	GENMASK(5, 4)
+#define HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT	4
+#define HAP_AUTO_RES_ERR_RECOVERY_BIT	BIT(3)
+#define HAP_AUTO_RES_EN_DLY_MASK	GENMASK(2, 0)
+#define AUTO_RES_CNT_ERR_DELTA(x)	(x << HAP_AUTO_RES_CNT_ERR_DELTA_SHIFT)
+#define AUTO_RES_EN_DLY(x)		x
+
+#define REG_HAP_CFG1			0x4C
+#define REG_HAP_CFG2			0x4D
+#define HAP_LRA_RES_TYPE_BIT		BIT(0)
+
+#define REG_HAP_SEL			0x4E
+#define HAP_WF_SOURCE_MASK		GENMASK(5, 4)
+#define HAP_WF_SOURCE_SHIFT		4
+#define HAP_WF_TRIGGER_BIT		BIT(0)
+#define HAP_WF_SOURCE_VMAX		(0 << HAP_WF_SOURCE_SHIFT)
+#define HAP_WF_SOURCE_BUFFER		(1 << HAP_WF_SOURCE_SHIFT)
+#define HAP_WF_SOURCE_AUDIO		(2 << HAP_WF_SOURCE_SHIFT)
+#define HAP_WF_SOURCE_PWM		(3 << HAP_WF_SOURCE_SHIFT)
+
+#define REG_HAP_AUTO_RES_CFG		0x4F
+#define HAP_AUTO_RES_MODE_BIT		BIT(7)
+#define HAP_AUTO_RES_MODE_SHIFT		7
+#define HAP_AUTO_RES_CAL_DURATON_MASK	GENMASK(6, 5)
+#define HAP_CAL_EOP_EN_BIT		BIT(3)
+#define HAP_CAL_PERIOD_MASK		GENMASK(2, 0)
+#define HAP_CAL_OPT3_EVERY_8_PERIOD	2
+
+#define REG_HAP_SLEW_CFG		0x50
+#define REG_HAP_VMAX_CFG		0x51
+#define HAP_VMAX_SIGN_BIT		BIT(7)
+#define HAP_VMAX_OVD_BIT		BIT(6)
+#define HAP_VMAX_MV_MASK		GENMASK(5, 1)
+#define HAP_VMAX_MV_SHIFT		1
+#define HAP_VMAX_MV_LSB			116
+
+#define REG_HAP_ILIM_CFG		0x52
+#define REG_HAP_SC_DEB_CFG		0x53
+#define REG_HAP_RATE_CFG1		0x54
+#define REG_HAP_RATE_CFG2		0x55
+#define REG_HAP_INTERNAL_PWM		0x56
+#define REG_HAP_EXTERNAL_PWM		0x57
+#define REG_HAP_PWM			0x58
+
+#define REG_HAP_SC_CLR			0x59
+#define HAP_SC_CLR_BIT			BIT(0)
+
+#define REG_HAP_ZX_CFG			0x5A
+#define HAP_ZX_DET_DEB_MASK		GENMASK(2, 0)
+#define ZX_DET_DEB_10US			0
+#define ZX_DET_DEB_20US			1
+#define ZX_DET_DEB_40US			2
+#define ZX_DET_DEB_80US			3
+
+#define REG_HAP_BRAKE			0x5C
+#define HAP_BRAKE_PATTERN_MASK		0x3
+#define HAP_BRAKE_PATTERN_SHIFT		2
+
+#define REG_HAP_WF_REPEAT		0x5E
+#define HAP_WF_REPEAT_MASK		GENMASK(6, 4)
+#define HAP_WF_REPEAT_SHIFT		4
+#define HAP_WF_S_REPEAT_MASK		GENMASK(1, 0)
+
+#define REG_HAP_WF_S1			0x60
+#define HAP_WF_SIGN_BIT			BIT(7)
+#define HAP_WF_OVD_BIT			BIT(6)
+#define HAP_WF_AMP_BIT			GENMASK(5, 1)
+#define HAP_WF_AMP_SHIFT		1
+
+#define REG_HAP_PLAY			0x70
+#define HAP_PLAY_BIT			BIT(7)
+
+#define REG_HAP_SEC_ACCESS		0xD0
+
+struct qti_hap_effect {
+	int			id;
+	u8			*pattern;
+	int			pattern_length;
+	u16			play_rate_us;
+	u8			wf_repeat_n;
+	u8			wf_s_repeat_n;
+	u8			brake[HAP_BRAKE_PATTERN_MAX];
+	int			brake_pattern_length;
+	bool			brake_en;
+	bool			lra_auto_res_disable;
+};
+
+struct qti_hap_play_info {
+	struct qti_hap_effect	*effect;
+	u16			vmax_mv;
+	int			length_us;
+	int			playing_pos;
+	bool			playing_pattern;
+};
+
+struct qti_hap_config {
+	enum actutor_type	act_type;
+	enum lra_res_sig_shape	lra_shape;
+	enum lra_auto_res_mode	lra_auto_res_mode;
+	enum wf_src		ext_src;
+	u16			vmax_mv;
+	u16			ilim_ma;
+	u16			play_rate_us;
+	bool			lra_allow_variable_play_rate;
+	bool			use_ext_wf_src;
+};
+
+struct qti_hap_chip {
+	struct platform_device		*pdev;
+	struct device			*dev;
+	struct regmap			*regmap;
+	struct input_dev		*input_dev;
+	struct pwm_device		*pwm_dev;
+	struct qti_hap_config		config;
+	struct qti_hap_play_info	play;
+	struct qti_hap_effect		*predefined;
+	struct qti_hap_effect		constant;
+	struct regulator		*vdd_supply;
+	struct hrtimer			stop_timer;
+	spinlock_t			bus_lock;
+	ktime_t				last_sc_time;
+	int				play_irq;
+	int				sc_irq;
+	int				effects_count;
+	int				sc_det_count;
+	u16				reg_base;
+	bool				perm_disable;
+	bool				play_irq_en;
+	bool				vdd_enabled;
+};
+
+static int wf_repeat[8] = {1, 2, 4, 8, 16, 32, 64, 128};
+static int wf_s_repeat[4] = {1, 2, 4, 8};
+
+static inline bool is_secure(u8 addr)
+{
+	return ((addr & 0xFF) > 0xD0);
+}
+
+static int qti_haptics_read(struct qti_hap_chip *chip,
+			u8 addr, u8 *val, int len)
+{
+	int rc = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chip->bus_lock, flags);
+
+	rc = regmap_bulk_read(chip->regmap, chip->reg_base + addr, val, len);
+	if (rc < 0)
+		dev_err(chip->dev, "Reading addr 0x%x failed, rc=%d\n",
+				addr, rc);
+	spin_unlock_irqrestore(&chip->bus_lock, flags);
+
+	return rc;
+}
+
+static int qti_haptics_write(struct qti_hap_chip *chip,
+		u8 addr, u8 *val, int len)
+{
+	int rc = 0, i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chip->bus_lock, flags);
+	if (is_secure(addr)) {
+		for (i = 0; i < len; i++) {
+			rc = regmap_write(chip->regmap,
+					chip->reg_base + REG_HAP_SEC_ACCESS,
+					0xA5);
+			if (rc < 0) {
+				dev_err(chip->dev, "write SEC_ACCESS failed, rc=%d\n",
+						rc);
+				goto unlock;
+			}
+
+			rc = regmap_write(chip->regmap,
+					chip->reg_base + addr + i, val[i]);
+			if (rc < 0) {
+				dev_err(chip->dev, "write val 0x%x to addr 0x%x failed, rc=%d\n",
+						val[i], addr + i, rc);
+				goto unlock;
+			}
+		}
+	} else {
+		if (len > 1)
+			rc = regmap_bulk_write(chip->regmap,
+					chip->reg_base + addr, val, len);
+		else
+			rc = regmap_write(chip->regmap,
+					chip->reg_base + addr, *val);
+
+			if (rc < 0)
+				dev_err(chip->dev, "write addr 0x%x failed, rc=%d\n",
+						addr, rc);
+	}
+
+	for (i = 0; i < len; i++)
+		dev_dbg(chip->dev, "Update addr 0x%x to val 0x%x\n",
+				addr + i, val[i]);
+
+unlock:
+	spin_unlock_irqrestore(&chip->bus_lock, flags);
+	return rc;
+}
+
+static int qti_haptics_masked_write(struct qti_hap_chip *chip, u8 addr,
+		u8 mask, u8 val)
+{
+	int rc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&chip->bus_lock, flags);
+	if (is_secure(addr)) {
+		rc = regmap_write(chip->regmap,
+				chip->reg_base + REG_HAP_SEC_ACCESS,
+				0xA5);
+		if (rc < 0) {
+			dev_err(chip->dev, "write SEC_ACCESS failed, rc=%d\n",
+					rc);
+			goto unlock;
+		}
+	}
+
+	rc = regmap_update_bits(chip->regmap, chip->reg_base + addr, mask, val);
+	if (rc < 0)
+		dev_err(chip->dev, "Update addr 0x%x to val 0x%x with mask 0x%x failed, rc=%d\n",
+				addr, val, mask, rc);
+
+	dev_dbg(chip->dev, "Update addr 0x%x to val 0x%x with mask 0x%x\n",
+			addr, val, mask);
+unlock:
+	spin_unlock_irqrestore(&chip->bus_lock, flags);
+
+	return rc;
+}
+
+static void construct_constant_waveform_in_pattern(
+		struct qti_hap_play_info *play)
+{
+	struct qti_hap_chip *chip = container_of(play,
+			struct qti_hap_chip, play);
+	struct qti_hap_config *config = &chip->config;
+	struct qti_hap_effect *effect = play->effect;
+	int total_samples, samples, left, magnitude, i, j, k;
+	int delta = INT_MAX, delta_min = INT_MAX;
+
+	/* Using play_rate_us in config for constant waveform */
+	effect->play_rate_us = config->play_rate_us;
+	total_samples = play->length_us / effect->play_rate_us;
+	left = play->length_us % effect->play_rate_us;
+
+	if (total_samples <= HAP_WAVEFORM_BUFFER_MAX) {
+		effect->pattern_length = total_samples;
+		effect->wf_s_repeat_n = 0;
+		effect->wf_repeat_n = 0;
+	} else {
+		/*
+		 * Find a closest setting to achieve the constant waveform
+		 * with the required length by using buffer waveform source:
+		 * play_length_us = pattern_length * wf_s_repeat_n
+		 *		* wf_repeat_n * play_rate_us
+		 */
+		for (i = 0; i < ARRAY_SIZE(wf_repeat); i++) {
+			for (j = 0; j < ARRAY_SIZE(wf_s_repeat); j++) {
+				for (k = 1; k <= HAP_WAVEFORM_BUFFER_MAX; k++) {
+					samples = k * wf_s_repeat[j] *
+						wf_repeat[i];
+					delta = abs(total_samples - samples);
+					if (delta < delta_min) {
+						delta_min = delta;
+						effect->pattern_length = k;
+						effect->wf_s_repeat_n = j;
+						effect->wf_repeat_n = i;
+					}
+					if (samples > total_samples)
+						break;
+				}
+			}
+		}
+	}
+
+	if (left > 0 && effect->pattern_length < HAP_WAVEFORM_BUFFER_MAX)
+		effect->pattern_length++;
+
+	play->length_us = effect->pattern_length * effect->play_rate_us;
+	dev_dbg(chip->dev, "total_samples = %d, pattern_length = %d, wf_s_repeat = %d, wf_repeat = %d\n",
+			total_samples, effect->pattern_length,
+			wf_s_repeat[effect->wf_s_repeat_n],
+			wf_repeat[effect->wf_repeat_n]);
+
+	for (i = 0; i < effect->pattern_length; i++) {
+		magnitude = play->vmax_mv / HAP_VMAX_MV_LSB;
+		effect->pattern[i] = (u8)magnitude << HAP_WF_AMP_SHIFT;
+	}
+}
+
+static int qti_haptics_config_wf_buffer(struct qti_hap_chip *chip)
+{
+	struct qti_hap_play_info *play = &chip->play;
+	struct qti_hap_effect *effect = play->effect;
+	u8 addr, pattern[HAP_WAVEFORM_BUFFER_MAX] = {0};
+	int rc = 0;
+	size_t len;
+
+	if (play->playing_pos == effect->pattern_length) {
+		dev_dbg(chip->dev, "pattern playing done\n");
+		return 0;
+	}
+
+	if (effect->pattern_length - play->playing_pos
+			>= HAP_WAVEFORM_BUFFER_MAX)
+		len = HAP_WAVEFORM_BUFFER_MAX;
+	else
+		len = effect->pattern_length - play->playing_pos;
+
+	dev_dbg(chip->dev, "copy %d bytes start from %d\n",
+			(int)len, play->playing_pos);
+	memcpy(pattern, &effect->pattern[play->playing_pos], len);
+
+	play->playing_pos += len;
+
+	addr = REG_HAP_WF_S1;
+	rc = qti_haptics_write(chip, REG_HAP_WF_S1, pattern,
+			HAP_WAVEFORM_BUFFER_MAX);
+	if (rc < 0)
+		dev_err(chip->dev, "Program WF_SAMPLE failed, rc=%d\n", rc);
+
+	return rc;
+}
+
+static int qti_haptics_config_wf_repeat(struct qti_hap_chip *chip)
+{
+	struct qti_hap_effect *effect = chip->play.effect;
+	u8 addr, mask, val;
+	int rc = 0;
+
+	addr = REG_HAP_WF_REPEAT;
+	mask = HAP_WF_REPEAT_MASK | HAP_WF_S_REPEAT_MASK;
+	val = effect->wf_repeat_n << HAP_WF_REPEAT_SHIFT;
+	val |= effect->wf_s_repeat_n;
+	rc = qti_haptics_masked_write(chip, addr, mask, val);
+	if (rc < 0)
+		dev_err(chip->dev, "Program WF_REPEAT failed, rc=%d\n", rc);
+
+	return rc;
+}
+
+static int qti_haptics_play(struct qti_hap_chip *chip, bool play)
+{
+	int rc = 0;
+	u8 val = play ? HAP_PLAY_BIT : 0;
+
+	rc = qti_haptics_write(chip,
+			REG_HAP_PLAY, &val, 1);
+	if (rc < 0)
+		dev_err(chip->dev, "%s playing haptics failed, rc=%d\n",
+				play ? "start" : "stop", rc);
+
+	return rc;
+}
+
+static int qti_haptics_module_en(struct qti_hap_chip *chip, bool en)
+{
+	int rc = 0;
+	u8 val = en ? HAP_EN_BIT : 0;
+
+	rc = qti_haptics_write(chip,
+			REG_HAP_EN_CTL1, &val, 1);
+	if (rc < 0)
+		dev_err(chip->dev, "%s haptics failed, rc=%d\n",
+				en ? "enable" : "disable", rc);
+
+
+	return rc;
+}
+
+static int qti_haptics_config_vmax(struct qti_hap_chip *chip, int vmax_mv)
+{
+	u8 addr, mask, val;
+	int rc;
+
+	addr = REG_HAP_VMAX_CFG;
+	mask = HAP_VMAX_MV_MASK;
+	val = (vmax_mv / HAP_VMAX_MV_LSB) << HAP_VMAX_MV_SHIFT;
+	rc = qti_haptics_masked_write(chip, addr, mask, val);
+	if (rc < 0)
+		dev_err(chip->dev, "write VMAX_CFG failed, rc=%d\n",
+				rc);
+
+	return rc;
+}
+
+static int qti_haptics_config_wf_src(struct qti_hap_chip *chip,
+						enum wf_src src)
+{
+	u8 addr, mask, val = 0;
+	int rc;
+
+	addr = REG_HAP_SEL;
+	mask = HAP_WF_SOURCE_MASK | HAP_WF_TRIGGER_BIT;
+	val = src << HAP_WF_SOURCE_SHIFT;
+	if (src == EXT_WF_AUDIO || src == EXT_WF_PWM)
+		val |= HAP_WF_TRIGGER_BIT;
+
+	rc = qti_haptics_masked_write(chip, addr, mask, val);
+	if (rc < 0)
+		dev_err(chip->dev, "set HAP_SEL failed, rc=%d\n", rc);
+
+	return rc;
+}
+
+static int qti_haptics_config_play_rate_us(struct qti_hap_chip *chip,
+						int play_rate_us)
+{
+	u8 addr, val[2];
+	int tmp, rc;
+
+	addr = REG_HAP_RATE_CFG1;
+	tmp = play_rate_us / HAP_PLAY_RATE_US_LSB;
+	val[0] = tmp & 0xff;
+	val[1] = (tmp >> 8) & 0xf;
+	rc = qti_haptics_write(chip, addr, val, 2);
+	if (rc < 0)
+		dev_err(chip->dev, "write play_rate failed, rc=%d\n", rc);
+
+	return rc;
+}
+
+static int qti_haptics_config_brake(struct qti_hap_chip *chip, u8 *brake)
+{
+	u8 addr, mask, val;
+	int i, rc;
+	bool en = true;
+
+	addr = REG_HAP_BRAKE;
+	for (val = 0, i = 0; i < HAP_BRAKE_PATTERN_MAX; i++)
+		val |= (brake[i] & HAP_BRAKE_PATTERN_MASK) <<
+			i * HAP_BRAKE_PATTERN_SHIFT;
+
+	rc = qti_haptics_write(chip, addr, &val, 1);
+	if (rc < 0) {
+		dev_err(chip->dev, "write brake pattern failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	if (val == 0)
+		en = false;
+
+	/* Set BRAKE_EN only if brake pattern is non-zero */
+	addr = REG_HAP_EN_CTL2;
+	mask = HAP_BRAKE_EN_BIT;
+	val = en;
+	rc = qti_haptics_masked_write(chip, addr, mask, val);
+	if (rc < 0)
+		dev_err(chip->dev, "set EN_CTL2 failed, rc=%d\n", rc);
+
+	return rc;
+}
+
+static int qti_haptics_lra_auto_res_enable(struct qti_hap_chip *chip, bool en)
+{
+	int rc;
+	u8 addr, val, mask;
+
+	addr = REG_HAP_AUTO_RES_CTRL;
+	mask = HAP_AUTO_RES_EN_BIT;
+	val = en ? HAP_AUTO_RES_EN_BIT : 0;
+	rc = qti_haptics_masked_write(chip, addr, mask, val);
+	if (rc < 0)
+		dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n", rc);
+
+	return rc;
+}
+
+static int qti_haptics_load_constant_waveform(struct qti_hap_chip *chip)
+{
+	struct qti_hap_play_info *play = &chip->play;
+	struct qti_hap_config *config = &chip->config;
+	int rc = 0;
+
+	rc = qti_haptics_module_en(chip, true);
+	if (rc < 0)
+		return rc;
+
+	/*
+	 * Using VMAX waveform source if playing length is >= 20ms,
+	 * otherwise using buffer waveform source and calculate the
+	 * pattern length and repeating times to achieve accurate
+	 * playing time accuracy.
+	 */
+	if (play->length_us >= VMAX_MIN_PLAY_TIME_US) {
+		rc = qti_haptics_config_vmax(chip, play->vmax_mv);
+		if (rc < 0)
+			return rc;
+
+		/* Enable Auto-Resonance when VMAX wf-src is selected */
+		if (config->act_type == ACT_LRA) {
+			rc = qti_haptics_lra_auto_res_enable(chip, true);
+			if (rc < 0)
+				return rc;
+		}
+
+		/* Set WF_SOURCE to VMAX */
+		rc = qti_haptics_config_wf_src(chip, INT_WF_VMAX);
+		if (rc < 0)
+			return rc;
+
+		play->playing_pattern = false;
+	} else {
+		rc = qti_haptics_config_vmax(chip, config->vmax_mv);
+		if (rc < 0)
+			return rc;
+
+		play->effect = &chip->constant;
+		play->playing_pos = 0;
+		/* Format and config waveform in patterns */
+		construct_constant_waveform_in_pattern(play);
+		rc = qti_haptics_config_wf_buffer(chip);
+		if (rc < 0)
+			return rc;
+
+		rc = qti_haptics_config_wf_repeat(chip);
+		if (rc < 0)
+			return rc;
+
+		/* Set WF_SOURCE to buffer */
+		rc = qti_haptics_config_wf_src(chip, INT_WF_BUFFER);
+		if (rc < 0)
+			return rc;
+
+		play->playing_pattern = true;
+	}
+
+	return 0;
+}
+
+static int qti_haptics_load_predefined_effect(struct qti_hap_chip *chip,
+		int effect_idx)
+{
+	struct qti_hap_play_info *play = &chip->play;
+	struct qti_hap_config *config = &chip->config;
+	int rc = 0;
+
+	if (effect_idx >= chip->effects_count)
+		return -EINVAL;
+
+	play->effect = &chip->predefined[effect_idx];
+	play->playing_pos = 0;
+
+	rc = qti_haptics_module_en(chip, true);
+	if (rc < 0)
+		return rc;
+
+	rc = qti_haptics_config_vmax(chip, play->vmax_mv);
+	if (rc < 0)
+		return rc;
+
+	rc = qti_haptics_config_play_rate_us(chip, play->effect->play_rate_us);
+	if (rc < 0)
+		return rc;
+
+	if (config->act_type == ACT_LRA) {
+		rc = qti_haptics_lra_auto_res_enable(chip,
+				!play->effect->lra_auto_res_disable);
+		if (rc < 0)
+			return rc;
+	}
+
+	/* Set brake pattern in the effect */
+	rc = qti_haptics_config_brake(chip, play->effect->brake);
+	if (rc < 0)
+		return rc;
+
+	rc = qti_haptics_config_wf_buffer(chip);
+	if (rc < 0)
+		return rc;
+
+	rc = qti_haptics_config_wf_repeat(chip);
+	if (rc < 0)
+		return rc;
+
+	/* Set WF_SOURCE to buffer */
+	rc = qti_haptics_config_wf_src(chip, INT_WF_BUFFER);
+	if (rc < 0)
+		return rc;
+
+	play->playing_pattern = true;
+
+	return 0;
+}
+
+static irqreturn_t qti_haptics_play_irq_handler(int irq, void *data)
+{
+	struct qti_hap_chip *chip = (struct qti_hap_chip *)data;
+	struct qti_hap_play_info *play = &chip->play;
+	struct qti_hap_effect *effect = play->effect;
+	int rc;
+
+	dev_dbg(chip->dev, "play_irq triggered\n");
+	if (play->playing_pos == effect->pattern_length) {
+		dev_dbg(chip->dev, "waveform playing done\n");
+		qti_haptics_play(chip, false);
+		if (chip->play_irq_en) {
+			disable_irq_nosync(chip->play_irq);
+			chip->play_irq_en = false;
+		}
+
+		goto handled;
+	}
+
+	/* Config to play remaining patterns */
+	rc = qti_haptics_config_wf_repeat(chip);
+	if (rc < 0)
+		goto handled;
+
+	rc = qti_haptics_config_wf_buffer(chip);
+	if (rc < 0)
+		goto handled;
+
+handled:
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t qti_haptics_sc_irq_handler(int irq, void *data)
+{
+	struct qti_hap_chip *chip = (struct qti_hap_chip *)data;
+	u8 addr, val;
+	ktime_t temp;
+	s64 sc_delta_time_us;
+	int rc;
+
+	dev_dbg(chip->dev, "sc_irq triggered\n");
+	addr = REG_HAP_STATUS1;
+	rc = qti_haptics_read(chip, addr, &val, 1);
+	if (rc < 0) {
+		dev_err(chip->dev, "read HAP_STATUS1 failed, rc=%d\n", rc);
+		goto handled;
+	}
+
+	if (!(val & HAP_SC_DET_BIT))
+		goto handled;
+
+	temp = ktime_get();
+	sc_delta_time_us = ktime_us_delta(temp, chip->last_sc_time);
+	chip->last_sc_time = temp;
+
+	if (sc_delta_time_us > HAP_SC_DET_TIME_US)
+		chip->sc_det_count = 0;
+	else
+		chip->sc_det_count++;
+
+	addr = REG_HAP_SC_CLR;
+	val = HAP_SC_CLR_BIT;
+	rc = qti_haptics_write(chip, addr, &val, 1);
+	if (rc < 0) {
+		dev_err(chip->dev, "write SC_CLR failed, rc=%d\n", rc);
+		goto handled;
+	}
+
+	if (chip->sc_det_count > HAP_SC_DET_MAX_COUNT) {
+		rc = qti_haptics_module_en(chip, false);
+		if (rc < 0)
+			goto handled;
+
+		dev_crit(chip->dev, "Short circuit persists, disable haptics\n");
+		chip->perm_disable = true;
+	}
+
+handled:
+	return IRQ_HANDLED;
+}
+
+static inline void get_play_length(struct qti_hap_play_info *play,
+		int *length_us)
+{
+	struct qti_hap_effect *effect = play->effect;
+	int tmp;
+
+	tmp = effect->pattern_length * effect->play_rate_us;
+	tmp *= wf_s_repeat[effect->wf_s_repeat_n];
+	tmp *= wf_repeat[effect->wf_repeat_n];
+	if (effect->brake_en)
+		tmp += effect->play_rate_us * effect->brake_pattern_length;
+
+	*length_us = tmp;
+}
+
+static int qti_haptics_upload_effect(struct input_dev *dev,
+		struct ff_effect *effect, struct ff_effect *old)
+{
+	struct qti_hap_chip *chip = input_get_drvdata(dev);
+	struct qti_hap_config *config = &chip->config;
+	struct qti_hap_play_info *play = &chip->play;
+	int rc = 0, tmp, i;
+	s16 level, data[CUSTOM_DATA_LEN];
+
+	if (chip->vdd_supply && !chip->vdd_enabled) {
+		rc = regulator_enable(chip->vdd_supply);
+		if (rc < 0) {
+			dev_err(chip->dev, "Enable VDD supply failed, rc=%d\n",
+					rc);
+			return rc;
+		}
+		chip->vdd_enabled = true;
+	}
+
+	switch (effect->type) {
+	case FF_CONSTANT:
+		play->length_us = effect->replay.length * USEC_PER_MSEC;
+		level = effect->u.constant.level;
+		tmp = level * config->vmax_mv;
+		play->vmax_mv = tmp / 0x7fff;
+		dev_dbg(chip->dev, "upload constant effect, length = %dus, vmax_mv=%d\n",
+				play->length_us, play->vmax_mv);
+
+		rc = qti_haptics_load_constant_waveform(chip);
+		if (rc < 0) {
+			dev_err(chip->dev, "Play constant waveform failed, rc=%d\n",
+					rc);
+			goto disable_vdd;
+		}
+		break;
+
+	case FF_PERIODIC:
+		if (chip->effects_count == 0) {
+			rc = -EINVAL;
+			goto disable_vdd;
+		}
+
+		if (effect->u.periodic.waveform != FF_CUSTOM) {
+			dev_err(chip->dev, "Only accept custom waveforms\n");
+			rc = -EINVAL;
+			goto disable_vdd;
+		}
+
+		level = effect->u.periodic.magnitude;
+		tmp = level * config->vmax_mv;
+		play->vmax_mv = tmp / 0x7fff;
+
+		if (copy_from_user(data, effect->u.periodic.custom_data,
+					sizeof(s16) * CUSTOM_DATA_LEN)) {
+			rc = -EFAULT;
+			goto disable_vdd;
+		}
+
+		for (i = 0; i < chip->effects_count; i++)
+			if (chip->predefined[i].id ==
+					data[CUSTOM_DATA_EFFECT_IDX])
+				break;
+
+		if (i == chip->effects_count) {
+			dev_err(chip->dev, "predefined effect %d is NOT supported\n",
+					data[0]);
+			rc = -EINVAL;
+			goto disable_vdd;
+		}
+
+		dev_dbg(chip->dev, "upload effect %d, vmax_mv=%d\n",
+				chip->predefined[i].id, play->vmax_mv);
+		rc = qti_haptics_load_predefined_effect(chip, i);
+		if (rc < 0) {
+			dev_err(chip->dev, "Play predefined effect %d failed, rc=%d\n",
+					chip->predefined[i].id, rc);
+			goto disable_vdd;
+		}
+
+		get_play_length(play, &play->length_us);
+		data[CUSTOM_DATA_TIMEOUT_SEC_IDX] =
+			play->length_us / USEC_PER_SEC;
+		data[CUSTOM_DATA_TIMEOUT_MSEC_IDX] =
+			(play->length_us % USEC_PER_SEC) / USEC_PER_MSEC;
+
+		/*
+		 * Copy the custom data contains the play length back to
+		 * userspace so that the userspace client can wait and
+		 * send stop playing command after it's done.
+		 */
+		if (copy_to_user(effect->u.periodic.custom_data, data,
+					sizeof(s16) * CUSTOM_DATA_LEN)) {
+			rc = -EFAULT;
+			goto disable_vdd;
+		}
+		break;
+
+	default:
+		dev_err(chip->dev, "Unsupported effect type: %d\n",
+				effect->type);
+		break;
+	}
+
+	return 0;
+disable_vdd:
+	if (chip->vdd_supply && chip->vdd_enabled) {
+		rc = regulator_disable(chip->vdd_supply);
+		if (rc < 0) {
+			dev_err(chip->dev, "Disable VDD supply failed, rc=%d\n",
+					rc);
+			return rc;
+		}
+		chip->vdd_enabled = false;
+	}
+	return rc;
+}
+
+static int qti_haptics_playback(struct input_dev *dev, int effect_id, int val)
+{
+	struct qti_hap_chip *chip = input_get_drvdata(dev);
+	struct qti_hap_play_info *play = &chip->play;
+	s64 secs;
+	unsigned long nsecs;
+	int rc = 0;
+
+	dev_dbg(chip->dev, "playback, val = %d\n", val);
+	if (!!val) {
+		rc = qti_haptics_play(chip, true);
+		if (rc < 0)
+			return rc;
+
+		if (play->playing_pattern) {
+			if (!chip->play_irq_en) {
+				enable_irq(chip->play_irq);
+				chip->play_irq_en = true;
+			}
+		} else {
+			if (chip->play_irq_en) {
+				disable_irq_nosync(chip->play_irq);
+				chip->play_irq_en = false;
+			}
+			secs = play->length_us / USEC_PER_SEC;
+			nsecs = (play->length_us % USEC_PER_SEC) *
+				NSEC_PER_USEC;
+			hrtimer_start(&chip->stop_timer, ktime_set(secs, nsecs),
+					HRTIMER_MODE_REL);
+		}
+	} else {
+		play->length_us = 0;
+		rc = qti_haptics_play(chip, false);
+		if (rc < 0)
+			return rc;
+
+		rc = qti_haptics_module_en(chip, false);
+		if (rc < 0)
+			return rc;
+
+		if (chip->play_irq_en) {
+			disable_irq_nosync(chip->play_irq);
+			chip->play_irq_en = false;
+		}
+	}
+
+	return rc;
+}
+
+static int qti_haptics_erase(struct input_dev *dev, int effect_id)
+{
+	struct qti_hap_chip *chip = input_get_drvdata(dev);
+	int rc = 0;
+
+	if (chip->vdd_supply && chip->vdd_enabled) {
+		rc = regulator_disable(chip->vdd_supply);
+		if (rc < 0) {
+			dev_err(chip->dev, "Disable VDD supply failed, rc=%d\n",
+					rc);
+			return rc;
+		}
+		chip->vdd_enabled = false;
+	}
+
+	return rc;
+}
+
+static int qti_haptics_hw_init(struct qti_hap_chip *chip)
+{
+	struct qti_hap_config *config = &chip->config;
+	u8 addr, val, mask;
+	int rc = 0;
+
+	/* Config actuator type */
+	addr = REG_HAP_CFG1;
+	val = config->act_type;
+	rc = qti_haptics_write(chip, addr, &val, 1);
+	if (rc < 0) {
+		dev_err(chip->dev, "write actuator type failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	/* Config ilim_ma */
+	addr = REG_HAP_ILIM_CFG;
+	val = config->ilim_ma == 400 ? 0 : 1;
+	rc = qti_haptics_write(chip, addr, &val, 1);
+	if (rc < 0) {
+		dev_err(chip->dev, "write ilim_ma failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	/* Set HAP_EN_CTL3 */
+	addr = REG_HAP_EN_CTL3;
+	val = HAP_HBRIDGE_EN_BIT | HAP_PWM_SIGNAL_EN_BIT | HAP_ILIM_EN_BIT |
+		HAP_ILIM_CC_EN_BIT | HAP_AUTO_RES_RBIAS_EN_BIT |
+		HAP_DAC_EN_BIT | HAP_PWM_CTL_EN_BIT;
+	rc = qti_haptics_write(chip, addr, &val, 1);
+	if (rc < 0) {
+		dev_err(chip->dev, "set EN_CTL3 failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	/* Set ZX_CFG */
+	addr = REG_HAP_ZX_CFG;
+	mask = HAP_ZX_DET_DEB_MASK;
+	val = ZX_DET_DEB_80US;
+	rc = qti_haptics_masked_write(chip, addr, mask, val);
+	if (rc < 0) {
+		dev_err(chip->dev, "write ZX_CFG failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	/*
+	 * Config play rate: this is the resonance period for LRA,
+	 * or the play duration of each waveform sample for ERM.
+	 */
+	rc = qti_haptics_config_play_rate_us(chip, config->play_rate_us);
+	if (rc < 0)
+		return rc;
+
+	/* Set external waveform source if it's used */
+	if (config->use_ext_wf_src) {
+		rc = qti_haptics_config_wf_src(chip, config->ext_src);
+		if (rc < 0)
+			return rc;
+	}
+
+	/*
+	 * Skip configurations below for ERM actuator
+	 * as they're only for LRA actuators
+	 */
+	if (config->act_type == ACT_ERM)
+		return 0;
+
+	addr = REG_HAP_CFG2;
+	val = config->lra_shape;
+	rc = qti_haptics_write(chip, addr, &val, 1);
+	if (rc < 0) {
+		dev_err(chip->dev, "write lra_sig_shape failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	addr = REG_HAP_AUTO_RES_CFG;
+	mask = HAP_AUTO_RES_MODE_BIT | HAP_CAL_EOP_EN_BIT | HAP_CAL_PERIOD_MASK;
+	val = config->lra_auto_res_mode << HAP_AUTO_RES_MODE_SHIFT;
+	val |= HAP_CAL_EOP_EN_BIT | HAP_CAL_OPT3_EVERY_8_PERIOD;
+	rc = qti_haptics_masked_write(chip, addr, mask, val);
+	if (rc < 0) {
+		dev_err(chip->dev, "set AUTO_RES_CFG failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	addr = REG_HAP_AUTO_RES_CTRL;
+	val = HAP_AUTO_RES_EN_BIT | HAP_SEL_AUTO_RES_PERIOD |
+		AUTO_RES_CNT_ERR_DELTA(2) | HAP_AUTO_RES_ERR_RECOVERY_BIT |
+		AUTO_RES_EN_DLY(4);
+	rc = qti_haptics_write(chip, addr, &val, 1);
+	if (rc < 0) {
+		dev_err(chip->dev, "set AUTO_RES_CTRL failed, rc=%d\n",
+				rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+static enum hrtimer_restart qti_hap_stop_timer(struct hrtimer *timer)
+{
+	struct qti_hap_chip *chip = container_of(timer, struct qti_hap_chip,
+			stop_timer);
+	int rc;
+
+	chip->play.length_us = 0;
+	rc = qti_haptics_play(chip, false);
+	if (rc < 0) {
+		dev_err(chip->dev, "Stop playing failed, rc=%d\n", rc);
+		goto err_out;
+	}
+
+	rc = qti_haptics_module_en(chip, false);
+	if (rc < 0)
+		dev_err(chip->dev, "Disable module failed, rc=%d\n", rc);
+err_out:
+	return HRTIMER_NORESTART;
+}
+
+static int qti_haptics_parse_dt(struct qti_hap_chip *chip)
+{
+	struct qti_hap_config *config = &chip->config;
+	const struct device_node *node = chip->dev->of_node;
+	struct device_node *child_node;
+	struct qti_hap_effect *effect;
+	const char *str;
+	int rc = 0, tmp, i = 0, j;
+	u8 val;
+
+	rc = of_property_read_u32(node, "reg", &tmp);
+	if (rc < 0) {
+		dev_err(chip->dev, "Failed to reg base, rc=%d\n", rc);
+		return rc;
+	}
+	chip->reg_base = (u16)tmp;
+
+	chip->sc_irq = platform_get_irq_byname(chip->pdev, "hap-sc-irq");
+	if (chip->sc_irq < 0) {
+		dev_err(chip->dev, "Failed to get hap-sc-irq\n");
+		return chip->sc_irq;
+	}
+
+	chip->play_irq = platform_get_irq_byname(chip->pdev, "hap-play-irq");
+	if (chip->play_irq < 0) {
+		dev_err(chip->dev, "Failed to get hap-play-irq\n");
+		return chip->play_irq;
+	}
+
+	config->act_type = ACT_LRA;
+	rc = of_property_read_string(node, "qcom,actuator-type", &str);
+	if (!rc) {
+		if (strcmp(str, "erm") == 0) {
+			config->act_type = ACT_ERM;
+		} else if (strcmp(str, "lra") == 0) {
+			config->act_type = ACT_LRA;
+		} else {
+			dev_err(chip->dev, "Invalid actuator type: %s\n",
+					str);
+			return -EINVAL;
+		}
+	}
+
+	config->vmax_mv = HAP_VMAX_MV_DEFAULT;
+	rc = of_property_read_u32(node, "qcom,vmax-mv", &tmp);
+	if (!rc)
+		config->vmax_mv = (tmp > HAP_VMAX_MV_MAX) ?
+			HAP_VMAX_MV_MAX : tmp;
+
+	config->ilim_ma = HAP_ILIM_MA_DEFAULT;
+	rc = of_property_read_u32(node, "qcom,ilim-ma", &tmp);
+	if (!rc)
+		config->ilim_ma = (tmp >= HAP_ILIM_MA_MAX) ?
+			HAP_ILIM_MA_MAX : HAP_ILIM_MA_DEFAULT;
+
+	config->play_rate_us = HAP_PLAY_RATE_US_DEFAULT;
+	rc = of_property_read_u32(node, "qcom,play-rate-us", &tmp);
+	if (!rc)
+		config->play_rate_us = (tmp >= HAP_PLAY_RATE_US_MAX) ?
+			HAP_PLAY_RATE_US_MAX : tmp;
+
+	if (of_find_property(node, "qcom,external-waveform-source", NULL)) {
+		if (!of_property_read_string(node,
+				"qcom,external-waveform-source", &str)) {
+			if (strcmp(str, "audio") == 0) {
+				config->ext_src = EXT_WF_AUDIO;
+			} else if (strcmp(str, "pwm") == 0) {
+				config->ext_src = EXT_WF_PWM;
+			} else {
+				dev_err(chip->dev, "Invalid external waveform source: %s\n",
+						str);
+				return -EINVAL;
+			}
+		}
+		config->use_ext_wf_src = true;
+	}
+
+	if (of_find_property(node, "vdd-supply", NULL)) {
+		chip->vdd_supply = devm_regulator_get(chip->dev, "vdd");
+		if (IS_ERR(chip->vdd_supply)) {
+			rc = PTR_ERR(chip->vdd_supply);
+			if (rc != -EPROBE_DEFER)
+				dev_err(chip->dev, "Failed to get vdd regulator");
+			return rc;
+		}
+	}
+
+	if (config->act_type == ACT_LRA) {
+		config->lra_shape = RES_SIG_SINE;
+		rc = of_property_read_string(node,
+				"qcom,lra-resonance-sig-shape", &str);
+		if (!rc) {
+			if (strcmp(str, "sine") == 0) {
+				config->lra_shape = RES_SIG_SINE;
+			} else if (strcmp(str, "square") == 0) {
+				config->lra_shape = RES_SIG_SQUARE;
+			} else {
+				dev_err(chip->dev, "Invalid resonance signal shape: %s\n",
+						str);
+				return -EINVAL;
+			}
+		}
+
+		config->lra_allow_variable_play_rate = of_property_read_bool(
+				node, "qcom,lra-allow-variable-play-rate");
+
+		config->lra_auto_res_mode = AUTO_RES_MODE_ZXD;
+		rc = of_property_read_string(node,
+				"qcom,lra-auto-resonance-mode", &str);
+		if (!rc) {
+			if (strcmp(str, "zxd") == 0) {
+				config->lra_auto_res_mode = AUTO_RES_MODE_ZXD;
+			} else if (strcmp(str, "qwd") == 0) {
+				config->lra_auto_res_mode = AUTO_RES_MODE_QWD;
+			} else {
+				dev_err(chip->dev, "Invalid auto resonance mode: %s\n",
+						str);
+				return -EINVAL;
+			}
+		}
+	}
+
+	chip->constant.pattern = devm_kcalloc(chip->dev,
+			HAP_WAVEFORM_BUFFER_MAX,
+			sizeof(u8), GFP_KERNEL);
+	if (!chip->constant.pattern)
+		return -ENOMEM;
+
+	tmp = of_get_available_child_count(node);
+	if (tmp == 0)
+		return 0;
+
+	chip->predefined = devm_kcalloc(chip->dev, tmp,
+			sizeof(*chip->predefined), GFP_KERNEL);
+	if (!chip->predefined)
+		return -ENOMEM;
+
+	chip->effects_count = tmp;
+
+	for_each_available_child_of_node(node, child_node) {
+		effect = &chip->predefined[i++];
+		rc = of_property_read_u32(child_node, "qcom,effect-id",
+				&effect->id);
+		if (rc < 0) {
+			dev_err(chip->dev, "Read qcom,effect-id failed, rc=%d\n",
+					rc);
+			return rc;
+		}
+
+		rc = of_property_count_elems_of_size(child_node,
+				"qcom,wf-pattern", sizeof(u8));
+		if (rc < 0) {
+			dev_err(chip->dev, "Count qcom,wf-pattern property failed, rc=%d\n",
+					rc);
+			return rc;
+		} else if (rc == 0) {
+			dev_dbg(chip->dev, "qcom,wf-pattern has no data\n");
+			return -EINVAL;
+		}
+
+		effect->pattern_length = rc;
+		effect->pattern = devm_kcalloc(chip->dev,
+				effect->pattern_length, sizeof(u8), GFP_KERNEL);
+		if (!effect->pattern)
+			return -ENOMEM;
+
+		rc = of_property_read_u8_array(child_node, "qcom,wf-pattern",
+				effect->pattern, effect->pattern_length);
+		if (rc < 0) {
+			dev_err(chip->dev, "Read qcom,wf-pattern property failed, rc=%d\n",
+					rc);
+			return rc;
+		}
+
+		effect->play_rate_us = config->play_rate_us;
+		rc = of_property_read_u32(child_node, "qcom,wf-play-rate-us",
+				&tmp);
+		if (rc < 0)
+			dev_dbg(chip->dev, "Read qcom,wf-play-rate-us failed, rc=%d\n",
+					rc);
+		else
+			effect->play_rate_us = tmp;
+
+		if (config->act_type == ACT_LRA &&
+				!config->lra_allow_variable_play_rate &&
+				config->play_rate_us != effect->play_rate_us) {
+			dev_warn(chip->dev, "play rate should match with LRA resonance frequency\n");
+			effect->play_rate_us = config->play_rate_us;
+		}
+
+		rc = of_property_read_u32(child_node, "qcom,wf-repeat-count",
+				&tmp);
+		if (rc < 0) {
+			dev_dbg(chip->dev, "Read qcom,wf-repeat-count failed, rc=%d\n",
+					rc);
+		} else {
+			for (j = 0; j < ARRAY_SIZE(wf_repeat); j++)
+				if (tmp <= wf_repeat[j])
+					break;
+
+			effect->wf_repeat_n = j;
+		}
+
+		rc = of_property_read_u32(child_node, "qcom,wf-s-repeat-count",
+				&tmp);
+		if (rc < 0) {
+			dev_dbg(chip->dev, "Read qcom,wf-s-repeat-count failed, rc=%d\n",
+					rc);
+		} else {
+			for (j = 0; j < ARRAY_SIZE(wf_s_repeat); j++)
+				if (tmp <= wf_s_repeat[j])
+					break;
+
+			effect->wf_s_repeat_n = j;
+		}
+
+		effect->lra_auto_res_disable = of_property_read_bool(node,
+				"qcom,lra-auto-resonance-disable");
+
+		tmp = of_property_count_elems_of_size(child_node,
+				"qcom,wf-brake-pattern", sizeof(u8));
+		if (tmp <= 0)
+			continue;
+
+		if (tmp > HAP_BRAKE_PATTERN_MAX) {
+			dev_err(chip->dev, "wf-brake-pattern shouldn't be more than %d bytes\n",
+					HAP_BRAKE_PATTERN_MAX);
+			return -EINVAL;
+		}
+
+		rc = of_property_read_u8_array(child_node,
+				"qcom,wf-brake-pattern", effect->brake, tmp);
+		if (rc < 0) {
+			dev_err(chip->dev, "Failed to get wf-brake-pattern, rc=%d\n",
+					rc);
+			return rc;
+		}
+
+		effect->brake_pattern_length = tmp;
+		for (j = tmp - 1; j >= 0; j--) {
+			if (effect->brake[j] != 0)
+				break;
+			effect->brake_pattern_length--;
+		}
+
+		for (val = 0, j = 0; j < effect->brake_pattern_length; j++)
+			val |= (effect->brake[j] & HAP_BRAKE_PATTERN_MASK)
+				<< j * HAP_BRAKE_PATTERN_SHIFT;
+
+		effect->brake_en = (val != 0);
+	}
+
+	return 0;
+}
+
+static int qti_haptics_probe(struct platform_device *pdev)
+{
+	struct qti_hap_chip *chip;
+	struct input_dev *input_dev;
+	struct ff_device *ff;
+	int rc = 0, effect_count_max;
+
+	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	input_dev = devm_input_allocate_device(&pdev->dev);
+	if (!input_dev)
+		return -ENOMEM;
+
+	chip->pdev = pdev;
+	chip->dev = &pdev->dev;
+	chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
+	if (!chip->regmap) {
+		dev_err(chip->dev, "Failed to get regmap handle\n");
+		return -ENXIO;
+	}
+
+	rc = qti_haptics_parse_dt(chip);
+	if (rc < 0) {
+		dev_err(chip->dev, "parse device-tree failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	spin_lock_init(&chip->bus_lock);
+
+	rc = qti_haptics_hw_init(chip);
+	if (rc < 0) {
+		dev_err(chip->dev, "parse device-tree failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = devm_request_threaded_irq(chip->dev, chip->play_irq, NULL,
+			qti_haptics_play_irq_handler,
+			IRQF_ONESHOT, "hap_play_irq", chip);
+	if (rc < 0) {
+		dev_err(chip->dev, "request play-irq failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	disable_irq(chip->play_irq);
+	chip->play_irq_en = false;
+
+	rc = devm_request_threaded_irq(chip->dev, chip->sc_irq, NULL,
+			qti_haptics_sc_irq_handler,
+			IRQF_ONESHOT, "hap_sc_irq", chip);
+	if (rc < 0) {
+		dev_err(chip->dev, "request sc-irq failed, rc=%d\n", rc);
+		return rc;
+	}
+
+	hrtimer_init(&chip->stop_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	chip->stop_timer.function = qti_hap_stop_timer;
+
+	input_dev->name = "qti-haptics";
+	input_set_drvdata(input_dev, chip);
+	chip->input_dev = input_dev;
+
+	input_set_capability(input_dev, EV_FF, FF_CONSTANT);
+	if (chip->effects_count != 0) {
+		input_set_capability(input_dev, EV_FF, FF_PERIODIC);
+		input_set_capability(input_dev, EV_FF, FF_CUSTOM);
+	}
+
+	if (chip->effects_count + 1 > FF_EFFECT_COUNT_MAX)
+		effect_count_max = chip->effects_count + 1;
+	else
+		effect_count_max = FF_EFFECT_COUNT_MAX;
+	rc = input_ff_create(input_dev, effect_count_max);
+	if (rc < 0) {
+		dev_err(chip->dev, "create FF input device failed, rc=%d\n",
+				rc);
+		return rc;
+	}
+
+	ff = input_dev->ff;
+	ff->upload = qti_haptics_upload_effect;
+	ff->playback = qti_haptics_playback;
+	ff->erase = qti_haptics_erase;
+
+	rc = input_register_device(input_dev);
+	if (rc < 0) {
+		dev_err(chip->dev, "register input device failed, rc=%d\n",
+				rc);
+		goto destroy_ff;
+	}
+
+	dev_set_drvdata(chip->dev, chip);
+	return 0;
+
+destroy_ff:
+	input_ff_destroy(chip->input_dev);
+	return rc;
+}
+
+static int qti_haptics_remove(struct platform_device *pdev)
+{
+	struct qti_hap_chip *chip = dev_get_drvdata(&pdev->dev);
+
+	input_ff_destroy(chip->input_dev);
+	dev_set_drvdata(chip->dev, NULL);
+
+	return 0;
+}
+
+static const struct of_device_id haptics_match_table[] = {
+	{ .compatible = "qcom,haptics" },
+	{ .compatible = "qcom,pm660-haptics" },
+	{ .compatible = "qcom,pm8150b-haptics" },
+	{},
+};
+
+static struct platform_driver qti_haptics_driver = {
+	.driver		= {
+		.name = "qcom,haptics",
+		.of_match_table = haptics_match_table,
+	},
+	.probe		= qti_haptics_probe,
+	.remove		= qti_haptics_remove,
+};
+module_platform_driver(qti_haptics_driver);
+
+MODULE_DESCRIPTION("QTI haptics driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/misc/vl53l0x/stmvl53l0x_module.c b/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
index 34508b2..357a17c 100644
--- a/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
+++ b/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
@@ -1130,6 +1130,25 @@
 				stmvl53l0x_set_XTalkCompensationRateMegaCps);
 
 
+static ssize_t stmvl53l0x_show_GetSensorID(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	u32 SensorID = 0;
+	int ret = 0;
+	struct vl_data *data = dev_get_drvdata(dev);
+	struct i2c_data *i2c_object = (struct i2c_data *)data->client_object;
+
+	ret = of_property_read_u32(i2c_object->client->dev.of_node,
+							"tof-id",
+							&SensorID);
+	return snprintf(buf, 5, "%d\n", SensorID);
+}
+
+/* DEVICE_ATTR(name,mode,show,store) */
+static DEVICE_ATTR(show_sensorid, 0660/*S_IWUGO | S_IRUGO*/,
+				stmvl53l0x_show_GetSensorID,
+				NULL);
 
 static struct attribute *stmvl53l0x_attributes[] = {
 	&dev_attr_enable_ps_sensor.attr,
@@ -1144,6 +1163,7 @@
 	&dev_attr_ref_cal.attr,
 	&dev_attr_set_offsetdata.attr,
 	&dev_attr_set_xtalkdata.attr,
+	&dev_attr_show_sensorid.attr,
 	NULL,
 };
 
@@ -1948,12 +1968,6 @@
 	input_set_drvdata(data->input_dev_ps, data);
 
 	/* Register sysfs hooks */
-	data->range_kobj = kobject_create_and_add("range", kernel_kobj);
-	if (!data->range_kobj) {
-		rc = -ENOMEM;
-		err("%d error:%d\n", __LINE__, rc);
-		goto exit_unregister_dev_ps;
-	}
 	rc = sysfs_create_group(&data->input_dev_ps->dev.kobj,
 			&stmvl53l0x_attr_group);
 	if (rc) {
@@ -1981,7 +1995,6 @@
 	return 0;
 exit_unregister_dev_ps_1:
 	kobject_put(data->range_kobj);
-exit_unregister_dev_ps:
 	input_unregister_device(data->input_dev_ps);
 exit_free_dev_ps:
 	input_free_device(data->input_dev_ps);
diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c
index d773ec5..1e62cde 100644
--- a/drivers/leds/leds-qpnp-flash-v2.c
+++ b/drivers/leds/leds-qpnp-flash-v2.c
@@ -745,8 +745,11 @@
 	union power_supply_propval pval = {0, };
 
 	if (!led->bms_psy) {
-		pr_err("no bms psy found\n");
-		return -EINVAL;
+		led->bms_psy = power_supply_get_by_name("bms");
+		if (!led->bms_psy) {
+			pr_err_ratelimited("Couldn't get bms_psy\n");
+			return -ENODEV;
+		}
 	}
 
 	rc = power_supply_get_property(led->bms_psy, prop, &pval);
@@ -1793,41 +1796,6 @@
 	__ATTR(enable, 0664, NULL, qpnp_flash_led_prepare_store),
 };
 
-static int flash_led_psy_notifier_call(struct notifier_block *nb,
-		unsigned long ev, void *v)
-{
-	struct power_supply *psy = v;
-	struct qpnp_flash_led *led =
-			container_of(nb, struct qpnp_flash_led, nb);
-
-	if (ev != PSY_EVENT_PROP_CHANGED)
-		return NOTIFY_OK;
-
-	if (!strcmp(psy->desc->name, "bms")) {
-		led->bms_psy = power_supply_get_by_name("bms");
-		if (!led->bms_psy)
-			pr_err("Failed to get bms power_supply\n");
-		else
-			power_supply_unreg_notifier(&led->nb);
-	}
-
-	return NOTIFY_OK;
-}
-
-static int flash_led_psy_register_notifier(struct qpnp_flash_led *led)
-{
-	int rc;
-
-	led->nb.notifier_call = flash_led_psy_notifier_call;
-	rc = power_supply_reg_notifier(&led->nb);
-	if (rc < 0) {
-		pr_err("Couldn't register psy notifier, rc = %d\n", rc);
-		return rc;
-	}
-
-	return 0;
-}
-
 /* irq handler */
 static irqreturn_t qpnp_flash_led_irq_handler(int irq, void *_led)
 {
@@ -2821,15 +2789,6 @@
 		}
 	}
 
-	led->bms_psy = power_supply_get_by_name("bms");
-	if (!led->bms_psy) {
-		rc = flash_led_psy_register_notifier(led);
-		if (rc < 0) {
-			pr_err("Couldn't register psy notifier, rc = %d\n", rc);
-			goto error_switch_register;
-		}
-	}
-
 	rc = qpnp_flash_led_init_settings(led);
 	if (rc < 0) {
 		pr_err("Failed to initialize flash LED, rc=%d\n", rc);
diff --git a/drivers/media/platform/msm/Makefile b/drivers/media/platform/msm/Makefile
index 24c27cd..e19da45 100644
--- a/drivers/media/platform/msm/Makefile
+++ b/drivers/media/platform/msm/Makefile
@@ -9,3 +9,4 @@
 obj-$(CONFIG_MSMB_CAMERA) += camera_v2/
 obj-y += broadcast/
 obj-$(CONFIG_DVB_MPQ) += dvb/
+obj-$(CONFIG_QCA402X) += qca402/
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 891b738..670349d 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.c
@@ -56,7 +56,7 @@
 	}
 
 	if (!rc)
-		cam_destroy_device_hdl(ctx_hdl);
+		rc = cam_destroy_device_hdl(ctx_hdl);
 	return rc;
 }
 
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 fce7fc6..89aad8c 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
@@ -490,6 +490,7 @@
 	release.ctxt_to_hw_map = ctx->ctxt_to_hw_map;
 	ctx->hw_mgr_intf->hw_release(ctx->hw_mgr_intf->hw_mgr_priv, &release);
 	ctx->ctxt_to_hw_map = NULL;
+	ctx->dev_hdl = -1;
 end:
 	return rc;
 }
@@ -504,6 +505,7 @@
 	bool free_req;
 
 	CAM_DBG(CAM_CTXT, "[%s] E: NRT flush ctx", ctx->dev_name);
+	memset(&flush_args, 0, sizeof(flush_args));
 
 	/*
 	 * flush pending requests, take the sync lock to synchronize with the
@@ -670,6 +672,7 @@
 
 	CAM_DBG(CAM_CTXT, "[%s] E: NRT flush req", ctx->dev_name);
 
+	memset(&flush_args, 0, sizeof(flush_args));
 	flush_args.num_req_pending = 0;
 	flush_args.num_req_active = 0;
 	mutex_lock(&ctx->sync_mutex);
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 0a9fabc..3f24c6d 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_node.c
@@ -413,13 +413,16 @@
 int cam_node_shutdown(struct cam_node *node)
 {
 	int i = 0;
+	int rc = 0;
 
 	if (!node)
 		return -EINVAL;
 
 	for (i = 0; i < node->ctx_size; i++) {
-		if (node->ctx_list[i].dev_hdl >= 0) {
-			cam_context_shutdown(&(node->ctx_list[i]));
+		if (node->ctx_list[i].dev_hdl > 0) {
+			rc = cam_context_shutdown(&(node->ctx_list[i]));
+			if (rc)
+				continue;
 			cam_context_putref(&(node->ctx_list[i]));
 		}
 	}
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 d32d4b6..1733017 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
@@ -3841,19 +3841,15 @@
 		return -EINVAL;
 	}
 
-	CAM_DBG(CAM_REQ, "ctx_id %d req %lld Flush type %d",
-		ctx_data->ctx_id,
-		*(int64_t *)flush_args->flush_req_pending[0],
-		flush_args->flush_type);
+	CAM_DBG(CAM_REQ, "ctx_id %d Flush type %d",
+		ctx_data->ctx_id, flush_args->flush_type);
 
 	switch (flush_args->flush_type) {
 	case CAM_FLUSH_TYPE_ALL:
 		mutex_lock(&hw_mgr->hw_mgr_mutex);
-		if (!hw_mgr->recovery) {
-			if (flush_args->num_req_active) {
-				mutex_unlock(&hw_mgr->hw_mgr_mutex);
-				cam_icp_mgr_abort_handle(ctx_data);
-			}
+		if (!hw_mgr->recovery && flush_args->num_req_active) {
+			mutex_unlock(&hw_mgr->hw_mgr_mutex);
+			cam_icp_mgr_abort_handle(ctx_data);
 		} else {
 			mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		}
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 f5b1bb1..08ef0e9 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
@@ -1395,12 +1395,56 @@
 	struct cam_context *ctx,
 	struct cam_req_mgr_flush_request *flush_req)
 {
+	struct cam_isp_context           *ctx_isp =
+		(struct cam_isp_context *) ctx->ctx_priv;
+	struct cam_isp_stop_args          stop_isp;
+	struct cam_hw_stop_args           stop_args;
+	struct cam_isp_start_args         start_isp;
 	int rc = 0;
 
 	CAM_DBG(CAM_ISP, "try to flush pending list");
 	spin_lock_bh(&ctx->lock);
 	rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
 	spin_unlock_bh(&ctx->lock);
+
+	if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) {
+		/* if active and wait list are empty, return */
+		spin_lock_bh(&ctx->lock);
+		if ((list_empty(&ctx->wait_req_list)) &&
+			(list_empty(&ctx->active_req_list))) {
+			spin_unlock_bh(&ctx->lock);
+			CAM_DBG(CAM_ISP, "active and wait list are empty");
+			goto end;
+		}
+		spin_unlock_bh(&ctx->lock);
+
+		/* Stop hw first before active list flush */
+		stop_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
+		stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY;
+		stop_isp.stop_only = true;
+		stop_args.args = (void *)&stop_isp;
+		ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv,
+				&stop_args);
+
+		spin_lock_bh(&ctx->lock);
+		CAM_DBG(CAM_ISP, "try to flush wait list");
+		rc = __cam_isp_ctx_flush_req(ctx, &ctx->wait_req_list,
+		flush_req);
+		CAM_DBG(CAM_ISP, "try to flush active list");
+		rc = __cam_isp_ctx_flush_req(ctx, &ctx->active_req_list,
+		flush_req);
+		spin_unlock_bh(&ctx->lock);
+
+		/* Start hw */
+		start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx;
+		start_isp.start_only = true;
+		start_isp.hw_config.priv = NULL;
+
+		rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv,
+			&start_isp);
+	}
+
+end:
 	CAM_DBG(CAM_ISP, "Flush request in top state %d",
 		 ctx->state);
 	return rc;
@@ -1438,7 +1482,7 @@
 	spin_lock_bh(&ctx->lock);
 	rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req);
 
-	/* if nothing is in pending req list, change state to acquire*/
+	/* if nothing is in pending req list, change state to acquire */
 	if (list_empty(&ctx->pending_req_list))
 		ctx->state = CAM_CTX_ACQUIRED;
 	spin_unlock_bh(&ctx->lock);
@@ -2366,7 +2410,7 @@
 	struct cam_start_stop_dev_cmd *cmd)
 {
 	int rc = 0;
-	struct cam_hw_config_args        arg;
+	struct cam_isp_start_args        start_isp;
 	struct cam_ctx_request          *req;
 	struct cam_isp_ctx_req          *req_isp;
 	struct cam_isp_context          *ctx_isp =
@@ -2395,12 +2439,13 @@
 		goto end;
 	}
 
-	arg.ctxt_to_hw_map = ctx_isp->hw_ctx;
-	arg.request_id = req->request_id;
-	arg.hw_update_entries = req_isp->cfg;
-	arg.num_hw_update_entries = req_isp->num_cfg;
-	arg.priv  = &req_isp->hw_update_data;
-	arg.init_packet = 1;
+	start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx;
+	start_isp.hw_config.request_id = req->request_id;
+	start_isp.hw_config.hw_update_entries = req_isp->cfg;
+	start_isp.hw_config.num_hw_update_entries = req_isp->num_cfg;
+	start_isp.hw_config.priv  = &req_isp->hw_update_data;
+	start_isp.hw_config.init_packet = 1;
+	start_isp.start_only = false;
 
 	ctx_isp->frame_id = 0;
 	ctx_isp->active_req_cnt = 0;
@@ -2417,7 +2462,8 @@
 	 */
 	ctx->state = CAM_CTX_ACTIVATED;
 	trace_cam_context_state("ISP", ctx);
-	rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, &arg);
+	rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv,
+		&start_isp);
 	if (rc) {
 		/* HW failure. user need to clean up the resource */
 		CAM_ERR(CAM_ISP, "Start HW failed");
@@ -2458,6 +2504,7 @@
 	struct cam_isp_ctx_req          *req_isp;
 	struct cam_isp_context          *ctx_isp =
 		(struct cam_isp_context *) ctx->ctx_priv;
+	struct cam_isp_stop_args         stop_isp;
 
 	/* Mask off all the incoming hardware events */
 	spin_lock_bh(&ctx->lock);
@@ -2468,7 +2515,15 @@
 	/* stop hw first */
 	if (ctx_isp->hw_ctx) {
 		stop.ctxt_to_hw_map = ctx_isp->hw_ctx;
-		stop.args = stop_cmd;
+
+		if (stop_cmd)
+			stop_isp.hw_stop_cmd =
+				CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY;
+		else
+			stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY;
+
+		stop_isp.stop_only = false;
+		stop.args = (void *) &stop_isp;
 		ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv,
 			&stop);
 	}
@@ -2489,6 +2544,22 @@
 		list_add_tail(&req->list, &ctx->free_req_list);
 	}
 
+	while (!list_empty(&ctx->wait_req_list)) {
+		req = list_first_entry(&ctx->wait_req_list,
+				struct cam_ctx_request, list);
+		list_del_init(&req->list);
+		req_isp = (struct cam_isp_ctx_req *) req->req_priv;
+		CAM_DBG(CAM_ISP, "signal fence in wait list. fence num %d",
+			 req_isp->num_fence_map_out);
+		for (i = 0; i < req_isp->num_fence_map_out; i++)
+			if (req_isp->fence_map_out[i].sync_id != -1) {
+				cam_sync_signal(
+					req_isp->fence_map_out[i].sync_id,
+					CAM_SYNC_STATE_SIGNALED_ERROR);
+			}
+		list_add_tail(&req->list, &ctx->free_req_list);
+	}
+
 	while (!list_empty(&ctx->active_req_list)) {
 		req = list_first_entry(&ctx->active_req_list,
 				struct cam_ctx_request, list);
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 8d764b0..aab323e 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
@@ -283,6 +283,100 @@
 	}
 }
 
+static int cam_ife_hw_mgr_init_hw(
+	struct cam_ife_hw_mgr_ctx *ctx)
+{
+	struct cam_ife_hw_mgr_res *hw_mgr_res;
+	int rc = 0, i;
+
+	CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d",
+		ctx->ctx_index);
+	/* INIT IFE CID */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
+		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Can not INIT IFE CID(id :%d)",
+				 hw_mgr_res->res_id);
+			return rc;
+		}
+	}
+
+	CAM_DBG(CAM_ISP, "INIT IFE csid ... in ctx id:%d",
+		ctx->ctx_index);
+
+	/* INIT IFE csid */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
+		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Can not INIT IFE CSID(id :%d)",
+				 hw_mgr_res->res_id);
+			return rc;
+		}
+	}
+
+	/* INIT IFE SRC */
+	CAM_DBG(CAM_ISP, "INIT IFE SRC in ctx id:%d",
+		ctx->ctx_index);
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Can not INIT IFE SRC (%d)",
+				 hw_mgr_res->res_id);
+			return rc;
+		}
+	}
+
+	/* INIT IFE OUT */
+	CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d",
+		ctx->ctx_index);
+
+	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) {
+		rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_ife_out[i]);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Can not INIT IFE OUT (%d)",
+				 ctx->res_list_ife_out[i].res_id);
+			return rc;
+		}
+	}
+
+	return rc;
+}
+
+static void cam_ife_hw_mgr_deinit_hw(
+	struct cam_ife_hw_mgr_ctx *ctx)
+{
+	struct cam_ife_hw_mgr_res *hw_mgr_res;
+	int i = 0;
+
+	if (!ctx->init_done) {
+		CAM_WARN(CAM_ISP, "ctx is not in init state");
+		return;
+	}
+
+	/* Deinit IFE CID */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
+		CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CID\n", __func__);
+		cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
+	}
+
+	/* Deinit IFE CSID */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
+		CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CSID\n", __func__);
+		cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
+	}
+
+	/* Deint IFE MUX(SRC) */
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+		cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
+	}
+
+	/* Deinit IFE OUT */
+	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
+		cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]);
+
+	ctx->init_done = false;
+}
+
 static int cam_ife_hw_mgr_put_res(
 	struct list_head                *src_list,
 	struct cam_ife_hw_mgr_res      **res)
@@ -1833,6 +1927,7 @@
 {
 	int                               rc        = 0;
 	struct cam_hw_stop_args          *stop_args = stop_hw_args;
+	struct cam_isp_stop_args         *stop_isp;
 	struct cam_ife_hw_mgr_res        *hw_mgr_res;
 	struct cam_ife_hw_mgr_ctx        *ctx;
 	enum cam_ife_csid_halt_cmd        csid_halt_type;
@@ -1842,6 +1937,7 @@
 		CAM_ERR(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
+
 	ctx = (struct cam_ife_hw_mgr_ctx *)stop_args->ctxt_to_hw_map;
 	if (!ctx || !ctx->ctx_in_use) {
 		CAM_ERR(CAM_ISP, "Invalid context is used");
@@ -1849,12 +1945,20 @@
 	}
 
 	CAM_DBG(CAM_ISP, " Enter...ctx id:%d", ctx->ctx_index);
+	stop_isp = (struct cam_isp_stop_args    *)stop_args->args;
+
+	if ((stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_IMMEDIATELY) &&
+		(stop_isp->stop_only)) {
+		CAM_ERR(CAM_ISP, "Invalid params hw_stop_cmd:%d stop_only:%d",
+			stop_isp->hw_stop_cmd, stop_isp->stop_only);
+		return -EPERM;
+	}
 
 	/* Set the csid halt command */
-	if (!stop_args->args)
-		csid_halt_type = CAM_CSID_HALT_IMMEDIATELY;
-	else
+	if (stop_isp->hw_stop_cmd == CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY)
 		csid_halt_type = CAM_CSID_HALT_AT_FRAME_BOUNDARY;
+	else
+		csid_halt_type = CAM_CSID_HALT_IMMEDIATELY;
 
 	/* Note:stop resource will remove the irq mask from the hardware */
 
@@ -1930,30 +2034,15 @@
 			ctx->base[i].idx, csid_halt_type);
 	}
 
-	/* Deinit IFE CID */
-	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
-		CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CID\n", __func__);
-		cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
-	}
+	if (stop_isp->stop_only)
+		goto end;
 
-	/* Deinit IFE CSID */
-	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
-		CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CSID\n", __func__);
-		cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
-	}
-
-	/* Deint IFE MUX(SRC) */
-	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
-		cam_ife_hw_mgr_deinit_hw_res(hw_mgr_res);
-	}
-
-	/* Deinit IFE OUT */
-	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
-		cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]);
-
+	cam_ife_hw_mgr_deinit_hw(ctx);
 	CAM_DBG(CAM_ISP,
 		"Stop success for ctx id:%d rc :%d", ctx->ctx_index, rc);
 
+end:
+
 	mutex_lock(&g_ife_hw_mgr.ctx_mutex);
 	if (!atomic_dec_return(&g_ife_hw_mgr.active_ctx_cnt)) {
 		rc = cam_ife_notify_safe_lut_scm(CAM_IFE_SAFE_DISABLE);
@@ -2065,19 +2154,20 @@
 static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args)
 {
 	int                               rc = -1;
-	struct cam_hw_config_args        *start_args = start_hw_args;
+	struct cam_isp_start_args        *start_isp = start_hw_args;
 	struct cam_hw_stop_args           stop_args;
-	struct cam_isp_stop_hw_method     stop_hw_method;
+	struct cam_isp_stop_args          stop_isp;
 	struct cam_ife_hw_mgr_ctx        *ctx;
 	struct cam_ife_hw_mgr_res        *hw_mgr_res;
 	uint32_t                          i;
 
-	if (!hw_mgr_priv || !start_hw_args) {
+	if (!hw_mgr_priv || !start_isp) {
 		CAM_ERR(CAM_ISP, "Invalid arguments");
 		return -EINVAL;
 	}
 
-	ctx = (struct cam_ife_hw_mgr_ctx *)start_args->ctxt_to_hw_map;
+	ctx = (struct cam_ife_hw_mgr_ctx *)
+		start_isp->hw_config.ctxt_to_hw_map;
 	if (!ctx || !ctx->ctx_in_use) {
 		CAM_ERR(CAM_ISP, "Invalid context is used");
 		return -EPERM;
@@ -2090,6 +2180,9 @@
 
 	cam_tasklet_start(ctx->common.tasklet_info);
 
+	if (ctx->init_done && start_isp->start_only)
+		goto start_only;
+
 	/* set current csid debug information to CSID HW */
 	for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
 		if (g_ife_hw_mgr.csid_devices[i])
@@ -2100,58 +2193,13 @@
 				sizeof(g_ife_hw_mgr.debug_cfg.csid_debug));
 	}
 
-	/* INIT IFE Root: do nothing */
-
-	CAM_DBG(CAM_ISP, "INIT IFE CID ... in ctx id:%d",
-		ctx->ctx_index);
-	/* INIT IFE CID */
-	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
-		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "Can not INIT IFE CID(id :%d)",
-				 hw_mgr_res->res_id);
-			goto err;
-		}
+	rc = cam_ife_hw_mgr_init_hw(ctx);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Init failed");
+		goto err;
 	}
 
-
-	CAM_DBG(CAM_ISP, "INIT IFE csid ... in ctx id:%d",
-		ctx->ctx_index);
-
-	/* INIT IFE csid */
-	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
-		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "Can not INIT IFE CSID(id :%d)",
-				 hw_mgr_res->res_id);
-			goto err;
-		}
-	}
-
-	/* INIT IFE SRC */
-	CAM_DBG(CAM_ISP, "INIT IFE SRC in ctx id:%d",
-		ctx->ctx_index);
-	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
-		rc = cam_ife_hw_mgr_init_hw_res(hw_mgr_res);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "Can not INIT IFE SRC (%d)",
-				 hw_mgr_res->res_id);
-			goto err;
-		}
-	}
-
-	/* INIT IFE OUT */
-	CAM_DBG(CAM_ISP, "INIT IFE OUT RESOURCES in ctx id:%d",
-		ctx->ctx_index);
-
-	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) {
-		rc = cam_ife_hw_mgr_init_hw_res(&ctx->res_list_ife_out[i]);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "Can not INIT IFE OUT (%d)",
-				 ctx->res_list_ife_out[i].res_id);
-			goto err;
-		}
-	}
+start_only:
 
 	mutex_lock(&g_ife_hw_mgr.ctx_mutex);
 	if (!atomic_fetch_inc(&g_ife_hw_mgr.active_ctx_cnt)) {
@@ -2172,12 +2220,15 @@
 		goto err;
 	}
 
-	/* Apply initial configuration */
-	CAM_DBG(CAM_ISP, "Config HW");
-	rc = cam_ife_mgr_config_hw(hw_mgr_priv, start_hw_args);
-	if (rc) {
-		CAM_ERR(CAM_ISP, "Config HW failed");
-		goto err;
+	if (!start_isp->start_only) {
+		/* Apply initial configuration */
+		CAM_DBG(CAM_ISP, "Config HW");
+		rc = cam_ife_mgr_config_hw(hw_mgr_priv,
+			&start_isp->hw_config);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Config HW failed");
+			goto err;
+		}
 	}
 
 	CAM_DBG(CAM_ISP, "START IFE OUT ... in ctx id:%d",
@@ -2229,13 +2280,18 @@
 		}
 	}
 
+	ctx->init_done = true;
 	/* Start IFE root node: do nothing */
 	CAM_DBG(CAM_ISP, "Start success for ctx id:%d", ctx->ctx_index);
+
 	return 0;
+
 err:
-	stop_hw_method.hw_stop_cmd = CAM_CSID_HALT_IMMEDIATELY;
-	stop_args.ctxt_to_hw_map = start_args->ctxt_to_hw_map;
-	stop_args.args = (void *)(&stop_hw_method);
+	stop_isp.stop_only = false;
+	stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_IMMEDIATELY;
+	stop_args.ctxt_to_hw_map = start_isp->hw_config.ctxt_to_hw_map;
+	stop_args.args = (void *)(&stop_isp);
+
 	cam_ife_mgr_stop_hw(hw_mgr_priv, &stop_args);
 	CAM_DBG(CAM_ISP, "Exit...(rc=%d)", rc);
 	return rc;
@@ -2274,6 +2330,9 @@
 	CAM_DBG(CAM_ISP, "Enter...ctx id:%d",
 		ctx->ctx_index);
 
+	if (ctx->init_done)
+		cam_ife_hw_mgr_deinit_hw(ctx);
+
 	/* we should called the stop hw before this already */
 	cam_ife_hw_mgr_release_hw_for_ctx(ctx);
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
index 0e678b4..0198f3d 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
@@ -123,6 +123,7 @@
  *                          context
  * @is_rdi_only_context     flag to specify the context has only rdi resource
  * @config_done_complete    indicator for configuration complete
+ * @init_done               indicate whether init hw is done
  */
 struct cam_ife_hw_mgr_ctx {
 	struct list_head                list;
@@ -156,6 +157,7 @@
 	atomic_t                        overflow_pending;
 	uint32_t                        is_rdi_only_context;
 	struct completion               config_done_complete;
+	bool                            init_done;
 };
 
 /**
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 8f1911e..fd71c37 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
@@ -60,13 +60,29 @@
 };
 
 /**
- * struct cam_isp_stop_hw_method - hardware stop method
+ * struct cam_isp_stop_args - hardware stop arguments
  *
  * @hw_stop_cmd:               Hardware stop command type information
+ * @stop_only                  Send stop only to hw drivers. No Deinit to be
+ *                             done.
  *
  */
-struct cam_isp_stop_hw_method {
+struct cam_isp_stop_args {
 	enum cam_isp_hw_stop_cmd      hw_stop_cmd;
+	bool                          stop_only;
+};
+
+/**
+ * struct cam_isp_start_args - isp hardware start arguments
+ *
+ * @config_args:               Hardware configuration commands.
+ * @start_only                 Send start only to hw drivers. No init to
+ *                             be done.
+ *
+ */
+struct cam_isp_start_args {
+	struct cam_hw_config_args     hw_config;
+	bool                          start_only;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
index 67b572e..206b3a3 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_bus/cam_vfe_bus_ver2.c
@@ -1131,6 +1131,9 @@
 		rsrc_data->common_data;
 
 	/* Disble WM */
+	cam_io_w_mb(0x0,
+		common_data->mem_base + rsrc_data->hw_regs->cfg);
+
 	/* Disable all register access, reply on global reset */
 	CAM_DBG(CAM_ISP, "WM res %d irq_enabled %d",
 		rsrc_data->index, rsrc_data->irq_enabled);
@@ -2291,9 +2294,10 @@
 	struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
 	struct cam_vfe_bus_ver2_reg_offset_ubwc_client *ubwc_client = NULL;
 	uint32_t *reg_val_pair;
-	uint32_t  i, j, size = 0;
+	uint32_t  i, j, k, size = 0;
 	uint32_t  frame_inc = 0, ubwc_bw_limit = 0, camera_hw_version, val;
 	int rc = 0;
+	uint32_t loop_size = 0;
 
 	bus_priv = (struct cam_vfe_bus_ver2_priv  *) priv;
 	update_buf =  (struct cam_isp_hw_get_cmd_update *) cmd_args;
@@ -2492,20 +2496,6 @@
 			}
 		}
 
-		/* WM Image address */
-		if (wm_data->en_ubwc)
-			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
-				wm_data->hw_regs->image_addr,
-				(update_buf->wm_update->image_buf[i] +
-				io_cfg->planes[i].meta_size));
-		else
-			CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
-				wm_data->hw_regs->image_addr,
-				update_buf->wm_update->image_buf[i] +
-				wm_data->offset);
-		CAM_DBG(CAM_ISP, "WM %d image address 0x%x",
-			wm_data->index, reg_val_pair[j-1]);
-
 		if (wm_data->en_ubwc) {
 			frame_inc = ALIGNUP(io_cfg->planes[i].plane_stride *
 			    io_cfg->planes[i].slice_height, 4096);
@@ -2521,6 +2511,28 @@
 				io_cfg->planes[i].slice_height;
 		}
 
+		if (wm_data->index < 3)
+			loop_size = wm_data->irq_subsample_period + 1;
+		else
+			loop_size = 1;
+
+		/* WM Image address */
+		for (k = 0; k < loop_size; k++) {
+			if (wm_data->en_ubwc)
+				CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+					wm_data->hw_regs->image_addr,
+					update_buf->wm_update->image_buf[i] +
+					io_cfg->planes[i].meta_size +
+					k * frame_inc);
+			else
+				CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+					wm_data->hw_regs->image_addr,
+					update_buf->wm_update->image_buf[i] +
+					wm_data->offset + k * frame_inc);
+			CAM_DBG(CAM_ISP, "WM %d image address 0x%x",
+				wm_data->index, reg_val_pair[j-1]);
+		}
+
 		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
 			wm_data->hw_regs->frame_inc, frame_inc);
 		CAM_DBG(CAM_ISP, "WM %d frame_inc %d",
@@ -2591,6 +2603,13 @@
 
 		wm_data = vfe_out_data->wm_res[i]->res_priv;
 
+		if (wm_data->index <= 2 && hfr_cfg->subsample_period > 3) {
+			CAM_ERR(CAM_ISP,
+				"RDI doesn't support irq subsample period %d",
+				hfr_cfg->subsample_period);
+			return -EINVAL;
+		}
+
 		if ((wm_data->framedrop_pattern !=
 			hfr_cfg->framedrop_pattern) ||
 			!wm_data->hfr_cfg_done) {
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 346cd56..61fd7a8 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
@@ -1142,24 +1142,26 @@
 }
 
 /**
- * __cam_req_mgr_sof_freeze()
+ * __cam_req_mgr_process_sof_freeze()
  *
  * @brief : Apoptosis - Handles case when connected devices are not responding
- * @data  : timer pointer
+ * @priv  : link information
+ * @data  : task data
  *
  */
-static void __cam_req_mgr_sof_freeze(unsigned long data)
+static int __cam_req_mgr_process_sof_freeze(void *priv, void *data)
 {
-	struct cam_req_mgr_timer     *timer = (struct cam_req_mgr_timer *)data;
 	struct cam_req_mgr_core_link    *link = NULL;
 	struct cam_req_mgr_core_session *session = NULL;
 	struct cam_req_mgr_message       msg;
+	int rc = 0;
 
-	if (!timer) {
-		CAM_ERR(CAM_CRM, "NULL timer");
-		return;
+	if (!data || !priv) {
+		CAM_ERR(CAM_CRM, "input args NULL %pK %pK", data, priv);
+		return -EINVAL;
 	}
-	link = (struct cam_req_mgr_core_link *)timer->parent;
+
+	link = (struct cam_req_mgr_core_link *)priv;
 	session = (struct cam_req_mgr_core_session *)link->parent;
 
 	CAM_ERR(CAM_CRM, "SOF freeze for session %d link 0x%x",
@@ -1173,12 +1175,47 @@
 	msg.u.err_msg.request_id = 0;
 	msg.u.err_msg.link_hdl   = link->link_hdl;
 
+	rc = cam_req_mgr_notify_message(&msg,
+		V4L_EVENT_CAM_REQ_MGR_ERROR, V4L_EVENT_CAM_REQ_MGR_EVENT);
 
-	if (cam_req_mgr_notify_message(&msg,
-		V4L_EVENT_CAM_REQ_MGR_ERROR, V4L_EVENT_CAM_REQ_MGR_EVENT))
+	if (rc)
 		CAM_ERR(CAM_CRM,
-			"Error notifying SOF freeze for session %d link 0x%x",
-			session->session_hdl, link->link_hdl);
+			"Error notifying SOF freeze for session %d link 0x%x rc %d",
+			session->session_hdl, link->link_hdl, rc);
+
+	return rc;
+}
+
+/**
+ * __cam_req_mgr_sof_freeze()
+ *
+ * @brief : Callback function for timer timeout indicating SOF freeze
+ * @data  : timer pointer
+ *
+ */
+static void __cam_req_mgr_sof_freeze(unsigned long data)
+{
+	struct cam_req_mgr_timer     *timer = (struct cam_req_mgr_timer *)data;
+	struct crm_workq_task               *task = NULL;
+	struct cam_req_mgr_core_link        *link = NULL;
+	struct crm_task_payload             *task_data;
+
+	if (!timer) {
+		CAM_ERR(CAM_CRM, "NULL timer");
+		return;
+	}
+
+	link = (struct cam_req_mgr_core_link *)timer->parent;
+	task = cam_req_mgr_workq_get_task(link->workq);
+	if (!task) {
+		CAM_ERR(CAM_CRM, "No empty task");
+		return;
+	}
+
+	task_data = (struct crm_task_payload *)task->payload;
+	task_data->type = CRM_WORKQ_TASK_NOTIFY_FREEZE;
+	task->process_cb = &__cam_req_mgr_process_sof_freeze;
+	cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0);
 }
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
index 025c16a..68ec09b 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
@@ -45,6 +45,7 @@
 	CRM_WORKQ_TASK_APPLY_REQ,
 	CRM_WORKQ_TASK_NOTIFY_SOF,
 	CRM_WORKQ_TASK_NOTIFY_ERR,
+	CRM_WORKQ_TASK_NOTIFY_FREEZE,
 	CRM_WORKQ_TASK_SCHED_REQ,
 	CRM_WORKQ_TASK_FLUSH_REQ,
 	CRM_WORKQ_TASK_INVALID,
diff --git a/drivers/media/platform/msm/qca402/Makefile b/drivers/media/platform/msm/qca402/Makefile
new file mode 100644
index 0000000..cffd2c4
--- /dev/null
+++ b/drivers/media/platform/msm/qca402/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for MSM HTC driver.
+#
+obj-y += msm_qca402.o
diff --git a/drivers/media/platform/msm/qca402/msm_qca402.c b/drivers/media/platform/msm/qca402/msm_qca402.c
new file mode 100644
index 0000000..74b4929
--- /dev/null
+++ b/drivers/media/platform/msm/qca402/msm_qca402.c
@@ -0,0 +1,1530 @@
+/* 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 <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/of_device.h>
+#include <uapi/media/msmb_qca.h>
+#include <linux/spinlock_types.h>
+#include "msm_qca402.h"
+
+#define DEVICE_NAME "msm_qca402char"
+#define DEVICE_CLASS "msm_qca402"
+#define MAX_DEVICE_NUM (1)
+#define QCA402_START_ENQ_BUFFS (8)
+#define QCA402_MAX_EVENTS_IN_MSG (16)
+#undef  pr_fmt
+#define pr_fmt(fmt) "[qca402x]: %s: " fmt, __func__
+
+static int msm_qca402_major;
+static struct class *msm_qca402_class;
+struct msm_qca402_device_t {
+	struct msm_qca402_dev_data_t *dev;
+	struct task_struct *user_task;
+	struct task_struct *recv_task;
+};
+
+static struct msm_qca402_device_t msm_qca402_device[MAX_DEVICE_NUM];
+
+static const struct of_device_id msm_qca402_dt_match[] = {
+	{
+		.compatible = "qcom,qca402",
+	},
+	{}
+};
+MODULE_DEVICE_TABLE(of, msm_qca402_dt_match);
+
+static int msm_qca402_open(struct inode *ip, struct file *fp)
+{
+	struct msm_qca402_dev_data_t *dev_data = container_of(ip->i_cdev,
+				struct msm_qca402_dev_data_t, cdev);
+	struct msm_qca402_file_data_t *file_data;
+	struct file_data_list_t *f_entry;
+
+	pr_debug("called for device %d\n", dev_data->dev_idx);
+
+	file_data = kzalloc(sizeof(*file_data), GFP_KERNEL);
+	if (!file_data)
+		return -EINVAL;
+	pr_debug("Out q %pK", &file_data->out_queue);
+	init_waitqueue_head(&file_data->out_queue);
+	/* initialize channel list here */
+	file_data->dev_data = dev_data;
+	INIT_LIST_HEAD(&file_data->evt_list);
+	INIT_LIST_HEAD(&file_data->ready_ch_list);
+	mutex_init(&file_data->file_mutex);
+	f_entry = kzalloc(sizeof(*f_entry), GFP_KERNEL);
+	if (!f_entry) {
+		mutex_destroy(&file_data->file_mutex);
+		kfree(file_data);
+		return -EINVAL;
+	}
+	f_entry->file_data = file_data;
+	list_add_tail(&f_entry->list, &dev_data->file_list);
+	fp->private_data = file_data;
+	return 0;
+}
+
+static void msm_qca402_free_file_data(struct msm_qca402_file_data_t *file_data)
+{
+	struct msm_qca402_evt_list_t *cur_evt, *next_evt;
+	struct msm_qca402_ready_list_t *cur_rch, *next_rch;
+
+	list_for_each_entry_safe(cur_evt, next_evt, &file_data->evt_list,
+				 list) {
+		list_del_init(&cur_evt->list);
+		kfree(cur_evt);
+		break;
+	}
+	list_for_each_entry_safe(cur_rch, next_rch, &file_data->ready_ch_list,
+			list) {
+		list_del_init(&cur_rch->list);
+		kfree(cur_rch);
+		break;
+	}
+	mutex_destroy(&file_data->file_mutex);
+	kfree(file_data);
+}
+
+static void msm_qca402_release_file(struct msm_qca402_dev_data_t *dev_data,
+		struct msm_qca402_file_data_t *file_data)
+{
+	struct file_data_list_t *f_entry;
+	struct file_data_list_t *next;
+
+	list_for_each_entry_safe(f_entry, next, &dev_data->file_list, list) {
+		if (!file_data || f_entry->file_data == file_data) {
+			list_del_init(&f_entry->list);
+			msm_qca402_free_file_data(f_entry->file_data);
+			kfree(f_entry);
+			break;
+		}
+	}
+}
+
+static int msm_qca402_release(struct inode *ip, struct file *fp)
+{
+	struct msm_qca402_file_data_t *file_data =
+		(struct msm_qca402_file_data_t *)fp->private_data;
+	struct msm_qca402_dev_data_t *dev_data = container_of(ip->i_cdev,
+				struct msm_qca402_dev_data_t, cdev);
+
+	pr_debug("called\n");
+
+	msm_qca402_release_file(dev_data, file_data);
+
+	return 0;
+}
+
+static struct msm_qca402_channel_list_t *msm_qca402_init_channel(
+		struct msm_qca402_dev_data_t *dev_data,
+		__u32 channel_id)
+{
+	struct msm_qca402_channel_list_t *channel = NULL;
+	struct msm_qca402_channel_list_t *new_channel = NULL;
+
+	list_for_each_entry(channel, &dev_data->channel_list, list) {
+		if (channel->channel_id == channel_id) {
+			channel->ref_cnt++;
+			pr_debug("channel with %d exists\n", channel_id);
+			return channel;
+		}
+	}
+	new_channel = kzalloc(sizeof(*new_channel), GFP_KERNEL);
+	if (!new_channel)
+		return NULL;
+	new_channel->channel_id = channel_id;
+	INIT_LIST_HEAD(&new_channel->enqueued_list);
+	INIT_LIST_HEAD(&new_channel->ready_list);
+	INIT_LIST_HEAD(&new_channel->dequeued_list);
+	list_add_tail(&new_channel->list, &dev_data->channel_list);
+	new_channel->ref_cnt = 1;
+	return new_channel;
+}
+
+static void msm_qca402_free_buffer_list(struct msm_qca402_dev_data_t *dev_data,
+					struct list_head  *buffer_list)
+{
+	struct msm_qca402_buffer_list_t *buffer;
+	struct msm_qca402_buffer_list_t *n_buffer;
+
+	list_for_each_entry_safe(buffer, n_buffer, buffer_list, list) {
+		if (buffer->ih)
+			ion_unmap_kernel(dev_data->ion_client, buffer->ih);
+		list_del_init(&buffer->list);
+		kfree(buffer);
+	}
+}
+
+static int msm_qca402_deinit_channel(
+		struct msm_qca402_dev_data_t *dev_data,
+		__u32 channel_id)
+{
+	struct msm_qca402_channel_list_t *channel;
+	struct msm_qca402_channel_list_t *c_channel = NULL;
+
+	list_for_each_entry(channel, &dev_data->channel_list, list) {
+		if (channel->channel_id == channel_id) {
+			c_channel = channel;
+			break;
+		}
+	}
+	if (!c_channel) {
+		pr_debug("No channel %d\n", channel_id);
+		return -EINVAL;
+	}
+	c_channel->ref_cnt--;
+	if (channel->ref_cnt)
+		return 0;
+	msm_qca402_free_buffer_list(dev_data, &channel->enqueued_list);
+	msm_qca402_free_buffer_list(dev_data, &channel->ready_list);
+	msm_qca402_free_buffer_list(dev_data, &channel->dequeued_list);
+	list_del_init(&channel->list);
+	kfree(channel);
+	return 0;
+}
+
+static void msm_qca402_unregister_events(
+		struct msm_qca402_file_data_t *file_data, int num_events,
+		struct msm_qca_event_type *evts)
+{
+	int i;
+	struct msm_qca402_evt_list_t *c_evt_entry;
+	struct msm_qca402_evt_list_t *next;
+
+	for (i = 0; i < num_events; i++) {
+		list_for_each_entry_safe(c_evt_entry, next,
+						&file_data->evt_list, list) {
+			if (c_evt_entry->channel_id == evts[i].channel_id &&
+				c_evt_entry->cmd == evts[i].cmd) {
+				pr_debug("%pK Unregistering %d %d\n", file_data,
+					c_evt_entry->channel_id,
+					c_evt_entry->cmd);
+				msm_qca402_deinit_channel(file_data->dev_data,
+						evts[i].channel_id);
+				list_del_init(&c_evt_entry->list);
+				kfree(c_evt_entry);
+				break;
+			}
+		}
+	}
+}
+
+static int msm_qca402_register_events(struct msm_qca402_file_data_t *file_data,
+				int num_events,
+				struct msm_qca_event_type *evts)
+{
+	int i;
+	int ret = 0;
+	struct msm_qca402_evt_list_t *c_evt_entry;
+
+	for (i = 0; i < num_events; i++) {
+		c_evt_entry = kzalloc(sizeof(*c_evt_entry), GFP_KERNEL);
+		if (!c_evt_entry) {
+			ret = -ENOMEM;
+			break;
+		}
+		c_evt_entry->channel_id = evts[i].channel_id;
+		c_evt_entry->cmd = evts[i].cmd;
+		pr_debug("%pK Registering %d %d\n", file_data,
+			c_evt_entry->channel_id, c_evt_entry->cmd);
+		list_add_tail(&c_evt_entry->list, &file_data->evt_list);
+		msm_qca402_init_channel(file_data->dev_data,
+			evts[i].channel_id);
+	}
+
+	if (ret)
+		msm_qca402_unregister_events(file_data, num_events, evts);
+
+	return ret;
+}
+
+static void msm_qca402_free_workbuffs(struct msm_qca402_dev_data_t *dev_data)
+{
+	struct msm_qca402_workbuff_list_t *wb;
+	struct msm_qca402_workbuff_list_t *next;
+
+	list_for_each_entry_safe(wb, next, &dev_data->work_list, list) {
+		list_del_init(&wb->list);
+		kfree(wb);
+	}
+}
+
+static int msm_qca402_alloc_add_workbuffs(
+	struct msm_qca402_dev_data_t *dev_data,
+	__u32 num_buffs)
+{
+	int ret = 0;
+	int i;
+	struct msm_qca402_workbuff_list_t *wb;
+
+	for (i = 0; i < num_buffs; i++) {
+		wb = kzalloc(sizeof(*wb), GFP_KERNEL);
+		if (!wb) {
+			ret = -ENOMEM;
+			msm_qca402_free_workbuffs(dev_data);
+			break;
+		}
+		list_add_tail(&wb->list, &dev_data->work_list);
+	}
+	return ret;
+}
+
+static struct msm_qca402_workbuff_list_t *msm_qca402_get_workbuff(
+	struct msm_qca402_dev_data_t *dev_data)
+{
+	int ret;
+	struct msm_qca402_workbuff_list_t *wb;
+
+	if (list_empty(&dev_data->work_list)) {
+		ret = msm_qca402_alloc_add_workbuffs(dev_data, 1);
+		if (ret)
+			return NULL;
+	}
+	wb = list_first_entry(&dev_data->work_list,
+		struct msm_qca402_workbuff_list_t, list);
+	list_del_init(&wb->list);
+	return wb;
+}
+
+static void msm_qca402_propagate_event(struct msm_qca402_dev_data_t *dev_data,
+				struct msm_qca_event_type *event,
+				struct msm_qca402_channel_list_t *channel)
+{
+	struct msm_qca402_file_data_t *file_data;
+	struct file_data_list_t *f_entry;
+	struct msm_qca402_evt_list_t *e_entry;
+	struct msm_qca402_ready_list_t *r_entry;
+
+	list_for_each_entry(f_entry, &dev_data->file_list, list) {
+		file_data = f_entry->file_data;
+		list_for_each_entry(e_entry, &file_data->evt_list, list) {
+			if (e_entry->channel_id == event->channel_id &&
+				e_entry->cmd == event->cmd) {
+				/**
+				 * put event into queue
+				 * unblock poll
+				 */
+				pr_debug("%d %d\n", event->channel_id,
+						e_entry->cmd);
+				r_entry = kzalloc(sizeof(*r_entry), GFP_KERNEL);
+				if (!r_entry)
+					return;
+
+				channel->ref_cnt += 1;
+				r_entry->ch_data = channel;
+				r_entry->cmd = e_entry->cmd;
+				list_add_tail(&r_entry->list,
+						&file_data->ready_ch_list);
+				pr_debug("called\n");
+				wake_up_interruptible(&file_data->out_queue);
+			}
+		}
+	}
+}
+
+static int msm_qca402_copy_data(struct msm_qca402_htca_message_t *htca_msg,
+		struct msm_qca402_buffer_list_t *buffer,
+		__u32 size)
+{
+
+	__u32 c_payload_size = 0;
+	__u32 c_meta_size = 0;
+
+	if (size < (QCA_MSG_HEADER_SIZE + htca_msg->header.meta_size))
+		return -EINVAL;
+	c_payload_size = size - htca_msg->header.meta_size -
+		QCA_MSG_HEADER_SIZE;
+
+
+	switch (htca_msg->header.msg_flags & LPCHTCA_PACKET_MASK) {
+	case LPCHTCA_FULL_PACKET:
+	case LPCHTCA_START_PACKET: {
+		if (buffer->valid_size > 0)
+			buffer->valid_size = 0;
+		if ((htca_msg->header.meta_size >
+					buffer->qca_msg.header_size) ||
+			(c_payload_size > buffer->qca_msg.data_size))
+			return -EINVAL;
+		c_meta_size = htca_msg->header.meta_size;
+	}
+		break;
+
+	case LPCHTCA_END_PACKET:
+	case LPCHTCA_MID_PACKET:
+		if (c_payload_size + buffer->valid_size >
+			buffer->qca_msg.data_size) {
+			/* indicate ERROR here */
+			return -EINVAL;
+		}
+		break;
+	case LPCHTCA_UNSPEC_PACKET:
+		if (c_payload_size + buffer->valid_size >
+			buffer->qca_msg.data_size) {
+			if (buffer->valid_size)
+				/* continue in next buffer */
+				return -ENOMEM;
+			else
+				return -EINVAL;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (c_meta_size)
+		if (copy_to_user((void __user *)
+					(uintptr_t)buffer->qca_msg.header,
+				htca_msg->payload,
+				c_meta_size))
+			return -EFAULT;
+
+	if (c_payload_size) {
+		__u8 *ptr;
+
+		if (buffer->vaddr) {
+			/* ion buffer */
+			ptr = (__u8 *)buffer->vaddr;
+			ptr += buffer->valid_size;
+			memcpy((void *)ptr,
+				&htca_msg->payload[htca_msg->header.meta_size],
+				c_payload_size);
+		} else {
+			ptr = (__u8 *)((uintptr_t)buffer->qca_msg.buff_addr);
+			ptr += buffer->valid_size;
+			if (copy_to_user((void __user *)ptr,
+				&htca_msg->payload[htca_msg->header.meta_size],
+				c_payload_size))
+				return -EFAULT;
+		}
+		buffer->valid_size += c_payload_size;
+	}
+
+	switch (htca_msg->header.msg_flags & LPCHTCA_PACKET_MASK) {
+	case LPCHTCA_START_PACKET: {
+		buffer->qca_msg.header_size = c_meta_size;
+	}
+		break;
+
+	case LPCHTCA_FULL_PACKET: {
+		buffer->qca_msg.header_size = c_meta_size;
+		buffer->qca_msg.data_size = buffer->valid_size;
+	}
+		break;
+
+	case LPCHTCA_END_PACKET: {
+		buffer->qca_msg.data_size = buffer->valid_size;
+	}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int msm_qca402_move_userbuff_to_(struct list_head *target_list,
+		struct msm_qca402_channel_list_t *ch_data)
+{
+	struct msm_qca402_buffer_list_t *c_entry;
+
+	c_entry = ch_data->current_entry;
+	if (c_entry) {
+		list_del_init(&c_entry->list);
+		list_add_tail(&c_entry->list, target_list);
+	}
+	ch_data->current_entry = NULL;
+	if (!list_empty(&ch_data->enqueued_list)) {
+		ch_data->current_entry = list_first_entry(
+			&ch_data->enqueued_list,
+			struct msm_qca402_buffer_list_t, list);
+	}
+	return 0;
+}
+
+static int msm_qca402_process_htca_message(
+		struct msm_qca402_dev_data_t *dev_data,
+		struct msm_qca402_workbuff_list_t *wb)
+{
+	int ret = 0;
+	int keep = 0;
+	__u8 pkt_flags;
+	struct msm_qca402_htca_message_t *htca_msg = &wb->htca_msg;
+	struct msm_qca402_channel_list_t *ch_data_cur;
+	struct msm_qca402_channel_list_t *ch_data = NULL;
+
+	pr_debug("wb %pK %d\n", htca_msg,
+			htca_msg->header.channel_id);
+	list_for_each_entry(ch_data_cur, &dev_data->channel_list, list) {
+		if (ch_data_cur->channel_id == htca_msg->header.channel_id) {
+			ch_data = ch_data_cur;
+			break;
+		}
+	}
+	if (!ch_data && !(htca_msg->header.msg_flags & LPCHTCA_ASYNC_MESSAGE)) {
+		/* No registered handler and not ASYNC message, drop packet */
+		goto return_wb;
+	} else if (!ch_data) {
+		/* if ASYNC message with no registered handler, add it */
+		ch_data = msm_qca402_init_channel(dev_data,
+				htca_msg->header.channel_id);
+		if (!ch_data)
+			return -EINVAL;
+	}
+	if (!ch_data->has_buff &&
+			!(htca_msg->header.msg_flags & LPCHTCA_FULL_PACKET)) {
+		/* data packet but no free enqueued buffers, drop packet */
+		/* indicate ERROR here */
+		goto return_wb;
+	} else if (ch_data->has_buff) {
+		if (!ch_data->current_entry) {
+			pr_debug("NO CURRENT ENTRY\n");
+			return -EINVAL;
+		}
+		/* data packet and there is enqueued buffer start filling it */
+		ret = msm_qca402_copy_data(htca_msg, ch_data->current_entry,
+				wb->size);
+		pkt_flags = htca_msg->header.msg_flags & LPCHTCA_PACKET_MASK;
+		if ((pkt_flags == LPCHTCA_UNSPEC_PACKET && ret == -ENOMEM) ||
+			(pkt_flags == LPCHTCA_FULL_PACKET) ||
+			(pkt_flags == LPCHTCA_END_PACKET) ||
+			(htca_msg->header.msg_flags &
+					LPCHTCA_END_TRANSMISSON)) {
+			struct msm_qca_event_type event;
+
+			event.cmd = MSM_QCA_EVENT_ENQ_BUF;
+			event.channel_id = ch_data->channel_id;
+			msm_qca402_move_userbuff_to_(&ch_data->ready_list,
+					ch_data);
+			msm_qca402_propagate_event(dev_data, &event, ch_data);
+		}
+		if (ret == -ENOMEM) {
+			ret = msm_qca402_copy_data(htca_msg,
+				ch_data->current_entry, wb->size);
+		}
+	} else {
+		struct msm_qca_event_type event;
+
+		/* control message, save for future receiving */
+		keep = 1;
+		ch_data->wbout = wb;
+		event.cmd = MSM_QCA_EVENT_RECV_MSG;
+		event.channel_id = ch_data->channel_id;
+		msm_qca402_propagate_event(dev_data, &event, ch_data);
+	}
+
+return_wb:
+	if (!keep)
+		list_add_tail(&wb->list, &dev_data->work_list);
+	return ret;
+}
+
+static struct msm_qca402_channel_list_t *msm_qca402_find_channel(
+		struct msm_qca402_dev_data_t *dev_data,
+		__u32 channel_id)
+{
+	struct msm_qca402_channel_list_t *ch_data;
+
+	list_for_each_entry(ch_data, &dev_data->channel_list, list) {
+		if (ch_data->channel_id == channel_id)
+			return ch_data;
+	}
+
+	return NULL;
+}
+
+static int msm_qca402_copy_header(struct msm_qca402_dev_data_t *dev_data,
+		struct msm_qca402_buffer_list_t *buff,
+		struct msm_qca_message_type *data)
+{
+		buff->wbb = msm_qca402_get_workbuff(dev_data);
+		if (!buff->wbb)
+			return -ENOMEM;
+
+		if (data->header_size <= QCA_MSG_PAYLOAD_SIZE) {
+			if (copy_from_user(
+				(void *)&buff->wbb->htca_msg.payload[0],
+				(void __user *)(uintptr_t)data->header,
+				data->header_size))
+				return -EFAULT;
+			buff->wbb->htca_msg.header.meta_size =
+				data->header_size;
+		} else
+			return -EINVAL;
+		return 0;
+}
+
+static struct msm_qca402_buffer_list_t *msm_qca402_deq_map_buff(
+		struct msm_qca402_dev_data_t *dev_data,
+		struct msm_qca402_channel_list_t *ch_data,
+		struct msm_qca_message_type *data)
+{
+	int ret;
+	struct msm_qca402_buffer_list_t *buff;
+
+	list_for_each_entry(buff, &ch_data->dequeued_list, list) {
+		if (buff->qca_msg.fd == data->fd) {
+			list_del_init(&buff->list);
+			if (!ch_data->has_buff) {
+				ret = msm_qca402_copy_header(dev_data, buff,
+						data);
+				if (ret < 0)
+					return NULL;
+			}
+			buff->qca_msg = *data;
+			return buff;
+		}
+	}
+	buff = kzalloc(sizeof(*buff), GFP_KERNEL);
+	if (!buff)
+		return NULL;
+	if (!ch_data->has_buff) {
+		ret = msm_qca402_copy_header(dev_data, buff, data);
+		if (ret < 0)
+			return NULL;
+	}
+	buff->qca_msg = *data;
+	if (data->is_ion_data) {
+		buff->ih = ion_import_dma_buf_fd(dev_data->ion_client,
+				data->fd);
+		buff->vaddr = ion_map_kernel(dev_data->ion_client, buff->ih);
+	}
+
+	return buff;
+}
+
+static unsigned int msm_qca402_recv_message(
+		struct msm_qca402_file_data_t *file,
+		struct msm_qca_message_type *data)
+{
+	struct msm_qca402_channel_list_t *channel;
+	struct msm_qca402_ready_list_t *rq_entry;
+	struct msm_qca402_buffer_list_t *buffer;
+	int ret = 0;
+
+	if (list_empty(&file->ready_ch_list))
+		return -ENODATA;
+	rq_entry = list_first_entry(&file->ready_ch_list,
+		struct msm_qca402_ready_list_t, list);
+	channel = rq_entry->ch_data;
+	list_del_init(&rq_entry->list);
+	kfree(rq_entry);
+
+	if (!list_empty(&channel->ready_list)) {
+		buffer = list_first_entry(&channel->ready_list,
+			struct msm_qca402_buffer_list_t, list);
+		*data = buffer->qca_msg;
+		if (channel->has_buff)
+			data->cmd = MSM_QCA_EVENT_ENQ_BUF;
+		else
+			data->cmd = MSM_QCA_EVENT_SEND_MSG;
+		list_del_init(&buffer->list);
+		buffer->valid_size = 0;
+		channel->ref_cnt--;
+		list_add_tail(&buffer->list, &channel->dequeued_list);
+	} else if (channel->wbout) {
+		data->channel_id = channel->channel_id;
+		data->is_ion_data = 0;
+		data->data_size = 0;
+		if (data->header_size >=
+			channel->wbout->htca_msg.header.meta_size) {
+			data->header_size =
+				channel->wbout->htca_msg.header.meta_size;
+			data->cmd = MSM_QCA_EVENT_RECV_MSG;
+			if (copy_to_user((void __user *)(uintptr_t)data->header,
+				channel->wbout->htca_msg.payload,
+				channel->wbout->htca_msg.header.meta_size)) {
+				list_add_tail(&channel->wbout->list,
+						&file->dev_data->work_list);
+				return -EFAULT;
+			}
+			channel->ref_cnt--;
+			list_add_tail(&channel->wbout->list,
+					&file->dev_data->work_list);
+		} else {
+			ret = -EINVAL;
+		}
+	}
+
+	return ret;
+}
+
+static __u8 msm_qca402_fill_wb(
+		struct msm_qca402_buffer_list_t *buff,
+		struct msm_qca402_workbuff_list_t *wb)
+{
+	__u32 total_size = buff->qca_msg.header_size +
+		buff->qca_msg.data_size;
+	__u32 write_size = 0;
+	__u8 *ptr;
+
+	wb->htca_msg.header.msg_flags = 0;
+
+	wb->htca_msg.header.channel_id = buff->qca_msg.channel_id;
+
+	pr_debug("valid size %d total %d\n", buff->valid_size, total_size);
+	if (buff->valid_size == 0) {
+		if (total_size <= QCA_MSG_PAYLOAD_SIZE)
+			wb->htca_msg.header.msg_flags = LPCHTCA_FULL_PACKET;
+		else
+			wb->htca_msg.header.msg_flags = LPCHTCA_START_PACKET;
+		write_size = min(QCA_MSG_PAYLOAD_SIZE -
+					wb->htca_msg.header.meta_size,
+				buff->qca_msg.data_size);
+	} else {
+		wb->htca_msg.header.meta_size = 0;
+		if (total_size - buff->valid_size <= QCA_MSG_PAYLOAD_SIZE)
+			wb->htca_msg.header.msg_flags = LPCHTCA_END_PACKET;
+		else
+			wb->htca_msg.header.msg_flags = LPCHTCA_MID_PACKET;
+		write_size = min(QCA_MSG_PAYLOAD_SIZE,
+				buff->qca_msg.data_size - buff->valid_size);
+	}
+	if (buff->vaddr) {
+		ptr = (__u8 *)buff->vaddr + buff->valid_size;
+		memcpy(&wb->htca_msg.payload[wb->htca_msg.header.meta_size],
+				(void *)ptr, write_size);
+	} else {
+		ptr = (__u8 *)((uintptr_t)buff->qca_msg.buff_addr) +
+				buff->valid_size;
+		if (copy_from_user(
+			&wb->htca_msg.payload[wb->htca_msg.header.meta_size],
+			(void __user *)ptr, write_size))
+			return -EFAULT;
+	}
+	buff->valid_size += write_size;
+	wb->size = QCA_MSG_HEADER_SIZE + wb->htca_msg.header.meta_size +
+		write_size;
+	if (buff->qca_msg.last_data &&
+		((wb->htca_msg.header.msg_flags == LPCHTCA_FULL_PACKET) ||
+		(wb->htca_msg.header.msg_flags == LPCHTCA_END_PACKET)))
+		wb->htca_msg.header.msg_flags |= LPCHTCA_END_TRANSMISSON;
+
+	pr_debug("flags %x\n", wb->htca_msg.header.msg_flags);
+	return wb->htca_msg.header.msg_flags;
+}
+static unsigned int msm_qca402_process_wb(
+	struct msm_qca402_dev_data_t *dev_data,
+	struct msm_qca402_channel_list_t *ch_data,
+	struct msm_qca402_buffer_list_t *buff,
+	struct msm_qca402_workbuff_list_t **wb)
+{
+	__u8 flags;
+	struct msm_qca_event_type event;
+
+	if (!*wb)
+		*wb = msm_qca402_get_workbuff(dev_data);
+
+	flags = msm_qca402_fill_wb(buff, *wb);
+
+	if ((flags & LPCHTCA_PACKET_MASK) == LPCHTCA_FULL_PACKET ||
+		(flags & LPCHTCA_PACKET_MASK) == LPCHTCA_END_PACKET) {
+		msm_qca402_move_userbuff_to_(&ch_data->ready_list,
+				ch_data);
+		event.cmd = MSM_QCA_EVENT_SEND_MSG;
+		event.channel_id = ch_data->channel_id;
+		msm_qca402_propagate_event(dev_data, &event, ch_data);
+		return 1;
+	}
+
+	return 0;
+}
+
+static unsigned int msm_qca402_send_htca_message(
+	struct msm_qca402_dev_data_t *dev_data,
+	struct msm_qca402_channel_list_t *ch_data)
+{
+	int status;
+	int ret;
+	struct msm_qca402_buffer_list_t *buff = ch_data->current_entry;
+	struct msm_qca402_workbuff_list_t *wb = NULL;
+
+
+	wb = ch_data->wbin;
+	if (!wb) {
+		if (!buff)
+			return -EINVAL;
+		wb = buff->wbb;
+		if (!wb) {
+			pr_err("Incorrect header error\n");
+			return -EINVAL;
+		}
+		ret = msm_qca402_process_wb(dev_data, ch_data, buff,
+				&wb);
+		if (!wb)
+			return -EINVAL;
+		buff->wbb = NULL;
+	}
+
+	pr_debug("send %d\n", wb->size);
+	dev_data->sending++;
+	status = htca_buffer_send(dev_data->htca_target, 0,
+			(void *)&wb->htca_msg.header, wb->size, wb);
+	ch_data->wbin = NULL;
+	if (status)
+		return -EINVAL;
+	if (((wb->htca_msg.header.msg_flags & LPCHTCA_PACKET_MASK) ==
+				LPCHTCA_FULL_PACKET) ||
+		((wb->htca_msg.header.msg_flags & LPCHTCA_PACKET_MASK) ==
+				LPCHTCA_END_PACKET)) {
+		return 0;
+	}
+
+	if (!buff)
+		return -EINVAL;
+	ret = msm_qca402_process_wb(dev_data, ch_data, buff, &ch_data->wbin);
+
+	return -EAGAIN;
+}
+
+
+static unsigned int msm_qca402_poll(struct file *fp, poll_table *wait)
+{
+	struct msm_qca402_file_data_t *file_data =
+		(struct msm_qca402_file_data_t *)fp->private_data;
+	unsigned int mask = 0;
+
+	pr_debug("called %pK\n", &file_data->out_queue);
+	poll_wait(fp, &file_data->out_queue, wait);
+	if (!list_empty(&file_data->ready_ch_list))
+		mask = POLLIN | POLLRDNORM;
+	return mask;
+}
+
+static struct msm_qca_event_type *msm_qca402_alloc_get_evts(
+		struct msm_qca_event_list_type *evt_list)
+{
+	int len = sizeof(struct msm_qca_event_type) *
+				evt_list->num_events;
+	struct msm_qca_event_type *evts;
+
+	if (evt_list->num_events > QCA402_MAX_EVENTS_IN_MSG)
+		return NULL;
+	evts = kzalloc(len, GFP_KERNEL);
+	if (!evts)
+		return NULL;
+	if (copy_from_user((void *)evts,
+			(void __user *)(uintptr_t)evt_list->events,
+			len)) {
+		kfree(evts);
+		return NULL;
+	}
+	return evts;
+}
+
+static int msm_qca402_abort(struct msm_qca402_file_data_t *file_data,
+	int num_events, struct msm_qca_event_type *evts) {
+	return 0;
+}
+
+static int msm_qca402_flush(struct msm_qca402_file_data_t *file_data,
+	int num_events, struct msm_qca_event_type *evts) {
+	return 0;
+}
+
+static long msm_qca402_ioctl(struct file *file, unsigned int cmd,
+		void *arg)
+{
+	struct msm_qca402_file_data_t *file_data =
+		(struct msm_qca402_file_data_t *)file->private_data;
+	long ret = 0;
+
+	switch (cmd) {
+	case MSM_QCA402X_ENQUEUE_BUFFER: {
+		struct msm_qca_message_type *data =
+			(struct msm_qca_message_type *)arg;
+		struct msm_qca402_buffer_list_t *buff;
+		struct msm_qca402_channel_list_t *ch_data;
+
+		pr_debug("MSM_QCA402X_ENQUEUE_BUFFER\n");
+		mutex_lock(&file_data->dev_data->dev_mutex);
+		ch_data = msm_qca402_find_channel(file_data->dev_data,
+				data->channel_id);
+		if (!ch_data) {
+			mutex_unlock(&file_data->dev_data->dev_mutex);
+			return -EINVAL;
+		}
+		ch_data->has_buff = 1;
+		buff = msm_qca402_deq_map_buff(file_data->dev_data, ch_data,
+				data);
+		if (!buff) {
+			mutex_unlock(&file_data->dev_data->dev_mutex);
+			return -ENOMEM;
+		}
+		list_add_tail(&buff->list, &ch_data->enqueued_list);
+		if (!ch_data->current_entry)
+			ch_data->current_entry = list_first_entry(
+				&ch_data->enqueued_list,
+				struct msm_qca402_buffer_list_t, list);
+		mutex_unlock(&file_data->dev_data->dev_mutex);
+	}
+		break;
+	case MSM_QCA402X_SEND_MESSAGE: {
+		struct msm_qca_message_type *data =
+			(struct msm_qca_message_type *)arg;
+		struct msm_qca402_buffer_list_t *buff;
+		struct msm_qca402_channel_list_t *ch_data;
+		struct msm_qca402_ready_list_t *r_entry;
+
+		pr_debug("MSM_QCA402X_SEND_MESSAGE\n");
+		mutex_lock(&file_data->dev_data->dev_mutex);
+		ch_data = msm_qca402_find_channel(file_data->dev_data,
+				data->channel_id);
+		if (!ch_data) {
+			mutex_unlock(&file_data->dev_data->dev_mutex);
+			return -EINVAL;
+		}
+		ch_data->has_buff = 0;
+		buff = msm_qca402_deq_map_buff(file_data->dev_data, ch_data,
+				data);
+		if (!buff) {
+			mutex_unlock(&file_data->dev_data->dev_mutex);
+			return -ENOMEM;
+		}
+		r_entry = kzalloc(sizeof(*r_entry), GFP_KERNEL);
+		if (!r_entry) {
+			list_add_tail(&buff->list, &ch_data->dequeued_list);
+			mutex_unlock(&file_data->dev_data->dev_mutex);
+			return -ENOMEM;
+		}
+		ch_data->ref_cnt += 1;
+		list_add_tail(&buff->list, &ch_data->enqueued_list);
+		r_entry->ch_data = ch_data;
+		list_add_tail(&r_entry->list, &file_data->dev_data->in_list);
+		if (!ch_data->current_entry)
+			ch_data->current_entry = list_first_entry(
+				&ch_data->enqueued_list,
+				struct msm_qca402_buffer_list_t, list);
+		mutex_unlock(&file_data->dev_data->dev_mutex);
+
+		wake_up_interruptible(&file_data->dev_data->in_queue);
+	}
+		break;
+	case MSM_QCA402X_RECEIVE_MESSAGE: {
+		struct msm_qca_message_type *data =
+			(struct msm_qca_message_type *)arg;
+		pr_debug("MSM_QCA402X_RECEIVE_MESSAGE\n");
+		mutex_lock(&file_data->dev_data->dev_mutex);
+		ret = msm_qca402_recv_message(file_data, data);
+		mutex_unlock(&file_data->dev_data->dev_mutex);
+	}
+		break;
+	case MSM_QCA402X_REGISTER_EVENT: {
+		struct msm_qca_event_list_type *evt_list =
+			(struct msm_qca_event_list_type *)arg;
+		struct msm_qca_event_type *evts;
+
+		pr_debug("MSM_QCA402X_REGISTER_EVENT\n");
+
+		evts = msm_qca402_alloc_get_evts(evt_list);
+		if (!evts)
+			return -ENOMEM;
+		mutex_lock(&file_data->dev_data->dev_mutex);
+		ret = msm_qca402_register_events(file_data,
+						 evt_list->num_events,
+						 evts);
+		mutex_unlock(&file_data->dev_data->dev_mutex);
+		kfree(evts);
+	}
+		break;
+	case MSM_QCA402X_UNREGISTER_EVENT: {
+		struct msm_qca_event_list_type *evt_list =
+			(struct msm_qca_event_list_type *)arg;
+		struct msm_qca_event_type *evts;
+
+		pr_debug("MSM_QCA402X_UNREGISTER_EVENT\n");
+
+		evts = msm_qca402_alloc_get_evts(evt_list);
+		if (!evts)
+			return -ENOMEM;
+		mutex_lock(&file_data->dev_data->dev_mutex);
+		msm_qca402_unregister_events(file_data, evt_list->num_events,
+						evts);
+		mutex_unlock(&file_data->dev_data->dev_mutex);
+		kfree(evts);
+	}
+		break;
+	case MSM_QCA402X_FLUSH_BUFFERS: {
+		struct msm_qca_event_list_type *evt_list =
+			(struct msm_qca_event_list_type *)arg;
+		struct msm_qca_event_type *evts;
+
+		pr_debug("MSM_QCA402X_UNREGISTER_EVENT\n");
+
+		evts = msm_qca402_alloc_get_evts(evt_list);
+		if (!evts)
+			return -ENOMEM;
+		mutex_lock(&file_data->dev_data->dev_mutex);
+		msm_qca402_flush(file_data, evt_list->num_events, evts);
+		mutex_unlock(&file_data->dev_data->dev_mutex);
+		kfree(evts);
+	}
+		break;
+
+	case MSM_QCA402X_ABORT_MESSAGE: {
+		struct msm_qca_event_list_type *evt_list =
+			(struct msm_qca_event_list_type *)arg;
+		struct msm_qca_event_type *evts;
+
+		pr_debug("MSM_QCA402X_UNREGISTER_EVENT\n");
+
+		evts = msm_qca402_alloc_get_evts(evt_list);
+		if (!evts)
+			return -ENOMEM;
+		mutex_lock(&file_data->dev_data->dev_mutex);
+		msm_qca402_abort(file_data, evt_list->num_events, evts);
+		mutex_unlock(&file_data->dev_data->dev_mutex);
+		kfree(evts);
+	}
+		break;
+	default:
+		pr_debug("unhandled ioctl command: %d\n", cmd);
+	}
+	return ret;
+}
+static long msm_qca402_unlocked_ioctl(struct file *file, unsigned int cmd,
+		unsigned long arg)
+{
+	long ret = 0;
+	__u32 len = 0;
+
+	switch (cmd) {
+	case MSM_QCA402X_ENQUEUE_BUFFER:
+	case MSM_QCA402X_SEND_MESSAGE:
+	case MSM_QCA402X_RECEIVE_MESSAGE: {
+		struct msm_qca_message_type data;
+
+		len = sizeof(struct msm_qca_message_type);
+		if (copy_from_user(&data, (void __user *)arg, len))
+			return -EFAULT;
+		ret = msm_qca402_ioctl(file, cmd, (void *)&data);
+		if (copy_to_user((void __user *)arg, &data, len))
+			return -EFAULT;
+	}
+		break;
+	case MSM_QCA402X_FLUSH_BUFFERS:
+	case MSM_QCA402X_ABORT_MESSAGE:
+	case MSM_QCA402X_REGISTER_EVENT:
+	case MSM_QCA402X_UNREGISTER_EVENT: {
+		struct msm_qca_event_list_type data;
+
+		len = sizeof(struct msm_qca_event_list_type);
+		if (copy_from_user(&data, (void __user *)arg, len))
+			return -EFAULT;
+		ret = msm_qca402_ioctl(file, cmd, (void *)&data);
+		if (copy_to_user((void __user *)arg, &data, len))
+			return -EFAULT;
+	}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+#ifdef CONFIG_COMPAT
+struct msm_qca_message_type_32 {
+	__u64 header;
+	__u64 buff_addr;
+	__u32 header_size;
+	__u32 data_size;
+	int fd;
+	__u8 cmd;
+	__u8 channel_id;
+	__u8 is_ion_data;
+	__u8 last_data;
+};
+
+struct msm_qca_event_list_type_32 {
+	__u64 events;
+	__u32 num_events;
+};
+
+#define MSM_QCA402X_ENQUEUE_BUFFER_COMPAT \
+	_IOWR(0xdd, 1, struct msm_qca_message_type_32)
+#define MSM_QCA402X_SEND_MESSAGE_COMPAT \
+	_IOWR(0xdd, 2, struct msm_qca_message_type_32)
+#define MSM_QCA402X_RECEIVE_MESSAGE_COMPAT \
+	_IOWR(0xdd, 3, struct msm_qca_message_type_32)
+#define MSM_QCA402X_FLUSH_BUFFERS_COMPAT \
+	_IOWR(0xdd, 4, struct msm_qca_event_list_type_32)
+#define MSM_QCA402X_ABORT_MESSAGE_COMPAT \
+	_IOWR(0xdd, 5, struct msm_qca_event_list_type_32)
+#define MSM_QCA402X_REGISTER_EVENT_COMPAT \
+	_IOWR(0xdd, 6, struct msm_qca_event_list_type_32)
+#define MSM_QCA402X_UNREGISTER_EVENT_COMPAT \
+	_IOWR(0xdd, 7, struct msm_qca_event_list_type_32)
+
+static long msm_qca402_compat_ioctl(struct file *file, unsigned int cmd,
+		unsigned long arg)
+{
+	long ret = 0;
+
+	pr_debug("called\n");
+
+	switch (cmd) {
+	case MSM_QCA402X_ENQUEUE_BUFFER_COMPAT:
+	case MSM_QCA402X_SEND_MESSAGE_COMPAT:
+	case MSM_QCA402X_RECEIVE_MESSAGE_COMPAT: {
+		struct msm_qca_message_type_32 data32;
+		struct msm_qca_message_type data;
+		__u32 len = 0;
+
+		len = sizeof(struct msm_qca_message_type_32);
+		if (copy_from_user(&data32, (void __user *)arg, len))
+			return -EFAULT;
+		data.channel_id = data32.channel_id;
+		data.is_ion_data = data32.is_ion_data;
+		data.header_size = data32.header_size;
+		data.fd = data32.fd;
+		data.data_size = data32.data_size;
+		data.cmd = data32.cmd;
+		data.last_data = data32.last_data;
+		data.header = compat_ptr(data32.header);
+		data.buff_addr = compat_ptr(data32.buff_addr);
+
+		ret = msm_qca402_ioctl(file, cmd, (void *)&data);
+
+		data32.header_size = data.header_size;
+		data32.fd = data.fd;
+		data32.data_size = data.data_size;
+		if (copy_to_user((void __user *)arg, (void *)&data32, len))
+			return -EFAULT;
+	}
+		break;
+	case MSM_QCA402X_FLUSH_BUFFERS_COMPAT:
+	case MSM_QCA402X_ABORT_MESSAGE_COMPAT:
+	case MSM_QCA402X_REGISTER_EVENT_COMPAT:
+	case MSM_QCA402X_UNREGISTER_EVENT_COMPAT: {
+		struct msm_qca_event_list_type_32 data32;
+		struct msm_qca_event_list_type data;
+		int i;
+
+		len = sizeof(struct msm_qca_event_list_type_32);
+		if (copy_from_user(&data32, (void __user *)arg, len))
+			return -EFAULT;
+		data.num_events = data32.num_events;
+		for (i = 0; i < data.num_events; i++)
+			data.events[i] = data32.events[i];
+		ret = msm_qca402_ioctl(file, cmd, (void *)&data);
+	}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return ret;
+}
+#endif
+
+static void msm_qca402_send_msg_hndl(void *target, __u8 epid,
+	__u8 eventid, struct htca_event_info *event_info,
+	void *context)
+{
+	struct msm_qca402_dev_data_t *dev_data =
+		(struct msm_qca402_dev_data_t *)context;
+	struct msm_qca402_workbuff_list_t *wb;
+
+	wb = (struct msm_qca402_workbuff_list_t *)event_info->cookie;
+	if ((!wb) || (!dev_data))
+		return;
+
+	wake_up_interruptible(&dev_data->in_queue);
+
+	mutex_lock(&dev_data->dev_mutex);
+	dev_data->sending--;
+	list_add_tail(&wb->list, &dev_data->work_list);
+	mutex_unlock(&dev_data->dev_mutex);
+
+}
+
+static void msm_qca402_recv_msg_hndl(void *target, __u8 epid,
+	__u8 eventid, struct htca_event_info *event_info,
+	void *context)
+{
+	struct msm_qca402_dev_data_t *dev_data =
+		(struct msm_qca402_dev_data_t *)context;
+	struct msm_qca402_workbuff_list_t *wb;
+
+	wb = (struct msm_qca402_workbuff_list_t *)event_info->cookie;
+	if ((!wb) || (!dev_data))
+		return;
+
+	mutex_lock(&dev_data->dev_mutex);
+	dev_data->receiving--;
+	wb->size = event_info->actual_length;
+	list_add_tail(&wb->list, &dev_data->recv_list);
+	mutex_unlock(&dev_data->dev_mutex);
+	if (dev_data->sending < dev_data->receiving)
+		wake_up_interruptible(&dev_data->in_queue);
+	wake_up_interruptible(&dev_data->recv_queue);
+}
+
+static void msm_qca402_data_avl_hndl(void *target, __u8 epid,
+	__u8 eventid, struct htca_event_info *event_info,
+	void *context)
+{
+	pr_debug("started\n");
+}
+
+static int msm_qca402_htca_recv_thread(void *hdl)
+{
+
+	int wait;
+	struct msm_qca402_dev_data_t *dev_data =
+		(struct msm_qca402_dev_data_t *)hdl;
+	struct msm_qca402_workbuff_list_t *wb_prev, *wb_curr;
+	int status;
+
+	pr_debug("start waiting\n");
+
+	while (!kthread_should_stop()) {
+		wait = wait_event_interruptible(dev_data->recv_queue,
+			!list_empty(&dev_data->recv_list) ||
+			kthread_should_stop());
+
+		if (kthread_should_stop())
+			break;
+
+		pr_debug("rcvd\n");
+		mutex_lock(&dev_data->dev_mutex);
+		wb_prev = list_first_entry(&dev_data->recv_list,
+				struct msm_qca402_workbuff_list_t, list);
+		list_del_init(&wb_prev->list);
+
+		wb_curr = msm_qca402_get_workbuff(dev_data);
+		status = htca_buffer_receive(dev_data->htca_target, 0,
+			(void *)&wb_curr->htca_msg, HTCA_MAX_BUFF_SIZE,
+			wb_curr);
+		dev_data->receiving++;
+
+		if (status)
+			pr_err("Receive error\n");
+
+		msm_qca402_process_htca_message(dev_data, wb_prev);
+		mutex_unlock(&dev_data->dev_mutex);
+
+	}
+
+	return 0;
+}
+
+
+static int msm_qca402_htca_user_thread(void *hdl)
+{
+	int ret, wait, i;
+	struct msm_qca402_dev_data_t *dev_data =
+		(struct msm_qca402_dev_data_t *)hdl;
+	struct msm_qca402_ready_list_t *r_entry;
+	struct msm_qca402_channel_list_t *ch_data = NULL;
+	struct msm_qca402_workbuff_list_t *wb;
+	int status;
+
+	pr_debug("started EP\n");
+	ret = htca_start(dev_data->htca_target);
+	WARN_ON(ret);
+	htca_event_reg(dev_data->htca_target, 0, HTCA_EVENT_BUFFER_SENT,
+		msm_qca402_send_msg_hndl, dev_data);
+	htca_event_reg(dev_data->htca_target, 0, HTCA_EVENT_BUFFER_RECEIVED,
+		msm_qca402_recv_msg_hndl, dev_data);
+	htca_event_reg(dev_data->htca_target, 0, HTCA_EVENT_DATA_AVAILABLE,
+		msm_qca402_data_avl_hndl, dev_data);
+	pr_debug("start waiting\n");
+
+
+	for (i = 0; i < QCA402_START_ENQ_BUFFS; i++) {
+		wb = msm_qca402_get_workbuff(dev_data);
+		status = htca_buffer_receive(dev_data->htca_target, 0,
+			(void *)&wb->htca_msg, HTCA_MAX_BUFF_SIZE, wb);
+	}
+
+	dev_data->receiving += QCA402_START_ENQ_BUFFS;
+
+	while (!kthread_should_stop()) {
+		wait = wait_event_interruptible(dev_data->in_queue,
+			((!list_empty(&dev_data->in_list) || ch_data) &&
+			(dev_data->sending < dev_data->receiving)) ||
+			kthread_should_stop());
+
+		if (kthread_should_stop())
+			break;
+
+		mutex_lock(&dev_data->dev_mutex);
+		if (!ch_data) {
+			r_entry = list_first_entry(&dev_data->in_list,
+					struct msm_qca402_ready_list_t, list);
+
+			ch_data = r_entry->ch_data;
+			list_del_init(&r_entry->list);
+			kfree(r_entry);
+		}
+		ret = msm_qca402_send_htca_message(dev_data, ch_data);
+		if (ret == -EINVAL) {
+			pr_err("Error during message send\n");
+			ch_data = NULL;
+		} else if (ret == 0) {
+			pr_debug("Message sent\n");
+			ch_data->ref_cnt--;
+			ch_data = NULL;
+		}
+		mutex_unlock(&dev_data->dev_mutex);
+	}
+
+	return 0;
+}
+
+static const struct file_operations msm_qca402_ops = {
+	.open = msm_qca402_open,
+	.poll = msm_qca402_poll,
+	.release = msm_qca402_release,
+	.unlocked_ioctl = msm_qca402_unlocked_ioctl,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl = msm_qca402_compat_ioctl,
+#endif
+};
+
+static int msm_qca402_create_device(struct msm_qca402_dev_data_t **dv,
+		int minor)
+{
+	int ret;
+	char name[20];
+
+	*dv = kzalloc(sizeof(**dv), GFP_KERNEL);
+	if (!*dv)
+		return -ENOMEM;
+	snprintf(name, sizeof(name), "%s%d", DEVICE_NAME, minor);
+	pr_debug("called for device %s\n", name);
+	(*dv)->dev = device_create(msm_qca402_class, NULL,
+			MKDEV(msm_qca402_major, minor), NULL, name);
+	if (IS_ERR((*dv)->dev)) {
+		ret = PTR_ERR((*dv)->dev);
+		kfree(*dv);
+		*dv = NULL;
+		return ret;
+	}
+	cdev_init(&(*dv)->cdev, &msm_qca402_ops);
+	ret = cdev_add(&(*dv)->cdev, MKDEV(msm_qca402_major, minor), 1);
+	if (ret < 0) {
+		device_unregister((*dv)->dev);
+		kfree(*dv);
+		*dv = NULL;
+	}
+
+	return ret;
+}
+
+static void msm_qca402_destroy_device(struct msm_qca402_dev_data_t *dv)
+{
+	pr_debug("called\n");
+	cdev_del(&dv->cdev);
+	device_unregister(dv->dev);
+	kfree(dv);
+}
+
+static void msm_qca402_trgt_avail_hndl(void *target, __u8 epid,
+	__u8 eventid, struct htca_event_info *event_info,
+	void *context)
+{
+	struct msm_qca402_dev_data_t *dev_data;
+	dev_t devid;
+	int ret;
+	int i;
+
+	pr_debug("started\n");
+	/* get the actual number from dts */
+	ret = alloc_chrdev_region(&devid, 0, MAX_DEVICE_NUM, DEVICE_NAME);
+	if (ret < 0)
+		goto register_error;
+	msm_qca402_major = MAJOR(devid);
+	msm_qca402_class = class_create(THIS_MODULE, DEVICE_CLASS);
+	if (IS_ERR(msm_qca402_class)) {
+		ret = PTR_ERR(msm_qca402_class);
+		goto class_error;
+	}
+	for (i = 0; i < MAX_DEVICE_NUM; i++) {
+		ret = msm_qca402_create_device(&msm_qca402_device[i].dev,
+				i + MINOR(devid));
+		if (ret < 0)
+			goto device_error;
+		dev_data = msm_qca402_device[i].dev;
+		dev_data->dev_idx = i;
+		dev_data->ion_client =
+			msm_ion_client_create("qca_ion_client");
+		if (IS_ERR_OR_NULL(dev_data->ion_client)) {
+			msm_qca402_destroy_device(dev_data);
+			msm_qca402_device[i].dev = NULL;
+			goto device_error;
+		}
+
+		init_waitqueue_head(&dev_data->in_queue);
+		init_waitqueue_head(&dev_data->recv_queue);
+
+		pr_debug("ion done\n");
+		INIT_LIST_HEAD(&dev_data->file_list);
+		INIT_LIST_HEAD(&dev_data->channel_list);
+		INIT_LIST_HEAD(&dev_data->work_list);
+		INIT_LIST_HEAD(&dev_data->recv_list);
+		INIT_LIST_HEAD(&dev_data->in_list);
+		ret = msm_qca402_alloc_add_workbuffs(dev_data,
+				QCA402_MIN_NUM_WORKBUFS);
+		if (ret < 0)
+			goto device_error;
+		pr_debug("lists done\n");
+		mutex_init(&dev_data->dev_mutex);
+		spin_lock_init(&dev_data->lock);
+		pr_debug("device[%d] %pK\n", i, dev_data);
+		dev_data->htca_target = target;
+	}
+
+	for (i = 0; i < MAX_DEVICE_NUM; i++) {
+		msm_qca402_device[i].user_task = kthread_create(
+			msm_qca402_htca_user_thread, dev_data, "qca402_user");
+		msm_qca402_device[i].recv_task = kthread_create(
+			msm_qca402_htca_recv_thread, dev_data, "qca402_recv");
+		wake_up_process(msm_qca402_device[i].user_task);
+		wake_up_process(msm_qca402_device[i].recv_task);
+	}
+	return;
+
+device_error:
+	for (--i; i >= 0; i--) {
+		if (msm_qca402_device[i].dev) {
+			mutex_destroy(&msm_qca402_device[i].dev->dev_mutex);
+			msm_qca402_free_workbuffs(msm_qca402_device[i].dev);
+			ion_client_destroy(
+				msm_qca402_device[i].dev->ion_client);
+			msm_qca402_destroy_device(msm_qca402_device[i].dev);
+			msm_qca402_device[i].dev = NULL;
+		}
+	}
+	class_destroy(msm_qca402_class);
+class_error:
+	unregister_chrdev(msm_qca402_major, DEVICE_NAME);
+register_error:
+	pr_err("error: %d\n", ret);
+}
+
+static void msm_qca402_trgt_unavail_hndl(void *target, __u8 epid,
+	__u8 eventid, struct htca_event_info *event_info,
+	void *context)
+{
+	int i;
+
+	for (i = 0; i < MAX_DEVICE_NUM; i++) {
+		if (msm_qca402_device[i].dev) {
+			kthread_stop(msm_qca402_device[i].user_task);
+			kthread_stop(msm_qca402_device[i].recv_task);
+			htca_stop(msm_qca402_device[i].dev->htca_target);
+			mutex_destroy(&msm_qca402_device[i].dev->dev_mutex);
+			msm_qca402_free_workbuffs(msm_qca402_device[i].dev);
+			ion_client_destroy(
+				msm_qca402_device[i].dev->ion_client);
+			msm_qca402_destroy_device(msm_qca402_device[i].dev);
+			msm_qca402_device[i].dev = NULL;
+		}
+	}
+	class_unregister(msm_qca402_class);
+	class_destroy(msm_qca402_class);
+	unregister_chrdev(msm_qca402_major, DEVICE_NAME);
+}
+
+static int msm_qca402_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match_dev;
+	int status;
+
+	if (pdev->dev.of_node) {
+		pr_debug("device found\n");
+		match_dev = of_match_device(pdev->dev.driver->of_match_table,
+			&pdev->dev);
+	}
+
+	pr_debug("called\n");
+	if (htca_init())
+		return -EINVAL;
+
+	pr_debug("register\n");
+	status = htca_event_reg(NULL, 0, HTCA_EVENT_TARGET_AVAILABLE,
+		msm_qca402_trgt_avail_hndl, NULL);
+	if (status != HTCA_OK)
+		return -EINVAL;
+	status = htca_event_reg(NULL, 0, HTCA_EVENT_TARGET_UNAVAILABLE,
+		msm_qca402_trgt_unavail_hndl, NULL);
+	if (status != HTCA_OK)
+		return -EINVAL;
+	pr_debug("register_end\n");
+
+	return 0;
+}
+
+static int msm_qca402_remove(struct platform_device *pdev)
+{
+	int i, stop_flag = 0;
+
+	for (i = 0; i < MAX_DEVICE_NUM; i++) {
+		if (msm_qca402_device[i].dev) {
+			stop_flag = 1;
+			kthread_stop(msm_qca402_device[i].user_task);
+			kthread_stop(msm_qca402_device[i].recv_task);
+			htca_stop(msm_qca402_device[i].dev->htca_target);
+			mutex_destroy(&msm_qca402_device[i].dev->dev_mutex);
+			msm_qca402_free_workbuffs(msm_qca402_device[i].dev);
+			ion_client_destroy(
+				msm_qca402_device[i].dev->ion_client);
+			msm_qca402_destroy_device(msm_qca402_device[i].dev);
+			msm_qca402_device[i].dev = NULL;
+		}
+	}
+	if (stop_flag) {
+		class_unregister(msm_qca402_class);
+		class_destroy(msm_qca402_class);
+		unregister_chrdev(msm_qca402_major, DEVICE_NAME);
+	}
+	htca_shutdown();
+	return 0;
+}
+
+static struct platform_driver msm_qca402_driver = {
+	.probe = msm_qca402_probe,
+	.remove = msm_qca402_remove,
+	.driver = {
+		.name = "msm_qca402",
+		.owner = THIS_MODULE,
+		.of_match_table = msm_qca402_dt_match,
+	},
+};
+
+static int __init msm_qca402_init(void)
+{
+	platform_driver_register(&msm_qca402_driver);
+	return 0;
+}
+
+static void __exit msm_qca402_exit(void)
+{
+}
+
+module_init(msm_qca402_init);
+module_exit(msm_qca402_exit);
+
+MODULE_DESCRIPTION("Driver for QCA402x HTCA High level communication");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/qca402/msm_qca402.h b/drivers/media/platform/msm/qca402/msm_qca402.h
new file mode 100644
index 0000000..518ded7
--- /dev/null
+++ b/drivers/media/platform/msm/qca402/msm_qca402.h
@@ -0,0 +1,142 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#ifndef _QCA402_H_
+#define _QCA402_H_
+#include <linux/types.h>
+#include <linux/cdev.h>
+#include <linux/mutex.h>
+#include <linux/msm_ion.h>
+#include "../drivers/net/wireless/qca402x/htca_mbox/htca.h"
+
+/* current htca buffer limitation */
+#define HTCA_MAX_BUFF_SIZE (2048)
+enum lpchtca_packet_type {
+	/* the below three types are for piece of data (i.e. frame) with
+	 *  known size
+	 */
+	LPCHTCA_START_PACKET = 1,
+	LPCHTCA_MID_PACKET,
+	LPCHTCA_END_PACKET,
+
+	/* For piece of data (i.e. frame) with known size that fits in one
+	 *  packet
+	 */
+	LPCHTCA_FULL_PACKET,
+
+	/* If data size is unknown/continuous - this case assumes no header or
+	 * user space to take care of headers
+	 */
+	LPCHTCA_UNSPEC_PACKET,
+
+};
+
+/* Message Flags */
+#define LPCHTCA_ASYNC_MESSAGE        (1 << 7)
+/* this bit is added to one of the above to indicate the packet is last that
+ * will be received for this stream
+ */
+#define LPCHTCA_END_TRANSMISSON      (1 << 6)
+#define LPCHTCA_PACKET_MASK          ((1 << 6) - 1)
+#define QCA402_MIN_NUM_WORKBUFS (4)
+
+struct msm_qca402_file_data_t;
+
+struct __packed msm_qca402_htca_header_t {
+	__u8 channel_id;
+	__u8 msg_flags;
+	__u16 meta_size;
+};
+
+#define QCA_MSG_HEADER_SIZE (sizeof(struct msm_qca402_htca_header_t))
+#define QCA_MSG_PAYLOAD_SIZE (HTCA_MAX_BUFF_SIZE - QCA_MSG_HEADER_SIZE -\
+				HTCA_HEADER_LEN_MAX)
+
+struct __packed msm_qca402_htca_message_t {
+	__u8 htca_private[HTCA_HEADER_LEN_MAX];
+	struct msm_qca402_htca_header_t header;
+	__u8 payload[QCA_MSG_PAYLOAD_SIZE];
+};
+
+struct file_data_list_t {
+	struct msm_qca402_file_data_t *file_data;
+	struct list_head list;
+};
+
+struct msm_qca402_workbuff_list_t {
+	struct msm_qca402_htca_message_t htca_msg;
+	__u32 size;
+	struct list_head list;
+};
+
+struct msm_qca402_buffer_list_t {
+	struct msm_qca_message_type qca_msg;
+	struct msm_qca402_workbuff_list_t *wbb;
+	void *vaddr;
+	struct ion_handle *ih;
+	__u32 valid_size;
+	struct list_head list;
+};
+
+struct msm_qca402_evt_list_t {
+	__u8 channel_id;
+	__u8 cmd;
+	struct list_head list;
+};
+
+struct msm_qca402_channel_list_t {
+	struct msm_qca402_buffer_list_t *current_entry;
+	struct msm_qca402_workbuff_list_t *wbin;
+	struct msm_qca402_workbuff_list_t *wbout;
+	struct list_head enqueued_list;
+	struct list_head ready_list;
+	struct list_head dequeued_list;
+	__u32 ref_cnt;
+	__u8 channel_id;
+	__u8 has_buff;
+	struct list_head list;
+};
+
+struct msm_qca402_ready_list_t {
+	struct msm_qca402_channel_list_t *ch_data;
+	__u8 cmd;
+	struct list_head list;
+};
+
+struct msm_qca402_dev_data_t {
+	struct cdev cdev;
+	struct device *dev;
+	struct ion_client *ion_client;
+	__u8 endPointId;
+	void *htca_target;
+	struct list_head file_list;
+	struct list_head channel_list;
+	struct mutex dev_mutex;
+	struct list_head work_list;
+	wait_queue_head_t in_queue;
+	struct list_head in_list;
+	wait_queue_head_t recv_queue;
+	struct list_head recv_list;
+	spinlock_t lock;
+	__u8 dev_idx;
+	__u8 sending;
+	__u8 receiving;
+};
+
+struct msm_qca402_file_data_t {
+	struct msm_qca402_dev_data_t *dev_data;
+	wait_queue_head_t out_queue;
+	struct mutex file_mutex;
+	struct list_head evt_list;
+	struct list_head ready_ch_list;
+};
+
+#endif /* _QCA402_H_ */
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_platform.c b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
index f80d9b0..f975409 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_platform.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
@@ -120,7 +120,7 @@
 	},
 	{
 		.key = "qcom,max-secure-instances",
-		.value = 5,
+		.value = 2,
 	},
 	{
 		.key = "qcom,max-hw-load",
@@ -154,6 +154,10 @@
 		.key = "qcom,debug-timeout",
 		.value = 0,
 	},
+	{
+		.key = "qcom,enable-idle-indicator",
+		.value = 1,
+	},
 };
 
 static struct msm_vidc_common_data sdm670_common_data_v0[] = {
@@ -205,6 +209,10 @@
 		.key = "qcom,hw-resp-timeout",
 		.value = 1000,
 	},
+	{
+		.key = "qcom,enable-idle-indicator",
+		.value = 1,
+	},
 };
 
 static struct msm_vidc_common_data sdm670_common_data_v1[] = {
@@ -256,6 +264,10 @@
 		.key = "qcom,hw-resp-timeout",
 		.value = 1000,
 	},
+	{
+		.key = "qcom,enable-idle-indicator",
+		.value = 1,
+	},
 };
 
 static struct msm_vidc_efuse_data sdm670_efuse_data[] = {
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 79ed798..6975c13 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -2747,7 +2747,7 @@
 {
 	int rc = 0;
 	u32 wfi_status = 0, idle_status = 0, pc_ready = 0;
-	int count = 0;
+	int pc_count = 0, idle_count = 0;
 	const int max_tries = 10;
 	struct venus_hfi_device *device = list_first_entry(
 			&hal_ctxt.dev_head, struct venus_hfi_device, list);
@@ -2796,8 +2796,16 @@
 				wfi_status);
 			goto skip_power_off;
 		}
-		if (device->res->sys_idle_indicator &&
-			!(idle_status & BIT(30))) {
+		while (device->res->sys_idle_indicator &&
+				idle_count < max_tries) {
+			if (idle_status & BIT(30))
+				break;
+			usleep_range(50, 100);
+			idle_status = __read_register(device,
+				VIDC_CPU_CS_SCIACMDARG0);
+			idle_count++;
+		}
+		if (idle_count == max_tries) {
 			dprintk(VIDC_WARN,
 				"Skipping PC as idle_status (%#x) bit not set\n",
 				idle_status);
@@ -2810,7 +2818,7 @@
 			goto skip_power_off;
 		}
 
-		while (count < max_tries) {
+		while (pc_count < max_tries) {
 			wfi_status = __read_register(device,
 					VIDC_WRAPPER_CPU_STATUS);
 			pc_ready = __read_register(device,
@@ -2819,10 +2827,10 @@
 				VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY))
 				break;
 			usleep_range(150, 250);
-			count++;
+			pc_count++;
 		}
 
-		if (count == max_tries) {
+		if (pc_count == max_tries) {
 			dprintk(VIDC_ERR,
 					"Skip PC. Core is not in right state (%#x, %#x)\n",
 					wfi_status, pc_ready);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index d0b5a0e..f9f2160 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1658,8 +1658,9 @@
 	int rc = 0;
 	uint32_t lstnr;
 	unsigned long flags;
-	struct qseecom_client_listener_data_irsp send_data_rsp;
-	struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit;
+	struct qseecom_client_listener_data_irsp send_data_rsp = {0};
+	struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit
+									= {0};
 	struct qseecom_registered_listener_list *ptr_svc = NULL;
 	sigset_t new_sigset;
 	sigset_t old_sigset;
@@ -1757,32 +1758,38 @@
 		}
 err_resp:
 		qseecom.send_resp_flag = 0;
-		ptr_svc->send_resp_flag = 0;
-		table = ptr_svc->sglistinfo_ptr;
+		if (ptr_svc) {
+			ptr_svc->send_resp_flag = 0;
+			table = ptr_svc->sglistinfo_ptr;
+		}
 		if (qseecom.qsee_version < QSEE_VERSION_40) {
 			send_data_rsp.listener_id  = lstnr;
 			send_data_rsp.status = status;
-			send_data_rsp.sglistinfo_ptr =
-				(uint32_t)virt_to_phys(table);
-			send_data_rsp.sglistinfo_len =
-				SGLISTINFO_TABLE_SIZE;
-			dmac_flush_range((void *)table,
-				(void *)table + SGLISTINFO_TABLE_SIZE);
+			if (table) {
+				send_data_rsp.sglistinfo_ptr =
+					(uint32_t)virt_to_phys(table);
+				send_data_rsp.sglistinfo_len =
+					SGLISTINFO_TABLE_SIZE;
+				dmac_flush_range((void *)table,
+					(void *)table + SGLISTINFO_TABLE_SIZE);
+			}
 			cmd_buf = (void *)&send_data_rsp;
 			cmd_len = sizeof(send_data_rsp);
 		} else {
 			send_data_rsp_64bit.listener_id  = lstnr;
 			send_data_rsp_64bit.status = status;
-			send_data_rsp_64bit.sglistinfo_ptr =
-				virt_to_phys(table);
-			send_data_rsp_64bit.sglistinfo_len =
-				SGLISTINFO_TABLE_SIZE;
-			dmac_flush_range((void *)table,
-				(void *)table + SGLISTINFO_TABLE_SIZE);
+			if (table) {
+				send_data_rsp_64bit.sglistinfo_ptr =
+					virt_to_phys(table);
+				send_data_rsp_64bit.sglistinfo_len =
+					SGLISTINFO_TABLE_SIZE;
+				dmac_flush_range((void *)table,
+					(void *)table + SGLISTINFO_TABLE_SIZE);
+			}
 			cmd_buf = (void *)&send_data_rsp_64bit;
 			cmd_len = sizeof(send_data_rsp_64bit);
 		}
-		if (qseecom.whitelist_support == false)
+		if (qseecom.whitelist_support == false || table == NULL)
 			*(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND;
 		else
 			*(uint32_t *)cmd_buf =
@@ -1806,8 +1813,10 @@
 
 		ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
 					cmd_buf, cmd_len, resp, sizeof(*resp));
-		ptr_svc->listener_in_use = false;
-		__qseecom_clean_listener_sglistinfo(ptr_svc);
+		if (ptr_svc) {
+			ptr_svc->listener_in_use = false;
+			__qseecom_clean_listener_sglistinfo(ptr_svc);
+		}
 		if (ret) {
 			pr_err("scm_call() failed with err: %d (app_id = %d)\n",
 				ret, data->client.app_id);
@@ -1960,8 +1969,9 @@
 	int rc = 0;
 	uint32_t lstnr;
 	unsigned long flags;
-	struct qseecom_client_listener_data_irsp send_data_rsp;
-	struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit;
+	struct qseecom_client_listener_data_irsp send_data_rsp = {0};
+	struct qseecom_client_listener_data_64bit_irsp send_data_rsp_64bit
+									= {0};
 	struct qseecom_registered_listener_list *ptr_svc = NULL;
 	sigset_t new_sigset;
 	sigset_t old_sigset;
@@ -2052,30 +2062,36 @@
 			status  = QSEOS_RESULT_SUCCESS;
 		}
 err_resp:
-		table = ptr_svc->sglistinfo_ptr;
+		if (ptr_svc)
+			table = ptr_svc->sglistinfo_ptr;
 		if (qseecom.qsee_version < QSEE_VERSION_40) {
 			send_data_rsp.listener_id  = lstnr;
 			send_data_rsp.status = status;
-			send_data_rsp.sglistinfo_ptr =
-				(uint32_t)virt_to_phys(table);
-			send_data_rsp.sglistinfo_len = SGLISTINFO_TABLE_SIZE;
-			dmac_flush_range((void *)table,
-				(void *)table + SGLISTINFO_TABLE_SIZE);
+			if (table) {
+				send_data_rsp.sglistinfo_ptr =
+					(uint32_t)virt_to_phys(table);
+				send_data_rsp.sglistinfo_len =
+						SGLISTINFO_TABLE_SIZE;
+				dmac_flush_range((void *)table,
+					(void *)table + SGLISTINFO_TABLE_SIZE);
+			}
 			cmd_buf = (void *)&send_data_rsp;
 			cmd_len = sizeof(send_data_rsp);
 		} else {
 			send_data_rsp_64bit.listener_id  = lstnr;
 			send_data_rsp_64bit.status = status;
-			send_data_rsp_64bit.sglistinfo_ptr =
-				virt_to_phys(table);
-			send_data_rsp_64bit.sglistinfo_len =
-				SGLISTINFO_TABLE_SIZE;
-			dmac_flush_range((void *)table,
-				(void *)table + SGLISTINFO_TABLE_SIZE);
+			if (table) {
+				send_data_rsp_64bit.sglistinfo_ptr =
+					virt_to_phys(table);
+				send_data_rsp_64bit.sglistinfo_len =
+					SGLISTINFO_TABLE_SIZE;
+				dmac_flush_range((void *)table,
+					(void *)table + SGLISTINFO_TABLE_SIZE);
+			}
 			cmd_buf = (void *)&send_data_rsp_64bit;
 			cmd_len = sizeof(send_data_rsp_64bit);
 		}
-		if (qseecom.whitelist_support == false)
+		if (qseecom.whitelist_support == false || table == NULL)
 			*(uint32_t *)cmd_buf = QSEOS_LISTENER_DATA_RSP_COMMAND;
 		else
 			*(uint32_t *)cmd_buf =
@@ -2098,9 +2114,11 @@
 
 		ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1,
 					cmd_buf, cmd_len, resp, sizeof(*resp));
-		ptr_svc->listener_in_use = false;
-		__qseecom_clean_listener_sglistinfo(ptr_svc);
-		wake_up_interruptible(&ptr_svc->listener_block_app_wq);
+		if (ptr_svc) {
+			ptr_svc->listener_in_use = false;
+			__qseecom_clean_listener_sglistinfo(ptr_svc);
+			wake_up_interruptible(&ptr_svc->listener_block_app_wq);
+		}
 
 		if (ret) {
 			pr_err("scm_call() failed with err: %d (app_id = %d)\n",
@@ -2644,6 +2662,7 @@
 		}
 	}
 
+unload_exit:
 	if (found_app) {
 		spin_lock_irqsave(&qseecom.registered_app_list_lock, flags1);
 		if (app_crash) {
@@ -2666,7 +2685,6 @@
 		spin_unlock_irqrestore(&qseecom.registered_app_list_lock,
 								flags1);
 	}
-unload_exit:
 	qseecom_unmap_ion_allocated_memory(data);
 	data->released = true;
 	return ret;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 69465f8..6278377 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -507,28 +507,24 @@
 	pr_debug("%s: target freq = %lu (%s)\n", mmc_hostname(host),
 		*freq, current->comm);
 
-	if ((clk_scaling->curr_freq == *freq) ||
-		clk_scaling->skip_clk_scale_freq_update)
-		goto out;
-
-	/* No need to scale the clocks if they are gated */
-	if (!host->ios.clock)
-		goto out;
-
 	spin_lock_bh(&clk_scaling->lock);
-	if (clk_scaling->clk_scaling_in_progress) {
-		pr_debug("%s: clocks scaling is already in-progress by mmc thread\n",
-			mmc_hostname(host));
+	if (clk_scaling->target_freq == *freq ||
+		clk_scaling->skip_clk_scale_freq_update) {
 		spin_unlock_bh(&clk_scaling->lock);
 		goto out;
 	}
+
 	clk_scaling->need_freq_change = true;
 	clk_scaling->target_freq = *freq;
 	clk_scaling->state = *freq < clk_scaling->curr_freq ?
 		MMC_LOAD_LOW : MMC_LOAD_HIGH;
 	spin_unlock_bh(&clk_scaling->lock);
 
-	abort = __mmc_claim_host(host, &clk_scaling->devfreq_abort);
+	if (!clk_scaling->is_suspended && host->ios.clock)
+		abort = __mmc_claim_host(host, &clk_scaling->devfreq_abort);
+	else
+		goto out;
+
 	if (abort)
 		goto out;
 
@@ -572,6 +568,7 @@
 {
 	unsigned long target_freq;
 	int err;
+	struct mmc_devfeq_clk_scaling clk_scaling;
 
 	if (!host->clk_scaling.enable)
 		return;
@@ -581,8 +578,7 @@
 
 	spin_lock_bh(&host->clk_scaling.lock);
 
-	if (host->clk_scaling.clk_scaling_in_progress ||
-		!(host->clk_scaling.need_freq_change)) {
+	if (!host->clk_scaling.need_freq_change) {
 		spin_unlock_bh(&host->clk_scaling.lock);
 		return;
 	}
@@ -590,7 +586,12 @@
 
 	atomic_inc(&host->clk_scaling.devfreq_abort);
 	target_freq = host->clk_scaling.target_freq;
-	host->clk_scaling.clk_scaling_in_progress = true;
+	/*
+	 * Store the clock scaling state while the lock is acquired so that
+	 * if devfreq context modifies clk_scaling, it will get reflected only
+	 * in the next deferred scaling check.
+	 */
+	clk_scaling = host->clk_scaling;
 	host->clk_scaling.need_freq_change = false;
 	spin_unlock_bh(&host->clk_scaling.lock);
 	pr_debug("%s: doing deferred frequency change (%lu) (%s)\n",
@@ -598,7 +599,7 @@
 				target_freq, current->comm);
 
 	err = mmc_clk_update_freq(host, target_freq,
-		host->clk_scaling.state);
+		clk_scaling.state);
 	if (err && err != -EAGAIN) {
 		pr_err("%s: failed on deferred scale clocks (%d)\n",
 			mmc_hostname(host), err);
@@ -608,7 +609,6 @@
 			mmc_hostname(host),
 			target_freq, current->comm);
 	}
-	host->clk_scaling.clk_scaling_in_progress = false;
 	atomic_dec(&host->clk_scaling.devfreq_abort);
 }
 EXPORT_SYMBOL(mmc_deferred_scaling);
@@ -738,7 +738,6 @@
 	spin_lock_init(&host->clk_scaling.lock);
 	atomic_set(&host->clk_scaling.devfreq_abort, 0);
 	host->clk_scaling.curr_freq = host->ios.clock;
-	host->clk_scaling.clk_scaling_in_progress = false;
 	host->clk_scaling.need_freq_change = false;
 	host->clk_scaling.is_busy_started = false;
 
@@ -809,7 +808,8 @@
 		return -EINVAL;
 	}
 
-	if (!mmc_can_scale_clk(host) || !host->clk_scaling.enable)
+	if (!mmc_can_scale_clk(host) || !host->clk_scaling.enable ||
+			host->clk_scaling.is_suspended)
 		return 0;
 
 	if (!host->clk_scaling.devfreq) {
@@ -826,7 +826,7 @@
 			mmc_hostname(host), __func__);
 		return err;
 	}
-	host->clk_scaling.enable = false;
+	host->clk_scaling.is_suspended = true;
 
 	host->clk_scaling.total_busy_time_us = 0;
 
@@ -880,15 +880,12 @@
 	if (host->ios.clock < host->clk_scaling.freq_table[max_clk_idx])
 		host->clk_scaling.curr_freq = devfreq_min_clk;
 
-	host->clk_scaling.clk_scaling_in_progress = false;
-	host->clk_scaling.need_freq_change = false;
-
 	err = devfreq_resume_device(host->clk_scaling.devfreq);
 	if (err) {
 		pr_err("%s: %s: failed to resume devfreq (%d)\n",
 			mmc_hostname(host), __func__, err);
 	} else {
-		host->clk_scaling.enable = true;
+		host->clk_scaling.is_suspended = false;
 		pr_debug("%s: devfreq resumed\n", mmc_hostname(host));
 	}
 
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 45df01b..02dffe9 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -761,6 +761,7 @@
 		/* Suspend the clock scaling and mask host capability */
 		if (host->clk_scaling.enable)
 			mmc_suspend_clk_scaling(host);
+		host->clk_scaling.enable = false;
 		host->caps2 &= ~MMC_CAP2_CLK_SCALE;
 		host->clk_scaling.state = MMC_LOAD_HIGH;
 		/* Set to max. frequency when disabling */
@@ -769,8 +770,10 @@
 	} else if (value) {
 		/* Unmask host capability and resume scaling */
 		host->caps2 |= MMC_CAP2_CLK_SCALE;
-		if (!host->clk_scaling.enable)
+		if (!host->clk_scaling.enable) {
+			host->clk_scaling.enable = true;
 			mmc_resume_clk_scaling(host);
+		}
 	}
 
 	mmc_put_card(host->card);
diff --git a/drivers/mmc/host/sdhci-msm-ice.c b/drivers/mmc/host/sdhci-msm-ice.c
index f86ce5b..42021af 100644
--- a/drivers/mmc/host/sdhci-msm-ice.c
+++ b/drivers/mmc/host/sdhci-msm-ice.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -244,8 +244,8 @@
 }
 
 static
-void sdhci_msm_ice_update_cfg(struct sdhci_host *host, u64 lba,
-			u32 slot, unsigned int bypass, short key_index)
+void sdhci_msm_ice_update_cfg(struct sdhci_host *host, u64 lba, u32 slot,
+		unsigned int bypass, short key_index, u32 cdu_sz)
 {
 	unsigned int ctrl_info_val = 0;
 
@@ -257,7 +257,7 @@
 
 	/* Configure data unit size of transfer request */
 	ctrl_info_val |=
-		(SDHCI_MSM_ICE_TR_DATA_UNIT_512_B &
+		(cdu_sz &
 		 MASK_SDHCI_MSM_ICE_CTRL_INFO_CDU)
 		 << OFFSET_SDHCI_MSM_ICE_CTRL_INFO_CDU;
 
@@ -335,8 +335,9 @@
 	struct sdhci_msm_host *msm_host = pltfm_host->priv;
 	int err = 0;
 	short key_index = 0;
-	sector_t lba = 0;
+	u64 dun = 0;
 	unsigned int bypass = SDHCI_MSM_ICE_ENABLE_BYPASS;
+	u32 cdu_sz = SDHCI_MSM_ICE_TR_DATA_UNIT_512_B;
 	struct request *req;
 
 	if (msm_host->ice.state != SDHCI_MSM_ICE_STATE_ACTIVE) {
@@ -349,8 +350,13 @@
 	if (!mrq)
 		return -EINVAL;
 	req = mrq->req;
-	if (req) {
-		lba = req->__sector;
+	if (req && req->bio) {
+		if (bio_dun(req->bio)) {
+			dun = bio_dun(req->bio);
+			cdu_sz = SDHCI_MSM_ICE_TR_DATA_UNIT_4_KB;
+		} else {
+			dun = req->__sector;
+		}
 		err = sdhci_msm_ice_get_cfg(msm_host, req, &bypass, &key_index);
 		if (err)
 			return err;
@@ -362,11 +368,12 @@
 
 	if (msm_host->ice_hci_support) {
 		/* For ICE HCI / ICE3.0 */
-		sdhci_msm_ice_hci_update_noncq_cfg(host, lba, bypass,
+		sdhci_msm_ice_hci_update_noncq_cfg(host, dun, bypass,
 						key_index);
 	} else {
 		/* For ICE versions earlier to ICE3.0 */
-		sdhci_msm_ice_update_cfg(host, lba, slot, bypass, key_index);
+		sdhci_msm_ice_update_cfg(host, dun, slot, bypass, key_index,
+					cdu_sz);
 	}
 	return 0;
 }
@@ -378,9 +385,10 @@
 	struct sdhci_msm_host *msm_host = pltfm_host->priv;
 	int err = 0;
 	short key_index = 0;
-	sector_t lba = 0;
+	u64 dun = 0;
 	unsigned int bypass = SDHCI_MSM_ICE_ENABLE_BYPASS;
 	struct request *req;
+	u32 cdu_sz = SDHCI_MSM_ICE_TR_DATA_UNIT_512_B;
 
 	if (msm_host->ice.state != SDHCI_MSM_ICE_STATE_ACTIVE) {
 		pr_err("%s: ice is in invalid state %d\n",
@@ -392,8 +400,13 @@
 	if (!mrq)
 		return -EINVAL;
 	req = mrq->req;
-	if (req) {
-		lba = req->__sector;
+	if (req && req->bio) {
+		if (bio_dun(req->bio)) {
+			dun = bio_dun(req->bio);
+			cdu_sz = SDHCI_MSM_ICE_TR_DATA_UNIT_4_KB;
+		} else {
+			dun = req->__sector;
+		}
 		err = sdhci_msm_ice_get_cfg(msm_host, req, &bypass, &key_index);
 		if (err)
 			return err;
@@ -405,11 +418,12 @@
 
 	if (msm_host->ice_hci_support) {
 		/* For ICE HCI / ICE3.0 */
-		sdhci_msm_ice_hci_update_cmdq_cfg(lba, bypass, key_index,
+		sdhci_msm_ice_hci_update_cmdq_cfg(dun, bypass, key_index,
 						ice_ctx);
 	} else {
 		/* For ICE versions earlier to ICE3.0 */
-		sdhci_msm_ice_update_cfg(host, lba, slot, bypass, key_index);
+		sdhci_msm_ice_update_cfg(host, dun, slot, bypass, key_index,
+					cdu_sz);
 	}
 	return 0;
 }
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index f51ab9e..15f3df9 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -975,6 +975,59 @@
 	}
 }
 
+static bool is_gpio_tlmm_dc(struct irq_data *d, u32 type)
+{
+	const struct msm_pingroup *g;
+	unsigned long flags;
+	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
+	struct msm_pinctrl *pctrl;
+	bool ret = false;
+	unsigned int polarity = 0, offset, val;
+	int i;
+
+	if (!gc)
+		return false;
+
+	pctrl = gpiochip_get_data(gc);
+
+	for (i = 0; i < pctrl->soc->n_dir_conns; i++) {
+		struct msm_dir_conn *dir_conn = (struct msm_dir_conn *)
+			&pctrl->soc->dir_conn[i];
+
+		if (dir_conn->gpio == d->hwirq && dir_conn->tlmm_dc) {
+			ret = true;
+			offset = pctrl->soc->dir_conn_irq_base -
+				dir_conn->hwirq;
+			break;
+		}
+	}
+
+	if (!ret)
+		return ret;
+
+	if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW))
+		return ret;
+
+	/*
+	 * Since the default polarity is set to 0, change it to 1 for
+	 * Rising edge and active high interrupt type such that the line
+	 * is not inverted.
+	 */
+	polarity = 1;
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+	g = &pctrl->soc->groups[d->hwirq];
+
+	val = readl_relaxed(pctrl->regs + g->dir_conn_reg + (offset * 4));
+	val |= polarity << 8;
+
+	writel_relaxed(val, pctrl->regs + g->dir_conn_reg + (offset * 4));
+
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	return ret;
+}
+
 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);
@@ -1283,12 +1336,12 @@
 	if (!parent_data)
 		return 0;
 
-	if (type == IRQ_TYPE_EDGE_BOTH) {
+	if (type == IRQ_TYPE_EDGE_BOTH)
 		add_dirconn_tlmm(d, irq);
-	} else {
-		if (is_gpio_dual_edge(d, &irq))
-			remove_dirconn_tlmm(d, irq);
-	}
+	else if (is_gpio_dual_edge(d, &irq))
+		remove_dirconn_tlmm(d, irq);
+	else if (is_gpio_tlmm_dc(d, type))
+		type = IRQ_TYPE_EDGE_RISING;
 
 	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
 		irq_set_handler_locked(d, handle_level_irq);
@@ -1366,9 +1419,28 @@
 
 	for (i = 0; i < pctrl->soc->n_dir_conns; i++) {
 		const struct msm_dir_conn *dirconn = &pctrl->soc->dir_conn[i];
+		struct irq_data *d;
 
 		request_dc_interrupt(pctrl->chip.irqdomain, pdc_domain,
 					dirconn->hwirq, dirconn->gpio);
+
+		if (!dirconn->gpio)
+			continue;
+
+		if (!dirconn->tlmm_dc)
+			continue;
+
+		/*
+		 * If the gpio is routed through TLMM direct connect interrupts,
+		 * program the TLMM registers for this setup.
+		 */
+		d = irq_get_irq_data(irq_find_mapping(pctrl->chip.irqdomain,
+					dirconn->gpio));
+		if (!d)
+			continue;
+
+		msm_dirconn_cfg_reg(d, pctrl->soc->dir_conn_irq_base
+					- (u32)dirconn->hwirq);
 	}
 
 	for (i = 0; i < pctrl->soc->n_pdc_mux_out; i++) {
@@ -1383,7 +1455,7 @@
 	 * 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++) {
+	for (i = 0; i < pctrl->soc->n_gpio_mux_in; i++) {
 		unsigned int irq;
 		struct irq_data *d;
 		struct msm_gpio_mux_input *gpio_in =
@@ -1403,6 +1475,12 @@
 static int msm_gpiochip_to_irq(struct gpio_chip *chip, unsigned int offset)
 {
 	struct irq_fwspec fwspec;
+	struct irq_domain *domain = chip->irqdomain;
+	int virq;
+
+	virq = irq_find_mapping(domain, offset);
+	if (virq)
+		return virq;
 
 	fwspec.fwnode = of_node_to_fwnode(chip->of_node);
 	fwspec.param[0] = offset;
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
index b8185ae..d0a0766 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.h
+++ b/drivers/pinctrl/qcom/pinctrl-msm.h
@@ -128,10 +128,12 @@
  * struct msm_dir_conn - Direct GPIO connect configuration
  * @gpio:	GPIO pin number
  * @hwirq:	The GIC interrupt that the pin is connected to
+ * @tlmm_dc:	indicates if the GPIO is routed to GIC directly
  */
 struct msm_dir_conn {
 	unsigned int gpio;
 	irq_hw_number_t hwirq;
+	bool tlmm_dc;
 };
 
 /**
diff --git a/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
index c5f1307..54d8f56 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdxpoorwills.c
@@ -50,6 +50,7 @@
 		.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,	\
+		.dir_conn_reg = REG_BASE + 0xab000,\
 		.mux_bit = 2,			\
 		.pull_bit = 0,			\
 		.drv_bit = 6,			\
@@ -64,6 +65,7 @@
 		.intr_polarity_bit = 1,		\
 		.intr_detection_bit = 2,	\
 		.intr_detection_width = 2,	\
+		.dir_conn_en_bit = 8,		\
 	}
 
 #define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv)	\
@@ -454,6 +456,7 @@
 	msm_mux_qdss_stm0,
 	msm_mux_dbg_out,
 	msm_mux_gcc_plltest,
+	msm_mux_emac_pps,
 	msm_mux_NA,
 };
 
@@ -830,6 +833,10 @@
 	"gpio73", "gpio74",
 };
 
+static const char * const emac_pps_groups[] = {
+	"gpio89",
+};
+
 static const struct msm_function sdxpoorwills_functions[] = {
 	FUNCTION(uim2_data),
 	FUNCTION(gpio),
@@ -948,6 +955,7 @@
 	FUNCTION(qdss_stm0),
 	FUNCTION(dbg_out),
 	FUNCTION(gcc_plltest),
+	FUNCTION(emac_pps),
 };
 
 /* Every pin is maintained as a single group, and missing or non-existing pin
@@ -1085,7 +1093,8 @@
 	[86] = PINGROUP(86, NA, NA, NA, NA, NA, NA, NA, NA, NA),
 	[87] = PINGROUP(87, NA, NA, NA, NA, NA, NA, NA, NA, NA),
 	[88] = PINGROUP(88, qdss_cti, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
-	[89] = PINGROUP(89, qdss_cti, qdss_cti, NA, NA, NA, NA, NA, NA, NA),
+	[89] = PINGROUP(89, qdss_cti, qdss_cti, emac_pps, NA, NA, NA, NA,
+			NA, NA),
 	[90] = PINGROUP(90, NA, NA, NA, NA, NA, NA, NA, NA, NA),
 	[91] = PINGROUP(91, NA, NA, NA, NA, NA, NA, NA, NA, NA),
 	[92] = PINGROUP(92, NA, NA, NA, NA, NA, NA, NA, NA, NA),
@@ -1151,7 +1160,7 @@
 	{42, 80},
 	{43, 82},
 	{44, 83},
-	{45, 84},
+	{45, 84, 1},
 	{46, 86},
 	{47, 87},
 	{48, 88},
@@ -1196,6 +1205,17 @@
 	{0, 195},
 };
 
+static struct msm_dir_conn sdxpoorwills_dir_conn[] = {
+	{0, 220},
+	{0, 219},
+	{0, 218},
+	{0, 217},
+	{0, 216},
+	{0, 215},
+	{0, 214},
+	{0, 213},
+};
+
 static const struct msm_pinctrl_soc_data sdxpoorwills_pinctrl = {
 	.pins = sdxpoorwills_pins,
 	.npins = ARRAY_SIZE(sdxpoorwills_pins),
@@ -1209,6 +1229,9 @@
 	.n_pdc_mux_out = ARRAY_SIZE(sdxpoorwills_mux_out),
 	.n_pdc_mux_offset = 20,
 	.ngpios = 100,
+	.dir_conn_irq_base = 220,
+	.dir_conn = sdxpoorwills_dir_conn,
+	.n_dir_conns = ARRAY_SIZE(sdxpoorwills_dir_conn),
 };
 
 static int sdxpoorwills_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
index b4af0a09..5085d75 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
@@ -2146,6 +2146,15 @@
 		IPA_MHI_ERR("ipa_mhi_set_state failed %d\n", res);
 		return res;
 	}
+
+	res = ipa_mhi_suspend_dl(force);
+	if (res) {
+		IPA_MHI_ERR("ipa_mhi_suspend_dl failed %d\n", res);
+		goto fail_suspend_dl_channel;
+	}
+
+	usleep_range(IPA_MHI_SUSPEND_SLEEP_MIN, IPA_MHI_SUSPEND_SLEEP_MAX);
+
 	res = ipa_mhi_suspend_ul(force, &empty, &force_clear);
 	if (res) {
 		IPA_MHI_ERR("ipa_mhi_suspend_ul failed %d\n", res);
@@ -2190,12 +2199,6 @@
 #endif
 	usleep_range(IPA_MHI_SUSPEND_SLEEP_MIN, IPA_MHI_SUSPEND_SLEEP_MAX);
 
-	res = ipa_mhi_suspend_dl(force);
-	if (res) {
-		IPA_MHI_ERR("ipa_mhi_suspend_dl failed %d\n", res);
-		goto fail_suspend_dl_channel;
-	}
-
 	if (!empty)
 		ipa_set_tag_process_before_gating(false);
 
@@ -2209,7 +2212,6 @@
 	IPA_MHI_FUNC_EXIT();
 	return 0;
 
-fail_suspend_dl_channel:
 fail_release_cons:
 	if (!ipa_pm_is_used())
 	ipa_mhi_request_prod();
@@ -2225,7 +2227,6 @@
 	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 fail_suspend_ul_channel:
 	ipa_mhi_resume_channels(true, ipa_mhi_client_ctx->ul_channels);
-	ipa_mhi_set_state(IPA_MHI_STATE_STARTED);
 	if (force_clear) {
 		if (
 		ipa_mhi_disable_force_clear(ipa_mhi_client_ctx->qmi_req_id)) {
@@ -2235,6 +2236,9 @@
 		IPA_MHI_DBG("force clear datapath disabled\n");
 		ipa_mhi_client_ctx->qmi_req_id++;
 	}
+fail_suspend_dl_channel:
+	ipa_mhi_resume_channels(true, ipa_mhi_client_ctx->dl_channels);
+	ipa_mhi_set_state(IPA_MHI_STATE_STARTED);
 	return res;
 }
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 5bfb8e4..bc032d9 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -2536,6 +2536,9 @@
 
 	ipa3_q6_pipe_delay(true);
 	ipa3_q6_avoid_holb();
+	if (ipa3_ctx->ipa_config_is_mhi)
+		ipa3_set_reset_client_cons_pipe_sus_holb(true,
+		IPA_CLIENT_MHI_CONS);
 	if (ipa3_q6_clean_q6_tables()) {
 		IPAERR("Failed to clean Q6 tables\n");
 		BUG();
@@ -2548,8 +2551,11 @@
 	 * on pipe reset procedure
 	 */
 	ipa3_q6_pipe_delay(false);
-
-	ipa3_set_usb_prod_pipe_delay();
+	ipa3_set_reset_client_prod_pipe_delay(true,
+		IPA_CLIENT_USB_PROD);
+	if (ipa3_ctx->ipa_config_is_mhi)
+		ipa3_set_reset_client_prod_pipe_delay(true,
+		IPA_CLIENT_MHI_PROD);
 
 	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 	IPADBG_LOW("Exit with success\n");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
index cfac126..bbc3a4f 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
@@ -1331,27 +1331,32 @@
 }
 
 /*
- * Set USB PROD pipe delay for MBIM/RMNET config
+ * Set reset ep_delay for CLEINT PROD pipe
  * Clocks, should be voted before calling this API
  * locks should be taken before calling this API
  */
 
-void ipa3_set_usb_prod_pipe_delay(void)
+int ipa3_set_reset_client_prod_pipe_delay(bool set_reset,
+		enum ipa_client_type client)
 {
-	int result;
+	int result = 0;
 	int pipe_idx;
 	struct ipa3_ep_context *ep;
 	struct ipa_ep_cfg_ctrl ep_ctrl;
 
 	memset(&ep_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
-	ep_ctrl.ipa_ep_delay = true;
+	ep_ctrl.ipa_ep_delay = set_reset;
 
+	if (IPA_CLIENT_IS_CONS(client)) {
+		IPAERR("client (%d) not PROD\n", client);
+		return -EINVAL;
+	}
 
-	pipe_idx = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD);
+	pipe_idx = ipa3_get_ep_mapping(client);
 
 	if (pipe_idx == IPA_EP_NOT_ALLOCATED) {
-		IPAERR("client (%d) not valid\n", IPA_CLIENT_USB_PROD);
-		return;
+		IPAERR("client (%d) not valid\n", client);
+		return -EINVAL;
 	}
 
 	ep = &ipa3_ctx->ep[pipe_idx];
@@ -1368,6 +1373,59 @@
 			IPADBG("client (ep: %d) success\n", pipe_idx);
 	}
 	client_lock_unlock_cb(pipe_idx, false);
+	return result;
+}
+
+int ipa3_set_reset_client_cons_pipe_sus_holb(bool set_reset,
+		enum ipa_client_type client)
+{
+	int pipe_idx;
+	struct ipa3_ep_context *ep;
+	struct ipa_ep_cfg_ctrl ep_suspend;
+	struct ipa_ep_cfg_holb ep_holb;
+
+	memset(&ep_suspend, 0, sizeof(ep_suspend));
+	memset(&ep_holb, 0, sizeof(ep_holb));
+
+	ep_suspend.ipa_ep_suspend = set_reset;
+	ep_holb.tmr_val = 0;
+	ep_holb.en = set_reset;
+
+	if (IPA_CLIENT_IS_PROD(client)) {
+		IPAERR("client (%d) not CONS\n", client);
+		return -EINVAL;
+	}
+
+	pipe_idx = ipa3_get_ep_mapping(client);
+
+	if (pipe_idx == IPA_EP_NOT_ALLOCATED) {
+		IPAERR("client (%d) not valid\n", client);
+		return -EINVAL;
+	}
+
+	ep = &ipa3_ctx->ep[pipe_idx];
+	/* Setting sus/holb on MHI_CONS with skip_ep_cfg */
+	client_lock_unlock_cb(pipe_idx, true);
+	if (ep->valid && ep->skip_ep_cfg) {
+		if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0)
+			ipahal_write_reg_n_fields(
+					IPA_ENDP_INIT_CTRL_n,
+					pipe_idx, &ep_suspend);
+		/*
+		 * ipa3_cfg_ep_holb is not used here because we are
+		 * setting HOLB on Q6 pipes, and from APPS perspective
+		 * they are not valid, therefore, the above function
+		 * will fail.
+		 */
+		ipahal_write_reg_n_fields(
+			IPA_ENDP_INIT_HOL_BLOCK_TIMER_n,
+			pipe_idx, &ep_holb);
+		ipahal_write_reg_n_fields(
+			IPA_ENDP_INIT_HOL_BLOCK_EN_n,
+			pipe_idx, &ep_holb);
+	}
+	client_lock_unlock_cb(pipe_idx, false);
+	return 0;
 }
 
 void ipa3_xdci_ep_delay_rm(u32 clnt_hdl)
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 43f4c74..6dc2905 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1922,7 +1922,10 @@
 void ipa3_xdci_ep_delay_rm(u32 clnt_hdl);
 void ipa3_register_lock_unlock_callback(int (*client_cb)(bool), u32 ipa_ep_idx);
 void ipa3_deregister_lock_unlock_callback(u32 ipa_ep_idx);
-void ipa3_set_usb_prod_pipe_delay(void);
+int ipa3_set_reset_client_prod_pipe_delay(bool set_reset,
+		enum ipa_client_type client);
+int ipa3_set_reset_client_cons_pipe_sus_holb(bool set_reset,
+		enum ipa_client_type client);
 
 int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl,
 	bool should_force_clear, u32 qmi_req_id, bool is_dpl);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
index dd97038..9075237 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
@@ -199,6 +199,7 @@
 	struct ipa3_ep_context *ep;
 	const struct ipa_gsi_ep_config *ep_cfg;
 	bool burst_mode_enabled = false;
+	struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
 
 	IPA_MHI_FUNC_ENTRY();
 
@@ -341,6 +342,20 @@
 
 	*params->mhi = ch_scratch.mhi;
 
+	if (IPA_CLIENT_IS_PROD(ep->client) && ep->skip_ep_cfg) {
+		memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
+		ep_cfg_ctrl.ipa_ep_delay = true;
+		ep->ep_delay_set = true;
+		res = ipa3_cfg_ep_ctrl(ipa_ep_idx, &ep_cfg_ctrl);
+		if (res)
+			IPA_MHI_ERR("client (ep: %d) failed result=%d\n",
+			ipa_ep_idx, res);
+		else
+			IPA_MHI_DBG("client (ep: %d) success\n", ipa_ep_idx);
+	} else {
+		ep->ep_delay_set = false;
+	}
+
 	IPA_MHI_DBG("Starting channel\n");
 	res = gsi_start_channel(ep->gsi_chan_hdl);
 	if (res) {
@@ -524,6 +539,7 @@
 {
 	struct ipa3_ep_context *ep;
 	int res;
+	struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
 
 	IPA_MHI_FUNC_ENTRY();
 
@@ -538,6 +554,21 @@
 	}
 
 	ep = &ipa3_ctx->ep[clnt_hdl];
+	if (ep->ep_delay_set == true) {
+		memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
+		ep_cfg_ctrl.ipa_ep_delay = false;
+		res = ipa3_cfg_ep_ctrl(clnt_hdl,
+			&ep_cfg_ctrl);
+		if (res) {
+			IPAERR
+			("client(ep:%d) failed to remove delay res=%d\n",
+				clnt_hdl, res);
+		} else {
+			IPADBG("client (ep: %d) delay removed\n",
+				clnt_hdl);
+			ep->ep_delay_set = false;
+		}
+	}
 
 	res = gsi_dealloc_channel(ep->gsi_chan_hdl);
 	if (res) {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
index 736c0fb..2212b00 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
@@ -908,6 +908,20 @@
 	return 0;
 }
 
+static int __ipa_rt_validate_rule_id(u16 rule_id)
+{
+	if (!rule_id)
+		return 0;
+
+	if ((rule_id < ipahal_get_rule_id_hi_bit()) ||
+		(rule_id >= ((ipahal_get_rule_id_hi_bit()<<1)-1))) {
+		IPAERR_RL("Invalid rule_id provided 0x%x\n",
+			rule_id);
+		return -EPERM;
+	}
+
+	return 0;
+}
 static int __ipa_rt_validate_hndls(const struct ipa_rt_rule *rule,
 				struct ipa3_hdr_entry **hdr,
 				struct ipa3_hdr_proc_ctx_entry **proc_ctx)
@@ -1023,6 +1037,8 @@
 	if (__ipa_rt_validate_hndls(rule, &hdr, &proc_ctx))
 		goto error;
 
+	if (__ipa_rt_validate_rule_id(rule_id))
+		goto error;
 
 	tbl = __ipa_add_rt_tbl(ip, name);
 	if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) {
diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c
index 0b8c212..37ae308 100644
--- a/drivers/power/reset/msm-poweroff.c
+++ b/drivers/power/reset/msm-poweroff.c
@@ -50,20 +50,23 @@
 #define SCM_DLOAD_BOTHDUMPS	(SCM_DLOAD_MINIDUMP | SCM_DLOAD_FULLDUMP)
 
 static int restart_mode;
-static void __iomem *restart_reason, *dload_type_addr;
+static void *restart_reason;
 static bool scm_pmic_arbiter_disable_supported;
 static bool scm_deassert_ps_hold_supported;
 /* Download mode master kill-switch */
 static void __iomem *msm_ps_hold;
 static phys_addr_t tcsr_boot_misc_detect;
+static void scm_disable_sdi(void);
+
+#ifdef CONFIG_QCOM_DLOAD_MODE
 /* Runtime could be only changed value once.
  * There is no API from TZ to re-enable the registers.
  * So the SDI cannot be re-enabled when it already by-passed.
  */
 static int download_mode = 1;
-static struct kobject dload_kobj;
-static void scm_disable_sdi(void);
-
+#else
+static const int download_mode;
+#endif
 
 #ifdef CONFIG_QCOM_DLOAD_MODE
 #define EDL_MODE_PROP "qcom,msm-imem-emergency_download_mode"
@@ -81,6 +84,8 @@
 static void *kaslr_imem_addr;
 #endif
 static bool scm_dload_supported;
+static struct kobject dload_kobj;
+static void *dload_type_addr;
 
 static int dload_set(const char *val, const struct kernel_param *kp);
 /* interface for exporting attributes */
@@ -431,6 +436,7 @@
 	pr_err("Powering off has failed\n");
 }
 
+#ifdef CONFIG_QCOM_DLOAD_MODE
 static ssize_t attr_show(struct kobject *kobj, struct attribute *attr,
 				char *buf)
 {
@@ -561,6 +567,7 @@
 static struct attribute_group reset_attr_group = {
 	.attrs = reset_attrs,
 };
+#endif
 
 static int msm_restart_probe(struct platform_device *pdev)
 {
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 36521a1..c596f54 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -573,14 +573,15 @@
 		return rc;
 	}
 
-	*val = div_s64(cc_soc * chip->cl.nom_cap_uah, CC_SOC_30BIT);
+	*val = div_s64((int64_t)cc_soc * chip->cl.nom_cap_uah, CC_SOC_30BIT);
 	return 0;
 }
 
 #define BATT_SOC_32BIT	GENMASK(31, 0)
 static int fg_get_charge_counter_shadow(struct fg_chip *chip, int *val)
 {
-	int rc, batt_soc;
+	int rc;
+	unsigned int batt_soc;
 
 	rc = fg_get_sram_prop(chip, FG_SRAM_BATT_SOC, &batt_soc);
 	if (rc < 0) {
@@ -588,13 +589,15 @@
 		return rc;
 	}
 
-	*val = div_u64((u32)batt_soc * chip->cl.learned_cc_uah, BATT_SOC_32BIT);
+	*val = div_u64((uint64_t)batt_soc * chip->cl.learned_cc_uah,
+							BATT_SOC_32BIT);
 	return 0;
 }
 
 static int fg_get_charge_counter(struct fg_chip *chip, int *val)
 {
-	int rc, cc_soc;
+	int rc;
+	int cc_soc;
 
 	rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc);
 	if (rc < 0) {
@@ -602,7 +605,7 @@
 		return rc;
 	}
 
-	*val = div_s64(cc_soc * chip->cl.learned_cc_uah, CC_SOC_30BIT);
+	*val = div_s64((int64_t)cc_soc * chip->cl.learned_cc_uah, CC_SOC_30BIT);
 	return 0;
 }
 
@@ -1296,7 +1299,7 @@
 	return true;
 }
 
-static int fg_prime_cc_soc_sw(struct fg_chip *chip, int cc_soc_sw)
+static int fg_prime_cc_soc_sw(struct fg_chip *chip, unsigned int cc_soc_sw)
 {
 	int rc;
 
@@ -1306,7 +1309,7 @@
 	if (rc < 0)
 		pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
 	else
-		fg_dbg(chip, FG_STATUS, "cc_soc_sw: %x\n", cc_soc_sw);
+		fg_dbg(chip, FG_STATUS, "cc_soc_sw: %u\n", cc_soc_sw);
 
 	return rc;
 }
@@ -1469,8 +1472,10 @@
 
 static int fg_cap_learning_process_full_data(struct fg_chip *chip)
 {
-	int rc, cc_soc_sw, cc_soc_delta_pct;
+	int rc;
+	unsigned int cc_soc_sw;
 	int64_t delta_cc_uah;
+	unsigned int cc_soc_delta_pct;
 
 	rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc_sw);
 	if (rc < 0) {
@@ -1488,31 +1493,32 @@
 		return -ERANGE;
 	}
 
-	delta_cc_uah = div64_s64(chip->cl.learned_cc_uah * cc_soc_delta_pct,
+	delta_cc_uah = div64_u64(chip->cl.learned_cc_uah * cc_soc_delta_pct,
 				100);
 	chip->cl.final_cc_uah = chip->cl.init_cc_uah + delta_cc_uah;
-	fg_dbg(chip, FG_CAP_LEARN, "Current cc_soc=%d cc_soc_delta_pct=%d total_cc_uah=%lld\n",
+	fg_dbg(chip, FG_CAP_LEARN, "Current cc_soc=%d cc_soc_delta_pct=%u total_cc_uah=%llu\n",
 		cc_soc_sw, cc_soc_delta_pct, chip->cl.final_cc_uah);
 	return 0;
 }
 
 static int fg_cap_learning_begin(struct fg_chip *chip, u32 batt_soc)
 {
-	int rc, cc_soc_sw, batt_soc_msb;
+	int rc;
+	unsigned int batt_soc_msb, cc_soc_sw;
 
 	batt_soc_msb = batt_soc >> 24;
 	if (DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW) >
 		chip->dt.cl_start_soc) {
-		fg_dbg(chip, FG_CAP_LEARN, "Battery SOC %d is high!, not starting\n",
+		fg_dbg(chip, FG_CAP_LEARN, "Battery SOC %u is high!, not starting\n",
 			batt_soc_msb);
 		return -EINVAL;
 	}
 
-	chip->cl.init_cc_uah = div64_s64(chip->cl.learned_cc_uah * batt_soc_msb,
+	chip->cl.init_cc_uah = div64_u64(chip->cl.learned_cc_uah * batt_soc_msb,
 					FULL_SOC_RAW);
 
 	/* Prime cc_soc_sw with battery SOC when capacity learning begins */
-	cc_soc_sw = div64_s64((int64_t)batt_soc * CC_SOC_30BIT,
+	cc_soc_sw = div64_u64((uint64_t)batt_soc * CC_SOC_30BIT,
 				BATT_SOC_32BIT);
 	rc = fg_prime_cc_soc_sw(chip, cc_soc_sw);
 	if (rc < 0) {
@@ -1529,7 +1535,8 @@
 
 static int fg_cap_learning_done(struct fg_chip *chip)
 {
-	int rc, cc_soc_sw;
+	int rc;
+	unsigned int cc_soc_sw;
 
 	rc = fg_cap_learning_process_full_data(chip);
 	if (rc < 0) {
@@ -1553,7 +1560,8 @@
 
 static void fg_cap_learning_update(struct fg_chip *chip)
 {
-	int rc, batt_soc, batt_soc_msb, cc_soc_sw;
+	int rc;
+	unsigned int batt_soc, batt_soc_msb, cc_soc_sw;
 	bool input_present = is_input_present(chip);
 	bool prime_cc = false;
 
@@ -1640,7 +1648,7 @@
 		if (chip->charge_done)
 			cc_soc_sw = CC_SOC_30BIT;
 		else
-			cc_soc_sw = div_u64((u32)batt_soc *
+			cc_soc_sw = div_u64((uint64_t)batt_soc *
 					CC_SOC_30BIT, BATT_SOC_32BIT);
 
 		rc = fg_prime_cc_soc_sw(chip, cc_soc_sw);
diff --git a/drivers/power/supply/qcom/qpnp-linear-charger.c b/drivers/power/supply/qcom/qpnp-linear-charger.c
index aedc77a..7815eba 100644
--- a/drivers/power/supply/qcom/qpnp-linear-charger.c
+++ b/drivers/power/supply/qcom/qpnp-linear-charger.c
@@ -2877,7 +2877,8 @@
 			IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 1);
 
 	REQUEST_IRQ(chip, USBIN_VALID, rc, usbin_valid, 1,
-			IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 1);
+			IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING
+			| IRQF_ONESHOT, 1);
 
 	REQUEST_IRQ(chip, USB_CHG_GONE, rc, chg_gone, 0,
 			IRQF_TRIGGER_RISING, 1);
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 56a09c6..e3e4f2b 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -985,6 +985,7 @@
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CURRENT_QNOVO,
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
 	POWER_SUPPLY_PROP_TEMP,
 	POWER_SUPPLY_PROP_TECHNOLOGY,
 	POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
@@ -1076,6 +1077,10 @@
 		val->intval = get_client_vote(chg->fcc_votable,
 					      BATT_PROFILE_VOTER);
 		break;
+	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+		val->intval = get_client_vote(chg->fcc_votable,
+					      FG_ESR_VOTER);
+		break;
 	case POWER_SUPPLY_PROP_TECHNOLOGY:
 		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
 		break;
@@ -1183,6 +1188,12 @@
 		chg->batt_profile_fcc_ua = val->intval;
 		vote(chg->fcc_votable, BATT_PROFILE_VOTER, true, val->intval);
 		break;
+	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+		if (val->intval)
+			vote(chg->fcc_votable, FG_ESR_VOTER, true, val->intval);
+		else
+			vote(chg->fcc_votable, FG_ESR_VOTER, false, 0);
+		break;
 	case POWER_SUPPLY_PROP_SET_SHIP_MODE:
 		/* Not in ship mode as long as the device is active */
 		if (!val->intval)
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index 71a4369..e56ecb0 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -1260,6 +1260,52 @@
 	POWER_SUPPLY_PROP_CHARGE_FULL,
 };
 
+#define ITERM_SCALING_FACTOR_PMI632	1525
+#define ITERM_SCALING_FACTOR_PM855B	3050
+static int smb5_get_prop_batt_iterm(struct smb_charger *chg,
+		union power_supply_propval *val)
+{
+	int rc, temp, scaling_factor;
+	u8 stat, buf[2];
+
+	/*
+	 * Currently, only ADC comparator-based termination is supported,
+	 * hence read only the threshold corresponding to ADC source.
+	 * Proceed only if CHGR_ITERM_USE_ANALOG_BIT is 0.
+	 */
+	rc = smblib_read(chg, CHGR_ENG_CHARGING_CFG_REG, &stat);
+	if (rc < 0) {
+		pr_err("Couldn't read CHGR_ENG_CHARGING_CFG_REG rc=%d\n", rc);
+		return rc;
+	}
+
+	if (stat & CHGR_ITERM_USE_ANALOG_BIT) {
+		val->intval = -EINVAL;
+		return 0;
+	}
+
+	rc = smblib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, buf, 2);
+
+	if (rc < 0) {
+		pr_err("Couldn't read CHGR_ADC_ITERM_UP_THD_MSB_REG rc=%d\n",
+				rc);
+		return rc;
+	}
+
+	temp = buf[1] | (buf[0] << 8);
+	temp = sign_extend32(temp, 15);
+
+	if (chg->smb_version == PMI632_SUBTYPE)
+		scaling_factor = ITERM_SCALING_FACTOR_PMI632;
+	else
+		scaling_factor = ITERM_SCALING_FACTOR_PM855B;
+
+	temp = div_s64(temp * scaling_factor, 10000);
+	val->intval = temp;
+
+	return rc;
+}
+
 static int smb5_batt_get_prop(struct power_supply *psy,
 		enum power_supply_property psp,
 		union power_supply_propval *val)
@@ -1322,7 +1368,7 @@
 					      BATT_PROFILE_VOTER);
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
-		rc = smblib_get_prop_batt_iterm(chg, val);
+		rc = smb5_get_prop_batt_iterm(chg, val);
 		break;
 	case POWER_SUPPLY_PROP_TEMP:
 		rc = smblib_get_prop_from_bms(chg, POWER_SUPPLY_PROP_TEMP, val);
@@ -1772,30 +1818,42 @@
 	return 0;
 }
 
+#define RAW_TERM_CURR(conv_factor, scaled_ma)	\
+				div_s64((int64_t)scaled_ma * 10000, conv_factor)
+#define ITERM_LIMITS_PMI632_MA	5000
+#define ITERM_LIMITS_PM855B_MA	10000
 static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip)
 {
 	u8 *buf;
 	int rc = 0;
-	s16 raw_hi_thresh, raw_lo_thresh;
+	int raw_hi_thresh, raw_lo_thresh, max_limit_ma, scaling_factor;
 	struct smb_charger *chg = &chip->chg;
 
-	if (chip->dt.term_current_thresh_hi_ma < -10000 ||
-			chip->dt.term_current_thresh_hi_ma > 10000 ||
-			chip->dt.term_current_thresh_lo_ma < -10000 ||
-			chip->dt.term_current_thresh_lo_ma > 10000) {
+	if (chip->chg.smb_version == PMI632_SUBTYPE) {
+		scaling_factor = ITERM_SCALING_FACTOR_PMI632;
+		max_limit_ma = ITERM_LIMITS_PMI632_MA;
+	} else {
+		scaling_factor = ITERM_SCALING_FACTOR_PM855B;
+		max_limit_ma = ITERM_LIMITS_PM855B_MA;
+	}
+
+	if (chip->dt.term_current_thresh_hi_ma < (-1 * max_limit_ma)
+		|| chip->dt.term_current_thresh_hi_ma > max_limit_ma
+		|| chip->dt.term_current_thresh_lo_ma < (-1 * max_limit_ma)
+		|| chip->dt.term_current_thresh_lo_ma > max_limit_ma) {
 		dev_err(chg->dev, "ITERM threshold out of range rc=%d\n", rc);
 		return -EINVAL;
 	}
 
 	/*
 	 * Conversion:
-	 *	raw (A) = (scaled_mA * ADC_CHG_TERM_MASK) / (10 * 1000)
+	 *	raw (A) = (scaled_mA * (10000) / conv_factor)
 	 * Note: raw needs to be converted to big-endian format.
 	 */
 
 	if (chip->dt.term_current_thresh_hi_ma) {
-		raw_hi_thresh = ((chip->dt.term_current_thresh_hi_ma *
-						ADC_CHG_TERM_MASK) / 10000);
+		raw_hi_thresh = RAW_TERM_CURR(scaling_factor,
+					chip->dt.term_current_thresh_hi_ma);
 		raw_hi_thresh = sign_extend32(raw_hi_thresh, 15);
 		buf = (u8 *)&raw_hi_thresh;
 		raw_hi_thresh = buf[1] | (buf[0] << 8);
@@ -1810,8 +1868,8 @@
 	}
 
 	if (chip->dt.term_current_thresh_lo_ma) {
-		raw_lo_thresh = ((chip->dt.term_current_thresh_lo_ma *
-					ADC_CHG_TERM_MASK) / 10000);
+		raw_lo_thresh = RAW_TERM_CURR(scaling_factor,
+					chip->dt.term_current_thresh_lo_ma);
 		raw_lo_thresh = sign_extend32(raw_lo_thresh, 15);
 		buf = (u8 *)&raw_lo_thresh;
 		raw_lo_thresh = buf[1] | (buf[0] << 8);
@@ -2438,6 +2496,7 @@
 	[TYPEC_ATTACH_DETACH_IRQ] = {
 		.name		= "typec-attach-detach",
 		.handler	= typec_attach_detach_irq_handler,
+		.wake		= true,
 	},
 	[TYPEC_LEGACY_CABLE_DETECT_IRQ] = {
 		.name		= "typec-legacy-cable-detect",
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 5b94ff2..6b6bc9c 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -3123,7 +3123,9 @@
 		return 0;
 
 	chg->cc2_detach_wa_active = false;
+	chg->in_chg_lock = true;
 	cancel_work_sync(&chg->rdstd_cc2_detach_work);
+	chg->in_chg_lock = false;
 	smblib_reg_block_restore(chg, cc2_detach_settings);
 	return 0;
 }
@@ -4757,7 +4759,6 @@
 {
 	int rc;
 	u8 stat4, stat5;
-	bool lock = false;
 	struct smb_charger *chg = container_of(work, struct smb_charger,
 						rdstd_cc2_detach_work);
 
@@ -4826,22 +4827,15 @@
 	 * during pd_hard_reset from the function smblib_cc2_sink_removal_exit
 	 * which is called in the same lock context that we try to acquire in
 	 * this work routine.
-	 * Check if this work is running during pd_hard_reset and use trylock
-	 * instead of mutex_lock to prevent any deadlock if mutext is already
-	 * held.
+	 * Check if this work is running during pd_hard_reset and skip holding
+	 * mutex if lock is already held.
 	 */
-	if (chg->pd_hard_reset) {
-		if (mutex_trylock(&chg->lock))
-			lock = true;
-	} else {
+	if (!chg->in_chg_lock)
 		mutex_lock(&chg->lock);
-		lock = true;
-	}
-
 	smblib_usb_typec_change(chg);
-
-	if (lock)
+	if (!chg->in_chg_lock)
 		mutex_unlock(&chg->lock);
+
 	return;
 
 rerun:
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 3b8bc1f..2457ed2 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -71,6 +71,7 @@
 #define MOISTURE_VOTER			"MOISTURE_VOTER"
 #define HVDCP2_ICL_VOTER		"HVDCP2_ICL_VOTER"
 #define OV_VOTER			"OV_VOTER"
+#define FG_ESR_VOTER			"FG_ESR_VOTER"
 
 #define VCONN_MAX_ATTEMPTS	3
 #define OTG_MAX_ATTEMPTS	3
@@ -354,6 +355,7 @@
 	bool			otg_present;
 	bool			is_audio_adapter;
 	bool			disable_stat_sw_override;
+	bool			in_chg_lock;
 
 	/* workaround flag */
 	u32			wa_flags;
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index 054d153..f91d477 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -1598,45 +1598,6 @@
 	return 0;
 }
 
-int smblib_get_prop_batt_iterm(struct smb_charger *chg,
-		union power_supply_propval *val)
-{
-	int rc, temp;
-	u8 stat, buf[2];
-
-	/*
-	 * Currently, only ADC comparator-based termination is supported,
-	 * hence read only the threshold corresponding to ADC source.
-	 * Proceed only if CHGR_ITERM_USE_ANALOG_BIT is 0.
-	 */
-	rc = smblib_read(chg, CHGR_ENG_CHARGING_CFG_REG, &stat);
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't read CHGR_ENG_CHARGING_CFG_REG rc=%d\n",
-				rc);
-		return rc;
-	}
-
-	if (stat & CHGR_ITERM_USE_ANALOG_BIT) {
-		val->intval = -EINVAL;
-		return 0;
-	}
-
-	rc = smblib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, buf, 2);
-
-	if (rc < 0) {
-		smblib_err(chg, "Couldn't read CHGR_ADC_ITERM_UP_THD_MSB_REG rc=%d\n",
-				rc);
-		return rc;
-	}
-
-	temp = buf[1] | (buf[0] << 8);
-	temp = sign_extend32(temp, 15);
-	temp = DIV_ROUND_CLOSEST(temp * 10000, ADC_CHG_TERM_MASK);
-	val->intval = temp;
-
-	return rc;
-}
-
 int smblib_get_prop_batt_charge_done(struct smb_charger *chg,
 					union power_supply_propval *val)
 {
@@ -1720,9 +1681,6 @@
 		return -EINVAL;
 
 	chg->system_temp_level = val->intval;
-	/* disable parallel charge in case of system temp level */
-	vote(chg->pl_disable_votable, THERMAL_DAEMON_VOTER,
-			chg->system_temp_level ? true : false, 0);
 
 	if (chg->system_temp_level == chg->thermal_levels)
 		return vote(chg->chg_disable_votable,
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index c252ef0..9afd7cd 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -84,7 +84,6 @@
 #define TYPEC_DEFAULT_CURRENT_UA	900000
 #define TYPEC_MEDIUM_CURRENT_UA		1500000
 #define TYPEC_HIGH_CURRENT_UA		3000000
-#define ADC_CHG_TERM_MASK	32767
 
 enum smb_mode {
 	PARALLEL_MASTER = 0,
@@ -500,8 +499,6 @@
 				union power_supply_propval *val);
 int smblib_get_prop_input_current_limited(struct smb_charger *chg,
 				union power_supply_propval *val);
-int smblib_get_prop_batt_iterm(struct smb_charger *chg,
-				union power_supply_propval *val);
 int smblib_set_prop_input_suspend(struct smb_charger *chg,
 				const union power_supply_propval *val);
 int smblib_set_prop_batt_capacity(struct smb_charger *chg,
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 0ae6979..4dfd8d3 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -897,17 +897,16 @@
 		req = lrbp->cmd->request;
 	else
 		return 0;
-	/*
-	 * Right now ICE do not support variable dun but can be
-	 * taken as future enhancement
-	 * if (bio_dun(req->bio)) {
-	 *      dun @bio can be split, so we have to adjust offset
-	 *      *dun = bio_dun(req->bio);
-	 * } else
-	 */
+
+	/* Use request LBA or given dun as the DUN value */
 	if (req->bio) {
-		*dun = req->bio->bi_iter.bi_sector;
-		*dun >>= UFS_QCOM_ICE_TR_DATA_UNIT_4_KB;
+		if (bio_dun(req->bio)) {
+			/* dun @bio can be split, so we have to adjust offset */
+			*dun = bio_dun(req->bio);
+		} else {
+			*dun = req->bio->bi_iter.bi_sector;
+			*dun >>= UFS_QCOM_ICE_TR_DATA_UNIT_4_KB;
+		}
 	}
 
 	ret = ufs_qcom_ice_req_setup(host, lrbp->cmd, cc_index, enable);
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 52d9f65..0e16501 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -195,6 +195,43 @@
 	  Client driver for the WCNSS_CTRL SMD channel, used to download nv
 	  firmware to a newly booted WCNSS chip.
 
+config SETUP_SSR_NOTIF_TIMEOUTS
+	bool "Set timeouts on SSR sysmon notifications and notifier callbacks"
+	help
+	  Setup timers prior to initiating communication between
+	  subsystems through sysmon, and prior to sending notifications
+	  to drivers in the kernel that have registered callbacks with the
+	  subsystem notifier framework for a particular subsystem. This
+	  is a debugging feature.
+
+config SSR_SYSMON_NOTIF_TIMEOUT
+	depends on SETUP_SSR_NOTIF_TIMEOUTS
+	int "SSR Sysmon notifications timeout in ms"
+	default 10000
+	help
+	  The amount of time, in milliseconds, that should elapse between
+	  the start and end of sysmon SSR notifications, before a warning
+	  is emitted.
+
+config SSR_SUBSYS_NOTIF_TIMEOUT
+	depends on SETUP_SSR_NOTIF_TIMEOUTS
+	int "SSR Subsystem notifier timeout in ms"
+	default 10000
+	help
+	  The amount of time, in milliseconds, that should elapse between
+	  the start and end of SSR notifications through the subsystem
+	  notifier, before a warning is emitted.
+
+config PANIC_ON_SSR_NOTIF_TIMEOUT
+	bool "Trigger kernel panic when notification timeout expires"
+	depends on SETUP_SSR_NOTIF_TIMEOUTS
+	help
+	  Trigger a kernel panic when communication between subsystems
+	  through sysmon is taking too long. Also trigger a kernel panic
+	  if invoking the callbacks registered with a particular subsystem's
+	  notifications by the subsystem notifier framework is taking too long.
+	  This is a debugging feature.
+
 config MSM_BOOT_STATS
 	bool "Use MSM boot stats reporting"
 	help
diff --git a/drivers/soc/qcom/bam_dmux.c b/drivers/soc/qcom/bam_dmux.c
index 3b75e74..84e5193 100644
--- a/drivers/soc/qcom/bam_dmux.c
+++ b/drivers/soc/qcom/bam_dmux.c
@@ -1099,6 +1099,12 @@
 		kfree(hdr);
 		return -ENODEV;
 	}
+	if (in_global_reset) {
+		BAM_DMUX_LOG("%s: In SSR... ch_id[%d]\n", __func__, id);
+		spin_unlock_irqrestore(&bam_ch[id].lock, flags);
+		kfree(hdr);
+		return -ENODEV;
+	}
 
 	bam_ch[id].notify = notify;
 	bam_ch[id].priv = priv;
@@ -1177,6 +1183,12 @@
 		return 0;
 	}
 
+	if (in_global_reset) {
+		BAM_DMUX_LOG("%s: In SSR... ch_id[%d]\n", __func__, id);
+		read_unlock(&ul_wakeup_lock);
+		return 0;
+	}
+
 	hdr = kmalloc(sizeof(struct bam_mux_hdr), GFP_ATOMIC);
 	if (hdr == NULL) {
 		read_unlock(&ul_wakeup_lock);
diff --git a/drivers/soc/qcom/bgcom_spi.c b/drivers/soc/qcom/bgcom_spi.c
index 446669f..d21e2e9 100644
--- a/drivers/soc/qcom/bgcom_spi.c
+++ b/drivers/soc/qcom/bgcom_spi.c
@@ -928,6 +928,8 @@
 		pr_debug("No callback registered\n");
 		return IRQ_HANDLED;
 	} else if (spi_state == BGCOM_SPI_BUSY) {
+		/* delay for SPI to be freed */
+		msleep(50);
 		return IRQ_HANDLED;
 	} else if (!bg_spi->irq_lock) {
 		bg_spi->irq_lock = 1;
diff --git a/drivers/soc/qcom/big_cluster_min_freq_adjust.c b/drivers/soc/qcom/big_cluster_min_freq_adjust.c
index 979dd81..32feedc 100644
--- a/drivers/soc/qcom/big_cluster_min_freq_adjust.c
+++ b/drivers/soc/qcom/big_cluster_min_freq_adjust.c
@@ -180,6 +180,11 @@
 	if (!p->min_freq_floor)
 		p->min_freq_floor = POLICY_MIN;
 
+	p->min_freq_state = RESET_MIN_FLOOR;
+	p->min_freq_request = RESET_MIN_FLOOR;
+	spin_lock_init(&p->lock);
+	p->big_min_freq_on = true;
+
 	ret = cpu_pm_register_notifier(&cpu_pm_nb);
 	if (ret) {
 		pr_err("Failed to register for PM notification\n");
@@ -193,11 +198,6 @@
 		return ret;
 	}
 
-	p->min_freq_state = RESET_MIN_FLOOR;
-	p->min_freq_request = RESET_MIN_FLOOR;
-	spin_lock_init(&p->lock);
-	p->big_min_freq_on = true;
-
 	/* If BIG cluster is active at this time and continue to be active
 	 * forever, in that case min frequency of the cluster will never be
 	 * set to floor value.  This is to trigger the state machine and set
diff --git a/drivers/soc/qcom/dcc.c b/drivers/soc/qcom/dcc.c
index bef0757..3f4ad5d 100644
--- a/drivers/soc/qcom/dcc.c
+++ b/drivers/soc/qcom/dcc.c
@@ -39,8 +39,6 @@
 #define dcc_readl(drvdata, off)						\
 	__raw_readl(drvdata->base + off)
 
-#define dcc_sram_writel(drvdata, val, off)				\
-	__raw_writel((val), drvdata->ram_base + off)
 #define dcc_sram_readl(drvdata, off)					\
 	__raw_readl(drvdata->ram_base + off)
 
@@ -129,6 +127,16 @@
 	uint64_t		xpu_addr;
 	uint32_t		xpu_unlock_count;
 };
+static int dcc_sram_writel(struct dcc_drvdata *drvdata,
+					uint32_t val, uint32_t off)
+{
+	if (unlikely(off > (drvdata->ram_size - 4)))
+		return -EINVAL;
+
+	__raw_writel((val), drvdata->ram_base + off);
+
+	return 0;
+}
 
 static int dcc_cfg_xpu(struct dcc_drvdata *drvdata, bool enable)
 {
@@ -277,12 +285,17 @@
 		if (!prev_addr || prev_addr != addr || prev_off > off) {
 			/* Check if we need to write link of prev entry */
 			if (link) {
-				dcc_sram_writel(drvdata, link, sram_offset);
+				ret = dcc_sram_writel(drvdata,
+							link, sram_offset);
+				if (ret)
+					goto overstep;
 				sram_offset += 4;
 			}
 
 			/* Write address */
-			dcc_sram_writel(drvdata, addr, sram_offset);
+			ret = dcc_sram_writel(drvdata, addr, sram_offset);
+			if (ret)
+				goto overstep;
 			sram_offset += 4;
 
 			/* Reset link and prev_off */
@@ -322,7 +335,9 @@
 			 ((entry->len << 8) & BM(8, 14))) << pos;
 
 		if (pos) {
-			dcc_sram_writel(drvdata, link, sram_offset);
+			ret = dcc_sram_writel(drvdata, link, sram_offset);
+			if (ret)
+				goto overstep;
 			sram_offset += 4;
 			link = 0;
 		}
@@ -332,12 +347,16 @@
 	}
 
 	if (link) {
-		dcc_sram_writel(drvdata, link, sram_offset);
+		ret = dcc_sram_writel(drvdata, link, sram_offset);
+		if (ret)
+			goto overstep;
 		sram_offset += 4;
 	}
 
 	/* Setting zero to indicate end of the list */
-	dcc_sram_writel(drvdata, 0, sram_offset);
+	ret = dcc_sram_writel(drvdata, 0, sram_offset);
+	if (ret)
+		goto overstep;
 	sram_offset += 4;
 
 	/* check if the data will overstep */
diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c
index ac50996..279461d 100644
--- a/drivers/soc/qcom/dcc_v2.c
+++ b/drivers/soc/qcom/dcc_v2.c
@@ -35,8 +35,6 @@
 #define dcc_readl(drvdata, off)						\
 	__raw_readl(drvdata->base + off)
 
-#define dcc_sram_writel(drvdata, val, off)				\
-	__raw_writel((val), drvdata->ram_base + off)
 #define dcc_sram_readl(drvdata, off)					\
 	__raw_readl(drvdata->ram_base + off)
 
@@ -153,6 +151,17 @@
 	uint8_t			cti_trig;
 };
 
+static int dcc_sram_writel(struct dcc_drvdata *drvdata,
+					uint32_t val, uint32_t off)
+{
+	if (unlikely(off > (drvdata->ram_size - 4)))
+		return -EINVAL;
+
+	__raw_writel((val), drvdata->ram_base + off);
+
+	return 0;
+}
+
 static bool dcc_ready(struct dcc_drvdata *drvdata)
 {
 	uint32_t val;
@@ -252,7 +261,10 @@
 				 * processing the list
 				 */
 				link |= ((0x1 << 8) & BM(8, 14));
-				dcc_sram_writel(drvdata, link, sram_offset);
+				ret = dcc_sram_writel(drvdata,
+							link, sram_offset);
+				if (ret)
+					goto overstep;
 				sram_offset += 4;
 				/* Reset link and prev_off */
 				addr = 0x00;
@@ -262,13 +274,21 @@
 			}
 
 			addr = DCC_RD_MOD_WR_DESCRIPTOR;
-			dcc_sram_writel(drvdata, addr, sram_offset);
+			ret = dcc_sram_writel(drvdata, addr, sram_offset);
+			if (ret)
+				goto overstep;
 				sram_offset += 4;
 
-			dcc_sram_writel(drvdata, entry->mask, sram_offset);
+			ret = dcc_sram_writel(drvdata,
+					entry->mask, sram_offset);
+			if (ret)
+				goto overstep;
 				sram_offset += 4;
 
-			dcc_sram_writel(drvdata, entry->write_val, sram_offset);
+			ret = dcc_sram_writel(drvdata,
+					entry->write_val, sram_offset);
+			if (ret)
+				goto overstep;
 				sram_offset += 4;
 			addr = 0;
 			break;
@@ -278,7 +298,10 @@
 		{
 			/* Check if we need to write link of prev entry */
 			if (link) {
-				dcc_sram_writel(drvdata, link, sram_offset);
+				ret = dcc_sram_writel(drvdata,
+						link, sram_offset);
+				if (ret)
+					goto overstep;
 				sram_offset += 4;
 			}
 
@@ -288,7 +311,10 @@
 				loop |= DCC_LOOP_DESCRIPTOR;
 				total_len += (total_len - loop_len) * loop_cnt;
 
-				dcc_sram_writel(drvdata, loop, sram_offset);
+				ret = dcc_sram_writel(drvdata,
+						loop, sram_offset);
+				if (ret)
+					goto overstep;
 				sram_offset += 4;
 
 				loop_start = false;
@@ -317,7 +343,10 @@
 				 * processing the list
 				 */
 				link |= ((0x1 << 8) & BM(8, 14));
-				dcc_sram_writel(drvdata, link, sram_offset);
+				ret = dcc_sram_writel(drvdata,
+						link, sram_offset);
+				if (ret)
+					goto overstep;
 				sram_offset += 4;
 				/* Reset link and prev_off */
 				addr = 0x00;
@@ -340,13 +369,20 @@
 				addr |= DCC_ADDR_DESCRIPTOR | DCC_WRITE_IND
 					| DCC_AHB_IND;
 
-			dcc_sram_writel(drvdata, addr, sram_offset);
+			ret = dcc_sram_writel(drvdata, addr, sram_offset);
+			if (ret)
+				goto overstep;
 				sram_offset += 4;
 
-			dcc_sram_writel(drvdata, link, sram_offset);
+			ret = dcc_sram_writel(drvdata, link, sram_offset);
+			if (ret)
+				goto overstep;
 				sram_offset += 4;
 
-			dcc_sram_writel(drvdata, entry->write_val, sram_offset);
+			ret = dcc_sram_writel(drvdata,
+				entry->write_val, sram_offset);
+			if (ret)
+				goto overstep;
 				sram_offset += 4;
 			addr = 0x00;
 			link = 0;
@@ -370,8 +406,10 @@
 			if (!prev_addr || prev_addr != addr || prev_off > off) {
 				/* Check if we need to write prev link entry */
 				if (link) {
-					dcc_sram_writel(drvdata,
+					ret = dcc_sram_writel(drvdata,
 							link, sram_offset);
+					if (ret)
+						goto overstep;
 					sram_offset += 4;
 				}
 				dev_dbg(drvdata->dev,
@@ -379,7 +417,10 @@
 					sram_offset);
 
 				/* Write address */
-				dcc_sram_writel(drvdata, addr, sram_offset);
+				ret = dcc_sram_writel(drvdata,
+						addr, sram_offset);
+				if (ret)
+					goto overstep;
 				sram_offset += 4;
 
 				/* Reset link and prev_off */
@@ -422,7 +463,10 @@
 			link |= DCC_LINK_DESCRIPTOR;
 
 			if (pos) {
-				dcc_sram_writel(drvdata, link, sram_offset);
+				ret = dcc_sram_writel(drvdata,
+						link, sram_offset);
+				if (ret)
+					goto overstep;
 				sram_offset += 4;
 				link = 0;
 			}
@@ -434,7 +478,9 @@
 	}
 
 	if (link) {
-		dcc_sram_writel(drvdata, link, sram_offset);
+		ret = dcc_sram_writel(drvdata, link, sram_offset);
+		if (ret)
+			goto overstep;
 		sram_offset += 4;
 	}
 
@@ -450,13 +496,17 @@
 		addr = (0xC105E) & BM(0, 27);
 		addr |= DCC_ADDR_DESCRIPTOR;
 
-		dcc_sram_writel(drvdata, addr, sram_offset);
+		ret = dcc_sram_writel(drvdata, addr, sram_offset);
+		if (ret)
+			goto overstep;
 		sram_offset += 4;
 	}
 
 	/* Setting zero to indicate end of the list */
 	link = DCC_LINK_DESCRIPTOR;
-	dcc_sram_writel(drvdata, link, sram_offset);
+	ret = dcc_sram_writel(drvdata, link, sram_offset);
+	if (ret)
+		goto overstep;
 	sram_offset += 4;
 
 	/* Update ram_cfg and check if the data will overstep */
diff --git a/drivers/soc/qcom/glink_bgcom_xprt.c b/drivers/soc/qcom/glink_bgcom_xprt.c
index 3c3923c..290d667 100644
--- a/drivers/soc/qcom/glink_bgcom_xprt.c
+++ b/drivers/soc/qcom/glink_bgcom_xprt.c
@@ -324,25 +324,22 @@
 				 uint32_t size)
 {
 	int ret;
-	DEFINE_WAIT(wait);
+	DEFINE_WAIT_FUNC(wait, woken_wake_function);
 
 	mutex_lock(&einfo->write_lock);
+	add_wait_queue(&einfo->tx_blocked_queue, &wait);
 	while (glink_bgcom_get_tx_avail(einfo) < (size/WORD_SIZE)) {
 		send_tx_blocked_signal(einfo);
-		prepare_to_wait(&einfo->tx_blocked_queue, &wait,
-				TASK_UNINTERRUPTIBLE);
-		if (glink_bgcom_get_tx_avail(einfo) < (size/WORD_SIZE)
-							&& !einfo->in_ssr) {
-			mutex_unlock(&einfo->write_lock);
-			schedule();
-			mutex_lock(&einfo->write_lock);
-		}
-		finish_wait(&einfo->tx_blocked_queue, &wait);
 		if (einfo->in_ssr) {
+			remove_wait_queue(&einfo->tx_blocked_queue, &wait);
 			mutex_unlock(&einfo->write_lock);
 			return -EFAULT;
 		}
+		mutex_unlock(&einfo->write_lock);
+		wait_woken(&wait, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
+		mutex_lock(&einfo->write_lock);
 	}
+	remove_wait_queue(&einfo->tx_blocked_queue, &wait);
 	ret = glink_bgcom_xprt_tx_cmd_safe(einfo, src, size);
 	mutex_unlock(&einfo->write_lock);
 	return ret;
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index b9572bd..7286f08 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -2211,6 +2211,7 @@
 
 err_setup_msa:
 	icnss_assign_msa_perm_all(penv, ICNSS_MSA_PERM_HLOS_ALL);
+	clear_bit(ICNSS_MSA0_ASSIGNED, &penv->state);
 err_power_on:
 	icnss_hw_power_off(penv);
 fail:
@@ -3529,7 +3530,6 @@
 		goto out;
 	}
 
-	WARN_ON(1);
 	icnss_pr_warn("Initiate PD restart at WLAN FW, state: 0x%lx\n",
 		      priv->state);
 
diff --git a/drivers/soc/qcom/rpm-smd.c b/drivers/soc/qcom/rpm-smd.c
index 7a4ab97..aff0389 100644
--- a/drivers/soc/qcom/rpm-smd.c
+++ b/drivers/soc/qcom/rpm-smd.c
@@ -747,6 +747,7 @@
 {
 	int ret;
 	char buf[MAX_ERR_BUFFER_SIZE] = {0};
+	uint32_t msg_id;
 
 	if (glink_enabled)
 		ret = msm_rpm_glink_rx_poll(glink_data->glink_handle);
@@ -773,24 +774,42 @@
 		 * spinlock from being locked out.
 		 */
 
-		if (!timeout) {
-			pr_err("Timed out waiting for RPM ACK\n");
+		if (!timeout)
 			return -EAGAIN;
-		}
 
 		ret = msm_rpm_read_smd_data(buf);
-		if (!ret)
+		if (!ret) {
+			/* Mimic Glink behavior to ensure that the
+			 * data is read and the msg is removed from
+			 * the wait list. We should have gotten here
+			 * only when there are no drivers waiting on
+			 * ACKs. msm_rpm_get_entry_from_msg_id()
+			 * return non-NULL only then.
+			 */
+			msg_id = msm_rpm_get_msg_id_from_ack(buf);
+			msm_rpm_process_ack(msg_id, 0);
 			ret = smd_is_pkt_avail(msm_rpm_data.ch_info);
+		}
 	}
 	return ret;
 }
 
+static void msm_rpm_flush_noack_messages(void)
+{
+	while (!list_empty(&msm_rpm_wait_list)) {
+		if (!msm_rpm_read_sleep_ack())
+			break;
+	}
+}
+
 static int msm_rpm_flush_requests(bool print)
 {
 	struct rb_node *t;
 	int ret;
 	int count = 0;
 
+	msm_rpm_flush_noack_messages();
+
 	for (t = rb_first(&tr_root); t; t = rb_next(t)) {
 
 		struct slp_buf *s = rb_entry(t, struct slp_buf, node);
@@ -827,8 +846,10 @@
 
 			if (ret >= 0)
 				count--;
-			else
+			else {
+				pr_err("Timed out waiting for RPM ACK\n");
 				return ret;
+			}
 		}
 	}
 	return 0;
@@ -1057,14 +1078,18 @@
 
 bool msm_rpm_waiting_for_ack(void)
 {
-	bool ret;
+	bool ret = false;
 	unsigned long flags;
+	struct msm_rpm_wait_data *elem = NULL;
 
 	spin_lock_irqsave(&msm_rpm_list_lock, flags);
-	ret = list_empty(&msm_rpm_wait_list);
+	elem = list_first_entry_or_null(&msm_rpm_wait_list,
+				struct msm_rpm_wait_data, list);
+	if (elem)
+		ret = !elem->delete_on_ack;
 	spin_unlock_irqrestore(&msm_rpm_list_lock, flags);
 
-	return !ret;
+	return ret;
 }
 
 static struct msm_rpm_wait_data *msm_rpm_get_entry_from_msg_id(uint32_t msg_id)
diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c
index 110cdf7..f20eda2 100644
--- a/drivers/soc/qcom/subsystem_restart.c
+++ b/drivers/soc/qcom/subsystem_restart.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
@@ -38,6 +38,7 @@
 #include <trace/events/trace_msm_pil_event.h>
 
 #include <asm/current.h>
+#include <linux/timer.h>
 
 #include "peripheral-loader.h"
 
@@ -53,6 +54,35 @@
 #define SHUTDOWN_ACK_MAX_LOOPS	100
 #define SHUTDOWN_ACK_DELAY_MS	100
 
+#ifdef CONFIG_SETUP_SSR_NOTIF_TIMEOUTS
+/* Timeout used for detection of notification hangs. In seconds.*/
+#define SYSMON_COMM_TIMEOUT	CONFIG_SSR_SYSMON_NOTIF_TIMEOUT
+#define SUBSYS_NOTIF_TIMEOUT	CONFIG_SSR_SUBSYS_NOTIF_TIMEOUT
+
+#define setup_timeout(dest_ss, source_ss, comm_type) \
+	_setup_timeout(dest_ss, source_ss, comm_type)
+#define cancel_timeout(subsys) del_timer(&subsys->timeout_data.timer)
+#define init_subsys_timer(subsys) _init_subsys_timer(subsys)
+
+/* Timeout values */
+static unsigned long timeout_vals[NUM_SSR_COMMS] = {
+	[SUBSYS_TO_SUBSYS_SYSMON] = SYSMON_COMM_TIMEOUT,
+	[SUBSYS_TO_HLOS] = SUBSYS_NOTIF_TIMEOUT,
+	[HLOS_TO_SUBSYS_SYSMON_SHUTDOWN] = SYSMON_COMM_TIMEOUT,
+};
+
+#ifdef CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT
+#define SSR_NOTIF_TIMEOUT_WARN(fmt...) panic(fmt)
+#else /* CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT */
+#define SSR_NOTIF_TIMEOUT_WARN(fmt...) WARN(1, fmt)
+#endif /* CONFIG_PANIC_ON_SSR_NOTIF_TIMEOUT */
+
+#else /* CONFIG_SETUP_SSR_NOTIF_TIMEOUTS */
+#define setup_timeout(dest_ss, source_ss, sysmon_comm)
+#define cancel_timeout(subsys)
+#define init_subsys_timer(subsys)
+#endif /* CONFIG_SETUP_SSR_NOTIF_TIMEOUTS */
+
 /**
  * enum p_subsys_state - state of a subsystem (private)
  * @SUBSYS_NORMAL: subsystem is operating normally
@@ -470,15 +500,89 @@
 	return enable_ramdumps;
 }
 
+#ifdef CONFIG_SETUP_SSR_NOTIF_TIMEOUTS
+static void notif_timeout_handler(unsigned long data)
+{
+	char *sysmon_msg = "Sysmon communication from %s to %s taking too long";
+	char *subsys_notif_msg = "Subsys notifier chain for %s taking too long";
+	char *sysmon_shutdwn_msg = "sysmon_send_shutdown to %s taking too long";
+	char *unknown_err_msg = "Unknown communication occurred";
+	struct subsys_notif_timeout *timeout_data =
+		(struct subsys_notif_timeout *) data;
+	enum ssr_comm comm_type = timeout_data->comm_type;
+
+	switch (comm_type) {
+	case SUBSYS_TO_SUBSYS_SYSMON:
+		SSR_NOTIF_TIMEOUT_WARN(sysmon_msg, timeout_data->source_name,
+				       timeout_data->dest_name);
+		break;
+	case SUBSYS_TO_HLOS:
+		SSR_NOTIF_TIMEOUT_WARN(subsys_notif_msg,
+				       timeout_data->source_name);
+		break;
+	case HLOS_TO_SUBSYS_SYSMON_SHUTDOWN:
+		SSR_NOTIF_TIMEOUT_WARN(sysmon_shutdwn_msg,
+				       timeout_data->dest_name);
+		break;
+	default:
+		SSR_NOTIF_TIMEOUT_WARN(unknown_err_msg);
+	}
+
+}
+
+static void _setup_timeout(struct subsys_desc *source_ss,
+			   struct subsys_desc *dest_ss, enum ssr_comm comm_type)
+{
+	struct subsys_notif_timeout *timeout_data;
+	unsigned long timeout;
+
+	switch (comm_type) {
+	case SUBSYS_TO_SUBSYS_SYSMON:
+		timeout_data = &source_ss->timeout_data;
+		timeout_data->dest_name = dest_ss->name;
+		timeout_data->source_name = source_ss->name;
+		break;
+	case SUBSYS_TO_HLOS:
+		timeout_data = &source_ss->timeout_data;
+		timeout_data->dest_name = NULL;
+		timeout_data->source_name = source_ss->name;
+		break;
+	case HLOS_TO_SUBSYS_SYSMON_SHUTDOWN:
+		timeout_data = &dest_ss->timeout_data;
+		timeout_data->dest_name = dest_ss->name;
+		timeout_data->source_name = NULL;
+		break;
+	default:
+		return;
+	}
+
+	timeout_data->timer.data = (unsigned long) timeout_data;
+	timeout_data->comm_type = comm_type;
+	timeout = jiffies + msecs_to_jiffies(timeout_vals[comm_type]);
+	mod_timer(&timeout_data->timer, timeout);
+}
+
+static void _init_subsys_timer(struct subsys_desc *subsys)
+{
+	init_timer(&subsys->timeout_data.timer);
+	subsys->timeout_data.timer.function = notif_timeout_handler;
+}
+
+#endif /* CONFIG_SETUP_SSR_NOTIF_TIMEOUTS */
+
 static void send_sysmon_notif(struct subsys_device *dev)
 {
 	struct subsys_device *subsys;
 
 	mutex_lock(&subsys_list_lock);
 	list_for_each_entry(subsys, &subsys_list, list)
-		if ((subsys->notif_state > 0) && (subsys != dev))
+		if ((subsys->notif_state > 0) && (subsys != dev)) {
+			setup_timeout(subsys->desc, dev->desc,
+				      SUBSYS_TO_SUBSYS_SYSMON);
 			sysmon_send_event(dev->desc, subsys->desc,
 						subsys->notif_state);
+			cancel_timeout(subsys->desc);
+		}
 	mutex_unlock(&subsys_list_lock);
 }
 
@@ -520,9 +624,13 @@
 		mutex_lock(&subsys_list_lock);
 		list_for_each_entry(subsys, &subsys_list, list)
 			if (dev != subsys &&
-				subsys->track.state == SUBSYS_ONLINE)
+				subsys->track.state == SUBSYS_ONLINE) {
+				setup_timeout(dev->desc, subsys->desc,
+					      SUBSYS_TO_SUBSYS_SYSMON);
 				sysmon_send_event(subsys->desc, dev->desc,
-								notif);
+						  notif);
+				cancel_timeout(dev->desc);
+			}
 		mutex_unlock(&subsys_list_lock);
 
 		if (notif == SUBSYS_AFTER_POWERUP &&
@@ -536,8 +644,10 @@
 		notif_data.pdev = pdev;
 
 		trace_pil_notif("before_send_notif", notif, dev->desc->fw_name);
+		setup_timeout(dev->desc, NULL, SUBSYS_TO_HLOS);
 		subsys_notif_queue_notification(dev->notify, notif,
 								&notif_data);
+		cancel_timeout(dev->desc);
 		trace_pil_notif("after_send_notif", notif, dev->desc->fw_name);
 	}
 }
@@ -750,8 +860,11 @@
 	if (!of_property_read_bool(subsys->desc->dev->of_node,
 					"qcom,pil-force-shutdown")) {
 		subsys_set_state(subsys, SUBSYS_OFFLINING);
+		setup_timeout(NULL, subsys->desc,
+			      HLOS_TO_SUBSYS_SYSMON_SHUTDOWN);
 		subsys->desc->sysmon_shutdown_ret =
 				sysmon_send_shutdown(subsys->desc);
+		cancel_timeout(subsys->desc);
 		if (subsys->desc->sysmon_shutdown_ret)
 			pr_debug("Graceful shutdown failed for %s\n", name);
 	}
@@ -1639,6 +1752,7 @@
 	INIT_WORK(&subsys->work, subsystem_restart_wq_func);
 	INIT_WORK(&subsys->device_restart_work, device_restart_work_hdlr);
 	spin_lock_init(&subsys->track.s_lock);
+	init_subsys_timer(desc);
 
 	subsys->id = ida_simple_get(&subsys_ida, 0, 0, GFP_KERNEL);
 	if (subsys->id < 0) {
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 32729c6..b5d9131 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -541,8 +541,14 @@
 		} else if (ret < 0 && ret != -ENOTSUPP) {
 			pr_err("Failed to wake function %s from suspend state. ret=%d.\n",
 				func->name ? func->name : "", ret);
+		} else {
+			/*
+			 * Return -EAGAIN to queue the request from
+			 * function driver wakeup function.
+			 */
+			ret = -EAGAIN;
+			goto done;
 		}
-		goto done;
 	}
 
 	if (!func->func_is_suspended)
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 0c4baf2..5222f79 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -96,6 +96,21 @@
 	return remote_wakeup_allowed;
 }
 
+static void usb_gsi_check_pending_wakeup(struct usb_function *f)
+{
+	struct f_gsi *gsi = func_to_gsi(f);
+
+	/*
+	 * If host suspended bus without receiving notification request then
+	 * initiate remote-wakeup. As driver won't be able to do it later since
+	 * notification request is already queued.
+	 */
+	if (gsi->c_port.notify_req_queued && usb_gsi_remote_wakeup_allowed(f)) {
+		mod_timer(&gsi->gsi_rw_timer, jiffies + msecs_to_jiffies(2000));
+		log_event_dbg("%s: pending response, arm rw_timer\n", __func__);
+	}
+}
+
 static void post_event(struct gsi_data_port *port, u8 event)
 {
 	unsigned long flags;
@@ -1834,6 +1849,9 @@
 	gsi->c_port.notify_req_queued = false;
 	spin_unlock_irqrestore(&gsi->c_port.lock, flags);
 
+	log_event_dbg("%s: status:%d req_queued:%d",
+		__func__, status, gsi->c_port.notify_req_queued);
+
 	switch (status) {
 	case -ECONNRESET:
 	case -ESHUTDOWN:
@@ -2494,6 +2512,7 @@
 	 */
 	if (gsi->prot_id == USB_PROT_GPS_CTRL) {
 		log_event_dbg("%s: suspend done\n", __func__);
+		usb_gsi_check_pending_wakeup(f);
 		return;
 	}
 
@@ -2503,16 +2522,7 @@
 	post_event(&gsi->d_port, EVT_SUSPEND);
 	queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w);
 	log_event_dbg("gsi suspended");
-
-	/*
-	 * If host suspended bus without receiving notification request then
-	 * initiate remote-wakeup. As driver won't be able to do it later since
-	 * notification request is already queued.
-	 */
-	if (gsi->c_port.notify_req_queued && usb_gsi_remote_wakeup_allowed(f)) {
-		mod_timer(&gsi->gsi_rw_timer, jiffies + msecs_to_jiffies(2000));
-		log_event_dbg("%s: pending response, arm rw_timer\n", __func__);
-	}
+	usb_gsi_check_pending_wakeup(f);
 }
 
 static void gsi_resume(struct usb_function *f)
diff --git a/drivers/video/fbdev/msm/mdss_dba_utils.c b/drivers/video/fbdev/msm/mdss_dba_utils.c
index 2758a5a..f904ace 100644
--- a/drivers/video/fbdev/msm/mdss_dba_utils.c
+++ b/drivers/video/fbdev/msm/mdss_dba_utils.c
@@ -734,7 +734,6 @@
 	struct mdss_dba_utils_data *udata = NULL;
 	struct msm_dba_reg_info info;
 	struct cec_abstract_init_data cec_abst_init_data;
-	void *cec_abst_data;
 	int ret = 0;
 
 	if (!uid) {
@@ -823,7 +822,7 @@
 	udata->cec_abst_data = cec_abstract_init(&cec_abst_init_data);
 	if (IS_ERR_OR_NULL(udata->cec_abst_data)) {
 		pr_err("error initializing cec abstract module\n");
-		ret = PTR_ERR(cec_abst_data);
+		ret = PTR_ERR(udata->cec_abst_data);
 		goto error;
 	}
 
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index a470656..25a2600 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -1462,6 +1462,11 @@
 					(mipi->vc << 8) | DTYPE_DCS_LWRITE;
 			stream_total = pinfo->roi.h << 16 | pinfo->roi.w;
 		} else {
+			width = width + pdata->panel_info.lcdc.border_left +
+				pdata->panel_info.lcdc.border_right;
+			height = height +  pdata->panel_info.lcdc.border_top +
+				pdata->panel_info.lcdc.border_bottom;
+			ystride = width * bpp + 1;
 			stream_ctrl = (ystride << 16) | (mipi->vc << 8) |
 					DTYPE_DCS_LWRITE;
 			stream_total = height << 16 | width;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 4683c71..bbffc06 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -960,7 +960,7 @@
 {
 	u32 prefill_us = 0;
 	u32 prefill_amortized = 0;
-	struct mdss_data_type *mdata;
+	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
 	struct mdss_mdp_mixer *mixer;
 	struct mdss_panel_info *pinfo;
 	u32 fps, v_total;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 3de3906..7c8a273 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -1754,7 +1754,7 @@
 
 int mdss_mode_switch(struct msm_fb_data_type *mfd, u32 mode)
 {
-	struct mdss_rect l_roi, r_roi;
+	struct mdss_rect l_roi = {0}, r_roi = {0};
 	struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
 	struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
 	struct mdss_mdp_ctl *sctl;
diff --git a/fs/crypto/fscrypt_ice.h b/fs/crypto/fscrypt_ice.h
index c540506..d448eae 100644
--- a/fs/crypto/fscrypt_ice.h
+++ b/fs/crypto/fscrypt_ice.h
@@ -21,7 +21,7 @@
 {
 	if (!inode->i_sb->s_cop)
 		return 0;
-	if (!inode->i_sb->s_cop->is_encrypted((struct inode *)inode))
+	if (!IS_ENCRYPTED((struct inode *)inode))
 	return 0;
 
 	return fscrypt_using_hardware_encryption(inode);
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 03ff3aa..6563f88 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -105,7 +105,8 @@
 	    filenames_mode == FS_ENCRYPTION_MODE_SPECK128_256_CTS)
 		return true;
 
-	if (contents_mode == FS_ENCRYPTION_MODE_PRIVATE)
+	if (contents_mode == FS_ENCRYPTION_MODE_PRIVATE &&
+	    filenames_mode == FS_ENCRYPTION_MODE_AES_256_CTS)
 		return true;
 
 	return false;
diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c
index 737b6fc..1866733 100644
--- a/fs/crypto/keyinfo.c
+++ b/fs/crypto/keyinfo.c
@@ -267,7 +267,7 @@
 
 static int fscrypt_data_encryption_mode(struct inode *inode)
 {
-	return fscrypt_should_be_processed_by_ice(inode) ?
+	return fscrypt_is_ice_capable(inode->i_sb) ?
 	FS_ENCRYPTION_MODE_PRIVATE : FS_ENCRYPTION_MODE_AES_256_XTS;
 }
 
diff --git a/fs/direct-io.c b/fs/direct-io.c
index bf03a92..081e539 100644
--- a/fs/direct-io.c
+++ b/fs/direct-io.c
@@ -37,6 +37,8 @@
 #include <linux/uio.h>
 #include <linux/atomic.h>
 #include <linux/prefetch.h>
+#define __FS_HAS_ENCRYPTION IS_ENABLED(CONFIG_F2FS_FS_ENCRYPTION)
+#include <linux/fscrypt.h>
 
 /*
  * How many user pages to map in one call to get_user_pages().  This determines
@@ -390,6 +392,21 @@
 	sdio->logical_offset_in_bio = sdio->cur_page_fs_offset;
 }
 
+static bool is_inode_filesystem_type(const struct inode *inode,
+					const char *fs_type)
+{
+	if (!inode || !fs_type)
+		return false;
+
+	if (!inode->i_sb)
+		return false;
+
+	if (!inode->i_sb->s_type)
+		return false;
+
+	return (strcmp(inode->i_sb->s_type->name, fs_type) == 0);
+}
+
 /*
  * In the AIO read case we speculatively dirty the pages before starting IO.
  * During IO completion, any of these pages which happen to have been written
@@ -412,6 +429,14 @@
 		bio_set_pages_dirty(bio);
 
 	bio->bi_dio_inode = dio->inode;
+
+/* iv sector for security/pfe/pfk_fscrypt.c and f2fs in fs/f2fs/f2fs.h.*/
+#define PG_DUN_NEW(i,p)                                            \
+	(((((u64)(i)->i_ino) & 0xffffffff) << 32) | ((p) & 0xffffffff))
+
+	if (is_inode_filesystem_type(dio->inode, "f2fs"))
+		fscrypt_set_ice_dun(dio->inode, bio, PG_DUN_NEW(dio->inode,
+			(sdio->logical_offset_in_bio >> PAGE_SHIFT)));
 	dio->bio_bdev = bio->bi_bdev;
 
 	if (sdio->submit_io) {
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index fec1eaa..6941365 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -1317,7 +1317,10 @@
 			    ext4_itable_unused_count(sb, gdp)),
 			    sbi->s_inodes_per_block);
 
-	if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group)) {
+	if ((used_blks < 0) || (used_blks > sbi->s_itb_per_group) ||
+	    ((group == 0) && ((EXT4_INODES_PER_GROUP(sb) -
+			       ext4_itable_unused_count(sb, gdp)) <
+			      EXT4_FIRST_INO(sb)))) {
 		ext4_error(sb, "Something is wrong with group %u: "
 			   "used itable blocks: %d; "
 			   "itable unused count: %u",
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2436c76..ab72207 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1180,11 +1180,6 @@
 		EXT4_NAME_LEN;
 }
 
-static inline bool ext4_is_encrypted(struct inode *inode)
-{
-	return ext4_encrypted_inode(inode);
-}
-
 static const struct fscrypt_operations ext4_cryptops = {
 	.key_prefix		= "ext4:",
 	.get_context		= ext4_get_context,
@@ -1192,7 +1187,6 @@
 	.dummy_context		= ext4_dummy_context,
 	.empty_dir		= ext4_empty_dir,
 	.max_namelen		= ext4_max_namelen,
-	.is_encrypted       = ext4_is_encrypted,
 };
 #endif
 
@@ -3047,14 +3041,8 @@
 		if (!gdp)
 			continue;
 
-		if (gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED))
-			continue;
-		if (group != 0)
+		if (!(gdp->bg_flags & cpu_to_le16(EXT4_BG_INODE_ZEROED)))
 			break;
-		ext4_error(sb, "Inode table for bg 0 marked as "
-			   "needing zeroing");
-		if (sb->s_flags & MS_RDONLY)
-			return ngroups;
 	}
 
 	return group;
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 9efe77e..25256ae 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -565,7 +565,8 @@
 	bio->bi_end_io = f2fs_read_end_io;
 	bio_set_op_attrs(bio, REQ_OP_READ, 0);
 
-	if (f2fs_encrypted_file(inode))
+        if (f2fs_encrypted_file(inode) &&
+            !fscrypt_using_hardware_encryption(inode))
 		post_read_steps |= 1 << STEP_DECRYPT;
 	if (post_read_steps) {
 		ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS);
@@ -1548,9 +1549,9 @@
 				bio = NULL;
 				goto set_error_page;
 			}
+			if (bio_encrypted)
+				fscrypt_set_ice_dun(inode, bio, dun);
 		}
-		if (bio_encrypted)
-			fscrypt_set_ice_dun(inode, bio, dun);
 		if (bio_add_page(bio, page, blocksize, 0) < blocksize)
 			goto submit_and_realloc;
 
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index a7711d7..c850618 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1344,6 +1344,8 @@
 		seq_printf(seq, ",fsync_mode=%s", "posix");
 	else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_STRICT)
 		seq_printf(seq, ",fsync_mode=%s", "strict");
+	else if (F2FS_OPTION(sbi).fsync_mode == FSYNC_MODE_NOBARRIER)
+		seq_printf(seq, ",fsync_mode=%s", "nobarrier");
 	return 0;
 }
 
@@ -1940,11 +1942,6 @@
 			inode->i_sb->s_blocksize : F2FS_NAME_LEN;
 }
 
-static inline bool f2fs_is_encrypted(struct inode *inode)
-{
-	return f2fs_encrypted_file(inode);
-}
-
 static const struct fscrypt_operations f2fs_cryptops = {
 	.key_prefix	= "f2fs:",
 	.get_context	= f2fs_get_context,
@@ -1952,7 +1949,6 @@
 	.dummy_context	= f2fs_dummy_context,
 	.empty_dir	= f2fs_empty_dir,
 	.max_namelen	= f2fs_max_namelen,
-	.is_encrypted = f2fs_is_encrypted,
 };
 #endif
 
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 211e80b..9f91d48 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -103,6 +103,7 @@
 	/* the following two fields are internal, NEVER access directly */
 	unsigned int __data_len;	/* total data len */
 	sector_t __sector;		/* sector cursor */
+	u64 __dun;			/* dun for UFS */
 
 	struct bio *bio;
 	struct bio *biotail;
@@ -866,6 +867,11 @@
 	return rq->__sector;
 }
 
+static inline sector_t blk_rq_dun(const struct request *rq)
+{
+	return rq->__dun;
+}
+
 static inline unsigned int blk_rq_bytes(const struct request *rq)
 {
 	return rq->__data_len;
diff --git a/include/linux/fscrypt.h b/include/linux/fscrypt.h
index 8f4e90c..7a7fce9 100644
--- a/include/linux/fscrypt.h
+++ b/include/linux/fscrypt.h
@@ -19,12 +19,9 @@
 
 struct fscrypt_ctx;
 
-/* iv sector for security/pfe/pfk_fscrypt.c and f2fs. sizeof is required
- * to accommodate 32 bit targets.
- */
+/* iv sector for security/pfe/pfk_fscrypt.c and f2fs */
 #define PG_DUN(i, p)                                            \
-	((((i)->i_ino & 0xffffffff) << (sizeof((i)->i_ino)/2)) | \
-				((p)->index & 0xffffffff))
+	(((((u64)(i)->i_ino) & 0xffffffff) << 32) | ((p)->index & 0xffffffff))
 
 struct fscrypt_info;
 
diff --git a/include/linux/fscrypt_supp.h b/include/linux/fscrypt_supp.h
index 32e2b6c..2f62d5b 100644
--- a/include/linux/fscrypt_supp.h
+++ b/include/linux/fscrypt_supp.h
@@ -29,7 +29,6 @@
 	bool (*dummy_context)(struct inode *);
 	bool (*empty_dir)(struct inode *);
 	unsigned (*max_namelen)(struct inode *);
-	bool (*is_encrypted)(struct inode *);
 };
 
 struct fscrypt_ctx {
diff --git a/include/linux/irq_sim.h b/include/linux/irq_sim.h
new file mode 100644
index 0000000..0380d89
--- /dev/null
+++ b/include/linux/irq_sim.h
@@ -0,0 +1,44 @@
+#ifndef _LINUX_IRQ_SIM_H
+#define _LINUX_IRQ_SIM_H
+/*
+ * Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/irq_work.h>
+#include <linux/device.h>
+
+/*
+ * Provides a framework for allocating simulated interrupts which can be
+ * requested like normal irqs and enqueued from process context.
+ */
+
+struct irq_sim_work_ctx {
+	struct irq_work		work;
+	int			irq;
+};
+
+struct irq_sim_irq_ctx {
+	int			irqnum;
+	bool			enabled;
+};
+
+struct irq_sim {
+	struct irq_sim_work_ctx	work_ctx;
+	int			irq_base;
+	unsigned int		irq_count;
+	struct irq_sim_irq_ctx	*irqs;
+};
+
+int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs);
+int devm_irq_sim_init(struct device *dev, struct irq_sim *sim,
+		      unsigned int num_irqs);
+void irq_sim_fini(struct irq_sim *sim);
+void irq_sim_fire(struct irq_sim *sim, unsigned int offset);
+int irq_sim_irqnum(struct irq_sim *sim, unsigned int offset);
+
+#endif /* _LINUX_IRQ_SIM_H */
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 149b718..4cbe862 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -350,9 +350,9 @@
  * @upthreshold: up-threshold supplied to ondemand governor
  * @downthreshold: down-threshold supplied to ondemand governor
  * @need_freq_change: flag indicating if a frequency change is required
- * @clk_scaling_in_progress: flag indicating if there's ongoing frequency change
  * @is_busy_started: flag indicating if a request is handled by the HW
  * @enable: flag indicating if the clock scaling logic is enabled for this host
+ * @is_suspended: to make devfreq request queued when mmc is suspened
  */
 struct mmc_devfeq_clk_scaling {
 	spinlock_t	lock;
@@ -377,9 +377,9 @@
 	unsigned int	lower_bus_speed_mode;
 #define MMC_SCALING_LOWER_DDR52_MODE	1
 	bool		need_freq_change;
-	bool		clk_scaling_in_progress;
 	bool		is_busy_started;
 	bool		enable;
+	bool		is_suspended;
 };
 
 struct mmc_host {
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 3fbfe96..6b20f91 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2986,6 +2986,8 @@
 	return __skb_grow(skb, len);
 }
 
+#define rb_to_skb(rb) rb_entry_safe(rb, struct sk_buff, rbnode)
+
 #define skb_queue_walk(queue, skb) \
 		for (skb = (queue)->next;					\
 		     skb != (struct sk_buff *)(queue);				\
diff --git a/include/soc/qcom/subsystem_restart.h b/include/soc/qcom/subsystem_restart.h
index 9a0a53e..c1c1386 100644
--- a/include/soc/qcom/subsystem_restart.h
+++ b/include/soc/qcom/subsystem_restart.h
@@ -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
@@ -35,6 +35,30 @@
 struct device;
 struct module;
 
+enum ssr_comm {
+	SUBSYS_TO_SUBSYS_SYSMON,
+	SUBSYS_TO_HLOS,
+	HLOS_TO_SUBSYS_SYSMON_SHUTDOWN,
+	NUM_SSR_COMMS,
+};
+
+/**
+ * struct subsys_notif_timeout - timeout data used by notification timeout hdlr
+ * @comm_type: Specifies if the type of communication being tracked is
+ * through sysmon between two subsystems, subsystem notifier call chain, or
+ * sysmon shutdown.
+ * @dest_name: subsystem to which sysmon notification is being sent to
+ * @source_name: subsystem which generated event that notification is being sent
+ * for
+ * @timer: timer for scheduling timeout
+ */
+struct subsys_notif_timeout {
+	enum ssr_comm comm_type;
+	const char *dest_name;
+	const char *source_name;
+	struct timer_list timer;
+};
+
 /**
  * struct subsys_desc - subsystem descriptor
  * @name: name of subsystem
@@ -95,6 +119,9 @@
 	bool system_debug;
 	bool ignore_ssr_failure;
 	const char *edge;
+#ifdef CONFIG_SETUP_SSR_NOTIF_TIMEOUTS
+	struct subsys_notif_timeout timeout_data;
+#endif /* CONFIG_SETUP_SSR_NOTIF_TIMEOUTS */
 };
 
 /**
diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h
index 34ecd82..bd9836c 100644
--- a/include/uapi/linux/msm_ipa.h
+++ b/include/uapi/linux/msm_ipa.h
@@ -586,6 +586,9 @@
  * @IPA_HW_v3_5: IPA hardware version 3.5
  * @IPA_HW_v3_5_1: IPA hardware version 3.5.1
  * @IPA_HW_v4_0: IPA hardware version 4.0
+ * @IPA_HW_v4_1: IPA hardware version 4.1
+ * @IPA_HW_v4_2: IPA hardware version 4.2
+ * @IPA_HW_v4_5: IPA hardware version 4.5
  */
 enum ipa_hw_type {
 	IPA_HW_None = 0,
@@ -601,10 +604,16 @@
 	IPA_HW_v3_5 = 12,
 	IPA_HW_v3_5_1 = 13,
 	IPA_HW_v4_0 = 14,
+	IPA_HW_v4_1 = 15,
+	IPA_HW_v4_2 = 16,
+	IPA_HW_v4_5 = 17,
 };
-#define IPA_HW_MAX (IPA_HW_v4_0 + 1)
+#define IPA_HW_MAX (IPA_HW_v4_5 + 1)
 
 #define IPA_HW_v4_0 IPA_HW_v4_0
+#define IPA_HW_v4_1 IPA_HW_v4_1
+#define IPA_HW_v4_2 IPA_HW_v4_2
+#define IPA_HW_v4_5 IPA_HW_v4_5
 
 /**
  * struct ipa_rule_attrib - attributes of a routing/filtering
diff --git a/include/uapi/media/msmb_qca.h b/include/uapi/media/msmb_qca.h
index 02a6b1f..22b1006 100644
--- a/include/uapi/media/msmb_qca.h
+++ b/include/uapi/media/msmb_qca.h
@@ -1,16 +1,3 @@
-/* Copyright (c) 2018, The Linux Foundation.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
 #ifndef __UAPI_LINUX_MSMB_QCA402X_H
 #define __UAPI_LINUX_MSMB_QCA402X_H
 
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 3bbfd6a..9b2d34f 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -59,6 +59,11 @@
 config IRQ_DOMAIN
 	bool
 
+# Support for simulated interrupts
+config IRQ_SIM
+	bool
+	select IRQ_WORK
+
 # Support for hierarchical irq domains
 config IRQ_DOMAIN_HIERARCHY
 	bool
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 1d3ee31..2c0ba4e 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -3,6 +3,7 @@
 obj-$(CONFIG_GENERIC_IRQ_CHIP) += generic-chip.o
 obj-$(CONFIG_GENERIC_IRQ_PROBE) += autoprobe.o
 obj-$(CONFIG_IRQ_DOMAIN) += irqdomain.o
+obj-$(CONFIG_IRQ_SIM) += irq_sim.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_GENERIC_PENDING_IRQ) += migration.o
 obj-$(CONFIG_GENERIC_IRQ_MIGRATION) += cpuhotplug.o
diff --git a/kernel/irq/irq_sim.c b/kernel/irq/irq_sim.c
new file mode 100644
index 0000000..8569085
--- /dev/null
+++ b/kernel/irq/irq_sim.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2017 Bartosz Golaszewski <brgl@bgdev.pl>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/slab.h>
+#include <linux/irq_sim.h>
+#include <linux/irq.h>
+
+struct irq_sim_devres {
+	struct irq_sim		*sim;
+};
+
+static void irq_sim_irqmask(struct irq_data *data)
+{
+	struct irq_sim_irq_ctx *irq_ctx = irq_data_get_irq_chip_data(data);
+
+	irq_ctx->enabled = false;
+}
+
+static void irq_sim_irqunmask(struct irq_data *data)
+{
+	struct irq_sim_irq_ctx *irq_ctx = irq_data_get_irq_chip_data(data);
+
+	irq_ctx->enabled = true;
+}
+
+static struct irq_chip irq_sim_irqchip = {
+	.name		= "irq_sim",
+	.irq_mask	= irq_sim_irqmask,
+	.irq_unmask	= irq_sim_irqunmask,
+};
+
+static void irq_sim_handle_irq(struct irq_work *work)
+{
+	struct irq_sim_work_ctx *work_ctx;
+
+	work_ctx = container_of(work, struct irq_sim_work_ctx, work);
+	handle_simple_irq(irq_to_desc(work_ctx->irq));
+}
+
+/**
+ * irq_sim_init - Initialize the interrupt simulator: allocate a range of
+ *                dummy interrupts.
+ *
+ * @sim:        The interrupt simulator object to initialize.
+ * @num_irqs:   Number of interrupts to allocate
+ *
+ * On success: return the base of the allocated interrupt range.
+ * On failure: a negative errno.
+ */
+int irq_sim_init(struct irq_sim *sim, unsigned int num_irqs)
+{
+	int i;
+
+	sim->irqs = kmalloc_array(num_irqs, sizeof(*sim->irqs), GFP_KERNEL);
+	if (!sim->irqs)
+		return -ENOMEM;
+
+	sim->irq_base = irq_alloc_descs(-1, 0, num_irqs, 0);
+	if (sim->irq_base < 0) {
+		kfree(sim->irqs);
+		return sim->irq_base;
+	}
+
+	for (i = 0; i < num_irqs; i++) {
+		sim->irqs[i].irqnum = sim->irq_base + i;
+		sim->irqs[i].enabled = false;
+		irq_set_chip(sim->irq_base + i, &irq_sim_irqchip);
+		irq_set_chip_data(sim->irq_base + i, &sim->irqs[i]);
+		irq_set_handler(sim->irq_base + i, &handle_simple_irq);
+		irq_modify_status(sim->irq_base + i,
+				  IRQ_NOREQUEST | IRQ_NOAUTOEN, IRQ_NOPROBE);
+	}
+
+	init_irq_work(&sim->work_ctx.work, irq_sim_handle_irq);
+	sim->irq_count = num_irqs;
+
+	return sim->irq_base;
+}
+EXPORT_SYMBOL_GPL(irq_sim_init);
+
+/**
+ * irq_sim_fini - Deinitialize the interrupt simulator: free the interrupt
+ *                descriptors and allocated memory.
+ *
+ * @sim:        The interrupt simulator to tear down.
+ */
+void irq_sim_fini(struct irq_sim *sim)
+{
+	irq_work_sync(&sim->work_ctx.work);
+	irq_free_descs(sim->irq_base, sim->irq_count);
+	kfree(sim->irqs);
+}
+EXPORT_SYMBOL_GPL(irq_sim_fini);
+
+static void devm_irq_sim_release(struct device *dev, void *res)
+{
+	struct irq_sim_devres *this = res;
+
+	irq_sim_fini(this->sim);
+}
+
+/**
+ * irq_sim_init - Initialize the interrupt simulator for a managed device.
+ *
+ * @dev:        Device to initialize the simulator object for.
+ * @sim:        The interrupt simulator object to initialize.
+ * @num_irqs:   Number of interrupts to allocate
+ *
+ * On success: return the base of the allocated interrupt range.
+ * On failure: a negative errno.
+ */
+int devm_irq_sim_init(struct device *dev, struct irq_sim *sim,
+		      unsigned int num_irqs)
+{
+	struct irq_sim_devres *dr;
+	int rv;
+
+	dr = devres_alloc(devm_irq_sim_release, sizeof(*dr), GFP_KERNEL);
+	if (!dr)
+		return -ENOMEM;
+
+	rv = irq_sim_init(sim, num_irqs);
+	if (rv < 0) {
+		devres_free(dr);
+		return rv;
+	}
+
+	dr->sim = sim;
+	devres_add(dev, dr);
+
+	return rv;
+}
+EXPORT_SYMBOL_GPL(devm_irq_sim_init);
+
+/**
+ * irq_sim_fire - Enqueue an interrupt.
+ *
+ * @sim:        The interrupt simulator object.
+ * @offset:     Offset of the simulated interrupt which should be fired.
+ */
+void irq_sim_fire(struct irq_sim *sim, unsigned int offset)
+{
+	if (sim->irqs[offset].enabled) {
+		sim->work_ctx.irq = irq_sim_irqnum(sim, offset);
+		irq_work_queue(&sim->work_ctx.work);
+	}
+}
+EXPORT_SYMBOL_GPL(irq_sim_fire);
+
+/**
+ * irq_sim_irqnum - Get the allocated number of a dummy interrupt.
+ *
+ * @sim:        The interrupt simulator object.
+ * @offset:     Offset of the simulated interrupt for which to retrieve
+ *              the number.
+ */
+int irq_sim_irqnum(struct irq_sim *sim, unsigned int offset)
+{
+	return sim->irqs[offset].irqnum;
+}
+EXPORT_SYMBOL_GPL(irq_sim_irqnum);
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 91a909f..335b40e 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -10540,8 +10540,12 @@
 	rcu_read_lock();
 	sd = rcu_dereference_check_sched_domain(rq->sd);
 	if (sd) {
-		cpumask_and(&cpumask, nohz.idle_cpus_mask,
-			    sched_domain_span(sd));
+		if (energy_aware() && rq->misfit_task)
+			cpumask_andnot(&cpumask, nohz.idle_cpus_mask,
+				sched_domain_span(sd));
+		else
+			cpumask_and(&cpumask, nohz.idle_cpus_mask,
+				    sched_domain_span(sd));
 		cpumask_andnot(&cpumask, &cpumask,
 			    cpu_isolated_mask);
 		ilb = cpumask_first(&cpumask);
@@ -10552,7 +10556,7 @@
 		if (!energy_aware() ||
 		    (capacity_orig_of(cpu) ==
 		     cpu_rq(cpu)->rd->max_cpu_capacity.val ||
-		     cpu_overutilized(cpu))) {
+		     (cpu_overutilized(cpu) && rq->nr_running > 1))) {
 			cpumask_andnot(&cpumask, nohz.idle_cpus_mask,
 			    cpu_isolated_mask);
 			ilb = cpumask_first(&cpumask);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 59c1581..340a3db 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -889,12 +889,9 @@
 	now = jiffies;
 	next = now + HZ;
 
-	if (!(state & NUD_IN_TIMER)) {
-		if (neigh_probe_enable && (state & NUD_STALE))
-			neigh_dbg(2, "neigh %pK is still alive\n", neigh);
-		else
-			goto out;
-	}
+	if (!(state & NUD_IN_TIMER))
+		goto out;
+
 	if (state & NUD_REACHABLE) {
 		if (time_before_eq(now,
 				   neigh->confirmed + neigh->parms->reachable_time)) {
@@ -1185,10 +1182,7 @@
 		neigh_del_timer(neigh);
 		if (new & NUD_PROBE)
 			atomic_set(&neigh->probes, 0);
-		if (new & NUD_IN_TIMER || (
-			neigh_probe_enable &&
-			(neigh->tbl->family == AF_INET6) &&
-			(new & NUD_STALE)))
+		if (new & NUD_IN_TIMER)
 			neigh_add_timer(neigh, (jiffies +
 						((new & NUD_REACHABLE) ?
 						 neigh->parms->reachable_time :
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index f0fc835..c244b72 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -4909,6 +4909,7 @@
 static void tcp_collapse_ofo_queue(struct sock *sk)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
+	u32 range_truesize, sum_tiny = 0;
 	struct sk_buff *skb, *head;
 	struct rb_node *p;
 	u32 start, end;
@@ -4927,6 +4928,7 @@
 	}
 	start = TCP_SKB_CB(skb)->seq;
 	end = TCP_SKB_CB(skb)->end_seq;
+	range_truesize = skb->truesize;
 
 	for (head = skb;;) {
 		skb = tcp_skb_next(skb, NULL);
@@ -4937,11 +4939,20 @@
 		if (!skb ||
 		    after(TCP_SKB_CB(skb)->seq, end) ||
 		    before(TCP_SKB_CB(skb)->end_seq, start)) {
-			tcp_collapse(sk, NULL, &tp->out_of_order_queue,
-				     head, skb, start, end);
+			/* Do not attempt collapsing tiny skbs */
+			if (range_truesize != head->truesize ||
+			    end - start >= SKB_WITH_OVERHEAD(SK_MEM_QUANTUM)) {
+				tcp_collapse(sk, NULL, &tp->out_of_order_queue,
+					     head, skb, start, end);
+			} else {
+				sum_tiny += range_truesize;
+				if (sum_tiny > sk->sk_rcvbuf >> 3)
+					return;
+			}
 			goto new_range;
 		}
 
+		range_truesize += skb->truesize;
 		if (unlikely(before(TCP_SKB_CB(skb)->seq, start)))
 			start = TCP_SKB_CB(skb)->seq;
 		if (after(TCP_SKB_CB(skb)->end_seq, end))
@@ -4956,6 +4967,7 @@
  * 2) not add too big latencies if thousands of packets sit there.
  *    (But if application shrinks SO_RCVBUF, we could still end up
  *     freeing whole queue here)
+ * 3) Drop at least 12.5 % of sk_rcvbuf to avoid malicious attacks.
  *
  * Return true if queue has shrunk.
  */
@@ -4963,20 +4975,26 @@
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct rb_node *node, *prev;
+	int goal;
 
 	if (RB_EMPTY_ROOT(&tp->out_of_order_queue))
 		return false;
 
 	NET_INC_STATS(sock_net(sk), LINUX_MIB_OFOPRUNED);
+	goal = sk->sk_rcvbuf >> 3;
 	node = &tp->ooo_last_skb->rbnode;
 	do {
 		prev = rb_prev(node);
 		rb_erase(node, &tp->out_of_order_queue);
+		goal -= rb_to_skb(node)->truesize;
 		tcp_drop(sk, rb_entry(node, struct sk_buff, rbnode));
-		sk_mem_reclaim(sk);
-		if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
-		    !tcp_under_memory_pressure(sk))
-			break;
+		if (!prev || goal <= 0) {
+			sk_mem_reclaim(sk);
+			if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
+			    !tcp_under_memory_pressure(sk))
+				break;
+			goal = sk->sk_rcvbuf >> 3;
+		}
 		node = prev;
 	} while (node);
 	tp->ooo_last_skb = rb_entry(prev, struct sk_buff, rbnode);
@@ -5011,6 +5029,9 @@
 	else if (tcp_under_memory_pressure(sk))
 		tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss);
 
+	if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf)
+		return 0;
+
 	tcp_collapse_ofo_queue(sk);
 	if (!skb_queue_empty(&sk->sk_receive_queue))
 		tcp_collapse(sk, &sk->sk_receive_queue, NULL,
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 0fdd61a..38fbe09 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -1141,8 +1141,8 @@
 
 country TT: DFS-FCC
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (24)
-	(5250 - 5330 @ 80), (24), DFS
+	(5170 - 5250 @ 80), (24), AUTO-BW
+	(5250 - 5330 @ 80), (24), DFS, AUTO-BW
 	(5490 - 5730 @ 160), (24), DFS
 	(5735 - 5835 @ 80), (30)
 	# 60 gHz band channels 1-3, FCC
@@ -1216,7 +1216,7 @@
 	(5735 - 5875 @ 80), (14)
 
 country VE: DFS-FCC
-	(2402 - 2482 @ 40), (20)
+	(2402 - 2482 @ 40), (30)
 	(5170 - 5250 @ 80), (23), AUTO-BW
         (5250 - 5330 @ 80), (23), DFS, AUTO-BW
 	(5735 - 5835 @ 80), (30)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index f00e7d3..e086950 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -11438,6 +11438,7 @@
 		return -EOPNOTSUPP;
 
 	if (!info->attrs[NL80211_ATTR_MDID] ||
+	    !info->attrs[NL80211_ATTR_IE] ||
 	    !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
 		return -EINVAL;
 
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 9195f23..e4f9816 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1688,7 +1688,9 @@
 		 * as some drivers used this to restore its orig_* reg domain.
 		 */
 		if (initiator == NL80211_REGDOM_SET_BY_CORE &&
-		    wiphy->regulatory_flags & REGULATORY_CUSTOM_REG)
+		    wiphy->regulatory_flags & REGULATORY_CUSTOM_REG &&
+		    !(wiphy->regulatory_flags &
+		      REGULATORY_WIPHY_SELF_MANAGED))
 			reg_call_notifier(wiphy, lr);
 		return;
 	}
@@ -2157,26 +2159,6 @@
 	}
 }
 
-static bool reg_only_self_managed_wiphys(void)
-{
-	struct cfg80211_registered_device *rdev;
-	struct wiphy *wiphy;
-	bool self_managed_found = false;
-
-	ASSERT_RTNL();
-
-	list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
-		wiphy = &rdev->wiphy;
-		if (wiphy->regulatory_flags & REGULATORY_WIPHY_SELF_MANAGED)
-			self_managed_found = true;
-		else
-			return false;
-	}
-
-	/* make sure at least one self-managed wiphy exists */
-	return self_managed_found;
-}
-
 /*
  * Processes regulatory hints, this is all the NL80211_REGDOM_SET_BY_*
  * Regulatory hints come on a first come first serve basis and we
@@ -2209,10 +2191,6 @@
 	spin_unlock(&reg_requests_lock);
 
 	notify_self_managed_wiphys(reg_request);
-	if (reg_only_self_managed_wiphys()) {
-		reg_free_request(reg_request);
-		return;
-	}
 
 	reg_process_hint(reg_request);
 
diff --git a/security/pfe/pfk.c b/security/pfe/pfk.c
index 740da32..8ad25cc 100644
--- a/security/pfe/pfk.c
+++ b/security/pfe/pfk.c
@@ -220,11 +220,7 @@
 	if (!page_mapping(bio->bi_io_vec->bv_page))
 		return NULL;
 
-	if (!bio->bi_io_vec->bv_page->mapping->host)
-
-		return NULL;
-
-	return bio->bi_io_vec->bv_page->mapping->host;
+	return page_mapping(bio->bi_io_vec->bv_page)->host;
 }
 
 /**