Merge "Merge android-4.9.92 (9c3fb9c) into msm-4.9"
diff --git a/Documentation/devicetree/bindings/arm/msm/clock-controller.txt b/Documentation/devicetree/bindings/arm/msm/clock-controller.txt
index 37718e1..75f901b 100644
--- a/Documentation/devicetree/bindings/arm/msm/clock-controller.txt
+++ b/Documentation/devicetree/bindings/arm/msm/clock-controller.txt
@@ -25,6 +25,8 @@
 			"qcom,gcc-8992"
 			"qcom,gcc-8952"
 			"qcom,gcc-8937"
+			"qcom,gcc-sdm439"
+			"qcom,gcc-sdm429"
 			"qcom,gcc-8917"
 			"qcom,gcc-8940"
 			"qcom,gcc-8920"
@@ -45,6 +47,8 @@
 			"qcom,gcc-mdss-8917"
 			"qcom,gcc-mdss-8940"
 			"qcom,gcc-mdss-8920"
+			"qcom,gcc-mdss-sdm429"
+			"qcom,gcc-mdss-sdm439"
 			"qcom,gcc-gfx-8953"
 			"qcom,gcc-gfx-sdm450"
 			"qcom,gcc-mdm9607"
diff --git a/Documentation/devicetree/bindings/arm/msm/clock-cpu-8939.txt b/Documentation/devicetree/bindings/arm/msm/clock-cpu-8939.txt
index 5d570d0..e2190df 100644
--- a/Documentation/devicetree/bindings/arm/msm/clock-cpu-8939.txt
+++ b/Documentation/devicetree/bindings/arm/msm/clock-cpu-8939.txt
@@ -7,7 +7,8 @@
 
 Required properties:
 - compatible:		Must be one of "qcom,clock-cpu-8939" or
-			"qcom,cpu-clock-8952", "qcom,cpu-clock-8917".
+			"qcom,cpu-clock-8952", "qcom,cpu-clock-8917",
+			"qcom,cpu-clock-sdm439", "qcom,cpu-clock-sdm429".
 - reg:			Pairs of physical base addresses and region sizes of
 			memory mapped registers.
 - reg-names:		Names of the bases for the above registers. Expected
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
index 55d06b2..1a357b1 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
@@ -28,6 +28,14 @@
 	mask of the cluster mode in the composite state ID used to define
 	cluster low power modes in PSCI.
 
+Optional properties:
+	- qcom,disable-prediction: This property is used to indicate the LPM
+	governor will not use LPM prediction for this cluster.
+	- qcom,clstr-tmr-add: This property is used as correction timer for
+	wrong prediction by lpm prediction algorithm for cluster predictions.
+	This value should be between 100 to 1500. Higher values would mean
+	longer time staying in shallower state before waking up to select a
+	deeper state in case of wrong prediction.
 	qcom,pm-cluster contains qcom,pm-cluster-level nodes which identify
 	the various low power modes that the cluster can enter. The
 	qcom,pm-cluster node should also include another cluster node or a cpu
@@ -77,8 +85,22 @@
 	- qcom,pm-cpu-levels: The different low power modes that a CPU could
 	enter. The following section explains the required properties of this
 	node.
-	-qcom,use-prediction: This optional property is used to indicate the
-	the LPM governor is to apply sleep prediction to this cluster.
+
+Optional properties:
+	- qcom,disable-prediction: This property is used to indicate the
+	LPM governor is to disable sleep prediction to this cpu.
+	- qcom,ref-stddev: This property is used as reference standard deviation
+	in lpm prediction algorithm. This value should be between 100 to 1000.
+	Higher value would result in more predictions and thereby resulting in
+	shallower low power modes.
+	- qcom,tmr-add: This property is used as correction timer for wrong
+	prediction by lpm prediction algorithm. This value should be between
+	100 to 1500. Higher values would mean longer time staying in shallower
+	state before waking up to select a deeper state in case of wrong prediction.
+	- qcom,ref-premature-cnt: This property is used as reference premature
+	count to predict next sleep state by the prediction algorithm. This value
+	should be between 1 to 5. Higher value for this parameter would result in
+	less predictions to disallow deeper low power modes.
 
 [Node bindings for qcom,pm-cpu-levels]
  Required properties:
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index bacaeb6..9c2d647 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -110,6 +110,9 @@
 - SDM450
   compatible = "qcom,sdm450"
 
+- SDA450
+  compatible = "qcom,sda450"
+
 - SDM632
   compatible = "qcom,sdm632"
 
@@ -122,9 +125,15 @@
 - SDM439
   compatible = "qcom,sdm439"
 
+- SDA439
+  compatible = "qcom,sda439"
+
 - SDM429
   compatible = "qcom,sdm429"
 
+- SDA429
+  compatible = "qcom,sda429"
+
 - MDM9640
   compatible = "qcom,mdm9640"
 
@@ -334,9 +343,13 @@
 compatible = "qcom,sdm429-cdp"
 compatible = "qcom,sdm429-mtp"
 compatible = "qcom,sdm429-qrd"
+compatible = "qcom,sda429-cdp"
+compatible = "qcom,sda429-mtp"
 compatible = "qcom,sdm439-cdp"
 compatible = "qcom,sdm439-mtp"
 compatible = "qcom,sdm439-qrd"
+compatible = "qcom,sda439-cdp"
+compatible = "qcom,sda439-mtp"
 compatible = "qcom,msm8953-rumi"
 compatible = "qcom,msm8953-sim"
 compatible = "qcom,msm8953-cdp"
@@ -347,6 +360,8 @@
 compatible = "qcom,sdm450-mtp"
 compatible = "qcom,sdm450-cdp"
 compatible = "qcom,sdm450-qrd"
+compatible = "qcom,sda450-mtp"
+compatible = "qcom,sda450-cdp"
 compatible = "qcom,sdm632-rumi"
 compatible = "qcom,sdm632-cdp"
 compatible = "qcom,sdm632-mtp"
@@ -364,6 +379,7 @@
 compatible = "qcom,apq8009-cdp"
 compatible = "qcom,apq8009-mtp"
 compatible = "qcom,sdxpoorwills-rumi"
+compatible = "qcom,sdxpoorwills-atp"
 compatible = "qcom,sdxpoorwills-mtp"
 compatible = "qcom,sdxpoorwills-cdp"
 compatible = "qcom,mdm9607-ttp"
diff --git a/Documentation/devicetree/bindings/arm/msm/spm-v2.txt b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
index 194059c..d44ab56 100644
--- a/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
+++ b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
@@ -45,6 +45,8 @@
 	index to send the PMIC data to
 - qcom,vctl-port: The PVC (PMIC Virtual Channel) port used for changing
 	voltage
+- qcom,vctl-port-ub: The PVC (PMIC Virtual Channel) port used for changing
+	voltage
 - qcom,phase-port: The PVC port used for changing the number of phases
 - qcom,pfm-port: The PVC port used for enabling PWM/PFM modes
 - qcom,cpu-vctl-mask: Mask of cpus, whose voltage the spm device can control.
@@ -105,6 +107,8 @@
 	between AVS controller requests
 - qcom,vctl-port: The PVC (PMIC Virtual Channel) port used for changing
 	voltage
+- qcom,vctl-port-ub: The PVC (PMIC Virtual Channel) port used for changing
+	voltage
 - qcom,phase-port: The PVC port used for changing the number of phases
 - qcom,pfm-port: The PVC port used for enabling PWM/PFM modes
 - qcom,cpu-vctl-list: List of cpu node phandles, whose voltage the spm device
diff --git a/Documentation/devicetree/bindings/batterydata/batterydata.txt b/Documentation/devicetree/bindings/batterydata/batterydata.txt
index 884b19c..84c67da 100644
--- a/Documentation/devicetree/bindings/batterydata/batterydata.txt
+++ b/Documentation/devicetree/bindings/batterydata/batterydata.txt
@@ -101,6 +101,12 @@
 			     the low and high thresholds.
 			The threshold values in range should be in ascending
 			and shouldn't overlap. It support 8 ranges at max.
+- qcom,jeita-soft-thresholds: A tuple entry to specify ADC code for battery's soft JEITA
+				threshold.
+				<SOFT_COLD_ADC_CODE, SOFT_HOT_ADC_CODE>.
+- qcom,jeita-hard-thresholds: A tuple entry to specify ADC code for battery's hard JEITA
+				threshold.
+				<HARD_COLD_ADC_CODE, HARD_HOT_ADC_CODE>.
 
 Profile data node required subnodes:
 - qcom,fcc-temp-lut : An 1-dimensional lookup table node that encodes
@@ -165,6 +171,8 @@
 	qcom,v-cutoff-uv = <3400000>;
 	qcom,chg-term-ua = <100000>;
 	qcom,batt-id-kohm = <75>;
+	qcom,jeita-soft-thresholds = <0x3ecc 0x1bff>;
+	qcom,jeita-hard-thresholds = <0x4aff 0x15aa>;
 	qcom,step-chg-ranges = <3600000 4000000 3000000
 				4001000 4200000 2800000
 				4201000 4400000 2000000>;
diff --git a/Documentation/devicetree/bindings/crypto/msm/qcedev.txt b/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
index 6f1d8e3..addfd46 100644
--- a/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
+++ b/Documentation/devicetree/bindings/crypto/msm/qcedev.txt
@@ -1,5 +1,8 @@
 * QCEDEV (QTI Crypto Engine Device)
 
+[Root level node]
+Crypto Engine
+============
 Required properties:
   - compatible : should be "qcom,qcedev"
   - reg : should contain crypto, BAM register map.
@@ -23,6 +26,19 @@
   - qcom,smmu-s1-enable : Boolean flag to enable SMMU stage 1 translation.
   - iommus : A list of phandle and IOMMU specifier pairs that describe the IOMMU master interfaces of the device.
 
+
+[Second level nodes]
+Context banks
+=============
+Required properties:
+  - compatible : should be "qcom,qcedev,context-bank"
+  - iommus : A phandle parsed by smmu driver. Number of entries will vary across targets.
+
+Optional properties:
+  - label - string describing iommu domain usage.
+  - virtual-addr : start of virtual address pool.
+  - virtual-size : size of virtual address pool.
+
 Example:
 
 	qcom,qcedev@fd440000 {
@@ -42,4 +58,15 @@
 				<56 512 0 0>,
 				<56 512 3936000 393600>,
 		qcom,ce-opp-freq = <100000000>;
+
+		qcom_cedev_ns_cb {
+			compatible = "qcom,qcedev,context-bank";
+			label = "ns_context";
+			iommus = <&anoc2_smmu 0x1878>,
+				<&anoc2_smmu 0x1879>,
+				<&anoc2_smmu 0x187c>,
+				<&anoc2_smmu 0x187f>;
+			virtual-addr = <0x60000000>;
+			virtual-size = <0x00200000>;
+		};
 	};
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 7bcb2dc..b8cb903 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -40,6 +40,8 @@
 					timing settings for the panel.
 - qcom,mdss-dsi-panel-timings-phy-v2:	An array of length 40 char that specifies the PHY version 2
 					lane timing settings for the panel.
+- qcom,mdss-dsi-panel-timings-phy-12nm: An array of length 8 char that specifies the 12nm DSI PHY
+					lane timing settings for the panel.
 - qcom,mdss-dsi-on-command:		A byte stream formed by multiple dcs packets base on
 					qcom dsi controller protocol.
 					byte 0: dcs data type
@@ -631,6 +633,8 @@
                                 23 20 06 09 05 03 04 a0
                                 23 20 06 09 05 03 04 a0
                                 23 2e 06 08 05 03 04 a0];
+                qcom,mdss-dsi-panel-timings-phy-12nm =
+				[a9 4e 56 0b 8a 4d 0b d6];
 		qcom,mdss-dsi-on-command = [32 01 00 00 00 00 02 00 00
 					29 01 00 00 10 00 02 FF 99];
 		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
diff --git a/Documentation/devicetree/bindings/fb/mdss-pll.txt b/Documentation/devicetree/bindings/fb/mdss-pll.txt
index 6b9238c..5c0bb2a 100644
--- a/Documentation/devicetree/bindings/fb/mdss-pll.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-pll.txt
@@ -14,7 +14,7 @@
 			"qcom,mdss_hdmi_pll_8996_v2", "qcom,mdss_dsi_pll_8996_v2",
 			"qcom,mdss_hdmi_pll_8996_v3", "qcom,mdss_dsi_pll_8952",
 			"qcom,mdss_dsi_pll_8937", "qcom,mdss_hdmi_pll_8996_v3_1p8",
-			"qcom,mdss_dsi_pll_8953"
+			"qcom,mdss_dsi_pll_8953", "qcom,mdss_dsi_pll_sdm439"
 - cell-index:		Specifies the controller used
 - reg:			offset and length of the register set for the device.
 - reg-names :		names to refer to register sets related to this device
diff --git a/Documentation/devicetree/bindings/input/gen_vkeys.txt b/Documentation/devicetree/bindings/input/gen_vkeys.txt
new file mode 100644
index 0000000..2f8d65e
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/gen_vkeys.txt
@@ -0,0 +1,28 @@
+Touchscreen Virtual Keys Device
+
+Generate virtual keys sysfs entry for Android
+
+Required properties:
+
+ - compatible	: should be "qcom,gen-vkeys"
+ - label		: name of the touch controller
+ - qcom,disp-maxx	: Maximum x-coordinate of display
+ - qcom,disp-maxy	: Maximum y-coordinate of display
+ - qcom,panel-maxx	: Maximum x-coordinate of touch panel
+ - qcom,panel-maxy	: Maximum y-coordinate of touch panel
+ - qcom,key-codes	: Array of key codes for virtual keys
+
+Optional properties:
+ - qcom,y-offset	: Offset of y-location for virtual keys, default 0
+
+Example:
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "atmel_mxt_ts";
+		qcom,disp-maxx = <720>;
+		qcom,disp-maxy = <1280>;
+		qcom,panel-maxx = <760>;
+		qcom,panel-maxy = <1424>;
+		qcom,key-codes = <158 139 102 217>;
+		qcom,y-offset = <35>;
+	};
diff --git a/Documentation/devicetree/bindings/input/qpnp-power-on.txt b/Documentation/devicetree/bindings/input/qpnp-power-on.txt
index 0f1d9e1..9addf15 100644
--- a/Documentation/devicetree/bindings/input/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/input/qpnp-power-on.txt
@@ -115,6 +115,10 @@
 - qcom,use-legacy-hard-reset-offset	Boolean property to support legacy
 				hard-reset offset of the PON_RB_SPARE register for
 				some (PON gen2) platforms.
+- qcom,support-twm-config       Boolean property to allow the PON module to be
+                                configured to support TWM modes.
+- qcom,pbs-client               Phandle of the PBS client node. Should be
+                                defined if 'qcom,support-twm-config' is present.
 
 All the below properties are in the sub-node section (properties of the child
 node).
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
new file mode 100644
index 0000000..f7494c4
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
@@ -0,0 +1,120 @@
+FocalTech touch controller
+
+The focaltech controller is connected to host processor
+via i2c. The controller generates interrupts when the
+user touches the panel. The host controller is expected
+to read the touch coordinates over i2c and pass the coordinates
+to the rest of the system.
+
+Required properties:
+
+ - compatible		: should be "focaltech,5x06".
+ - reg			: i2c slave address of the device.
+ - interrupt-parent	: parent of interrupt.
+ - interrupts		: touch sample interrupt to indicate presense or release
+				of fingers on the panel.
+ - vdd-supply		: Power supply needed to power up the device.
+ - vcc_i2c-supply	: Power source required to power up i2c bus.
+ - focaltech,family-id	: family identification of the controller.
+ - focaltech,irq-gpio	: irq gpio which is to provide interrupts to host,
+				same as "interrupts" node. It will also
+				contain active low or active high information.
+ - focaltech,reset-gpio	: reset gpio to control the reset of chip.
+ - focaltech,display-coords : display coordinates in pixels. It is a four
+				tuple consisting of min x, min y, max x and
+				max y values
+ - focaltech,name	: name of the controller
+ - focaltech,group-id	: group id of this device
+ - focaltech,hard-reset-delay-ms : hard reset delay in ms
+ - focaltech,soft-reset-delay-ms : soft reset delay in ms
+ - focaltech,fw-delay-aa-ms : specify the delay in ms after programming 0xaa
+				register for firmware upgrade
+ - focaltech,fw-delay-55-ms : specify the delay in ms after programming 0x55
+				register for firmware upgrade
+ - focaltech,fw-upgrade-id1 : specify the upgrade id1 for firmware upgrade
+ - focaltech,fw-upgrade-id2 : specify the upgrade id2 for firmware upgrade
+ - focaltech,fw-delay-readid-ms : specify the read id delay in ms for firmware upgrade
+ - focaltech,fw-delay-era-flsh-ms : specify the erase flash delay in ms for firmware upgrade
+ - pinctrl-names : This should be defined if a target uses pinctrl framework.
+			See "pinctrl" in Documentation/devicetree/bindings/pinctrl/msm-pinctrl.txt.
+			Specify the names of the configs that pinctrl can install in driver.
+			Following are the pinctrl configs that can be installed:
+			"pmx_ts_active" : Active configuration of pins, this should specify active
+			config defined in pin groups of interrupt and reset gpio.
+			"pmx_ts_suspend" : Disabled configuration of pins, this should specify sleep
+			config defined in pin groups of interrupt and reset gpio.
+			"pmx_ts_release" : Release configuration of pins, this should specify
+			release config defined in pin groups of interrupt and reset gpio.
+
+Optional properties:
+
+ - focaltech,panel-coords : panel coordinates for the chip in pixels.
+				It is a four tuple consisting of min x,
+				min y, max x and max y values.
+ - focaltech,i2c-pull-up : to specify pull up is required.
+ - focaltech,no-force-update : to specify force update is allowed.
+ - focaltech,button-map : button map of key codes. The number
+				of key codes depend on panel
+ - focaltech,fw-name	: specify the firmware file name
+ - focaltech,fw-delay-aa-ms : specify the "aa" delay in ms for firmware upgrade
+ - focaltech,fw-delay-55-ms : specify the "55" delay in ms for firmware upgrade
+ - focaltech,fw-upgrade-id1 : specify the upgrade id1 for firmware upgrade
+ - focaltech,fw-upgrade-id2 : specify the upgrade id2 for firmware upgrade
+ - focaltech,fw-delay-readid-ms : specify the read id delay in ms for firmware upgrade
+ - focaltech,fw-delay-era-flsh-ms : specify the erase flash delay in ms for firmware upgrade
+ - focaltech,fw-auto-cal	: specify whether calibration is needed after firmware upgrade
+ - focaltech,fw-vkey-support	: specify if virtual keys are supported through firmware
+ - focaltech,ignore-id-check : specify ignore family-id check
+ - focaltech,panel-coords : panel coordinates for the chip in pixels.
+				It is a four tuple consisting of min x,
+				min y, max x and max y values
+ - focaltech,fw-name	: specify the firmware file name
+ - focaltech,psensor-support	: specify whether support the proximity sensor
+ - focaltech,gesture-support	: specify whether support gesture feature
+ - focaltech,resume-in-workqueue : specifiy whether to defer the resume to workqueue
+ - clock-names:               : Clock names used for secure touch. They are: "iface_clk", "core_clk"
+ - clocks                        : Defined if 'clock-names' DT property is defined. These clocks
+				   are associated with the underlying I2C bus.
+
+Example:
+	i2c@f9923000{
+		focaltech@38{
+			compatible = "focaltech,5x06";
+			reg = <0x38>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <1 0x2>;
+			vdd-supply = <&pm8110_l19>;
+			vcc_i2c-supply = <&pm8110_l14>;
+			pinctrl-names = "pmx_ts_active","pmx_ts_suspend","pmx_ts_release";
+			pinctrl-0 = <&ts_int_active &ts_reset_active>;
+			pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+			pinctrl-2 = <&ts_release>;
+			focaltech,name = "ft6x06";
+			focaltech,family-id = <0x06>;
+			focaltech,reset-gpio = <&msmgpio 0 0x00>;
+			focaltech,irq-gpio = <&msmgpio 1 0x00>;
+			focaltech,display-coords = <0 0 480 800>;
+			focaltech,panel-coords = <0 0 480 800>;
+			focaltech,button-map= <139 102 158>;
+			focaltech,no-force-update;
+			focaltech,i2c-pull-up;
+			focaltech,group-id = <1>;
+			focaltech,hard-reset-delay = <20>;
+			focaltech,soft-reset-delay = <150>;
+			focaltech,num-max-touches = <2>;
+			focaltech,fw-name = "ft_8610_qrd_fw.bin";
+			focaltech,fw-delay-aa-ms = <100>;
+			focaltech,fw-delay-55-ms = <30>;
+			focaltech,fw-upgrade-id1 = <0x79>;
+			focaltech,fw-upgrade-id2 = <0x08>;
+			focaltech,fw-delay-readid-ms = <10>;
+			focaltech,fw-delay-era-flsh-ms = <2000>;
+			focaltech,fw-auto-cal;
+			focaltech,psensor-support;
+			focaltech,gesture-support;
+			/* Underlying clocks used by secure touch */
+			clock-names = "iface_clk", "core_clk";
+			clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+			<&clock_gcc clk_gcc_blsp1_qup3_i2c_apps_clk>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/synaptics_dsxv26_i2c.txt b/Documentation/devicetree/bindings/input/touchscreen/synaptics_dsxv26_i2c.txt
index c33daab..87a551ba 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/synaptics_dsxv26_i2c.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/synaptics_dsxv26_i2c.txt
@@ -26,6 +26,7 @@
  - synaptics,ub-i2c-addr	 : microbootloader mode I2C slave address.
  - synaptics,cap-button-codes  : virtual key code mappings to be used.
  - synaptics,vir-button-codes  : virtual key code and the response region on panel.
+ - synaptics,wakeup-gestures-en: enable wakeup gestures.
  - synaptics,x-flip		       : modify orientation of the x axis.
  - synaptics,y-flip		       : modify orientation of the y axis.
  - synaptics,reset-delay-ms	   : reset delay for controller (ms), default 100.
diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,mpm.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,mpm.txt
index 833b108..18e8cf5 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/qti,mpm.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/qti,mpm.txt
@@ -52,7 +52,7 @@
 Example:
 
 wakegic: wake-gic@7781b8 {
-	compatible = "qcom,mpm-gic", "qcom,mpm-gic-msm8953", "qcom,mpm-gic-msm8937";
+	compatible = "qcom,mpm-gic", "qcom,mpm-gic-msm8953", "qcom,mpm-gic-msm8937", "qcom,mpm-gic-msm8909";
 	interrupts = <GIC_SPI 171 IRQ_TYPE_EDGE_RISING>;
 	reg = <0x601d4 0x1000>,
 	    <0xb011008 0x4>;  /* MSM_APCS_GCC_BASE 4K */
@@ -85,7 +85,7 @@
 Example:
 
 wakegpio: wake-gpio {
-	compatible = "qcom,mpm-gpio", "qcom,mpm-gpio-msm8953", "qcom,mpm-gpio-msm8937";
+	compatible = "qcom,mpm-gpio", "qcom,mpm-gpio-msm8953", "qcom,mpm-gpio-msm8937","qcom,mpm-gpio-msm8909";
 	interrupt-controller;
 	interrupt-parent = <&tlmm>;
 	#interrupt-cells = <2>;
diff --git a/Documentation/devicetree/bindings/media/video/msm-csi-phy.txt b/Documentation/devicetree/bindings/media/video/msm-csi-phy.txt
index 8a6b3c4..24a3443 100644
--- a/Documentation/devicetree/bindings/media/video/msm-csi-phy.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-csi-phy.txt
@@ -14,6 +14,7 @@
     - "qcom,csiphy-v3.5"
     - "qcom,csiphy-v5.0"
     - "qcom,csiphy-v5.01"
+    - "qcom,csiphy-v10.00"
 - reg : offset and length of the register set for the device
     for the csiphy operating in compatible mode.
 - reg-names : should specify relevant names to each reg property defined.
diff --git a/Documentation/devicetree/bindings/misc/qpnp-misc.txt b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
index a34cbde..ada8da9 100644
--- a/Documentation/devicetree/bindings/misc/qpnp-misc.txt
+++ b/Documentation/devicetree/bindings/misc/qpnp-misc.txt
@@ -16,6 +16,12 @@
 				if a non-zero PWM source is specified under
 				"qcom,pwm-sel" property.
 
+- qcom,support-twm-config	Enable configuration for TWM mode.
+
+- qcom,twm-mode			The TWM mode which PMIC enters post power-off.
+				Valid only if 'qcom,support-twm-config' is
+				defined. If not specified, the default mode
+				is 3.
 Example:
 	qcom,misc@900 {
 		compatible = "qcom,qpnp-misc";
diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt
index 73cd1db..8b63075 100644
--- a/Documentation/devicetree/bindings/platform/msm/ipa.txt
+++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt
@@ -37,6 +37,8 @@
 	compatible "qcom,ipa-smmu-uc-cb"
 - qcom,use-a2-service: determine if A2 service will be used
 - qcom,use-ipa-tethering-bridge: determine if tethering bridge will be used
+- qcom,use-ipa-in-mhi-mode: Boolean context flag to indicate whether
+				device booting in MHI config or not.
 - qcom,use-ipa-bamdma-a2-bridge: determine if a2/ipa hw bridge will be used
 - qcom,ee: which EE is assigned to (non-secure) APPS from IPA-BAM POV. This
 is a number
diff --git a/Documentation/devicetree/bindings/platform/msm/usb-bam.txt b/Documentation/devicetree/bindings/platform/msm/usb-bam.txt
index 7d2e31e..9af22e2 100644
--- a/Documentation/devicetree/bindings/platform/msm/usb-bam.txt
+++ b/Documentation/devicetree/bindings/platform/msm/usb-bam.txt
@@ -36,7 +36,6 @@
 - qcom,reset-bam-on-connect: If present then BAM is RESET before connecting
   pipe. This may be required if BAM peripheral is also reset before connect.
 - qcom,reset-bam-on-disconnect: If present then BAM is RESET after disconnecting pipes.
-- qcom,enable-hsusb-bam-on-boot: If present then BAM is enabled at bootup itself.
 
 A number of USB BAM pipe parameters are represented as sub-nodes:
 
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
index 392ee7b..3d054f3 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
@@ -36,6 +36,8 @@
 	Definition: For details about IIO bindings see:
 		    Documentation/devicetree/bindings/iio/iio-bindings.txt
 
+- #thermal-sensor-cells: Should be 0. See thermal.txt for a description.
+
 - qcom,rradc-base
 	Usage:      required
 	Value type: <u32>
@@ -489,6 +491,7 @@
 	qcom,slope-limit-temp-threshold = <100>;
 	qcom,slope-limit-coeffs = <10 11 12 13>;
 	qcom,battery-thermal-coefficients = [9d 50 ff];
+	#thermal-sensor-cells = <0>;
 	status = "okay";
 
 	qcom,fg-batt-soc@4000 {
@@ -517,3 +520,32 @@
 		reg = <0x4400 0x100>;
 	};
 };
+
+======================================
+Example for thermal zone configuration
+======================================
+
+thermal_zones {
+	pmi8998_fg {
+		polling-delay-passive = <200>;
+		polling-delay = <200>;
+		thermal-governor = <userspace>;
+		thermal-sensors = <&pmi8998_fg>;
+
+		pmi8998_fg_trip1: pmi8998-fg-trip0 {
+			temperature = <45000>;
+			hysteresis = <0>;
+			type = "passive";
+		};
+		pmi8998_fg_trip2: pmi8998-fg-trip2 {
+			temperature = <50000>;
+			hysteresis = <0>;
+			type = "hot";
+		};
+		pmi8998_fg_trip3: pmi8998-fg-trip3 {
+			temperature = <60000>;
+			hysteresis = <0>;
+			type = "alert";
+		};
+	};
+};
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
index f87f7db..efa67f5 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
@@ -41,6 +41,16 @@
 		    when this interrupt fires. If not specified, the
 		    default value is 3200 mV.
 
+- qcom,vbatt-empty-cold-mv
+	Usage:      optional
+	Value type: <u32>
+	Definition: The battery voltage threshold (in mV) at which the
+		    vbatt-empty interrupt fires. This threshold is only
+		    applied at cold temperature specified by
+		    'qcom,cold-temp-threshold'. The SOC is forced to 0
+		    when this interrupt fires. If not specified, the
+		    default value is 3000 mV.
+
 - qcom,vbatt-cutoff-mv
 	Usage:      optional
 	Value type: <u32>
@@ -56,6 +66,16 @@
 		    the action when this interrupt fires. If not specified
 		    the default value is 3500 mV.
 
+- qcom,vbatt-low-cold-mv
+	Usage:      optional
+	Value type: <u32>
+	Definition: The battery voltage threshold (in mV) at which the
+		    the VBAT_LOW interrupt fires. The threshold is only
+		    applied at cold temperature specified by
+		    'qcom,cold-temp-threshold'. Software can take necessary
+		    the action when this interrupt fires. If not specified
+		    the default value is 3800 mV.
+
 - qcom,qg-iterm-ma
 	Usage:      optional
 	Value type: <u32>
@@ -164,6 +184,13 @@
 		    improve the user experience. This is applicable only if
 		    "qcom,hold-soc-while-full" is specified.
 
+- qcom,cold-temp-threshold
+	Usage:      optional
+	Value type: <u32>
+	Definition: Temperature threshold in decidegree at which the low
+		    temperature specific configuration as applied. If not
+		    specified, the default value is 0 degree centigrade.
+
 ==========================================================
 Second Level Nodes - Peripherals managed by QGAUGE driver
 ==========================================================
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
index b7e6a31b..de273cd 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
@@ -167,10 +167,7 @@
   Usage:      optional
   Value type: <phandle>
   Definition: Specifies the phandle of the node which contains the battery
-		profiles supported on the device. This is only specified
-		when step charging and sw-jeita configurations are desired
-		to be get from these properties defined in battery profile:
-		qcom,step-chg-ranges, qcom,jeita-fcc-ranges, qcom,jeita-fv-ranges.
+		profiles supported on the device.
 
 - qcom,flash-derating-soc
   Usage:      optional
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smbcharger.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smbcharger.txt
index efd64cd..d1d66cf 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smbcharger.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smbcharger.txt
@@ -282,6 +282,9 @@
 						battery.
 - qcom,vchg_sns-vadc		Phandle of the VADC node.
 - qcom,vchg-adc-channel-id	The ADC channel to which the VCHG is routed.
+- qcom,max-pulse-allowed	The maximum number of pulses allowed in
+				HVDCP3 mode. It can be used to restrict VBUS
+				to a value.
 
 Example:
 	qcom,qpnp-smbcharger {
diff --git a/Documentation/devicetree/bindings/pwm/pwm-qti-lpg.txt b/Documentation/devicetree/bindings/pwm/pwm-qti-lpg.txt
index 3174ccb..ddd90e1 100644
--- a/Documentation/devicetree/bindings/pwm/pwm-qti-lpg.txt
+++ b/Documentation/devicetree/bindings/pwm/pwm-qti-lpg.txt
@@ -11,26 +11,137 @@
 - reg:
 	Usage: required
 	Value type: <prop-encoded-array>
-	Definition: Register base and length for LPG modules. The length
-		      varies based on the number of channels available in
-		      the PMIC chips.
+	Definition: Register base and length for LPG and LUT modules. LPG size
+		      or length available per channel varies depending on the
+		      number of channels in PMIC.
 
 - reg-names:
 	Usage: required
 	Value type: <string>
 	Definition: The name of the register defined in the reg property.
-		      It must be "lpg-base".
+		      It must have "lpg-base", "lut-base" is optional but
+		      it's required if any LPG channels support LUT mode.
 
 - #pwm-cells:
 	Usage: required
 	Value type: <u32>
-	Definition: See Documentation/devicetree/bindings/pwm/pwm.txt;
+	Definition: The number of cells in "pwms" property specified in
+		      PWM user nodes. It should be 2. The first cell is
+		      the PWM channel ID indexed from 0, and the second
+		      cell is the PWM default period in nanoseconds.
 
+- qcom,lut-patterns:
+	Usage: optional
+	Value type: <prop-encoded-array>
+	Definition: Duty ratios in percentages for LPG working at LUT mode.
+		      These duty ratios will be translated into PWM values
+		      and stored in LUT module. The LUT module has resource
+		      to store 47 PWM values at max and shared for all LPG
+		      channels. This property is required if any LPG channels
+		      support LUT mode.
+
+Subnode is optional if LUT mode is not required, it's required if any LPG
+channels expected to be supported in LUT mode.
+
+Subnode properties:
+Subnodes for each LPG channel (lpg@X) can be defined if any of the following
+parameters needs to be configured for that channel.
+
+- qcom,lpg-chan-id:
+	Usage: required
+	Value type: <u32>
+	Definition: The LPG channel's hardware ID indexed from 1. Allowed
+		      range is 1 - 8. Maximum value depends on the number of
+		      channels supported on PMIC.
+
+- qcom,ramp-step-ms:
+	Usage: required
+	Value type: <u32>
+	Definition: The step duration in milliseconds for LPG staying at each
+		      duty specified in the LUT pattern. Allowed range is
+		      1 - 511.
+
+- qcom,ramp-high-index:
+	Usage: required
+	Value type: <u32>
+	Definition: The high index of the LUT pattern where LPG ends up
+		      ramping to. Allowed range is 1 - 47.
+
+- qcom,ramp-low-index:
+	Usage: required
+	Value type: <u32>
+	Definition: The low index of the LUT pattern from where LPG begins
+		      ramping from. Allowed range is 0 - 46.
+
+- qcom,ramp-from-low-to-high:
+	Usage: optional
+	Value type: <empty>
+	Definition: The flag to specify the LPG ramping direction. The ramping
+		      direction is from low index to high index of the LUT
+		      pattern if it's specified.
+
+- qcom,ramp-pattern-repeat:
+	Usage: optional
+	Value type: <empty>
+	Definition: The flag to specify if LPG would be ramping with the LUT
+		      pattern repeatedly.
+
+- qcom,ramp-toggle:
+	Usage: optional
+	Value type: <empty>
+	Definition: The flag to specify if LPG would toggle the LUT pattern
+		      in ramping. If toggling enabled, LPG would return to the
+		      low index when high index is reached, or return to the high
+		      index when low index is reached.
+
+- qcom,ramp-pause-hi-count:
+	Usage: optional
+	Value type: <u32>
+	Definition: The step count that LPG stop the output when it ramped up
+		      to the high index of the LUT.
+
+- qcom,ramp-pause-lo-count:
+	Usage: optional
+	Value type: <u32>
+	Definition: The step count that LPG stop the output when it ramped up
+		      to the low index of the LUT.
 Example:
 
 	pmi8998_lpg: lpg@b100 {
 		compatible = "qcom,pwm-lpg";
-		reg = <0xb100 0x600>;
-		reg-names = "lpg-base";
+		reg = <0xb100 0x600>, <0xb000 0x100>;
+		reg-names = "lpg-base", "lut-base";
 		#pwm-cells = <2>;
+		qcom,lut-patterns = <0 14 28 42 56 70 84 100
+					100 84 70 56 42 28 14 0>;
+		lpg@3 {
+			qcom,lpg-chan-id = <3>;
+			qcom,ramp-step-ms = <200>;
+			qcom,ramp-pause-hi-count = <10>;
+			qcom,ramp-pause-lo-count = <10>;
+			qcom,ramp-low-index = <0>;
+			qcom,ramp-high-index = <15>;
+			qcom,ramp-from-low-to-high;
+			qcom,ramp-pattern-repeat;
+		};
+		lpg@4 {
+			qcom,lpg-chan-id = <4>;
+			qcom,ramp-step-ms = <200>;
+			qcom,ramp-pause-hi-count = <10>;
+			qcom,ramp-pause-lo-count = <10>;
+			qcom,ramp-low-index = <0>;
+			qcom,ramp-high-index = <15>;
+			qcom,ramp-from-low-to-high;
+			qcom,ramp-pattern-repeat;
+		};
+		lpg@5 {
+			qcom,lpg-chan-id = <5>;
+			qcom,ramp-step-ms = <200>;
+			qcom,ramp-pause-hi-count = <10>;
+			qcom,ramp-pause-lo-count = <10>;
+			qcom,ramp-low-index = <0>;
+			qcom,ramp-high-index = <15>;
+			qcom,ramp-from-low-to-high;
+			qcom,ramp-pattern-repeat;
+		};
 	};
diff --git a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
index de40a7c..a034acc 100644
--- a/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
+++ b/Documentation/devicetree/bindings/qdsp/msm-fastrpc.txt
@@ -15,6 +15,7 @@
 - qcom,rpc-latency-us:	FastRPC QoS latency vote
 - qcom,adsp-remoteheap-vmid:  FastRPC remote heap VMID list
 - qcom,fastrpc-adsp-audio-pdr:  Flag to enable ADSP Audio PDR
+- qcom,fastrpc-adsp-sensors-pdr: Flag to enable Sensors PDR
 
 Optional subnodes:
 - qcom,msm_fastrpc_compute_cb :	Child nodes representing the compute context
@@ -25,12 +26,17 @@
 - iommus : 		A list of phandle and IOMMU specifier pairs that describe the
 			IOMMU master interfaces of the device
 
+Subnode Optional properties:
+- shared-cb : 		Present if context bank need to be shared
+
+
 Example:
 	qcom,msm_fastrpc {
 		compatible = "qcom,msm-fastrpc-adsp";
 		qcom,fastrpc-glink;
 		qcom,rpc-latency-us = <2343>;
 		qcom,adsp-remoteheap-vmid = <22 37>;
+		qcom,fastrpc-adsp-sensors-pdr;
 
 		qcom,msm_fastrpc_compute_cb_1 {
 			compatible = "qcom,msm-fastrpc-compute-cb";
@@ -41,6 +47,7 @@
 			compatible = "qcom,msm-fastrpc-compute-cb";
 			label = "adsprpc-smd";
 			iommus = <&lpass_q6_smmu 9>,
+			shared-cb;
 		};
 	};
 
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt
index 9798ac60..72c4eaf 100644
--- a/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt
@@ -212,8 +212,9 @@
 - qcom,bst-headroom-mv
 	Usage:      optional
 	Value type:  <u16>
-	Definition:  Headroom of the boost (in mV). The minimum headroom is
-		     200mV and if not specified defaults to 200mV.
+	Definition:  Headroom of the boost (in mV). If not specified, then the
+		     default value is 200 mV (PM660L) or 150 mV (for PM855L or
+		     PMI632).
 
 =======
 Example
diff --git a/Documentation/devicetree/bindings/soc/qcom/bg_daemon.txt b/Documentation/devicetree/bindings/soc/qcom/bg_daemon.txt
index 149a01a..1417eb0 100644
--- a/Documentation/devicetree/bindings/soc/qcom/bg_daemon.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/bg_daemon.txt
@@ -6,9 +6,15 @@
 Required properties:
 - compatible : should be "qcom,bg-daemon"
 - qcom,bg-reset-gpio : gpio for the apps processor use to soft reset BG
+- ssr-reg1-supply : Power supply needed to power up the BG device.
+		When BG brought up this regulator will be in normal power mode.
+- ssr-reg2-supply : Power supply needed to power up the BG device.
+		When BG BG brought up this regulator will be in normal power mode.
 
 Example:
 	qcom,bg-daemon {
 		compatible = "qcom,bg-daemon";
 		qcom,bg-reset-gpio = <&pm660_gpios 5 0>;
+		ssr-reg1-supply = <&pm660_l3>;
+		ssr-reg2-supply = <&pm660_l9>;
 	};
diff --git a/Documentation/devicetree/bindings/soc/qcom/dcc.txt b/Documentation/devicetree/bindings/soc/qcom/dcc.txt
index 5150459..c9bf3f5 100644
--- a/Documentation/devicetree/bindings/soc/qcom/dcc.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/dcc.txt
@@ -8,7 +8,7 @@
 Required properties:
 
 - compatible : name of the component used for driver matching, should be
-	       "qcom,dcc" or "qcom,dcc_v2"
+	       "qcom,dcc" or "qcom,dcc-v2"
 
 - reg : physical base address and length of the register set(s), SRAM and XPU
 	of the component.
diff --git a/Documentation/devicetree/bindings/sound/aqt1000_codec.txt b/Documentation/devicetree/bindings/sound/aqt1000_codec.txt
new file mode 100644
index 0000000..af615b8
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/aqt1000_codec.txt
@@ -0,0 +1,79 @@
+Qualcomm Technologies, Inc. for AQT1000 audio CODEC
+
+Required properties:
+
+- compatible: "qcom,aqt1000-i2c-codec" for AQT1000 Codec
+
+- qcom,aqt-rst-gpio-node: Phandle reference to the DT node having codec reset gpio
+			  configuration.
+
+- reg: Address of the codec. This property enabled I2C to get AQT1000 base address.
+
+- qcom,cdc-static-supplies: Static VREG_BOB Supply for AQT1000 codec.
+			    All other supplies are derived from this.
+
+-qcom,cdc-micbias1-mv: micbias1 output voltage in milli volts.
+		       This is used when cfilt is not user configurable
+		       and micbias1 is directly controlled with a register
+		       write.
+
+-qcom,cdc-mclk-clk-rate: Specifies the master clock rate in Hz required for
+			 codec.
+
+Optional properties:
+
+-qcom,cdc-ext-clk-rate: External clock frequency used for AQT1000.
+			All internal clocks for AQT1000 are derived from this clock.
+			If this property is not defined then default external
+			clock rate of 9.6M will be provided.
+
+- qcom,cdc-vdd-mic-bias-supply: phandle of vreg_bob supply's regulator device tree
+			   node.
+
+- qcom,cdc-vdd-mic-bias-voltage: vreg_bob supply's voltage level min and max
+				 in mV.
+- qcom,cdc-vdd-mic-bias-current: vreg_bob supply's max current in mA.
+
+- qcom,cdc-micbias-ldoh-v: LDOH output in volts (should be 3V).
+
+- qcom,cdc-micbias-cfilt1-mv: cfilt1 output voltage in milli volts.
+  cfilt voltage can be set to max of qcom,cdc-micbias-ldoh-v - 0.15V.
+- qcom,cdc-micbias1-cfilt-sel: cfilt to use for micbias1
+			(should be from 1 to 3).
+
+- clock-names : clock name defined for external clock.
+- clocks : external clock defined for codec clock.
+
+Example:
+i2c@a88000 {
+	status = "ok";
+	aqt1000_cdc: aqt1000-i2c-codec@d {
+		status = "disabled";
+		compatible = "qcom,aqt1000-i2c-codec";
+		reg = <0x0d>;
+
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&tlmm>;
+		qcom,gpio-connect = <&tlmm 79 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&aqt_intr_default>;
+
+		qcom,aqt-rst-gpio-node = <&aqt_rst_gpio>;
+
+		qcom,cdc-vdd-mic-bias-supply = <&pm660l_bob>;
+		qcom,cdc-vdd-mic-bias-voltage = <3312000 3312000>;
+		qcom,cdc-vdd-mic-bias-current = <30400>;
+		qcom,cdc-static-supplies = "cdc-vdd-mic-bias";
+
+		qcom,cdc-micbias-ldoh-v = <3>;
+
+		qcom,cdc-ext-clk-rate = <19200000>;
+		qcom,cdc-mclk-clk-rate = <9600000>;
+
+		qcom,cdc-micbias1-mv = <1800>;
+
+		clock-names = "aqt_clk";
+		clocks = <&clock_audio_lnbb AUDIO_PMIC_LNBB_CLK>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 991e26c..7b8ae6f 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -1729,6 +1729,9 @@
 - qcom,msm-mi2s-master: This property is used to inform machine driver
   if MSM is the clock master of mi2s. 1 means master and 0 means slave. The
   first entry is primary mi2s; the second entry is secondary mi2s, and so on.
+- qcom,mi2s-aqt-enabled: This property is used to inform machine driver
+  if AQT1000 codec is enabled or not. If this is enabled then codec name
+  for TERT_MI2S needs to be overridden with AQT codec.
 - qcom,msm-mi2s-ext-mclk: This property is used to inform machine driver
   if MCLK from MSM is used for any external audio connections. 1 means used
   as external mclk source and 0 indicate not used. The first entry is
@@ -3187,3 +3190,80 @@
 		qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrLeft",
 					  "SpkrRight", "SpkrLeft";
 	};
+
+* QCS605 LC  ASoC Machine driver
+
+Required properties:
+- compatible : "qcom,qcs605-dig-asoc-snd"
+- qcom,model : The user-visible name of this sound card.
+- qcom,audio-routing : A list of the connections between audio components.
+- qcom,msm-gpios : Lists down all the gpio sets that are supported.
+- qcom,pinctrl-names : Lists all the possible combinations of the gpio sets
+mentioned in qcom,msm-gpios.
+- pinctrl-names : The combinations of gpio sets from above that are supported in
+the flavor.
+- pinctrl-# : Pinctrl states as mentioned in pinctrl-names.
+
+Optional properties:
+- qcom,wsa-disable : Boolean. Disables WSA speaker dailinks from sound node.
+- qcom,msm-spk-ext-pa : GPIO which enables external speaker pa.
+- qcom,msm-mclk-freq : This property is used to inform machine driver about
+mclk frequency needs to be configured for internal and external PA.
+- asoc-platform: This is phandle list containing the references to platform device
+		 nodes that are used as part of the sound card dai-links.
+- asoc-platform-names: This property contains list of platform names. The order of
+		       the platform names should match to that of the phandle order
+		       given in "asoc-platform".
+- asoc-cpu: This is phandle list containing the references to cpu dai device nodes
+	    that are used as part of the sound card dai-links.
+- asoc-cpu-names: This property contains list of cpu dai names. The order of the
+		  cpu dai names should match to that of the phandle order given.
+- asoc-codec: This is phandle list containing the references to codec dai device
+	nodes that are used as part of the sound card dai-links.
+- asoc-codec-names: This property contains list of codec dai names. The order of the
+	codec dai names should match to that of the phandle order given
+	in "asoc-codec".
+- qcom,wsa-max-devs : Maximum number of WSA881x devices present in the target
+- qcom,wsa-devs : List of phandles for all possible WSA881x devices supported for the target
+- qcom,wsa-aux-dev-prefix : Name prefix with Left/Right configuration for WSA881x device
+- qcom,cdc-dmic-gpios : phandle for Digital mic clk and data gpios.
+- qcom,cdc-sdw-gpios : phandle for soundwire clk and data gpios.
+- qcom,pri-mi2s-gpios : phandle for primary MI2S clk, word select and data gpios.
+- qcom,sec-mi2s-gpios : phandle for secondary MI2S clk, word select and data gpios.
+- qcom,tert-mi2s-gpios : phandle for tertiary MI2S clk, word select and data gpios.
+- qcom,quat-mi2s-gpios : phandle for quaternary MI2S clk, word select and data gpios.
+- qcom,quin-mi2s-gpios : phandle for quinary MI2S clk, word select and data gpios.
+
+Example:
+	 sound {
+		compatible = "qcom,qcs605-dig-asoc-snd";
+		qcom,model = "qcs605-lc-snd-card";
+		qcom,audio-routing =
+			"RX_BIAS", "INT_MCLK0",
+			"SPK_RX_BIAS", "INT_MCLK0",
+			"DMIC1", "DIGITAL_REGULATOR",
+			"DIGITAL_REGULATOR", "Digital Mic1",
+			"DMIC2", "DIGITAL_REGULATOR",
+			"DIGITAL_REGULATOR", "Digital Mic2",
+			"DMIC3", "DIGITAL_REGULATOR",
+			"DIGITAL_REGULATOR", "Digital Mic3",
+			"DMIC4", "DIGITAL_REGULATOR",
+			"DIGITAL_REGULATOR", "Digital Mic4",
+			"SpkrLeft IN", "SPK1 OUT",
+			"SpkrRight IN", "SPK2 OUT";
+
+		qcom,msm-mi2s-master = <1>, <1>, <1>, <1>, <1>;
+		qcom,msm-mclk-freq = <9600000>;
+		qcom,cdc-dmic-gpios = <&cdc_dmic_gpios>;
+
+		asoc-codec = <&stub_codec>, <&msm_digital_codec>,
+				<&msm_sdw_codec>;
+		asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+					"msm_sdw_codec";
+
+		qcom,wsa-max-devs = <2>;
+		qcom,wsa-devs = <&wsa881x_211_en>, <&wsa881x_212_en>,
+				<&wsa881x_213_en>, <&wsa881x_214_en>;
+		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+					"SpkrLeft", "SpkrRight";
+	}
diff --git a/Documentation/devicetree/bindings/sound/wcd_codec.txt b/Documentation/devicetree/bindings/sound/wcd_codec.txt
index 6d2ae5e..585da1a 100644
--- a/Documentation/devicetree/bindings/sound/wcd_codec.txt
+++ b/Documentation/devicetree/bindings/sound/wcd_codec.txt
@@ -439,6 +439,7 @@
 				Value from 4000 to 5550 in mV in steps of 50 mV can be given.
  - qcom,dig-cdc-base-addr: Specifies the digital codec base address for MSM digital
 				core register writes.
+ - qcom,anlg-cdc-mbhc-disable: Boolean variable that informs if AQT1000 codec is enabled or not.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index 881f9ca..0cc8b00 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -82,6 +82,7 @@
 - qcom,smmu-s1-bypass: If present, configure SMMU to bypass stage 1 translation.
 - qcom,no-vbus-vote-with-type-C: If present, then do not try to get and enable VBUS
 	regulator in type-C host mode from dwc3-msm driver.
+- qcom,connector-type-uAB: HW platform is using micro-AB USB connector type.
 
 Sub nodes:
 - Sub node for "DWC3- USB3 controller".
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index b4bc69f..4642d0d 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -2,6 +2,7 @@
 dtb-$(CONFIG_ARCH_SDXPOORWILLS) += sdxpoorwills-rumi.dtb \
 	sdxpoorwills-cdp.dtb \
 	sdxpoorwills-mtp.dtb \
+	sdxpoorwills-atp.dtb \
 	sdxpoorwills-cdp-256.dtb \
 	sdxpoorwills-mtp-256.dtb \
 	sdxpoorwills-dualwifi-cdp.dtb \
diff --git a/arch/arm/boot/dts/qcom/mdm9607-ion.dtsi b/arch/arm/boot/dts/qcom/mdm9607-ion.dtsi
index 6da25c2..3deba29 100644
--- a/arch/arm/boot/dts/qcom/mdm9607-ion.dtsi
+++ b/arch/arm/boot/dts/qcom/mdm9607-ion.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, 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
diff --git a/arch/arm/boot/dts/qcom/msm-pm8019.dtsi b/arch/arm/boot/dts/qcom/msm-pm8019.dtsi
index afb4723..a8c2552 100644
--- a/arch/arm/boot/dts/qcom/msm-pm8019.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm8019.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2013, 2015, Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 2013, 2015, 2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-atp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-atp.dts
new file mode 100644
index 0000000..a1ce68f
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-atp.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 "sdxpoorwills-atp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDXPOORWILLS ATP";
+	compatible = "qcom,sdxpoorwills-atp",
+		"qcom,sdxpoorwills", "qcom,atp";
+	qcom,board-id = <33 0x0>, <33 0x100>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-atp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-atp.dtsi
new file mode 100644
index 0000000..6a3b391
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-atp.dtsi
@@ -0,0 +1,25 @@
+/* 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 "sdxpoorwills.dtsi"
+#include "sdxpoorwills-pinctrl.dtsi"
+#include "sdxpoorwills-mtp-audio-overlay.dtsi"
+
+&serial_uart {
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart3_console_active>;
+	status = "ok";
+};
+
+&qnand_1 {
+	status = "ok";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi
index c652a44..9da25abd 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi
@@ -520,6 +520,34 @@
 						<&tpda_modem_out_funnel_in1>;
 				};
 			};
+
+			port@4 {
+				reg = <0>;
+				funnel_in1_in_etm0: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&etm0_out_funnel_in1>;
+				};
+			};
+		};
+	};
+
+	etm0: etm@7002000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b956>;
+
+		reg = <0x7002000 0x1000>;
+		cpu = <&CPU0>;
+
+		coresight-name = "coresight-etm0";
+
+		clocks = <&clock_aop QDSS_CLK>;
+		clock-names = "apb_pclk";
+
+		port {
+			etm0_out_funnel_in1: endpoint {
+				remote-endpoint = <&funnel_in1_in_etm0>;
+			};
 		};
 	};
 
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dtsi
index 8a7b771..d447724 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dtsi
@@ -11,3 +11,28 @@
  */
 
 #include "sdxpoorwills-cdp.dtsi"
+
+&sdhc_1 {
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+
+	qcom,core_3_0v_support;
+	qcom,nonremovable;
+
+	pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on
+					&sdc1_wlan_gpio_active>;
+	pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off
+					&sdc1_wlan_gpio_sleep>;
+
+	#address-cells = <0>;
+	interrupt-parent = <&sdhc_1>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 210 0
+			1 &intc 0 227 0
+			2 &tlmm 82 0x4>;
+	interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+	/delete-property/ qcom,devfreq,freq-table;
+	/delete-property/ cd-gpios;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi
index 4a2ece8c..b60225a 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi
@@ -11,3 +11,28 @@
  */
 
 #include "sdxpoorwills-mtp.dtsi"
+
+&sdhc_1 {
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+
+	qcom,core_3_0v_support;
+	qcom,nonremovable;
+
+	pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on
+					&sdc1_wlan_gpio_active>;
+	pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off
+					&sdc1_wlan_gpio_sleep>;
+
+	#address-cells = <0>;
+	interrupt-parent = <&sdhc_1>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 210 0
+			1 &intc 0 227 0
+			2 &tlmm 82 0x4>;
+	interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+	/delete-property/ qcom,devfreq,freq-table;
+	/delete-property/ cd-gpios;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
index 08c6c3b..d31916b 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
@@ -1585,6 +1585,34 @@
 			};
 		};
 
+		sdc1_wlan_gpio_active: sdc1_wlan_gpio_active {
+			mux {
+				pins = "gpio81";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio81";
+				output-high;
+				drive-strength = <8>;
+				bias-pull-up;
+			};
+		};
+
+		sdc1_wlan_gpio_sleep: sdc1_wlan_gpio_sleep {
+			mux {
+				pins = "gpio81";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio81";
+				drive-strength = <2>;
+				bias-pull-down;
+				output-low;
+			};
+		};
+
 		smb_int_default: smb_int_default {
 			mux {
 				pins = "gpio42";
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
index ce4d882..77fc533 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
@@ -95,7 +95,7 @@
 
 	qcom,rpm-stats@c300000 {
 		compatible = "qcom,rpm-stats";
-		reg = <0xC300000 0x1000>, <0xC3F0004 0x4>;
+		reg = <0xC300000 0x1000>, <0xC370004 0x4>;
 		reg-names = "phys_addr_base", "offset_addr";
 	};
 };
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index 98d09de..38ba7fc 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -565,7 +565,13 @@
 			compatible = "qcom,msm-imem-diag-dload";
 			reg = <0xc8 200>;
 		};
-};
+	};
+
+	qcom,mpm2-sleep-counter@c221000 {
+		compatible = "qcom,mpm2-sleep-counter";
+		reg = <0x0c221000 0x1000>;
+		clock-frequency = <32768>;
+	};
 
 	restart@c264000 {
 		compatible = "qcom,pshold";
@@ -654,6 +660,13 @@
 		qcom,fragmented-data;
 	};
 
+	qcom,glink-ssr-modem {
+		compatible = "qcom,glink_ssr";
+		label = "modem";
+		qcom,edge = "mpss";
+		qcom,xprt = "smem";
+	};
+
 	qcom,glink_pkt {
 		compatible = "qcom,glinkpkt";
 
@@ -813,8 +826,15 @@
 	qcom,rmnet-ipa {
 		compatible = "qcom,rmnet-ipa3";
 		qcom,rmnet-ipa-ssr;
-		qcom,ipa-loaduC;
-		qcom,ipa-advertise-sg-support;
+	};
+
+	dcc: dcc_v2@10a2000 {
+		compatible = "qcom,dcc-v2";
+		reg = <0x10a2000 0x1000>,
+		      <0x10ae000 0x2000>;
+		reg-names = "dcc-base", "dcc-ram-base";
+
+		dcc-ram-offset = <0x6000>;
 	};
 
 	system_pm {
@@ -1193,7 +1213,7 @@
 			<&pdc 0 54 4>, <&pdc 0 55 4>,
 			<&pdc 0 56 4>, <&pdc 0 57 4>;
 		interrupt-names = "sbd-intr", "lpi-intr",
-			"wol-intr", "tx-ch0-intr",
+			"phy-intr", "tx-ch0-intr",
 			"tx-ch1-intr", "tx-ch2-intr",
 			"tx-ch3-intr", "tx-ch4-intr",
 			"rx-ch0-intr", "rx-ch1-intr",
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index 0c04f9c..0e3a3ec 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -15,7 +15,6 @@
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
-CONFIG_CGROUP_DEBUG=y
 CONFIG_CGROUP_FREEZER=y
 CONFIG_CPUSETS=y
 CONFIG_CGROUP_CPUACCT=y
@@ -27,12 +26,15 @@
 CONFIG_SCHED_AUTOGROUP=y
 CONFIG_SCHED_TUNE=y
 CONFIG_DEFAULT_USE_ENERGY_AWARE=y
+CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_BPF_SYSCALL=y
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -49,7 +51,6 @@
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
 CONFIG_CMA=y
-CONFIG_CMA_DEBUGFS=y
 CONFIG_ZSMALLOC=y
 CONFIG_BALANCE_ANON_FILE_RECLAIM=y
 CONFIG_SECCOMP=y
@@ -62,7 +63,6 @@
 CONFIG_PM_AUTOSLEEP=y
 CONFIG_PM_WAKELOCKS=y
 CONFIG_PM_WAKELOCKS_LIMIT=0
-CONFIG_PM_DEBUG=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -173,7 +173,6 @@
 CONFIG_BRIDGE_NF_EBTABLES=y
 CONFIG_BRIDGE_EBT_BROUTE=y
 CONFIG_L2TP=y
-CONFIG_L2TP_DEBUGFS=y
 CONFIG_L2TP_V3=y
 CONFIG_L2TP_IP=y
 CONFIG_L2TP_ETH=y
@@ -219,6 +218,7 @@
 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
@@ -266,11 +266,10 @@
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_QPNP_POWER_ON=y
 CONFIG_INPUT_UINPUT=y
-CONFIG_SERIAL_MSM=y
-CONFIG_SERIAL_MSM_CONSOLE=y
 CONFIG_SERIAL_MSM_HS=y
 CONFIG_SERIAL_MSM_SMD=y
 CONFIG_DIAG_CHAR=y
+CONFIG_DIAG_USES_SMD=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM_LEGACY=y
 CONFIG_MSM_SMD_PKT=y
@@ -318,8 +317,13 @@
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_QCOM_KGSL=y
 CONFIG_FB=y
 CONFIG_FB_VIRTUAL=y
+CONFIG_FB_MSM=y
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_MDP3=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_LOGO=y
@@ -357,6 +361,7 @@
 CONFIG_USB_CONFIGFS_ACM=y
 CONFIG_USB_CONFIGFS_NCM=y
 CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_RMNET_BAM=y
 CONFIG_USB_CONFIGFS_EEM=y
 CONFIG_USB_CONFIGFS_MASS_STORAGE=y
 CONFIG_USB_CONFIGFS_F_FS=y
@@ -381,6 +386,10 @@
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_MSM=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_QPNP_HAPTICS=y
+CONFIG_LEDS_TRIGGERS=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_QPNP=y
 CONFIG_DMADEVICES=y
@@ -392,13 +401,18 @@
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
 CONFIG_ION=y
 CONFIG_ION_MSM=y
+CONFIG_IPA=y
+CONFIG_RMNET_IPA=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_NDP_BAM=y
 CONFIG_QPNP_REVID=y
 CONFIG_USB_BAM=y
+CONFIG_MSM_RMNET_BAM=y
+CONFIG_MSM_MDSS_PLL=y
 CONFIG_REMOTE_SPINLOCK_MSM=y
 CONFIG_MAILBOX=y
 CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
 CONFIG_QCOM_PM=y
 CONFIG_MSM_SPM=y
 CONFIG_MSM_L2_SPM=y
@@ -406,6 +420,7 @@
 CONFIG_MSM_CORE_HANG_DETECT=y
 CONFIG_MSM_GLADIATOR_HANG_DETECT=y
 CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QPNP_PBS=y
 CONFIG_QCOM_MEMORY_DUMP_V2=y
 CONFIG_QCOM_BUS_SCALING=y
 CONFIG_QCOM_SECURE_BUFFER=y
@@ -414,6 +429,7 @@
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_DEBUG=y
 CONFIG_MSM_GLINK=y
+CONFIG_MSM_TZ_SMMU=y
 CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
 CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
 CONFIG_MSM_GLINK_SPI_XPRT=y
@@ -431,12 +447,21 @@
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_MSM_BAM_DMUX=y
+CONFIG_MSM_GLINK_BGCOM_XPRT=y
+CONFIG_MSM_BGCOM_INTERFACE=y
+CONFIG_MSM_BGRSB=y
+CONFIG_MSM_PIL_SSR_BG=y
+CONFIG_MSM_BGCOM=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_QCOM_DEVFREQ_DEVBW=y
 CONFIG_IIO=y
 CONFIG_QCOM_SPMI_IADC=y
 CONFIG_QCOM_SPMI_VADC=y
 CONFIG_QCOM_RRADC=y
 CONFIG_PWM=y
+CONFIG_QTI_MPM=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
 CONFIG_SENSORS_SSC=y
@@ -447,6 +472,7 @@
 CONFIG_EXT4_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
 CONFIG_FUSE_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
@@ -456,27 +482,11 @@
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 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
-CONFIG_DEBUG_PAGEALLOC=y
-CONFIG_SLUB_DEBUG_PANIC_ON=y
-CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_FREE=y
-CONFIG_DEBUG_OBJECTS_TIMERS=y
-CONFIG_DEBUG_OBJECTS_WORK=y
-CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
-CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
-CONFIG_SLUB_DEBUG_ON=y
-CONFIG_DEBUG_KMEMLEAK=y
-CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
-CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
-CONFIG_DEBUG_STACK_USAGE=y
-CONFIG_DEBUG_MEMORY_INIT=y
 CONFIG_LOCKUP_DETECTOR=y
 # CONFIG_DETECT_HUNG_TASK is not set
 CONFIG_WQ_WATCHDOG=y
@@ -485,26 +495,11 @@
 CONFIG_PANIC_ON_RT_THROTTLING=y
 CONFIG_SCHEDSTATS=y
 CONFIG_SCHED_STACK_END_CHECK=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_ATOMIC_SLEEP=y
-CONFIG_DEBUG_LIST=y
-CONFIG_FAULT_INJECTION=y
-CONFIG_FAIL_PAGE_ALLOC=y
-CONFIG_FAULT_INJECTION_DEBUG_FS=y
-CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
-CONFIG_IPC_LOGGING=y
-CONFIG_QCOM_RTB=y
-CONFIG_QCOM_RTB_SEPARATE_CPUS=y
-CONFIG_FUNCTION_TRACER=y
-CONFIG_IRQSOFF_TRACER=y
-CONFIG_PREEMPT_TRACER=y
-CONFIG_BLK_DEV_IO_TRACE=y
-CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_FTRACE is not set
 CONFIG_LKDTM=y
-CONFIG_MEMTEST=y
 CONFIG_PANIC_ON_DATA_CORRUPTION=y
-CONFIG_DEBUG_USER=y
+# CONFIG_ARM_UNWIND is not set
 CONFIG_PID_IN_CONTEXTIDR=y
 CONFIG_DEBUG_SET_MODULE_RONX=y
 CONFIG_CORESIGHT=y
diff --git a/arch/arm/configs/msm8909w_defconfig b/arch/arm/configs/msm8909w_defconfig
index 0c04f9c..bb6bc88 100644
--- a/arch/arm/configs/msm8909w_defconfig
+++ b/arch/arm/configs/msm8909w_defconfig
@@ -28,11 +28,13 @@
 CONFIG_SCHED_TUNE=y
 CONFIG_DEFAULT_USE_ENERGY_AWARE=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_BPF_SYSCALL=y
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
@@ -219,6 +221,7 @@
 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
@@ -271,6 +274,7 @@
 CONFIG_SERIAL_MSM_HS=y
 CONFIG_SERIAL_MSM_SMD=y
 CONFIG_DIAG_CHAR=y
+CONFIG_DIAG_USES_SMD=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM_LEGACY=y
 CONFIG_MSM_SMD_PKT=y
@@ -318,8 +322,13 @@
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_QCOM_KGSL=y
 CONFIG_FB=y
 CONFIG_FB_VIRTUAL=y
+CONFIG_FB_MSM=y
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_MDP3=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_LOGO=y
@@ -357,6 +366,7 @@
 CONFIG_USB_CONFIGFS_ACM=y
 CONFIG_USB_CONFIGFS_NCM=y
 CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_RMNET_BAM=y
 CONFIG_USB_CONFIGFS_EEM=y
 CONFIG_USB_CONFIGFS_MASS_STORAGE=y
 CONFIG_USB_CONFIGFS_F_FS=y
@@ -381,6 +391,10 @@
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_MSM=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_QPNP_HAPTICS=y
+CONFIG_LEDS_TRIGGERS=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_QPNP=y
 CONFIG_DMADEVICES=y
@@ -392,13 +406,18 @@
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
 CONFIG_ION=y
 CONFIG_ION_MSM=y
+CONFIG_IPA=y
+CONFIG_RMNET_IPA=y
 CONFIG_SPS=y
 CONFIG_SPS_SUPPORT_NDP_BAM=y
 CONFIG_QPNP_REVID=y
 CONFIG_USB_BAM=y
+CONFIG_MSM_RMNET_BAM=y
+CONFIG_MSM_MDSS_PLL=y
 CONFIG_REMOTE_SPINLOCK_MSM=y
 CONFIG_MAILBOX=y
 CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
 CONFIG_QCOM_PM=y
 CONFIG_MSM_SPM=y
 CONFIG_MSM_L2_SPM=y
@@ -406,6 +425,7 @@
 CONFIG_MSM_CORE_HANG_DETECT=y
 CONFIG_MSM_GLADIATOR_HANG_DETECT=y
 CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QPNP_PBS=y
 CONFIG_QCOM_MEMORY_DUMP_V2=y
 CONFIG_QCOM_BUS_SCALING=y
 CONFIG_QCOM_SECURE_BUFFER=y
@@ -414,6 +434,7 @@
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_DEBUG=y
 CONFIG_MSM_GLINK=y
+CONFIG_MSM_TZ_SMMU=y
 CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
 CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
 CONFIG_MSM_GLINK_SPI_XPRT=y
@@ -431,12 +452,21 @@
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_MSM_BAM_DMUX=y
+CONFIG_MSM_GLINK_BGCOM_XPRT=y
+CONFIG_MSM_BGCOM_INTERFACE=y
+CONFIG_MSM_BGRSB=y
+CONFIG_MSM_PIL_SSR_BG=y
+CONFIG_MSM_BGCOM=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_QCOM_DEVFREQ_DEVBW=y
 CONFIG_IIO=y
 CONFIG_QCOM_SPMI_IADC=y
 CONFIG_QCOM_SPMI_VADC=y
 CONFIG_QCOM_RRADC=y
 CONFIG_PWM=y
+CONFIG_QTI_MPM=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
 CONFIG_SENSORS_SSC=y
@@ -447,6 +477,7 @@
 CONFIG_EXT4_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
 CONFIG_FUSE_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
@@ -531,6 +562,8 @@
 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_OTA_CRYPTO=y
 CONFIG_CRYPTO_DEV_QCOM_ICE=y
 CONFIG_ARM_CRYPTO=y
diff --git a/arch/arm/configs/msm8937-perf_defconfig b/arch/arm/configs/msm8937-perf_defconfig
new file mode 100644
index 0000000..a6a85f1
--- /dev/null
+++ b/arch/arm/configs/msm8937-perf_defconfig
@@ -0,0 +1,627 @@
+CONFIG_LOCALVERSION="-perf"
+# 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_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_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# 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_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_ARCH_MMAP_RND_BITS=16
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MSM8937=y
+CONFIG_ARCH_MSM8917=y
+CONFIG_ARCH_SDM439=y
+CONFIG_ARCH_SDM429=y
+# CONFIG_VDSO is not set
+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_CMA=y
+CONFIG_CMA_DEBUGFS=y
+CONFIG_ZSMALLOC=y
+CONFIG_SECCOMP=y
+CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_CPU_FREQ_MSM=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_DEBUGFS=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_SKBEDIT=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_BT=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+# CONFIG_CFG80211_CRDA_SUPPORT is not set
+CONFIG_RFKILL=y
+CONFIG_NFC_NQ=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_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_HDCP_QSEECOM=y
+CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_SERIAL_MSM_SMD=y
+CONFIG_DIAG_CHAR=y
+CONFIG_DIAG_USES_SMD=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_SMD_PKT=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_MSM_RDBG=m
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MSM_V2=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
+CONFIG_PINCTRL_MSM8937=y
+CONFIG_PINCTRL_MSM8917=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_QPNP_PIN=y
+CONFIG_GPIO_QPNP_PIN_DEBUG=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_QPNP_FG=y
+CONFIG_SMB135X_CHARGER=y
+CONFIG_SMB1351_USB_CHARGER=y
+CONFIG_QPNP_SMB5=y
+CONFIG_QPNP_SMBCHARGER=y
+CONFIG_QPNP_TYPEC=y
+CONFIG_QPNP_QG=y
+CONFIG_MSM_APM=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_MFD_SPMI_PMIC=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_PROXY_CONSUMER=y
+CONFIG_REGULATOR_CPR=y
+CONFIG_REGULATOR_CPR4_APSS=y
+CONFIG_REGULATOR_CPRH_KBSS=y
+CONFIG_REGULATOR_MEM_ACC=y
+CONFIG_REGULATOR_MSM_GFX_LDO=y
+CONFIG_REGULATOR_QPNP_LABIBB=y
+CONFIG_REGULATOR_QPNP_LCDB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_RPM_SMD=y
+CONFIG_REGULATOR_SPM=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_CAMERA=y
+CONFIG_MSM_CAMERA_DEBUG=y
+CONFIG_MSMB_CAMERA=y
+CONFIG_MSMB_CAMERA_DEBUG=y
+CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
+CONFIG_MSM_CSI20_HEADER=y
+CONFIG_MSM_CSI22_HEADER=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSI31_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_EEPROM=y
+CONFIG_MSM_ISPIF_V2=y
+CONFIG_IMX134=y
+CONFIG_IMX132=y
+CONFIG_OV9724=y
+CONFIG_OV5648=y
+CONFIG_GC0339=y
+CONFIG_OV8825=y
+CONFIG_OV8865=y
+CONFIG_s5k4e1=y
+CONFIG_OV12830=y
+CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
+CONFIG_MSMB_JPEG=y
+CONFIG_MSM_FD=y
+CONFIG_MSM_JPEGDMA=y
+CONFIG_MSM_VIDC_3X_V4L2=y
+CONFIG_MSM_VIDC_3X_GOVERNORS=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=y
+CONFIG_QCOM_KGSL=y
+CONFIG_FB=y
+CONFIG_FB_MSM=y
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_SERIAL=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_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_QCRNDIS=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+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
+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_QDSS=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
+CONFIG_LEDS_QTI_TRI_LED=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_QPNP_FLASH=y
+CONFIG_LEDS_QPNP_FLASH_V2=y
+CONFIG_LEDS_QPNP_WLED=y
+CONFIG_LEDS_QPNP_HAPTICS=y
+CONFIG_LEDS_QPNP_VIBRATOR_LDO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_DMADEVICES=y
+CONFIG_QCOM_SPS_DMA=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_IPA=y
+CONFIG_RMNET_IPA=y
+CONFIG_RNDIS_IPA=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_COINCELL=y
+CONFIG_QPNP_REVID=y
+CONFIG_USB_BAM=y
+CONFIG_MSM_RMNET_BAM=y
+CONFIG_MSM_MDSS_PLL=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MAILBOX=y
+CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
+CONFIG_MSM_SPM=y
+CONFIG_MSM_L2_SPM=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_MSM_RPM_SMD=y
+CONFIG_QCOM_BUS_SCALING=y
+CONFIG_QCOM_SECURE_BUFFER=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_MSM_SMEM=y
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_DEBUG=y
+CONFIG_MSM_TZ_SMMU=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_SYSMON_COMM=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_ICNSS=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_AVTIMER=y
+CONFIG_MSM_PM=y
+CONFIG_QCOM_DCC=y
+CONFIG_QTI_RPM_STATS_LOG=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_MEM_SHARE_QMI_SERVICE=y
+CONFIG_MSM_BAM_DMUX=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_SIMPLE_DEV=y
+CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_SPDM_SCM=y
+CONFIG_DEVFREQ_SPDM=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
+CONFIG_PWM_QTI_LPG=y
+CONFIG_QTI_MPM=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_SENSORS_SSC=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=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_PANIC_TIMEOUT=5
+CONFIG_SCHEDSTATS=y
+CONFIG_SCHED_STACK_END_CHECK=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_IPC_LOGGING=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_REMOTE_ETM=y
+CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
+CONFIG_CORESIGHT_CTI=y
+CONFIG_CORESIGHT_EVENT=y
+CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_OTA_CRYPTO=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_ARM_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM_NEON=y
+CONFIG_CRYPTO_SHA2_ARM_CE=y
+CONFIG_CRYPTO_AES_ARM_BS=y
+CONFIG_CRYPTO_AES_ARM_CE=y
+CONFIG_QMI_ENCDEC=y
diff --git a/arch/arm/configs/msm8937_defconfig b/arch/arm/configs/msm8937_defconfig
new file mode 100644
index 0000000..54461cf
--- /dev/null
+++ b/arch/arm/configs/msm8937_defconfig
@@ -0,0 +1,686 @@
+# 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_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_RCU_EXPERT=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_ALL=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHEDTUNE=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_BPF=y
+CONFIG_SCHED_CORE_CTL=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# 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_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=m
+CONFIG_KPROBES=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_ARCH_MMAP_RND_BITS=16
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MSM8937=y
+CONFIG_ARCH_MSM8917=y
+CONFIG_ARCH_SDM439=y
+CONFIG_ARCH_SDM429=y
+# CONFIG_VDSO is not set
+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_CMA=y
+CONFIG_CMA_DEBUGFS=y
+CONFIG_ZSMALLOC=y
+CONFIG_SECCOMP=y
+CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_CPU_FREQ_MSM=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_PM_DEBUG=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TEE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_RPFILTER=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RPFILTER=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_L2TP=y
+CONFIG_L2TP_DEBUGFS=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_SKBEDIT=y
+CONFIG_DNS_RESOLVER=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_BT=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+# CONFIG_CFG80211_CRDA_SUPPORT is not set
+CONFIG_RFKILL=y
+CONFIG_NFC_NQ=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_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_HDCP_QSEECOM=y
+CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_SERIAL_MSM_SMD=y
+CONFIG_DIAG_CHAR=y
+CONFIG_DIAG_USES_SMD=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_SMD_PKT=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_MSM_RDBG=m
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MSM_V2=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
+CONFIG_PINCTRL_MSM8937=y
+CONFIG_PINCTRL_MSM8917=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_QPNP_PIN=y
+CONFIG_GPIO_QPNP_PIN_DEBUG=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_QPNP_FG=y
+CONFIG_SMB135X_CHARGER=y
+CONFIG_SMB1351_USB_CHARGER=y
+CONFIG_QPNP_SMB5=y
+CONFIG_QPNP_SMBCHARGER=y
+CONFIG_QPNP_TYPEC=y
+CONFIG_QPNP_QG=y
+CONFIG_MSM_APM=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_MFD_SPMI_PMIC=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_PROXY_CONSUMER=y
+CONFIG_REGULATOR_CPR=y
+CONFIG_REGULATOR_CPR4_APSS=y
+CONFIG_REGULATOR_CPRH_KBSS=y
+CONFIG_REGULATOR_MEM_ACC=y
+CONFIG_REGULATOR_MSM_GFX_LDO=y
+CONFIG_REGULATOR_QPNP_LABIBB=y
+CONFIG_REGULATOR_QPNP_LCDB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_RPM_SMD=y
+CONFIG_REGULATOR_SPM=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_MEDIA_USB_SUPPORT=y
+CONFIG_USB_VIDEO_CLASS=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_CAMERA=y
+CONFIG_MSM_CAMERA_DEBUG=y
+CONFIG_MSMB_CAMERA=y
+CONFIG_MSMB_CAMERA_DEBUG=y
+CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
+CONFIG_MSM_CSI20_HEADER=y
+CONFIG_MSM_CSI22_HEADER=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSI31_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_EEPROM=y
+CONFIG_MSM_ISPIF_V2=y
+CONFIG_IMX134=y
+CONFIG_IMX132=y
+CONFIG_OV9724=y
+CONFIG_OV5648=y
+CONFIG_GC0339=y
+CONFIG_OV8825=y
+CONFIG_OV8865=y
+CONFIG_s5k4e1=y
+CONFIG_OV12830=y
+CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
+CONFIG_MSMB_JPEG=y
+CONFIG_MSM_FD=y
+CONFIG_MSM_JPEGDMA=y
+CONFIG_MSM_VIDC_3X_V4L2=y
+CONFIG_MSM_VIDC_3X_GOVERNORS=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=y
+CONFIG_QCOM_KGSL=y
+CONFIG_FB=y
+CONFIG_FB_VIRTUAL=y
+CONFIG_FB_MSM=y
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_SERIAL=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_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_QCRNDIS=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+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
+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_QDSS=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_RING_BUFFER=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
+CONFIG_LEDS_QTI_TRI_LED=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_QPNP_FLASH=y
+CONFIG_LEDS_QPNP_FLASH_V2=y
+CONFIG_LEDS_QPNP_WLED=y
+CONFIG_LEDS_QPNP_HAPTICS=y
+CONFIG_LEDS_QPNP_VIBRATOR_LDO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_DMADEVICES=y
+CONFIG_QCOM_SPS_DMA=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_IPA=y
+CONFIG_RMNET_IPA=y
+CONFIG_RNDIS_IPA=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_COINCELL=y
+CONFIG_QPNP_REVID=y
+CONFIG_USB_BAM=y
+CONFIG_MSM_EXT_DISPLAY=y
+CONFIG_MSM_RMNET_BAM=y
+CONFIG_MSM_MDSS_PLL=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MAILBOX=y
+CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_IOMMU_DEBUG=y
+CONFIG_IOMMU_DEBUG_TRACKING=y
+CONFIG_IOMMU_TESTS=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
+CONFIG_MSM_SPM=y
+CONFIG_MSM_L2_SPM=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_CORE_HANG_DETECT=y
+CONFIG_MSM_GLADIATOR_HANG_DETECT=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_MSM_RPM_SMD=y
+CONFIG_QCOM_BUS_SCALING=y
+CONFIG_QCOM_SECURE_BUFFER=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_MSM_SMEM=y
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_DEBUG=y
+CONFIG_MSM_TZ_SMMU=y
+CONFIG_TRACER_PKT=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_SYSMON_COMM=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_ICNSS=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_AVTIMER=y
+CONFIG_MSM_PM=y
+CONFIG_QCOM_DCC=y
+CONFIG_QTI_RPM_STATS_LOG=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_MEM_SHARE_QMI_SERVICE=y
+CONFIG_MSM_BAM_DMUX=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_SIMPLE_DEV=y
+CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_SPDM_SCM=y
+CONFIG_DEVFREQ_SPDM=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
+CONFIG_PWM_QTI_LPG=y
+CONFIG_QTI_MPM=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_SENSORS_SSC=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_WARN=2048
+CONFIG_PAGE_OWNER=y
+CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_SLUB_DEBUG_PANIC_ON=y
+CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_FREE=y
+CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_DEBUG_OBJECTS_WORK=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
+CONFIG_SLUB_DEBUG_ON=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_WQ_WATCHDOG=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_PANIC_ON_SCHED_BUG=y
+CONFIG_PANIC_ON_RT_THROTTLING=y
+CONFIG_SCHEDSTATS=y
+CONFIG_SCHED_STACK_END_CHECK=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_LIST=y
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_IPC_LOGGING=y
+CONFIG_QCOM_RTB=y
+CONFIG_QCOM_RTB_SEPARATE_CPUS=y
+CONFIG_FUNCTION_TRACER=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_LKDTM=y
+CONFIG_MEMTEST=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
+CONFIG_DEBUG_USER=y
+CONFIG_PID_IN_CONTEXTIDR=y
+CONFIG_DEBUG_SET_MODULE_RONX=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_REMOTE_ETM=y
+CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
+CONFIG_CORESIGHT_CTI=y
+CONFIG_CORESIGHT_EVENT=y
+CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_LSM_MMAP_MIN_ADDR=4096
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_OTA_CRYPTO=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_ARM_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM_NEON=y
+CONFIG_CRYPTO_SHA2_ARM_CE=y
+CONFIG_CRYPTO_AES_ARM_BS=y
+CONFIG_CRYPTO_AES_ARM_CE=y
+CONFIG_QMI_ENCDEC=y
diff --git a/arch/arm/configs/msm8953-perf_defconfig b/arch/arm/configs/msm8953-perf_defconfig
index 6ac3955..bfa6cc7 100644
--- a/arch/arm/configs/msm8953-perf_defconfig
+++ b/arch/arm/configs/msm8953-perf_defconfig
@@ -6,6 +6,9 @@
 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
@@ -27,6 +30,8 @@
 CONFIG_SCHED_TUNE=y
 CONFIG_DEFAULT_USE_ENERGY_AWARE=y
 CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
 # CONFIG_RD_XZ is not set
 # CONFIG_RD_LZO is not set
 # CONFIG_RD_LZ4 is not set
@@ -49,9 +54,8 @@
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_MSM8953=y
-CONFIG_ARCH_MSM8937=y
-CONFIG_ARCH_MSM8917=y
 CONFIG_ARCH_SDM450=y
+CONFIG_ARCH_SDM632=y
 # CONFIG_VDSO is not set
 CONFIG_SMP=y
 CONFIG_SCHED_MC=y
@@ -63,7 +67,7 @@
 CONFIG_CMA=y
 CONFIG_CMA_DEBUGFS=y
 CONFIG_ZSMALLOC=y
-CONFIG_BALANCE_ANON_FILE_RECLAIM=y
+CONFIG_PROCESS_RECLAIM=y
 CONFIG_SECCOMP=y
 CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
 CONFIG_CPU_FREQ=y
@@ -203,8 +207,6 @@
 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
@@ -216,9 +218,6 @@
 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
@@ -240,6 +239,7 @@
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_HDCP_QSEECOM=y
 CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
 CONFIG_MEMORY_STATE_TIME=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
@@ -264,6 +264,14 @@
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 CONFIG_PPP=y
 CONFIG_PPP_BSDCOMP=y
 CONFIG_PPP_DEFLATE=y
@@ -277,6 +285,21 @@
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
 CONFIG_USB_USBNET=y
+# CONFIG_WLAN_VENDOR_ADMTEK is not set
+# CONFIG_WLAN_VENDOR_ATH is not set
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_CISCO is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+# CONFIG_WLAN_VENDOR_MARVELL is not set
+# CONFIG_WLAN_VENDOR_MEDIATEK is not set
+# CONFIG_WLAN_VENDOR_RALINK is not set
+# CONFIG_WLAN_VENDOR_REALTEK is not set
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_CLD_LL_CORE=y
 CONFIG_INPUT_EVDEV=y
@@ -284,6 +307,8 @@
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_FT5X06=y
+CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_HBTP_INPUT=y
 CONFIG_INPUT_QPNP_POWER_ON=y
@@ -311,8 +336,6 @@
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
 CONFIG_PINCTRL_MSM8953=y
-CONFIG_PINCTRL_MSM8937=y
-CONFIG_PINCTRL_MSM8917=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_QPNP_PIN=y
@@ -373,7 +396,7 @@
 CONFIG_MSM_CSIPHY=y
 CONFIG_MSM_CSID=y
 CONFIG_MSM_EEPROM=y
-CONFIG_MSM_ISPIF_V2=y
+CONFIG_MSM_ISPIF=y
 CONFIG_IMX134=y
 CONFIG_IMX132=y
 CONFIG_OV9724=y
@@ -400,9 +423,6 @@
 CONFIG_FB_MSM_MDSS_XLOG_DEBUG=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
@@ -422,8 +442,6 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MSM=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_ACM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
@@ -535,6 +553,7 @@
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_QMI_INTERFACE=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_SYSMON_COMM=y
 CONFIG_MSM_PIL=y
 CONFIG_MSM_PIL_SSR_GENERIC=y
 CONFIG_MSM_PIL_MSS_QDSP6V5=y
@@ -564,9 +583,7 @@
 CONFIG_ANDROID_BINDER_IPC=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
@@ -577,6 +594,7 @@
 CONFIG_TMPFS=y
 CONFIG_ECRYPT_FS=y
 CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
 # CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
diff --git a/arch/arm/configs/msm8953_defconfig b/arch/arm/configs/msm8953_defconfig
index 104e206..b7dc23d 100644
--- a/arch/arm/configs/msm8953_defconfig
+++ b/arch/arm/configs/msm8953_defconfig
@@ -31,6 +31,8 @@
 CONFIG_SCHED_TUNE=y
 CONFIG_DEFAULT_USE_ENERGY_AWARE=y
 CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
 # CONFIG_RD_XZ is not set
 # CONFIG_RD_LZO is not set
 # CONFIG_RD_LZ4 is not set
@@ -55,9 +57,8 @@
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_MSM8953=y
-CONFIG_ARCH_MSM8937=y
-CONFIG_ARCH_MSM8917=y
 CONFIG_ARCH_SDM450=y
+CONFIG_ARCH_SDM632=y
 # CONFIG_VDSO is not set
 CONFIG_SMP=y
 CONFIG_SCHED_MC=y
@@ -69,7 +70,7 @@
 CONFIG_CMA=y
 CONFIG_CMA_DEBUGFS=y
 CONFIG_ZSMALLOC=y
-CONFIG_BALANCE_ANON_FILE_RECLAIM=y
+CONFIG_PROCESS_RECLAIM=y
 CONFIG_SECCOMP=y
 CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
 CONFIG_CPU_FREQ=y
@@ -210,8 +211,6 @@
 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
@@ -223,9 +222,6 @@
 CONFIG_NET_EMATCH_META=y
 CONFIG_NET_EMATCH_TEXT=y
 CONFIG_NET_CLS_ACT=y
-CONFIG_NET_ACT_GACT=y
-CONFIG_NET_ACT_MIRRED=y
-CONFIG_NET_ACT_SKBEDIT=y
 CONFIG_DNS_RESOLVER=y
 CONFIG_RMNET_DATA=y
 CONFIG_RMNET_DATA_FC=y
@@ -273,6 +269,14 @@
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 CONFIG_PPP=y
 CONFIG_PPP_BSDCOMP=y
 CONFIG_PPP_DEFLATE=y
@@ -286,6 +290,21 @@
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
 CONFIG_USB_USBNET=y
+# CONFIG_WLAN_VENDOR_ADMTEK is not set
+# CONFIG_WLAN_VENDOR_ATH is not set
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_CISCO is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+# CONFIG_WLAN_VENDOR_MARVELL is not set
+# CONFIG_WLAN_VENDOR_MEDIATEK is not set
+# CONFIG_WLAN_VENDOR_RALINK is not set
+# CONFIG_WLAN_VENDOR_REALTEK is not set
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_CLD_LL_CORE=y
 CONFIG_INPUT_EVDEV=y
@@ -293,6 +312,8 @@
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_FT5X06=y
+CONFIG_TOUCHSCREEN_GEN_VKEYS=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_HBTP_INPUT=y
 CONFIG_INPUT_QPNP_POWER_ON=y
@@ -322,8 +343,6 @@
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
 CONFIG_PINCTRL_MSM8953=y
-CONFIG_PINCTRL_MSM8937=y
-CONFIG_PINCTRL_MSM8917=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_QPNP_PIN=y
@@ -384,7 +403,7 @@
 CONFIG_MSM_CSIPHY=y
 CONFIG_MSM_CSID=y
 CONFIG_MSM_EEPROM=y
-CONFIG_MSM_ISPIF_V2=y
+CONFIG_MSM_ISPIF=y
 CONFIG_IMX134=y
 CONFIG_IMX132=y
 CONFIG_OV9724=y
@@ -412,9 +431,6 @@
 CONFIG_FB_MSM_MDSS_XLOG_DEBUG=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
@@ -434,8 +450,6 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MSM=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_ACM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
@@ -555,6 +569,7 @@
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_QMI_INTERFACE=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_SYSMON_COMM=y
 CONFIG_MSM_PIL=y
 CONFIG_MSM_PIL_SSR_GENERIC=y
 CONFIG_MSM_PIL_MSS_QDSP6V5=y
@@ -584,9 +599,7 @@
 CONFIG_ANDROID_BINDER_IPC=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
@@ -597,6 +610,7 @@
 CONFIG_TMPFS=y
 CONFIG_ECRYPT_FS=y
 CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
 # CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index e3c1c1a..889e812 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -374,6 +374,7 @@
 CONFIG_QCOM_DCC_V2=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_QMP_DEBUGFS_CLIENT=y
 CONFIG_EXTCON_QCOM_SPMI_MISC=y
 CONFIG_IIO=y
 CONFIG_PWM=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index fd3d784..164f1ed 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -380,6 +380,7 @@
 CONFIG_QCOM_DCC_V2=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_QMP_DEBUGFS_CLIENT=y
 CONFIG_QCOM_DEVFREQ_DEVBW=y
 CONFIG_EXTCON_QCOM_SPMI_MISC=y
 CONFIG_IIO=y
@@ -417,10 +418,13 @@
 CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
 CONFIG_IPC_LOGGING=y
 CONFIG_QCOM_RTB=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
 CONFIG_DEBUG_USER=y
 CONFIG_CORESIGHT=y
 CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_SOURCE_ETM3X=y
 CONFIG_CORESIGHT_REMOTE_ETM=y
 CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
 CONFIG_CORESIGHT_QCOM_REPLICATOR=y
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index 65b43ea..1ab1fbb 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -114,6 +114,30 @@
 	select HAVE_CLK_PREPARE
 	select COMMON_CLK_MSM
 
+config ARCH_SDM439
+	bool "Enable support for SDM439"
+	select CPU_V7
+	select HAVE_ARM_ARCH_TIMER
+	select PINCTRL
+	select QCOM_SCM if SMP
+	select PM_DEVFREQ
+	select CLKDEV_LOOKUP
+	select HAVE_CLK
+	select HAVE_CLK_PREPARE
+	select COMMON_CLK_MSM
+
+config ARCH_SDM429
+	bool "Enable support for SDM429"
+	select CPU_V7
+	select HAVE_ARM_ARCH_TIMER
+	select PINCTRL
+	select QCOM_SCM if SMP
+	select PM_DEVFREQ
+	select CLKDEV_LOOKUP
+	select HAVE_CLK
+	select HAVE_CLK_PREPARE
+	select COMMON_CLK_MSM
+
 config ARCH_SDM450
 	bool "Enable support for SDM450"
 	select CPU_V7
@@ -126,6 +150,22 @@
 	select HAVE_CLK_PREPARE
 	select COMMON_CLK_MSM
 
+config ARCH_SDM632
+	bool "Enable Support for Qualcomm Technologies Inc. SDM632"
+	select CPU_V7
+	select PINCTRL
+	select QCOM_SCM if SMP
+	select CLKDEV_LOOKUP
+	select HAVE_CLK
+	select HAVE_CLK_PREPARE
+	select SOC_BUS
+	select PM_OPP
+	select MFD_CORE
+	select SND_SOC_COMPRESS
+	select SND_HWDEP
+	select CPU_FREQ_QCOM
+	select COMMON_CLK_MSM
+
 config ARCH_MDM9650
 	bool "MDM9650"
 	select ARM_GIC
diff --git a/arch/arm/mach-qcom/Makefile b/arch/arm/mach-qcom/Makefile
index c167075..5b93fa3 100644
--- a/arch/arm/mach-qcom/Makefile
+++ b/arch/arm/mach-qcom/Makefile
@@ -5,6 +5,9 @@
 obj-$(CONFIG_ARCH_MSM8937) += board-msm8937.o
 obj-$(CONFIG_ARCH_MSM8909) += board-msm8909.o
 obj-$(CONFIG_ARCH_MSM8917) += board-msm8917.o
+obj-$(CONFIG_ARCH_SDM429) += board-sdm429.o
+obj-$(CONFIG_ARCH_SDM439) += board-sdm439.o
 obj-$(CONFIG_ARCH_SDM450) += board-sdm450.o
 obj-$(CONFIG_ARCH_MDM9650) += board-9650.o
 obj-$(CONFIG_ARCH_MDM9607) += board-9607.o
+obj-$(CONFIG_ARCH_SDM632) += board-sdm632.o
diff --git a/arch/arm/mach-qcom/board-sdm429.c b/arch/arm/mach-qcom/board-sdm429.c
new file mode 100644
index 0000000..c648eaf
--- /dev/null
+++ b/arch/arm/mach-qcom/board-sdm429.c
@@ -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.
+ */
+
+#include <linux/kernel.h>
+#include "board-dt.h"
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+static const char *sdm429_dt_match[] __initconst = {
+	"qcom,sdm429",
+	NULL
+};
+
+static void __init sdm429_init(void)
+{
+	board_dt_populate(NULL);
+}
+
+DT_MACHINE_START(SDM429_DT,
+	"Qualcomm Technologies, Inc. SDM429 (Flattened Device Tree)")
+	.init_machine		= sdm429_init,
+	.dt_compat		= sdm429_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-qcom/board-sdm439.c b/arch/arm/mach-qcom/board-sdm439.c
new file mode 100644
index 0000000..312f3a5
--- /dev/null
+++ b/arch/arm/mach-qcom/board-sdm439.c
@@ -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.
+ */
+
+#include <linux/kernel.h>
+#include "board-dt.h"
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+static const char *sdm439_dt_match[] __initconst = {
+	"qcom,sdm439",
+	NULL
+};
+
+static void __init sdm439_init(void)
+{
+	board_dt_populate(NULL);
+}
+
+DT_MACHINE_START(SDM439_DT,
+	"Qualcomm Technologies, Inc. SDM439 (Flattened Device Tree)")
+	.init_machine		= sdm439_init,
+	.dt_compat		= sdm439_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-qcom/board-sdm632.c b/arch/arm/mach-qcom/board-sdm632.c
new file mode 100644
index 0000000..c6a55f2
--- /dev/null
+++ b/arch/arm/mach-qcom/board-sdm632.c
@@ -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.
+ */
+
+#include <linux/kernel.h>
+#include "board-dt.h"
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+
+static const char *sdm632_dt_match[] __initconst = {
+	"qcom,sdm632",
+	NULL
+};
+
+static void __init sdm632_init(void)
+{
+	board_dt_populate(NULL);
+}
+
+DT_MACHINE_START(SDM632_DT,
+	"Qualcomm Technologies, Inc. SDM632 (Flattened Device Tree)")
+	.init_machine		= sdm632_init,
+	.dt_compat		= sdm632_dt_match,
+MACHINE_END
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 8df9953..1b135e5 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -85,6 +85,7 @@
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_GCC_PLUGINS
 	select HAVE_GENERIC_DMA_COHERENT
+	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_IRQ_TIME_ACCOUNTING
 	select HAVE_MEMBLOCK
 	select HAVE_MEMBLOCK_NODE_MAP if NUMA
@@ -1150,6 +1151,29 @@
 	  Space separated list of names of dtbs to append when
 	  building a concatenated Image.gz-dtb.
 
+choice
+	prompt "Kernel compression method"
+	default BUILD_ARM64_KERNEL_COMPRESSION_GZIP
+	help
+	  Allows choice between gzip compressed or uncompressed
+	  kernel image
+
+config BUILD_ARM64_KERNEL_COMPRESSION_GZIP
+	bool "Build compressed kernel image"
+	help
+	  Build a kernel image using gzip
+	  compression with concatenated dtb.
+	  gzip is based on the DEFLATE
+	  algorithm.
+
+config BUILD_ARM64_UNCOMPRESSED_KERNEL
+	bool "Build uncompressed kernel image"
+	help
+	  Build a kernel image without
+	  compression and with
+	  concatenated dtb.
+endchoice
+
 config BUILD_ARM64_DT_OVERLAY
 	bool "enable DT overlay compilation support"
 	depends on OF
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 35a89dd2b..2b265a7 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -122,11 +122,15 @@
 libs-y		:= arch/arm64/lib/ $(libs-y)
 core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
 
+ifeq ($(CONFIG_BUILD_ARM64_KERNEL_COMPRESSION_GZIP),y)
+KBUILD_IMAGE   := Image.gz
+else
+KBUILD_IMAGE   := Image
+endif
+
 # Default target when executing plain make
 ifeq ($(CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE),y)
-KBUILD_IMAGE	:= $(subst $\",,$(CONFIG_BUILD_ARM64_APPENDED_KERNEL_IMAGE_NAME))
-else
-KBUILD_IMAGE	:= Image.gz
+KBUILD_IMAGE	:=  $(addsuffix -dtb,$(KBUILD_IMAGE))
 endif
 
 KBUILD_DTBS	:= dtbs
diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile
index b97f1de..ccdfa1f 100644
--- a/arch/arm64/boot/Makefile
+++ b/arch/arm64/boot/Makefile
@@ -45,7 +45,11 @@
 $(obj)/Image.bz2: $(obj)/Image FORCE
 	$(call if_changed,bzip2)
 
-$(obj)/Image-dtb: $(obj)/Image $(DTB_OBJS) FORCE
+$(obj)/Image-dtb-hdr: $(obj)/Image FORCE
+	echo -n 'UNCOMPRESSED_IMG' > $@ && \
+	$(call size_append, $(filter-out FORCE,$^)) >> $@
+
+$(obj)/Image-dtb: $(obj)/Image-dtb-hdr $(obj)/Image $(DTB_OBJS) FORCE
 	$(call if_changed,cat)
 
 $(obj)/Image.gz: $(obj)/Image FORCE
diff --git a/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi b/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
index c9996f8..3947406 100644
--- a/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
@@ -450,7 +450,7 @@
 			pins = "gpio12";
 			function = "normal";
 			output-enable;
-			qcom,drive-strength = "medium";
+			qcom,drive-strength = <2>;
 		};
 	};
 
@@ -459,7 +459,7 @@
 			pins = "gpio5";
 			function = "func1";
 			output-enable;
-			qcom,drive-strength = "medium";
+			qcom,drive-strength = <2>;
 			bias-disable;
 		};
 	};
@@ -469,6 +469,15 @@
 	qcom,support-twm-config;
 };
 
+&pm660_pbs {
+	status = "okay";
+};
+
+&pm660_pon {
+	qcom,support-twm-config;
+	qcom,pbs-client = <&pm660_pbs>;
+};
+
 / {
 	/delete-node/ qcom,battery-data;
 	mtp_batterydata: qcom,battery-data {
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 315b3fd..31d4b0d 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -139,6 +139,8 @@
 		sda670-pm660a-mtp-overlay.dtbo \
 		sdm670-tasha-codec-cdp-overlay.dtbo \
 		sdm670-pm660a-tasha-codec-cdp-overlay.dtbo \
+		sdm670-aqt1000-cdp-overlay.dtbo \
+		sdm670-pm660a-aqt1000-cdp-overlay.dtbo \
 		qcs605-cdp-overlay.dtbo \
 		qcs605-mtp-overlay.dtbo \
 		qcs605-360camera-overlay.dtbo \
@@ -163,7 +165,9 @@
 		sdm710-usbc-external-codec-pm660a-cdp-overlay.dtbo \
 		sdm710-usbc-external-codec-pm660a-mtp-overlay.dtbo \
 		sdm710-tasha-codec-cdp-overlay.dtbo \
-		sdm710-pm660a-tasha-codec-cdp-overlay.dtbo
+		sdm710-pm660a-tasha-codec-cdp-overlay.dtbo \
+		sdm710-aqt1000-cdp-overlay.dtbo \
+		sdm710-pm660a-aqt1000-cdp-overlay.dtbo
 
 sdm670-cdp-overlay.dtbo-base := sdm670.dtb
 sdm670-mtp-overlay.dtbo-base := sdm670.dtb
@@ -186,6 +190,8 @@
 sdm670-usbc-external-codec-pm660a-mtp-overlay.dtbo-base := sdm670.dtb
 sdm670-tasha-codec-cdp-overlay.dtbo-base := sdm670.dtb
 sdm670-pm660a-tasha-codec-cdp-overlay.dtbo-base := sdm670.dtb
+sdm670-aqt1000-cdp-overlay.dtbo-base := sdm670.dtb
+sdm670-pm660a-aqt1000-cdp-overlay.dtbo-base := sdm670.dtb
 sda670-cdp-overlay.dtbo-base := sda670.dtb
 sda670-mtp-overlay.dtbo-base := sda670.dtb
 sda670-pm660a-cdp-overlay.dtbo-base := sda670.dtb
@@ -215,6 +221,8 @@
 sdm710-usbc-external-codec-pm660a-mtp-overlay.dtbo-base := sdm710.dtb
 sdm710-tasha-codec-cdp-overlay.dtbo-base := sdm710.dtb
 sdm710-pm660a-tasha-codec-cdp-overlay.dtbo-base := sdm710.dtb
+sdm710-aqt1000-cdp-overlay.dtbo-base := sdm710.dtb
+sdm710-pm660a-aqt1000-cdp-overlay.dtbo-base := sdm710.dtb
 
 else
 dtb-$(CONFIG_ARCH_SDM670) += sdm670-rumi.dtb \
@@ -292,11 +300,24 @@
 dtbo-$(CONFIG_ARCH_SDM632) += sdm632-rumi-overlay.dtbo \
 	sdm450-cdp-s2-overlay.dtbo \
 	sdm450-mtp-s3-overlay.dtbo \
-	sdm450-qrd-sku4-overlay.dtbo
+	sdm632-ext-codec-cdp-s3-overlay.dtbo \
+	sdm632-ext-codec-mtp-s4-overlay.dtbo \
+	sdm632-rcm-overlay.dtbo \
+	sdm450-qrd-sku4-overlay.dtbo \
+	sdm632-qrd-overlay.dtbo
+
+dtbo-$(CONFIG_ARCH_SDM439) += sdm439-mtp-overlay.dtbo \
+	sdm439-cdp-overlay.dtbo \
+	sdm439-qrd-overlay.dtbo
+
+dtbo-$(CONFIG_ARCH_SDM429) += sdm429-mtp-overlay.dtbo \
+	sdm429-cdp-overlay.dtbo \
+	sdm429-qrd-overlay.dtbo
 
 msm8953-mtp-overlay.dtbo-base := sdm450.dtb \
 	msm8953.dtb \
 	apq8053.dtb \
+	sda450.dtb \
 	msm8953-pmi8940.dtb \
 	msm8953-pmi8937.dtb \
 	sdm450-pmi8940.dtb \
@@ -304,6 +325,7 @@
 msm8953-cdp-overlay.dtbo-base := sdm450.dtb \
 	msm8953.dtb \
 	apq8053.dtb \
+	sda450.dtb \
 	msm8953-pmi8940.dtb \
 	msm8953-pmi8937.dtb
 msm8953-rcm-overlay.dtbo-base := sdm450.dtb \
@@ -325,13 +347,38 @@
 msm8953-cdp-1200p-overlay.dtbo-base := msm8953.dtb
 sdm450-cdp-s2-overlay.dtbo-base := sdm450-pmi632.dtb \
 	sdm632.dtb \
-	msm8953-pmi632.dtb
+	sdm632-pm8004.dtb \
+	msm8953-pmi632.dtb \
+	sda450-pmi632.dtb
 sdm450-mtp-s3-overlay.dtbo-base := sdm450-pmi632.dtb \
-	sdm632.dtb
+	sdm632.dtb \
+	sdm632-pm8004.dtb \
+	sda450-pmi632.dtb
 sdm450-qrd-sku4-overlay.dtbo-base := sdm450-pmi632.dtb \
-	sdm632.dtb
+	sdm632.dtb \
+	sdm632-pm8004.dtb
 sdm632-rumi-overlay.dtbo-base := sdm632.dtb
+sdm632-ext-codec-cdp-s3-overlay.dtbo-base := sdm632.dtb \
+	sdm632-pm8004.dtb
+sdm632-ext-codec-mtp-s4-overlay.dtbo-base := sdm632.dtb \
+	sdm632-pm8004.dtb
+sdm632-rcm-overlay.dtbo-base := sdm632.dtb \
+	sdm632-pm8004.dtb
+sdm632-qrd-overlay.dtbo-base := sdm632.dtb \
+	sdm632-pm8004.dtb
 
+sdm439-mtp-overlay.dtbo-base := sdm439.dtb \
+	msm8937-interposer-sdm439.dtb
+sdm439-cdp-overlay.dtbo-base := sdm439.dtb \
+	msm8937-interposer-sdm439.dtb
+sdm439-qrd-overlay.dtbo-base := sdm439.dtb \
+	msm8937-interposer-sdm439.dtb
+sdm429-mtp-overlay.dtbo-base := sdm429.dtb \
+	msm8937-interposer-sdm429.dtb
+sdm429-cdp-overlay.dtbo-base := sdm429.dtb \
+	msm8937-interposer-sdm429.dtb
+sdm429-qrd-overlay.dtbo-base := sdm429.dtb \
+	msm8937-interposer-sdm429.dtb
 else
 dtb-$(CONFIG_ARCH_MSM8953) += msm8953-cdp.dtb \
 	msm8953-mtp.dtb \
@@ -362,38 +409,63 @@
 dtb-$(CONFIG_ARCH_MSM8937) += msm8937-pmi8950-mtp.dtb \
 	msm8937-interposer-sdm439-cdp.dtb \
 	msm8937-interposer-sdm439-mtp.dtb \
-	msm8937-interposer-sdm439-qrd.dtb
+	msm8937-interposer-sdm439-qrd.dtb \
+	msm8937-interposer-sdm429-cdp.dtb \
+	msm8937-interposer-sdm429-mtp.dtb
 
-dtb-$(CONFIG_ARCH_MSM8917) += msm8917-pmi8950-mtp.dtb
+dtb-$(CONFIG_ARCH_MSM8917) += msm8917-pmi8950-mtp.dtb \
+	msm8917-pmi8937-qrd-sku5.dtb \
+	msm8917-pmi8940-mtp.dtb \
+	msm8917-pmi8937-mtp.dtb
 
 dtb-$(CONFIG_ARCH_MSM8909) += msm8909w-bg-wtp-v2.dtb \
 	apq8009w-bg-wtp-v2.dtb \
 	apq8009w-bg-alpha.dtb \
-	apq8009-mtp-wcd9326-refboard.dtb
+	apq8009-mtp-wcd9326-refboard.dtb \
+	apq8009-dragon.dtb
 
 dtb-$(CONFIG_ARCH_SDM450) += sdm450-rcm.dtb \
 	sdm450-cdp.dtb \
 	sdm450-mtp.dtb \
+	sda450-cdp.dtb \
+	sda450-mtp.dtb \
 	sdm450-qrd.dtb \
 	sdm450-pmi8940-mtp.dtb \
 	sdm450-pmi8937-mtp.dtb \
 	sdm450-iot-mtp.dtb \
 	sdm450-qrd-sku4.dtb \
 	sdm450-pmi632-cdp-s2.dtb \
-	sdm450-pmi632-mtp-s3.dtb
+	sdm450-pmi632-mtp-s3.dtb \
+	sda450-pmi632-cdp-s2.dtb \
+	sda450-pmi632-mtp-s3.dtb
 
 dtb-$(CONFIG_ARCH_SDM632) += sdm632-rumi.dtb \
-	sdm632-cdp-s2.dtb	\
-	sdm632-mtp-s3.dtb	\
-	sdm632-qrd-sku4.dtb
+	sdm632-cdp-s2.dtb \
+	sdm632-ext-codec-cdp-s3.dtb \
+	sdm632-mtp-s3.dtb \
+	sdm632-ext-codec-mtp-s4.dtb \
+	sdm632-rcm.dtb \
+	sdm632-qrd-sku4.dtb \
+	sdm632-qrd.dtb \
+	sdm632-pm8004-cdp-s2.dtb \
+	sdm632-pm8004-ext-codec-cdp-s3.dtb \
+	sdm632-pm8004-mtp-s3.dtb \
+	sdm632-pm8004-ext-codec-mtp-s4.dtb \
+	sdm632-pm8004-rcm.dtb \
+	sdm632-pm8004-qrd-sku4.dtb \
+	sdm632-pm8004-qrd.dtb
 
 dtb-$(CONFIG_ARCH_SDM439) += sdm439-mtp.dtb \
 	sdm439-cdp.dtb \
-	sdm439-qrd.dtb
+	sdm439-qrd.dtb \
+	sda439-mtp.dtb \
+	sda439-cdp.dtb
 
 dtb-$(CONFIG_ARCH_SDM429) += sdm429-mtp.dtb \
 	sdm429-cdp.dtb \
-	sdm429-qrd.dtb
+	sdm429-qrd.dtb \
+	sda429-mtp.dtb \
+	sda429-cdp.dtb
 
 endif
 
diff --git a/arch/arm64/boot/dts/qcom/apq8009-dragon.dts b/arch/arm64/boot/dts/qcom/apq8009-dragon.dts
new file mode 100644
index 0000000..1446c9c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8009-dragon.dts
@@ -0,0 +1,113 @@
+/*
+ * 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 "msm8909-mtp.dtsi"
+#include "8909-pm8916.dtsi"
+#include "msm8909-pm8916-mtp.dtsi"
+#include "apq8009-audio-external_codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8009 Dragon Board";
+	compatible = "qcom,apq8009-mtp", "qcom,apq8009", "qcom,mtp";
+	qcom,msm-id = <265 2>;
+	qcom,board-id = <32 0x0>;
+};
+
+&soc {
+	ext-codec {
+		qcom,msm-mbhc-hphl-swh = <0>;
+		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";
+	};
+
+	sound-9335 {
+		status = "disabled";
+	};
+
+	i2c@78b8000 {
+		wcd9xxx_codec@d {
+		  status = "disabled";
+		};
+	};
+
+	vph_pwr_vreg: vph_pwr_vreg {
+		compatible = "regulator-fixed";
+		status = "ok";
+		regulator-name = "vph_pwr";
+		regulator-always-on;
+	};
+
+	mdss_mdp: qcom,mdss_mdp@1a00000 {
+		status = "disabled";
+	};
+};
+
+&sdhc_2 {
+	status = "disabled";
+};
+
+&usb_otg {
+		interrupts = <0 134 0>,<0 140 0>,<0 136 0>;
+		interrupt-names = "core_irq", "async_irq", "phy_irq";
+	qcom,hsusb-otg-mode = <3>;
+		qcom,switch-vbus-w-id;
+	vbus_otg-supply = <&vph_pwr_vreg>;
+};
+
+&external_image_mem {
+	reg = <0x0 0x87a00000 0x0 0x0600000>;
+};
+
+&modem_adsp_mem {
+	reg = <0x0 0x88000000 0x0 0x01e00000>;
+};
+
+&peripheral_mem {
+	reg = <0x0 0x89e00000 0x0 0x0700000>;
+};
+
+&i2c_4 {
+	smb1360_otg_supply: smb1360-chg-fg@14 {
+		compatible = "qcom,smb1360-chg-fg";
+		reg = <0x14>;
+		interrupt-parent = <&msm_gpio>;
+		interrupts = <58 8>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&smb_int_default>;
+		qcom,charging-disabled;
+		qcom,empty-soc-disabled;
+		qcom,chg-inhibit-disabled;
+		qcom,float-voltage-mv = <4200>;
+		qcom,iterm-ma = <200>;
+		qcom,recharge-thresh-mv = <100>;
+		qcom,thermal-mitigation = <1500 700 600 0>;
+		regulator-name = "smb1360_otg_vreg";
+		status= "disabled";
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8009w-bg-alpha.dts b/arch/arm64/boot/dts/qcom/apq8009w-bg-alpha.dts
index 57a28d0..89e1b76 100644
--- a/arch/arm64/boot/dts/qcom/apq8009w-bg-alpha.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009w-bg-alpha.dts
@@ -296,3 +296,8 @@
 		output-high;
 	};
 };
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_auo_390p_cmd>;
+	qcom,platform-bklight-en-gpio = <&msm_gpio 52 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8009w-bg-memory.dtsi b/arch/arm64/boot/dts/qcom/apq8009w-bg-memory.dtsi
index d41a792..d83ae5c 100644
--- a/arch/arm64/boot/dts/qcom/apq8009w-bg-memory.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8009w-bg-memory.dtsi
@@ -12,7 +12,7 @@
  */
 
 &external_image_mem {
-	reg = <0x0 0x87b00000 0x0 0x0500000>;
+	reg = <0x0 0x87a00000 0x0 0x0600000>;
 };
 
 &modem_adsp_mem {
diff --git a/arch/arm64/boot/dts/qcom/apq8009w-bg-wtp-v2.dts b/arch/arm64/boot/dts/qcom/apq8009w-bg-wtp-v2.dts
index 454ba81..9fb6626 100644
--- a/arch/arm64/boot/dts/qcom/apq8009w-bg-wtp-v2.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009w-bg-wtp-v2.dts
@@ -313,3 +313,8 @@
 		output-high;
 	};
 };
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_auo_390p_cmd>;
+	qcom,platform-bklight-en-gpio = <&msm_gpio 52 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi b/arch/arm64/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi
new file mode 100644
index 0000000..1cecf4a
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-camera-sensor-dragon.dtsi
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&cci {
+	actuator0: qcom,actuator@0 {
+		cell-index = <0>;
+		reg = <0x0>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+		cam_vaf-supply = <&pm8953_l22>;
+		qcom,cam-vreg-name = "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2850000>;
+		qcom,cam-vreg-max-voltage = <2850000>;
+		qcom,cam-vreg-op-mode = <80000>;
+	};
+
+	actuator1: qcom,actuator@1 {
+		cell-index = <1>;
+		reg = <0x1>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+		qcam_vaf-supply = <&eldo_cam1_vcm_vreg>;
+		qcom,cam-vreg-name = "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2850000>;
+		qcom,cam-vreg-max-voltage = <2850000>;
+		qcom,cam-vreg-op-mode = <80000>;
+	};
+
+	eeprom0: qcom,eeprom@0 {
+		cell-index = <0>;
+		compatible = "qcom,eeprom";
+		reg = <0x0>;
+		qcom,cci-master = <0>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vdig-supply = <&pm8953_l2>;
+		cam_vana-supply = <&pm8953_l17>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vdig",
+						"cam_vana";
+		qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>;
+		qcom,cam-vreg-op-mode = <105000 0 100000>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_default
+				&cam_sensor_rear_default
+				&cam_sensor_rear_vana>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
+				&cam_sensor_rear_vana_sleep>;
+		gpios = <&tlmm 26 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_MCLK0",
+			"CAM_RESET0",
+			"CAM_STANDBY0";
+		clocks = <&clock_gcc clk_mclk0_clk_src>,
+				<&clock_gcc clk_gcc_camss_mclk0_clk>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+	eeprom1: qcom,eeprom@1 {
+		cell-index = <1>;
+		compatible = "qcom,eeprom";
+		reg = <0x1>;
+		qcom,cci-master = <0>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vdig-supply = <&pm8953_l2>;
+		cam_vana-supply = <&pm8953_l17>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vdig",
+						"cam_vana";
+		qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>;
+		qcom,cam-vreg-op-mode = <105000 0 100000>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_default
+				&cam_sensor_front1_default>;
+		pinctrl-1 = <&cam_sensor_mclk1_sleep
+				&cam_sensor_front1_sleep>;
+		gpios = <&tlmm 27 0>,
+			<&tlmm 129 0>,
+			<&tlmm 130 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_MCLK1",
+			"CAM_RESET1",
+			"CAM_STANDBY1";
+		clocks = <&clock_gcc clk_mclk1_clk_src>,
+				<&clock_gcc clk_gcc_camss_mclk1_clk>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+	eeprom2: qcom,eeprom@2 {
+		cell-index = <2>;
+		compatible = "qcom,eeprom";
+		reg = <0x2>;
+		qcom,cci-master = <0>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vdig-supply = <&pm8953_l2>;
+		cam_vana-supply = <&pm8953_l17>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vdig",
+						"cam_vana";
+		qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>;
+		qcom,cam-vreg-op-mode = <105000 0 100000>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk2_default
+				&cam_sensor_front_default>;
+		pinctrl-1 = <&cam_sensor_mclk2_sleep
+				&cam_sensor_front_sleep>;
+		gpios = <&tlmm 28 0>,
+			<&tlmm 131 0>,
+			<&tlmm 132 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";
+		clocks = <&clock_gcc clk_mclk2_clk_src>,
+				<&clock_gcc clk_gcc_camss_mclk2_clk>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+	camera0: qcom,camera@0 {
+		cell-index = <0>;
+		compatible = "qcom,camera";
+		reg = <0x0>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,mount-angle = <0>;
+		/*qcom,led-flash-src = <&led_flash0>;*/
+		qcom,actuator-src = <&actuator0>;
+		qcom,eeprom-src = <&eeprom0>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vdig-supply = <&pm8953_l2>;
+		cam_vana-supply = <&pm8953_l17>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vdig",
+						"cam_vana";
+		qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>;
+		qcom,cam-vreg-op-mode = <105000 0 100000>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_default
+				&cam_sensor_rear_default
+				&cam_sensor_rear_vana>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
+				&cam_sensor_rear_vana_sleep>;
+		gpios = <&tlmm 26 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_MCLK0",
+			"CAM_RESET0",
+			"CAM_STANDBY0";
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <0>;
+		status = "ok";
+		clocks = <&clock_gcc clk_mclk0_clk_src>,
+				<&clock_gcc clk_gcc_camss_mclk0_clk>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+	camera1: qcom,camera@1 {
+		cell-index = <1>;
+		compatible = "qcom,camera";
+		reg = <0x1>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <0>;
+		qcom,actuator-src = <&actuator0>;
+		qcom,eeprom-src = <&eeprom1>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vdig-supply = <&pm8953_l2>;
+		cam_vana-supply = <&pm8953_l17>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vdig",
+						"cam_vana";
+		qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>;
+		qcom,cam-vreg-op-mode = <105000 0 100000>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_default
+				&cam_sensor_front1_default>;
+		pinctrl-1 = <&cam_sensor_mclk1_sleep
+				&cam_sensor_front1_sleep>;
+		gpios = <&tlmm 27 0>,
+			<&tlmm 129 0>,
+			<&tlmm 130 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_MCLK1",
+			"CAM_RESET1",
+			"CAM_STANDBY1";
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <0>;
+		status = "ok";
+		clocks = <&clock_gcc clk_mclk1_clk_src>,
+				<&clock_gcc clk_gcc_camss_mclk1_clk>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+	camera2: qcom,camera@2 {
+		cell-index = <2>;
+		compatible = "qcom,camera";
+		reg = <0x02>;
+		qcom,csiphy-sd-index = <2>;
+		qcom,csid-sd-index = <2>;
+		qcom,mount-angle = <0>;
+		qcom,actuator-src = <&actuator0>;
+		qcom,eeprom-src = <&eeprom2>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vdig-supply = <&pm8953_l2>;
+		cam_vana-supply = <&pm8953_l17>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vdig",
+						"cam_vana";
+		qcom,cam-vreg-min-voltage = <1800000 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <1800000 1200000 2850000>;
+		qcom,cam-vreg-op-mode = <105000 0 100000>;
+		/*qcom,gpio-no-mux = <0>;*/
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk2_default
+				&cam_sensor_front_default>;
+		pinctrl-1 = <&cam_sensor_mclk2_sleep
+				&cam_sensor_front_sleep>;
+		gpios = <&tlmm 28 0>,
+			<&tlmm 131 0>,
+			<&tlmm 132 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";
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <0>;
+		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 = <24000000 0>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.0.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.0.dtsi
index 0c70cf1..947af4d 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.0.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.0.dtsi
@@ -12,6 +12,7 @@
  */
 
 #include "apq8053-lite-dragon.dtsi"
+#include "msm8953-mdss-panels.dtsi"
 
 &i2c_3 {
 	status = "okay";
@@ -34,6 +35,34 @@
 	};
 };
 
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+	hw-config = "single_dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_boyi_hx83100a_800p_video>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_dsi_active &mdss_te_active &mdss_dsi_gpio>;
+	pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend &mdss_dsi_gpio>;
+
+	vdd-supply = <&pm8953_l10>;
+	vddio-supply = <&pm8953_l6>;
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+
+	qcom,platform-te-gpio = <&tlmm 24 0>;
+	qcom,platform-reset-gpio = <&tlmm 61 0>;
+	qcom,platform-bklight-en-gpio = <&tlmm 100 0>;
+};
+
+&mdss_dsi1 {
+	status = "disabled";
+};
+
 &labibb {
 	status = "okay";
 	qpnp,qpnp-labibb-mode = "lcd";
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
index f2d4ef3..5e3ddce 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
@@ -12,6 +12,7 @@
  */
 
 #include "msm8953-pinctrl.dtsi"
+#include "apq8053-camera-sensor-dragon.dtsi"
 #include "pmi8950.dtsi"
 #include "msm8953-pmi8950.dtsi"
 
@@ -86,6 +87,36 @@
 		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>;
+		pinctrl-1 = <&sec_tlmm_lines_sus>;
+	};
+
+};
+
+&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 {
@@ -109,10 +140,45 @@
 	};
 };
 
+&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;
+};
 &spi_3 {
 	status = "disabled";
 };
 
+&i2c_1 {
+	status = "okay";
+};
+
 &i2c_2 {
 	status = "okay";
 };
@@ -222,34 +288,18 @@
 };
 
 &sdhc_2 {
-	/* device core power supply */
-	vdd-supply = <&pm8953_l11>;
-	qcom,vdd-voltage-level = <2950000 2950000>;
-	qcom,vdd-current-level = <15000 800000>;
-
 	/* 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_cd_on
-			&sdc2_wlan_gpio_on>;
+	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>;
-
-	#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 133 0>;
-	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+		 &sdc2_wlan_gpio_off>;
 
 	qcom,clk-rates = <400000 20000000 25000000 50000000>;
 	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
diff --git a/arch/arm64/boot/dts/qcom/batterydata-qrd-sku2-4v35-2590mah.dtsi b/arch/arm64/boot/dts/qcom/batterydata-qrd-sku2-4v35-2590mah.dtsi
new file mode 100644
index 0000000..1bde941
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/batterydata-qrd-sku2-4v35-2590mah.dtsi
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+qcom,qrd_msm8937_sku2_2590mah {
+	/* #QRD8937_SKU2_2590mAh_averaged_MasterSlave_Nov25th2015*/
+	qcom,max-voltage-uv = <4350000>;
+	qcom,nom-batt-capacity-mah = <2590>;
+	qcom,batt-id-kohm = <10>;
+	qcom,battery-beta = <3380>;
+	qcom,battery-type = "qrd_msm8937_sku2_2590mah";
+	qcom,fastchg-current-ma = <3000>;
+	qcom,fg-cc-cv-threshold-mv = <4340>;
+	qcom,chg-rslow-comp-c1 = <3504694>;
+	qcom,chg-rslow-comp-c2 = <7724034>;
+	qcom,chg-rs-to-rslow = <967819>;
+	qcom,chg-rslow-comp-thr = <0xC6>;
+	qcom,checksum = <0x606D>;
+	qcom,gui-version = "PMI8937GUI - 2.0.0.15";
+	qcom,fg-profile-data = [
+		E3 83 D6 7C
+		DC 80 C6 76
+		47 83 C1 62
+		DF 7A 98 86
+		18 82 20 99
+		16 B7 A5 C2
+		5D 0F E6 83
+		4C 7C 46 80
+		6E 75 54 83
+		7B 59 91 82
+		E8 8E 6C 82
+		E8 93 80 B5
+		2E C1 52 13
+		45 0A F2 5B
+		CE 6E 71 FD
+		E6 3C 4C 3F
+		C6 3A 00 00
+		A1 4C 45 3C
+		36 43 00 00
+		00 00 00 00
+		00 00 00 00
+		96 70 30 70
+		29 50 A4 83
+		97 75 55 69
+		BC 68 49 82
+		D2 74 C4 63
+		D7 68 E4 B0
+		1E E4 63 F8
+		64 A0 71 0C
+		28 00 FF 36
+		F0 11 30 03
+		00 00 00 0C
+	];
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-390p-auo-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-390p-auo-cmd.dtsi
new file mode 100644
index 0000000..b4ac287
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-390p-auo-cmd.dtsi
@@ -0,0 +1,98 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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.
+ */
+
+&mdss_mdp {
+	dsi_auo_390p_cmd: qcom,mdss_dsi_auo_390p_cmd {
+		qcom,mdss-dsi-panel-name = "AUO 390p command mode dsi panel";
+		qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
+		qcom,mdss-dsi-panel-framerate = <45>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <390>;
+		qcom,mdss-dsi-panel-height = <390>;
+		qcom,mdss-pan-physical-height-dimension = <29>;
+		qcom,mdss-pan-physical-width-dimension = <29>;
+		qcom,mdss-dsi-h-front-porch = <4>;
+		qcom,mdss-dsi-h-back-porch = <4>;
+		qcom,mdss-dsi-h-pulse-width = <4>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <8>;
+		qcom,mdss-dsi-v-front-porch = <8>;
+		qcom,mdss-dsi-v-pulse-width = <8>;
+		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-color-order = "rgb_swap_rgb";
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-tear-check-frame-rate = <4500>;
+		qcom,mdss-dsi-on-command = [
+			15 01 00 00 00 00 02 fe 01
+			15 01 00 00 00 00 02 0a f0
+			15 01 00 00 00 00 02 fe 00
+			15 01 00 00 00 00 02 35 00
+			29 01 00 00 00 00 05 2a 00 04 01 89
+			29 01 00 00 00 00 05 2b 00 00 01 85
+			29 01 00 00 00 00 05 30 00 00 01 85
+			29 01 00 00 00 00 05 31 00 04 01 89
+			05 01 00 00 00 00 02 12 00
+			15 01 00 00 00 00 02 53 20
+			05 01 00 00 96 00 02 11 00
+			05 01 00 00 00 00 02 29 00
+			39 01 00 00 00 00 06 f0 55 aa 52 08 01
+			39 01 00 00 00 00 07 ff 00 55 aa 52 08 01
+			];
+		qcom,mdss-dsi-off-command = [
+			05 01 00 00 00 00 02 28 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_hs_mode";
+
+		qcom,mdss-dsi-idle-on-command = [
+			05 01 00 00 00 00 01 39 /* Idle-Mode On */
+			];
+		qcom,mdss-dsi-idle-on-command-state = "dsi_hs_mode";
+		qcom,mdss-dsi-idle-off-command = [
+			05 01 00 00 00 00 01 38 /* Idle-Mode Off  */
+			/* Reset column start address*/
+			29 01 00 00 00 00 05 2a 00 04 01 89
+			/* Reset row start address */
+			29 01 00 00 00 00 05 2b 00 00 01 85
+			];
+		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-te-pin-select = <1>;
+		qcom,mdss-dsi-te-dcs-command = <1>;
+		qcom,mdss-dsi-te-using-te-pin;
+		qcom,mdss-dsi-te-check-enable;
+		qcom,mdss-dsi-panel-timings = [5f 12 0a 00 32 34 10
+			16 0f 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x05>;
+		qcom,mdss-dsi-t-clk-pre = <0x11>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <255>;
+		qcom,mdss-dsi-dma-trigger = "trigger_sw";
+		qcom,mdss-dsi-mdp-trigger = "none";
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
+		qcom,mdss-dsi-reset-sequence = <1 20>, <0 20>, <1 20>;
+		/* clk = totlaH * totalV * bpp* 66fps */
+		qcom,mdss-dsi-panel-clockrate = <276705792>;
+		qcom,esd-check-enabled;
+		qcom,mdss-dsi-panel-status-check-mode = "te_signal_check";
+	};
+};
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
new file mode 100644
index 0000000..03c3659
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi
@@ -0,0 +1,84 @@
+/* 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.
+ */
+
+&mdss_mdp {
+	dsi_boyi_hx83100a_800p_video: qcom,mdss_dsi_boyi_hx83100a_800p_video {
+		qcom,mdss-dsi-panel-name = "hx83100a 800p video mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-destination = "display_2";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <800>;
+		qcom,mdss-dsi-panel-height = <1280>;
+		qcom,mdss-dsi-h-front-porch = <40>;
+		qcom,mdss-dsi-h-back-porch = <40>;
+		qcom,mdss-dsi-h-pulse-width = <40>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <8>;
+		qcom,mdss-dsi-v-front-porch = <412>;
+		qcom,mdss-dsi-v-pulse-width = <4>;
+		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-color-order = "rgb_swap_rgb";
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [
+			/*exit sleep mode and delay 120ms*/
+			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];
+		qcom,mdss-dsi-on-command-state = "dsi_hs_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+		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 = [9b 22 18 00 4a 4e 1c 26
+			1d 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x04>;
+		qcom,mdss-dsi-t-clk-pre = <0x1f>;
+		qcom,mdss-dsi-bl-min-level = <2>;
+		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-bl-pmic-control-type = "bl_ctrl_wled";
+		qcom,mdss-pan-physical-width-dimension = <107>;
+		qcom,mdss-pan-physical-height-dimension = <172>;
+		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/dsi-panel-hx8394f-720p-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-hx8394f-720p-video.dtsi
new file mode 100644
index 0000000..749ffe6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx8394f-720p-video.dtsi
@@ -0,0 +1,134 @@
+/*
+ * 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.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------
+ */
+&mdss_mdp {
+	dsi_hx8394f_720p_video: qcom,mdss_dsi_hx8394f_720p_video {
+		qcom,mdss-dsi-panel-name = "hx8394f 720p video mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-destination = "display_1";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <720>;
+		qcom,mdss-dsi-panel-height = <1280>;
+		qcom,mdss-dsi-h-front-porch = <16>;
+		qcom,mdss-dsi-h-back-porch = <16>;
+		qcom,mdss-dsi-h-pulse-width = <10>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <12>;
+		qcom,mdss-dsi-v-front-porch = <15>;
+		qcom,mdss-dsi-v-pulse-width = <4>;
+		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 = [39 01 00 00 00 00 04 B9 FF 83 94
+				39 01 00 00 00 00 07
+					BA 63 03 68 6B B2 C0
+				39 01 00 00 00 00 0B
+					B1 50 12 72 09 33 54 B1 31 6B 2F
+				39 01 00 00 00 00 07
+					B2 00 80 64 0E 0D 2F
+				39 01 00 00 00 00 16
+					B4 73 74 73 74 73 74 01 0C 86 75
+					00 3F 73 74 73 74 73 74 01 0C 86
+				39 01 00 00 00 00 22
+					D3 00 00 07 07 40 07 10 00 08 10
+					08 00 08 54 15 0E 05 0E 02 15 06
+					05 06 47 44 0A 0A 4B 10 07 07 0E
+					40
+				39 01 00 00 00 00 2D
+					D5 1A 1A 1B 1B 00 01 02 03 04 05
+					06 07 08 09 0A 0B 24 25 18 18 26
+					27 18 18 18 18 18 18 18 18 18 18
+					18 18 18 18 18 18 20 21 18 18 18
+					18
+				39 01 00 00 00 00 2D
+					D6 1A 1A 1B 1B 0B 0A 09 08 07 06
+					05 04 03 02 01 00 21 20 18 18 27
+					26 18 18 18 18 18 18 18 18 18 18
+					18 18 18 18 18 18 25 24 18 18 18
+					18
+				39 01 00 00 00 00 3B
+					E0 00 0C 19 20 23 26 29 28 51 61
+					70 6F 76 86 89 8D 99 9A 95 A1 B0
+					57 55 58 5C 5e 64 6B 7F 00 0C 19
+					20 23 26 29 28 51 61 70 6F 76 86
+					89 8D 99 9A 95 A1 B0 57 55 58 5C
+					5E 64 6B 7F
+				39 01 00 00 00 00 03 C0 1F 31
+				15 01 00 00 00 00 02 CC 0B
+				15 01 00 00 00 00 02 D4 02
+				15 01 00 00 00 00 02 BD 02
+				39 01 00 00 00 00 0D
+					D8 FF FF FF FF FF FF FF FF FF FF
+					FF FF
+				15 01 00 00 00 00 02 BD 00
+				15 01 00 00 00 00 02 BD 01
+				15 01 00 00 00 00 02 B1 00
+				15 01 00 00 00 00 02 BD 00
+				39 01 00 00 00 00 08
+					BF 40 81 50 00 1A FC 01
+				39 01 00 00 00 00 03 B6 7D 7D
+				05 01 00 00 78 00 02 11 00
+				39 01 00 00 00 00 0D
+					B2 00 80 64 0E 0D 2F 00 00 00 00
+					C0 18
+				05 01 00 00 14 00 02 29 00];
+
+		qcom,mdss-dsi-off-command = [05 01 00 00 78 00 02 28 00
+				05 01 00 00 96 00 02 10 00];
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+		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
+			= [72 16 0e 00 38 3c 12 1a 10 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x04>;
+		qcom,mdss-dsi-t-clk-pre = <0x18>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,mdss-dsi-dma-trigger = "trigger_sw";
+		qcom,mdss-dsi-mdp-trigger = "none";
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+		qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
+		qcom,mdss-dsi-panel-status-command = [06 01 00 01 05 00 01 D9
+			06 01 00 01 05 00 01 09
+			06 01 00 01 05 00 01 45];
+		qcom,mdss-dsi-panel-status-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+		qcom,mdss-dsi-panel-status-read-length = <4 4 3>;
+		qcom,mdss-dsi-panel-status-valid-params = <1 3 2>;
+		qcom,mdss-dsi-panel-status-value =
+			<0x80 0x80 0x73 0x04 0x05 0x0f>,
+			<0x80 0x80 0x73 0x04 0x05 0x1e>;
+		qcom,mdss-dsi-panel-max-error-count = <3>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-fhd-plus-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-fhd-plus-video.dtsi
index 9b703fe..1ccde7b 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-fhd-plus-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-fhd-plus-video.dtsi
@@ -31,6 +31,8 @@
 		qcom,mdss-dsi-h-right-border = <0>;
 		qcom,mdss-dsi-v-top-border = <0>;
 		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-pan-physical-width-dimension = <65>;
+		qcom,mdss-pan-physical-height-dimension = <129>;
 		qcom,mdss-dsi-bpp = <24>;
 		qcom,mdss-dsi-color-order = "rgb_swap_rgb";
 		qcom,mdss-dsi-underflow-color = <0xff>;
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-hd-plus-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-hd-plus-video.dtsi
index fc09a65..237684e 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-hd-plus-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-hd-plus-video.dtsi
@@ -126,7 +126,7 @@
 		qcom,mdss-dsi-lane-2-state;
 		qcom,mdss-dsi-lane-3-state;
 		qcom,mdss-dsi-panel-timings =
-			[7a 1a 12 00 3e 42 16 1e 03 04 00];
+			[7a 1a 12 00 3e 42 16 1e 14 03 04 00];
 		qcom,mdss-dsi-t-clk-post = <0x0a>;
 		qcom,mdss-dsi-t-clk-pre = <0x1d>;
 		qcom,mdss-dsi-dma-trigger = "trigger_sw";
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-8909.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-8909.dtsi
index a601b5f..b506fb4 100644
--- a/arch/arm64/boot/dts/qcom/msm-arm-smmu-8909.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-8909.dtsi
@@ -16,6 +16,46 @@
 
 &soc {
 
+	kgsl_smmu: arm,smmu-kgsl@1f00000 {
+		status = "ok";
+		compatible = "qcom,qsmmu-v500";
+		reg = <0x1f00000 0x10000>,
+			<0x1ef2000 0x20>;
+		reg-names = "base", "tcu-base";
+		#iommu-cells = <1>;
+		qcom,tz-device-id = "GPU";
+		qcom,skip-init;
+		qcom,dynamic;
+		qcom,use-3-lvl-tables;
+		#global-interrupts = <0>;
+		#size-cells = <1>;
+		#address-cells = <1>;
+		ranges;
+		interrupts =
+			<GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>,
+			<GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>;
+
+		vdd-supply = <&gdsc_oxili_gx>;
+		qcom,regulator-names = "vdd";
+		clocks =
+			<&clock_gcc clk_gcc_oxili_ahb_clk>,
+			<&clock_gcc clk_gcc_bimc_gfx_clk>;
+		clock-names = "gpu_ahb_clk", "gcc_bimc_gfx_clk";
+	};
+
+	/* A test device to test the SMMU operation */
+	kgsl_iommu_test_device0 {
+		status = "disabled";
+		compatible = "iommu-debug-test";
+		/*
+		 * The SID should be valid one to get the proper
+		 * SMR,S2CR indices.
+		 */
+		iommus = <&kgsl_smmu 0x0>;
+	};
+
 	apps_iommu: qcom,iommu@1e00000 {
 		compatible = "qcom,qsmmu-v500";
 		reg = <0x1e00000 0x40000>,
diff --git a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
index b20feef8..9467297 100644
--- a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -262,6 +262,11 @@
 			qcom,msm-dai-q6-dev-id = <240>;
 		};
 
+		afe_loopback_tx: qcom,msm-dai-q6-afe-loopback-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <24577>;
+		};
+
 		incall_record_rx: qcom,msm-dai-q6-incall-record-rx {
 			compatible = "qcom,msm-dai-q6-dev";
 			qcom,msm-dai-q6-dev-id = <32771>;
@@ -297,6 +302,10 @@
 		compatible = "qcom,msm-pcm-hostless";
 	};
 
+	audio_apr: qcom,msm-audio-apr {
+		compatible = "qcom,msm-audio-apr";
+	};
+
 	dai_pri_auxpcm: qcom,msm-pri-auxpcm {
 		compatible = "qcom,msm-auxpcm-dev";
 		qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
diff --git a/arch/arm64/boot/dts/qcom/msm8909-gpu.dtsi b/arch/arm64/boot/dts/qcom/msm8909-gpu.dtsi
new file mode 100644
index 0000000..dc95570
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-gpu.dtsi
@@ -0,0 +1,149 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	msm_bus: qcom,kgsl-busmon {
+		label = "kgsl-busmon";
+		compatible = "qcom,kgsl-busmon";
+	};
+
+	/* To use BIMC based bus governor */
+	gpubw: qcom,gpubw {
+		compatible = "qcom,devbw";
+		governor = "bw_hwmon";
+		qcom,src-dst-ports = <26 512>;
+		qcom,bw-tbl =
+			<    0 >,	/*   9.6 MHz */
+			<  381 >,	/*  50.0 MHz */
+			<  762 >,	/* 100.0 MHz */
+			< 1525 >,	/* 200.0 MHz */
+			< 3051 >,	/* 400.0 MHz */
+			< 4066 >;	/* 533.0 MHz */
+	};
+
+	qcom,gpu-bwmon@410000 {
+		compatible = "qcom,bimc-bwmon2";
+		reg = <0x00410000 0x300>, <0x00401000 0x200>;
+		reg-names = "base", "global_base";
+		interrupts = <0 183 4>;
+		qcom,mport = <2>;
+		qcom,target-dev = <&gpubw>;
+	};
+
+	msm_gpu: qcom,kgsl-3d0@01c00000 {
+		label = "kgsl-3d0";
+		compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
+		status = "ok";
+		reg = <0x01c00000 0x10000
+		       0x01c10000 0x10000
+		       0x0005c000 0x204>;
+		reg-names = "kgsl_3d0_reg_memory" , "kgsl_3d0_shader_memory" ,
+			    "qfprom_memory";
+		interrupts = <0 33 0>;
+		interrupt-names = "kgsl_3d0_irq";
+		qcom,id = <0>;
+
+		qcom,chipid = <0x03000400>;
+
+		qcom,initial-pwrlevel = <1>;
+
+		qcom,idle-timeout = <80>; /* msec */
+		qcom,strtstp-sleepwake;
+		qcom,gpu-disable-fuse = <0x44 0x00000001 27>;
+
+		/*
+		 * Clocks = KGSL_CLK_CORE | KGSL_CLK_IFACE |
+		 * KGSL_CLK_MEM_IFACE | KGSL_CLK_ALT_MEM_IFACE
+		 */
+		qcom,clk-map = <0x00000056>;
+		clocks = <&clock_gcc clk_gcc_oxili_gfx3d_clk>,
+			<&clock_gcc clk_gcc_oxili_ahb_clk>,
+			<&clock_gcc clk_gcc_bimc_gfx_clk>,
+			<&clock_gcc clk_gcc_bimc_gpu_clk>,
+			<&clock_gcc clk_gcc_gtcu_ahb_clk>;
+		clock-names = "core_clk", "iface_clk",
+				"mem_iface_clk", "alt_mem_iface_clk",
+				"gtcu_iface_clk";
+
+		/* Bus Scale Settings */
+		qcom,gpubw-dev = <&gpubw>;
+		qcom,msm-bus,name = "grp3d";
+		qcom,msm-bus,num-cases = <4>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<26 512 0 0>,
+			<26 512 0 1600000>,
+			<26 512 0 3200000>,
+			<26 512 0 4264000>;
+
+		/* GDSC oxili regulators */
+		vdd-supply = <&gdsc_oxili_gx>;
+
+		/* CPU latency parameter */
+		qcom,pm-qos-active-latency = <701>;
+		qcom,pm-qos-wakeup-latency = <701>;
+
+		/* Power levels */
+		qcom,gpu-pwrlevels {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			compatible = "qcom,gpu-pwrlevels";
+
+			qcom,gpu-pwrlevel@0 {
+				reg = <0>;
+				qcom,gpu-freq = <456000000>;
+				qcom,bus-freq = <3>;
+			};
+
+			qcom,gpu-pwrlevel@1 {
+				reg = <1>;
+				qcom,gpu-freq = <307200000>;
+				qcom,bus-freq = <2>;
+			};
+
+			qcom,gpu-pwrlevel@2 {
+				reg = <2>;
+				qcom,gpu-freq = <200000000>;
+				qcom,bus-freq = <1>;
+			};
+
+			qcom,gpu-pwrlevel@3 {
+				reg = <3>;
+				qcom,gpu-freq = <19200000>;
+				qcom,bus-freq = <0>;
+			};
+		};
+
+	};
+	kgsl_msm_iommu: qcom,kgsl-iommu@1f00000 {
+		compatible = "qcom,kgsl-smmu-v2";
+		reg = <0x1f00000 0x10000>;
+		/*
+		 * The gpu can only program a single context bank
+		 * at this fixed offset.
+		 */
+		qcom,protect = <0xa000 0x1000>;
+		clocks = <&clock_gcc clk_gcc_smmu_cfg_clk>,
+				<&clock_gcc clk_gcc_gfx_tcu_clk>,
+				<&clock_gcc clk_gcc_gtcu_ahb_clk>,
+				<&clock_gcc clk_gcc_gfx_tbu_clk>;
+				clock-names = "scfg_clk", "gtcu_clk",
+				"gtcu_iface_clk", "gtbu_clk";
+		qcom,retention;
+		gfx3d_user: gfx3d_user {
+			compatible = "qcom,smmu-kgsl-cb";
+			iommus = <&kgsl_smmu 0>;
+			qcom,gpu-offset = <0xa000>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-ion.dtsi b/arch/arm64/boot/dts/qcom/msm8909-ion.dtsi
index 74f2be0..858429b 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-ion.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-ion.dtsi
@@ -39,6 +39,12 @@
 			qcom,ion-heap-type = "DMA";
 		};
 
+		qcom,ion-heap@19 { /* QSEECOM TA HEAP */
+			reg = <19>;
+			memory-region = <&qseecom_ta_mem>;
+			qcom,ion-heap-type = "DMA";
+		};
+
 		adsp_heap: qcom,ion-heap@22 { /* MODEM HEAP */
 			reg = <22>;
 			memory-region = <&adsp_mem>;
diff --git a/arch/arm64/boot/dts/qcom/msm8909-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8909-mdss-panels.dtsi
new file mode 100644
index 0000000..0a657da
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-mdss-panels.dtsi
@@ -0,0 +1,75 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "dsi-panel-390p-auo-cmd.dtsi"
+
+&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 = "vdd";
+			qcom,supply-min-voltage = <2850000>;
+			qcom,supply-max-voltage = <2850000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+		};
+
+		qcom,panel-supply-entry@1 {
+			reg = <1>;
+			qcom,supply-name = "vddio";
+			qcom,supply-min-voltage = <1800000>;
+			qcom,supply-max-voltage = <1800000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+		};
+	};
+
+	dsi_pm660_panel_pwr_supply: dsi_pm660_panel_pwr_supply {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,panel-supply-entry@0 {
+			reg = <0>;
+			qcom,supply-name = "vdd";
+			qcom,supply-min-voltage = <3000000>;
+			qcom,supply-max-voltage = <3000000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+		};
+
+		qcom,panel-supply-entry@1 {
+			reg = <1>;
+			qcom,supply-name = "vddio";
+			qcom,supply-min-voltage = <1800000>;
+			qcom,supply-max-voltage = <1800000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+		};
+
+		qcom,panel-supply-entry@2 {
+			reg = <2>;
+			qcom,supply-name = "bklt";
+			qcom,supply-min-voltage = <0>;
+			qcom,supply-max-voltage = <0>;
+			qcom,supply-enable-load = <0>;
+			qcom,supply-disable-load = <0>;
+		};
+	};
+};
+
+&dsi_auo_390p_cmd {
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
+	qcom,panel-supply-entries = <&dsi_pm660_panel_pwr_supply>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-mdss.dtsi b/arch/arm64/boot/dts/qcom/msm8909-mdss.dtsi
index 0d824e0..67c6d06 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-mdss.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-mdss.dtsi
@@ -38,9 +38,11 @@
 
 		smmu_mdp_unsec: qcom,smmu_mdp_unsec_cb {
 			compatible = "qcom,smmu_mdp_unsec";
+			iommus = <&apps_iommu 0xC00 0>; /* For NS ctx bank */
 		};
 		smmu_mdp_sec: qcom,smmu_mdp_sec_cb {
 			compatible = "qcom,smmu_mdp_sec";
+			iommus = <&apps_iommu 0xC01 0>; /* For SEC Ctx Bank */
 		};
 	};
 
@@ -51,8 +53,8 @@
 		#size-cells = <1>;
 		qcom,mdss-fb-map-prim = <&mdss_fb0>;
 		gdsc-supply = <&gdsc_mdss>;
-		vdda-supply = <&pm8909_l2>;
-		vddio-supply = <&pm8909_l6>;
+		vdda-supply = <&pm660_l2>;
+		vddio-supply = <&pm660_l6>;
 
 		/* Bus Scale Settings */
 		qcom,msm-bus,name = "mdss_dsi";
@@ -133,8 +135,8 @@
 			interrupts = <0 80 0>;
 
 			qcom,mdss-mdp = <&mdss_mdp>;
-			vdd-supply = <&pm8909_l17>;
-			vddio-supply = <&pm8909_l6>;
+			vdd-supply = <&pm660_l17>;
+			vddio-supply = <&pm660_l6>;
 
 			clocks = <&clock_gcc_mdss clk_gcc_mdss_byte0_clk>,
 				 <&clock_gcc_mdss clk_gcc_mdss_pclk0_clk>,
@@ -157,4 +159,4 @@
 	};
 };
 
-/* #include "msm8909-mdss-panels.dtsi" */
+#include "msm8909-mdss-panels.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
index 25688ff..c86da64 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
@@ -15,9 +15,11 @@
 		compatible = "qcom,msm8909-pinctrl";
 		reg = <0x1000000 0x300000>;
 		interrupts = <0 208 0>;
+		interrupts-extended = <&wakegic GIC_SPI 208 IRQ_TYPE_NONE>;
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
+		interrupt-parent = <&wakegpio>;
 		#interrupt-cells = <2>;
 
 		/* sensors */
diff --git a/arch/arm64/boot/dts/qcom/msm8909.dtsi b/arch/arm64/boot/dts/qcom/msm8909.dtsi
index 5e56c49..a6d42f1 100644
--- a/arch/arm64/boot/dts/qcom/msm8909.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909.dtsi
@@ -21,7 +21,7 @@
 			<258 0>,
 			<265 0>,
 			<275 0>;
-	interrupt-parent = <&intc>;
+	interrupt-parent = <&wakegic>;
 
 	aliases {
 		/* smdtty devices */
@@ -194,6 +194,14 @@
 			size = <0 0x0800000>;
 		};
 
+		qseecom_ta_mem: qseecom_ta_region {
+			compatible = "shared-dma-pool";
+			alloc-ranges = <0 0x00000000 0 0xffffffff>;
+			reusable;
+			alignment = <0 0x400000>;
+			size = <0 0x400000>;
+		};
+
 		audio_mem: audio_region@0 {
 			compatible = "shared-dma-pool";
 			reusable;
@@ -211,6 +219,13 @@
 		cont_splash_mem: splash_region@83000000 {
 			reg = <0x0 0x83000000 0x0 0xc00000>;
 		};
+
+		dump_mem: mem_dump_region {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0 0x100000>;
+		};
+
 	};
 
 	soc: soc { };
@@ -220,6 +235,8 @@
 #include "msm8909-smp2p.dtsi"
 #include "msm8909-ipcrouter.dtsi"
 #include "msm-gdsc-8916.dtsi"
+#include "msm-arm-smmu-8909.dtsi"
+#include "msm8909-gpu.dtsi"
 #include "msm8909-coresight.dtsi"
 #include "msm8909-bus.dtsi"
 #include "msm8909-mdss.dtsi"
@@ -234,11 +251,30 @@
 	intc: interrupt-controller@b000000 {
 		compatible = "qcom,msm-qgic2";
 		interrupt-controller;
+		interrupt-parent = <&intc>;
 		#interrupt-cells = <3>;
 		reg = <0x0b000000 0x1000>,
 		<0x0b002000 0x1000>;
 	};
 
+	wakegic: wake-gic@601d0 {
+		compatible = "qcom,mpm-gic-msm8909", "qcom,mpm-gic";
+		interrupts = <GIC_SPI 171 IRQ_TYPE_EDGE_RISING>;
+		reg = <0x601d0 0x1000>,
+			<0xb011008 0x4>;  /* MSM_APCS_GCC_BASE 4K */
+		reg-names = "vmpm", "ipc";
+		interrupt-controller;
+		interrupt-parent = <&intc>;
+		#interrupt-cells = <3>;
+	};
+
+	wakegpio: wake-gpio {
+		compatible = "qcom,mpm-gpio-msm8909", "qcom,mpm-gpio";
+		interrupt-controller;
+		interrupt-parent = <&intc>;
+		#interrupt-cells = <2>;
+	};
+
 	restart@4ab000 {
 		compatible = "qcom,pshold";
 		reg =	<0x4ab000 0x4>,
@@ -481,6 +517,47 @@
 
 	thermal_zones: thermal-zones {};
 
+	mem_dump {
+		compatible = "qcom,mem-dump";
+		memory-region = <&dump_mem>;
+
+		rpm_sw_dump {
+			qcom,dump-size = <0x28000>;
+			qcom,dump-id = <0xea>;
+		};
+
+		pmic_dump {
+			qcom,dump-size = <0x10000>;
+			qcom,dump-id = <0xe4>;
+		};
+
+		vsense_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0xe9>;
+		};
+
+		tmc_etf_dump {
+			qcom,dump-size = <0x10000>;
+			qcom,dump-id = <0xf0>;
+		};
+
+		tmc_etr_reg_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0x100>;
+		};
+
+		tmc_etf_reg_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0x101>;
+		};
+
+		misc_data_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0xe8>;
+		};
+
+	};
+
 	qcom,sensor-information {
 		compatible = "qcom,sensor-information";
 		sensor_information0: qcom,sensor-information-0 {
@@ -623,6 +700,16 @@
 		rpm-channel-type = <15>; /* SMD_APPS_RPM */
 	};
 
+	qcom,bam_dmux@4044000 {
+		compatible = "qcom,bam_dmux";
+		reg = <0x4044000 0x19000>;
+		interrupts = <0 29 1>;
+		qcom,rx-ring-size = <32>;
+		qcom,max-rx-mtu = <4096>;
+		qcom,fast-shutdown;
+		qcom,no-cpu-affinity;
+	};
+
 	qcom,smdtty {
 		compatible = "qcom,smdtty";
 
@@ -1623,6 +1710,16 @@
 		memory-region = <&adsp_mem>;
 	};
 
+	qcom,msm-adsprpc-mem {
+		compatible = "qcom,msm-adsprpc-mem-region";
+		memory-region = <&adsp_mem>;
+		restrict-access;
+	};
+
+	qcom,msm_fastrpc {
+		compatible = "qcom,msm-fastrpc-legacy-compute";
+	};
+
 	qcom,msm-adsp-loader {
 		compatible = "qcom,adsp-loader";
 		qcom,adsp-state = <0>;
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-bg-memory.dtsi b/arch/arm64/boot/dts/qcom/msm8909w-bg-memory.dtsi
index 945b945..f841097 100644
--- a/arch/arm64/boot/dts/qcom/msm8909w-bg-memory.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909w-bg-memory.dtsi
@@ -12,7 +12,7 @@
  */
 
 &external_image_mem {
-	reg = <0x0 0x87b00000 0x0 0x0500000>;
+	reg = <0x0 0x87a00000 0x0 0x0600000>;
 };
 
 &modem_adsp_mem {
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts b/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
index 24266e8..8149eb2 100644
--- a/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
+++ b/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
@@ -14,11 +14,11 @@
 /dts-v1/;
 
 #include "msm8909-mtp.dtsi"
+#include "msm8909w-gpu.dtsi"
 #include "msm8909w.dtsi"
 #include "msm8909w-bg-memory.dtsi"
 #include "8909w-pm660.dtsi"
 #include "msm8909-audio-bg_codec.dtsi"
-#include "msm-arm-smmu-8909.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. MSM8909W-PM660 BLACKGHOST WTP";
@@ -69,6 +69,17 @@
 		/delete-node/ it7260@46;
 	};
 
+	qcom,blackghost {
+		compatible = "qcom,pil-blackghost";
+		qcom,firmware-name = "bg-wear";
+		/* GPIO inputs from blackghost */
+		qcom,bg2ap-status-gpio = <&msm_gpio 97 0>;
+		qcom,bg2ap-errfatal-gpio = <&msm_gpio 95 0>;
+		/* GPIO output to blackghost */
+		qcom,ap2bg-status-gpio = <&msm_gpio 17 0>;
+		qcom,ap2bg-errfatal-gpio = <&msm_gpio 23 0>;
+	};
+
 	qcom,msm-ssc-sensors {
 		compatible = "qcom,msm-ssc-sensors";
 	};
@@ -155,6 +166,8 @@
 	qcom,bg-daemon {
 		compatible = "qcom,bg-daemon";
 		qcom,bg-reset-gpio = <&pm660_gpios 5 0>;
+		ssr-reg1-supply = <&pm660_l3>;
+		ssr-reg2-supply = <&pm660_l9>;
 	};
 
 	qcom,bcl {
@@ -303,3 +316,8 @@
 		output-high;
 	};
 };
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_auo_390p_cmd>;
+	qcom,platform-bklight-en-gpio = <&msm_gpio 52 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-gpu.dtsi b/arch/arm64/boot/dts/qcom/msm8909w-gpu.dtsi
new file mode 100644
index 0000000..7d42127
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909w-gpu.dtsi
@@ -0,0 +1,62 @@
+/* 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.
+ */
+
+/* To use BIMC based bus governor */
+&gpubw {
+	qcom,bw-tbl =
+		<    0 >,	/*   9.6 MHz */
+		<  366 >,	/*  48.0 MHz */
+		<  732 >,	/*  96.0 MHz */
+		< 1464 >,	/* 192.0 MHz */
+		< 2929 >;	/* 384.0 MHz */
+};
+
+&msm_gpu {
+
+	/* To disable GPU wake up on touch event */
+	qcom,disable-wake-on-touch;
+
+	/* Bus Scale Settings */
+	qcom,msm-bus,num-cases = <3>;
+	qcom,msm-bus,vectors-KBps =
+		<26 512 0 0>,
+		<26 512 0 1536000>,
+		<26 512 0 3070000>;
+
+	/delete-node/qcom,gpu-pwrlevels;
+
+	/* Power levels */
+	qcom,gpu-pwrlevels {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		compatible = "qcom,gpu-pwrlevels";
+
+		qcom,gpu-pwrlevel@0 {
+			reg = <0>;
+			qcom,gpu-freq = <200000000>;
+			qcom,bus-freq = <1>;
+			qcom,bus-min = <1>;
+			qcom,bus-max = <1>;
+		};
+
+		qcom,gpu-pwrlevel@1 {
+			reg = <1>;
+			qcom,gpu-freq = <19200000>;
+			qcom,bus-freq = <0>;
+			qcom,bus-min = <0>;
+			qcom,bus-max = <0>;
+		};
+
+	};
+
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909w.dtsi b/arch/arm64/boot/dts/qcom/msm8909w.dtsi
index 707b56e..c2e28d1 100644
--- a/arch/arm64/boot/dts/qcom/msm8909w.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909w.dtsi
@@ -94,3 +94,14 @@
 		<55 512 196800 196800>,
 		<55 512 393600 393600>;
 };
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_auo_cx_qvga_cmd>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+	pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+
+	qcom,platform-te-gpio = <&msm_gpio 24 0>;
+	qcom,platform-reset-gpio = <&msm_gpio 25 0>;
+	qcom,platform-bklight-en-gpio = <&msm_gpio 37 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-audio.dtsi b/arch/arm64/boot/dts/qcom/msm8917-audio.dtsi
new file mode 100644
index 0000000..a46e4fe
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-audio.dtsi
@@ -0,0 +1,434 @@
+/*
+ * 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 "msm-audio-lpass.dtsi"
+#include "msm8953-wsa881x.dtsi"
+
+&msm_audio_ion {
+	iommus = <&apps_iommu 0x2001 0x0>;
+	qcom,smmu-sid-mask = /bits/ 64 <0xf>;
+};
+
+&soc {
+	qcom,msm-audio-apr {
+		compatible = "qcom,msm-audio-apr";
+		msm_audio_apr_dummy {
+			compatible = "qcom,msm-audio-apr-dummy";
+		};
+	};
+
+	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 = "msm8952-snd-card-mtp";
+		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",
+				"RX_I2S_CLK", "MCLK",
+				"TX_I2S_CLK", "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",
+				"ADC1_IN", "ADC1_OUT",
+				"ADC2_IN", "ADC2_OUT",
+				"ADC3_IN", "ADC3_OUT",
+				"PDM_IN_RX1", "PDM_OUT_RX1",
+				"PDM_IN_RX2", "PDM_OUT_RX2",
+				"PDM_IN_RX3", "PDM_OUT_RX3",
+				"WSA_SPK OUT", "VDD_WSA_SWITCH",
+				"SpkrMono WSA_IN", "WSA_SPK OUT";
+
+		qcom,cdc-us-euro-gpios = <&tlmm 63 0>;
+		qcom,cdc-us-eu-gpios = <&cdc_us_euro_sw>;
+		qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+		qcom,quin-mi2s-gpios = <&cdc_quin_mi2s_gpios>;
+
+		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+				<&loopback>, <&compress>, <&hostless>,
+				<&afe>, <&lsm>, <&routing>, <&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-dsp-noirq";
+		asoc-cpu = <&dai_pri_auxpcm>,
+			<&dai_mi2s0>, <&dai_mi2s1>,
+			<&dai_mi2s2>, <&dai_mi2s3>,
+			<&dai_mi2s4>, <&dai_mi2s5>,
+			<&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.4", "msm-dai-q6-mi2s.6",
+				"msm-dai-q6-dev.16384", "msmdai-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>, <&msm_digital_codec>,
+				<&pmic_analog_codec>;
+		asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+					"analog-codec";
+		asoc-wsa-codec-names = "wsa881x-i2c-codec.2-000f";
+		asoc-wsa-codec-prefixes = "SpkrMono";
+		msm-vdd-wsa-switch-supply = <&pm8937_l5>;
+		qcom,msm-vdd-wsa-switch-voltage = <1800000>;
+		qcom,msm-vdd-wsa-switch-current = <10000>;
+	};
+
+	cdc_us_euro_sw: msm_cdc_pinctrl_us_euro_sw {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cross_conn_det_act>;
+		pinctrl-1 = <&cross_conn_det_sus>;
+	};
+
+	cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_pdm_lines_act &cdc_pdm_lines_2_act>;
+		pinctrl-1 = <&cdc_pdm_lines_sus &cdc_pdm_lines_2_sus>;
+	};
+
+	cdc_quin_mi2s_gpios: msm_cdc_pinctrl_quin {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&pri_tlmm_lines_act &pri_tlmm_ws_act>;
+		pinctrl-1 = <&pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+	};
+
+
+	i2c@78b6000 {
+		status = "okay";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		wsa881x_i2c_f: wsa881x-i2c-codec@f {
+			status = "okay";
+			compatible = "qcom,wsa881x-i2c-codec";
+			reg = <0x0f>;
+			qcom,wsa-analog-vi-gpio = <&wsa881x_analog_vi_gpio>;
+			qcom,wsa-analog-clk-gpio = <&wsa881x_analog_clk_gpio>;
+			qcom,wsa-analog-reset-gpio =
+				<&wsa881x_analog_reset_gpio>;
+		};
+		wsa881x_i2c_45: wsa881x-i2c-codec@45 {
+			status = "okay";
+			compatible = "qcom,wsa881x-i2c-codec";
+			reg = <0x45>;
+		};
+	};
+
+	wsa881x_analog_vi_gpio: wsa881x_analog_vi_pctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&wsa_vi_on>;
+		pinctrl-1 = <&wsa_vi_off>;
+	};
+	wsa881x_analog_clk_gpio: wsa881x_analog_clk_pctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&wsa_clk_on>;
+		pinctrl-1 = <&wsa_clk_off>;
+	};
+	wsa881x_analog_reset_gpio: wsa881x_analog_reset_pctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&wsa_reset_on>;
+		pinctrl-1 = <&wsa_reset_off>;
+	};
+
+	ext_codec: sound-9335 {
+		status = "disabled";
+		compatible = "qcom,msm8952-audio-slim-codec";
+		qcom,model = "msm8952-tasha-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,audio-routing =
+			"AIF4 VI", "MCLK",
+			"AIF4 VI", "MICBIAS_REGULATOR",
+			"RX_BIAS", "MCLK",
+			"MADINPUT", "MCLK",
+			"AIF4 MAD", "MICBIAS_REGULATOR",
+			"AMIC2", "MIC BIAS2",
+			"MIC BIAS2", "Headset Mic",
+			"AMIC3", "MIC BIAS2",
+			"MIC BIAS2", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2",
+			"MIC BIAS2", "ANCLeft Headset Mic",
+			"AMIC5", "MIC BIAS3",
+			"MIC BIAS3", "Handset Mic",
+			"AMIC6", "MIC BIAS4",
+			"MIC BIAS4", "Analog Mic6",
+			"DMIC0", "MIC BIAS1",
+			"MIC BIAS1", "Digital Mic0",
+			"DMIC1", "MIC BIAS1",
+			"MIC BIAS1", "Digital Mic1",
+			"DMIC2", "MIC BIAS3",
+			"MIC BIAS3", "Digital Mic2",
+			"DMIC3", "MIC BIAS3",
+			"MIC BIAS3", "Digital Mic3",
+			"DMIC4", "MIC BIAS4",
+			"MIC BIAS4", "Digital Mic4",
+			"DMIC5", "MIC BIAS4",
+			"MIC BIAS4", "Digital Mic5",
+			"MIC BIAS1", "MICBIAS_REGULATOR",
+			"MIC BIAS2", "MICBIAS_REGULATOR",
+			"MIC BIAS3", "MICBIAS_REGULATOR",
+			"MIC BIAS4", "MICBIAS_REGULATOR",
+			"SpkrLeft IN", "SPK1 OUT",
+			"SpkrRight IN", "SPK2 OUT";
+
+		qcom,tasha-mclk-clk-freq = <9600000>;
+
+		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+				<&loopback>, <&compress>, <&hostless>,
+				<&afe>, <&lsm>, <&routing>;
+		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";
+
+		asoc-cpu = <&dai_pri_auxpcm>,
+				<&dai_mi2s2>, <&dai_mi2s3>, <&dai_mi2s5>,
+				<&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+				<&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>,
+				<&sb_4_rx>, <&sb_4_tx>, <&sb_5_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>,
+				<&sb_5_rx>, <&bt_sco_rx>, <&bt_sco_tx>,
+				<&int_fm_rx>, <&int_fm_tx>, <&sb_6_rx>;
+
+		asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+				"msm-dai-q6-mi2s.5", "msm-dai-q6-dev.16384",
+				"msm-dai-q6-dev.16385", "msm-dai-q6-dev.16386",
+				"msm-dai-q6-dev.16387", "msm-dai-q6-dev.16388",
+				"msm-dai-q6-dev.16389", "msm-dai-q6-dev.16390",
+				"msm-dai-q6-dev.16391", "msm-dai-q6-dev.16392",
+				"msm-dai-q6-dev.16393", "msm-dai-q6-dev.16395",
+				"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",
+				"msm-dai-q6-dev.16394", "msm-dai-q6-dev.12288",
+				"msm-dai-q6-dev.12289", "msm-dai-q6-dev.12292",
+				"msm-dai-q6-dev.12293", "msm-dai-q6-dev.16396";
+
+		qcom,cdc-us-euro-gpios = <&tlmm 63 0>;
+		qcom,msm-mbhc-hphl-swh = <0>;
+		qcom,msm-mbhc-gnd-swh = <0>;
+
+		qcom,wsa-max-devs = <2>;
+		qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>,
+				<&wsa881x_213>, <&wsa881x_214>;
+		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+				"SpkrLeft", "SpkrRight";
+	};
+
+	wcd9xxx_intc: wcd9xxx-irq {
+		status = "disabled";
+		interrupt-parent = <&tlmm>;
+		interrupts = <73 0>;
+		qcom,gpio-connect = <&tlmm 73 0>;
+	};
+
+	clock_audio: audio_ext_clk {
+		status = "disabled";
+		compatible = "qcom,audio-ref-clk";
+		clock-names = "osr_clk";
+		qcom,node_has_rpm_clock;
+		#clock-cells = <1>;
+		qcom,audio-ref-clk-gpio = <&pm8937_gpios 1 0>;
+		qcom,lpass-mclk-id = "pri_mclk";
+		clocks = <&clock_gcc clk_div_clk2>;
+		pinctrl-0 = <&cdc_mclk2_sleep>;
+		pinctrl-1 = <&cdc_mclk2_active>;
+	};
+
+	wcd_rst_gpio: wcd_gpio_ctrl {
+		status = "disabled";
+		qcom,cdc-rst-n-gpio = <&tlmm 68 0>;
+	};
+};
+
+&slim_msm {
+	status = "disabled";
+	wcd9335: tasha_codec {
+		status = "disabled";
+		compatible = "qcom,tasha-slim-pgd";
+		clock-names = "wcd_clk", "wcd_native_clk";
+		clocks = <&clock_audio clk_audio_pmi_clk>,
+			<&clock_audio clk_audio_ap_clk2>;
+
+		qcom,cdc-reset-gpio = <&tlmm 68 0>;
+
+		cdc-vdd-buck-supply = <&eldo2_pm8937>;
+		qcom,cdc-vdd-buck-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-buck-current = <650000>;
+
+		cdc-buck-sido-supply = <&eldo2_pm8937>;
+		qcom,cdc-buck-sido-voltage = <1800000 1800000>;
+		qcom,cdc-buck-sido-current = <250000>;
+
+		cdc-vdd-tx-h-supply = <&pm8937_l5>;
+		qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-tx-h-current = <25000>;
+
+		cdc-vdd-rx-h-supply = <&pm8937_l5>;
+		qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-rx-h-current = <25000>;
+
+		cdc-vdd-px-supply = <&pm8937_l5>;
+		qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-px-current = <10000>;
+
+		cdc-vdd-mic-bias-supply = <&pm8937_l13>;
+		qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+		qcom,cdc-vdd-mic-bias-current = <15000>;
+	};
+};
+
+&pm8937_gpios {
+	gpio@c000 {
+		status = "ok";
+		qcom,mode = <1>;
+		qcom,pull = <5>;
+		qcom,vin-sel = <0>;
+		qcom,src-sel = <2>;
+		qcom,master-en = <1>;
+		qcom,out-strength = <2>;
+	};
+};
+
+&pm8937_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 = <&pm8937_s4>;
+		qcom,cdc-vdda-cp-voltage = <2050000 2050000>;
+		qcom,cdc-vdda-cp-current = <210000>;
+
+		cdc-vdd-io-supply = <&pm8937_l5>;
+		qcom,cdc-vdd-io-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-io-current = <5000>;
+
+		cdc-vdd-pa-supply = <&pm8937_s4>;
+		qcom,cdc-vdd-pa-voltage = <1900000 2050000>;
+		qcom,cdc-vdd-pa-current = <260000>;
+
+		cdc-vdd-mic-bias-supply = <&pm8937_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 = <0xc0f0000 0x0>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi
index b8516d5..b9229e1 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi
@@ -237,6 +237,31 @@
 			};
 		};
 
+		cdc_mclk2_pin {
+			cdc_mclk2_sleep: cdc_mclk2_sleep {
+				mux {
+					pins = "gpio66";
+					function = "pri_mi2s";
+				};
+				config {
+					pins = "gpio66";
+					drive-strength = <2>; /* 2 mA */
+					bias-pull-down;       /* PULL DOWN */
+				};
+			};
+			cdc_mclk2_active: cdc_mclk2_active {
+				mux {
+					pins = "gpio66";
+					function = "pri_mi2s";
+				};
+				config {
+					pins = "gpio66";
+					drive-strength = <8>; /* 8 mA */
+					bias-disable;         /* NO PULL */
+				};
+			};
+		};
+
 		pmx_mdss: pmx_mdss {
 			mdss_dsi_active: mdss_dsi_active {
 				mux {
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8937-mtp.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8937-mtp.dts
new file mode 100644
index 0000000..e5207fe
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8937-mtp.dts
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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 "msm8917.dtsi"
+#include "msm8917-mtp.dtsi"
+#include "msm8917-pmi8937.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917-PMI8937 MTP";
+	compatible = "qcom,msm8917-mtp", "qcom,msm8917", "qcom,mtp";
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x10019 0x020037 0x0 0x0>;
+};
+
+&vendor {
+	mtp_batterydata: qcom,battery-data {
+		qcom,batt-id-range-pct = <15>;
+		#include "batterydata-itech-3000mah.dtsi"
+		#include "batterydata-ascent-3450mAh.dtsi"
+	};
+};
+
+&qpnp_fg {
+	qcom,battery-data = <&mtp_batterydata>;
+};
+
+&qpnp_smbcharger {
+	qcom,battery-data = <&mtp_batterydata>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts
new file mode 100644
index 0000000..29ef47c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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 "msm8917.dtsi"
+#include "msm8917-qrd.dtsi"
+#include "msm8917-pmi8937.dtsi"
+#include "msm8937-mdss-panels.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917-PMI8937 QRD SKU5";
+	compatible = "qcom,msm8917-qrd-sku5", "qcom,msm8917-qrd",
+		   "qcom,msm8917", "qcom,qrd";
+	qcom,board-id = <0x1000b 0>;
+};
+
+&vendor{
+	qrd_batterydata: qcom,battery-data {
+		qcom,batt-id-range-pct = <15>;
+		#include "batterydata-qrd-sku2-4v35-2590mah.dtsi"
+	};
+};
+
+&qpnp_smbcharger {
+	qcom,battery-data = <&qrd_batterydata>;
+};
+
+&qpnp_fg {
+	qcom,battery-data = <&qrd_batterydata>;
+};
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+	hw-config = "single_dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_hx8394f_720p_video>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_dsi_active>;
+	pinctrl-1 = <&mdss_dsi_suspend>;
+
+	qcom,platform-reset-gpio = <&tlmm 60 0>;
+};
+
+&dsi_hx8394f_720p_video {
+	qcom,esd-check-enabled;
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
+&soc {
+	i2c@78b7000 {
+		status = "ok";
+		focaltech@38 {
+			compatible = "focaltech,5x06";
+			reg = <0x38>;
+			interrupt-parent = <&tlmm>;
+			interrupts = <65 0x2>;
+			vdd-supply = <&pm8937_l10>;
+			vcc_i2c-supply = <&pm8937_l5>;
+			/* pins used by touchscreen */
+			pinctrl-names = "pmx_ts_active",
+						"pmx_ts_suspend",
+						"pmx_ts_release";
+			pinctrl-0 = <&ts_int_active &ts_reset_active>;
+			pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+			pinctrl-2 = <&ts_release>;
+			focaltech,name = "ft5436";
+			focaltech,family-id = <0x06>;
+			focaltech,reset-gpio = <&tlmm 64 0x0>;
+			focaltech,irq-gpio = <&tlmm 65 0x2008>;
+			focaltech,display-coords = <0 0 720 1280>;
+			focaltech,panel-coords = <0 0 720 1400>;
+			focaltech,button-map= <139 102 158>;
+			focaltech,no-force-update;
+			focaltech,i2c-pull-up;
+			focaltech,group-id = <1>;
+			focaltech,hard-reset-delay-ms = <20>;
+			focaltech,soft-reset-delay-ms = <200>;
+			focaltech,num-max-touches = <5>;
+			focaltech,fw-delay-aa-ms = <30>;
+			focaltech,fw-delay-55-ms = <30>;
+			focaltech,fw-upgrade-id1 = <0x79>;
+			focaltech,fw-upgrade-id2 = <0x08>;
+			focaltech,fw-delay-readid-ms = <10>;
+			focaltech,fw-delay-era-flsh-ms = <2000>;
+			focaltech,fw-auto-cal;
+			focaltech,ignore-id-check;
+			focaltech,resume-in-workqueue;
+		};
+	};
+
+	gen-vkeys {
+		compatible = "qcom,gen-vkeys";
+		label = "ft5x06_ts";
+		qcom,disp-maxx = <720>;
+		qcom,disp-maxy = <1280>;
+		qcom,panel-maxx = <720>;
+		qcom,panel-maxy = <1400>;
+		qcom,key-codes = <139 172 158>;
+		qcom,y-offset = <0>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi
new file mode 100644
index 0000000..3b24ab7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi
@@ -0,0 +1,24 @@
+/*
+ * 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 "pmi8937.dtsi"
+
+&qpnp_smbcharger {
+	qcom,chg-led-sw-controls;
+	qcom,chg-led-support;
+	/delete-property/ dpdm-supply;
+};
+
+&usb_otg {
+	extcon = <&qpnp_smbcharger>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8940-mtp.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8940-mtp.dts
new file mode 100644
index 0000000..8379228
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8940-mtp.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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 "msm8917.dtsi"
+#include "msm8917-mtp.dtsi"
+#include "msm8917-pmi8940.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917-PMI8940 MTP";
+	compatible = "qcom,msm8917-mtp", "qcom,msm8917", "qcom,mtp";
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x10019 0x020040 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
new file mode 100644
index 0000000..528bde4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
@@ -0,0 +1,24 @@
+/*
+ * 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 "pmi8940.dtsi"
+
+&qpnp_smbcharger {
+	qcom,chg-led-sw-controls;
+	qcom,chg-led-support;
+	/delete-property/ dpdm-supply;
+};
+
+&usb_otg {
+	extcon = <&qpnp_smbcharger>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi b/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
new file mode 100644
index 0000000..f897b59
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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 "msm8917-pinctrl.dtsi"
+
+&blsp1_uart2 {
+	status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console_active>;
+};
+
+&sdhc_1 {
+	/* device core power supply */
+	vdd-supply = <&pm8937_l8>;
+	qcom,vdd-voltage-level = <2900000 2900000>;
+	qcom,vdd-current-level = <200 570000>;
+
+	/* device communication power supply */
+	vdd-io-supply = <&pm8937_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";
+};
+
+&sdhc_2 {
+	/* device core power supply */
+	vdd-supply = <&pm8937_l11>;
+	qcom,vdd-voltage-level = <2950000 2950000>;
+	qcom,vdd-current-level = <15000 800000>;
+
+	/* device communication power supply */
+	vdd-io-supply = <&pm8937_l12>;
+	qcom,vdd-io-voltage-level = <1800000 2950000>;
+	qcom,vdd-io-current-level = <200 22000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_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 67 0>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&tlmm 67 0x1>;
+
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+								200000000>;
+	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+	status = "ok";
+};
+
+&soc {
+	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>;
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&tlmm 91 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			debounce-interval = <15>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917.dtsi b/arch/arm64/boot/dts/qcom/msm8917.dtsi
index 9b91fe9..78410b3 100644
--- a/arch/arm64/boot/dts/qcom/msm8917.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917.dtsi
@@ -1140,6 +1140,175 @@
 		qcom,ce-opp-freq = <100000000>;
 	};
 
+	qcom,mss@4080000 {
+		compatible = "qcom,pil-q6v55-mss";
+		reg = <0x04080000 0x100>,
+			<0x0194f000 0x010>,
+			<0x01950000 0x008>,
+			<0x01951000 0x008>,
+			<0x04020000 0x040>,
+			<0x01871000 0x004>;
+		reg-names = "qdsp6_base", "halt_q6", "halt_modem", "halt_nc",
+			"rmb_base", "restart_reg";
+
+		interrupts = <GIC_SPI 24 IRQ_TYPE_EDGE_RISING>;
+		vdd_mss-supply = <&pm8937_s1>;
+		vdd_cx-supply = <&pm8937_s2_level>;
+		vdd_cx-voltage = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+		vdd_mx-supply = <&pm8937_l3_level_ao>;
+		vdd_mx-uV = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+		vdd_pll-supply = <&pm8937_l7>;
+		qcom,vdd_pll = <1800000>;
+		vdd_mss-uV = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+
+		clocks = <&clock_gcc clk_xo_pil_mss_clk>,
+		<&clock_gcc clk_gcc_mss_cfg_ahb_clk>,
+		<&clock_gcc clk_gcc_mss_q6_bimc_axi_clk>,
+		<&clock_gcc clk_gcc_boot_rom_ahb_clk>;
+		clock-names = "xo", "iface_clk", "bus_clk", "mem_clk";
+		qcom,proxy-clock-names = "xo";
+		qcom,active-clock-names = "iface_clk", "bus_clk", "mem_clk";
+
+		qcom,firmware-name = "modem";
+		qcom,pil-self-auth;
+		qcom,override-acc-1 = <0x80800000>;
+		qcom,sysmon-id = <0>;
+		qcom,ssctl-instance-id = <0x12>;
+		qcom,qdsp6v56-1-8-inrush-current;
+		qcom,reset-clk;
+
+		/* GPIO inputs from mss */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
+		qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_1_in 3 0>;
+		qcom,gpio-shutdown-ack = <&smp2pgpio_ssr_smp2p_1_in 7 0>;
+
+		/* GPIO output to mss */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
+
+		memory-region = <&modem_mem>;
+	};
+
+	qcom,lpass@c200000 {
+		compatible = "qcom,pil-tz-generic";
+		reg = <0xc200000 0x00100>;
+		interrupts = <GIC_SPI 293 IRQ_TYPE_EDGE_RISING>;
+
+		vdd_cx-supply = <&pm8937_s2_level>;
+		qcom,proxy-reg-names = "vdd_cx";
+		qcom,vdd_cx-uV-uA = <RPM_SMD_REGULATOR_LEVEL_TURBO 100000>;
+
+		clocks = <&clock_gcc clk_xo_pil_lpass_clk>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>,
+			 <&clock_gcc clk_crypto_clk_src>;
+		clock-names = "xo", "scm_core_clk", "scm_iface_clk",
+				"scm_bus_clk", "scm_core_clk_src";
+		qcom,proxy-clock-names = "xo", "scm_core_clk", "scm_iface_clk",
+			 "scm_bus_clk", "scm_core_clk_src";
+		qcom,scm_core_clk_src-freq = <80000000>;
+
+		qcom,mas-crypto = <&mas_crypto>;
+		qcom,pas-id = <1>;
+		qcom,complete-ramdump;
+		qcom,proxy-timeout-ms = <10000>;
+		qcom,smem-id = <423>;
+		qcom,sysmon-id = <1>;
+		qcom,ssctl-instance-id = <0x14>;
+		qcom,firmware-name = "adsp";
+
+		/* GPIO inputs from lpass */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_2_in 0 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_2_in 2 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_2_in 1 0>;
+		qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_2_in 3 0>;
+
+		/* GPIO output to lpass */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>;
+
+		memory-region = <&adsp_fw_mem>;
+	};
+
+	qcom,pronto@a21b000 {
+		compatible = "qcom,pil-tz-generic";
+		reg = <0x0a21b000 0x3000>;
+		interrupts = <GIC_SPI 149 IRQ_TYPE_EDGE_RISING>;
+
+		vdd_pronto_pll-supply = <&pm8937_l7>;
+		proxy-reg-names = "vdd_pronto_pll";
+		vdd_pronto_pll-uV-uA = <1800000 18000>;
+		clocks = <&clock_gcc clk_xo_pil_pronto_clk>,
+		<&clock_gcc clk_gcc_crypto_clk>,
+		<&clock_gcc clk_gcc_crypto_ahb_clk>,
+		<&clock_gcc clk_gcc_crypto_axi_clk>,
+		<&clock_gcc clk_crypto_clk_src>;
+
+		clock-names = "xo", "scm_core_clk", "scm_iface_clk",
+			"scm_bus_clk", "scm_core_clk_src";
+		qcom,proxy-clock-names = "xo", "scm_core_clk", "scm_iface_clk",
+			 "scm_bus_clk", "scm_core_clk_src";
+		qcom,scm_core_clk_src = <80000000>;
+
+		qcom,mas-crypto = <&mas_crypto>;
+		qcom,pas-id = <6>;
+		qcom,proxy-timeout-ms = <10000>;
+		qcom,smem-id = <422>;
+		qcom,sysmon-id = <6>;
+		qcom,ssctl-instance-id = <0x13>;
+		qcom,firmware-name = "wcnss";
+
+		/* GPIO inputs from wcnss */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_4_in 1 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
+		qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_4_in 3 0>;
+
+		/* GPIO output to wcnss */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
+		memory-region = <&wcnss_fw_mem>;
+	};
+
+	qcom,venus@1de0000 {
+		compatible = "qcom,pil-tz-generic";
+		reg = <0x1de0000 0x4000>;
+
+		vdd-supply = <&gdsc_venus>;
+		qcom,proxy-reg-names = "vdd";
+
+		clocks = <&clock_gcc clk_gcc_venus0_vcodec0_clk>,
+			 <&clock_gcc clk_gcc_venus0_ahb_clk>,
+			 <&clock_gcc clk_gcc_venus0_axi_clk>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>,
+			 <&clock_gcc clk_crypto_clk_src>;
+
+		clock-names = "core_clk", "iface_clk", "bus_clk",
+				"scm_core_clk", "scm_iface_clk",
+				"scm_bus_clk", "scm_core_clk_src";
+
+		qcom,proxy-clock-names = "core_clk", "iface_clk",
+					 "bus_clk", "scm_core_clk",
+					 "scm_iface_clk", "scm_bus_clk",
+					 "scm_core_clk_src";
+		qcom,scm_core_clk_src-freq = <80000000>;
+
+		qcom,msm-bus,name = "pil-venus";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<63 512 0 0>,
+				<63 512 0 304000>;
+
+		qcom,mas-crypto = <&mas_crypto>;
+		qcom,pas-id = <9>;
+		qcom,proxy-timeout-ms = <100>;
+		qcom,firmware-name = "venus";
+		memory-region = <&venus_mem>;
+	};
+
 	qcom_rng: qrng@e3000 {
 		compatible = "qcom,msm-rng";
 		reg = <0xe3000 0x1000>;
@@ -1258,6 +1427,7 @@
 #include "pm8937-rpm-regulator.dtsi"
 #include "msm8917-regulator.dtsi"
 #include "pm8937.dtsi"
+#include "msm8917-audio.dtsi"
 #include "msm-gdsc-8916.dtsi"
 #include "msm8917-thermal.dtsi"
 
diff --git a/arch/arm64/boot/dts/qcom/msm8937-camera.dtsi b/arch/arm64/boot/dts/qcom/msm8937-camera.dtsi
index b5f467e..831ce61 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-camera.dtsi
@@ -24,7 +24,7 @@
 	qcom,csiphy@1b34000 {
 		status = "ok";
 		cell-index = <0>;
-		compatible = "qcom,csiphy-v3.4.2", "qcom,csiphy";
+		compatible = "qcom,csiphy-v10.00", "qcom,csiphy";
 		reg = <0x1b34000 0x1000>,
 			<0x1b00030 0x4>;
 		reg-names = "csiphy", "csiphy_clk_mux";
@@ -45,7 +45,7 @@
 	qcom,csiphy@1b35000 {
 		status = "ok";
 		cell-index = <1>;
-		compatible = "qcom,csiphy-v3.4.2", "qcom,csiphy";
+		compatible = "qcom,csiphy-v10.00", "qcom,csiphy";
 		reg = <0x1b35000 0x1000>,
 			<0x1b00038 0x4>;
 		reg-names = "csiphy", "csiphy_clk_mux";
diff --git a/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi b/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
index f7831c5..b952908 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
@@ -1,13 +1,13 @@
 /*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
- *
+ * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved.
+
  * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 an
+ * 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
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
 
@@ -28,6 +28,7 @@
 		qcom,force-reg-dump;
 
 		coresight-name = "coresight-tmc-etr";
+		coresight-csr = <&csr>;
 		coresight-ctis = <&cti0 &cti8>;
 
 		clocks = <&clock_gcc clk_qdss_clk>,
@@ -50,6 +51,7 @@
 		reg-names = "tmc-base";
 
 		coresight-name = "coresight-tmc-etf";
+		coresight-csr = <&csr>;
 
 		arm,default-sink;
 		qcom,force-reg-dump;
@@ -1094,6 +1096,10 @@
 		reg-names = "csr-base";
 		coresight-name = "coresight-csr";
 
+		qcom,usb-bam-support;
+		qcom,hwctrl-set-support;
+		qcom,set-byte-cntr-support;
+
 		qcom,blk-size = <1>;
 
 		clocks = <&clock_gcc clk_qdss_clk>,
@@ -1195,6 +1201,7 @@
 				"usbbam-mux", "blsp-mux";
 
 		coresight-name = "coresight-hwevent";
+		coresight-csr = <&csr>;
 
 		clocks = <&clock_gcc clk_qdss_clk>,
 			 <&clock_gcc clk_qdss_a_clk>;
diff --git a/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi b/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi
index ec92805..05d1e45 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi
@@ -269,3 +269,83 @@
 		};
 	};
 };
+
+&soc {
+	cpuss_dump {
+		compatible = "qcom,cpuss-dump";
+		qcom,l2_dump0 {
+			/* L2 cache dump for A53 cluster */
+			qcom,dump-node = <&L2_0>;
+			qcom,dump-id = <0xC0>;
+		};
+		qcom,l2_dump1 {
+			/* L2 cache dump for A53 cluster */
+			qcom,dump-node = <&L2_1>;
+			qcom,dump-id = <0xC1>;
+		};
+		qcom,l1_i_cache0 {
+			qcom,dump-node = <&L1_I_0>;
+			qcom,dump-id = <0x60>;
+		};
+		qcom,l1_i_cache1 {
+			qcom,dump-node = <&L1_I_1>;
+			qcom,dump-id = <0x61>;
+		};
+		qcom,l1_i_cache2 {
+			qcom,dump-node = <&L1_I_2>;
+			qcom,dump-id = <0x62>;
+		};
+		qcom,l1_i_cache3 {
+			qcom,dump-node = <&L1_I_3>;
+			qcom,dump-id = <0x63>;
+		};
+		qcom,l1_i_cache100 {
+			qcom,dump-node = <&L1_I_100>;
+			qcom,dump-id = <0x64>;
+		};
+		qcom,l1_i_cache101 {
+			qcom,dump-node = <&L1_I_101>;
+			qcom,dump-id = <0x65>;
+		};
+		qcom,l1_i_cache102 {
+			qcom,dump-node = <&L1_I_102>;
+			qcom,dump-id = <0x66>;
+		};
+		qcom,l1_i_cache103 {
+			qcom,dump-node = <&L1_I_103>;
+			qcom,dump-id = <0x67>;
+		};
+		qcom,l1_d_cache0 {
+			qcom,dump-node = <&L1_D_0>;
+			qcom,dump-id = <0x80>;
+		};
+		qcom,l1_d_cache1 {
+			qcom,dump-node = <&L1_D_1>;
+			qcom,dump-id = <0x81>;
+		};
+		qcom,l1_d_cache2 {
+			qcom,dump-node = <&L1_D_2>;
+			qcom,dump-id = <0x82>;
+		};
+		qcom,l1_d_cache3 {
+			qcom,dump-node = <&L1_D_3>;
+			qcom,dump-id = <0x83>;
+		};
+		qcom,l1_d_cache100 {
+			qcom,dump-node = <&L1_D_100>;
+			qcom,dump-id = <0x84>;
+		};
+		qcom,l1_d_cache101 {
+			qcom,dump-node = <&L1_D_101>;
+			qcom,dump-id = <0x85>;
+		};
+		qcom,l1_d_cache102 {
+			qcom,dump-node = <&L1_D_102>;
+			qcom,dump-id = <0x86>;
+		};
+		qcom,l1_d_cache103 {
+			qcom,dump-node = <&L1_D_103>;
+			qcom,dump-id = <0x87>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm429-cdp.dts b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm429-cdp.dts
new file mode 100644
index 0000000..151a12f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm429-cdp.dts
@@ -0,0 +1,24 @@
+/*
+ * 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 "msm8937-interposer-sdm429.dtsi"
+#include "sdm429-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8937 Interposer SDM429 CDP";
+	compatible = "qcom,msm8937-cdp", "qcom,msm8937", "qcom,cdp";
+	qcom,board-id = <1 3>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm429-mtp.dts b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm429-mtp.dts
new file mode 100644
index 0000000..abf38f6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm429-mtp.dts
@@ -0,0 +1,24 @@
+/*
+ * 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 "msm8937-interposer-sdm429.dtsi"
+#include "sdm429-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8937 Interposer SDM429 MTP";
+	compatible = "qcom,msm8937-mtp", "qcom,msm8937", "qcom,mtp";
+	qcom,board-id = <8 2>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm429.dts b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm429.dts
new file mode 100644
index 0000000..ab28966
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm429.dts
@@ -0,0 +1,23 @@
+/*
+ * 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 "msm8937-interposer-sdm429.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8953 + PMI632 SOC";
+	compatible = "qcom,msm8953";
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+	qcom.pmic-name = "PMI632";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm429.dtsi b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm429.dtsi
new file mode 100644
index 0000000..5ae93333
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm429.dtsi
@@ -0,0 +1,58 @@
+/*
+ * 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 "msm8937-interposer-sdm439.dtsi"
+#include "sdm429-cpu.dtsi"
+
+&soc {
+	/delete-node/ etm@619c000;
+	/delete-node/ etm@619d000;
+	/delete-node/ etm@619e000;
+	/delete-node/ etm@619f000;
+	/delete-node/ cti@61b8000;
+	/delete-node/ cti@61b9000;
+	/delete-node/ cti@61ba000;
+	/delete-node/ cti@61bb000;
+
+	qcom,spm@b1d2000 {
+		qcom,cpu-vctl-list = <&CPU0 &CPU1 &CPU2 &CPU3>;
+	};
+
+	qcom,lpm-levels {
+		qcom,pm-cluster@0 {
+			/delete-node/qcom,pm-cluster@1;
+		};
+	};
+};
+
+&funnel_apss {
+	ports {
+		/delete-node/ port@1;
+		/delete-node/ port@2;
+		/delete-node/ port@3;
+		/delete-node/ port@4;
+	};
+};
+
+&thermal_zones {
+	hexa-cpu-max-step {
+		cooling-maps {
+			/delete-node/ cpu4_cdev;
+			/delete-node/ cpu5_cdev;
+			/delete-node/ cpu6_cdev;
+			/delete-node/ cpu7_cdev;
+		};
+	};
+
+	/delete-node/ cpuss0-step;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts
index 2bad28b..71157e2 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts
@@ -22,3 +22,10 @@
 	qcom,board-id = <0xb 2>;
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
+
+&pmi632_vadc {
+	chan@4a {
+		qcom,scale-function = <22>;
+	};
+};
+
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dts b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dts
new file mode 100644
index 0000000..33b2c74
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dts
@@ -0,0 +1,23 @@
+/*
+ * 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 "msm8937-interposer-sdm439.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8953 + PMI632 SOC";
+	compatible = "qcom,msm8953";
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+	qcom.pmic-name = "PMI632";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi
index fbe5ce7..ad6511c 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi
@@ -27,6 +27,12 @@
 };
 
 &soc {
+	qcom,csiphy@1b34000 {
+		compatible = "qcom,csiphy-v3.4.2", "qcom,csiphy";
+	};
+	qcom,csiphy@1b35000 {
+		compatible = "qcom,csiphy-v3.4.2", "qcom,csiphy";
+	};
 	qcom,csid@1b30000 {
 		qcom,mipi-csi-vdd-supply = <&pm8953_l2>;
 	};
@@ -168,3 +174,8 @@
 		vdd-cci-supply = <&apc_vreg_corner>;
 	};
 };
+
+&mdss_dsi {
+	vdda-supply = <&pm8953_l2>;
+	vddio-supply = <&pm8953_l6>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi
index bca8912..436b8a7 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi
@@ -18,6 +18,7 @@
 #include "dsi-panel-truly-720p-cmd.dtsi"
 #include "dsi-panel-r69006-1080p-cmd.dtsi"
 #include "dsi-panel-r69006-1080p-video.dtsi"
+#include "dsi-panel-hx8394f-720p-video.dtsi"
 #include "dsi-adv7533-1080p.dtsi"
 #include "dsi-adv7533-720p.dtsi"
 #include "dsi-panel-hx8399c-fhd-plus-video.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
index 87dd30e..86e41a3 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
@@ -141,39 +141,67 @@
 			};
 		};
 
-		pmx_rd_nfc_int {
-			/*qcom,pins = <&gp 17>;*/
-			pins = "gpio17";
-			qcom,pin-func = <0>;
-			qcom,num-grp-pins = <1>;
-			label = "pmx_nfc_int";
+		nfc {
+			nfc_int_active: nfc_int_active {
+				/* active state */
+				mux {
+					/* GPIO 17 NFC Read Interrupt */
+					pins = "gpio17";
+					function = "gpio";
+				};
 
-			nfc_int_active: active {
-				drive-strength = <6>;
-				bias-pull-up;
+				config {
+					pins = "gpio17";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-up;
+				};
 			};
 
-			nfc_int_suspend: suspend {
-				drive-strength = <6>;
-				bias-pull-up;
-			};
-		};
+			nfc_int_suspend: nfc_int_suspend {
+				/* sleep state */
+				mux {
+					/* GPIO 17 NFC Read Interrupt */
+					pins = "gpio17";
+					function = "gpio";
+				};
 
-		pmx_nfc_reset {
-			/*qcom,pins = <&gp 16>;*/
-			pins = "gpio16";
-			qcom,pin-func = <0>;
-			qcom,num-grp-pins = <1>;
-			label = "pmx_nfc_disable";
-
-			nfc_disable_active: active {
-				drive-strength = <6>;
-				bias-pull-up;
+				config {
+					pins = "gpio17";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-up;
+				};
 			};
 
-			nfc_disable_suspend: suspend {
-				drive-strength = <6>;
-				bias-disable;
+			nfc_disable_active: nfc_disable_active {
+				/* active state */
+				mux {
+					/* 16: NFC ENABLE 130: FW DNLD */
+					/* 93: ESE Enable */
+					pins = "gpio16", "gpio130", "gpio93";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio16", "gpio130", "gpio93";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-up;
+				};
+			};
+
+			nfc_disable_suspend: nfc_disable_suspend {
+				/* sleep state */
+				mux {
+					/* 16: NFC ENABLE 130: FW DNLD */
+					/* 93: ESE Enable */
+					pins = "gpio16", "gpio130", "gpio93";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio16", "gpio130", "gpio93";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable;
+				};
 			};
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/msm8937-vidc.dtsi b/arch/arm64/boot/dts/qcom/msm8937-vidc.dtsi
index c4d5b90..ce6692d 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-vidc.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-vidc.dtsi
@@ -78,7 +78,9 @@
 		secure_bitstream_cb {
 			compatible = "qcom,msm-vidc,context-bank";
 			label = "venus_sec_bitstream";
-			iommus = <&apps_iommu 0x90c 0x20>;
+			iommus = <&apps_iommu 0x900 0x00>,
+				<&apps_iommu 0x90a 0x04>,
+				<&apps_iommu 0x909 0x22>;
 			buffer-types = <0x241>;
 			virtual-addr-pool = <0x4b000000 0x12c00000>;
 			qcom,secure-context-bank;
@@ -87,10 +89,7 @@
 		secure_pixel_cb {
 			compatible = "qcom,msm-vidc,context-bank";
 			label = "venus_sec_pixel";
-			iommus = <&apps_iommu 0x940 0x00>,
-				<&apps_iommu 0x907 0x08>,
-				<&apps_iommu 0x908 0x20>,
-				<&apps_iommu 0x90d 0x20>;
+			iommus = <&apps_iommu 0x90c 0x20>;
 			buffer-types = <0x106>;
 			virtual-addr-pool = <0x25800000 0x25800000>;
 			qcom,secure-context-bank;
@@ -99,9 +98,10 @@
 		secure_non_pixel_cb {
 			compatible = "qcom,msm-vidc,context-bank";
 			label = "venus_sec_non_pixel";
-			iommus = <&apps_iommu 0x900 0x00>,
-				<&apps_iommu 0x90a 0x04>,
-				<&apps_iommu 0x909 0x22>;
+			iommus = <&apps_iommu 0x940 0x00>,
+				<&apps_iommu 0x907 0x08>,
+				<&apps_iommu 0x908 0x20>,
+				<&apps_iommu 0x90d 0x20>;
 			buffer-types = <0x480>;
 			virtual-addr-pool = <0x1000000 0x24800000>;
 			qcom,secure-context-bank;
diff --git a/arch/arm64/boot/dts/qcom/msm8937.dtsi b/arch/arm64/boot/dts/qcom/msm8937.dtsi
index 8f769fe..240cc04 100644
--- a/arch/arm64/boot/dts/qcom/msm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937.dtsi
@@ -53,7 +53,7 @@
 		};
 	};
 
-	reserved-memory {
+	reserved_memory: reserved-memory {
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges;
@@ -191,13 +191,24 @@
 		      <0x0b002000 0x1000>;
 	};
 
+	dcc: dcc@b3000 {
+		compatible = "qcom,dcc";
+		reg = <0xb3000 0x1000>,
+		      <0xb4000 0x2000>;
+		reg-names = "dcc-base", "dcc-ram-base";
+
+		clocks = <&clock_gcc clk_gcc_dcc_clk>;
+		clock-names = "apb_pclk";
+		qcom,save-reg;
+	};
+
 	wakegic: wake-gic {
 		compatible = "qcom,mpm-gic-msm8937", "qcom,mpm-gic";
 		interrupts = <GIC_SPI 171 IRQ_TYPE_EDGE_RISING>;
 		reg = <0x601d0 0x1000>,
 			<0xb011008 0x4>;  /* MSM_APCS_GCC_BASE 4K */
 		reg-names = "vmpm", "ipc";
-		qcom,num-mpm-irqs = <96>;
+		qcom,num-mpm-irqs = <64>;
 		interrupt-controller;
 		interrupt-parent = <&intc>;
 		#interrupt-cells = <3>;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-audio.dtsi b/arch/arm64/boot/dts/qcom/msm8953-audio.dtsi
index fc10b4d..f862a07 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-audio.dtsi
@@ -82,6 +82,8 @@
 		qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
 		qcom,quin-mi2s-gpios = <&cdc_quin_mi2s_gpios>;
 
+		qcom,afe-rxtx-lb;
+
 		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
 				<&loopback>, <&compress>, <&hostless>,
 				<&afe>, <&lsm>, <&routing>, <&pcm_noirq>;
@@ -102,7 +104,8 @@
 			<&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>;
+			<&incall_music_rx>, <&incall_music_2_rx>,
+			<&afe_loopback_tx>;
 
 		asoc-cpu-names = "msm-dai-q6-auxpcm.1",
 				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
@@ -117,7 +120,8 @@
 				"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";
+				"msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770",
+				"msm-dai-q6-dev.24577";
 
 		asoc-codec = <&stub_codec>, <&msm_digital_codec>,
 				<&pmic_analog_codec>;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-cdp.dtsi
index db9fb13..6e961b1 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-cdp.dtsi
@@ -45,8 +45,8 @@
 		cam_vdig-supply = <&pm8953_l2>;
 		cam_vaf-supply = <&pm8953_l17>;
 		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000>;
+		qcom,cam-vreg-min-voltage = <0 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <0 1200000 2850000>;
 		qcom,cam-vreg-op-mode = <0 105000 100000>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_default
@@ -207,8 +207,8 @@
 		cam_v_custom1-supply = <&pm8953_l23>;
 		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf",
 						"cam_vana", "cam_v_custom1";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000 1220000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000 2800000 1220000>;
+		qcom,cam-vreg-min-voltage = <0 1200000 2850000 2800000 1220000>;
+		qcom,cam-vreg-max-voltage = <0 1200000 2850000 2800000 1220000>;
 		qcom,cam-vreg-op-mode = <0 105000 100000 80000 105000>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_default
@@ -297,8 +297,8 @@
 		cam_vaf-supply = <&pm8953_l17>;
 		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
 					"cam_vaf";
-		qcom,cam-vreg-min-voltage = <1175000 0 2800000 2850000>;
-		qcom,cam-vreg-max-voltage = <1175000 0 2800000 2850000>;
+		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";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-mtp.dtsi
index db9fb13..6e961b1 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-mtp.dtsi
@@ -45,8 +45,8 @@
 		cam_vdig-supply = <&pm8953_l2>;
 		cam_vaf-supply = <&pm8953_l17>;
 		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000>;
+		qcom,cam-vreg-min-voltage = <0 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <0 1200000 2850000>;
 		qcom,cam-vreg-op-mode = <0 105000 100000>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_default
@@ -207,8 +207,8 @@
 		cam_v_custom1-supply = <&pm8953_l23>;
 		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf",
 						"cam_vana", "cam_v_custom1";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000 1220000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000 2800000 1220000>;
+		qcom,cam-vreg-min-voltage = <0 1200000 2850000 2800000 1220000>;
+		qcom,cam-vreg-max-voltage = <0 1200000 2850000 2800000 1220000>;
 		qcom,cam-vreg-op-mode = <0 105000 100000 80000 105000>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_default
@@ -297,8 +297,8 @@
 		cam_vaf-supply = <&pm8953_l17>;
 		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
 					"cam_vaf";
-		qcom,cam-vreg-min-voltage = <1175000 0 2800000 2850000>;
-		qcom,cam-vreg-max-voltage = <1175000 0 2800000 2850000>;
+		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";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-qrd.dtsi b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-qrd.dtsi
index 8098efb..adaaec6 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-qrd.dtsi
@@ -33,8 +33,8 @@
 		cam_vdig-supply = <&pm8953_l23>;
 		cam_vaf-supply = <&pm8953_l17>;
 		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000>;
+		qcom,cam-vreg-min-voltage = <0 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <0 1200000 2850000>;
 		qcom,cam-vreg-op-mode = <0 105000 100000>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_default
@@ -113,8 +113,8 @@
 		cam_vana-supply = <&pm8953_l22>;
 		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf",
 						"cam_vana";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000 2800000>;
+		qcom,cam-vreg-min-voltage = <0 1200000 2850000 2800000>;
+		qcom,cam-vreg-max-voltage = <0 1200000 2850000 2800000>;
 		qcom,cam-vreg-op-mode = <0 105000 100000 80000>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_default
diff --git a/arch/arm64/boot/dts/qcom/msm8953-camera.dtsi b/arch/arm64/boot/dts/qcom/msm8953-camera.dtsi
index b125612..b7f060a 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-camera.dtsi
@@ -423,6 +423,8 @@
 		qcom,clock-rates = <80000000 0 180000000 0 0 180000000 0 0>;
 		qcom,min-clock-rate = <100000000>;
 		qcom,bus-master = <1>;
+		resets = <&clock_gcc GCC_CAMSS_MICRO_BCR>;
+		reset-names = "micro_iface_reset";
 		qcom,msm-bus,name = "msm_camera_cpp";
 		qcom,msm-bus,num-cases = <2>;
 		qcom,msm-bus,num-paths = <1>;
@@ -430,6 +432,7 @@
 			<106 512 0 0>,
 			<106 512 0 0>;
 		qcom,msm-bus-vector-dyn-vote;
+		qcom,micro-reset;
 		qcom,cpp-fw-payload-info {
 			qcom,stripe-base = <156>;
 			qcom,plane-base = <141>;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi
index 8782325..9b78253 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi
@@ -42,6 +42,7 @@
 		qcom,nq-ven = <&tlmm 16 0x00>;
 		qcom,nq-firm = <&tlmm 62 0x00>;
 		qcom,nq-clkreq = <&pm8953_gpios 2 0x00>;
+		qcom,nq-esepwr = <&tlmm 141 0x00>;
 		interrupt-parent = <&tlmm>;
 		qcom,clk-src = "BBCLK2";
 		interrupts = <17 0>;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts
index 08a343e..b182a25 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts
@@ -17,7 +17,81 @@
 #include "msm8953-mtp.dtsi"
 
 / {
-	model = "Ext Codec MTP";
+	model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 Ext Codec MTP";
+	compatible = "qcom,msm8953-mtp", "qcom,msm8953", "qcom,mtp";
 	qcom,board-id= <8 1>;
+	qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
 };
 
+&int_codec {
+	status = "disabled";
+};
+
+&pmic_analog_codec {
+	status = "disabled";
+};
+
+&wsa881x_i2c_f {
+	status = "disabled";
+};
+
+&wsa881x_i2c_45 {
+	status = "disabled";
+};
+
+&cdc_pri_mi2s_gpios {
+	status = "disabled";
+};
+
+&wsa881x_analog_vi_gpio {
+	status = "disabled";
+};
+
+&wsa881x_analog_clk_gpio {
+	status = "disabled";
+};
+
+&wsa881x_analog_reset_gpio {
+	status = "disabled";
+};
+
+&cdc_comp_gpios {
+	status = "disabled";
+};
+
+&slim_msm {
+	status = "okay";
+};
+
+&dai_slim {
+	status = "okay";
+};
+
+&wcd9xxx_intc {
+	status = "okay";
+};
+
+&clock_audio {
+	status = "okay";
+};
+
+&wcd9335 {
+	status = "okay";
+};
+
+&cdc_us_euro_sw {
+	status = "okay";
+};
+
+&cdc_quin_mi2s_gpios {
+	status = "okay";
+};
+
+&wcd_rst_gpio {
+	status = "okay";
+};
+
+&ext_codec {
+	qcom,model = "msm8953-tasha-snd-card";
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts
index e3a5b4a..b80583e 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts
@@ -25,75 +25,3 @@
 	qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
 };
 
-&int_codec {
-	status = "disabled";
-};
-
-&pmic_analog_codec {
-	status = "disabled";
-};
-
-&wsa881x_i2c_f {
-	status = "disabled";
-};
-
-&wsa881x_i2c_45 {
-	status = "disabled";
-};
-
-&cdc_pri_mi2s_gpios {
-	status = "disabled";
-};
-
-&wsa881x_analog_vi_gpio {
-	status = "disabled";
-};
-
-&wsa881x_analog_clk_gpio {
-	status = "disabled";
-};
-
-&wsa881x_analog_reset_gpio {
-	status = "disabled";
-};
-
-&cdc_comp_gpios {
-	status = "disabled";
-};
-
-&slim_msm {
-	status = "okay";
-};
-
-&dai_slim {
-	status = "okay";
-};
-
-&wcd9xxx_intc {
-	status = "okay";
-};
-
-&clock_audio {
-	status = "okay";
-};
-
-&wcd9335 {
-	status = "okay";
-};
-
-&cdc_us_euro_sw {
-	status = "okay";
-};
-
-&cdc_quin_mi2s_gpios {
-	status = "okay";
-};
-
-&wcd_rst_gpio {
-	status = "okay";
-};
-
-&ext_codec {
-	qcom,model = "msm8953-tasha-snd-card";
-	status = "okay";
-};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-ipc.dtsi b/arch/arm64/boot/dts/qcom/msm8953-ipc.dtsi
index b62d12d..0e635d4 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-ipc.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-ipc.dtsi
@@ -18,3 +18,61 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart_console_active>;
 };
+
+&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";
+};
+
+&sdhc_2 {
+	/* device core power supply */
+	vdd-supply = <&pm8953_l11>;
+	qcom,vdd-voltage-level = <2950000 2950000>;
+	qcom,vdd-current-level = <15000 800000>;
+
+	/* device communication power supply */
+	vdd-io-supply = <&pm8953_l12>;
+	qcom,vdd-io-voltage-level = <1800000 2950000>;
+	qcom,vdd-io-current-level = <200 22000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_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 133 0>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&tlmm 133 0x1>;
+
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+								200000000>;
+	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+	status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
index c6bc2b9..f7671dc 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
@@ -24,6 +24,7 @@
 #include "dsi-panel-lt8912-480p-video.dtsi"
 #include "dsi-panel-lt8912-1080p-video.dtsi"
 #include "dsi-panel-hx8399c-fhd-plus-video.dtsi"
+#include "dsi-panel-hx83100a-800p-video.dtsi"
 
 &soc {
 	dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -118,7 +119,7 @@
 	qcom,mdss-dsi-panel-on-check-value = <0x9d 0x9d 0x9d 0x9d>;
 	qcom,mdss-dsi-panel-status-read-length = <4>;
 	qcom,mdss-dsi-panel-max-error-count = <3>;
-	qcom,mdss-dsi-min-refresh-rate = <55>;
+	qcom,mdss-dsi-min-refresh-rate = <48>;
 	qcom,mdss-dsi-max-refresh-rate = <60>;
 	qcom,mdss-dsi-pan-enable-dynamic-fps;
 	qcom,mdss-dsi-pan-fps-update =
@@ -148,3 +149,11 @@
 		24 1f 08 09 05 03 04 a0
 		24 1c 08 09 05 03 04 a0];
 };
+
+&dsi_boyi_hx83100a_800p_video {
+	qcom,mdss-dsi-panel-timings-phy-v2 = [1f 1c 05 06 03 03 04 a0
+		1f 1c 05 06 03 03 04 a0
+		1f 1c 05 06 03 03 04 a0
+		1f 1c 05 06 03 03 04 a0
+		1f 10 05 06 03 03 04 a0];
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
index a3bd5e9..cc4bc7f 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
@@ -41,6 +41,7 @@
 		qcom,nq-ven = <&tlmm 16 0x00>;
 		qcom,nq-firm = <&tlmm 62 0x00>;
 		qcom,nq-clkreq = <&pm8953_gpios 2 0x00>;
+		qcom,nq-esepwr = <&tlmm 141 0x00>;
 		interrupt-parent = <&tlmm>;
 		qcom,clk-src = "BBCLK2";
 		interrupts = <17 0>;
@@ -208,4 +209,8 @@
 	case-therm-step {
 		status = "disabled";
 	};
+
+	quiet-therm-step {
+		status = "disabled";
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
index 15be898..cc3c392 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
@@ -425,6 +425,19 @@
 					bias-pull-down; /* pull down */
 				};
 			};
+			mdss_dsi_gpio: mdss_dsi_gpio {
+				mux {
+					pins = "gpio141";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio141";
+					drive-strength = <8>;
+					bias-pull-down;
+					output-low;
+				};
+			};
 		};
 
 		pmx_mdss_te {
@@ -453,6 +466,87 @@
 			};
 		};
 
+		cdc_dmic0_clk_act: cdc_dmic0_clk_act_default {
+				mux {
+						pins = "gpio89";
+						function = "dmic0_clk";
+				};
+
+				config {
+						pins = "gpio89";
+						drive-strength = <8>;
+				};
+			};
+
+		cdc_dmic0_clk_sus: cdc_dmic0_clk_sus_sleep {
+				mux {
+						pins = "gpio89";
+						function = "gpio";
+				};
+
+				config {
+						pins = "gpio89";
+						drive-strength = <2>;
+						bias-disable;
+				};
+		};
+
+		cdc_dmic0_data_act: cdc_dmic0_data_act_default {
+				mux {
+						pins = "gpio90";
+						function = "dmic0_data";
+				};
+
+				config {
+						pins = "gpio90";
+						drive-strength = <8>;
+				};
+		};
+
+		cdc_dmic0_data_sus: cdc_dmic0_data_sus_sleep {
+				mux {
+						pins = "gpio90";
+						function = "gpio";
+				};
+
+				config {
+						pins = "gpio90";
+						drive-strength = <2>;
+						bias-disable;
+				};
+		};
+
+		sec-tlmm-lines {
+			sec_tlmm_lines_act: sec_tlmm_lines_act {
+				mux {
+					pins = "gpio135", "gpio136",
+					       "gpio137", "gpio138";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio135", "gpio136",
+					       "gpio137", "gpio138";
+					drive-strength = <8>;
+				};
+			};
+
+			sec_tlmm_lines_sus: sec_tlmm_lines_sus {
+				mux {
+					pins = "gpio135", "gpio136",
+					       "gpio137", "gpio138";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio135", "gpio136",
+					       "gpio137", "gpio138";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
 		hsuart_active: default {
 			mux {
 				pins = "gpio12", "gpio13", "gpio14", "gpio15";
@@ -643,6 +737,32 @@
 			};
 		};
 
+		i2c_1 {
+			i2c_1_active: i2c_1_active {
+				mux {
+					pins = "gpio2", "gpio3";
+					function = "blsp_i2c1";
+				};
+				config {
+					pins = "gpio2", "gpio3";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+
+			i2c_1_sleep: i2c_1_sleep {
+				mux {
+					pins = "gpio2", "gpio3";
+					function = "blsp_i2c1";
+				};
+				config {
+					pins = "gpio2", "gpio3";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
 		i2c_2 {
 			i2c_2_active: i2c_2_active {
 				/* active state */
@@ -733,39 +853,67 @@
 			};
 		};
 
-		pmx_rd_nfc_int {
-			/*qcom,pins = <&gp 17>;*/
-			pins = "gpio17";
-			qcom,pin-func = <0>;
-			qcom,num-grp-pins = <1>;
-			label = "pmx_nfc_int";
+		nfc {
+			nfc_int_active: nfc_int_active {
+				/* active state */
+				mux {
+					/* GPIO 17 NFC Read Interrupt */
+					pins = "gpio17";
+					function = "gpio";
+				};
 
-			nfc_int_active: active {
-				drive-strength = <6>;
-				bias-pull-up;
+				config {
+					pins = "gpio17";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-up;
+				};
 			};
 
-			nfc_int_suspend: suspend {
-				drive-strength = <6>;
-				bias-pull-up;
-			};
-		};
+			nfc_int_suspend: nfc_int_suspend {
+				/* sleep state */
+				mux {
+					/* GPIO 17 NFC Read Interrupt */
+					pins = "gpio17";
+					function = "gpio";
+				};
 
-		pmx_nfc_reset {
-			/*qcom,pins = <&gp 16>;*/
-			pins = "gpio16";
-			qcom,pin-func = <0>;
-			qcom,num-grp-pins = <1>;
-			label = "pmx_nfc_disable";
-
-			nfc_disable_active: active {
-				drive-strength = <6>;
-				bias-pull-up;
+				config {
+					pins = "gpio17";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-up;
+				};
 			};
 
-			nfc_disable_suspend: suspend {
-				drive-strength = <6>;
-				bias-disable;
+			nfc_disable_active: nfc_disable_active {
+				/* active state */
+				mux {
+					/* 16: NFC ENABLE 62: FW DNLD */
+					/* 141: ESE Enable */
+					pins = "gpio16", "gpio62", "gpio141";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio16", "gpio62", "gpio141";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-up;
+				};
+			};
+
+			nfc_disable_suspend: nfc_disable_suspend {
+				/* sleep state */
+				mux {
+					/* 16: NFC ENABLE 62: FW DNLD */
+					/* 141: ESE Enable */
+					pins = "gpio16", "gpio62", "gpio141";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio16", "gpio62", "gpio141";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable;
+				};
 			};
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/msm8953-qrd.dtsi b/arch/arm64/boot/dts/qcom/msm8953-qrd.dtsi
index 253e87e..1f0ad88 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-qrd.dtsi
@@ -69,6 +69,7 @@
 		qcom,nq-ven = <&tlmm 16 0x00>;
 		qcom,nq-firm = <&tlmm 62 0x00>;
 		qcom,nq-clkreq = <&pm8953_gpios 2 0x00>;
+		qcom,nq-esepwr = <&tlmm 141 0x00>;
 		interrupt-parent = <&tlmm>;
 		qcom,clk-src = "BBCLK2";
 		interrupts = <17 0>;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-thermal.dtsi b/arch/arm64/boot/dts/qcom/msm8953-thermal.dtsi
index 54634ce..d84898d 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-thermal.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-thermal.dtsi
@@ -360,7 +360,7 @@
 		thermal-governor = "step_wise";
 		trips {
 			pop_trip: pop-trip {
-				temperature = <70000>;
+				temperature = <95000>;
 				hysteresis = <0>;
 				type = "passive";
 			};
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index 50ee0e8..64e7664 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -161,6 +161,7 @@
 		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;
 		i2c5 = &i2c_5;
@@ -349,11 +350,6 @@
 		compatible = "qcom,mem-dump";
 		memory-region = <&dump_mem>;
 
-		rpmh_dump {
-			qcom,dump-size = <0x2000000>;
-			qcom,dump-id = <0xec>;
-		};
-
 		fcm_dump {
 			qcom,dump-size = <0x8400>;
 			qcom,dump-id = <0xee>;
@@ -649,6 +645,30 @@
 		qcom,master-id = <86>;
 		status = "disabled";
 	};
+	i2c_1: i2c@78b5000 { /* BLSP1 QUP1 */
+		compatible = "qcom,i2c-msm-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0x78b5000 0x600>;
+		interrupt-names = "qup_irq";
+		interrupts = <0 95 0>;
+		qcom,master-id = <86>;
+		qcom,clk-freq-out = <100000>;
+		qcom,clk-freq-in  = <19200000>;
+		clock-names = "iface_clk", "core_clk";
+		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+				 <&clock_gcc clk_gcc_blsp1_qup1_i2c_apps_clk>;
+		pinctrl-names = "i2c_active", "i2c_sleep";
+		pinctrl-0 = <&i2c_1_active>;
+		pinctrl-1 = <&i2c_1_sleep>;
+		qcom,noise-rjct-scl = <0>;
+		qcom,noise-rjct-sda = <0>;
+		dmas = <&dma_blsp1 4 64 0x20000020 0x20>,
+			<&dma_blsp1 5 32 0x20000020 0x20>;
+		dma-names = "tx", "rx";
+		status = "disabled";
+	};
 
 	i2c_2: i2c@78b6000 { /* BLSP1 QUP2 */
 		compatible = "qcom,i2c-msm-v2";
diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi
index fa10500..e8a82aa 100644
--- a/arch/arm64/boot/dts/qcom/pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660.dtsi
@@ -32,7 +32,7 @@
 			reg = <0x900 0x100>;
 		};
 
-		qcom,power-on@800 {
+		pm660_pon: qcom,power-on@800 {
 			compatible = "qcom,qpnp-power-on";
 			reg = <0x800 0x100>;
 			interrupts = <0x0 0x8 0x0 IRQ_TYPE_NONE>,
@@ -349,6 +349,12 @@
 			};
 		};
 
+		pm660_pbs: qcom,pbs@7400 {
+			compatible = "qcom,qpnp-pbs";
+			reg = <0x7400 0x100>;
+			status = "disabled";
+		};
+
 		bcl_sensor: bcl@4200 {
 			compatible = "qcom,msm-bcl-lmh";
 			reg = <0x4200 0xff>,
diff --git a/arch/arm64/boot/dts/qcom/pmi632.dtsi b/arch/arm64/boot/dts/qcom/pmi632.dtsi
index bdd69e2..b8f8b68 100644
--- a/arch/arm64/boot/dts/qcom/pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi632.dtsi
@@ -29,7 +29,9 @@
 		pmi632_pon: qcom,power-on@800 {
 			compatible = "qcom,qpnp-power-on";
 			reg = <0x800 0x100>;
+
 			qcom,secondary-pon-reset;
+			qcom,s3-src = "kpdpwr";
 		};
 
 		pmi632_vadc: vadc@3100 {
@@ -225,6 +227,33 @@
 			};
 		};
 
+		pmi632_adc_tm: vadc@3500 {
+			compatible = "qcom,qpnp-adc-tm-hc";
+			reg = <0x3500 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0x2 0x35 0x0 IRQ_TYPE_EDGE_RISING>;
+			interrupt-names = "eoc-int-en-set";
+			qcom,adc-vdd-reference = <1875>;
+			qcom,adc-full-scale-code = <0x70e4>;
+			qcom,adc_tm-vadc = <&pmi632_vadc>;
+			qcom,decimation = <0>;
+			qcom,fast-avg-setup = <0>;
+			#thermal-sensor-cells = <1>;
+
+			chan@53 {
+				label = "quiet_therm";
+				reg = <0x53>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <2>;
+				qcom,hw-settle-time = <0>;
+				qcom,btm-channel-number = <0x60>;
+				qcom,thermal-node;
+			};
+
+		};
+
 		pmi632_tz: qcom,temp-alarm@2400 {
 			compatible = "qcom,qpnp-temp-alarm";
 			reg = <0x2400 0x100>;
@@ -437,9 +466,6 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 
-			qcom,vbatt-empty-mv = <3300>;
-			qcom,vbatt-low-mv = <3500>;
-			qcom,vbatt-cutoff-mv = <3400>;
 			qcom,qg-iterm-ma = <100>;
 			qcom,hold-soc-while-full;
 			qcom,linearize-soc;
@@ -449,11 +475,12 @@
 			qcom,qgauge@4800 {
 				status = "okay";
 				reg = <0x4800 0x100>;
-				interrupts = <0x2 0x48 0x0 IRQ_TYPE_EDGE_BOTH>,
-					     <0x2 0x48 0x1 IRQ_TYPE_EDGE_BOTH>,
-					     <0x2 0x48 0x2 IRQ_TYPE_EDGE_BOTH>,
-					     <0x2 0x48 0x3 IRQ_TYPE_EDGE_BOTH>,
-					     <0x2 0x48 0x4 IRQ_TYPE_EDGE_BOTH>;
+				interrupts =
+					<0x2 0x48 0x0 IRQ_TYPE_EDGE_BOTH>,
+					<0x2 0x48 0x1 IRQ_TYPE_EDGE_BOTH>,
+					<0x2 0x48 0x2 IRQ_TYPE_EDGE_RISING>,
+					<0x2 0x48 0x3 IRQ_TYPE_EDGE_RISING>,
+					<0x2 0x48 0x4 IRQ_TYPE_EDGE_RISING>;
 				interrupt-names = "qg-batt-missing",
 						  "qg-vbat-low",
 						  "qg-vbat-empty",
@@ -657,14 +684,14 @@
 
 &thermal_zones {
 	pmi-ibat-lvl0 {
-		polling-delay-passive = <0>;
+		polling-delay-passive = <100>;
 		polling-delay = <0>;
 		thermal-governor = "step_wise";
 		thermal-sensors = <&bcl_sensor 0>;
 
 		trips {
-			pmi632_ibat:ibat-lvl0 {
-				temperature = <3500>;
+			pmi632_ibat_lvl0: ibat-lvl0 {
+				temperature = <4000>;
 				hysteresis = <200>;
 				type = "passive";
 			};
@@ -679,7 +706,7 @@
 
 		trips {
 			ibat-lvl1 {
-				temperature = <4000>;
+				temperature = <4200>;
 				hysteresis = <200>;
 				type = "passive";
 			};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi b/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
index aa316ba..63bb25f 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
@@ -166,6 +166,10 @@
 	qcom,battery-data = <&qcs_batterydata>;
 };
 
+&pm660_charger {
+	qcom,battery-data = <&qcs_batterydata>;
+};
+
 &int_codec {
 	qcom,model = "sdm670-360cam-snd-card";
 	qcom,audio-routing =
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-audio-overlay.dtsi
new file mode 100644
index 0000000..e80c1c4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-audio-overlay.dtsi
@@ -0,0 +1,130 @@
+/*
+ * 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 "sdm670-lpi.dtsi"
+
+&int_codec {
+	compatible = "qcom,qcs605-dig-asoc-snd";
+	qcom,model = "qcs605-lc-snd-card";
+	qcom,audio-routing =
+		"RX_BIAS", "INT_MCLK0",
+		"SPK_RX_BIAS", "INT_MCLK0",
+		"TX_I2S_CLK", "INT_MCLK0",
+		"DMIC1", "DIGITAL_REGULATOR",
+		"DIGITAL_REGULATOR", "Digital Mic1",
+		"DMIC2", "DIGITAL_REGULATOR",
+		"DIGITAL_REGULATOR", "Digital Mic2",
+		"DMIC3", "DIGITAL_REGULATOR",
+		"DIGITAL_REGULATOR", "Digital Mic3",
+		"DMIC4", "DIGITAL_REGULATOR",
+		"DIGITAL_REGULATOR", "Digital Mic4",
+		"SpkrLeft IN", "SPK1 OUT",
+		"SpkrRight IN", "SPK2 OUT";
+
+	qcom,msm-mi2s-master = <1>, <1>, <1>, <1>, <1>;
+	qcom,msm-mclk-freq = <9600000>;
+	qcom,cdc-dmic-gpios = <&cdc_dmic_gpios>;
+
+	asoc-codec = <&stub_codec>, <&msm_digital_codec>,
+		     <&msm_sdw_codec>;
+	asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+			   "msm_sdw_codec";
+
+	qcom,wsa-max-devs = <2>;
+	qcom,wsa-devs = <&wsa881x_211_en>, <&wsa881x_212_en>,
+			<&wsa881x_213_en>, <&wsa881x_214_en>;
+	qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+				  "SpkrLeft", "SpkrRight";
+};
+
+&soc {
+	msm_digital_codec: msm-dig-codec {
+		compatible = "qcom,msm-digital-codec";
+		reg = <0x62ec0000 0x0>;
+		qcom,no-analog-codec;
+
+		cdc-vdd-digital-supply = <&pm660_l13>;
+		qcom,cdc-vdd-digital-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-digital-current = <5000>;
+		qcom,cdc-on-demand-supplies = "cdc-vdd-digital";
+	};
+
+	cdc_dmic_gpios: cdc_dmic_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_dmic12_gpios_active
+			     &cdc_dmic34_gpios_active>;
+		pinctrl-1 = <&cdc_dmic12_gpios_sleep
+			     &cdc_dmic34_gpios_sleep>;
+		qcom,lpi-gpios;
+	};
+
+	cdc_sdw_gpios: sdw_clk_data_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&sdw_clk_active &sdw_data_active>;
+		pinctrl-1 = <&sdw_clk_sleep &sdw_data_sleep>;
+	};
+
+	wsa_spkr_en1: wsa_spkr_en1_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&spkr_1_sd_n_active>;
+		pinctrl-1 = <&spkr_1_sd_n_sleep>;
+	};
+
+	wsa_spkr_en2: wsa_spkr_en2_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&spkr_2_sd_n_active>;
+		pinctrl-1 = <&spkr_2_sd_n_sleep>;
+	};
+
+	msm_sdw_codec: msm-sdw-codec@62ec1000 {
+		status = "okay";
+		compatible = "qcom,msm-sdw-codec";
+		reg = <0x62ec1000 0x0>;
+		interrupts = <0 88 0>;
+		interrupt-names = "swr_master_irq";
+		qcom,cdc-sdw-gpios = <&cdc_sdw_gpios>;
+
+		swr_master {
+			compatible = "qcom,swr-wcd";
+			#address-cells = <2>;
+			#size-cells = <0>;
+
+			wsa881x_211_en: wsa881x_en@20170211 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x20170211>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_en1>;
+			};
+
+			wsa881x_212_en: wsa881x_en@20170212 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x20170212>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_en2>;
+			};
+
+			wsa881x_213_en: wsa881x_en@21170213 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x21170213>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_en1>;
+			};
+
+			wsa881x_214_en: wsa881x_en@21170214 {
+				compatible = "qcom,wsa881x";
+				reg = <0x0 0x21170214>;
+				qcom,spkr-sd-n-node = <&wsa_spkr_en2>;
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-mtp-overlay.dts
index e27baba..6dfb21b 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-mtp-overlay.dts
@@ -1,5 +1,5 @@
 /*
- * 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
@@ -21,6 +21,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 #include "qcs605-lc-mtp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 MTP";
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dts
index 3ca53b7..252d267 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dts
@@ -16,6 +16,7 @@
 
 #include "qcs605-lc.dtsi"
 #include "qcs605-lc-mtp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 MTP";
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
index 192bf42..15b23de 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
@@ -365,3 +365,7 @@
 	vdd-supply = <&pm660_l6>;  /* 0.88v */
 	core-supply = <&pm660_l2>; /* 1.2v */
 };
+
+&int_codec {
+	/delete-property/ qcom,ext-disp-audio-rx;
+};
diff --git a/arch/arm64/boot/dts/qcom/qg-batterydata-ascent-3450mah.dtsi b/arch/arm64/boot/dts/qcom/qg-batterydata-ascent-3450mah.dtsi
index 4d35628..f28f19e2 100644
--- a/arch/arm64/boot/dts/qcom/qg-batterydata-ascent-3450mah.dtsi
+++ b/arch/arm64/boot/dts/qcom/qg-batterydata-ascent-3450mah.dtsi
@@ -32,14 +32,19 @@
 				4201000  4300000  2760000
 				4301000  4350000  2070000>;
 
+	/* COOL = 5 DegC, WARM = 40 DegC */
+	qcom,jeita-soft-thresholds = <0x44bd 0x1fc4>;
+	/* COLD = 0 DegC, HOT = 45 DegC */
+	qcom,jeita-hard-thresholds = <0x4aa5 0x1bfb>;
+
 	qcom,fcc1-temp-lut {
 		qcom,lut-col-legend = <0 10 25 40 50>;
 		qcom,lut-data = <3377 3428 3481 3496 3500>;
 	};
 
 	qcom,fcc2-temp-lut {
-		qcom,lut-col-legend = <(-20) (-10) 0 10 25 40 50>;
-		qcom,lut-data = <3474 3480 3482 3476 3492 3478 3466>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-data = <3480 3482 3476 3492 3478 3466>;
 	};
 
 	qcom,pc-temp-v1-lut {
@@ -115,71 +120,73 @@
 	};
 
 	qcom,pc-temp-v2-lut {
-		qcom,lut-col-legend = <(-20) (-10) 0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000 8800>,
-			<8600 8400 8200 8000 7800 7600 7400>,
-			<7200 7000 6800 6600 6400 6200 6000>,
-			<5800 5600 5400 5200 5000 4800 4600>,
-			<4400 4200 4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200 2000 1800>,
-			<1600 1400 1200 1000 900 800 700>,
-			<600 500 400 300 200 100 0>;
-		qcom,lut-data = <43435 43425 43415 43385 43360 43315 43295>,
-			<43032 43070 43109 43097 43094 43052 43033>,
-			<42666 42748 42821 42826 42838 42799 42781>,
-			<42342 42462 42555 42571 42594 42557 42541>,
-			<42053 42208 42308 42333 42361 42326 42312>,
-			<41788 41968 42072 42101 42133 42099 42086>,
-			<41531 41736 41844 41872 41904 41872 41860>,
-			<41298 41516 41625 41649 41680 41649 41637>,
-			<41128 41303 41405 41431 41460 41430 41419>,
-			<41009 41100 41186 41217 41243 41215 41204>,
-			<40843 40896 40979 41012 41034 41005 40994>,
-			<40462 40694 40796 40826 40840 40802 40789>,
-			<40004 40482 40616 40642 40648 40604 40590>,
-			<39736 40220 40407 40432 40445 40411 40399>,
-			<39556 39903 40175 40199 40233 40222 40214>,
-			<39382 39636 39954 39996 40043 40042 40036>,
-			<39187 39443 39759 39844 39886 39877 39868>,
-			<39001 39272 39570 39700 39736 39717 39706>,
-			<38839 39091 39370 39511 39573 39556 39547>,
-			<38695 38908 39162 39283 39399 39396 39391>,
-			<38574 38742 38973 39072 39208 39217 39217>,
-			<38477 38591 38806 38886 38975 38988 38994>,
-			<38393 38460 38655 38721 38760 38766 38771>,
-			<38314 38358 38519 38585 38613 38613 38614>,
-			<38242 38274 38396 38468 38496 38494 38494>,
-			<38176 38201 38287 38362 38390 38388 38387>,
-			<38117 38138 38189 38265 38294 38291 38288>,
-			<38062 38080 38106 38177 38206 38202 38198>,
-			<38006 38027 38039 38096 38126 38120 38114>,
-			<37953 37980 37983 38021 38051 38044 38037>,
-			<37900 37934 37935 37954 37984 37976 37967>,
-			<37847 37889 37895 37891 37921 37915 37905>,
-			<37795 37843 37856 37838 37862 37856 37846>,
-			<37742 37795 37815 37799 37803 37790 37781>,
-			<37690 37746 37774 37768 37746 37720 37707>,
-			<37635 37692 37727 37728 37685 37643 37621>,
-			<37574 37633 37677 37677 37620 37554 37517>,
-			<37509 37568 37618 37617 37550 37465 37411>,
-			<37441 37491 37546 37548 37475 37387 37327>,
-			<37368 37404 37459 37466 37395 37313 37256>,
-			<37292 37310 37360 37369 37301 37226 37174>,
-			<37209 37206 37243 37246 37187 37117 37069>,
-			<37119 37103 37111 37106 37050 36988 36945>,
-			<37020 37005 36964 36946 36900 36839 36796>,
-			<36901 36909 36860 36837 36818 36761 36712>,
-			<36762 36808 36782 36769 36775 36718 36673>,
-			<36671 36746 36740 36732 36741 36690 36651>,
-			<36552 36670 36688 36684 36692 36649 36612>,
-			<36386 36553 36594 36591 36575 36542 36528>,
-			<36157 36329 36380 36368 36272 36271 36278>,
-			<35824 35961 35991 35957 35796 35833 35867>,
-			<35340 35436 35452 35401 35193 35271 35340>,
-			<34648 34709 34745 34680 34409 34550 34676>,
-			<33623 33672 33759 33677 33330 33585 33791>,
-			<31758 31857 32191 32244 31867 32001 32517>,
-			<27623 28160 28896 29014 27510 28586 29617>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <43425 43415 43385 43360 43315 43295>,
+			<43070 43109 43097 43094 43052 43033>,
+			<42748 42821 42826 42838 42799 42781>,
+			<42462 42555 42571 42594 42557 42541>,
+			<42208 42308 42333 42361 42326 42312>,
+			<41968 42072 42101 42133 42099 42086>,
+			<41736 41844 41872 41904 41872 41860>,
+			<41516 41625 41649 41680 41649 41637>,
+			<41303 41405 41431 41460 41430 41419>,
+			<41100 41186 41217 41243 41215 41204>,
+			<40896 40979 41012 41034 41005 40994>,
+			<40694 40796 40826 40840 40802 40789>,
+			<40482 40616 40642 40648 40604 40590>,
+			<40220 40407 40432 40445 40411 40399>,
+			<39903 40175 40199 40233 40222 40214>,
+			<39636 39954 39996 40043 40042 40036>,
+			<39443 39759 39844 39886 39877 39868>,
+			<39272 39570 39700 39736 39717 39706>,
+			<39091 39370 39511 39573 39556 39547>,
+			<38908 39162 39283 39399 39396 39391>,
+			<38742 38973 39072 39208 39217 39217>,
+			<38591 38806 38886 38975 38988 38994>,
+			<38460 38655 38721 38760 38766 38771>,
+			<38358 38519 38585 38613 38613 38614>,
+			<38274 38396 38468 38496 38494 38494>,
+			<38201 38287 38362 38390 38388 38387>,
+			<38138 38189 38265 38294 38291 38288>,
+			<38080 38106 38177 38206 38202 38198>,
+			<38027 38039 38096 38126 38120 38114>,
+			<37980 37983 38021 38051 38044 38037>,
+			<37934 37935 37954 37984 37976 37967>,
+			<37889 37895 37891 37921 37915 37905>,
+			<37843 37856 37838 37862 37856 37846>,
+			<37795 37815 37799 37803 37790 37781>,
+			<37746 37774 37768 37746 37720 37707>,
+			<37692 37727 37728 37685 37643 37621>,
+			<37633 37677 37677 37620 37554 37517>,
+			<37568 37618 37617 37550 37465 37411>,
+			<37491 37546 37548 37475 37387 37327>,
+			<37404 37459 37466 37395 37313 37256>,
+			<37310 37360 37369 37301 37226 37174>,
+			<37206 37243 37246 37187 37117 37069>,
+			<37103 37111 37106 37050 36988 36945>,
+			<37005 36964 36946 36900 36839 36796>,
+			<36909 36860 36837 36818 36761 36712>,
+			<36808 36782 36769 36775 36718 36673>,
+			<36746 36740 36732 36741 36690 36651>,
+			<36670 36688 36684 36692 36649 36612>,
+			<36553 36594 36591 36575 36542 36528>,
+			<36329 36380 36368 36272 36271 36278>,
+			<35961 35991 35957 35796 35833 35867>,
+			<35436 35452 35401 35193 35271 35340>,
+			<34709 34745 34680 34409 34550 34676>,
+			<33672 33759 33677 33330 33585 33791>,
+			<31857 32191 32244 31867 32001 32517>,
+			<28160 28896 29014 27510 28586 29617>;
 	};
 
 	qcom,pc-temp-z1-lut {
@@ -615,410 +622,422 @@
 	};
 
 	qcom,pc-temp-y1-lut {
-		qcom,lut-col-legend = <(-20) (-10) 0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000 8800>,
-			<8600 8400 8200 8000 7800 7600 7400>,
-			<7200 7000 6800 6600 6400 6200 6000>,
-			<5800 5600 5400 5200 5000 4800 4600>,
-			<4400 4200 4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200 2000 1800>,
-			<1600 1400 1200 1000 900 800 700>,
-			<600 500 400 300 200 100 0>;
-		qcom,lut-data = <7619 6963 6363 6007 5630 5512 5470>,
-			<7591 6945 6361 6003 5629 5510 5471>,
-			<7573 6934 6357 5999 5628 5508 5471>,
-			<7563 6929 6354 5995 5627 5506 5471>,
-			<7558 6928 6353 5992 5626 5505 5470>,
-			<7556 6928 6357 5988 5625 5503 5470>,
-			<7563 6934 6366 5985 5624 5502 5469>,
-			<7573 6942 6374 5981 5624 5501 5467>,
-			<7583 6939 6374 5982 5623 5500 5467>,
-			<7616 6920 6366 5984 5624 5499 5467>,
-			<7634 6910 6360 5985 5624 5498 5466>,
-			<7600 6919 6357 5980 5623 5498 5466>,
-			<7557 6931 6356 5973 5622 5498 5465>,
-			<7560 6935 6362 5973 5622 5499 5465>,
-			<7590 6938 6380 5978 5625 5500 5466>,
-			<7605 6939 6390 5981 5628 5501 5467>,
-			<7608 6942 6389 5985 5631 5501 5468>,
-			<7612 6946 6387 5990 5634 5502 5469>,
-			<7604 6943 6388 5989 5637 5503 5470>,
-			<7584 6932 6391 5988 5639 5506 5471>,
-			<7570 6929 6394 5987 5643 5508 5472>,
-			<7557 6957 6397 5989 5647 5510 5473>,
-			<7546 6985 6400 5994 5653 5513 5475>,
-			<7543 6976 6405 6001 5658 5515 5478>,
-			<7542 6942 6414 6012 5663 5518 5480>,
-			<7542 6928 6418 6018 5668 5522 5483>,
-			<7552 6934 6419 6019 5674 5525 5486>,
-			<7565 6942 6418 6020 5681 5529 5488>,
-			<7569 6951 6418 6021 5687 5533 5491>,
-			<7568 6972 6418 6023 5692 5537 5493>,
-			<7564 6978 6418 6025 5698 5541 5497>,
-			<7549 6971 6422 6028 5705 5545 5500>,
-			<7534 6961 6425 6032 5712 5550 5504>,
-			<7531 6947 6422 6038 5720 5554 5507>,
-			<7529 6929 6416 6048 5727 5559 5509>,
-			<7527 6925 6416 6055 5734 5563 5512>,
-			<7537 6932 6428 6059 5741 5569 5516>,
-			<7548 6939 6438 6062 5748 5575 5522>,
-			<7546 6939 6433 6063 5757 5580 5526>,
-			<7534 6942 6422 6064 5767 5585 5529>,
-			<7527 6944 6417 6067 5775 5591 5533>,
-			<7526 6946 6416 6077 5783 5596 5537>,
-			<7530 6941 6418 6083 5787 5603 5541>,
-			<7568 6923 6429 6090 5790 5610 5546>,
-			<7559 6953 6428 6086 5808 5622 5555>,
-			<7568 6932 6433 6091 5813 5631 5561>,
-			<7570 6928 6433 6099 5818 5635 5565>,
-			<7608 6933 6442 6113 5834 5640 5567>,
-			<7652 6932 6430 6105 5835 5645 5571>,
-			<7693 6936 6436 6106 5848 5654 5578>,
-			<7737 6965 6440 6099 5858 5666 5585>,
-			<7770 6990 6464 6110 5873 5684 5600>,
-			<7830 7027 6445 6123 5887 5704 5613>,
-			<7848 7064 6471 6136 5914 5726 5633>,
-			<7848 7064 6471 6136 5914 5726 5633>,
-			<7848 7064 6471 6136 5914 5726 5633>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <6963 6363 6007 5630 5512 5470>,
+			<6945 6361 6003 5629 5510 5471>,
+			<6934 6357 5999 5628 5508 5471>,
+			<6929 6354 5995 5627 5506 5471>,
+			<6928 6353 5992 5626 5505 5470>,
+			<6928 6357 5988 5625 5503 5470>,
+			<6934 6366 5985 5624 5502 5469>,
+			<6942 6374 5981 5624 5501 5467>,
+			<6939 6374 5982 5623 5500 5467>,
+			<6920 6366 5984 5624 5499 5467>,
+			<6910 6360 5985 5624 5498 5466>,
+			<6919 6357 5980 5623 5498 5466>,
+			<6931 6356 5973 5622 5498 5465>,
+			<6935 6362 5973 5622 5499 5465>,
+			<6938 6380 5978 5625 5500 5466>,
+			<6939 6390 5981 5628 5501 5467>,
+			<6942 6389 5985 5631 5501 5468>,
+			<6946 6387 5990 5634 5502 5469>,
+			<6943 6388 5989 5637 5503 5470>,
+			<6932 6391 5988 5639 5506 5471>,
+			<6929 6394 5987 5643 5508 5472>,
+			<6957 6397 5989 5647 5510 5473>,
+			<6985 6400 5994 5653 5513 5475>,
+			<6976 6405 6001 5658 5515 5478>,
+			<6942 6414 6012 5663 5518 5480>,
+			<6928 6418 6018 5668 5522 5483>,
+			<6934 6419 6019 5674 5525 5486>,
+			<6942 6418 6020 5681 5529 5488>,
+			<6951 6418 6021 5687 5533 5491>,
+			<6972 6418 6023 5692 5537 5493>,
+			<6978 6418 6025 5698 5541 5497>,
+			<6971 6422 6028 5705 5545 5500>,
+			<6961 6425 6032 5712 5550 5504>,
+			<6947 6422 6038 5720 5554 5507>,
+			<6929 6416 6048 5727 5559 5509>,
+			<6925 6416 6055 5734 5563 5512>,
+			<6932 6428 6059 5741 5569 5516>,
+			<6939 6438 6062 5748 5575 5522>,
+			<6939 6433 6063 5757 5580 5526>,
+			<6942 6422 6064 5767 5585 5529>,
+			<6944 6417 6067 5775 5591 5533>,
+			<6946 6416 6077 5783 5596 5537>,
+			<6941 6418 6083 5787 5603 5541>,
+			<6923 6429 6090 5790 5610 5546>,
+			<6953 6428 6086 5808 5622 5555>,
+			<6932 6433 6091 5813 5631 5561>,
+			<6928 6433 6099 5818 5635 5565>,
+			<6933 6442 6113 5834 5640 5567>,
+			<6932 6430 6105 5835 5645 5571>,
+			<6936 6436 6106 5848 5654 5578>,
+			<6965 6440 6099 5858 5666 5585>,
+			<6990 6464 6110 5873 5684 5600>,
+			<7027 6445 6123 5887 5704 5613>,
+			<7064 6471 6136 5914 5726 5633>,
+			<7064 6471 6136 5914 5726 5633>,
+			<7064 6471 6136 5914 5726 5633>;
 	};
 
 	qcom,pc-temp-y2-lut {
-		qcom,lut-col-legend = <(-20) (-10) 0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000 8800>,
-			<8600 8400 8200 8000 7800 7600 7400>,
-			<7200 7000 6800 6600 6400 6200 6000>,
-			<5800 5600 5400 5200 5000 4800 4600>,
-			<4400 4200 4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200 2000 1800>,
-			<1600 1400 1200 1000 900 800 700>,
-			<600 500 400 300 200 100 0>;
-		qcom,lut-data = <9652 9643 10780 11037 11216 11097 11009>,
-			<9653 9653 10747 10993 11177 11076 11016>,
-			<9654 9867 10710 10945 11129 11053 11018>,
-			<9655 10082 10673 10898 11080 11031 11018>,
-			<9655 10246 10642 10860 11037 11010 11015>,
-			<9655 10308 10624 10837 11007 10992 11010>,
-			<9655 10281 10616 10826 10987 10977 10981>,
-			<9655 10241 10610 10820 10968 10962 10937>,
-			<9655 10275 10600 10816 10953 10942 10920>,
-			<9655 10440 10586 10802 10939 10913 10908>,
-			<9655 10531 10580 10792 10927 10894 10901>,
-			<9654 10522 10610 10786 10915 10881 10897>,
-			<9654 10502 10665 10780 10900 10869 10890>,
-			<9653 10430 10721 10797 10878 10869 10877>,
-			<9653 10226 10789 10873 10846 10876 10849>,
-			<9653 10115 10817 10940 10834 10878 10831>,
-			<9653 9949 10805 10988 10876 10871 10840>,
-			<9653 9749 10791 11021 10939 10863 10860>,
-			<9653 9704 10791 11014 10991 10869 10866>,
-			<9653 9683 10795 10979 11041 10898 10870>,
-			<9653 9677 10801 10965 11063 10936 10877>,
-			<9653 9676 10808 10997 11078 11004 10940>,
-			<9653 9676 10820 11042 11093 11066 11026>,
-			<9652 9674 10836 11062 11099 11074 11055>,
-			<9652 9670 10861 11077 11105 11063 11066>,
-			<9652 9667 10915 11082 11111 11064 11068>,
-			<9652 9665 11341 11085 11126 11092 11072>,
-			<9652 9663 11748 11091 11149 11125 11083>,
-			<9652 9661 11516 11099 11179 11148 11096>,
-			<9652 9659 10816 11110 11217 11174 11118>,
-			<9652 9658 10376 11118 11236 11190 11131>,
-			<9652 9657 10155 11117 11245 11208 11140>,
-			<9652 9656 10000 11109 11252 11224 11152>,
-			<9652 9655 9892 11094 11259 11233 11175>,
-			<9652 9654 9812 11060 11260 11250 11208>,
-			<9652 9654 9762 11020 11250 11255 11218>,
-			<9652 9653 9725 10915 11227 11244 11186>,
-			<9652 9653 9701 10784 11207 11227 11146>,
-			<9652 9653 9688 10695 11192 11211 11135>,
-			<9651 9652 9678 10615 11172 11194 11131>,
-			<9651 9652 9671 10480 11143 11192 11126>,
-			<9651 9652 9665 10201 11106 11216 11112>,
-			<9651 9651 9661 10108 11076 11220 11105>,
-			<9651 9651 9658 10159 11042 11183 11120>,
-			<9650 9651 9656 9965 10929 11157 11073>,
-			<9650 9651 9654 9856 10889 11090 11023>,
-			<9650 9651 9653 9796 10823 11057 10968>,
-			<9649 9650 9653 9741 10794 11051 10955>,
-			<9649 9650 9652 9696 10740 11029 10918>,
-			<9649 9650 9652 9680 10652 10968 10907>,
-			<9648 9650 9651 9670 10540 10916 10868>,
-			<9648 9649 9651 9663 10397 10801 10776>,
-			<9647 9648 9650 9657 10262 10712 10696>,
-			<9647 9648 9650 9654 10448 10584 10596>,
-			<9647 9648 9650 9654 10448 10584 10596>,
-			<9647 9648 9650 9654 10448 10584 10596>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <9643 10780 11037 11216 11097 11009>,
+			<9653 10747 10993 11177 11076 11016>,
+			<9867 10710 10945 11129 11053 11018>,
+			<10082 10673 10898 11080 11031 11018>,
+			<10246 10642 10860 11037 11010 11015>,
+			<10308 10624 10837 11007 10992 11010>,
+			<10281 10616 10826 10987 10977 10981>,
+			<10241 10610 10820 10968 10962 10937>,
+			<10275 10600 10816 10953 10942 10920>,
+			<10440 10586 10802 10939 10913 10908>,
+			<10531 10580 10792 10927 10894 10901>,
+			<10522 10610 10786 10915 10881 10897>,
+			<10502 10665 10780 10900 10869 10890>,
+			<10430 10721 10797 10878 10869 10877>,
+			<10226 10789 10873 10846 10876 10849>,
+			<10115 10817 10940 10834 10878 10831>,
+			<9949 10805 10988 10876 10871 10840>,
+			<9749 10791 11021 10939 10863 10860>,
+			<9704 10791 11014 10991 10869 10866>,
+			<9683 10795 10979 11041 10898 10870>,
+			<9677 10801 10965 11063 10936 10877>,
+			<9676 10808 10997 11078 11004 10940>,
+			<9676 10820 11042 11093 11066 11026>,
+			<9674 10836 11062 11099 11074 11055>,
+			<9670 10861 11077 11105 11063 11066>,
+			<9667 10915 11082 11111 11064 11068>,
+			<9665 11341 11085 11126 11092 11072>,
+			<9663 11748 11091 11149 11125 11083>,
+			<9661 11516 11099 11179 11148 11096>,
+			<9659 10816 11110 11217 11174 11118>,
+			<9658 10376 11118 11236 11190 11131>,
+			<9657 10155 11117 11245 11208 11140>,
+			<9656 10000 11109 11252 11224 11152>,
+			<9655 9892 11094 11259 11233 11175>,
+			<9654 9812 11060 11260 11250 11208>,
+			<9654 9762 11020 11250 11255 11218>,
+			<9653 9725 10915 11227 11244 11186>,
+			<9653 9701 10784 11207 11227 11146>,
+			<9653 9688 10695 11192 11211 11135>,
+			<9652 9678 10615 11172 11194 11131>,
+			<9652 9671 10480 11143 11192 11126>,
+			<9652 9665 10201 11106 11216 11112>,
+			<9651 9661 10108 11076 11220 11105>,
+			<9651 9658 10159 11042 11183 11120>,
+			<9651 9656 9965 10929 11157 11073>,
+			<9651 9654 9856 10889 11090 11023>,
+			<9651 9653 9796 10823 11057 10968>,
+			<9650 9653 9741 10794 11051 10955>,
+			<9650 9652 9696 10740 11029 10918>,
+			<9650 9652 9680 10652 10968 10907>,
+			<9650 9651 9670 10540 10916 10868>,
+			<9649 9651 9663 10397 10801 10776>,
+			<9648 9650 9657 10262 10712 10696>,
+			<9648 9650 9654 10448 10584 10596>,
+			<9648 9650 9654 10448 10584 10596>,
+			<9648 9650 9654 10448 10584 10596>;
 	};
 
 	qcom,pc-temp-y3-lut {
-		qcom,lut-col-legend = <(-20) (-10) 0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000 8800>,
-			<8600 8400 8200 8000 7800 7600 7400>,
-			<7200 7000 6800 6600 6400 6200 6000>,
-			<5800 5600 5400 5200 5000 4800 4600>,
-			<4400 4200 4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200 2000 1800>,
-			<1600 1400 1200 1000 900 800 700>,
-			<600 500 400 300 200 100 0>;
-		qcom,lut-data = <14249 13491 13351 13296 13276 13275 13272>,
-			<14289 13481 13348 13297 13278 13275 13272>,
-			<14293 13476 13346 13298 13280 13275 13273>,
-			<14269 13476 13347 13300 13282 13276 13274>,
-			<14223 13480 13349 13302 13283 13276 13274>,
-			<14165 13486 13352 13303 13283 13276 13275>,
-			<14057 13513 13358 13303 13283 13276 13275>,
-			<13951 13546 13363 13304 13283 13276 13275>,
-			<13946 13543 13365 13306 13283 13277 13275>,
-			<13996 13505 13365 13310 13284 13278 13275>,
-			<14024 13476 13366 13315 13285 13278 13276>,
-			<13979 13465 13371 13319 13285 13278 13276>,
-			<13920 13456 13377 13322 13285 13278 13276>,
-			<13916 13446 13376 13322 13286 13278 13276>,
-			<13935 13434 13369 13321 13288 13279 13277>,
-			<13956 13428 13363 13320 13290 13279 13277>,
-			<13974 13428 13359 13318 13291 13280 13278>,
-			<13993 13428 13354 13316 13292 13282 13278>,
-			<14013 13414 13349 13313 13292 13283 13279>,
-			<14037 13377 13343 13308 13291 13283 13281>,
-			<14068 13356 13338 13304 13290 13284 13281>,
-			<14115 13351 13336 13301 13286 13280 13278>,
-			<14171 13349 13333 13299 13283 13276 13274>,
-			<14221 13354 13323 13298 13282 13275 13273>,
-			<14271 13374 13301 13297 13281 13275 13273>,
-			<14325 13397 13289 13297 13281 13275 13273>,
-			<14385 13424 13273 13297 13280 13275 13273>,
-			<14448 13457 13259 13297 13280 13275 13273>,
-			<14513 13494 13259 13296 13280 13275 13273>,
-			<14578 13537 13259 13296 13280 13275 13273>,
-			<14647 13586 13260 13295 13280 13274 13272>,
-			<14717 13644 13261 13291 13280 13274 13272>,
-			<14792 13708 13262 13288 13279 13274 13272>,
-			<14878 13777 13264 13289 13279 13274 13272>,
-			<14972 13853 13268 13293 13279 13273 13272>,
-			<15069 13939 13274 13295 13279 13273 13272>,
-			<15166 14040 13285 13294 13279 13274 13272>,
-			<15270 14153 13299 13292 13280 13274 13273>,
-			<15386 14276 13317 13292 13279 13274 13273>,
-			<15514 14412 13340 13293 13279 13274 13273>,
-			<15658 14564 13372 13291 13279 13274 13273>,
-			<15825 14738 13423 13271 13280 13275 13273>,
-			<16019 14925 13493 13262 13280 13275 13273>,
-			<16253 15128 13598 13261 13280 13274 13273>,
-			<16581 15354 13729 13263 13279 13275 13274>,
-			<16918 15547 13885 13266 13284 13276 13275>,
-			<17576 15700 13996 13270 13284 13277 13277>,
-			<18634 15883 14139 13280 13288 13279 13277>,
-			<20075 16098 14305 13309 13290 13280 13277>,
-			<22149 16340 14489 13343 13292 13280 13276>,
-			<25271 16656 14726 13389 13294 13281 13277>,
-			<29950 17634 15025 13481 13299 13283 13278>,
-			<37310 19636 15401 13635 13309 13286 13283>,
-			<47876 22946 16005 13899 13335 13293 13287>,
-			<47876 22946 16005 13899 13335 13293 13287>,
-			<47876 22946 16005 13899 13335 13293 13287>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <13491 13351 13296 13276 13275 13272>,
+			<13481 13348 13297 13278 13275 13272>,
+			<13476 13346 13298 13280 13275 13273>,
+			<13476 13347 13300 13282 13276 13274>,
+			<13480 13349 13302 13283 13276 13274>,
+			<13486 13352 13303 13283 13276 13275>,
+			<13513 13358 13303 13283 13276 13275>,
+			<13546 13363 13304 13283 13276 13275>,
+			<13543 13365 13306 13283 13277 13275>,
+			<13505 13365 13310 13284 13278 13275>,
+			<13476 13366 13315 13285 13278 13276>,
+			<13465 13371 13319 13285 13278 13276>,
+			<13456 13377 13322 13285 13278 13276>,
+			<13446 13376 13322 13286 13278 13276>,
+			<13434 13369 13321 13288 13279 13277>,
+			<13428 13363 13320 13290 13279 13277>,
+			<13428 13359 13318 13291 13280 13278>,
+			<13428 13354 13316 13292 13282 13278>,
+			<13414 13349 13313 13292 13283 13279>,
+			<13377 13343 13308 13291 13283 13281>,
+			<13356 13338 13304 13290 13284 13281>,
+			<13351 13336 13301 13286 13280 13278>,
+			<13349 13333 13299 13283 13276 13274>,
+			<13354 13323 13298 13282 13275 13273>,
+			<13374 13301 13297 13281 13275 13273>,
+			<13397 13289 13297 13281 13275 13273>,
+			<13424 13273 13297 13280 13275 13273>,
+			<13457 13259 13297 13280 13275 13273>,
+			<13494 13259 13296 13280 13275 13273>,
+			<13537 13259 13296 13280 13275 13273>,
+			<13586 13260 13295 13280 13274 13272>,
+			<13644 13261 13291 13280 13274 13272>,
+			<13708 13262 13288 13279 13274 13272>,
+			<13777 13264 13289 13279 13274 13272>,
+			<13853 13268 13293 13279 13273 13272>,
+			<13939 13274 13295 13279 13273 13272>,
+			<14040 13285 13294 13279 13274 13272>,
+			<14153 13299 13292 13280 13274 13273>,
+			<14276 13317 13292 13279 13274 13273>,
+			<14412 13340 13293 13279 13274 13273>,
+			<14564 13372 13291 13279 13274 13273>,
+			<14738 13423 13271 13280 13275 13273>,
+			<14925 13493 13262 13280 13275 13273>,
+			<15128 13598 13261 13280 13274 13273>,
+			<15354 13729 13263 13279 13275 13274>,
+			<15547 13885 13266 13284 13276 13275>,
+			<15700 13996 13270 13284 13277 13277>,
+			<15883 14139 13280 13288 13279 13277>,
+			<16098 14305 13309 13290 13280 13277>,
+			<16340 14489 13343 13292 13280 13276>,
+			<16656 14726 13389 13294 13281 13277>,
+			<17634 15025 13481 13299 13283 13278>,
+			<19636 15401 13635 13309 13286 13283>,
+			<22946 16005 13899 13335 13293 13287>,
+			<22946 16005 13899 13335 13293 13287>,
+			<22946 16005 13899 13335 13293 13287>;
 	};
 
 	qcom,pc-temp-y4-lut {
-		qcom,lut-col-legend = <(-20) (-10) 0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000 8800>,
-			<8600 8400 8200 8000 7800 7600 7400>,
-			<7200 7000 6800 6600 6400 6200 6000>,
-			<5800 5600 5400 5200 5000 4800 4600>,
-			<4400 4200 4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200 2000 1800>,
-			<1600 1400 1200 1000 900 800 700>,
-			<600 500 400 300 200 100 0>;
-		qcom,lut-data = <17711 16973 16623 16526 16458 16452 16456>,
-			<17567 16999 16632 16525 16457 16452 16456>,
-			<17504 17030 16641 16525 16457 16452 16456>,
-			<17504 17060 16652 16526 16457 16452 16456>,
-			<17547 17082 16663 16528 16457 16452 16456>,
-			<17613 17089 16674 16531 16457 16452 16456>,
-			<17765 17077 16687 16535 16459 16452 16456>,
-			<17948 17059 16701 16539 16462 16453 16456>,
-			<18024 17098 16711 16545 16465 16453 16456>,
-			<18066 17276 16720 16552 16468 16454 16457>,
-			<18080 17396 16735 16563 16473 16455 16457>,
-			<17811 17426 16824 16584 16480 16458 16458>,
-			<17427 17443 16930 16612 16490 16461 16460>,
-			<17319 17384 16951 16638 16498 16465 16462>,
-			<17285 17155 16958 16663 16504 16470 16465>,
-			<17245 17028 16959 16695 16515 16476 16469>,
-			<17166 17014 16934 16758 16539 16486 16475>,
-			<17085 17005 16887 16816 16571 16502 16486>,
-			<17039 16980 16831 16800 16609 16530 16506>,
-			<17007 16933 16754 16713 16656 16576 16541>,
-			<16985 16886 16692 16635 16664 16593 16558>,
-			<16968 16837 16644 16572 16570 16535 16521>,
-			<16957 16797 16610 16522 16475 16468 16470>,
-			<16954 16783 16607 16507 16460 16455 16458>,
-			<16953 16776 16623 16498 16454 16451 16455>,
-			<16953 16770 16632 16494 16453 16449 16454>,
-			<16951 16765 16645 16493 16454 16449 16453>,
-			<16951 16761 16659 16493 16455 16448 16453>,
-			<16953 16761 16662 16492 16457 16449 16453>,
-			<16959 16761 16663 16493 16461 16452 16454>,
-			<16965 16762 16667 16493 16466 16456 16455>,
-			<16974 16764 16677 16492 16474 16464 16461>,
-			<16982 16767 16687 16492 16479 16471 16470>,
-			<16985 16770 16690 16494 16478 16474 16476>,
-			<16987 16775 16693 16500 16474 16474 16483>,
-			<16990 16778 16693 16505 16467 16471 16482>,
-			<16999 16782 16689 16508 16455 16458 16467>,
-			<17010 16784 16685 16510 16448 16447 16453>,
-			<17021 16783 16685 16511 16449 16450 16455>,
-			<17033 16781 16683 16512 16452 16456 16465>,
-			<17048 16779 16681 16517 16455 16459 16471>,
-			<17066 16770 16670 16558 16460 16458 16470>,
-			<17087 16768 16654 16579 16464 16456 16468>,
-			<17112 16776 16634 16584 16465 16448 16452>,
-			<17124 16801 16629 16593 16474 16448 16444>,
-			<17066 16819 16647 16617 16493 16467 16470>,
-			<17161 16856 16669 16641 16507 16488 16496>,
-			<17324 16905 16699 16672 16536 16520 16521>,
-			<17559 16944 16754 16675 16565 16529 16536>,
-			<17893 16949 16780 16683 16555 16503 16488>,
-			<18450 16941 16767 16681 16554 16495 16479>,
-			<19496 17078 16794 16695 16582 16508 16485>,
-			<21979 17565 16874 16751 16646 16545 16510>,
-			<30091 19162 17124 16888 16859 16671 16581>,
-			<30091 19162 17124 16888 16859 16671 16581>,
-			<30091 19162 17124 16888 16859 16671 16581>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <16973 16623 16526 16458 16452 16456>,
+			<16999 16632 16525 16457 16452 16456>,
+			<17030 16641 16525 16457 16452 16456>,
+			<17060 16652 16526 16457 16452 16456>,
+			<17082 16663 16528 16457 16452 16456>,
+			<17089 16674 16531 16457 16452 16456>,
+			<17077 16687 16535 16459 16452 16456>,
+			<17059 16701 16539 16462 16453 16456>,
+			<17098 16711 16545 16465 16453 16456>,
+			<17276 16720 16552 16468 16454 16457>,
+			<17396 16735 16563 16473 16455 16457>,
+			<17426 16824 16584 16480 16458 16458>,
+			<17443 16930 16612 16490 16461 16460>,
+			<17384 16951 16638 16498 16465 16462>,
+			<17155 16958 16663 16504 16470 16465>,
+			<17028 16959 16695 16515 16476 16469>,
+			<17014 16934 16758 16539 16486 16475>,
+			<17005 16887 16816 16571 16502 16486>,
+			<16980 16831 16800 16609 16530 16506>,
+			<16933 16754 16713 16656 16576 16541>,
+			<16886 16692 16635 16664 16593 16558>,
+			<16837 16644 16572 16570 16535 16521>,
+			<16797 16610 16522 16475 16468 16470>,
+			<16783 16607 16507 16460 16455 16458>,
+			<16776 16623 16498 16454 16451 16455>,
+			<16770 16632 16494 16453 16449 16454>,
+			<16765 16645 16493 16454 16449 16453>,
+			<16761 16659 16493 16455 16448 16453>,
+			<16761 16662 16492 16457 16449 16453>,
+			<16761 16663 16493 16461 16452 16454>,
+			<16762 16667 16493 16466 16456 16455>,
+			<16764 16677 16492 16474 16464 16461>,
+			<16767 16687 16492 16479 16471 16470>,
+			<16770 16690 16494 16478 16474 16476>,
+			<16775 16693 16500 16474 16474 16483>,
+			<16778 16693 16505 16467 16471 16482>,
+			<16782 16689 16508 16455 16458 16467>,
+			<16784 16685 16510 16448 16447 16453>,
+			<16783 16685 16511 16449 16450 16455>,
+			<16781 16683 16512 16452 16456 16465>,
+			<16779 16681 16517 16455 16459 16471>,
+			<16770 16670 16558 16460 16458 16470>,
+			<16768 16654 16579 16464 16456 16468>,
+			<16776 16634 16584 16465 16448 16452>,
+			<16801 16629 16593 16474 16448 16444>,
+			<16819 16647 16617 16493 16467 16470>,
+			<16856 16669 16641 16507 16488 16496>,
+			<16905 16699 16672 16536 16520 16521>,
+			<16944 16754 16675 16565 16529 16536>,
+			<16949 16780 16683 16555 16503 16488>,
+			<16941 16767 16681 16554 16495 16479>,
+			<17078 16794 16695 16582 16508 16485>,
+			<17565 16874 16751 16646 16545 16510>,
+			<19162 17124 16888 16859 16671 16581>,
+			<19162 17124 16888 16859 16671 16581>,
+			<19162 17124 16888 16859 16671 16581>;
 	};
 
 	qcom,pc-temp-y5-lut {
-		qcom,lut-col-legend = <(-20) (-10) 0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000 8800>,
-			<8600 8400 8200 8000 7800 7600 7400>,
-			<7200 7000 6800 6600 6400 6200 6000>,
-			<5800 5600 5400 5200 5000 4800 4600>,
-			<4400 4200 4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200 2000 1800>,
-			<1600 1400 1200 1000 900 800 700>,
-			<600 500 400 300 200 100 0>;
-		qcom,lut-data = <9336 11501 16034 14767 13793 19407 15565>,
-			<10230 11603 15822 15156 15683 19413 16938>,
-			<10807 11875 15497 15333 17017 19416 18058>,
-			<11133 12285 15152 15352 17855 19416 18894>,
-			<11279 12803 14881 15266 18259 19413 19416>,
-			<11310 13403 14778 15128 18284 19405 19590>,
-			<11059 14551 14807 14793 17405 18933 19301>,
-			<10701 15710 14848 14419 16236 18269 18809>,
-			<11143 15425 14688 14471 15943 18195 18561>,
-			<13343 13533 13983 14951 15873 18327 18385>,
-			<14582 12513 13556 15219 15744 18394 18198>,
-			<13448 13803 13493 14892 15050 17832 17726>,
-			<11924 15473 13460 14418 14306 16921 17099>,
-			<11782 15394 13744 14254 14381 16318 16821>,
-			<12065 14258 14851 14181 14869 15815 16673>,
-			<12212 13562 15643 14199 15070 15556 16471>,
-			<12106 13428 15965 14556 14786 15450 15954>,
-			<11900 13274 16199 15160 14490 15387 15465>,
-			<11618 12936 16398 15863 14755 15446 15449>,
-			<11196 12423 16588 16824 15793 15777 15650>,
-			<11019 11952 16732 17460 16919 16267 15980>,
-			<11074 11476 16879 17821 18292 17600 16933>,
-			<11141 11117 16964 18087 19430 19112 18163>,
-			<11133 11033 16245 18242 19821 19838 19000>,
-			<11069 11009 14141 18325 19945 20331 19696>,
-			<11046 11024 12876 18331 19914 20756 20093>,
-			<11109 11056 11798 18517 19842 21457 20297>,
-			<11170 11084 10948 18759 19785 21999 20418>,
-			<11161 11132 10879 18828 19716 21658 20286>,
-			<11138 11232 10862 18868 19575 20509 19563>,
-			<11111 11269 10868 18768 19409 19604 18813>,
-			<11071 11345 11005 17096 19184 18920 18072>,
-			<11039 11421 11165 15478 19049 18499 17524>,
-			<11083 11456 11261 16038 19331 18661 17776>,
-			<11207 11520 11350 17571 20041 19331 19034>,
-			<11252 11543 11387 18037 20606 20274 20444>,
-			<11213 11613 11553 17270 21412 23017 22060>,
-			<11168 11678 11697 16300 21789 25208 23225>,
-			<11151 11640 11640 15861 20914 24442 22731>,
-			<11145 11545 11511 15530 19618 22425 21047>,
-			<11154 11506 11463 14798 19274 21559 20283>,
-			<11189 11457 11412 12697 19217 21506 20308>,
-			<11250 11415 11500 11853 18717 21719 20486>,
-			<11392 11368 11742 11779 17923 22443 22679>,
-			<11471 11364 11818 11639 16687 21754 22971>,
-			<11412 11379 11581 11310 17555 18408 18279>,
-			<11284 11464 11576 11214 16686 17313 17483>,
-			<10955 11729 11969 11315 17033 16467 15409>,
-			<10501 12142 11899 11677 16717 15881 14424>,
-			<10146 11979 11895 11966 17491 17177 15372>,
-			<9743 11649 12007 11983 17478 18213 16253>,
-			<9402 11017 11938 11964 17190 17836 15973>,
-			<9188 10265 11845 11923 16780 17343 17751>,
-			<8988 9626 11312 12185 16916 17400 17911>,
-			<8988 9626 11312 12185 16916 17400 17911>,
-			<8988 9626 11312 12185 16916 17400 17911>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <11501 16034 14767 13793 19407 15565>,
+			<11603 15822 15156 15683 19413 16938>,
+			<11875 15497 15333 17017 19416 18058>,
+			<12285 15152 15352 17855 19416 18894>,
+			<12803 14881 15266 18259 19413 19416>,
+			<13403 14778 15128 18284 19405 19590>,
+			<14551 14807 14793 17405 18933 19301>,
+			<15710 14848 14419 16236 18269 18809>,
+			<15425 14688 14471 15943 18195 18561>,
+			<13533 13983 14951 15873 18327 18385>,
+			<12513 13556 15219 15744 18394 18198>,
+			<13803 13493 14892 15050 17832 17726>,
+			<15473 13460 14418 14306 16921 17099>,
+			<15394 13744 14254 14381 16318 16821>,
+			<14258 14851 14181 14869 15815 16673>,
+			<13562 15643 14199 15070 15556 16471>,
+			<13428 15965 14556 14786 15450 15954>,
+			<13274 16199 15160 14490 15387 15465>,
+			<12936 16398 15863 14755 15446 15449>,
+			<12423 16588 16824 15793 15777 15650>,
+			<11952 16732 17460 16919 16267 15980>,
+			<11476 16879 17821 18292 17600 16933>,
+			<11117 16964 18087 19430 19112 18163>,
+			<11033 16245 18242 19821 19838 19000>,
+			<11009 14141 18325 19945 20331 19696>,
+			<11024 12876 18331 19914 20756 20093>,
+			<11056 11798 18517 19842 21457 20297>,
+			<11084 10948 18759 19785 21999 20418>,
+			<11132 10879 18828 19716 21658 20286>,
+			<11232 10862 18868 19575 20509 19563>,
+			<11269 10868 18768 19409 19604 18813>,
+			<11345 11005 17096 19184 18920 18072>,
+			<11421 11165 15478 19049 18499 17524>,
+			<11456 11261 16038 19331 18661 17776>,
+			<11520 11350 17571 20041 19331 19034>,
+			<11543 11387 18037 20606 20274 20444>,
+			<11613 11553 17270 21412 23017 22060>,
+			<11678 11697 16300 21789 25208 23225>,
+			<11640 11640 15861 20914 24442 22731>,
+			<11545 11511 15530 19618 22425 21047>,
+			<11506 11463 14798 19274 21559 20283>,
+			<11457 11412 12697 19217 21506 20308>,
+			<11415 11500 11853 18717 21719 20486>,
+			<11368 11742 11779 17923 22443 22679>,
+			<11364 11818 11639 16687 21754 22971>,
+			<11379 11581 11310 17555 18408 18279>,
+			<11464 11576 11214 16686 17313 17483>,
+			<11729 11969 11315 17033 16467 15409>,
+			<12142 11899 11677 16717 15881 14424>,
+			<11979 11895 11966 17491 17177 15372>,
+			<11649 12007 11983 17478 18213 16253>,
+			<11017 11938 11964 17190 17836 15973>,
+			<10265 11845 11923 16780 17343 17751>,
+			<9626 11312 12185 16916 17400 17911>,
+			<9626 11312 12185 16916 17400 17911>,
+			<9626 11312 12185 16916 17400 17911>;
 	};
 
 	qcom,pc-temp-y6-lut {
-		qcom,lut-col-legend = <(-20) (-10) 0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000 8800>,
-			<8600 8400 8200 8000 7800 7600 7400>,
-			<7200 7000 6800 6600 6400 6200 6000>,
-			<5800 5600 5400 5200 5000 4800 4600>,
-			<4400 4200 4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200 2000 1800>,
-			<1600 1400 1200 1000 900 800 700>,
-			<600 500 400 300 200 100 0>;
-		qcom,lut-data = <7520 6106 5405 5178 5064 5046 5042>,
-			<7480 6097 5401 5177 5064 5046 5042>,
-			<7441 6092 5400 5176 5065 5046 5042>,
-			<7405 6089 5400 5176 5066 5047 5043>,
-			<7374 6088 5401 5176 5067 5047 5044>,
-			<7350 6088 5403 5176 5067 5047 5044>,
-			<7329 6090 5407 5176 5068 5047 5044>,
-			<7314 6094 5413 5177 5068 5047 5044>,
-			<7323 6102 5416 5178 5069 5047 5044>,
-			<7367 6117 5418 5182 5071 5048 5044>,
-			<7391 6129 5422 5187 5073 5049 5045>,
-			<7291 6135 5450 5195 5075 5050 5045>,
-			<7156 6139 5483 5204 5078 5051 5046>,
-			<7138 6123 5488 5211 5081 5052 5047>,
-			<7142 6059 5490 5218 5085 5054 5048>,
-			<7144 6027 5490 5226 5089 5056 5050>,
-			<7141 6030 5484 5243 5097 5060 5052>,
-			<7136 6034 5472 5259 5107 5066 5055>,
-			<7138 6032 5457 5253 5118 5075 5062>,
-			<7150 6027 5435 5225 5131 5088 5073>,
-			<7165 6025 5421 5201 5133 5093 5078>,
-			<7194 6031 5414 5182 5104 5074 5065>,
-			<7230 6042 5409 5169 5075 5052 5048>,
-			<7265 6061 5410 5167 5071 5048 5044>,
-			<7301 6095 5412 5166 5069 5047 5043>,
-			<7340 6132 5415 5166 5069 5046 5042>,
-			<7383 6169 5421 5168 5070 5047 5042>,
-			<7430 6210 5431 5171 5071 5047 5042>,
-			<7476 6254 5444 5175 5073 5048 5043>,
-			<7523 6302 5464 5178 5075 5049 5043>,
-			<7575 6354 5486 5181 5078 5050 5044>,
-			<7633 6411 5511 5183 5081 5052 5046>,
-			<7696 6471 5539 5185 5083 5055 5048>,
-			<7764 6535 5569 5192 5084 5056 5050>,
-			<7836 6602 5603 5205 5084 5056 5053>,
-			<7911 6677 5640 5216 5084 5056 5053>,
-			<7991 6759 5681 5225 5083 5053 5049>,
-			<8076 6849 5727 5234 5083 5051 5046>,
-			<8172 6948 5778 5244 5084 5052 5047>,
-			<8278 7058 5835 5257 5087 5055 5050>,
-			<8396 7178 5899 5273 5091 5057 5052>,
-			<8531 7313 5971 5295 5095 5058 5052>,
-			<8689 7461 6060 5322 5099 5058 5052>,
-			<8881 7625 6170 5355 5104 5056 5049>,
-			<9142 7801 6295 5404 5112 5059 5048>,
-			<9395 7952 6438 5465 5127 5066 5057>,
-			<9966 8083 6542 5513 5135 5074 5067>,
-			<10874 8233 6666 5574 5150 5086 5075>,
-			<12099 8404 6813 5646 5166 5090 5080>,
-			<13825 8597 6972 5725 5172 5084 5066>,
-			<16318 8831 7159 5819 5184 5085 5065>,
-			<20019 9655 7408 5955 5214 5093 5070>,
-			<25895 11356 7725 6149 5262 5110 5083>,
-			<35348 14260 8288 6430 5374 5157 5109>,
-			<35348 14260 8288 6430 5374 5157 5109>,
-			<35348 14260 8288 6430 5374 5157 5109>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <6106 5405 5178 5064 5046 5042>,
+			<6097 5401 5177 5064 5046 5042>,
+			<6092 5400 5176 5065 5046 5042>,
+			<6089 5400 5176 5066 5047 5043>,
+			<6088 5401 5176 5067 5047 5044>,
+			<6088 5403 5176 5067 5047 5044>,
+			<6090 5407 5176 5068 5047 5044>,
+			<6094 5413 5177 5068 5047 5044>,
+			<6102 5416 5178 5069 5047 5044>,
+			<6117 5418 5182 5071 5048 5044>,
+			<6129 5422 5187 5073 5049 5045>,
+			<6135 5450 5195 5075 5050 5045>,
+			<6139 5483 5204 5078 5051 5046>,
+			<6123 5488 5211 5081 5052 5047>,
+			<6059 5490 5218 5085 5054 5048>,
+			<6027 5490 5226 5089 5056 5050>,
+			<6030 5484 5243 5097 5060 5052>,
+			<6034 5472 5259 5107 5066 5055>,
+			<6032 5457 5253 5118 5075 5062>,
+			<6027 5435 5225 5131 5088 5073>,
+			<6025 5421 5201 5133 5093 5078>,
+			<6031 5414 5182 5104 5074 5065>,
+			<6042 5409 5169 5075 5052 5048>,
+			<6061 5410 5167 5071 5048 5044>,
+			<6095 5412 5166 5069 5047 5043>,
+			<6132 5415 5166 5069 5046 5042>,
+			<6169 5421 5168 5070 5047 5042>,
+			<6210 5431 5171 5071 5047 5042>,
+			<6254 5444 5175 5073 5048 5043>,
+			<6302 5464 5178 5075 5049 5043>,
+			<6354 5486 5181 5078 5050 5044>,
+			<6411 5511 5183 5081 5052 5046>,
+			<6471 5539 5185 5083 5055 5048>,
+			<6535 5569 5192 5084 5056 5050>,
+			<6602 5603 5205 5084 5056 5053>,
+			<6677 5640 5216 5084 5056 5053>,
+			<6759 5681 5225 5083 5053 5049>,
+			<6849 5727 5234 5083 5051 5046>,
+			<6948 5778 5244 5084 5052 5047>,
+			<7058 5835 5257 5087 5055 5050>,
+			<7178 5899 5273 5091 5057 5052>,
+			<7313 5971 5295 5095 5058 5052>,
+			<7461 6060 5322 5099 5058 5052>,
+			<7625 6170 5355 5104 5056 5049>,
+			<7801 6295 5404 5112 5059 5048>,
+			<7952 6438 5465 5127 5066 5057>,
+			<8083 6542 5513 5135 5074 5067>,
+			<8233 6666 5574 5150 5086 5075>,
+			<8404 6813 5646 5166 5090 5080>,
+			<8597 6972 5725 5172 5084 5066>,
+			<8831 7159 5819 5184 5085 5065>,
+			<9655 7408 5955 5214 5093 5070>,
+			<11356 7725 6149 5262 5110 5083>,
+			<14260 8288 6430 5374 5157 5109>,
+			<14260 8288 6430 5374 5157 5109>,
+			<14260 8288 6430 5374 5157 5109>;
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/qg-batterydata-mlp356477-2800mah.dtsi b/arch/arm64/boot/dts/qcom/qg-batterydata-mlp356477-2800mah.dtsi
index f418fa0..3b18010 100644
--- a/arch/arm64/boot/dts/qcom/qg-batterydata-mlp356477-2800mah.dtsi
+++ b/arch/arm64/boot/dts/qcom/qg-batterydata-mlp356477-2800mah.dtsi
@@ -11,15 +11,15 @@
  */
 
 qcom,mlp356477_2800mah {
-	/* mlp356477_2800mah_averaged_MasterSlave_Aug14th2017 */
+	/* mlp356477_2800mah_averaged_MasterSlave_Mar13th2018 */
 	qcom,max-voltage-uv = <4400000>;
 	qcom,fg-cc-cv-threshold-mv = <4390>;
 	qcom,fastchg-current-ma = <4200>;
 	qcom,batt-id-kohm = <82>;
 	qcom,battery-beta = <4250>;
-	qcom,battery-therm-kohm = <32>;
+	qcom,battery-therm-kohm = <100>;
 	qcom,battery-type =
-		"mlp356477_2800mah_averaged_MasterSlave_Aug14th2017";
+		"mlp356477_2800mah_averaged_MasterSlave_Mar13th2018";
 	qcom,qg-batt-profile-ver = <100>;
 
 	qcom,jeita-fcc-ranges = <0   150   560000
@@ -29,14 +29,19 @@
 				 151 450  4400000
 				 451 550  4150000>;
 
+	/* COOL = 15 DegC, WARM = 45 DegC */
+	qcom,jeita-soft-thresholds = <0x4621 0x20b8>;
+	/* COLD = 0 DegC, HOT = 55 DegC */
+	qcom,jeita-hard-thresholds = <0x58cd 0x181d>;
+
 	qcom,fcc1-temp-lut {
 		qcom,lut-col-legend = <0 10 25 40 50>;
 		qcom,lut-data = <2715 2788 2861 2898 2908>;
 	};
 
 	qcom,fcc2-temp-lut {
-		qcom,lut-col-legend = <0 10 25 40 50>;
-		qcom,lut-data = <2846 2860 2868 2865 2865>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-data = <2864 2846 2860 2868 2865 2865>;
 	};
 
 	qcom,pc-temp-v1-lut {
@@ -112,75 +117,73 @@
 	};
 
 	qcom,pc-temp-v2-lut {
-		qcom,lut-col-legend = <0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200>,
-			<9000 8800 8600 8400 8200>,
-			<8000 7800 7600 7400 7200>,
-			<7000 6800 6600 6400 6200>,
-			<6000 5800 5600 5400 5200>,
-			<5000 4800 4600 4400 4200>,
-			<4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200>,
-			<2000 1800 1600 1400 1200>,
-			<1000 900 800 700 600>,
-			<500 400 300 200 100>,
-			<0>;
-		qcom,lut-data = <43850 43830 43805 43740 43725>,
-			<43429 43514 43528 43481 43467>,
-			<43064 43219 43264 43228 43216>,
-			<42767 42948 43012 42983 42973>,
-			<42526 42700 42773 42744 42738>,
-			<42296 42458 42537 42509 42505>,
-			<42059 42213 42303 42277 42272>,
-			<41822 41972 42071 42047 42041>,
-			<41571 41739 41843 41820 41814>,
-			<41298 41515 41619 41595 41589>,
-			<41069 41297 41398 41374 41368>,
-			<40928 41088 41181 41158 41151>,
-			<40808 40884 40967 40946 40938>,
-			<40611 40677 40763 40742 40734>,
-			<40284 40461 40566 40541 40534>,
-			<39989 40259 40373 40348 40342>,
-			<39811 40087 40180 40164 40158>,
-			<39662 39920 39993 39985 39980>,
-			<39459 39722 39821 39814 39808>,
-			<39184 39492 39664 39651 39646>,
-			<38924 39264 39483 39469 39466>,
-			<38721 39048 39237 39230 39230>,
-			<38546 38846 38982 38986 38989>,
-			<38403 38678 38799 38809 38813>,
-			<38282 38535 38654 38669 38674>,
-			<38189 38406 38530 38547 38552>,
-			<38125 38286 38419 38438 38442>,
-			<38075 38179 38320 38341 38343>,
-			<38030 38090 38229 38250 38250>,
-			<37992 38012 38144 38166 38164>,
-			<37955 37949 38066 38089 38086>,
-			<37916 37900 37993 38019 38016>,
-			<37875 37857 37925 37953 37949>,
-			<37832 37817 37860 37884 37875>,
-			<37788 37781 37801 37812 37795>,
-			<37738 37740 37738 37728 37702>,
-			<37680 37688 37671 37625 37587>,
-			<37613 37625 37600 37519 37469>,
-			<37537 37552 37525 37430 37374>,
-			<37448 37465 37446 37352 37292>,
-			<37349 37363 37353 37263 37200>,
-			<37237 37238 37238 37151 37088>,
-			<37114 37101 37106 37022 36960>,
-			<36989 36957 36952 36870 36813>,
-			<36875 36859 36862 36807 36758>,
-			<36792 36792 36828 36785 36734>,
-			<36754 36762 36812 36769 36719>,
-			<36707 36710 36780 36736 36687>,
-			<36633 36613 36721 36656 36581>,
-			<36472 36411 36517 36379 36276>,
-			<36149 36031 36113 35946 35829>,
-			<35650 35485 35584 35386 35258>,
-			<34964 34771 34884 34643 34500>,
-			<34007 33739 33902 33598 33440>,
-			<32474 32144 32393 32025 31829>,
-			<28051 26513 28737 27554 26991>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <43865 43850 43830 43805 43740 43725>,
+			<43432 43429 43514 43528 43481 43467>,
+			<43037 43064 43219 43264 43228 43216>,
+			<42685 42767 42948 43012 42983 42973>,
+			<42369 42526 42700 42773 42744 42738>,
+			<42075 42296 42458 42537 42509 42505>,
+			<41776 42059 42213 42303 42277 42272>,
+			<41517 41822 41972 42071 42047 42041>,
+			<41353 41571 41739 41843 41820 41814>,
+			<41239 41298 41515 41619 41595 41589>,
+			<41095 41069 41297 41398 41374 41368>,
+			<40895 40928 41088 41181 41158 41151>,
+			<40650 40808 40884 40967 40946 40938>,
+			<40329 40611 40677 40763 40742 40734>,
+			<39941 40284 40461 40566 40541 40534>,
+			<39654 39989 40259 40373 40348 40342>,
+			<39456 39811 40087 40180 40164 40158>,
+			<39278 39662 39920 39993 39985 39980>,
+			<39086 39459 39722 39821 39814 39808>,
+			<38900 39184 39492 39664 39651 39646>,
+			<38740 38924 39264 39483 39469 39466>,
+			<38598 38721 39048 39237 39230 39230>,
+			<38480 38546 38846 38982 38986 38989>,
+			<38386 38403 38678 38799 38809 38813>,
+			<38308 38282 38535 38654 38669 38674>,
+			<38240 38189 38406 38530 38547 38552>,
+			<38182 38125 38286 38419 38438 38442>,
+			<38127 38075 38179 38320 38341 38343>,
+			<38076 38030 38090 38229 38250 38250>,
+			<38028 37992 38012 38144 38166 38164>,
+			<37978 37955 37949 38066 38089 38086>,
+			<37927 37916 37900 37993 38019 38016>,
+			<37875 37875 37857 37925 37953 37949>,
+			<37820 37832 37817 37860 37884 37875>,
+			<37763 37788 37781 37801 37812 37795>,
+			<37699 37738 37740 37738 37728 37702>,
+			<37630 37680 37688 37671 37625 37587>,
+			<37555 37613 37625 37600 37519 37469>,
+			<37475 37537 37552 37525 37430 37374>,
+			<37392 37448 37465 37446 37352 37292>,
+			<37308 37349 37363 37353 37263 37200>,
+			<37222 37237 37238 37238 37151 37088>,
+			<37133 37114 37101 37106 37022 36960>,
+			<37035 36989 36957 36952 36870 36813>,
+			<36935 36875 36859 36862 36807 36758>,
+			<36817 36792 36792 36828 36785 36734>,
+			<36752 36754 36762 36812 36769 36719>,
+			<36667 36707 36710 36780 36736 36687>,
+			<36541 36633 36613 36721 36656 36581>,
+			<36342 36472 36411 36517 36379 36276>,
+			<36024 36149 36031 36113 35946 35829>,
+			<35575 35650 35485 35584 35386 35258>,
+			<34953 34964 34771 34884 34643 34500>,
+			<34073 34007 33739 33902 33598 33440>,
+			<32647 32474 32144 32393 32025 31829>,
+			<30018 28051 26513 28737 27554 26991>;
 	};
 
 	qcom,pc-temp-z1-lut {
@@ -616,435 +619,422 @@
 	};
 
 	qcom,pc-temp-y1-lut {
-		qcom,lut-col-legend = <0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200>,
-			<9000 8800 8600 8400 8200>,
-			<8000 7800 7600 7400 7200>,
-			<7000 6800 6600 6400 6200>,
-			<6000 5800 5600 5400 5200>,
-			<5000 4800 4600 4400 4200>,
-			<4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200>,
-			<2000 1800 1600 1400 1200>,
-			<1000 900 800 700 600>,
-			<500 400 300 200 100>,
-			<0>;
-		qcom,lut-data = <6704 6050 5566 5322 5235>,
-			<6701 6050 5560 5320 5234>,
-			<6693 6051 5554 5318 5233>,
-			<6684 6051 5548 5316 5231>,
-			<6676 6052 5543 5313 5230>,
-			<6673 6053 5540 5311 5228>,
-			<6667 6054 5539 5308 5225>,
-			<6659 6054 5538 5305 5222>,
-			<6663 6055 5536 5302 5222>,
-			<6693 6056 5529 5299 5222>,
-			<6717 6055 5525 5298 5222>,
-			<6716 6050 5525 5297 5220>,
-			<6707 6044 5526 5296 5217>,
-			<6706 6044 5528 5295 5216>,
-			<6707 6049 5533 5293 5217>,
-			<6709 6052 5536 5291 5217>,
-			<6705 6053 5534 5290 5219>,
-			<6699 6055 5532 5288 5221>,
-			<6700 6057 5532 5289 5221>,
-			<6708 6062 5531 5290 5220>,
-			<6715 6065 5531 5292 5219>,
-			<6712 6067 5532 5294 5220>,
-			<6706 6071 5532 5296 5222>,
-			<6703 6071 5532 5297 5223>,
-			<6702 6070 5532 5298 5225>,
-			<6702 6069 5532 5299 5227>,
-			<6700 6068 5535 5301 5229>,
-			<6699 6065 5539 5305 5232>,
-			<6697 6062 5540 5309 5236>,
-			<6691 6059 5541 5311 5240>,
-			<6688 6059 5542 5314 5243>,
-			<6691 6063 5546 5317 5244>,
-			<6695 6069 5550 5320 5245>,
-			<6693 6072 5553 5324 5247>,
-			<6677 6077 5556 5329 5251>,
-			<6667 6080 5558 5333 5255>,
-			<6679 6081 5563 5336 5258>,
-			<6697 6082 5568 5339 5261>,
-			<6698 6085 5570 5342 5263>,
-			<6684 6094 5571 5348 5265>,
-			<6675 6101 5572 5352 5268>,
-			<6691 6098 5581 5353 5271>,
-			<6707 6096 5586 5356 5275>,
-			<6704 6102 5586 5363 5282>,
-			<6708 6104 5593 5368 5284>,
-			<6725 6098 5595 5370 5288>,
-			<6724 6114 5601 5370 5288>,
-			<6743 6089 5598 5376 5290>,
-			<6750 6086 5605 5374 5291>,
-			<6722 6104 5609 5381 5293>,
-			<6738 6105 5608 5384 5292>,
-			<6759 6112 5624 5392 5304>,
-			<6766 6128 5643 5400 5313>,
-			<6779 6149 5656 5417 5324>,
-			<6779 6149 5656 5417 5324>,
-			<6779 6149 5656 5417 5324>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <7929 6704 6050 5566 5322 5235>,
+			<8028 6701 6050 5560 5320 5234>,
+			<8101 6693 6051 5554 5318 5233>,
+			<8151 6684 6051 5548 5316 5231>,
+			<8179 6676 6052 5543 5313 5230>,
+			<8186 6673 6053 5540 5311 5228>,
+			<8157 6667 6054 5539 5308 5225>,
+			<8120 6659 6054 5538 5305 5222>,
+			<8110 6663 6055 5536 5302 5222>,
+			<8104 6693 6056 5529 5299 5222>,
+			<8099 6717 6055 5525 5298 5222>,
+			<8120 6716 6050 5525 5297 5220>,
+			<8146 6707 6044 5526 5296 5217>,
+			<8147 6706 6044 5528 5295 5216>,
+			<8147 6707 6049 5533 5293 5217>,
+			<8146 6709 6052 5536 5291 5217>,
+			<8135 6705 6053 5534 5290 5219>,
+			<8119 6699 6055 5532 5288 5221>,
+			<8100 6700 6057 5532 5289 5221>,
+			<8079 6708 6062 5531 5290 5220>,
+			<8070 6715 6065 5531 5292 5219>,
+			<8070 6712 6067 5532 5294 5220>,
+			<8076 6706 6071 5532 5296 5222>,
+			<8117 6703 6071 5532 5297 5223>,
+			<8170 6702 6070 5532 5298 5225>,
+			<8167 6702 6069 5532 5299 5227>,
+			<8118 6700 6068 5535 5301 5229>,
+			<8084 6699 6065 5539 5305 5232>,
+			<8087 6697 6062 5540 5309 5236>,
+			<8100 6691 6059 5541 5311 5240>,
+			<8092 6688 6059 5542 5314 5243>,
+			<8059 6691 6063 5546 5317 5244>,
+			<8043 6695 6069 5550 5320 5245>,
+			<8027 6693 6072 5553 5324 5247>,
+			<8011 6677 6077 5556 5329 5251>,
+			<8021 6667 6080 5558 5333 5255>,
+			<8050 6679 6081 5563 5336 5258>,
+			<8082 6697 6082 5568 5339 5261>,
+			<8123 6698 6085 5570 5342 5263>,
+			<8148 6684 6094 5571 5348 5265>,
+			<8101 6675 6101 5572 5352 5268>,
+			<8041 6691 6098 5581 5353 5271>,
+			<8104 6707 6096 5586 5356 5275>,
+			<8088 6704 6102 5586 5363 5282>,
+			<8048 6708 6104 5593 5368 5284>,
+			<8055 6725 6098 5595 5370 5288>,
+			<8059 6724 6114 5601 5370 5288>,
+			<8092 6743 6089 5598 5376 5290>,
+			<8157 6750 6086 5605 5374 5291>,
+			<8197 6722 6104 5609 5381 5293>,
+			<8269 6738 6105 5608 5384 5292>,
+			<8288 6759 6112 5624 5392 5304>,
+			<8380 6766 6128 5643 5400 5313>,
+			<8422 6779 6149 5656 5417 5324>,
+			<8422 6779 6149 5656 5417 5324>,
+			<8422 6779 6149 5656 5417 5324>;
 	};
 
 	qcom,pc-temp-y2-lut {
-		qcom,lut-col-legend = <0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200>,
-			<9000 8800 8600 8400 8200>,
-			<8000 7800 7600 7400 7200>,
-			<7000 6800 6600 6400 6200>,
-			<6000 5800 5600 5400 5200>,
-			<5000 4800 4600 4400 4200>,
-			<4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200>,
-			<2000 1800 1600 1400 1200>,
-			<1000 900 800 700 600>,
-			<500 400 300 200 100>,
-			<0>;
-		qcom,lut-data = <9643 10639 11070 11121 11086>,
-			<9643 10662 11056 11097 11058>,
-			<9643 10675 11037 11063 11029>,
-			<9871 10680 11014 11027 11001>,
-			<10190 10680 10988 10997 10976>,
-			<10325 10677 10959 10981 10958>,
-			<10308 10664 10918 10973 10946>,
-			<10282 10644 10881 10967 10935>,
-			<10301 10632 10875 10959 10916>,
-			<10440 10623 10874 10933 10882>,
-			<10534 10619 10874 10919 10864>,
-			<10489 10626 10869 10936 10874>,
-			<10417 10643 10861 10961 10888>,
-			<10413 10676 10856 10952 10885>,
-			<10487 10748 10851 10897 10860>,
-			<10553 10801 10851 10866 10840>,
-			<10580 10826 10885 10876 10837>,
-			<10597 10843 10946 10896 10845>,
-			<10521 10842 11018 10943 10884>,
-			<10042 10822 11115 11060 10984>,
-			<9696 10809 11159 11120 11034>,
-			<9682 10815 11129 11098 11013>,
-			<9676 10826 11091 11071 10987>,
-			<9675 10835 11085 11079 11009>,
-			<9676 10846 11088 11121 11106>,
-			<9676 10848 11093 11154 11162>,
-			<9675 10684 11108 11176 11166>,
-			<9671 10460 11130 11199 11168>,
-			<9668 10652 11152 11224 11182>,
-			<9665 11565 11178 11263 11214>,
-			<9662 12069 11192 11286 11238>,
-			<9660 11796 11199 11310 11257>,
-			<9659 11319 11203 11338 11277>,
-			<9657 10963 11202 11344 11307>,
-			<9656 10643 11198 11320 11345>,
-			<9655 10423 11189 11299 11359>,
-			<9654 10140 11148 11294 11325>,
-			<9653 9828 11108 11301 11280>,
-			<9653 9733 11099 11301 11271>,
-			<9653 9707 11096 11290 11278>,
-			<9652 9692 11071 11287 11277>,
-			<9652 9681 10975 11329 11250>,
-			<9652 9674 10939 11356 11231>,
-			<9652 9668 10913 11303 11229>,
-			<9652 9664 10802 11253 11135>,
-			<9652 9663 10839 11180 11044>,
-			<9652 9661 10832 11146 11009>,
-			<9652 9660 10811 11105 10962>,
-			<9651 9659 10794 11061 10965>,
-			<9651 9658 10764 11053 10938>,
-			<9651 9658 10711 10981 10871>,
-			<9651 9656 10651 10927 10829>,
-			<9651 9654 10594 10851 10747>,
-			<9651 9654 10531 10798 10659>,
-			<9651 9654 10531 10798 10659>,
-			<9651 9654 10531 10798 10659>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <9654 9643 10639 11070 11121 11086>,
+			<9654 9643 10662 11056 11097 11058>,
+			<9655 9643 10675 11037 11063 11029>,
+			<9655 9871 10680 11014 11027 11001>,
+			<9656 10190 10680 10988 10997 10976>,
+			<9656 10325 10677 10959 10981 10958>,
+			<9657 10308 10664 10918 10973 10946>,
+			<9657 10282 10644 10881 10967 10935>,
+			<9657 10301 10632 10875 10959 10916>,
+			<9658 10440 10623 10874 10933 10882>,
+			<9658 10534 10619 10874 10919 10864>,
+			<9658 10489 10626 10869 10936 10874>,
+			<9659 10417 10643 10861 10961 10888>,
+			<9658 10413 10676 10856 10952 10885>,
+			<9657 10487 10748 10851 10897 10860>,
+			<9657 10553 10801 10851 10866 10840>,
+			<9657 10580 10826 10885 10876 10837>,
+			<9657 10597 10843 10946 10896 10845>,
+			<9657 10521 10842 11018 10943 10884>,
+			<9656 10042 10822 11115 11060 10984>,
+			<9656 9696 10809 11159 11120 11034>,
+			<9656 9682 10815 11129 11098 11013>,
+			<9656 9676 10826 11091 11071 10987>,
+			<9656 9675 10835 11085 11079 11009>,
+			<9656 9676 10846 11088 11121 11106>,
+			<9655 9676 10848 11093 11154 11162>,
+			<9655 9675 10684 11108 11176 11166>,
+			<9655 9671 10460 11130 11199 11168>,
+			<9655 9668 10652 11152 11224 11182>,
+			<9654 9665 11565 11178 11263 11214>,
+			<9654 9662 12069 11192 11286 11238>,
+			<9654 9660 11796 11199 11310 11257>,
+			<9654 9659 11319 11203 11338 11277>,
+			<9654 9657 10963 11202 11344 11307>,
+			<9654 9656 10643 11198 11320 11345>,
+			<9654 9655 10423 11189 11299 11359>,
+			<9653 9654 10140 11148 11294 11325>,
+			<9653 9653 9828 11108 11301 11280>,
+			<9653 9653 9733 11099 11301 11271>,
+			<9653 9653 9707 11096 11290 11278>,
+			<9653 9652 9692 11071 11287 11277>,
+			<9653 9652 9681 10975 11329 11250>,
+			<9653 9652 9674 10939 11356 11231>,
+			<9653 9652 9668 10913 11303 11229>,
+			<9653 9652 9664 10802 11253 11135>,
+			<9653 9652 9663 10839 11180 11044>,
+			<9653 9652 9661 10832 11146 11009>,
+			<9652 9652 9660 10811 11105 10962>,
+			<9652 9651 9659 10794 11061 10965>,
+			<9651 9651 9658 10764 11053 10938>,
+			<9650 9651 9658 10711 10981 10871>,
+			<9650 9651 9656 10651 10927 10829>,
+			<9649 9651 9654 10594 10851 10747>,
+			<9648 9651 9654 10531 10798 10659>,
+			<9648 9651 9654 10531 10798 10659>,
+			<9648 9651 9654 10531 10798 10659>;
 	};
 
 	qcom,pc-temp-y3-lut {
-		qcom,lut-col-legend = <0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200>,
-			<9000 8800 8600 8400 8200>,
-			<8000 7800 7600 7400 7200>,
-			<7000 6800 6600 6400 6200>,
-			<6000 5800 5600 5400 5200>,
-			<5000 4800 4600 4400 4200>,
-			<4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200>,
-			<2000 1800 1600 1400 1200>,
-			<1000 900 800 700 600>,
-			<500 400 300 200 100>,
-			<0>;
-		qcom,lut-data = <13677 13390 13309 13301 13279>,
-			<13657 13393 13309 13294 13279>,
-			<13634 13397 13311 13289 13279>,
-			<13612 13400 13312 13285 13279>,
-			<13596 13403 13314 13283 13279>,
-			<13590 13406 13315 13282 13279>,
-			<13594 13408 13315 13283 13280>,
-			<13600 13410 13316 13286 13281>,
-			<13594 13412 13317 13287 13282>,
-			<13548 13416 13319 13287 13282>,
-			<13515 13419 13321 13287 13282>,
-			<13513 13421 13322 13289 13282>,
-			<13512 13423 13323 13291 13282>,
-			<13509 13422 13325 13291 13283>,
-			<13504 13414 13328 13291 13284>,
-			<13497 13407 13329 13291 13286>,
-			<13488 13401 13328 13292 13287>,
-			<13478 13395 13325 13294 13288>,
-			<13470 13387 13324 13297 13290>,
-			<13465 13376 13323 13301 13294>,
-			<13458 13367 13322 13303 13296>,
-			<13428 13360 13315 13297 13290>,
-			<13384 13354 13306 13287 13281>,
-			<13362 13349 13303 13283 13278>,
-			<13349 13346 13300 13281 13277>,
-			<13344 13341 13299 13280 13277>,
-			<13351 13308 13299 13280 13277>,
-			<13369 13266 13299 13282 13277>,
-			<13391 13259 13298 13282 13277>,
-			<13422 13259 13299 13283 13277>,
-			<13460 13258 13299 13283 13277>,
-			<13503 13258 13298 13283 13277>,
-			<13554 13259 13298 13283 13277>,
-			<13615 13263 13298 13283 13277>,
-			<13690 13285 13299 13283 13278>,
-			<13777 13302 13299 13283 13278>,
-			<13879 13294 13296 13281 13277>,
-			<13996 13281 13292 13279 13276>,
-			<14118 13282 13292 13278 13276>,
-			<14247 13299 13292 13277 13277>,
-			<14377 13319 13293 13277 13277>,
-			<14502 13343 13295 13277 13278>,
-			<14624 13368 13298 13277 13278>,
-			<14737 13402 13303 13278 13276>,
-			<14824 13470 13304 13280 13278>,
-			<14801 13476 13307 13284 13280>,
-			<14824 13517 13316 13291 13286>,
-			<14890 13560 13319 13292 13287>,
-			<14961 13607 13332 13295 13287>,
-			<15021 13665 13332 13292 13286>,
-			<15095 13703 13333 13294 13286>,
-			<15215 13779 13341 13296 13289>,
-			<15382 13934 13350 13299 13292>,
-			<15571 14143 13370 13308 13299>,
-			<15571 14143 13370 13308 13299>,
-			<15571 14143 13370 13308 13299>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <14501 13677 13390 13309 13301 13279>,
+			<14412 13657 13393 13309 13294 13279>,
+			<14328 13634 13397 13311 13289 13279>,
+			<14249 13612 13400 13312 13285 13279>,
+			<14179 13596 13403 13314 13283 13279>,
+			<14117 13590 13406 13315 13282 13279>,
+			<14063 13594 13408 13315 13283 13280>,
+			<14017 13600 13410 13316 13286 13281>,
+			<13976 13594 13412 13317 13287 13282>,
+			<13939 13548 13416 13319 13287 13282>,
+			<13929 13515 13419 13321 13287 13282>,
+			<13957 13513 13421 13322 13289 13282>,
+			<13986 13512 13423 13323 13291 13282>,
+			<13945 13509 13422 13325 13291 13283>,
+			<13843 13504 13414 13328 13291 13284>,
+			<13803 13497 13407 13329 13291 13286>,
+			<13797 13488 13401 13328 13292 13287>,
+			<13793 13478 13395 13325 13294 13288>,
+			<13788 13470 13387 13324 13297 13290>,
+			<13783 13465 13376 13323 13301 13294>,
+			<13783 13458 13367 13322 13303 13296>,
+			<13788 13428 13360 13315 13297 13290>,
+			<13796 13384 13354 13306 13287 13281>,
+			<13814 13362 13349 13303 13283 13278>,
+			<13843 13349 13346 13300 13281 13277>,
+			<13874 13344 13341 13299 13280 13277>,
+			<13910 13351 13308 13299 13280 13277>,
+			<13952 13369 13266 13299 13282 13277>,
+			<13999 13391 13259 13298 13282 13277>,
+			<14052 13422 13259 13299 13283 13277>,
+			<14110 13460 13258 13299 13283 13277>,
+			<14174 13503 13258 13298 13283 13277>,
+			<14243 13554 13259 13298 13283 13277>,
+			<14318 13615 13263 13298 13283 13277>,
+			<14398 13690 13285 13299 13283 13278>,
+			<14481 13777 13302 13299 13283 13278>,
+			<14568 13879 13294 13296 13281 13277>,
+			<14658 13996 13281 13292 13279 13276>,
+			<14750 14118 13282 13292 13278 13276>,
+			<14850 14247 13299 13292 13277 13277>,
+			<14963 14377 13319 13293 13277 13277>,
+			<15082 14502 13343 13295 13277 13278>,
+			<15198 14624 13368 13298 13277 13278>,
+			<15302 14737 13402 13303 13278 13276>,
+			<15264 14824 13470 13304 13280 13278>,
+			<15439 14801 13476 13307 13284 13280>,
+			<15557 14824 13517 13316 13291 13286>,
+			<15783 14890 13560 13319 13292 13287>,
+			<16058 14961 13607 13332 13295 13287>,
+			<16423 15021 13665 13332 13292 13286>,
+			<16935 15095 13703 13333 13294 13286>,
+			<17701 15215 13779 13341 13296 13289>,
+			<18847 15382 13934 13350 13299 13292>,
+			<20636 15571 14143 13370 13308 13299>,
+			<20636 15571 14143 13370 13308 13299>,
+			<20636 15571 14143 13370 13308 13299>;
 	};
 
 	qcom,pc-temp-y4-lut {
-		qcom,lut-col-legend = <0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200>,
-			<9000 8800 8600 8400 8200>,
-			<8000 7800 7600 7400 7200>,
-			<7000 6800 6600 6400 6200>,
-			<6000 5800 5600 5400 5200>,
-			<5000 4800 4600 4400 4200>,
-			<4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200>,
-			<2000 1800 1600 1400 1200>,
-			<1000 900 800 700 600>,
-			<500 400 300 200 100>,
-			<0>;
-		qcom,lut-data = <17305 16798 16610 16483 16470>,
-			<17330 16862 16610 16486 16469>,
-			<17378 16934 16609 16489 16468>,
-			<17433 17001 16608 16491 16467>,
-			<17479 17051 16607 16493 16467>,
-			<17501 17070 16605 16493 16466>,
-			<17503 17059 16603 16493 16466>,
-			<17504 17041 16601 16492 16466>,
-			<17511 17030 16599 16493 16466>,
-			<17550 17023 16599 16497 16470>,
-			<17608 17020 16599 16500 16473>,
-			<17742 17034 16602 16502 16478>,
-			<17902 17062 16609 16506 16483>,
-			<17876 17086 16619 16512 16487>,
-			<17547 17110 16638 16523 16492>,
-			<17320 17134 16659 16535 16498>,
-			<17344 17161 16679 16546 16506>,
-			<17386 17183 16703 16560 16518>,
-			<17370 17170 16748 16586 16537>,
-			<17216 17080 16821 16630 16569>,
-			<17060 16974 16852 16651 16585>,
-			<16974 16865 16754 16602 16552>,
-			<16908 16761 16616 16529 16502>,
-			<16873 16703 16567 16502 16483>,
-			<16851 16662 16543 16489 16473>,
-			<16841 16647 16535 16485 16469>,
-			<16841 16681 16535 16485 16470>,
-			<16842 16727 16535 16487 16471>,
-			<16843 16732 16537 16489 16474>,
-			<16844 16721 16543 16497 16482>,
-			<16845 16716 16549 16507 16491>,
-			<16852 16721 16554 16521 16504>,
-			<16866 16730 16558 16535 16515>,
-			<16879 16732 16556 16540 16518>,
-			<16893 16714 16549 16540 16515>,
-			<16906 16704 16540 16534 16509>,
-			<16920 16735 16528 16505 16492>,
-			<16932 16784 16517 16477 16475>,
-			<16941 16805 16517 16476 16471>,
-			<16947 16815 16522 16479 16469>,
-			<16950 16818 16530 16481 16469>,
-			<16948 16818 16544 16482 16469>,
-			<16945 16817 16555 16481 16467>,
-			<16947 16815 16561 16471 16454>,
-			<16965 16826 16575 16477 16456>,
-			<16961 16849 16584 16493 16477>,
-			<16977 16893 16606 16503 16495>,
-			<17046 16954 16635 16528 16531>,
-			<17107 17025 16679 16557 16532>,
-			<17131 17054 16682 16515 16493>,
-			<17101 17038 16673 16527 16498>,
-			<17060 17051 16712 16548 16514>,
-			<17063 17124 16764 16588 16554>,
-			<17135 17255 16879 16727 16719>,
-			<17135 17255 16879 16727 16719>,
-			<17135 17255 16879 16727 16719>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <17448 17305 16798 16610 16483 16470>,
+			<17520 17330 16862 16610 16486 16469>,
+			<17601 17378 16934 16609 16489 16468>,
+			<17679 17433 17001 16608 16491 16467>,
+			<17744 17479 17051 16607 16493 16467>,
+			<17783 17501 17070 16605 16493 16466>,
+			<17798 17503 17059 16603 16493 16466>,
+			<17813 17504 17041 16601 16492 16466>,
+			<17918 17511 17030 16599 16493 16466>,
+			<18180 17550 17023 16599 16497 16470>,
+			<18279 17608 17020 16599 16500 16473>,
+			<18148 17742 17034 16602 16502 16478>,
+			<17945 17902 17062 16609 16506 16483>,
+			<17736 17876 17086 16619 16512 16487>,
+			<17506 17547 17110 16638 16523 16492>,
+			<17399 17320 17134 16659 16535 16498>,
+			<17363 17344 17161 16679 16546 16506>,
+			<17328 17386 17183 16703 16560 16518>,
+			<17266 17370 17170 16748 16586 16537>,
+			<17193 17216 17080 16821 16630 16569>,
+			<17141 17060 16974 16852 16651 16585>,
+			<17100 16974 16865 16754 16602 16552>,
+			<17077 16908 16761 16616 16529 16502>,
+			<17070 16873 16703 16567 16502 16483>,
+			<17066 16851 16662 16543 16489 16473>,
+			<17066 16841 16647 16535 16485 16469>,
+			<17066 16841 16681 16535 16485 16470>,
+			<17067 16842 16727 16535 16487 16471>,
+			<17070 16843 16732 16537 16489 16474>,
+			<17074 16844 16721 16543 16497 16482>,
+			<17079 16845 16716 16549 16507 16491>,
+			<17088 16852 16721 16554 16521 16504>,
+			<17095 16866 16730 16558 16535 16515>,
+			<17099 16879 16732 16556 16540 16518>,
+			<17103 16893 16714 16549 16540 16515>,
+			<17111 16906 16704 16540 16534 16509>,
+			<17124 16920 16735 16528 16505 16492>,
+			<17134 16932 16784 16517 16477 16475>,
+			<17142 16941 16805 16517 16476 16471>,
+			<17149 16947 16815 16522 16479 16469>,
+			<17157 16950 16818 16530 16481 16469>,
+			<17167 16948 16818 16544 16482 16469>,
+			<17187 16945 16817 16555 16481 16467>,
+			<17208 16947 16815 16561 16471 16454>,
+			<17140 16965 16826 16575 16477 16456>,
+			<17176 16961 16849 16584 16493 16477>,
+			<17202 16977 16893 16606 16503 16495>,
+			<17281 17046 16954 16635 16528 16531>,
+			<17390 17107 17025 16679 16557 16532>,
+			<17524 17131 17054 16682 16515 16493>,
+			<17690 17101 17038 16673 16527 16498>,
+			<17978 17060 17051 16712 16548 16514>,
+			<18577 17063 17124 16764 16588 16554>,
+			<20156 17135 17255 16879 16727 16719>,
+			<20156 17135 17255 16879 16727 16719>,
+			<20156 17135 17255 16879 16727 16719>;
 	};
 
 	qcom,pc-temp-y5-lut {
-		qcom,lut-col-legend = <0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200>,
-			<9000 8800 8600 8400 8200>,
-			<8000 7800 7600 7400 7200>,
-			<7000 6800 6600 6400 6200>,
-			<6000 5800 5600 5400 5200>,
-			<5000 4800 4600 4400 4200>,
-			<4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200>,
-			<2000 1800 1600 1400 1200>,
-			<1000 900 800 700 600>,
-			<500 400 300 200 100>,
-			<0>;
-		qcom,lut-data = <8712 14223 14774 19943 16308>,
-			<8888 14349 15148 18667 15835>,
-			<10562 14526 15365 17009 15457>,
-			<12204 14713 15466 15353 15176>,
-			<13579 14867 15489 14086 14997>,
-			<14452 14948 15472 13593 14920>,
-			<14948 14973 15335 13800 15003>,
-			<15270 14986 15151 14123 15144>,
-			<15028 14986 15098 14118 15087>,
-			<13370 14973 15056 13826 14716>,
-			<12246 14930 14978 13664 14315>,
-			<13353 14287 14743 13788 13961>,
-			<15163 13386 14398 13870 13634>,
-			<15495 13334 14078 13643 13482>,
-			<15197 13853 13740 13191 13549>,
-			<14993 14346 13497 12887 13638>,
-			<15443 14672 13207 12793 13546>,
-			<16191 15006 12923 12796 13423>,
-			<16138 15417 13004 13001 13548>,
-			<14708 15994 13654 13569 14033>,
-			<13284 16419 14434 14193 14440>,
-			<12599 16670 15491 14905 14826>,
-			<12068 16832 16433 15541 15160>,
-			<11544 16827 16644 15650 15196>,
-			<10962 16682 16591 15306 15346>,
-			<10655 16390 16622 15048 15474>,
-			<10648 14341 16597 15293 15494>,
-			<10645 11728 16540 15744 15472>,
-			<10665 11156 16578 15865 15229>,
-			<10802 11032 16695 15749 14663>,
-			<10946 10959 16756 15607 14352>,
-			<11017 10901 16831 15502 14290>,
-			<11076 10865 16959 15400 14311>,
-			<11177 11054 17363 15705 14665>,
-			<11367 12196 18097 16573 15740>,
-			<11520 13011 18310 16919 16424>,
-			<11584 12496 17269 16620 16376>,
-			<11627 11602 15914 16091 16215>,
-			<11630 11486 15213 15448 16327>,
-			<11595 11681 14700 14692 16543>,
-			<11570 11787 14330 14365 16550>,
-			<11579 11797 14105 14243 16259>,
-			<11596 11778 14219 14209 16346>,
-			<11509 11647 14611 15058 16893>,
-			<11331 11779 14198 14882 16382>,
-			<11388 11508 14156 14882 14589>,
-			<11488 11654 14603 16012 16142>,
-			<11493 11662 14001 15040 14960>,
-			<11613 11939 14918 15399 14828>,
-			<11747 12726 15439 17093 17327>,
-			<11665 12655 15981 17753 17255>,
-			<11585 12280 16288 17881 17960>,
-			<11459 12118 16141 17436 18200>,
-			<11818 11932 16090 17352 17825>,
-			<11818 11932 16090 17352 17825>,
-			<11818 11932 16090 17352 17825>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <10030 8712 14223 14774 19943 16308>,
+			<10448 8888 14349 15148 18667 15835>,
+			<10794 10562 14526 15365 17009 15457>,
+			<11054 12204 14713 15466 15353 15176>,
+			<11214 13579 14867 15489 14086 14997>,
+			<11260 14452 14948 15472 13593 14920>,
+			<11143 14948 14973 15335 13800 15003>,
+			<11001 15270 14986 15151 14123 15144>,
+			<11151 15028 14986 15098 14118 15087>,
+			<11850 13370 14973 15056 13826 14716>,
+			<12871 12246 14930 14978 13664 14315>,
+			<15188 13353 14287 14743 13788 13961>,
+			<17100 15163 13386 14398 13870 13634>,
+			<15786 15495 13334 14078 13643 13482>,
+			<12439 15197 13853 13740 13191 13549>,
+			<11406 14993 14346 13497 12887 13638>,
+			<11547 15443 14672 13207 12793 13546>,
+			<11662 16191 15006 12923 12796 13423>,
+			<11574 16138 15417 13004 13001 13548>,
+			<11364 14708 15994 13654 13569 14033>,
+			<11181 13284 16419 14434 14193 14440>,
+			<10986 12599 16670 15491 14905 14826>,
+			<10835 12068 16832 16433 15541 15160>,
+			<10734 11544 16827 16644 15650 15196>,
+			<10666 10962 16682 16591 15306 15346>,
+			<10655 10655 16390 16622 15048 15474>,
+			<10654 10648 14341 16597 15293 15494>,
+			<10654 10645 11728 16540 15744 15472>,
+			<10689 10665 11156 16578 15865 15229>,
+			<10734 10802 11032 16695 15749 14663>,
+			<10745 10946 10959 16756 15607 14352>,
+			<10765 11017 10901 16831 15502 14290>,
+			<10797 11076 10865 16959 15400 14311>,
+			<10882 11177 11054 17363 15705 14665>,
+			<10953 11367 12196 18097 16573 15740>,
+			<10940 11520 13011 18310 16919 16424>,
+			<10897 11584 12496 17269 16620 16376>,
+			<10863 11627 11602 15914 16091 16215>,
+			<10835 11630 11486 15213 15448 16327>,
+			<10820 11595 11681 14700 14692 16543>,
+			<10867 11570 11787 14330 14365 16550>,
+			<10955 11579 11797 14105 14243 16259>,
+			<11030 11596 11778 14219 14209 16346>,
+			<11029 11509 11647 14611 15058 16893>,
+			<11044 11331 11779 14198 14882 16382>,
+			<11143 11388 11508 14156 14882 14589>,
+			<11321 11488 11654 14603 16012 16142>,
+			<11356 11493 11662 14001 15040 14960>,
+			<11206 11613 11939 14918 15399 14828>,
+			<10932 11747 12726 15439 17093 17327>,
+			<10539 11665 12655 15981 17753 17255>,
+			<10263 11585 12280 16288 17881 17960>,
+			<9994 11459 12118 16141 17436 18200>,
+			<9668 11818 11932 16090 17352 17825>,
+			<9668 11818 11932 16090 17352 17825>,
+			<9668 11818 11932 16090 17352 17825>;
 	};
 
 	qcom,pc-temp-y6-lut {
-		qcom,lut-col-legend = <0 10 25 40 50>;
-		qcom,lut-row-legend = <10000 9800 9600 9400 9200>,
-			<9000 8800 8600 8400 8200>,
-			<8000 7800 7600 7400 7200>,
-			<7000 6800 6600 6400 6200>,
-			<6000 5800 5600 5400 5200>,
-			<5000 4800 4600 4400 4200>,
-			<4000 3800 3600 3400 3200>,
-			<3000 2800 2600 2400 2200>,
-			<2000 1800 1600 1400 1200>,
-			<1000 900 800 700 600>,
-			<500 400 300 200 100>,
-			<0>;
-		qcom,lut-data = <6132 5538 5158 5055 5027>,
-			<6176 5550 5158 5053 5026>,
-			<6205 5557 5158 5050 5025>,
-			<6223 5561 5157 5048 5025>,
-			<6232 5562 5156 5046 5025>,
-			<6234 5562 5154 5046 5025>,
-			<6227 5555 5152 5046 5025>,
-			<6211 5540 5150 5047 5026>,
-			<6191 5531 5149 5047 5027>,
-			<6161 5522 5149 5048 5028>,
-			<6144 5519 5149 5049 5029>,
-			<6170 5520 5150 5051 5030>,
-			<6214 5522 5151 5053 5031>,
-			<6207 5523 5154 5055 5033>,
-			<6119 5523 5160 5058 5035>,
-			<6058 5522 5167 5061 5038>,
-			<6060 5524 5172 5065 5041>,
-			<6065 5527 5177 5070 5045>,
-			<6054 5521 5188 5079 5052>,
-			<5986 5487 5208 5095 5064>,
-			<5923 5449 5216 5102 5070>,
-			<5892 5413 5184 5083 5056>,
-			<5871 5381 5138 5056 5035>,
-			<5868 5365 5122 5045 5028>,
-			<5872 5355 5114 5040 5024>,
-			<5878 5349 5111 5038 5023>,
-			<5895 5343 5112 5039 5023>,
-			<5926 5339 5113 5040 5024>,
-			<5960 5339 5115 5042 5026>,
-			<5999 5342 5118 5045 5028>,
-			<6044 5346 5121 5048 5031>,
-			<6096 5354 5124 5053 5034>,
-			<6156 5367 5126 5057 5038>,
-			<6222 5383 5127 5059 5039>,
-			<6297 5405 5127 5060 5039>,
-			<6380 5430 5127 5058 5038>,
-			<6470 5458 5124 5049 5032>,
-			<6568 5491 5120 5041 5027>,
-			<6667 5530 5121 5040 5027>,
-			<6768 5579 5127 5041 5027>,
-			<6867 5632 5133 5042 5028>,
-			<6963 5689 5144 5044 5028>,
-			<7053 5751 5155 5044 5028>,
-			<7135 5817 5167 5043 5024>,
-			<7206 5905 5181 5046 5026>,
-			<7192 5921 5188 5056 5034>,
-			<7214 5976 5205 5063 5044>,
-			<7280 6034 5219 5072 5055>,
-			<7350 6096 5248 5083 5055>,
-			<7405 6155 5252 5069 5043>,
-			<7454 6196 5257 5074 5046>,
-			<7535 6282 5285 5084 5053>,
-			<7666 6442 5320 5100 5069>,
-			<7846 6646 5385 5148 5123>,
-			<7846 6646 5385 5148 5123>,
-			<7846 6646 5385 5148 5123>;
+		qcom,lut-col-legend = <(-10) 0 10 25 40 50>;
+		qcom,lut-row-legend = <10000 9800 9600 9400 9200 9000>,
+			<8800 8600 8400 8200 8000 7800>,
+			<7600 7400 7200 7000 6800 6600>,
+			<6400 6200 6000 5800 5600 5400>,
+			<5200 5000 4800 4600 4400 4200>,
+			<4000 3800 3600 3400 3200 3000>,
+			<2800 2600 2400 2200 2000 1800>,
+			<1600 1400 1200 1000 900 800>,
+			<700 600 500 400 300 200>,
+			<100 0>;
+		qcom,lut-data = <7467 6132 5538 5158 5055 5027>,
+			<7418 6176 5550 5158 5053 5026>,
+			<7371 6205 5557 5158 5050 5025>,
+			<7326 6223 5561 5157 5048 5025>,
+			<7283 6232 5562 5156 5046 5025>,
+			<7242 6234 5562 5154 5046 5025>,
+			<7194 6227 5555 5152 5046 5025>,
+			<7159 6211 5540 5150 5047 5026>,
+			<7167 6191 5531 5149 5047 5027>,
+			<7202 6161 5522 5149 5048 5028>,
+			<7216 6144 5519 5149 5049 5029>,
+			<7195 6170 5520 5150 5051 5030>,
+			<7155 6214 5522 5151 5053 5031>,
+			<7075 6207 5523 5154 5055 5033>,
+			<6953 6119 5523 5160 5058 5035>,
+			<6899 6058 5522 5167 5061 5038>,
+			<6884 6060 5524 5172 5065 5041>,
+			<6872 6065 5527 5177 5070 5045>,
+			<6853 6054 5521 5188 5079 5052>,
+			<6834 5986 5487 5208 5095 5064>,
+			<6828 5923 5449 5216 5102 5070>,
+			<6826 5892 5413 5184 5083 5056>,
+			<6825 5871 5381 5138 5056 5035>,
+			<6839 5868 5365 5122 5045 5028>,
+			<6867 5872 5355 5114 5040 5024>,
+			<6893 5878 5349 5111 5038 5023>,
+			<6923 5895 5343 5112 5039 5023>,
+			<6956 5926 5339 5113 5040 5024>,
+			<6991 5960 5339 5115 5042 5026>,
+			<7030 5999 5342 5118 5045 5028>,
+			<7074 6044 5346 5121 5048 5031>,
+			<7122 6096 5354 5124 5053 5034>,
+			<7175 6156 5367 5126 5057 5038>,
+			<7232 6222 5383 5127 5059 5039>,
+			<7293 6297 5405 5127 5060 5039>,
+			<7357 6380 5430 5127 5058 5038>,
+			<7425 6470 5458 5124 5049 5032>,
+			<7495 6568 5491 5120 5041 5027>,
+			<7567 6667 5530 5121 5040 5027>,
+			<7643 6768 5579 5127 5041 5027>,
+			<7727 6867 5632 5133 5042 5028>,
+			<7816 6963 5689 5144 5044 5028>,
+			<7908 7053 5751 5155 5044 5028>,
+			<7994 7135 5817 5167 5043 5024>,
+			<7959 7206 5905 5181 5046 5026>,
+			<8096 7192 5921 5188 5056 5034>,
+			<8195 7214 5976 5205 5063 5044>,
+			<8412 7280 6034 5219 5072 5055>,
+			<8678 7350 6096 5248 5083 5055>,
+			<9031 7405 6155 5252 5069 5043>,
+			<9521 7454 6196 5257 5074 5046>,
+			<10251 7535 6282 5285 5084 5053>,
+			<11352 7666 6442 5320 5100 5069>,
+			<13075 7846 6646 5385 5148 5123>,
+			<13075 7846 6646 5385 5148 5123>,
+			<13075 7846 6646 5385 5148 5123>;
 	};
-
 };
diff --git a/arch/arm64/boot/dts/qcom/sda429-cdp.dts b/arch/arm64/boot/dts/qcom/sda429-cdp.dts
new file mode 100644
index 0000000..6b895f1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda429-cdp.dts
@@ -0,0 +1,24 @@
+/*
+ * 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 "sda429.dtsi"
+#include "sdm429-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA429 CDP";
+	compatible = "qcom,sda429-cdp", "qcom,sda429", "qcom,cdp";
+	qcom,board-id = <1 3>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda429-mtp.dts b/arch/arm64/boot/dts/qcom/sda429-mtp.dts
new file mode 100644
index 0000000..b27fec9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda429-mtp.dts
@@ -0,0 +1,24 @@
+/*
+ * 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 "sda429.dtsi"
+#include "sdm429-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA429 MTP";
+	compatible = "qcom,sda429-mtp", "qcom,sda429", "qcom,mtp";
+	qcom,board-id = <8 2>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda429.dtsi b/arch/arm64/boot/dts/qcom/sda429.dtsi
new file mode 100644
index 0000000..75c8d67
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda429.dtsi
@@ -0,0 +1,20 @@
+/*
+ * 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 "sdm429.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA429";
+	compatible = "qcom,sda429";
+	qcom,msm-id = <364 0x0>;
+	qcom,msm-name = "SDA429";
+};
diff --git a/arch/arm64/boot/dts/qcom/sda439-cdp.dts b/arch/arm64/boot/dts/qcom/sda439-cdp.dts
new file mode 100644
index 0000000..1194676
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda439-cdp.dts
@@ -0,0 +1,25 @@
+/*
+ * 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 "sda439.dtsi"
+#include "sdm439-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA439 CDP";
+	compatible = "qcom,sda439-cdp", "qcom,sda439", "qcom,cdp";
+	qcom,board-id = <1 2>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda439-mtp.dts b/arch/arm64/boot/dts/qcom/sda439-mtp.dts
new file mode 100644
index 0000000..edc5c85
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda439-mtp.dts
@@ -0,0 +1,24 @@
+/*
+ * 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 "sda439.dtsi"
+#include "sdm439-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA439 MTP";
+	compatible = "qcom,sda439-mtp", "qcom,sda439", "qcom,mtp";
+	qcom,board-id = <8 1>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda439.dtsi b/arch/arm64/boot/dts/qcom/sda439.dtsi
new file mode 100644
index 0000000..1600bef
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda439.dtsi
@@ -0,0 +1,21 @@
+/*
+ * 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 "sdm439.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA439";
+	compatible = "qcom,sda439";
+	qcom,msm-id = <363 0x0>;
+	qcom,msm-name = "SDA439";
+};
diff --git a/arch/arm64/boot/dts/qcom/sda450-cdp.dts b/arch/arm64/boot/dts/qcom/sda450-cdp.dts
new file mode 100644
index 0000000..e8f22b8
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450-cdp.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sda450.dtsi"
+#include "pmi8950.dtsi"
+#include "msm8953-cdp.dtsi"
+#include "msm8953-pmi8950.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450 + PMI8950 CDP";
+	compatible = "qcom,sda450-cdp", "qcom,sda450", "qcom,cdp";
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda450-mtp.dts b/arch/arm64/boot/dts/qcom/sda450-mtp.dts
new file mode 100644
index 0000000..06002e0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450-mtp.dts
@@ -0,0 +1,44 @@
+/*
+ * 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 "sda450.dtsi"
+#include "pmi8950.dtsi"
+#include "msm8953-mtp.dtsi"
+#include "msm8953-pmi8950.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450 + PMI8950 MTP";
+	compatible = "qcom,sda450-mtp", "qcom,sda450", "qcom,mtp";
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
+};
+
+/{
+	mtp_batterydata: qcom,battery-data {
+		qcom,batt-id-range-pct = <15>;
+		#include "batterydata-itech-3000mah.dtsi"
+		#include "batterydata-ascent-3450mAh.dtsi"
+	};
+};
+
+&qpnp_fg {
+	qcom,battery-data = <&mtp_batterydata>;
+};
+
+&qpnp_smbcharger {
+	qcom,battery-data = <&mtp_batterydata>;
+	qcom,chg-led-sw-controls;
+	qcom,chg-led-support;
+};
diff --git a/arch/arm64/boot/dts/qcom/sda450-pmi632-cdp-s2.dts b/arch/arm64/boot/dts/qcom/sda450-pmi632-cdp-s2.dts
new file mode 100644
index 0000000..14c5e22
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450-pmi632-cdp-s2.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sda450.dtsi"
+#include "sdm450-pmi632-cdp-s2.dtsi"
+#include "sdm450-pmi632.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450 + PMI632 CDP S2";
+	compatible = "qcom,sda450-cdp", "qcom,sda450", "qcom,cdp";
+	qcom,board-id = <1 2>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sda450-pmi632-mtp-s3.dts b/arch/arm64/boot/dts/qcom/sda450-pmi632-mtp-s3.dts
new file mode 100644
index 0000000..c907977
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450-pmi632-mtp-s3.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sda450.dtsi"
+#include "sdm450-pmi632-mtp-s3.dtsi"
+#include "sdm450-pmi632.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450 + PMI632 MTP S3";
+	compatible = "qcom,sda450-mtp", "qcom,sda450", "qcom,mtp";
+	qcom,board-id = <8 3>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sda450-pmi632.dts b/arch/arm64/boot/dts/qcom/sda450-pmi632.dts
new file mode 100644
index 0000000..1bb0b47
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450-pmi632.dts
@@ -0,0 +1,25 @@
+/*
+ * 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 "sda450.dtsi"
+#include "sdm450-pmi632.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450 + PMI632 SOC";
+	compatible = "qcom,sda450";
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+	qcom,pmic-name = "PMI632";
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sda450.dts b/arch/arm64/boot/dts/qcom/sda450.dts
new file mode 100644
index 0000000..13b1622
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sda450.dtsi"
+#include "pmi8950.dtsi"
+#include "msm8953-pmi8950.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450 + PMI8950 SOC";
+	compatible = "qcom,sda450";
+	qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
+	qcom,pmic-name = "PMI8950";
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sda450.dtsi b/arch/arm64/boot/dts/qcom/sda450.dtsi
new file mode 100644
index 0000000..ba99fe9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda450.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.
+ */
+
+#include "sdm450.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDA450";
+	compatible = "qcom,sda450";
+	qcom,msm-id = <351 0x0>;
+	qcom,msm-name = "SDA450";
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm429-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm429-cdp-overlay.dts
new file mode 100644
index 0000000..93a9ae9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm429-cdp-overlay.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/msm-clocks-8953.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "sdm429-cdp.dtsi"
+
+/ {
+	model = "CDP";
+	qcom,board-id = <1 3>;
+	qcom,msm-id = <354 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-cdp.dts b/arch/arm64/boot/dts/qcom/sdm429-cdp.dts
index f3312bd..14bba82 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-cdp.dts
@@ -19,6 +19,6 @@
 / {
 	model = "Qualcomm Technologies, Inc. SDM429 CDP";
 	compatible = "qcom,sdm429-cdp", "qcom,sdm429", "qcom,cdp";
-	qcom,board-id = <1 0>;
+	qcom,board-id = <1 3>;
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm429-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm429-cdp.dtsi
index 4ba4c00..d53ba37 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429-cdp.dtsi
@@ -12,3 +12,7 @@
  */
 
 #include "sdm439-cdp.dtsi"
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_hx8399c_hd_vid>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi b/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi
index 80f7007..80aeb24 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi
@@ -128,7 +128,7 @@
 
 		CPU_COST_0: core-cost0 {
 			busy-cost-data = <
-				 800000	137
+				 960000	159
 				1001600	165
 				1305600	207
 				1497600	256
@@ -141,7 +141,7 @@
 		};
 		CLUSTER_COST_0: cluster-cost0 {
 			busy-cost-data = <
-				 800000	49
+				 960000	52
 				1001600	53
 				1305600	61
 				1497600	71
@@ -154,3 +154,17 @@
 		};
 	};
 };
+
+&soc {
+	cpuss_dump {
+		/delete-node/ qcom,l2_dump0;
+		/delete-node/ qcom,l1_i_cache0;
+		/delete-node/ qcom,l1_i_cache1;
+		/delete-node/ qcom,l1_i_cache2;
+		/delete-node/ qcom,l1_i_cache3;
+		/delete-node/ qcom,l1_d_cache0;
+		/delete-node/ qcom,l1_d_cache1;
+		/delete-node/ qcom,l1_d_cache2;
+		/delete-node/ qcom,l1_d_cache3;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm429-mtp-overlay.dts
new file mode 100644
index 0000000..3a339da
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm429-mtp-overlay.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/msm-clocks-8953.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "sdm429-mtp.dtsi"
+
+/ {
+	model = "MTP";
+	qcom,board-id = <8 2>;
+	qcom,msm-id = <354 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-mtp.dts b/arch/arm64/boot/dts/qcom/sdm429-mtp.dts
index a809be7..d66ee61 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-mtp.dts
@@ -19,6 +19,6 @@
 / {
 	model = "Qualcomm Technologies, Inc. SDM429 MTP";
 	compatible = "qcom,sdm429-mtp", "qcom,sdm429", "qcom,mtp";
-	qcom,board-id = <8 0>;
+	qcom,board-id = <8 2>;
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm429-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm429-mtp.dtsi
index 839fa56..4f00be1 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429-mtp.dtsi
@@ -12,3 +12,7 @@
  */
 
 #include "sdm439-mtp.dtsi"
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_hx8399c_hd_vid>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm429-qrd-overlay.dts
new file mode 100644
index 0000000..8abccb7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm429-qrd-overlay.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/msm-clocks-8953.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "sdm429-qrd.dtsi"
+
+/ {
+	model = "QRD";
+	qcom,board-id = <0xb 3>;
+	qcom,msm-id = <354 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-qrd.dts b/arch/arm64/boot/dts/qcom/sdm429-qrd.dts
index d97cf54..034e221 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-qrd.dts
@@ -19,6 +19,6 @@
 / {
 	model = "Qualcomm Technologies, Inc. SDM429 QRD";
 	compatible = "qcom,sdm429-qrd", "qcom,sdm429", "qcom,qrd";
-	qcom,board-id = <0xb 0>;
+	qcom,board-id = <0xb 3>;
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm429.dts b/arch/arm64/boot/dts/qcom/sdm429.dts
new file mode 100644
index 0000000..d8538bb
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm429.dts
@@ -0,0 +1,23 @@
+/*
+ * 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 "sdm429.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM429 MTP";
+	compatible = "qcom,sdm429";
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+	qcom.pmic-name = "PMI632";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429.dtsi b/arch/arm64/boot/dts/qcom/sdm429.dtsi
index a4d2a80..49be6e4 100644
--- a/arch/arm64/boot/dts/qcom/sdm429.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429.dtsi
@@ -38,6 +38,53 @@
 			/delete-node/qcom,pm-cluster@1;
 		};
 	};
+
+	msm_cpufreq: qcom,msm-cpufreq {
+		compatible = "qcom,msm-cpufreq";
+		clock-names =
+			"l2_clk",
+			"cpu0_clk";
+		clocks = <&clock_cpu clk_cci_clk>,
+			 <&clock_cpu clk_a53_bc_clk>;
+
+		qcom,governor-per-policy;
+
+		qcom,cpufreq-table =
+			 <  960000 >,
+			 < 1305600 >,
+			 < 1497600 >,
+			 < 1708800 >,
+			 < 1958400 >;
+	};
+
+	devfreq-cpufreq {
+		cpubw-cpufreq {
+		target-dev = <&cpubw>;
+		cpu-to-dev-map =
+			< 960000   2929 >,
+			< 1305600  5053 >,
+			< 1497600  5712 >,
+			< 1708800  7031 >,
+			< 1958400  7031 >;
+		};
+
+		cci-cpufreq {
+		target-dev = <&cci_cache>;
+		cpu-to-dev-map =
+			< 960000   400000 >,
+			< 1305600  400000 >,
+			< 1497600  533333 >,
+			< 1708800  533333 >,
+			< 1958400  533333 >;
+		};
+
+		mincpubw-cpufreq {
+			target-dev = <&mincpubw>;
+			cpu-to-dev-map =
+				< 1305600 2929 >,
+				< 1958400 4248 >;
+		};
+	};
 };
 
 &funnel_apss {
@@ -61,3 +108,84 @@
 
 	/delete-node/ cpuss0-step;
 };
+
+&clock_gcc {
+	compatible = "qcom,gcc-sdm429";
+	reg = <0x1800000 0x80000>,
+		<0xb016000 0x00040>;
+	reg-names = "cc_base", "apcs_c1_base";
+	vdd_dig-supply = <&pm8953_s2_level>;
+	vdd_hf_dig-supply = <&pm8953_s2_level_ao>;
+	vdd_hf_pll-supply = <&pm8953_l7_ao>;
+};
+
+&clock_debug {
+	compatible = "qcom,cc-debug-8917";
+	reg = <0x1874000 0x4>,
+		<0xb01101c 0x8>;
+	reg-names = "cc_base", "meas";
+	#clock-cells = <1>;
+};
+
+&soc {
+	/delete-node/ qcom,cpu-clock-8939@b111050;
+	clock_cpu: qcom,cpu-clock-8939@b111050 {
+		compatible = "qcom,cpu-clock-sdm429";
+
+		reg =   <0xb011050 0x8>,
+			<0xb1d1050 0x8>,
+			<0x00a412c 0x8>;
+		reg-names = "apcs-c1-rcg-base",
+			"apcs-cci-rcg-base", "efuse";
+
+		qcom,num-cluster;
+		vdd-c1-supply = <&apc_vreg_corner>;
+		vdd-cci-supply = <&apc_vreg_corner>;
+
+		clocks = <&clock_gcc clk_gpll0_ao_clk_src>,
+			<&clock_gcc clk_a53ss_c1_pll>,
+			<&clock_gcc clk_gpll0_ao_clk_src>,
+			<&clock_gcc clk_gpll0_ao_clk_src>;
+		clock-names = "clk-c1-4", "clk-c1-5",
+				"clk-cci-4", "clk-cci-2";
+
+		qcom,speed0-bin-v0-c1 =
+			<          0 0>,
+			<  960000000 1>,
+			< 1305600000 1>,
+			< 1497600000 2>,
+			< 1708800000 3>,
+			< 1958400000 5>;
+
+		qcom,speed0-bin-v0-cci =
+			<          0 0>,
+			<  400000000 1>,
+			<  533333333 3>;
+
+		qcom,speed1-bin-v0-c1 =
+			<          0 0>,
+			<  960000000 1>,
+			< 1305600000 1>,
+			< 1497600000 2>,
+			< 1708800000 3>,
+			< 1804800000 5>;
+
+		qcom,speed1-bin-v0-cci =
+			<          0 0>,
+			<  400000000 1>,
+			<  533333333 3>;
+
+		#clock-cells = <1>;
+	};
+};
+
+&clock_gcc_mdss {
+	compatible = "qcom,gcc-mdss-sdm429";
+	clocks = <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_src>,
+		 <&mdss_dsi0_pll clk_dsi0pll_byte_clk_src>,
+		 <&mdss_dsi1_pll clk_dsi1pll_pixel_clk_src>,
+		 <&mdss_dsi1_pll clk_dsi1pll_byte_clk_src>;
+	clock-names = "pclk0_src", "byte0_src", "pclk1_src",
+		"byte1_src";
+	#clock-cells = <1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-qrd.dtsi
new file mode 100644
index 0000000..c2c9c79
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-qrd.dtsi
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2015-2016, 2018 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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.
+ */
+
+&cci {
+	actuator0: qcom,actuator@0 {
+		cell-index = <0>;
+		reg = <0x0>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+		cam_vaf-supply = <&pm8953_l17>;
+		qcom,cam-vreg-name = "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2850000>;
+		qcom,cam-vreg-max-voltage = <2850000>;
+		qcom,cam-vreg-op-mode = <80000>;
+	};
+
+	actuator1: qcom,actuator@1 {
+		cell-index = <1>;
+		reg = <0x1>;
+		compatible = "qcom,actuator";
+		qcom,cci-master = <0>;
+		cam_vaf-supply = <&pm8953_l17>;
+		qcom,cam-vreg-name = "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2850000>;
+		qcom,cam-vreg-max-voltage = <2850000>;
+		qcom,cam-vreg-op-mode = <80000>;
+	};
+
+	eeprom0: qcom,eeprom@0 {
+		cell-index = <0>;
+		compatible = "qcom,eeprom";
+		qcom,cci-master = <0>;
+		reg = <0x0>;
+		cam_vana-supply = <&pm8953_l22>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vaf-supply = <&pm8953_l17>;
+		cam_vdig-supply = <&pm8953_l3>;
+		qcom,cam-vreg-name = "cam_vana", "cam_vio",
+					"cam_vdig", "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000 0 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <2800000 0 1200000 2850000>;
+		qcom,cam-vreg-op-mode = <80000 0 200000 100000>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_default
+			&cam_sensor_rear_reset
+			&cam_sensor_rear_vana>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep
+			&cam_sensor_rear_reset_sleep
+			&cam_sensor_rear_vana_sleep>;
+		gpios = <&tlmm 26 0>,
+			<&tlmm 36 0>,
+			<&tlmm 35 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+			"CAM_RESET0",
+			"CAM_VANA";
+		status = "ok";
+		clocks = <&clock_gcc clk_mclk0_clk_src>,
+			<&clock_gcc clk_gcc_camss_mclk0_clk>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <19200000 0>;
+	};
+
+	eeprom1: qcom,eeprom@1 {
+		cell-index = <1>;
+		reg = <0x1>;
+		qcom,eeprom-name = "sunny_8865";
+		compatible = "qcom,eeprom";
+		qcom,slave-addr = <0x6c>;
+		qcom,cci-master = <0>;
+		qcom,num-blocks = <8>;
+
+		qcom,page0 = <1 0x0100 2 0x01 1 1>;
+		qcom,poll0 = <0 0x0 2 0x0 1 0>;
+		qcom,mem0 = <0 0x0 2 0x0 1 0>;
+
+		qcom,page1 = <1 0x5002 2 0x00 1 0>;
+		qcom,poll1 = <0 0x0 2 0x0 1 0>;
+		qcom,mem1 = <0 0x0 2 0x0 1 0>;
+
+		qcom,page2 = <1 0x3d84 2 0xc0 1 0>;
+		qcom,poll2 = <0 0x0 2 0x0 1 0>;
+		qcom,mem2 = <0 0x0 2 0x0 1 0>;
+
+		qcom,page3 = <1 0x3d88 2 0x70 1 0>;
+		qcom,poll3 = <0 0x0 2 0x0 1 0>;
+		qcom,mem3 = <0 0x0 2 0x0 1 0>;
+
+		qcom,page4 = <1 0x3d89 2 0x10 1 0>;
+		qcom,poll4 = <0 0x0 2 0x0 1 0>;
+		qcom,mem4 = <0 0x0 2 0x0 1 0>;
+
+		qcom,page5 = <1 0x3d8a 2 0x70 1 0>;
+		qcom,poll5 = <0 0x0 2 0x0 1 0>;
+		qcom,mem5 = <0 0x0 2 0x0 1 0>;
+
+		qcom,page6 = <1 0x3d8b 2 0xf4 1 0>;
+		qcom,poll6 = <0 0x0 2 0x0 1 0>;
+		qcom,mem6 = <0 0x0 2 0x0 1 0>;
+
+		qcom,page7 = <1 0x3d81 2 0x01 1 10>;
+		qcom,poll7 = <0 0x0 2 0x0 1 1>;
+		qcom,mem7 = <1536 0x7010 2 0 1 0>;
+
+		cam_vdig-supply = <&pm8953_l23>;
+		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";
+		qcom,cam-power-seq-type = "sensor_vreg", "sensor_vreg",
+			"sensor_vreg",
+			"sensor_gpio", "sensor_gpio" , "sensor_clk";
+		qcom,cam-power-seq-val = "cam_vdig", "cam_vana", "cam_vio",
+			"sensor_gpio_reset", "sensor_gpio_standby",
+			"sensor_cam_mclk";
+		qcom,cam-power-seq-cfg-val = <1 1 1 1 1 24000000>;
+		qcom,cam-power-seq-delay = <1 1 1 30 30 5>;
+		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";
+		reg = <0x0>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,mount-angle = <90>;
+		qcom,led-flash-src = <&led_flash0>;
+		qcom,eeprom-src = <&eeprom0>;
+		qcom,actuator-src = <&actuator0>;
+		cam_vana-supply = <&pm8953_l22>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vaf-supply = <&pm8953_l17>;
+		cam_vdig-supply = <&pm8953_l3>;
+		qcom,cam-vreg-name = "cam_vana", "cam_vio",
+				"cam_vdig", "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000 0 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <2800000 0 1200000 2850000>;
+		qcom,cam-vreg-op-mode = <80000 0 200000 100000>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_default
+				&cam_sensor_rear_reset
+				&cam_sensor_rear_vana>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep
+				&cam_sensor_rear_reset_sleep
+				&cam_sensor_rear_vana_sleep>;
+		gpios = <&tlmm 26 0>,
+			<&tlmm 36 0>,
+			<&tlmm 35 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+			"CAM_RESET0",
+			"CAM_VANA";
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <0>;
+		status = "ok";
+		clocks = <&clock_gcc clk_mclk0_clk_src>,
+				<&clock_gcc clk_gcc_camss_mclk0_clk>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+	qcom,camera@1 {
+		cell-index = <1>;
+		compatible = "qcom,camera";
+		reg = <0x1>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <270>;
+		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 = <200000 0 80000 100000>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_default
+				&cam_sensor_front_default>;
+		pinctrl-1 = <&cam_sensor_mclk1_sleep
+				&cam_sensor_front_sleep>;
+		gpios = <&tlmm 27 0>,
+			<&tlmm 38 0>,
+			<&tlmm 50 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_MCLK1",
+			"CAM_RESET1",
+			"CAM_STANDBY1";
+		qcom,sensor-position = <0x100>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <1>;
+		clocks = <&clock_gcc clk_mclk1_clk_src>,
+				<&clock_gcc clk_gcc_camss_mclk1_clk>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+	qcom,camera@2 {
+		cell-index = <2>;
+		compatible = "qcom,camera";
+		reg = <0x02>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <270>;
+		qcom,eeprom-src = <&eeprom1>;
+		qcom,actuator-src = <&actuator1>;
+		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 27 0>,
+			<&tlmm 38 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";
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <0>;
+		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 = <24000000 0>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm439-cdp-overlay.dts
new file mode 100644
index 0000000..6d6f99b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-cdp-overlay.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/msm-clocks-8953.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "sdm439-cdp.dtsi"
+
+/ {
+	model = "CDP";
+	qcom,board-id = <1 2>;
+	qcom,msm-id = <353 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-cdp.dts b/arch/arm64/boot/dts/qcom/sdm439-cdp.dts
index 1306230..0128c65 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm439-cdp.dts
@@ -19,6 +19,6 @@
 / {
 	model = "Qualcomm Technologies, Inc. SDM439 CDP";
 	compatible = "qcom,sdm439-cdp", "qcom,sdm439", "qcom,cdp";
-	qcom,board-id = <1 0>;
+	qcom,board-id = <1 2>;
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
index 83a4651..0ad5dfe 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
@@ -17,6 +17,40 @@
 	status = "ok";
 };
 
+&pm8953_gpios {
+	nfc_clk {
+		nfc_clk_default: nfc_clk_default {
+			pins = "gpio2";
+			function = "normal";
+			input-enable;
+			power-source = <1>;
+		};
+	};
+};
+
+&i2c_5 { /* BLSP2 QUP1 (NFC) */
+	status = "ok";
+	nq@28 {
+		compatible = "qcom,nq-nci";
+		reg = <0x28>;
+		qcom,nq-irq = <&tlmm 17 0x00>;
+		qcom,nq-ven = <&tlmm 16 0x00>;
+		qcom,nq-firm = <&tlmm 130 0x00>;
+		qcom,nq-clkreq = <&pm8953_gpios 2 0x00>;
+		qcom,nq-esepwr = <&tlmm 93 0x00>;
+		interrupt-parent = <&tlmm>;
+		qcom,clk-src = "BBCLK2";
+		interrupts = <17 0>;
+		interrupt-names = "nfc_irq";
+		pinctrl-names = "nfc_active", "nfc_suspend";
+		pinctrl-0 = <&nfc_int_active &nfc_disable_active
+						&nfc_clk_default>;
+		pinctrl-1 = <&nfc_int_suspend &nfc_disable_suspend>;
+		clocks = <&clock_gcc clk_bb_clk2_pin>;
+		clock-names = "ref_clk";
+	};
+};
+
 &sdhc_1 {
 	/* device core power supply */
 	vdd-supply = <&pm8953_l8>;
@@ -138,15 +172,18 @@
 
 	qcom,platform-bklight-en-gpio = <&pm8953_gpios 4 0>;
 	qcom,platform-te-gpio = <&tlmm 24 0>;
-	qcom,platform-reset-gpio = <&tlmm 61 0>;
+	qcom,platform-reset-gpio = <&tlmm 60 0>;
 	lab-supply = <&lcdb_ldo_vreg>;
 	ibb-supply = <&lcdb_ncp_vreg>;
+};
 
+&mdss_dsi1 {
+	status = "disabled";
 };
 
 &dsi_hx8399c_truly_vid {
-	qcom,mdss-dsi-panel-timings =
-		[f3 3a 26 00 6c 6e 2c 3e 2f 03 04 00];
+	/delete-property/ qcom,mdss-dsi-panel-timings;
+	qcom,mdss-dsi-panel-timings-phy-12nm = [18 0a 10 06 03 08 06 0e];
 	qcom,mdss-dsi-t-clk-post = <0x02>;
 	qcom,mdss-dsi-t-clk-pre = <0x2d>;
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
@@ -154,15 +191,13 @@
 	qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
 	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
 	qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
-	qcom,mdss-dsi-pan-enable-dynamic-fps;
-	qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
 };
 
 
 &dsi_hx8399c_hd_vid {
+	/delete-property/ qcom,mdss-dsi-panel-timings;
+	qcom,mdss-dsi-panel-timings-phy-12nm = [08 06 0a 02 00 04 02 08];
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
-	qcom,mdss-dsi-pan-enable-dynamic-fps;
-	qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
 	qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
 	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm439-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm439-mtp-overlay.dts
new file mode 100644
index 0000000..df8a0d7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-mtp-overlay.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/msm-clocks-8953.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "sdm439-mtp.dtsi"
+
+/ {
+	model = "MTP";
+	qcom,board-id = <8 1>;
+	qcom,msm-id = <353 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-mtp.dts b/arch/arm64/boot/dts/qcom/sdm439-mtp.dts
index 9f221f0..77f3039 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm439-mtp.dts
@@ -19,6 +19,6 @@
 / {
 	model = "Qualcomm Technologies, Inc. SDM439 MTP";
 	compatible = "qcom,sdm439-mtp", "qcom,sdm439", "qcom,mtp";
-	qcom,board-id = <8 0>;
+	qcom,board-id = <8 1>;
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
index 17218a8..50f8ae1 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
@@ -17,6 +17,40 @@
 	status = "ok";
 };
 
+&pm8953_gpios {
+	nfc_clk {
+		nfc_clk_default: nfc_clk_default {
+			pins = "gpio2";
+			function = "normal";
+			input-enable;
+			power-source = <1>;
+		};
+	};
+};
+
+&i2c_5 { /* BLSP2 QUP1 (NFC) */
+	status = "ok";
+	nq@28 {
+		compatible = "qcom,nq-nci";
+		reg = <0x28>;
+		qcom,nq-irq = <&tlmm 17 0x00>;
+		qcom,nq-ven = <&tlmm 16 0x00>;
+		qcom,nq-firm = <&tlmm 130 0x00>;
+		qcom,nq-clkreq = <&pm8953_gpios 2 0x00>;
+		qcom,nq-esepwr = <&tlmm 93 0x00>;
+		interrupt-parent = <&tlmm>;
+		qcom,clk-src = "BBCLK2";
+		interrupts = <17 0>;
+		interrupt-names = "nfc_irq";
+		pinctrl-names = "nfc_active", "nfc_suspend";
+		pinctrl-0 = <&nfc_int_active &nfc_disable_active
+						&nfc_clk_default>;
+		pinctrl-1 = <&nfc_int_suspend &nfc_disable_suspend>;
+		clocks = <&clock_gcc clk_bb_clk2_pin>;
+		clock-names = "ref_clk";
+	};
+};
+
 &sdhc_1 {
 	/* device core power supply */
 	vdd-supply = <&pm8953_l8>;
@@ -138,15 +172,18 @@
 
 	qcom,platform-bklight-en-gpio = <&pm8953_gpios 4 0>;
 	qcom,platform-te-gpio = <&tlmm 24 0>;
-	qcom,platform-reset-gpio = <&tlmm 61 0>;
+	qcom,platform-reset-gpio = <&tlmm 60 0>;
 	lab-supply = <&lcdb_ldo_vreg>;
 	ibb-supply = <&lcdb_ncp_vreg>;
+};
 
+&mdss_dsi1 {
+	status = "disabled";
 };
 
 &dsi_hx8399c_truly_vid {
-	qcom,mdss-dsi-panel-timings =
-		[f3 3a 26 00 6c 6e 2c 3e 2f 03 04 00];
+	/delete-property/ qcom,mdss-dsi-panel-timings;
+	qcom,mdss-dsi-panel-timings-phy-12nm = [18 0a 10 06 03 08 06 0e];
 	qcom,mdss-dsi-t-clk-post = <0x02>;
 	qcom,mdss-dsi-t-clk-pre = <0x2d>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
@@ -154,14 +191,12 @@
 	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
 	qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
-	qcom,mdss-dsi-pan-enable-dynamic-fps;
-	qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
 };
 
 &dsi_hx8399c_hd_vid {
+	/delete-property/ qcom,mdss-dsi-panel-timings;
+	qcom,mdss-dsi-panel-timings-phy-12nm = [08 06 0a 02 00 04 02 08];
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
-	qcom,mdss-dsi-pan-enable-dynamic-fps;
-	qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
 	qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
 	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi b/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi
index 3c8a298..d34c34a 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi
@@ -125,8 +125,23 @@
 };
 
 &mdss_dsi {
-	vdda-supply = <&pm8953_l2>; /*1.2V*/
-	vddio-supply = <&pm8953_l6>; /*1.8V*/
+	vdda-supply = <&pm8953_l23>;
+	vddio-supply = <&pm8953_l5>;
+
+	qcom,ctrl-supply-entries {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,ctrl-supply-entry@0 {
+			reg = <0>;
+			qcom,supply-name = "vdda";
+			qcom,supply-min-voltage = <800000>;
+			qcom,supply-max-voltage = <800000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-post-on-sleep = <20>;
+		};
+	};
 };
 
 &usb_otg {
diff --git a/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi b/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi
index 5075862..300c83a 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi
@@ -39,6 +39,10 @@
 	qcom,battery-data = <&mtp_batterydata>;
 };
 
+&pmi632_charger {
+	qcom,battery-data = <&mtp_batterydata>;
+};
+
 &pm8953_typec {
 	status = "disabled";
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm439-qrd-overlay.dts
new file mode 100644
index 0000000..ac059c4d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd-overlay.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/clock/msm-clocks-8953.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "sdm439-qrd.dtsi"
+
+/ {
+	model = "QRD";
+	qcom,board-id = <0xb 2>;
+	qcom,msm-id = <353 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd.dts b/arch/arm64/boot/dts/qcom/sdm439-qrd.dts
index 7b93e0c..b8a9f2b 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd.dts
@@ -19,6 +19,13 @@
 / {
 	model = "Qualcomm Technologies, Inc. SDM439 QRD";
 	compatible = "qcom,sdm439-qrd", "qcom,sdm439", "qcom,qrd";
-	qcom,board-id = <0xb 0>;
+	qcom,board-id = <0xb 2>;
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
+
+&pmi632_vadc {
+	chan@4a {
+		qcom,scale-function = <22>;
+	};
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
index 24748dd..6d19786 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
@@ -11,6 +11,9 @@
  * GNU General Public License for more details.
  */
 
+#include "msm8937-mdss-panels.dtsi"
+#include "sdm439-camera-sensor-qrd.dtsi"
+
 &blsp1_uart2 {
 	status = "ok";
 };
@@ -58,6 +61,40 @@
 	status = "okay";
 };
 
+&pm8953_gpios {
+	nfc_clk {
+		nfc_clk_default: nfc_clk_default {
+			pins = "gpio2";
+			function = "normal";
+			input-enable;
+			power-source = <1>;
+		};
+	};
+};
+
+&i2c_5 { /* BLSP2 QUP1 (NFC) */
+	status = "ok";
+	nq@28 {
+		compatible = "qcom,nq-nci";
+		reg = <0x28>;
+		qcom,nq-irq = <&tlmm 17 0x00>;
+		qcom,nq-ven = <&tlmm 16 0x00>;
+		qcom,nq-firm = <&tlmm 130 0x00>;
+		qcom,nq-clkreq = <&pm8953_gpios 2 0x00>;
+		qcom,nq-esepwr = <&tlmm 93 0x00>;
+		interrupt-parent = <&tlmm>;
+		qcom,clk-src = "BBCLK2";
+		interrupts = <17 0>;
+		interrupt-names = "nfc_irq";
+		pinctrl-names = "nfc_active", "nfc_suspend";
+		pinctrl-0 = <&nfc_int_active &nfc_disable_active
+						&nfc_clk_default>;
+		pinctrl-1 = <&nfc_int_suspend &nfc_disable_suspend>;
+		clocks = <&clock_gcc clk_bb_clk2_pin>;
+		clock-names = "ref_clk";
+	};
+};
+
 &sdhc_2 {
 	/* device core power supply */
 	vdd-supply = <&pm8953_l11>;
@@ -100,3 +137,150 @@
 		};
 	};
 };
+
+&tlmm {
+	pmx_ts_rst_active {
+		ts_rst_active: ts_rst_active {
+			mux {
+				pins = "gpio99";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio99";
+				drive-strength = <16>;
+				bias-pull-up;
+			};
+		};
+	};
+
+	pmx_ts_rst_suspend {
+		ts_rst_suspend: ts_rst_suspend {
+			mux {
+				pins = "gpio99";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio99";
+				drive-strength = <2>;
+				bias-pull-down;
+			};
+		};
+	};
+};
+
+&soc {
+	hbtp {
+		compatible = "qcom,hbtp-input";
+		pinctrl-names = "pmx_ts_active", "pmx_ts_suspend";
+		pinctrl-0 = <&ts_rst_active>;
+		pinctrl-1 = <&ts_rst_suspend>;
+		vcc_ana-supply = <&pm8953_l10>;
+		vcc_dig-supply = <&pm8953_l5>;
+		qcom,afe-load = <20000>;
+		qcom,afe-vtg-min = <3000000>;
+		qcom,afe-vtg-max = <3000000>;
+		qcom,dig-load = <40000>;
+		qcom,dig-vtg-min = <1800000>;
+		qcom,dig-vtg-max = <1800000>;
+		qcom,fb-resume-delay-us = <1000>;
+		qcom,afe-force-power-on;
+		qcom,afe-power-on-delay-us = <6>;
+		qcom,afe-power-off-delay-us = <6>;
+	};
+};
+
+&tlmm {
+	pmx_mdss {
+		mdss_dsi_active: mdss_dsi_active {
+			mux {
+				pins = "gpio60";
+			};
+			config {
+				pins = "gpio60";
+			};
+		};
+		mdss_dsi_suspend: mdss_dsi_suspend {
+			mux {
+				pins = "gpio60";
+			};
+			config {
+				pins = "gpio60";
+			};
+		};
+	};
+};
+
+&dsi_panel_pwr_supply {
+	qcom,panel-supply-entry@0 {
+		reg = <0>;
+		qcom,supply-name = "bklight_en";
+		qcom,supply-min-voltage = <1800000>;
+		qcom,supply-max-voltage = <1800000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+
+	qcom,panel-supply-entry@2 {
+		reg = <2>;
+		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@3 {
+		reg = <3>;
+		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 = <10>;
+	};
+};
+
+&mdss_dsi {
+	hw-config = "single_dsi";
+};
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+	lab-supply = <&lcdb_ldo_vreg>;
+	ibb-supply = <&lcdb_ncp_vreg>;
+	bklight_en-supply = <&pm8953_l5>;
+	vddio-supply = <&pm8953_l6>;
+
+	qcom,dsi-pref-prim-pan = <&dsi_hx8399c_truly_vid>;
+	/delete-property/ qcom,platform-bklight-en-gpio;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+	pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+	qcom,platform-te-gpio = <&tlmm 24 0>;
+	qcom,platform-reset-gpio = <&tlmm 60 0>;
+};
+
+&mdss_dsi1 {
+	status = "disabled";
+};
+
+&pm8953_pwm {
+	status = "ok";
+};
+
+&dsi_hx8399c_truly_vid {
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+	qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+	qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	/delete-property/ qcom,mdss-dsi-panel-timings;
+	qcom,mdss-dsi-panel-timings-phy-12nm = [18 0a 10 06 03 08 06 0e];
+	qcom,mdss-dsi-t-clk-post = <0x02>;
+	qcom,mdss-dsi-t-clk-pre = <0x2d>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
index 08c9e4f..f325925 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
@@ -21,7 +21,7 @@
 			regulator-min-microvolt =
 					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
 			regulator-max-microvolt =
-					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+					<RPM_SMD_REGULATOR_LEVEL_BINNING>;
 			qcom,use-voltage-level;
 			status = "okay";
 		};
@@ -37,7 +37,7 @@
 			regulator-min-microvolt =
 					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
 			regulator-max-microvolt =
-					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+					<RPM_SMD_REGULATOR_LEVEL_BINNING>;
 			qcom,use-voltage-level;
 		};
 
@@ -48,7 +48,7 @@
 			regulator-min-microvolt =
 					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
 			regulator-max-microvolt =
-					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+					<RPM_SMD_REGULATOR_LEVEL_BINNING>;
 			qcom,use-voltage-floor-level;
 			qcom,always-send-voltage;
 		};
@@ -60,7 +60,7 @@
 			regulator-min-microvolt =
 					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
 			regulator-max-microvolt =
-					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+					<RPM_SMD_REGULATOR_LEVEL_BINNING>;
 			qcom,use-voltage-level;
 		};
 
@@ -76,9 +76,9 @@
 	rpm-regulator-smpa3 {
 		status = "okay";
 		pm8953_s3: regulator-s3 {
-			regulator-min-microvolt = <1280000>;
+			regulator-min-microvolt = <856000>;
 			regulator-max-microvolt = <1280000>;
-			qcom,init-voltage = <1280000>;
+			qcom,init-voltage = <856000>;
 			status = "okay";
 		};
 	};
@@ -86,9 +86,9 @@
 	rpm-regulator-smpa4 {
 		status = "okay";
 		pm8953_s4: regulator-s4 {
-			regulator-min-microvolt = <2040000>;
+			regulator-min-microvolt = <1900000>;
 			regulator-max-microvolt = <2040000>;
-			qcom,init-voltage = <2040000>;
+			qcom,init-voltage = <1900000>;
 			status = "okay";
 		};
 	};
@@ -103,7 +103,7 @@
 			regulator-min-microvolt =
 					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
 			regulator-max-microvolt =
-					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+					<RPM_SMD_REGULATOR_LEVEL_BINNING>;
 			qcom,init-voltage-level =
 					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
 			qcom,use-voltage-level;
@@ -117,7 +117,7 @@
 			regulator-min-microvolt =
 					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
 			regulator-max-microvolt =
-					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+					<RPM_SMD_REGULATOR_LEVEL_BINNING>;
 			qcom,use-voltage-level;
 			qcom,always-send-voltage;
 		};
@@ -129,7 +129,7 @@
 			regulator-min-microvolt =
 					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
 			regulator-max-microvolt =
-					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+					<RPM_SMD_REGULATOR_LEVEL_BINNING>;
 			qcom,init-voltage-level =
 					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
 			qcom,use-voltage-level;
@@ -139,9 +139,9 @@
 	rpm-regulator-ldoa1 {
 		status = "okay";
 		pm8953_l1: regulator-l1 {
-			regulator-min-microvolt = <1000000>;
-			regulator-max-microvolt = <1000000>;
-			qcom,init-voltage = <1000000>;
+			regulator-min-microvolt = <968000>;
+			regulator-max-microvolt = <1152000>;
+			qcom,init-voltage = <968000>;
 			status = "okay";
 		};
 	};
@@ -159,9 +159,9 @@
 	rpm-regulator-ldoa3 {
 		status = "okay";
 		pm8953_l3: regulator-l3 {
-			regulator-min-microvolt = <1200000>;
+			regulator-min-microvolt = <1140000>;
 			regulator-max-microvolt = <1200000>;
-			qcom,init-voltage = <1200000>;
+			qcom,init-voltage = <1140000>;
 			status = "okay";
 		};
 	};
@@ -236,9 +236,9 @@
 	rpm-regulator-ldoa9 {
 		status = "okay";
 		pm8953_l9: regulator-l9 {
-			regulator-min-microvolt = <3300000>;
+			regulator-min-microvolt = <3000000>;
 			regulator-max-microvolt = <3300000>;
-			qcom,init-voltage = <3300000>;
+			qcom,init-voltage = <3000000>;
 			status = "okay";
 		};
 	};
@@ -246,9 +246,9 @@
 	rpm-regulator-ldoa10 {
 		status = "okay";
 		pm8953_l10: regulator-l10 {
-			regulator-min-microvolt = <3000000>;
-			regulator-max-microvolt = <3000000>;
-			qcom,init-voltage = <3000000>;
+			regulator-min-microvolt = <2948000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <2948000>;
 			status = "okay";
 		};
 	};
@@ -256,9 +256,9 @@
 	rpm-regulator-ldoa11 {
 		status = "okay";
 		pm8953_l11: regulator-l11 {
-			regulator-min-microvolt = <2950000>;
-			regulator-max-microvolt = <2950000>;
-			qcom,init-voltage = <2950000>;
+			regulator-min-microvolt = <2700000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <2700000>;
 			status = "okay";
 		};
 	};
@@ -266,9 +266,9 @@
 	rpm-regulator-ldoa12 {
 		status = "okay";
 		pm8953_l12: regulator-l12 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <2950000>;
-			qcom,init-voltage = <1800000>;
+			regulator-min-microvolt = <1648000>;
+			regulator-max-microvolt = <3100000>;
+			qcom,init-voltage = <1648000>;
 			status = "okay";
 		};
 	};
@@ -276,9 +276,9 @@
 	rpm-regulator-ldoa13 {
 		status = "okay";
 		pm8953_l13: regulator-l13 {
-			regulator-min-microvolt = <3075000>;
-			regulator-max-microvolt = <3300000>;
-			qcom,init-voltage = <3075000>;
+			regulator-min-microvolt = <3050000>;
+			regulator-max-microvolt = <3100000>;
+			qcom,init-voltage = <3050000>;
 			status = "okay";
 		};
 	};
@@ -295,7 +295,7 @@
 			regulator-name = "pm8953_l14";
 			qcom,set = <3>;
 			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <2950000>;
+			regulator-max-microvolt = <3052000>;
 			qcom,init-voltage = <1800000>;
 			status = "okay";
 		};
@@ -313,7 +313,7 @@
 			regulator-name = "pm8953_l15";
 			qcom,set = <3>;
 			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <2950000>;
+			regulator-max-microvolt = <3052000>;
 			qcom,init-voltage = <1800000>;
 			status = "okay";
 		};
@@ -332,9 +332,9 @@
 	rpm-regulator-ldoa17 {
 		status = "okay";
 		pm8953_l17: regulator-l17 {
-			regulator-min-microvolt = <2850000>;
-			regulator-max-microvolt = <2850000>;
-			qcom,init-voltage = <2850000>;
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2900000>;
+			qcom,init-voltage = <2800000>;
 			status = "okay";
 		};
 	};
@@ -342,9 +342,9 @@
 	rpm-regulator-ldoa19 {
 		status = "okay";
 		pm8953_l19: regulator-l19 {
-			regulator-min-microvolt = <1300000>;
-			regulator-max-microvolt = <1350000>;
-			qcom,init-voltage = <1300000>;
+			regulator-min-microvolt = <1224000>;
+			regulator-max-microvolt = <1356000>;
+			qcom,init-voltage = <1224000>;
 			status = "okay";
 		};
 	};
@@ -352,9 +352,9 @@
 	rpm-regulator-ldoa22 {
 		status = "okay";
 		pm8953_l22: regulator-l22 {
-			regulator-min-microvolt = <2800000>;
-			regulator-max-microvolt = <2800000>;
-			qcom,init-voltage = <2800000>;
+			regulator-min-microvolt = <2560000>;
+			regulator-max-microvolt = <2840000>;
+			qcom,init-voltage = <2560000>;
 			status = "okay";
 		};
 	};
@@ -363,7 +363,7 @@
 		status = "okay";
 		pm8953_l23: regulator-l23 {
 			regulator-min-microvolt = <800000>;
-			regulator-max-microvolt = <800000>;
+			regulator-max-microvolt = <1000000>;
 			qcom,init-voltage = <800000>;
 			status = "okay";
 		};
@@ -388,3 +388,85 @@
 		};
 	};
 };
+
+&soc {
+	apc_mem_acc_vreg: apc-mem-acc-regulator {
+		compatible = "qcom,mem-acc-regulator";
+		regulator-name = "apc_mem_acc_corner";
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <2>;
+		qcom,acc-reg-addr-list = <0x01942138 0x01942130 0x01946004>;
+		qcom,acc-init-reg-config = <1 0xff>;
+		qcom,num-acc-corners = <2>;
+		qcom,boot-acc-corner = <1>;
+		qcom,corner1-reg-config =
+			/* 1 -> 1 */
+			<(-1) (-1)>, <(-1) (-1)>,
+			/* 1 -> 2 */
+			<  2 0xffff>, < 3  0xff>;
+		qcom,corner2-reg-config =
+			/* 2 -> 1 */
+			<  2 0x5555>, < 3  0x55>,
+			/* 2 -> 2 */
+			<(-1) (-1)>, <(-1) (-1)>;
+	};
+
+	apc_vreg_corner: regulator@b018000 {
+		compatible = "qcom,cpr-regulator";
+		reg = <0xb018000 0x1000>, <0xb011064 4>, <0xa4000 0x1000>;
+		reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
+		interrupts = <0 15 0>;
+		regulator-name = "apc_corner";
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <5>;
+
+		qcom,cpr-fuse-corners = <3>;
+		qcom,cpr-voltage-ceiling = <760000 795000 910000>;
+		qcom,cpr-voltage-floor =   <700000 700000 790000>;
+		vdd-apc-supply = <&pm8953_s5>;
+		mem-acc-supply = <&apc_mem_acc_vreg>;
+		qcom,mem-acc-corner-map = <1 1 1 1 2>;
+
+		qcom,cpr-ref-clk = <19200>;
+		qcom,cpr-timer-delay = <5000>;
+		qcom,cpr-timer-cons-up = <0>;
+		qcom,cpr-timer-cons-down = <2>;
+		qcom,cpr-irq-line = <0>;
+		qcom,cpr-step-quotient = <10>;
+		qcom,cpr-up-threshold = <2>;
+		qcom,cpr-down-threshold = <4>;
+		qcom,cpr-idle-clocks = <15>;
+		qcom,cpr-gcnt-time = <1>;
+		qcom,vdd-apc-step-up-limit = <1>;
+		qcom,vdd-apc-step-down-limit = <1>;
+		qcom,cpr-apc-volt-step = <5000>;
+
+		qcom,cpr-fuse-row = <67 0>;
+		qcom,cpr-fuse-target-quot = <42 24 6>;
+		qcom,cpr-fuse-ro-sel = <60 57 54>;
+		qcom,cpr-init-voltage-ref = <760000 795000 910000>;
+		qcom,cpr-fuse-init-voltage =
+					<67 36 6 0>,
+					<67 18 6 0>,
+					<67  0 6 0>;
+		qcom,cpr-fuse-quot-offset =
+					<71 26 6 0>,
+					<71 20 6 0>,
+					<70 54 7 0>;
+		qcom,cpr-fuse-quot-offset-scale = <5 5 5>;
+		qcom,cpr-init-voltage-step = <10000>;
+		qcom,cpr-corner-map = <1 2 3 3 3>;
+		qcom,cpr-corner-frequency-map =
+				<1 1305600000>,
+				<2 1497600000>,
+				<3 1708800000>,
+				<4 1804800000>,
+				<5 1958400000>;
+		qcom,speed-bin-fuse-sel = <37 34 3 0>;
+		qcom,cpr-speed-bin-max-corners = <(-1) (-1) 1 2 5>;
+		qcom,cpr-fuse-revision = <69 39 3 0>;
+		qcom,cpr-quot-adjust-scaling-factor-max = <0 1400 1400>;
+		qcom,cpr-voltage-scaling-factor-max = <0 2000 2000>;
+		qcom,cpr-scaled-init-voltage-as-ceiling;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439.dts b/arch/arm64/boot/dts/qcom/sdm439.dts
new file mode 100644
index 0000000..bf7a815
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439.dts
@@ -0,0 +1,23 @@
+/*
+ * 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 "sdm439.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM439 MTP";
+	compatible = "qcom,sdm439";
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+	qcom.pmic-name = "PMI632";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439.dtsi b/arch/arm64/boot/dts/qcom/sdm439.dtsi
index 422a95f..74d97a6 100644
--- a/arch/arm64/boot/dts/qcom/sdm439.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439.dtsi
@@ -23,13 +23,85 @@
 
 &soc {
 	qcom,csid@1b30000 {
-		/delete-property/ qcom,mipi-csi-vdd-supply;
+		qcom,csi-vdd-voltage = <800000>;
+		qcom,mipi-csi-vdd-supply = <&pm8953_l23>;
 	};
 	qcom,csid@1b30400 {
-		/delete-property/ qcom,mipi-csi-vdd-supply;
+		qcom,csi-vdd-voltage = <800000>;
+		qcom,mipi-csi-vdd-supply = <&pm8953_l23>;
 	};
 	qcom,csid@1b30800 {
-		/delete-property/ qcom,mipi-csi-vdd-supply;
+		qcom,csi-vdd-voltage = <800000>;
+		qcom,mipi-csi-vdd-supply = <&pm8953_l23>;
+	};
+
+	msm_cpufreq: qcom,msm-cpufreq {
+		compatible = "qcom,msm-cpufreq";
+		clock-names =
+			"l2_clk",
+			"cpu0_clk",
+			"cpu4_clk";
+		clocks = <&clock_cpu clk_cci_clk>,
+			 <&clock_cpu clk_a53_bc_clk>,
+			 <&clock_cpu clk_a53_lc_clk>;
+
+		qcom,governor-per-policy;
+
+		qcom,cpufreq-table-0 =
+			 < 1305600 >,
+			 < 1497600 >,
+			 < 1708800 >,
+			 < 1958400 >;
+
+		qcom,cpufreq-table-4 =
+			 <  768000 >,
+			 < 1001600 >,
+			 < 1171200 >,
+			 < 1305600 >,
+			 < 1459200 >;
+	};
+
+	devfreq-cpufreq {
+		cpubw-cpufreq {
+		target-dev = <&cpubw>;
+		cpu-to-dev-map-0 =
+			< 1305600  2929 >,
+			< 1497600  5053 >,
+			< 1708800  5712 >,
+			< 1958400  7031 >;
+		cpu-to-dev-map-4 =
+			<  768000  2929 >,
+			< 1001600  4101 >,
+			< 1171200  5053 >,
+			< 1305600  6152 >,
+			< 1459200  7031 >;
+
+		};
+
+		cci-cpufreq {
+		target-dev = <&cci_cache>;
+		cpu-to-dev-map-0 =
+			< 1305600  400000 >,
+			< 1497600  400000 >,
+			< 1708800  533333 >,
+			< 1958400  533333 >;
+		cpu-to-dev-map-4 =
+			<  768000  400000 >,
+			< 1001600  400000 >,
+			< 1171200  533333 >,
+			< 1305600  533333 >,
+			< 1459200  533333 >;
+		};
+
+		mincpubw-cpufreq {
+			target-dev = <&mincpubw>;
+			cpu-to-dev-map-0 =
+				< 1305600 2929 >,
+				< 1958400 4248 >;
+			cpu-to-dev-map-4 =
+				< 1171200 2929 >,
+				< 1459200 4248 >;
+		};
 	};
 };
 
@@ -38,7 +110,7 @@
 
 	CPU_COST_0: core-cost0 {
 		busy-cost-data = <
-			8000000	137
+			 800000	137
 			1001600	165
 			1305600	207
 			1497600	256
@@ -51,7 +123,7 @@
 	};
 	CPU_COST_1: core-cost1 {
 		busy-cost-data = <
-			8000000	45
+			 768000	43
 			1001600	56
 			1171200	71
 			1305600	89
@@ -63,7 +135,7 @@
 	};
 	CLUSTER_COST_0: cluster-cost0 {
 			busy-cost-data = <
-			8000000	49
+			 800000	49
 			1001600	53
 			1305600	61
 			1497600	71
@@ -76,7 +148,7 @@
 	};
 	CLUSTER_COST_1: cluster-cost1 {
 			busy-cost-data = <
-			8000000	9
+			 768000	8
 			1001600	10
 			1171200	13
 			1305600	15
@@ -87,3 +159,169 @@
 		>;
 	};
 };
+
+&kgsl_smmu {
+	qcom,enable-static-cb;
+};
+
+&reserved_memory {
+	gpu_mem: gpu_region@0 {
+		compatible = "shared-dma-pool";
+		reusable;
+		alloc-ranges = <0x0 0x80000000 0x0 0x10000000>;
+		alignment = <0 0x400000>;
+		size = <0 0x800000>;
+	};
+};
+
+&soc {
+	pil_gpu: qcom,kgsl-hyp {
+		compatible = "qcom,pil-tz-generic";
+		qcom,pas-id = <13>;
+		qcom,firmware-name = "a506_zap";
+		memory-region = <&gpu_mem>;
+		qcom,mas-crypto = <&mas_crypto>;
+		clocks = <&clock_gcc clk_gcc_crypto_clk>,
+		<&clock_gcc clk_gcc_crypto_ahb_clk>,
+		<&clock_gcc clk_gcc_crypto_axi_clk>,
+		<&clock_gcc clk_crypto_clk_src>;
+		clock-names = "scm_core_clk", "scm_iface_clk",
+				"scm_bus_clk", "scm_core_clk_src";
+		qcom,proxy-clock-names = "scm_core_clk", "scm_iface_clk",
+				"scm_bus_clk", "scm_core_clk_src";
+		qcom,scm_core_clk_src-freq = <80000000>;
+	};
+};
+
+&kgsl_msm_iommu {
+	gfx3d_secure: gfx3d_secure {
+		compatible = "qcom,smmu-kgsl-cb";
+		iommus = <&kgsl_smmu 2>;
+		memory-region = <&secure_mem>;
+	};
+};
+
+&clock_cpu {
+	compatible = "qcom,cpu-clock-sdm439";
+	vdd-c0-supply = <&apc_vreg_corner>;
+	vdd-c1-supply = <&apc_vreg_corner>;
+	vdd-cci-supply = <&apc_vreg_corner>;
+	qcom,speed0-bin-v0-c0 =
+		<          0 0>,
+		<  768000000 1>,
+		<  998400000 1>,
+		< 1171200000 2>,
+		< 1305600000 3>,
+		< 1459200000 5>;
+
+	qcom,speed0-bin-v0-c1 =
+		<          0 0>,
+		< 1305600000 1>,
+		< 1497600000 2>,
+		< 1708800000 3>,
+		< 1958400000 5>;
+
+	qcom,speed0-bin-v0-cci =
+		<          0 0>,
+		<  400000000 1>,
+		<  533333333 3>;
+
+	qcom,speed1-bin-v0-c0 =
+		<          0 0>,
+		<  768000000 1>,
+		<  998400000 1>,
+		< 1171200000 2>,
+		< 1305600000 3>,
+		< 1459200000 5>;
+
+	qcom,speed1-bin-v0-c1 =
+		<          0 0>,
+		< 1305600000 1>,
+		< 1497600000 2>,
+		< 1708800000 3>,
+		< 1804800000 5>;
+
+	qcom,speed1-bin-v0-cci =
+		<          0 0>,
+		<  400000000 1>,
+		<  533333333 3>;
+};
+
+&clock_gcc {
+	compatible = "qcom,gcc-sdm439";
+	reg = <0x1800000 0x80000>,
+		<0xb016000 0x00040>,
+		<0xb116000 0x00040>,
+		<0x00a6018 0x00004>;
+	reg-names = "cc_base", "apcs_c1_base",
+			"apcs_c0_base", "efuse";
+	vdd_dig-supply = <&pm8953_s2_level>;
+	vdd_sr2_dig-supply = <&pm8953_s2_level_ao>;
+	vdd_sr2_pll-supply = <&pm8953_l7_ao>;
+	vdd_hf_dig-supply = <&pm8953_s2_level_ao>;
+	vdd_hf_pll-supply = <&pm8953_l7_ao>;
+};
+
+&clock_gcc_mdss {
+	compatible = "qcom,gcc-mdss-sdm439";
+	clocks = <&mdss_dsi0_pll clk_dsi0pll_pixel_clk_src>,
+		 <&mdss_dsi0_pll clk_dsi0pll_byte_clk_src>,
+		 <&mdss_dsi1_pll clk_dsi1pll_pixel_clk_src>,
+		 <&mdss_dsi1_pll clk_dsi1pll_byte_clk_src>;
+	clock-names = "pclk0_src", "byte0_src", "pclk1_src",
+		"byte1_src";
+	#clock-cells = <1>;
+};
+
+&mdss_dsi0_pll {
+	compatible = "qcom,mdss_dsi_pll_sdm439";
+	reg = <0x001a94400 0x400>,
+		<0x0184d074 0x8>;
+	reg-names = "pll_base", "gdsc_base";
+	/delete-property/ qcom,dsi-pll-ssc-en;
+	/delete-property/ qcom,dsi-pll-ssc-mode;
+	/delete-property/ qcom,ssc-frequency-hz;
+	/delete-property/ qcom,ssc-ppm;
+};
+
+&mdss_dsi1_pll {
+	compatible = "qcom,mdss_dsi_pll_sdm439";
+	reg = <0x001a96400 0x400>,
+		<0x0184d074 0x8>;
+	reg-names = "pll_base", "gdsc_base";
+	/delete-property/ qcom,dsi-pll-ssc-en;
+	/delete-property/ qcom,dsi-pll-ssc-mode;
+	/delete-property/ qcom,ssc-frequency-hz;
+	/delete-property/ qcom,ssc-ppm;
+};
+
+&mdss_dsi {
+	ranges = <0x1a94000 0x1a94000 0x300
+		0x1a94400 0x1a94400 0x400
+		0x193e000 0x193e000 0x30
+		0x1a96000 0x1a96000 0x300
+		0x1a96400 0x1a96400 0x400
+		0x193e000 0x193e000 0x30>;
+};
+
+&mdss_dsi0 {
+	reg = <0x1a94000 0x300>,
+		<0x1a94400 0x400>,
+		<0x193e000 0x30>;
+	reg-names = "dsi_ctrl", "dsi_phy", "mmss_misc_phys";
+	/delete-property/ qcom,platform-strength-ctrl;
+	/delete-property/ qcom,platform-bist-ctrl;
+	/delete-property/ qcom,platform-regulator-settings;
+	/delete-property/ qcom,platform-lane-config;
+};
+
+&mdss_dsi1 {
+	reg = <0x1a96000 0x300>,
+		<0x1a96400 0x400>,
+		<0x193e000 0x30>;
+	reg-names = "dsi_ctrl", "dsi_phy", "mmss_misc_phys";
+	/delete-property/ qcom,platform-strength-ctrl;
+	/delete-property/ qcom,platform-bist-ctrl;
+	/delete-property/ qcom,platform-regulator-settings;
+	/delete-property/ qcom,platform-lane-config;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dts b/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dts
index 692da7f..68f02a8 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dts
@@ -24,16 +24,3 @@
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
 
-&pm8953_vadc {
-	pinctrl-0 = <&pa_therm1_default>;
-	/delete-node/ chan@13;
-};
-
-&pm8953_mpps {
-	/delete-node/ case_therm;
-};
-
-&thermal_zones {
-	/delete-node/ case-therm-adc;
-	/delete-node/ case-therm-step;
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dts b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dts
index 02bf751..b9aadc1 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dts
@@ -24,16 +24,3 @@
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
 
-&pm8953_vadc {
-	pinctrl-0 = <&pa_therm1_default>;
-	/delete-node/ chan@13;
-};
-
-&pm8953_mpps {
-	/delete-node/ case_therm;
-};
-
-&thermal_zones {
-	/delete-node/ case-therm-adc;
-	/delete-node/ case-therm-step;
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632.dtsi b/arch/arm64/boot/dts/qcom/sdm450-pmi632.dtsi
index d29d6fa..5c127bc 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632.dtsi
@@ -45,6 +45,10 @@
 	qcom,battery-data = <&mtp_batterydata>;
 };
 
+&pmi632_charger {
+	qcom,battery-data = <&mtp_batterydata>;
+};
+
 &pm8953_gpios {
 	bklt_en {
 		bklt_en_default: bklt_en_default {
@@ -63,6 +67,27 @@
 &thermal_zones {
 	pmi-vbat-lvl0 {
 		cooling-maps {
+			vbat_map0 {
+				trip = <&pmi632_vbat_lvl0>;
+				/* throttle from fmax to 1689600KHz */
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			vbat_map1 {
+				trip = <&pmi632_vbat_lvl0>;
+				cooling-device = <&CPU1 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			vbat_map2 {
+				trip = <&pmi632_vbat_lvl0>;
+				cooling-device = <&CPU2 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			vbat_map3 {
+				trip = <&pmi632_vbat_lvl0>;
+				cooling-device = <&CPU3 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
 			vbat_map4 {
 				trip = <&pmi632_vbat_lvl0>;
 				cooling-device =
@@ -90,8 +115,79 @@
 		};
 	};
 
+	pmi-ibat-lvl0 {
+		cooling-maps {
+			ibat_map0 {
+				trip = <&pmi632_ibat_lvl0>;
+				/* throttle from fmax to 1689600KHz */
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			ibat_map1 {
+				trip = <&pmi632_ibat_lvl0>;
+				cooling-device = <&CPU1 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			ibat_map2 {
+				trip = <&pmi632_ibat_lvl0>;
+				cooling-device = <&CPU2 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			ibat_map3 {
+				trip = <&pmi632_ibat_lvl0>;
+				cooling-device = <&CPU3 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			ibat_map4 {
+				trip = <&pmi632_ibat_lvl0>;
+				cooling-device =
+					<&CPU4 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			ibat_map5 {
+				trip = <&pmi632_ibat_lvl0>;
+				cooling-device =
+					<&CPU5 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			ibat_map6 {
+				trip = <&pmi632_ibat_lvl0>;
+				cooling-device =
+					<&CPU6 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			ibat_map7 {
+				trip = <&pmi632_ibat_lvl0>;
+				cooling-device =
+					<&CPU7 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+		};
+	};
+
 	soc {
 		cooling-maps {
+			soc_map0 {
+				trip = <&pmi632_low_soc>;
+				/* throttle from fmax to 1689600KHz */
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			soc_map1 {
+				trip = <&pmi632_low_soc>;
+				cooling-device = <&CPU1 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			soc_map2 {
+				trip = <&pmi632_low_soc>;
+				cooling-device = <&CPU2 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			soc_map3 {
+				trip = <&pmi632_low_soc>;
+				cooling-device = <&CPU3 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
 			soc_map4 {
 				trip = <&pmi632_low_soc>;
 				cooling-device =
@@ -119,45 +215,137 @@
 		};
 	};
 
-	case-therm-step {
+	quiet-therm-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pmi632_adc_tm 0x53>;
+		thermal-governor = "user_space";
+
 		trips {
-			batt_trip1: batt-trip1 {
+			active-config0 {
+				temperature = <65000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	case-therm-step {
+		status = "disabled";
+	};
+
+	quiet-therm-step {
+		polling-delay-passive = <2000>;
+		polling-delay = <0>;
+		thermal-sensors = <&pmi632_adc_tm 0x53>;
+		thermal-governor = "step_wise";
+
+		trips {
+			quiet_batt_trip1: quiet_batt-trip1 {
 				temperature = <38000>;
 				hysteresis = <3000>;
 				type = "passive";
 			};
-			batt_trip2: batt-trip2 {
+			quiet_batt_trip2: quiet_batt-trip2 {
 				temperature = <40000>;
 				hysteresis = <2000>;
 				type = "passive";
 			};
-			batt_trip3: batt-trip3 {
+			quiet_batt_trip3: quiet_batt-trip3 {
 				temperature = <43000>;
 				hysteresis = <3000>;
 				type = "passive";
 			};
-			batt_trip4: batt-trip4 {
+			quiet_cpus_trip: quiet_cpus-trip {
+				temperature = <43000>;
+				hysteresis = <0>;
+				type = "passive";
+			};
+			quiet_modem_trip0: quiet_modem-trip0 {
+				temperature = <45000>;
+				hysteresis = <2000>;
+				type = "passive";
+			};
+			quiet_batt_trip4: quiet_batt-trip4 {
 				temperature = <48000>;
 				hysteresis = <5000>;
 				type = "passive";
 			};
+			quiet_modem_trip1: quiet_modem-trip1 {
+				temperature = <48000>;
+				hysteresis = <3000>;
+				type = "passive";
+			};
+			quiet_modem_trip2: quiet_modem-trip2 {
+				temperature = <54000>;
+				hysteresis = <4000>;
+				type = "passive";
+			};
 		};
-
 		cooling-maps {
+			skin_cpu0 {
+				trip = <&quiet_cpus_trip>;
+				/* throttle from fmax to 1689600KHz */
+				cooling-device = <&CPU0 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu1 {
+				trip = <&quiet_cpus_trip>;
+				cooling-device = <&CPU1 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu2 {
+				trip = <&quiet_cpus_trip>;
+				cooling-device = <&CPU2 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu3 {
+				trip = <&quiet_cpus_trip>;
+				cooling-device = <&CPU3 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu4 {
+				trip = <&quiet_cpus_trip>;
+				cooling-device = <&CPU4 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu5 {
+				trip = <&quiet_cpus_trip>;
+				cooling-device = <&CPU5 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu6 {
+				trip = <&quiet_cpus_trip>;
+				cooling-device = <&CPU6 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu7 {
+				trip = <&quiet_cpus_trip>;
+				cooling-device = <&CPU7 THERMAL_NO_LIMIT 3>;
+			};
+			modem_lvl1 {
+				trip = <&quiet_modem_trip1>;
+				cooling-device = <&modem_pa 2 2>;
+			};
+			modem_lvl2 {
+				trip = <&quiet_modem_trip2>;
+				cooling-device = <&modem_pa 3 3>;
+			};
+			modem_proc_lvl1 {
+				trip = <&quiet_modem_trip0>;
+				cooling-device = <&modem_proc 1 1>;
+			};
+			modem_proc_lvl2 {
+				trip = <&quiet_modem_trip2>;
+				cooling-device = <&modem_proc 3 3>;
+			};
 			battery_lvl1 {
-				trip = <&batt_trip1>;
+				trip = <&quiet_batt_trip1>;
 				cooling-device = <&pmi632_charger 2 2>;
 			};
 			battery_lvl2 {
-				trip = <&batt_trip2>;
+				trip = <&quiet_batt_trip2>;
 				cooling-device = <&pmi632_charger 3 3>;
 			};
 			battery_lvl3 {
-				trip = <&batt_trip3>;
+				trip = <&quiet_batt_trip3>;
 				cooling-device = <&pmi632_charger 4 4>;
 			};
 			battery_lvl4 {
-				trip = <&batt_trip4>;
+				trip = <&quiet_batt_trip4>;
 				cooling-device = <&pmi632_charger 5 5>;
 			};
 		};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dts b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dts
index b0cb955..cad0c6f 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dts
@@ -14,8 +14,8 @@
 /dts-v1/;
 
 #include "sdm450.dtsi"
-#include "sdm450-qrd-sku4.dtsi"
 #include "sdm450-pmi632.dtsi"
+#include "sdm450-qrd-sku4.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM450 + PMI632 QRD SKU4";
@@ -24,22 +24,3 @@
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
 
-&pmi632_vadc {
-	chan@4a {
-		qcom,scale-function = <22>;
-	};
-};
-
-&pm8953_vadc {
-	pinctrl-0 = <&pa_therm1_default>;
-	/delete-node/ chan@13;
-};
-
-&pm8953_mpps {
-	/delete-node/ case_therm;
-};
-
-&thermal_zones {
-	/delete-node/ case-therm-adc;
-	/delete-node/ case-therm-step;
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
index bdefdc9..386bd71 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
@@ -150,3 +150,30 @@
 &sdhc_2 {
 	cd-gpios = <&tlmm 133 0x0>;
 };
+
+&pmi632_vadc {
+	chan@4a {
+		qcom,scale-function = <22>;
+	};
+};
+
+&soc {
+	gpio_keys {
+		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>;
+		};
+	};
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm450.dtsi b/arch/arm64/boot/dts/qcom/sdm450.dtsi
index 1d2abd7c..34c6815 100644
--- a/arch/arm64/boot/dts/qcom/sdm450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450.dtsi
@@ -132,3 +132,17 @@
 		};
 	};
 };
+
+&pm8953_vadc {
+	pinctrl-0 = <&pa_therm1_default>;
+	/delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+	/delete-node/ case_therm;
+};
+
+&thermal_zones {
+	/delete-node/ case-therm-adc;
+	/delete-node/ case-therm-step;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts b/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
index 2c3e830..2669d1f 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
@@ -18,10 +18,10 @@
 #include "sdm450-pmi632.dtsi"
 
 / {
-	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 CDP S2";
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 CDP S2";
 	compatible = "qcom,sdm632-cdp", "qcom,sdm632", "qcom,cdp";
 	qcom,board-id = <1 2>;
-	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
 
 
@@ -54,17 +54,3 @@
 		};
 	};
 };
-
-&pm8953_vadc {
-	pinctrl-0 = <&pa_therm1_default>;
-	/delete-node/ chan@13;
-};
-
-&pm8953_mpps {
-	/delete-node/ case_therm;
-};
-
-&thermal_zones {
-	/delete-node/ case-therm-adc;
-	/delete-node/ case-therm-step;
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-cpu.dtsi b/arch/arm64/boot/dts/qcom/sdm632-cpu.dtsi
index c53bb56..de1bd1f 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-cpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632-cpu.dtsi
@@ -248,7 +248,7 @@
 				1363200	88
 				1536000	112
 				1670400	151
-				1785600	192
+				1804800	194
 			>;
 			idle-cost-data = <
 				20 16 12 8
@@ -261,9 +261,9 @@
 				1036800	1739
 				1401600	2819
 				1555200	3532
-				1785600	4985
+				1804800	5038
 				1996000	6624
-				2082800	6905
+				2016000	6688
 			>;
 			idle-cost-data = <
 				100 80 60 40
@@ -277,7 +277,7 @@
 				1363200	28
 				1536000	35
 				1670400	43
-				1785600	54
+				1804800	54
 			>;
 			idle-cost-data = <
 				4 3 2 1
@@ -290,9 +290,9 @@
 				1036800	132
 				1401600	193
 				1555200	233
-				1785600	289
+				1804800	292
 				1996000	374
-				2082800	386
+				2016000	377
 			>;
 			idle-cost-data = <
 				4 3 2 1
diff --git a/arch/arm64/boot/dts/qcom/sdm632-ext-codec-cdp-s3-overlay.dts b/arch/arm64/boot/dts/qcom/sdm632-ext-codec-cdp-s3-overlay.dts
new file mode 100644
index 0000000..eb5afbd
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-ext-codec-cdp-s3-overlay.dts
@@ -0,0 +1,24 @@
+/*
+ * 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/;
+/plugin/;
+
+#include "sdm632-ext-codec-cdp-s3.dtsi"
+
+/ {
+	model = "Ext Codec CDP S3";
+	compatible = "qcom,cdp";
+	qcom,board-id = <1 3>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-ext-codec-cdp-s3.dts b/arch/arm64/boot/dts/qcom/sdm632-ext-codec-cdp-s3.dts
new file mode 100644
index 0000000..17ae9d1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-ext-codec-cdp-s3.dts
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632.dtsi"
+#include "sdm632-ext-codec-cdp-s3.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 Ext Codex CDP S3";
+	compatible = "qcom,sdm632-cdp", "qcom,sdm632", "qcom,cdp";
+	qcom,board-id = <1 3>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
+
+
+&soc {
+	gpio_keys {
+		/delete-node/home;
+	};
+};
+
+&tlmm {
+	tlmm_gpio_key {
+		gpio_key_active: gpio_key_active {
+			mux {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+
+			config {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+		};
+
+		gpio_key_suspend: gpio_key_suspend {
+			mux {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+
+			config {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+		};
+	};
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-ext-codec-cdp-s3.dtsi b/arch/arm64/boot/dts/qcom/sdm632-ext-codec-cdp-s3.dtsi
new file mode 100644
index 0000000..14ba3b4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-ext-codec-cdp-s3.dtsi
@@ -0,0 +1,15 @@
+/*
+ * 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 "sdm450-pmi632-cdp-s2.dtsi"
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-ext-codec-mtp-s4-overlay.dts b/arch/arm64/boot/dts/qcom/sdm632-ext-codec-mtp-s4-overlay.dts
new file mode 100644
index 0000000..5656fd0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-ext-codec-mtp-s4-overlay.dts
@@ -0,0 +1,24 @@
+/*
+ * 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/;
+/plugin/;
+
+#include "sdm632-ext-codec-mtp-s4.dtsi"
+
+/ {
+	model = "Ext Codec MTP S4";
+	compatible = "qcom,mtp";
+	qcom,board-id = <8 4>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-ext-codec-mtp-s4.dts b/arch/arm64/boot/dts/qcom/sdm632-ext-codec-mtp-s4.dts
new file mode 100644
index 0000000..b9e1178
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-ext-codec-mtp-s4.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632.dtsi"
+#include "sdm632-ext-codec-mtp-s4.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + Ext Codec MTP S4";
+	compatible = "qcom,sdm632-mtp", "qcom,sdm632", "qcom,mtp";
+	qcom,board-id = <8 4>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-ext-codec-mtp-s4.dtsi b/arch/arm64/boot/dts/qcom/sdm632-ext-codec-mtp-s4.dtsi
new file mode 100644
index 0000000..d8326ff
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-ext-codec-mtp-s4.dtsi
@@ -0,0 +1,15 @@
+/*
+ * 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 "sdm450-pmi632-mtp-s3.dtsi"
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts b/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts
index 0566fbb..3662cf3 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts
@@ -18,22 +18,9 @@
 #include "sdm450-pmi632.dtsi"
 
 / {
-	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 MTP S3";
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 MTP S3";
 	compatible = "qcom,sdm632-mtp", "qcom,sdm632", "qcom,mtp";
 	qcom,board-id = <8 3>;
-	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
 
-&pm8953_vadc {
-	pinctrl-0 = <&pa_therm1_default>;
-	/delete-node/ chan@13;
-};
-
-&pm8953_mpps {
-	/delete-node/ case_therm;
-};
-
-&thermal_zones {
-	/delete-node/ case-therm-adc;
-	/delete-node/ case-therm-step;
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-pm8004-cdp-s2.dts b/arch/arm64/boot/dts/qcom/sdm632-pm8004-cdp-s2.dts
new file mode 100644
index 0000000..4d68901
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-pm8004-cdp-s2.dts
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632-cdp-s2.dtsi"
+#include "sdm450-pmi632.dtsi"
+#include "sdm632-pm8004.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PM8004 CDP S2";
+	compatible = "qcom,sdm632-cdp", "qcom,sdm632", "qcom,cdp";
+	qcom,board-id = <1 2>;
+	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+};
+
+
+&soc {
+	gpio_keys {
+		/delete-node/home;
+	};
+};
+
+&tlmm {
+	tlmm_gpio_key {
+		gpio_key_active: gpio_key_active {
+			mux {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+
+			config {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+		};
+
+		gpio_key_suspend: gpio_key_suspend {
+			mux {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+
+			config {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+		};
+	};
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-pm8004-ext-codec-cdp-s3.dts b/arch/arm64/boot/dts/qcom/sdm632-pm8004-ext-codec-cdp-s3.dts
new file mode 100644
index 0000000..6ca2940
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-pm8004-ext-codec-cdp-s3.dts
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632.dtsi"
+#include "sdm632-pm8004.dtsi"
+#include "sdm632-ext-codec-cdp-s3.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 Ext Codec CDP S3";
+	compatible = "qcom,sdm632-cdp", "qcom,sdm632", "qcom,cdp";
+	qcom,board-id = <1 3>;
+	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+};
+
+
+&soc {
+	gpio_keys {
+		/delete-node/home;
+	};
+};
+
+&tlmm {
+	tlmm_gpio_key {
+		gpio_key_active: gpio_key_active {
+			mux {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+
+			config {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+		};
+
+		gpio_key_suspend: gpio_key_suspend {
+			mux {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+
+			config {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+		};
+	};
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-pm8004-ext-codec-mtp-s4.dts b/arch/arm64/boot/dts/qcom/sdm632-pm8004-ext-codec-mtp-s4.dts
new file mode 100644
index 0000000..7a30bff82e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-pm8004-ext-codec-mtp-s4.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632.dtsi"
+#include "sdm632-pm8004.dtsi"
+#include "sdm632-ext-codec-mtp-s4.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 MTP S4";
+	compatible = "qcom,sdm632-mtp", "qcom,sdm632", "qcom,mtp";
+	qcom,board-id = <8 4>;
+	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-pm8004-mtp-s3.dts b/arch/arm64/boot/dts/qcom/sdm632-pm8004-mtp-s3.dts
new file mode 100644
index 0000000..d2a9cf1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-pm8004-mtp-s3.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632-mtp-s3.dtsi"
+#include "sdm450-pmi632.dtsi"
+#include "sdm632-pm8004.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PM8004 MTP S3";
+	compatible = "qcom,sdm632-mtp", "qcom,sdm632", "qcom,mtp";
+	qcom,board-id = <8 3>;
+	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-pm8004-qrd-sku4.dts b/arch/arm64/boot/dts/qcom/sdm632-pm8004-qrd-sku4.dts
new file mode 100644
index 0000000..3472b86
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-pm8004-qrd-sku4.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm632-pm8004.dtsi"
+#include "sdm450-pmi632.dtsi"
+#include "sdm450-qrd-sku4.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PM8004 QRD SKU4";
+	compatible = "qcom,sdm632-qrd", "qcom,sdm632", "qcom,qrd";
+	qcom,board-id = <0xb 1>;
+	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-pm8004-qrd.dts b/arch/arm64/boot/dts/qcom/sdm632-pm8004-qrd.dts
new file mode 100644
index 0000000..89a56fa
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-pm8004-qrd.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632.dtsi"
+#include "sdm632-pm8004.dtsi"
+#include "sdm632-qrd.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PM8004 + QRD";
+	compatible = "qcom,sdm632-qrd", "qcom,sdm632", "qcom,qrd";
+	qcom,board-id = <0xb 3>;
+	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-pm8004-rcm.dts b/arch/arm64/boot/dts/qcom/sdm632-pm8004-rcm.dts
new file mode 100644
index 0000000..89eb789
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-pm8004-rcm.dts
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632.dtsi"
+#include "sdm632-pm8004.dtsi"
+#include "sdm632-rcm.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PM8004 RCM";
+	compatible = "qcom,sdm632-cdp", "qcom,sdm632", "qcom,cdp";
+	qcom,board-id= <21 2>;
+	qcom,pmic-id = <0x010016 0x010011 0xC 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-pm8004.dts b/arch/arm64/boot/dts/qcom/sdm632-pm8004.dts
new file mode 100644
index 0000000..625bf40
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-pm8004.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632.dtsi"
+#include "sdm632-pm8004.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PM8004 SOC";
+	compatible = "qcom,sdm450";
+	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+	qcom,pmic-name = "PMI632 + PM8004";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-pm8004.dtsi b/arch/arm64/boot/dts/qcom/sdm632-pm8004.dtsi
new file mode 100644
index 0000000..a5994c6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-pm8004.dtsi
@@ -0,0 +1,57 @@
+/*
+ * 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 "pm8004.dtsi"
+#include "pm8004-rpm-regulator.dtsi"
+
+&rpm_bus {
+	rpm-regulator-ldoc1 {
+		status = "okay";
+		pm8004_l1: regulator-l1 {
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,init-voltage = <1200000>;
+			status = "okay";
+		};
+	};
+};
+
+&spmi_bus {
+	qcom,pm8953@1 {
+		/delete-node/ spm-regulator@2000;
+	};
+
+	pmic@5 {
+		#size-cells = <1>;
+
+		/* PM8004 S2 + S4 + S5 = VDD_APC supply */
+		pm8004_s2: spm-regulator@1d00 {
+			compatible = "qcom,spm-regulator";
+			reg = <0x1d00 0x100>;
+			regulator-name = "pm8004_s2";
+			regulator-min-microvolt = <400000>;
+			regulator-max-microvolt = <1140000>;
+
+			pm8004_s2_limit: avs-limit-regulator {
+				regulator-name = "pm8004_s2_avs_limit";
+				regulator-min-microvolt = <400000>;
+				regulator-max-microvolt = <1140000>;
+			};
+		};
+	};
+};
+
+&apc_cpr {
+	vdd-supply = <&pm8004_s2>;
+	vdd-limit-supply = <&pm8004_s2_limit>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm632-qrd-overlay.dts
new file mode 100644
index 0000000..e6217e5
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-qrd-overlay.dts
@@ -0,0 +1,24 @@
+/*
+ * 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/;
+/plugin/;
+
+#include "sdm632-qrd.dtsi"
+
+/ {
+	model = "QRD";
+	compatible = "qcom,qrd";
+	qcom,board-id = <0xb 3>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts b/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
index fe1ac73..466c8fc 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
@@ -14,53 +14,13 @@
 /dts-v1/;
 
 #include "sdm632.dtsi"
-#include "sdm450-qrd-sku4.dtsi"
 #include "sdm450-pmi632.dtsi"
-#include "msm8953-camera-sensor-qrd.dtsi"
+#include "sdm450-qrd-sku4.dtsi"
 
 / {
-	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 QRD SKU4";
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 QRD SKU4";
 	compatible = "qcom,sdm632-qrd", "qcom,sdm632", "qcom,qrd";
 	qcom,board-id = <0xb 1>;
-	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
 
-&pmi632_vadc {
-	chan@4a {
-		qcom,scale-function = <22>;
-	};
-};
-
-&soc {
-	gpio_keys {
-		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>;
-		};
-	};
-};
-
-&pm8953_vadc {
-	pinctrl-0 = <&pa_therm1_default>;
-	/delete-node/ chan@13;
-};
-
-&pm8953_mpps {
-	/delete-node/ case_therm;
-};
-
-&thermal_zones {
-	/delete-node/ case-therm-adc;
-	/delete-node/ case-therm-step;
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-qrd.dts b/arch/arm64/boot/dts/qcom/sdm632-qrd.dts
new file mode 100644
index 0000000..c59fe5d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-qrd.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632.dtsi"
+#include "sdm632-qrd.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + QRD";
+	compatible = "qcom,sdm632-qrd", "qcom,sdm632", "qcom,qrd";
+	qcom,board-id = <0xb 3>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm632-qrd.dtsi
new file mode 100644
index 0000000..09077c42
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-qrd.dtsi
@@ -0,0 +1,14 @@
+/*
+ * 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 "sdm450-qrd-sku4.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm632-rcm-overlay.dts b/arch/arm64/boot/dts/qcom/sdm632-rcm-overlay.dts
new file mode 100644
index 0000000..42979ad
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-rcm-overlay.dts
@@ -0,0 +1,23 @@
+/*
+ * 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/;
+/plugin/;
+
+#include "sdm632-rcm.dtsi"
+
+/ {
+	model = "RCM";
+	qcom,board-id = <21 2>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-rcm.dts b/arch/arm64/boot/dts/qcom/sdm632-rcm.dts
new file mode 100644
index 0000000..68f0ea0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-rcm.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm632.dtsi"
+#include "sdm450-pmi632.dtsi"
+#include "sdm632-rcm.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 RCM";
+	compatible = "qcom,sdm632-cdp", "qcom,sdm632", "qcom,cdp";
+	qcom,board-id= <21 2>;
+	qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-rcm.dtsi b/arch/arm64/boot/dts/qcom/sdm632-rcm.dtsi
new file mode 100644
index 0000000..14ba3b4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm632-rcm.dtsi
@@ -0,0 +1,15 @@
+/*
+ * 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 "sdm450-pmi632-cdp-s2.dtsi"
+
diff --git a/arch/arm64/boot/dts/qcom/sdm632-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm632-regulator.dtsi
index 060b8996..b5373a2 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632-regulator.dtsi
@@ -49,43 +49,6 @@
 	qcom,init-voltage = <2800000>;
 };
 
-&rpm_bus {
-	rpm-regulator-ldoc1 {
-		status = "okay";
-		pm8004_l1: regulator-l1 {
-			regulator-min-microvolt = <1200000>;
-			regulator-max-microvolt = <1200000>;
-			qcom,init-voltage = <1200000>;
-			status = "okay";
-		};
-	};
-};
-
-&spmi_bus {
-	qcom,pm8953@1 {
-		/delete-node/ spm-regulator@2000;
-	};
-
-	pmic@5 {
-		#size-cells = <1>;
-
-		/* PM8004 S2 + S4 + S5 = VDD_APC supply */
-		pm8004_s2: spm-regulator@1d00 {
-			compatible = "qcom,spm-regulator";
-			reg = <0x1d00 0x100>;
-			regulator-name = "pm8004_s2";
-			regulator-min-microvolt = <400000>;
-			regulator-max-microvolt = <1140000>;
-
-			pm8004_s2_limit: avs-limit-regulator {
-				regulator-name = "pm8004_s2_avs_limit";
-				regulator-min-microvolt = <400000>;
-				regulator-max-microvolt = <1140000>;
-			};
-		};
-	};
-};
-
 &soc {
 	/delete-node/ regulator@19461d4;
 	/delete-node/ cpr4-ctrl@b018000;
@@ -156,9 +119,9 @@
 		qcom,apm-threshold-voltage = <875000>;
 		qcom,apm-hysteresis-voltage = <20000>;
 
-		vdd-supply = <&pm8004_s2>;
+		vdd-supply = <&pm8953_s5>;
 		qcom,voltage-step = <5000>;
-		vdd-limit-supply = <&pm8004_s2_limit>;
+		vdd-limit-supply = <&pm8953_s5_limit>;
 		mem-acc-supply = <&apc_mem_acc_vreg>;
 
 		qcom,cpr-panic-reg-addr-list =
@@ -181,7 +144,7 @@
 				regulator-max-microvolt = <7>;
 
 				qcom,cpr-fuse-corners = <5>;
-				qcom,cpr-fuse-combos = <8>;
+				qcom,cpr-fuse-combos = <64>;
 				qcom,cpr-corners = <7>;
 				qcom,cpr-corner-fmax-map = <1 2 3 4 7>;
 
@@ -231,7 +194,7 @@
 				regulator-max-microvolt = <5>;
 
 				qcom,cpr-fuse-corners = <3>;
-				qcom,cpr-fuse-combos = <8>;
+				qcom,cpr-fuse-combos = <64>;
 				qcom,cpr-corners = <5>;
 				qcom,cpr-corner-fmax-map = <1 2 5>;
 
diff --git a/arch/arm64/boot/dts/qcom/sdm632.dts b/arch/arm64/boot/dts/qcom/sdm632.dts
index dab409c..65f1ea2 100644
--- a/arch/arm64/boot/dts/qcom/sdm632.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632.dts
@@ -19,6 +19,6 @@
 / {
 	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 SOC";
 	compatible = "qcom,sdm450";
-	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 	qcom,pmic-name = "PMI632";
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm632.dtsi b/arch/arm64/boot/dts/qcom/sdm632.dtsi
index 813b89d..62689f5 100644
--- a/arch/arm64/boot/dts/qcom/sdm632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632.dtsi
@@ -13,8 +13,6 @@
 
 #include "msm8953.dtsi"
 #include "sdm632-cpu.dtsi"
-#include "pm8004.dtsi"
-#include "pm8004-rpm-regulator.dtsi"
 #include "sdm632-regulator.dtsi"
 
 / {
@@ -24,7 +22,7 @@
 	qcom,msm-name = "SDM632";
 
 	chosen {
-		/delete-property/ bootargs;
+		bootargs = "kpti=0";
 	};
 };
 
@@ -86,6 +84,10 @@
 		status = "disabled";
 	};
 
+	quiet-therm-step {
+		status = "disabled";
+	};
+
 	video-usr {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
@@ -819,13 +821,13 @@
 		<  1363200000 4>,
 		<  1536000000 5>,
 		<  1670400000 6>,
-		<  1785600000 7>;
+		<  1804800000 7>;
 	qcom,speed0-bin-v0-c1 =
 		<          0 0>,
 		<  1094400000 1>,
 		<  1401600000 2>,
 		<  1555200000 3>,
-		<  1785600000 4>;
+		<  1804800000 4>;
 	qcom,speed0-bin-v0-cci =
 		<          0 0>,
 		<  307200000 1>,
@@ -834,6 +836,56 @@
 		<  691200000 4>,
 		<  768000000 5>,
 		<  787200000 6>;
+
+	qcom,speed6-bin-v0-c0 =
+		<          0 0>,
+		<   614400000 1>,
+		<   883200000 2>,
+		<  1036800000 3>,
+		<  1363200000 4>,
+		<  1536000000 5>,
+		<  1670400000 6>,
+		<  1804800000 7>;
+	qcom,speed6-bin-v0-c1 =
+		<          0 0>,
+		<  1094400000 1>,
+		<  1401600000 2>,
+		<  1555200000 3>,
+		<  1804800000 4>;
+	qcom,speed6-bin-v0-cci =
+		<          0 0>,
+		<  307200000 1>,
+		<  403200000 2>,
+		<  499200000 3>,
+		<  691200000 4>,
+		<  768000000 5>,
+		<  787200000 6>;
+
+	qcom,speed2-bin-v0-c0 =
+		<          0 0>,
+		<   614400000 1>,
+		<   883200000 2>,
+		<  1036800000 3>,
+		<  1363200000 4>,
+		<  1536000000 5>,
+		<  1670400000 6>,
+		<  1804800000 7>;
+	qcom,speed2-bin-v0-c1 =
+		<          0 0>,
+		<  1094400000 1>,
+		<  1401600000 2>,
+		<  1555200000 3>,
+		<  1804800000 4>,
+		<  2016000000 5>;
+	qcom,speed2-bin-v0-cci =
+		<          0 0>,
+		<  307200000 1>,
+		<  403200000 2>,
+		<  499200000 3>,
+		<  691200000 4>,
+		<  768000000 5>,
+		<  787200000 6>;
+
 	#clock-cells = <1>;
 };
 
@@ -859,15 +911,15 @@
 			< 1363200 >,
 			< 1536000 >,
 			< 1670400 >,
-			< 1785600 >;
+			< 1804800 >;
 
 		qcom,cpufreq-table-4 =
 			< 1094400 >,
 			< 1401600 >,
 			< 1555200 >,
-			< 1785600 >,
+			< 1804800 >,
 			< 1996200 >,
-			< 2082800 >;
+			< 2016000 >;
 	};
 
 	cci_cache: qcom,cci {
@@ -891,12 +943,12 @@
 			cpu-to-dev-map-0 =
 				<  614400 1611>,
 				< 1363200 3221>,
-				< 1785600 5859>;
+				< 1804800 5859>;
 			cpu-to-dev-map-4 =
 				< 1094400 1611>,
 				< 1401600 3221>,
-				< 1785600 5859>,
-				< 2082800 7104>;
+				< 1804800 5859>,
+				< 2016000 7104>;
 		};
 
 		cci-cpufreq {
@@ -912,7 +964,22 @@
 				< 1094400 499200>,	/* SVS   */
 				< 1401600 691200>,      /* NOM   */
 				< 1555200 768000>,      /* NOM+  */
-				< 1785600 787200>;      /* TURBO */
+				< 1804800 787200>;      /* TURBO */
 		};
 	};
 };
+
+&pm8953_vadc {
+	pinctrl-0 = <&pa_therm1_default>;
+	/delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+	/delete-node/ case_therm;
+};
+
+&thermal_zones {
+	/delete-node/ case-therm-adc;
+	/delete-node/ case-therm-step;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm670-aqt1000-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm670-aqt1000-cdp-overlay.dts
new file mode 100644
index 0000000..001bcd4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-aqt1000-cdp-overlay.dts
@@ -0,0 +1,35 @@
+/* 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/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-int-cdc-aqt.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "sdm670-int-cdc-aqt-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM670 PM660 + PM660L AQT CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <336 0x0>;
+	qcom,board-id = <1 4>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi
index 2b3cb39..4d6b32f 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-audio-overlay.dtsi
@@ -320,6 +320,57 @@
 	wdsp_glink: qcom,wcd-dsp-glink {
 		compatible = "qcom,wcd-dsp-glink";
 	};
+
+	aqt_rst_gpio: aqt_cdc_pinctrl {
+		status = "disabled";
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&aqt_rst_active>;
+		pinctrl-1 = <&aqt_rst_idle>;
+	};
+
+	tert_mi2s_gpios: tert_mi2s_pinctrl {
+		status = "disabled";
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&ter_i2s_data0_active &ter_i2s_data1_active
+			     &ter_i2s_sck_active>;
+		pinctrl-1 = <&ter_i2s_data0_sleep &ter_i2s_data1_sleep
+			     &ter_i2s_sck_sleep>;
+	};
+
+	i2c@a88000 {
+		aqt1000_cdc: aqt1000-i2c-codec@d {
+			status = "disabled";
+			compatible = "qcom,aqt1000-i2c-codec";
+			reg = <0x0d>;
+
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			interrupt-parent = <&tlmm>;
+			qcom,gpio-connect = <&tlmm 79 0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&aqt_intr_default>;
+
+			qcom,aqt-rst-gpio-node = <&aqt_rst_gpio>;
+
+			qcom,cdc-vdd-mic-bias-supply = <&pm660l_bob>;
+			qcom,cdc-vdd-mic-bias-voltage = <3312000 3312000>;
+			qcom,cdc-vdd-mic-bias-current = <30400>;
+
+			qcom,cdc-static-supplies = "cdc-vdd-mic-bias";
+
+			qcom,cdc-micbias-ldoh-v = <3>;
+
+			qcom,cdc-ext-clk-rate = <19200000>;
+			qcom,cdc-mclk-clk-rate = <9600000>;
+
+			qcom,cdc-micbias1-mv = <1800>;
+
+			clock-names = "aqt_clk";
+			clocks = <&clock_audio_lnbb AUDIO_PMIC_LNBB_CLK>;
+		};
+	};
 };
 
 &slim_aud {
diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-cdp.dtsi
index 3cad0e2..f71fbd3 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-cdp.dtsi
@@ -129,7 +129,7 @@
 		rgltr-load-current = <0>;
 	};
 
-	actuator_front: qcom,actuator@1 {
+	actuator_rear_aux: qcom,actuator@1 {
 		cell-index = <1>;
 		reg = <0x1>;
 		compatible = "qcom,actuator";
@@ -142,6 +142,19 @@
 		rgltr-load-current = <0>;
 	};
 
+	actuator_front: qcom,actuator@2 {
+		cell-index = <2>;
+		reg = <0x2>;
+		compatible = "qcom,actuator";
+		cci-master = <1>;
+		cam_vaf-supply = <&actuator_regulator>;
+		regulator-names = "cam_vaf";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <2800000>;
+		rgltr-max-voltage = <2800000>;
+		rgltr-load-current = <0>;
+	};
+
 	ois_rear: qcom,ois@0 {
 		cell-index = <0>;
 		reg = <0x0>;
@@ -316,10 +329,11 @@
 		compatible = "qcom,cam-sensor";
 		reg = <0x1>;
 		csiphy-sd-index = <1>;
-		sensor-position-roll = <90>;
+		sensor-position-roll = <270>;
 		sensor-position-pitch = <0>;
 		sensor-position-yaw = <180>;
 		led-flash-src = <&led_flash_rear_aux>;
+		actuator-src = <&actuator_rear_aux>;
 		eeprom-src = <&eeprom_rear_aux>;
 		cam_vio-supply = <&camera_vio_ldo>;
 		cam_vana-supply = <&camera_vana_ldo>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-mtp.dtsi
index 3cad0e2..f71fbd3 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-mtp.dtsi
@@ -129,7 +129,7 @@
 		rgltr-load-current = <0>;
 	};
 
-	actuator_front: qcom,actuator@1 {
+	actuator_rear_aux: qcom,actuator@1 {
 		cell-index = <1>;
 		reg = <0x1>;
 		compatible = "qcom,actuator";
@@ -142,6 +142,19 @@
 		rgltr-load-current = <0>;
 	};
 
+	actuator_front: qcom,actuator@2 {
+		cell-index = <2>;
+		reg = <0x2>;
+		compatible = "qcom,actuator";
+		cci-master = <1>;
+		cam_vaf-supply = <&actuator_regulator>;
+		regulator-names = "cam_vaf";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <2800000>;
+		rgltr-max-voltage = <2800000>;
+		rgltr-load-current = <0>;
+	};
+
 	ois_rear: qcom,ois@0 {
 		cell-index = <0>;
 		reg = <0x0>;
@@ -316,10 +329,11 @@
 		compatible = "qcom,cam-sensor";
 		reg = <0x1>;
 		csiphy-sd-index = <1>;
-		sensor-position-roll = <90>;
+		sensor-position-roll = <270>;
 		sensor-position-pitch = <0>;
 		sensor-position-yaw = <180>;
 		led-flash-src = <&led_flash_rear_aux>;
+		actuator-src = <&actuator_rear_aux>;
 		eeprom-src = <&eeprom_rear_aux>;
 		cam_vio-supply = <&camera_vio_ldo>;
 		cam_vana-supply = <&camera_vana_ldo>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670-int-cdc-aqt-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm670-int-cdc-aqt-overlay.dtsi
new file mode 100644
index 0000000..5f70790
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-int-cdc-aqt-overlay.dtsi
@@ -0,0 +1,85 @@
+/* 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.
+ */
+
+&int_codec {
+	qcom,model = "sdm670-aqt-snd-card";
+	qcom,msm-mi2s-master = <1>, <1>, <0>, <1>, <1>;
+	qcom,tert-mi2s-gpios = <&tert_mi2s_gpios>;
+	qcom,us-euro-gpios = <&wcd_usbc_analog_en2_gpio>;
+	asoc-codec = <&stub_codec>, <&msm_digital_codec>,
+		     <&pmic_analog_codec>, <&msm_sdw_codec>,
+		     <&ext_disp_audio_codec>, <&aqt1000_cdc>;
+	qcom,audio-routing =
+		"RX_BIAS", "INT_MCLK0",
+		"SPK_RX_BIAS", "INT_MCLK0",
+		"INT_LDO_H", "INT_MCLK0",
+		"RX_I2S_CLK", "INT_MCLK0",
+		"TX_I2S_CLK", "INT_MCLK0",
+		"MIC BIAS External", "Handset Mic",
+		"AQT MIC BIAS1", "Headset Mic",
+		"MIC BIAS External", "Secondary Mic",
+		"AMIC1", "MIC BIAS External",
+		"AMIC2", "AQT MIC BIAS1",
+		"AMIC3", "MIC BIAS External",
+		"DMIC1", "MIC BIAS External",
+		"MIC BIAS External", "Digital Mic1",
+		"DMIC2", "MIC BIAS External",
+		"MIC BIAS External", "Digital Mic2",
+		"DMIC3", "MIC BIAS External",
+		"MIC BIAS External", "Digital Mic3",
+		"DMIC4", "MIC BIAS External",
+		"MIC BIAS External", "Digital Mic4",
+		"SpkrLeft IN", "SPK1 OUT",
+		"SpkrRight IN", "SPK2 OUT",
+		"PDM_IN_RX1", "PDM_OUT_RX1",
+		"PDM_IN_RX2", "PDM_OUT_RX2",
+		"PDM_IN_RX3", "PDM_OUT_RX3",
+		"ADC1_IN", "ADC1_OUT",
+		"ADC2_IN", "ADC2_OUT",
+		"ADC3_IN", "ADC3_OUT";
+	asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+			   "analog-codec", "msm_sdw_codec",
+			   "msm-ext-disp-audio-codec-rx", "aqt1000-i2c-codec";
+	qcom,mi2s-aqt-enabled;
+};
+
+&pmic_analog_codec {
+	qcom,anlg-cdc-mbhc-disable;
+};
+
+&soc {
+	i2c@a88000 {
+		status = "ok";
+	};
+	wcd_usbc_analog_en2_gpio: msm_cdc_pinctrl_usbc_audio_en2 {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&wcd_usbc_analog_en2_active>;
+		pinctrl-1 = <&wcd_usbc_analog_en2_idle>;
+	};
+};
+
+&tert_mi2s_gpios {
+	status = "ok";
+};
+
+&clock_audio_lnbb {
+	status = "ok";
+};
+
+&aqt1000_cdc {
+	status = "ok";
+};
+
+&aqt_rst_gpio {
+	status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-int-cdc-aqt.dtsi b/arch/arm64/boot/dts/qcom/sdm670-int-cdc-aqt.dtsi
new file mode 100644
index 0000000..56e60f2
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-int-cdc-aqt.dtsi
@@ -0,0 +1,64 @@
+/* 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 "sdm670-audio-overlay.dtsi"
+
+&dai_mi2s2 {
+	qcom,msm-mi2s-rx-lines = <1>;
+	qcom,msm-mi2s-tx-lines = <2>;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+	qcom,platform-reset-gpio = <&tlmm 90 0>;
+	qcom,panel-mode-gpio = <&tlmm 4 0>;
+};
+
+&dsi_dual_nt35597_truly_cmd_display {
+	qcom,platform-reset-gpio = <&tlmm 90 0>;
+	qcom,panel-mode-gpio = <&tlmm 4 0>;
+};
+
+&dsi_nt35597_truly_dsc_cmd_display {
+	qcom,platform-reset-gpio = <&tlmm 90 0>;
+	qcom,panel-mode-gpio = <&tlmm 4 0>;
+};
+
+&dsi_nt35597_truly_dsc_video_display {
+	qcom,platform-reset-gpio = <&tlmm 90 0>;
+	qcom,panel-mode-gpio = <&tlmm 4 0>;
+};
+
+&sde_dsi_active {
+	mux {
+		pins = "gpio90", "gpio4";
+		function = "gpio";
+	};
+
+	config {
+		pins = "gpio90", "gpio4";
+		drive-strength = <8>;   /* 8 mA */
+		bias-disable = <0>;   /* no pull */
+	};
+};
+
+&sde_dsi_suspend {
+	mux {
+		pins = "gpio90", "gpio4";
+		function = "gpio";
+	};
+
+	config {
+		pins = "gpio90", "gpio4";
+		drive-strength = <2>;   /* 2 mA */
+		bias-pull-down;         /* PULL DOWN */
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi
index 68f51e2..cc55127 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-mtp.dtsi
@@ -141,6 +141,10 @@
 	qcom,battery-data = <&mtp_batterydata>;
 };
 
+&pm660_charger {
+	qcom,battery-data = <&mtp_batterydata>;
+};
+
 &tlmm {
 	smb_int_default: smb_int_default {
 		mux {
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
index 5684e19..0461429 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
@@ -21,6 +21,52 @@
 		#interrupt-cells = <2>;
 		interrupt-parent = <&pdc>;
 
+		ufs_dev_reset_assert: ufs_dev_reset_assert {
+			config {
+				pins = "ufs_reset";
+				bias-pull-down;		/* default: pull down */
+				/*
+				 * UFS_RESET driver strengths are having
+				 * different values/steps compared to typical
+				 * GPIO drive strengths.
+				 *
+				 * Following table clarifies:
+				 *
+				 * HDRV value | UFS_RESET | Typical GPIO
+				 *   (dec)    |   (mA)    |    (mA)
+				 *     0      |   0.8     |    2
+				 *     1      |   1.55    |    4
+				 *     2      |   2.35    |    6
+				 *     3      |   3.1     |    8
+				 *     4      |   3.9     |    10
+				 *     5      |   4.65    |    12
+				 *     6      |   5.4     |    14
+				 *     7      |   6.15    |    16
+				 *
+				 * POR value for UFS_RESET HDRV is 3 which means
+				 * 3.1mA and we want to use that. Hence just
+				 * specify 8mA to "drive-strength" binding and
+				 * that should result into writing 3 to HDRV
+				 * field.
+				 */
+				drive-strength = <8>;	/* default: 3.1 mA */
+				output-low; /* active low reset */
+			};
+		};
+
+		ufs_dev_reset_deassert: ufs_dev_reset_deassert {
+			config {
+				pins = "ufs_reset";
+				bias-pull-down;		/* default: pull down */
+				/*
+				 * default: 3.1 mA
+				 * check comments under ufs_dev_reset_assert
+				 */
+				drive-strength = <8>;
+				output-high; /* active low reset */
+			};
+		};
+
 		/* QUPv3 South SE mappings */
 		/* SE 0 pin mappings */
 		qupv3_se0_i2c_pins: qupv3_se0_i2c_pins {
@@ -1679,6 +1725,132 @@
 			};
 		};
 
+		aqt_intr {
+			aqt_intr_default: aqt_intr_default{
+				mux {
+					pins = "gpio79";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio79";
+					drive-strength = <2>; /* 2 mA */
+					bias-pull-down; /* pull down */
+					input-enable;
+				};
+			};
+		};
+
+		aqt_rst_gpio {
+			aqt_rst_idle: aqt_rst_idle{
+				mux {
+					pins = "gpio80";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio80";
+					drive-strength = <8>;
+					bias-pull-down;
+					output-low;
+				};
+			};
+			aqt_rst_active: aqt_rst_active{
+				mux {
+					pins = "gpio80";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio80";
+					drive-strength = <8>;
+					bias-disable;
+					output-high;
+				};
+			};
+		};
+
+		ter_i2s_sck_ws {
+			ter_i2s_sck_sleep: ter_i2s_sck_sleep {
+				mux {
+					pins = "gpio75", "gpio76";
+					function = "ter_mi2s";
+				};
+
+				config {
+					pins = "gpio75", "gpio76";
+					drive-strength = <2>;   /* 2 mA */
+				};
+			};
+
+			ter_i2s_sck_active: ter_i2s_sck_active {
+				mux {
+					pins = "gpio75", "gpio76";
+					function = "ter_mi2s";
+				};
+
+				config {
+					pins = "gpio75", "gpio76";
+					drive-strength = <8>;   /* 8 mA */
+					input-enable;
+				};
+			};
+		};
+
+		ter_i2s_data0 {
+			ter_i2s_data0_sleep: ter_i2s_data0_sleep {
+				mux {
+					pins = "gpio77";
+					function = "ter_mi2s";
+				};
+
+				config {
+					pins = "gpio77";
+					drive-strength = <2>;   /* 2 mA */
+				};
+			};
+
+			ter_i2s_data0_active: ter_i2s_data0_active {
+				mux {
+					pins = "gpio77";
+					function = "ter_mi2s";
+				};
+
+				config {
+					pins = "gpio77";
+					drive-strength = <8>;   /* 8 mA */
+					input-enable;
+				};
+			};
+		};
+
+		ter_i2s_data1 {
+			ter_i2s_data1_sleep: ter_i2s_data1_sleep {
+				mux {
+					pins = "gpio78";
+					function = "ter_mi2s";
+				};
+
+				config {
+					pins = "gpio78";
+					drive-strength = <2>;   /* 2 mA */
+				};
+			};
+
+			ter_i2s_data1_active: ter_i2s_data1_active {
+				mux {
+					pins = "gpio78";
+					function = "ter_mi2s";
+				};
+
+				config {
+					pins = "gpio78";
+					drive-strength = <8>;   /* 8 mA */
+					output-high;
+				};
+			};
+		};
+
 		pmx_sde: pmx_sde {
 			sde_dsi_active: sde_dsi_active {
 				mux {
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pm.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pm.dtsi
index c54b8db..bdcd039 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pm.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pm.dtsi
@@ -23,6 +23,7 @@
 			label = "L3";
 			qcom,psci-mode-shift = <4>;
 			qcom,psci-mode-mask = <0xfff>;
+			qcom,clstr-tmr-add = <1000>;
 
 			qcom,pm-cluster-level@0 { /* D1 */
 				reg = <0>;
@@ -77,7 +78,9 @@
 				#size-cells = <0>;
 				qcom,psci-mode-shift = <0>;
 				qcom,psci-mode-mask = <0xf>;
-				qcom,use-prediction;
+				qcom,ref-stddev = <500>;
+				qcom,tmr-add = <1000>;
+				qcom,ref-premature-cnt = <1>;
 				qcom,cpu = <&CPU0 &CPU1 &CPU2 &CPU3 &CPU4
 									&CPU5>;
 
@@ -131,6 +134,7 @@
 				#size-cells = <0>;
 				qcom,psci-mode-shift = <0>;
 				qcom,psci-mode-mask = <0xf>;
+				qcom,disable-prediction;
 				qcom,cpu = <&CPU6 &CPU7>;
 
 				qcom,pm-cpu-level@0 { /* C1 */
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pm660a-aqt1000-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm670-pm660a-aqt1000-cdp-overlay.dts
new file mode 100644
index 0000000..1260e05
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-pm660a-aqt1000-cdp-overlay.dts
@@ -0,0 +1,75 @@
+/* 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/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-int-cdc-aqt.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "sdm670-int-cdc-aqt-overlay.dtsi"
+#include "pm660a.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM670 PM660 + PM660A AQT CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <336 0x0>;
+	qcom,board-id = <1 4>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+	/delete-property/ qcom,dsi-display-active;
+};
+
+&dsi_panel_pwr_supply_labibb_amoled {
+	qcom,panel-supply-entry@2 {
+		reg = <2>;
+		qcom,supply-name = "lab";
+		qcom,supply-min-voltage = <4600000>;
+		qcom,supply-max-voltage = <6100000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+
+	qcom,panel-supply-entry@3 {
+		reg = <3>;
+		qcom,supply-name = "ibb";
+		qcom,supply-min-voltage = <4000000>;
+		qcom,supply-max-voltage = <6300000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+
+	qcom,panel-supply-entry@4 {
+		reg = <4>;
+		qcom,supply-name = "oledb";
+		qcom,supply-min-voltage = <5000000>;
+		qcom,supply-max-voltage = <8100000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+};
+
+&dsi_rm67195_amoled_fhd_cmd_display {
+	qcom,dsi-display-active;
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+	oledb-supply = <&pm660a_oledb>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi b/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi
index 8707af2..a448732 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi
@@ -471,7 +471,9 @@
 			};
 			gpu_vdd_cdev {
 				trip = <&aoss0_trip>;
-				cooling-device = <&msm_gpu 0 0>;
+				/* Vote for SVS_L1 for GPU */
+				cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-3)
+							(THERMAL_MAX_LIMIT-3)>;
 			};
 			cx_vdd_cdev {
 				trip = <&aoss0_trip>;
@@ -521,7 +523,9 @@
 			};
 			gpu_vdd_cdev {
 				trip = <&aoss1_trip>;
-				cooling-device = <&msm_gpu 0 0>;
+				/* Vote for SVS_L1 for GPU */
+				cooling-device = <&msm_gpu (THERMAL_MAX_LIMIT-3)
+							(THERMAL_MAX_LIMIT-3)>;
 			};
 			cx_vdd_cdev {
 				trip = <&aoss1_trip>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 4d4e918..3ca33b2 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -1790,7 +1790,7 @@
 	};
 
 	dcc: dcc_v2@10a2000 {
-		compatible = "qcom,dcc_v2";
+		compatible = "qcom,dcc-v2";
 		reg = <0x10a2000 0x1000>,
 		      <0x10ae000 0x2000>;
 		reg-names = "dcc-base", "dcc-ram-base";
@@ -1935,6 +1935,10 @@
 		qcom,pm-qos-cpu-group-latency-us = <67 67>;
 		qcom,pm-qos-default-cpu = <0>;
 
+		pinctrl-names = "dev-reset-assert", "dev-reset-deassert";
+		pinctrl-0 = <&ufs_dev_reset_assert>;
+		pinctrl-1 = <&ufs_dev_reset_deassert>;
+
 		resets = <&clock_gcc GCC_UFS_PHY_BCR>;
 		reset-names = "core_reset";
 
@@ -2007,7 +2011,7 @@
 			<0 432 0>;
 		interrupt-names = "ipa-irq", "gsi-irq";
 		qcom,ipa-hw-ver = <13>; /* IPA core version = IPAv3.5.1 */
-		qcom,ipa-hw-mode = <1>;
+		qcom,ipa-hw-mode = <0>;
 		qcom,ee = <0>;
 		qcom,use-ipa-tethering-bridge;
 		qcom,modem-cfg-emb-pipe-flt;
diff --git a/arch/arm64/boot/dts/qcom/sdm710-aqt1000-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-aqt1000-cdp-overlay.dts
new file mode 100644
index 0000000..31c99de
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-aqt1000-cdp-overlay.dts
@@ -0,0 +1,35 @@
+/* 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/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-int-cdc-aqt.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "sdm670-int-cdc-aqt-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L AQT CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <1 4>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm710-pm660a-aqt1000-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-pm660a-aqt1000-cdp-overlay.dts
new file mode 100644
index 0000000..50b3470
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-pm660a-aqt1000-cdp-overlay.dts
@@ -0,0 +1,75 @@
+/* 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/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-int-cdc-aqt.dtsi"
+#include "sdm670-int-cdc-aqt-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660A AQT CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <1 4>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+	/delete-property/ qcom,dsi-display-active;
+};
+
+&dsi_panel_pwr_supply_labibb_amoled {
+	qcom,panel-supply-entry@2 {
+		reg = <2>;
+		qcom,supply-name = "lab";
+		qcom,supply-min-voltage = <4600000>;
+		qcom,supply-max-voltage = <6100000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+
+	qcom,panel-supply-entry@3 {
+		reg = <3>;
+		qcom,supply-name = "ibb";
+		qcom,supply-min-voltage = <4000000>;
+		qcom,supply-max-voltage = <6300000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+
+	qcom,panel-supply-entry@4 {
+		reg = <4>;
+		qcom,supply-name = "oledb";
+		qcom,supply-min-voltage = <5000000>;
+		qcom,supply-max-voltage = <8100000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+};
+
+&dsi_rm67195_amoled_fhd_cmd_display {
+	qcom,dsi-display-active;
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+	oledb-supply = <&pm660a_oledb>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710.dtsi b/arch/arm64/boot/dts/qcom/sdm710.dtsi
index 4a051b0..347e846 100644
--- a/arch/arm64/boot/dts/qcom/sdm710.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm710.dtsi
@@ -19,7 +19,7 @@
 };
 
 &msm_gpu {
-	qcom,chipid = <0x06010500>;
+	qcom,chipid = <0x06010600>;
 	/delete-property/qcom,gpu-quirk-limit-uche-gbif-rw;
 	/delete-property/qcom,soc-hw-rev-efuse;
 	/delete-node/qcom,soc-hw-revisions;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pcie.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pcie.dtsi
index af7feb5..c00c264 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-pcie.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-pcie.dtsi
@@ -259,7 +259,7 @@
 				"pcie_tbu_clk", "pcie_phy_refgen_clk",
 				"pcie_phy_aux_clk";
 
-		max-clock-frequency-hz = <0>, <0>, <19200000>, <0>, <0>,
+		max-clock-frequency-hz = <0>, <0>, <19200000>, <0>, <0>, <0>,
 					<0>, <0>, <0>, <0>, <100000000>, <0>;
 
 		resets = <&clock_gcc GCC_PCIE_0_BCR>,
@@ -382,28 +382,29 @@
 					0x01d0 0x30 0x0
 					0x01e0 0x04 0x0
 					0x01e8 0x73 0x0
-					0x01f0 0x1c 0x0
+					0x01f0 0x0c 0x0
 					0x01fc 0x15 0x0
 					0x021c 0x04 0x0
 					0x0224 0x01 0x0
 					0x0228 0x22 0x0
 					0x022c 0x00 0x0
-					0x0098 0x05 0x0
+					0x0098 0x20 0x0
+					0x01c8 0x07 0x0
 					0x080c 0x00 0x0
 					0x0818 0x0d 0x0
 					0x0860 0x01 0x0
-					0x0864 0x3a 0x0
+					0x0864 0x1a 0x0
 					0x087c 0x2f 0x0
 					0x08c0 0x09 0x0
 					0x08c4 0x09 0x0
-					0x08c8 0x1a 0x0
+					0x08c8 0x1b 0x0
 					0x08d0 0x01 0x0
 					0x08d4 0x07 0x0
 					0x08d8 0x31 0x0
 					0x08dc 0x31 0x0
 					0x08e0 0x03 0x0
 					0x08fc 0x02 0x0
-					0x0900 0x01 0x0
+					0x0900 0x00 0x0
 					0x0908 0x12 0x0
 					0x0914 0x25 0x0
 					0x0918 0x00 0x0
@@ -415,17 +416,17 @@
 					0x0934 0x04 0x0
 					0x0938 0x09 0x0
 					0x0954 0x15 0x0
-					0x0960 0x32 0x0
+					0x0960 0x28 0x0
 					0x0968 0x7f 0x0
 					0x096c 0x07 0x0
 					0x0978 0x04 0x0
 					0x0980 0x70 0x0
 					0x0984 0x8b 0x0
 					0x0988 0x08 0x0
-					0x098c 0x09 0x0
+					0x098c 0x0a 0x0
 					0x0990 0x03 0x0
 					0x0994 0x04 0x0
-					0x0998 0x02 0x0
+					0x0998 0x04 0x0
 					0x099c 0x0c 0x0
 					0x09a4 0x02 0x0
 					0x09c0 0x5c 0x0
@@ -437,78 +438,22 @@
 					0x0aa4 0x01 0x0
 					0x0aac 0xc3 0x0
 					0x0ab0 0x00 0x0
-					0x0ab8 0x8c 0x0
+					0x0ab8 0xbc 0x0
 					0x0ac0 0x7f 0x0
-					0x0ac4 0x2a 0x0
+					0x0ac4 0x15 0x0
 					0x0810 0x0c 0x0
-					0x0814 0x00 0x0
+					0x0814 0x0f 0x0
 					0x0acc 0x04 0x0
 					0x093c 0x20 0x0
-					0x100c 0x00 0x0
-					0x1018 0x0d 0x0
-					0x1060 0x01 0x0
-					0x1064 0x3a 0x0
-					0x107c 0x2f 0x0
-					0x10c0 0x09 0x0
-					0x10c4 0x09 0x0
-					0x10c8 0x1a 0x0
-					0x10d0 0x01 0x0
-					0x10d4 0x07 0x0
-					0x10d8 0x31 0x0
-					0x10dc 0x31 0x0
-					0x10e0 0x03 0x0
-					0x10fc 0x02 0x0
-					0x1100 0x01 0x0
-					0x1108 0x12 0x0
-					0x1114 0x25 0x0
-					0x1118 0x00 0x0
-					0x111c 0x05 0x0
-					0x1120 0x01 0x0
-					0x1124 0x26 0x0
-					0x1128 0x12 0x0
-					0x1130 0x04 0x0
-					0x1134 0x04 0x0
-					0x1138 0x09 0x0
-					0x1154 0x15 0x0
-					0x1160 0x32 0x0
-					0x1168 0x7f 0x0
-					0x116c 0x07 0x0
-					0x1178 0x04 0x0
-					0x1180 0x70 0x0
-					0x1184 0x8b 0x0
-					0x1188 0x08 0x0
-					0x118c 0x09 0x0
-					0x1190 0x03 0x0
-					0x1194 0x04 0x0
-					0x1198 0x02 0x0
-					0x119c 0x0c 0x0
-					0x11a4 0x02 0x0
-					0x11c0 0x5c 0x0
-					0x11c4 0x3e 0x0
-					0x11c8 0x3f 0x0
-					0x1230 0x01 0x0
-					0x1234 0xa0 0x0
-					0x1238 0x08 0x0
-					0x12a4 0x01 0x0
-					0x12ac 0xc3 0x0
-					0x12b0 0x00 0x0
-					0x12b8 0x8c 0x0
-					0x12c0 0x7f 0x0
-					0x12c4 0x2a 0x0
-					0x1010 0x0c 0x0
-					0x1014 0x00 0x0
-					0x12cc 0x04 0x0
-					0x113c 0x20 0x0
 					0x195c 0x3f 0x0
-					0x1974 0x58 0x0
-					0x196c 0x9f 0x0
+					0x1974 0x50 0x0
 					0x182c 0x19 0x0
 					0x1840 0x07 0x0
 					0x1854 0x17 0x0
 					0x1868 0x09 0x0
+					0x196c 0x9f 0x0
 					0x1800 0x00 0x0
 					0x0aa8 0x01 0x0
-					0x12a8 0x01 0x0
 					0x1808 0x01 0x0>;
 
 		pinctrl-names = "default";
@@ -595,7 +540,7 @@
 				"pcie_tbu_clk", "pcie_phy_refgen_clk",
 				"pcie_phy_aux_clk";
 
-		max-clock-frequency-hz = <0>, <0>, <19200000>, <0>, <0>,
+		max-clock-frequency-hz = <0>, <0>, <19200000>, <0>, <0>, <0>,
 					<0>, <0>, <0>, <0>, <100000000>, <0>;
 
 		resets = <&clock_gcc GCC_PCIE_1_BCR>,
diff --git a/arch/arm64/boot/dts/qcom/sdm845-pm.dtsi b/arch/arm64/boot/dts/qcom/sdm845-pm.dtsi
index 929239a..350f156 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-pm.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-pm.dtsi
@@ -21,6 +21,7 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			label = "L3";
+			qcom,clstr-tmr-add = <1000>;
 			qcom,psci-mode-shift = <4>;
 			qcom,psci-mode-mask = <0xfff>;
 
@@ -52,7 +53,9 @@
 				#size-cells = <0>;
 				qcom,psci-mode-shift = <0>;
 				qcom,psci-mode-mask = <0xf>;
-				qcom,use-prediction;
+				qcom,ref-stddev = <500>;
+				qcom,tmr-add = <1000>;
+				qcom,ref-premature-cnt = <1>;
 				qcom,cpu = <&CPU0 &CPU1 &CPU2 &CPU3>;
 
 				qcom,pm-cpu-level@0 { /* C1 */
@@ -95,6 +98,9 @@
 				#size-cells = <0>;
 				qcom,psci-mode-shift = <0>;
 				qcom,psci-mode-mask = <0xf>;
+				qcom,ref-stddev = <100>;
+				qcom,tmr-add = <100>;
+				qcom,ref-premature-cnt = <3>;
 				qcom,cpu = <&CPU4 &CPU5 &CPU6 &CPU7>;
 
 				qcom,pm-cpu-level@0 { /* C1 */
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 82e55c4..22b4b90 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -1908,6 +1908,11 @@
 			reg = <0x65c 4>;
 		};
 
+		dload_type@1c {
+			compatible = "qcom,msm-imem-dload-type";
+			reg = <0x1c 0x4>;
+		};
+
 		boot_stats@6b0 {
 			compatible = "qcom,msm-imem-boot_stats";
 			reg = <0x6b0 32>;
@@ -2565,9 +2570,31 @@
 			 <&clock_gcc GCC_CE1_AXI_CLK>;
 		qcom,ce-opp-freq = <171430000>;
 		qcom,request-bw-before-clk;
+
 		qcom,smmu-s1-enable;
 		iommus = <&apps_smmu 0x706 0x1>,
 			 <&apps_smmu 0x716 0x1>;
+
+		qcom_cedev_ns_cb {
+			compatible = "qcom,qcedev,context-bank";
+			label = "ns_context";
+			iommus = <&apps_smmu 0x712 0>,
+			       <&apps_smmu 0x71f 0>;
+			virtual-addr = <0x60000000>;
+			virtual-size = <0x40000000>;
+		};
+
+		qcom_cedev_s_cb {
+			compatible = "qcom,qcedev,context-bank";
+			label = "secure_context";
+			iommus = <&apps_smmu 0x713 0>,
+			       <&apps_smmu 0x71c 0>,
+			       <&apps_smmu 0x71d 0>,
+			       <&apps_smmu 0x71e 0>;
+			virtual-addr = <0x60200000>;
+			virtual-size = <0x40000000>;
+			qcom,secure-context-bank;
+		};
 	};
 
 	qcom_msmhdcp: qcom,msm_hdcp {
@@ -2838,7 +2865,7 @@
 	};
 
 	dcc: dcc_v2@10a2000 {
-		compatible = "qcom,dcc_v2";
+		compatible = "qcom,dcc-v2";
 		reg = <0x10a2000 0x1000>,
 		      <0x10ae000 0x2000>;
 		reg-names = "dcc-base", "dcc-ram-base";
@@ -3767,57 +3794,57 @@
 		compatible = "qcom,mem-dump";
 		memory-region = <&dump_mem>;
 
-		rpmh_dump {
+		rpmh {
 			qcom,dump-size = <0x2000000>;
 			qcom,dump-id = <0xec>;
 		};
 
-		fcm_dump {
+		fcm {
 			qcom,dump-size = <0x8400>;
 			qcom,dump-id = <0xee>;
 		};
 
-		rpm_sw_dump {
+		rpm_sw {
 			qcom,dump-size = <0x28000>;
 			qcom,dump-id = <0xea>;
 		};
 
-		pmic_dump {
+		pmic {
 			qcom,dump-size = <0x10000>;
 			qcom,dump-id = <0xe4>;
 		};
 
-		tmc_etf_dump {
+		tmc_etf {
 			qcom,dump-size = <0x10000>;
 			qcom,dump-id = <0xf0>;
 		};
 
-		tmc_etf_swao_dump {
+		tmc_etfswao {
 			qcom,dump-size = <0x8400>;
 			qcom,dump-id = <0xf1>;
 		};
 
-		tmc_etr_reg_dump {
+		tmc_etr_reg {
 			qcom,dump-size = <0x1000>;
 			qcom,dump-id = <0x100>;
 		};
 
-		tmc_etf_reg_dump {
+		tmc_etf_reg {
 			qcom,dump-size = <0x1000>;
 			qcom,dump-id = <0x101>;
 		};
 
-		tmc_etf_swao_reg_dump {
+		etfswao_reg {
 			qcom,dump-size = <0x1000>;
 			qcom,dump-id = <0x102>;
 		};
 
-		misc_data_dump {
+		misc_data {
 			qcom,dump-size = <0x1000>;
 			qcom,dump-id = <0xe8>;
 		};
 
-		tpdm_swao_dump {
+		tpdm_swao {
 			qcom,dump-size = <0x512>;
 			qcom,dump-id = <0xf2>;
 		};
diff --git a/arch/arm64/configs/msm8937-perf_defconfig b/arch/arm64/configs/msm8937-perf_defconfig
new file mode 100644
index 0000000..78f09fc
--- /dev/null
+++ b/arch/arm64/configs/msm8937-perf_defconfig
@@ -0,0 +1,637 @@
+CONFIG_LOCALVERSION="-perf"
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_FHANDLE is not set
+CONFIG_AUDIT=y
+# CONFIG_AUDITSYSCALL is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_SCHED_WALT=y
+CONFIG_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_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_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# 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_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MSM8937=y
+CONFIG_ARCH_MSM8917=y
+CONFIG_ARCH_SDM429=y
+CONFIG_ARCH_SDM439=y
+# CONFIG_ARM64_ERRATUM_1024718 is not set
+CONFIG_SCHED_MC=y
+CONFIG_NR_CPUS=8
+CONFIG_PREEMPT=y
+CONFIG_HZ_100=y
+CONFIG_CMA=y
+CONFIG_ZSMALLOC=y
+CONFIG_SECCOMP=y
+CONFIG_HARDEN_BRANCH_PREDICTOR=y
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_SWP_EMULATION=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_SETEND_EMULATION=y
+# CONFIG_ARM64_VHE is not set
+CONFIG_RANDOMIZE_BASE=y
+CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_COMPAT=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_CPU_FREQ_MSM=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TEE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_RPFILTER=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RPFILTER=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_L2TP=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_SKBEDIT=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_BT=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+# CONFIG_CFG80211_CRDA_SUPPORT is not set
+CONFIG_RFKILL=y
+CONFIG_NFC_NQ=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_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_HDCP_QSEECOM=y
+CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_SERIAL_MSM_SMD=y
+CONFIG_DIAG_CHAR=y
+CONFIG_DIAG_USES_SMD=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_SMD_PKT=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_MSM_RDBG=m
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MSM_V2=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
+CONFIG_PINCTRL_MSM8937=y
+CONFIG_PINCTRL_MSM8917=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_QPNP_PIN=y
+CONFIG_GPIO_QPNP_PIN_DEBUG=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_QPNP_FG=y
+CONFIG_SMB135X_CHARGER=y
+CONFIG_SMB1351_USB_CHARGER=y
+CONFIG_QPNP_SMB5=y
+CONFIG_QPNP_SMBCHARGER=y
+CONFIG_QPNP_TYPEC=y
+CONFIG_QPNP_QG=y
+CONFIG_MSM_APM=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_QTI_VIRTUAL_SENSOR=y
+CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_REGULATOR_COOLING_DEVICE=y
+CONFIG_QTI_BCL_PMIC5=y
+CONFIG_QTI_BCL_SOC_DRIVER=y
+CONFIG_MFD_SPMI_PMIC=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_CPR=y
+CONFIG_REGULATOR_CPR4_APSS=y
+CONFIG_REGULATOR_CPRH_KBSS=y
+CONFIG_REGULATOR_MEM_ACC=y
+CONFIG_REGULATOR_MSM_GFX_LDO=y
+CONFIG_REGULATOR_QPNP_LABIBB=y
+CONFIG_REGULATOR_QPNP_LCDB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_RPM_SMD=y
+CONFIG_REGULATOR_SPM=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_CAMERA=y
+CONFIG_MSM_CAMERA_DEBUG=y
+CONFIG_MSMB_CAMERA=y
+CONFIG_MSMB_CAMERA_DEBUG=y
+CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
+CONFIG_MSM_CSI20_HEADER=y
+CONFIG_MSM_CSI22_HEADER=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSI31_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_EEPROM=y
+CONFIG_MSM_ISPIF_V2=y
+CONFIG_IMX134=y
+CONFIG_IMX132=y
+CONFIG_OV9724=y
+CONFIG_OV5648=y
+CONFIG_GC0339=y
+CONFIG_OV8825=y
+CONFIG_OV8865=y
+CONFIG_s5k4e1=y
+CONFIG_OV12830=y
+CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
+CONFIG_MSMB_JPEG=y
+CONFIG_MSM_FD=y
+CONFIG_MSM_JPEGDMA=y
+CONFIG_MSM_VIDC_3X_V4L2=y
+CONFIG_MSM_VIDC_3X_GOVERNORS=y
+CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=y
+CONFIG_QCOM_KGSL=y
+CONFIG_FB=y
+CONFIG_FB_MSM=y
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_SERIAL=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_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_QCRNDIS=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+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
+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_QDSS=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
+CONFIG_LEDS_QTI_TRI_LED=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_QPNP_FLASH=y
+CONFIG_LEDS_QPNP_FLASH_V2=y
+CONFIG_LEDS_QPNP_WLED=y
+CONFIG_LEDS_QPNP_HAPTICS=y
+CONFIG_LEDS_QPNP_VIBRATOR_LDO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_DMADEVICES=y
+CONFIG_QCOM_SPS_DMA=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_IPA=y
+CONFIG_RMNET_IPA=y
+CONFIG_RNDIS_IPA=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_COINCELL=y
+CONFIG_QPNP_REVID=y
+CONFIG_USB_BAM=y
+CONFIG_MSM_EXT_DISPLAY=y
+CONFIG_MSM_RMNET_BAM=y
+CONFIG_MSM_MDSS_PLL=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MAILBOX=y
+CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
+CONFIG_MSM_SPM=y
+CONFIG_MSM_L2_SPM=y
+CONFIG_QCOM_SCM=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_MSM_RPM_SMD=y
+CONFIG_QCOM_BUS_SCALING=y
+CONFIG_QCOM_SECURE_BUFFER=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_MSM_SMEM=y
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_DEBUG=y
+CONFIG_MSM_TZ_SMMU=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_SYSMON_COMM=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_ICNSS=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_AVTIMER=y
+CONFIG_MSM_PM=y
+CONFIG_QCOM_DCC=y
+CONFIG_QTI_RPM_STATS_LOG=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_MEM_SHARE_QMI_SERVICE=y
+CONFIG_MSM_BAM_DMUX=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_SIMPLE_DEV=y
+CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_SPDM_SCM=y
+CONFIG_DEVFREQ_SPDM=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
+CONFIG_PWM_QTI_LPG=y
+CONFIG_ARM_GIC_V3_ACL=y
+CONFIG_QTI_MPM=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_SENSORS_SSC=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_FUSE_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_IPC_LOGGING=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_DEBUG_ALIGN_RODATA=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_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_EVENT=y
+CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_ARM64_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM64_CE=y
+CONFIG_CRYPTO_SHA2_ARM64_CE=y
+CONFIG_CRYPTO_GHASH_ARM64_CE=y
+CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
+CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y
+CONFIG_CRYPTO_CRC32_ARM64=y
+CONFIG_QMI_ENCDEC=y
diff --git a/arch/arm64/configs/msm8937_defconfig b/arch/arm64/configs/msm8937_defconfig
new file mode 100644
index 0000000..b4a8e29
--- /dev/null
+++ b/arch/arm64/configs/msm8937_defconfig
@@ -0,0 +1,703 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_FHANDLE is not set
+CONFIG_AUDIT=y
+# CONFIG_AUDITSYSCALL is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_SCHED_WALT=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_RCU_EXPERT=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_RCU_NOCB_CPU=y
+CONFIG_RCU_NOCB_CPU_ALL=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHEDTUNE=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_BPF=y
+CONFIG_SCHED_CORE_CTL=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# 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_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MSM8937=y
+CONFIG_ARCH_MSM8917=y
+CONFIG_ARCH_SDM429=y
+CONFIG_ARCH_SDM439=y
+# CONFIG_ARM64_ERRATUM_1024718 is not set
+CONFIG_SCHED_MC=y
+CONFIG_NR_CPUS=8
+CONFIG_PREEMPT=y
+CONFIG_HZ_100=y
+CONFIG_CLEANCACHE=y
+CONFIG_CMA=y
+CONFIG_CMA_DEBUGFS=y
+CONFIG_ZSMALLOC=y
+CONFIG_SECCOMP=y
+CONFIG_HARDEN_BRANCH_PREDICTOR=y
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_SWP_EMULATION=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_SETEND_EMULATION=y
+# CONFIG_ARM64_VHE is not set
+CONFIG_RANDOMIZE_BASE=y
+CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_COMPAT=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_PM_DEBUG=y
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_CPU_FREQ_MSM=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TEE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_RPFILTER=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RPFILTER=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_L2TP=y
+CONFIG_L2TP_DEBUGFS=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_SKBEDIT=y
+CONFIG_DNS_RESOLVER=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_BT=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+# CONFIG_CFG80211_CRDA_SUPPORT is not set
+CONFIG_RFKILL=y
+CONFIG_NFC_NQ=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_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_HDCP_QSEECOM=y
+CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_DEBUG=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_SERIAL_MSM_SMD=y
+CONFIG_DIAG_CHAR=y
+CONFIG_DIAG_USES_SMD=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_SMD_PKT=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_MSM_RDBG=m
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MSM_V2=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
+CONFIG_PINCTRL_MSM8937=y
+CONFIG_PINCTRL_MSM8917=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_QPNP_PIN=y
+CONFIG_GPIO_QPNP_PIN_DEBUG=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_QPNP_FG=y
+CONFIG_SMB135X_CHARGER=y
+CONFIG_SMB1351_USB_CHARGER=y
+CONFIG_QPNP_SMB5=y
+CONFIG_QPNP_SMBCHARGER=y
+CONFIG_QPNP_TYPEC=y
+CONFIG_QPNP_QG=y
+CONFIG_MSM_APM=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_QTI_VIRTUAL_SENSOR=y
+CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_REGULATOR_COOLING_DEVICE=y
+CONFIG_QTI_BCL_PMIC5=y
+CONFIG_QTI_BCL_SOC_DRIVER=y
+CONFIG_MFD_SPMI_PMIC=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_CPR=y
+CONFIG_REGULATOR_CPR4_APSS=y
+CONFIG_REGULATOR_CPRH_KBSS=y
+CONFIG_REGULATOR_MEM_ACC=y
+CONFIG_REGULATOR_MSM_GFX_LDO=y
+CONFIG_REGULATOR_QPNP_LABIBB=y
+CONFIG_REGULATOR_QPNP_LCDB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_RPM_SMD=y
+CONFIG_REGULATOR_SPM=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_CAMERA=y
+CONFIG_MSM_CAMERA_DEBUG=y
+CONFIG_MSMB_CAMERA=y
+CONFIG_MSMB_CAMERA_DEBUG=y
+CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
+CONFIG_MSM_CSI20_HEADER=y
+CONFIG_MSM_CSI22_HEADER=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSI31_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_EEPROM=y
+CONFIG_MSM_ISPIF_V2=y
+CONFIG_IMX134=y
+CONFIG_IMX132=y
+CONFIG_OV9724=y
+CONFIG_OV5648=y
+CONFIG_GC0339=y
+CONFIG_OV8825=y
+CONFIG_OV8865=y
+CONFIG_s5k4e1=y
+CONFIG_OV12830=y
+CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
+CONFIG_MSMB_JPEG=y
+CONFIG_MSM_FD=y
+CONFIG_MSM_JPEGDMA=y
+CONFIG_MSM_VIDC_3X_V4L2=y
+CONFIG_MSM_VIDC_3X_GOVERNORS=y
+CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=y
+CONFIG_QCOM_KGSL=y
+CONFIG_FB=y
+CONFIG_FB_VIRTUAL=y
+CONFIG_FB_MSM=y
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_SERIAL=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_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_QCRNDIS=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+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
+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_QDSS=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_RING_BUFFER=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
+CONFIG_LEDS_QTI_TRI_LED=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_QPNP_FLASH=y
+CONFIG_LEDS_QPNP_FLASH_V2=y
+CONFIG_LEDS_QPNP_WLED=y
+CONFIG_LEDS_QPNP_HAPTICS=y
+CONFIG_LEDS_QPNP_VIBRATOR_LDO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_DMADEVICES=y
+CONFIG_QCOM_SPS_DMA=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_IPA=y
+CONFIG_RMNET_IPA=y
+CONFIG_RNDIS_IPA=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_COINCELL=y
+CONFIG_QPNP_REVID=y
+CONFIG_USB_BAM=y
+CONFIG_MSM_EXT_DISPLAY=y
+CONFIG_MSM_RMNET_BAM=y
+CONFIG_MSM_MDSS_PLL=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MAILBOX=y
+CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_IOMMU_DEBUG=y
+CONFIG_IOMMU_DEBUG_TRACKING=y
+CONFIG_IOMMU_TESTS=y
+CONFIG_QCOM_CPUSS_DUMP=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
+CONFIG_MSM_SPM=y
+CONFIG_MSM_L2_SPM=y
+CONFIG_QCOM_SCM=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_CORE_HANG_DETECT=y
+CONFIG_MSM_GLADIATOR_HANG_DETECT=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_MSM_DEBUG_LAR_UNLOCK=y
+CONFIG_MSM_RPM_SMD=y
+CONFIG_QCOM_BUS_SCALING=y
+CONFIG_QCOM_SECURE_BUFFER=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_MSM_SMEM=y
+CONFIG_MSM_SMD=y
+CONFIG_MSM_SMD_DEBUG=y
+CONFIG_MSM_TZ_SMMU=y
+CONFIG_TRACER_PKT=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_SYSMON_COMM=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_ICNSS=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_AVTIMER=y
+CONFIG_MSM_PM=y
+CONFIG_QCOM_DCC=y
+CONFIG_QTI_RPM_STATS_LOG=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_MEM_SHARE_QMI_SERVICE=y
+CONFIG_MSM_BAM_DMUX=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_SIMPLE_DEV=y
+CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_SPDM_SCM=y
+CONFIG_DEVFREQ_SPDM=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
+CONFIG_PWM_QTI_LPG=y
+CONFIG_ARM_GIC_V3_ACL=y
+CONFIG_QTI_MPM=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_SENSORS_SSC=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_QFMT_V2=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_PAGE_OWNER=y
+CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_SLUB_DEBUG_PANIC_ON=y
+CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
+CONFIG_PAGE_POISONING=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_FREE=y
+CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_DEBUG_OBJECTS_WORK=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
+CONFIG_SLUB_DEBUG_ON=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_WQ_WATCHDOG=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_PANIC_ON_SCHED_BUG=y
+CONFIG_PANIC_ON_RT_THROTTLING=y
+CONFIG_SCHEDSTATS=y
+CONFIG_SCHED_STACK_END_CHECK=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_LIST=y
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_IPC_LOGGING=y
+CONFIG_QCOM_RTB=y
+CONFIG_QCOM_RTB_SEPARATE_CPUS=y
+CONFIG_FUNCTION_TRACER=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_LKDTM=y
+CONFIG_MEMTEST=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
+CONFIG_ARM64_PTDUMP=y
+CONFIG_PID_IN_CONTEXTIDR=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_SOURCE_ETM4X=y
+CONFIG_CORESIGHT_REMOTE_ETM=y
+CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
+CONFIG_CORESIGHT_QCOM_REPLICATOR=y
+CONFIG_CORESIGHT_DBGUI=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
+CONFIG_CORESIGHT_CTI=y
+CONFIG_CORESIGHT_EVENT=y
+CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_ARM64_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM64_CE=y
+CONFIG_CRYPTO_SHA2_ARM64_CE=y
+CONFIG_CRYPTO_GHASH_ARM64_CE=y
+CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
+CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y
+CONFIG_CRYPTO_CRC32_ARM64=y
+CONFIG_QMI_ENCDEC=y
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index a77f39f..46b34b3 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -7,6 +7,9 @@
 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
@@ -28,6 +31,8 @@
 CONFIG_SCHED_TUNE=y
 CONFIG_DEFAULT_USE_ENERGY_AWARE=y
 CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
 # CONFIG_RD_XZ is not set
 # CONFIG_RD_LZO is not set
 # CONFIG_RD_LZ4 is not set
@@ -51,19 +56,16 @@
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_MSM8953=y
-CONFIG_ARCH_MSM8937=y
-CONFIG_ARCH_MSM8917=y
 CONFIG_ARCH_SDM450=y
 CONFIG_ARCH_SDM632=y
-CONFIG_ARCH_SDM429=y
-CONFIG_ARCH_SDM439=y
+# CONFIG_ARM64_ERRATUM_1024718 is not set
 CONFIG_SCHED_MC=y
 CONFIG_NR_CPUS=8
 CONFIG_PREEMPT=y
 CONFIG_HZ_100=y
 CONFIG_CMA=y
 CONFIG_ZSMALLOC=y
-CONFIG_BALANCE_ANON_FILE_RECLAIM=y
+CONFIG_PROCESS_RECLAIM=y
 CONFIG_SECCOMP=y
 CONFIG_HARDEN_BRANCH_PREDICTOR=y
 CONFIG_ARMV8_DEPRECATED=y
@@ -206,8 +208,6 @@
 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
@@ -219,9 +219,6 @@
 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
@@ -241,7 +238,9 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_HDCP_QSEECOM=y
 CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
 CONFIG_MEMORY_STATE_TIME=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
@@ -266,6 +265,13 @@
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 CONFIG_PPP=y
 CONFIG_PPP_BSDCOMP=y
 CONFIG_PPP_DEFLATE=y
@@ -279,6 +285,21 @@
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
 CONFIG_USB_USBNET=y
+# CONFIG_WLAN_VENDOR_ADMTEK is not set
+# CONFIG_WLAN_VENDOR_ATH is not set
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_CISCO is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+# CONFIG_WLAN_VENDOR_MARVELL is not set
+# CONFIG_WLAN_VENDOR_MEDIATEK is not set
+# CONFIG_WLAN_VENDOR_RALINK is not set
+# CONFIG_WLAN_VENDOR_REALTEK is not set
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_CLD_LL_CORE=y
 CONFIG_INPUT_EVDEV=y
@@ -313,8 +334,6 @@
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
 CONFIG_PINCTRL_MSM8953=y
-CONFIG_PINCTRL_MSM8937=y
-CONFIG_PINCTRL_MSM8917=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
@@ -322,7 +341,6 @@
 CONFIG_GPIO_QPNP_PIN_DEBUG=y
 CONFIG_POWER_RESET_QCOM=y
 CONFIG_QCOM_DLOAD_MODE=y
-CONFIG_POWER_RESET_XGENE=y
 CONFIG_POWER_RESET_SYSCON=y
 CONFIG_QPNP_FG=y
 CONFIG_SMB135X_CHARGER=y
@@ -348,6 +366,7 @@
 CONFIG_QTI_BCL_PMIC5=y
 CONFIG_QTI_BCL_SOC_DRIVER=y
 CONFIG_MFD_SPMI_PMIC=y
+CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_CPR=y
 CONFIG_REGULATOR_CPR4_APSS=y
@@ -396,13 +415,10 @@
 CONFIG_MSM_VIDC_3X_V4L2=y
 CONFIG_MSM_VIDC_3X_GOVERNORS=y
 CONFIG_MSM_SDE_ROTATOR=y
-CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=y
 CONFIG_QCOM_KGSL=y
-CONFIG_DRM=y
-CONFIG_DRM_SDE_EVTLOG_DEBUG=y
-CONFIG_DRM_SDE_RSC=y
+CONFIG_FB=y
 CONFIG_FB_MSM=y
 CONFIG_FB_MSM_MDSS=y
 CONFIG_FB_MSM_MDSS_WRITEBACK=y
@@ -410,9 +426,6 @@
 CONFIG_FB_MSM_MDSS_XLOG_DEBUG=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
@@ -432,8 +445,6 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MSM=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_ACM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
@@ -521,6 +532,7 @@
 CONFIG_QPNP_COINCELL=y
 CONFIG_QPNP_REVID=y
 CONFIG_USB_BAM=y
+CONFIG_MSM_EXT_DISPLAY=y
 CONFIG_MSM_RMNET_BAM=y
 CONFIG_MSM_MDSS_PLL=y
 CONFIG_REMOTE_SPINLOCK_MSM=y
@@ -530,8 +542,8 @@
 CONFIG_QCOM_RUN_QUEUE_STATS=y
 CONFIG_MSM_SPM=y
 CONFIG_MSM_L2_SPM=y
+CONFIG_QCOM_SCM=y
 CONFIG_MSM_BOOT_STATS=y
-CONFIG_QCOM_EUD=y
 CONFIG_QCOM_WATCHDOG_V2=y
 CONFIG_QCOM_MEMORY_DUMP_V2=y
 CONFIG_MSM_RPM_SMD=y
@@ -546,6 +558,7 @@
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_QMI_INTERFACE=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_SYSMON_COMM=y
 CONFIG_MSM_PIL=y
 CONFIG_MSM_PIL_SSR_GENERIC=y
 CONFIG_MSM_PIL_MSS_QDSP6V5=y
@@ -576,18 +589,18 @@
 CONFIG_ANDROID_BINDER_IPC=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V2=y
 CONFIG_FUSE_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_ECRYPT_FS=y
 CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
 # CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index 569a69c..dc58fc3 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -32,6 +32,8 @@
 CONFIG_SCHED_TUNE=y
 CONFIG_DEFAULT_USE_ENERGY_AWARE=y
 CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
 # CONFIG_RD_XZ is not set
 # CONFIG_RD_LZO is not set
 # CONFIG_RD_LZ4 is not set
@@ -55,12 +57,9 @@
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_MSM8953=y
-CONFIG_ARCH_MSM8937=y
-CONFIG_ARCH_MSM8917=y
 CONFIG_ARCH_SDM450=y
 CONFIG_ARCH_SDM632=y
-CONFIG_ARCH_SDM429=y
-CONFIG_ARCH_SDM439=y
+# CONFIG_ARM64_ERRATUM_1024718 is not set
 CONFIG_SCHED_MC=y
 CONFIG_NR_CPUS=8
 CONFIG_PREEMPT=y
@@ -69,7 +68,7 @@
 CONFIG_CMA=y
 CONFIG_CMA_DEBUGFS=y
 CONFIG_ZSMALLOC=y
-CONFIG_BALANCE_ANON_FILE_RECLAIM=y
+CONFIG_PROCESS_RECLAIM=y
 CONFIG_SECCOMP=y
 CONFIG_HARDEN_BRANCH_PREDICTOR=y
 CONFIG_ARMV8_DEPRECATED=y
@@ -214,8 +213,6 @@
 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
@@ -227,9 +224,6 @@
 CONFIG_NET_EMATCH_META=y
 CONFIG_NET_EMATCH_TEXT=y
 CONFIG_NET_CLS_ACT=y
-CONFIG_NET_ACT_GACT=y
-CONFIG_NET_ACT_MIRRED=y
-CONFIG_NET_ACT_SKBEDIT=y
 CONFIG_DNS_RESOLVER=y
 CONFIG_RMNET_DATA=y
 CONFIG_RMNET_DATA_FC=y
@@ -250,6 +244,7 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_HDCP_QSEECOM=y
 CONFIG_QSEECOM=y
 CONFIG_UID_SYS_STATS=y
 CONFIG_MEMORY_STATE_TIME=y
@@ -276,6 +271,14 @@
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
+# CONFIG_NET_VENDOR_AMAZON is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
+# CONFIG_NET_VENDOR_HISILICON is not set
+# CONFIG_NET_VENDOR_NETRONOME is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SYNOPSYS is not set
 CONFIG_PPP=y
 CONFIG_PPP_BSDCOMP=y
 CONFIG_PPP_DEFLATE=y
@@ -289,6 +292,21 @@
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
 CONFIG_USB_USBNET=y
+# CONFIG_WLAN_VENDOR_ADMTEK is not set
+# CONFIG_WLAN_VENDOR_ATH is not set
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_CISCO is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+# CONFIG_WLAN_VENDOR_MARVELL is not set
+# CONFIG_WLAN_VENDOR_MEDIATEK is not set
+# CONFIG_WLAN_VENDOR_RALINK is not set
+# CONFIG_WLAN_VENDOR_REALTEK is not set
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_CLD_LL_CORE=y
 CONFIG_INPUT_EVDEV=y
@@ -325,8 +343,6 @@
 CONFIG_SPMI=y
 CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
 CONFIG_PINCTRL_MSM8953=y
-CONFIG_PINCTRL_MSM8937=y
-CONFIG_PINCTRL_MSM8917=y
 CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
@@ -334,7 +350,6 @@
 CONFIG_GPIO_QPNP_PIN_DEBUG=y
 CONFIG_POWER_RESET_QCOM=y
 CONFIG_QCOM_DLOAD_MODE=y
-CONFIG_POWER_RESET_XGENE=y
 CONFIG_POWER_RESET_SYSCON=y
 CONFIG_QPNP_FG=y
 CONFIG_SMB135X_CHARGER=y
@@ -360,6 +375,7 @@
 CONFIG_QTI_BCL_PMIC5=y
 CONFIG_QTI_BCL_SOC_DRIVER=y
 CONFIG_MFD_SPMI_PMIC=y
+CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_CPR=y
 CONFIG_REGULATOR_CPR4_APSS=y
@@ -408,13 +424,10 @@
 CONFIG_MSM_VIDC_3X_V4L2=y
 CONFIG_MSM_VIDC_3X_GOVERNORS=y
 CONFIG_MSM_SDE_ROTATOR=y
-CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
 CONFIG_RADIO_IRIS=y
 CONFIG_RADIO_IRIS_TRANSPORT=y
 CONFIG_QCOM_KGSL=y
-CONFIG_DRM=y
-CONFIG_DRM_SDE_EVTLOG_DEBUG=y
-CONFIG_DRM_SDE_RSC=y
+CONFIG_FB=y
 CONFIG_FB_VIRTUAL=y
 CONFIG_FB_MSM=y
 CONFIG_FB_MSM_MDSS=y
@@ -423,9 +436,6 @@
 CONFIG_FB_MSM_MDSS_XLOG_DEBUG=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
@@ -445,8 +455,6 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MSM=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_ACM=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE_DATAFAB=y
@@ -535,6 +543,7 @@
 CONFIG_QPNP_COINCELL=y
 CONFIG_QPNP_REVID=y
 CONFIG_USB_BAM=y
+CONFIG_MSM_EXT_DISPLAY=y
 CONFIG_MSM_RMNET_BAM=y
 CONFIG_MSM_MDSS_PLL=y
 CONFIG_REMOTE_SPINLOCK_MSM=y
@@ -548,10 +557,10 @@
 CONFIG_QCOM_RUN_QUEUE_STATS=y
 CONFIG_MSM_SPM=y
 CONFIG_MSM_L2_SPM=y
+CONFIG_QCOM_SCM=y
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_MSM_CORE_HANG_DETECT=y
 CONFIG_MSM_GLADIATOR_HANG_DETECT=y
-CONFIG_QCOM_EUD=y
 CONFIG_QCOM_WATCHDOG_V2=y
 CONFIG_QCOM_MEMORY_DUMP_V2=y
 CONFIG_MSM_DEBUG_LAR_UNLOCK=y
@@ -568,6 +577,7 @@
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_QMI_INTERFACE=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_SYSMON_COMM=y
 CONFIG_MSM_PIL=y
 CONFIG_MSM_PIL_SSR_GENERIC=y
 CONFIG_MSM_PIL_MSS_QDSP6V5=y
@@ -599,9 +609,7 @@
 CONFIG_ANDROID_BINDER_IPC=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
@@ -609,9 +617,11 @@
 CONFIG_FUSE_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_ECRYPT_FS=y
 CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
 # CONFIG_NETWORK_FILESYSTEMS is not set
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index 5297e3f..f82678e 100644
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -66,6 +66,7 @@
 CONFIG_BALANCE_ANON_FILE_RECLAIM=y
 CONFIG_PROCESS_RECLAIM=y
 CONFIG_SECCOMP=y
+CONFIG_HARDEN_BRANCH_PREDICTOR=y
 CONFIG_ARMV8_DEPRECATED=y
 CONFIG_SWP_EMULATION=y
 CONFIG_CP15_BARRIER_EMULATION=y
@@ -442,6 +443,7 @@
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_BLOCK_MINORS=32
 CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
 CONFIG_MMC_TEST=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index ad75f53..ee3418b 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -71,6 +71,7 @@
 CONFIG_BALANCE_ANON_FILE_RECLAIM=y
 CONFIG_PROCESS_RECLAIM=y
 CONFIG_SECCOMP=y
+CONFIG_HARDEN_BRANCH_PREDICTOR=y
 CONFIG_ARMV8_DEPRECATED=y
 CONFIG_SWP_EMULATION=y
 CONFIG_CP15_BARRIER_EMULATION=y
@@ -243,6 +244,7 @@
 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
@@ -448,6 +450,7 @@
 CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_RING_BUFFER=y
 CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_BLOCK_MINORS=32
 CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
 CONFIG_MMC_TEST=y
@@ -616,11 +619,6 @@
 CONFIG_SLUB_DEBUG_PANIC_ON=y
 CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
 CONFIG_PAGE_POISONING=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_FREE=y
-CONFIG_DEBUG_OBJECTS_TIMERS=y
-CONFIG_DEBUG_OBJECTS_WORK=y
-CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
 CONFIG_SLUB_DEBUG_ON=y
 CONFIG_DEBUG_KMEMLEAK=y
 CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
@@ -646,6 +644,7 @@
 CONFIG_QCOM_RTB=y
 CONFIG_QCOM_RTB_SEPARATE_CPUS=y
 CONFIG_FUNCTION_TRACER=y
+CONFIG_PREEMPTIRQ_EVENTS=y
 CONFIG_IRQSOFF_TRACER=y
 CONFIG_PREEMPT_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 8f213f4..f5dc2a8 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -545,7 +545,6 @@
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_QMP_DEBUGFS_CLIENT=y
-CONFIG_MEM_SHARE_QMI_SERVICE=y
 CONFIG_QSEE_IPC_IRQ_BRIDGE=y
 CONFIG_QCOM_BIMC_BWMON=y
 CONFIG_ARM_MEMLAT_MON=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index d3ae4a5..8dc560d 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -528,6 +528,7 @@
 CONFIG_QCOM_WATCHDOG_V2=y
 CONFIG_QCOM_WDOG_IPI_ENABLE=y
 CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_QCOM_MINIDUMP=y
 CONFIG_QCOM_BUS_SCALING=y
 CONFIG_QCOM_BUS_CONFIG_RPMH=y
 CONFIG_QCOM_SECURE_BUFFER=y
@@ -563,7 +564,6 @@
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_QMP_DEBUGFS_CLIENT=y
-CONFIG_MEM_SHARE_QMI_SERVICE=y
 CONFIG_MSM_REMOTEQDSS=y
 CONFIG_QSEE_IPC_IRQ_BRIDGE=y
 CONFIG_QCOM_BIMC_BWMON=y
@@ -617,11 +617,6 @@
 CONFIG_SLUB_DEBUG_PANIC_ON=y
 CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
 CONFIG_PAGE_POISONING=y
-CONFIG_DEBUG_OBJECTS=y
-CONFIG_DEBUG_OBJECTS_FREE=y
-CONFIG_DEBUG_OBJECTS_TIMERS=y
-CONFIG_DEBUG_OBJECTS_WORK=y
-CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
 CONFIG_SLUB_DEBUG_ON=y
 CONFIG_DEBUG_KMEMLEAK=y
 CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
@@ -649,6 +644,7 @@
 CONFIG_QCOM_RTB=y
 CONFIG_QCOM_RTB_SEPARATE_CPUS=y
 CONFIG_FUNCTION_TRACER=y
+CONFIG_PREEMPTIRQ_EVENTS=y
 CONFIG_IRQSOFF_TRACER=y
 CONFIG_PREEMPT_TRACER=y
 CONFIG_BLK_DEV_IO_TRACE=y
diff --git a/arch/arm64/include/asm/dma-iommu.h b/arch/arm64/include/asm/dma-iommu.h
index cfd49b2..fefec0b 100644
--- a/arch/arm64/include/asm/dma-iommu.h
+++ b/arch/arm64/include/asm/dma-iommu.h
@@ -25,6 +25,7 @@
 	dma_addr_t		base;
 	u32			min_iova_align;
 	struct page		*guard_page;
+	u32			force_guard_page_len;
 
 	struct dma_fast_smmu_mapping *fast;
 };
diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index 85997c0..e52727c 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -181,6 +181,85 @@
 #define ESR_ELx_SYS64_ISS_SYS_CNTFRQ	(ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 0, 14, 0) | \
 					 ESR_ELx_SYS64_ISS_DIR_READ)
 
+/* ISS field definitions for CP15 AArch32 access traps */
+#define ESR_ELx_CP15_32_ISS_CV_SHIFT	24
+#define ESR_ELx_CP15_32_ISS_CV_MASK \
+				(UL(0x1) << ESR_ELx_CP15_32_ISS_CV_SHIFT)
+#define ESR_ELx_CP15_32_ISS_DIR_MASK	0x1
+#define ESR_ELx_CP15_32_ISS_DIR_READ	0x1
+#define ESR_ELx_CP15_32_ISS_DIR_WRITE	0x0
+
+#define ESR_ELx_CP15_32_ISS_RT_SHIFT	5
+#define ESR_ELx_CP15_32_ISS_RT_MASK \
+				(UL(0x1f) << ESR_ELx_CP15_32_ISS_RT_SHIFT)
+#define ESR_ELx_CP15_32_ISS_CRM_SHIFT	1
+#define ESR_ELx_CP15_32_ISS_CRM_MASK \
+				(UL(0xf) << ESR_ELx_CP15_32_ISS_CRM_SHIFT)
+#define ESR_ELx_CP15_32_ISS_CRN_SHIFT	10
+#define ESR_ELx_CP15_32_ISS_CRN_MASK \
+				(UL(0xf) << ESR_ELx_CP15_32_ISS_CRN_SHIFT)
+#define ESR_ELx_CP15_32_ISS_OP1_SHIFT	14
+#define ESR_ELx_CP15_32_ISS_OP1_MASK \
+				(UL(0x7) << ESR_ELx_CP15_32_ISS_OP1_SHIFT)
+#define ESR_ELx_CP15_32_ISS_OP2_SHIFT	17
+#define ESR_ELx_CP15_32_ISS_OP2_MASK \
+				(UL(0x7) << ESR_ELx_CP15_32_ISS_OP2_SHIFT)
+#define ESR_ELx_CP15_32_ISS_COND_SHIFT	20
+#define ESR_ELx_CP15_32_ISS_COND_MASK \
+				(UL(0xf) << ESR_ELx_CP15_32_ISS_COND_SHIFT)
+#define ESR_ELx_CP15_32_ISS_SYS_MASK	(ESR_ELx_CP15_32_ISS_OP1_MASK | \
+					 ESR_ELx_CP15_32_ISS_OP2_MASK | \
+					 ESR_ELx_CP15_32_ISS_CRN_MASK | \
+					 ESR_ELx_CP15_32_ISS_CRM_MASK)
+#define ESR_ELx_CP15_32_ISS_SYS_VAL(op1, op2, crn, crm) \
+				(((op1) << ESR_ELx_CP15_32_ISS_OP1_SHIFT) | \
+				 ((op2) << ESR_ELx_CP15_32_ISS_OP2_SHIFT) | \
+				 ((crn) << ESR_ELx_CP15_32_ISS_CRN_SHIFT) | \
+				 ((crm) << ESR_ELx_CP15_32_ISS_CRM_SHIFT))
+
+#define ESR_ELx_CP15_32_ISS_SYS_OP_MASK	(ESR_ELx_CP15_32_ISS_SYS_MASK | \
+					 ESR_ELx_CP15_32_ISS_DIR_MASK)
+
+#define ESR_ELx_CP15_32_ISS_SYS_CNTFRQ	\
+				(ESR_ELx_CP15_32_ISS_SYS_VAL(0, 0, 14, 0) | \
+				 ESR_ELx_CP15_32_ISS_DIR_READ)
+
+/* ISS field definitions for CP15 AArch32 64-bit access traps */
+#define ESR_ELx_CP15_64_ISS_CV_SHIFT	24
+#define ESR_ELx_CP15_64_ISS_CV_MASK \
+				(UL(0x1) << ESR_ELx_CP15_64_ISS_CV_SHIFT)
+#define ESR_ELx_CP15_64_ISS_DIR_MASK	0x1
+#define ESR_ELx_CP15_64_ISS_DIR_READ	0x1
+#define ESR_ELx_CP15_64_ISS_DIR_WRITE	0x0
+
+#define ESR_ELx_CP15_64_ISS_RT_SHIFT	5
+#define ESR_ELx_CP15_64_ISS_RT_MASK \
+				(UL(0x1f) << ESR_ELx_CP15_64_ISS_RT_SHIFT)
+#define ESR_ELx_CP15_64_ISS_CRM_SHIFT	1
+#define ESR_ELx_CP15_64_ISS_CRM_MASK \
+				(UL(0xf) << ESR_ELx_CP15_64_ISS_CRM_SHIFT)
+#define ESR_ELx_CP15_64_ISS_RT2_SHIFT	10
+#define ESR_ELx_CP15_64_ISS_RT2_MASK \
+				(UL(0x1f) << ESR_ELx_CP15_64_ISS_RT2_SHIFT)
+#define ESR_ELx_CP15_64_ISS_OP1_SHIFT	16
+#define ESR_ELx_CP15_64_ISS_OP1_MASK \
+				(UL(0xf) << ESR_ELx_CP15_64_ISS_OP1_SHIFT)
+#define ESR_ELx_CP15_64_ISS_COND_SHIFT	20
+#define ESR_ELx_CP15_64_ISS_COND_MASK \
+				(UL(0xf) << ESR_ELx_CP15_64_ISS_COND_SHIFT)
+#define ESR_ELx_CP15_64_ISS_SYS_MASK	(ESR_ELx_CP15_64_ISS_OP1_MASK | \
+					 ESR_ELx_CP15_64_ISS_CRM_MASK)
+#define ESR_ELx_CP15_64_ISS_SYS_VAL(op1, crm) \
+				(((op1) << ESR_ELx_CP15_64_ISS_OP1_SHIFT) | \
+				 ((crm) << ESR_ELx_CP15_64_ISS_CRM_SHIFT))
+
+#define ESR_ELx_CP15_64_ISS_SYS_OP_MASK	(ESR_ELx_CP15_64_ISS_SYS_MASK | \
+					 ESR_ELx_CP15_64_ISS_DIR_MASK)
+
+#define ESR_ELx_CP15_64_ISS_SYS_CNTVCT	\
+				(ESR_ELx_CP15_64_ISS_SYS_VAL(1, 14) | \
+				 ESR_ELx_CP15_64_ISS_DIR_READ)
+
 #ifndef __ASSEMBLY__
 #include <asm/types.h>
 
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 458773a..69f6cae 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -130,8 +130,12 @@
 #ifdef CONFIG_COMPAT
 #define compat_thumb_mode(regs) \
 	(((regs)->pstate & COMPAT_PSR_T_BIT))
+#define compat_arm_instr_set(regs) \
+	(((regs)->pstate & (COMPAT_PSR_T_BIT | COMPAT_PSR_J_BIT)) == 0)
 #else
 #define compat_thumb_mode(regs) (0)
+#define compat_arm_instr_set(regs) (0)
+
 #endif
 
 #define user_mode(regs)	\
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 3b22fa3..f8ba35d 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -601,9 +601,9 @@
 	cmp	x24, #ESR_ELx_EC_UNKNOWN	// unknown exception in EL0
 	b.eq	el0_undef
 	cmp	x24, #ESR_ELx_EC_CP15_32	// CP15 MRC/MCR trap
-	b.eq	el0_undef
+	b.eq	el0_cp15_32_compat
 	cmp	x24, #ESR_ELx_EC_CP15_64	// CP15 MRRC/MCRR trap
-	b.eq	el0_undef
+	b.eq	el0_cp15_64_compat
 	cmp	x24, #ESR_ELx_EC_CP14_MR	// CP14 MRC/MCR trap
 	b.eq	el0_undef
 	cmp	x24, #ESR_ELx_EC_CP14_LS	// CP14 LDC/STC trap
@@ -622,6 +622,28 @@
 	mov     sc_nr, #__NR_compat_syscalls
 	b	el0_svc_naked
 
+el0_cp15_32_compat:
+	/*
+	 * AArch32 CP15 MRC/MCR trap handling
+	 */
+	enable_dbg_and_irq
+	ct_user_exit
+	mov	x0, x25
+	mov	x1, sp
+	bl	do_cp15_32_instr_compat
+	b	ret_to_user
+
+el0_cp15_64_compat:
+	/*
+	 * AArch32 CP15 MRRC/MCRR trap handling
+	 */
+	enable_dbg_and_irq
+	ct_user_exit
+	mov	x0, x25
+	mov	x1, sp
+	bl	do_cp15_64_instr_compat
+	b	ret_to_user
+
 	.align	6
 el0_irq_compat:
 	kernel_entry 0, 32
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 90be97b..bfaead1 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -606,6 +606,124 @@
 	force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
 }
 
+#ifdef CONFIG_COMPAT
+static void cntfrq_cp15_32_read_handler(unsigned int esr, struct pt_regs *regs)
+{
+	int rt =
+	  (esr & ESR_ELx_CP15_32_ISS_RT_MASK) >> ESR_ELx_CP15_32_ISS_RT_SHIFT;
+	int cv =
+	  (esr & ESR_ELx_CP15_32_ISS_CV_MASK) >> ESR_ELx_CP15_32_ISS_CV_SHIFT;
+	int cond =
+	  (esr & ESR_ELx_CP15_32_ISS_COND_MASK) >>
+		ESR_ELx_CP15_32_ISS_COND_SHIFT;
+	bool read_reg = 1;
+
+	if (rt == 13 && !compat_arm_instr_set(regs))
+		read_reg = 0;
+
+	if (cv && cond != 0xf &&
+	    !(*aarch32_opcode_cond_checks[cond])(regs->pstate & 0xffffffff))
+		read_reg = 0;
+
+	if (read_reg)
+		regs->regs[rt] = read_sysreg(cntfrq_el0);
+	regs->pc += 4;
+}
+
+struct cp15_32_hook {
+	unsigned int esr_mask;
+	unsigned int esr_val;
+	void (*handler)(unsigned int esr, struct pt_regs *regs);
+};
+
+static struct cp15_32_hook cp15_32_hooks[] = {
+	{
+		/* Trap CP15 AArch32 read access to CNTFRQ_EL0 */
+		.esr_mask = ESR_ELx_CP15_32_ISS_SYS_OP_MASK,
+		.esr_val = ESR_ELx_CP15_32_ISS_SYS_CNTFRQ,
+		.handler = cntfrq_cp15_32_read_handler,
+	},
+	{},
+};
+
+asmlinkage void __exception do_cp15_32_instr_compat(unsigned int esr,
+						    struct pt_regs *regs)
+{
+	struct cp15_32_hook *hook;
+
+	for (hook = cp15_32_hooks; hook->handler; hook++)
+		if ((hook->esr_mask & esr) == hook->esr_val) {
+			hook->handler(esr, regs);
+			return;
+		}
+
+	force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
+}
+
+static void cntvct_cp15_64_read_handler(unsigned int esr, struct pt_regs *regs)
+{
+	int rt =
+	  (esr & ESR_ELx_CP15_64_ISS_RT_MASK) >> ESR_ELx_CP15_64_ISS_RT_SHIFT;
+	int rt2 =
+	  (esr & ESR_ELx_CP15_64_ISS_RT2_MASK) >> ESR_ELx_CP15_64_ISS_RT2_SHIFT;
+	int cv =
+	  (esr & ESR_ELx_CP15_64_ISS_CV_MASK) >> ESR_ELx_CP15_64_ISS_CV_SHIFT;
+	int cond =
+	  (esr & ESR_ELx_CP15_64_ISS_COND_MASK) >>
+		ESR_ELx_CP15_64_ISS_COND_SHIFT;
+	bool read_reg = 1;
+
+	if (rt == 15 || rt2 == 15 || rt == rt2)
+		read_reg = 0;
+
+	if ((rt == 13 || rt2 == 13) && !compat_arm_instr_set(regs))
+		read_reg = 0;
+
+	if (cv && cond != 0xf &&
+	    !(*aarch32_opcode_cond_checks[cond])(regs->pstate & 0xffffffff))
+		read_reg = 0;
+
+	if (read_reg) {
+		u64 cval =  arch_counter_get_cntvct();
+
+		regs->regs[rt] = cval & 0xffffffff;
+		regs->regs[rt2] = cval >> 32;
+	}
+	regs->pc += 4;
+}
+
+struct cp15_64_hook {
+	unsigned int esr_mask;
+	unsigned int esr_val;
+	void (*handler)(unsigned int esr, struct pt_regs *regs);
+};
+
+static struct cp15_64_hook cp15_64_hooks[] = {
+	{
+		/* Trap CP15 AArch32 read access to CNTVCT_EL0 */
+		.esr_mask = ESR_ELx_CP15_64_ISS_SYS_OP_MASK,
+		.esr_val = ESR_ELx_CP15_64_ISS_SYS_CNTVCT,
+		.handler = cntvct_cp15_64_read_handler,
+	},
+	{},
+};
+
+asmlinkage void __exception do_cp15_64_instr_compat(unsigned int esr,
+						    struct pt_regs *regs)
+{
+	struct cp15_64_hook *hook;
+
+	for (hook = cp15_64_hooks; hook->handler; hook++)
+		if ((hook->esr_mask & esr) == hook->esr_val) {
+			hook->handler(esr, regs);
+			return;
+		}
+
+	force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
+}
+
+#endif
+
 long compat_arm_syscall(struct pt_regs *regs);
 
 asmlinkage long do_ni_syscall(struct pt_regs *regs)
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 31d4684..42dde2d 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -1183,7 +1183,8 @@
 
 	size = PAGE_ALIGN(size);
 	if (mapping->min_iova_align)
-		guard_len = ALIGN(size, mapping->min_iova_align) - size;
+		guard_len = ALIGN(size + mapping->force_guard_page_len,
+				  mapping->min_iova_align) - size;
 	else
 		guard_len = 0;
 
@@ -1231,12 +1232,14 @@
 
 	addr = addr & PAGE_MASK;
 	size = PAGE_ALIGN(size);
-	if (mapping->min_iova_align) {
-		guard_len = ALIGN(size, mapping->min_iova_align) - size;
-		iommu_unmap(mapping->domain, addr + size, guard_len);
-	} else {
+	if (mapping->min_iova_align)
+		guard_len = ALIGN(size + mapping->force_guard_page_len,
+				  mapping->min_iova_align) - size;
+	else
 		guard_len = 0;
-	}
+
+	if (guard_len)
+		iommu_unmap(mapping->domain, addr + size, guard_len);
 
 	start = (addr - mapping->base) >> PAGE_SHIFT;
 	count = (size + guard_len) >> PAGE_SHIFT;
@@ -1987,21 +1990,30 @@
 	unsigned int bitmap_size = BITS_TO_LONGS(mapping->bits) * sizeof(long);
 	int vmid = VMID_HLOS;
 	int min_iova_align = 0;
+	int force_iova_guard_page = 0;
 
 	iommu_domain_get_attr(mapping->domain,
 			DOMAIN_ATTR_MMU500_ERRATA_MIN_ALIGN,
 			&min_iova_align);
 	iommu_domain_get_attr(mapping->domain,
 			DOMAIN_ATTR_SECURE_VMID, &vmid);
+	iommu_domain_get_attr(mapping->domain,
+			      DOMAIN_ATTR_FORCE_IOVA_GUARD_PAGE,
+			      &force_iova_guard_page);
+
 	if (vmid >= VMID_LAST || vmid < 0)
 		vmid = VMID_HLOS;
 
-	if (min_iova_align) {
-		mapping->min_iova_align = ARM_SMMU_MIN_IOVA_ALIGN;
-		mapping->guard_page = arm_smmu_errata_get_guard_page(vmid);
-		if (!mapping->guard_page)
-			return -ENOMEM;
-	}
+	mapping->min_iova_align = (min_iova_align) ? ARM_SMMU_MIN_IOVA_ALIGN :
+		PAGE_SIZE;
+
+	if (force_iova_guard_page)
+		mapping->force_guard_page_len = PAGE_SIZE;
+
+	mapping->guard_page =
+		arm_smmu_errata_get_guard_page(vmid);
+	if (!mapping->guard_page)
+		return -ENOMEM;
 
 	mapping->bitmap = kzalloc(bitmap_size, GFP_KERNEL | __GFP_NOWARN |
 							__GFP_NORETRY);
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index 45fc564..9afd9a9 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -33,6 +33,17 @@
 config REGMAP_SWR
 	tristate
 
+config AQT_REGMAP
+	depends on SND_SOC
+	bool "For regmap on AQT"
+	select REGMAP_IRQ
+	default n
+	help
+	   Say 'y' here to enable regmap_irq for aqt1000 codec.
+	   This config is intended for enabling REGMAP_IRQ for
+	   AQT1000 codec. AQT codec uses pm_runtime and calls
+	   regmap_irq as a part of init.
+
 config REGMAP_ALLOW_WRITE_DEBUGFS
 	depends on REGMAP && DEBUG_FS
 	bool "Allow REGMAP debugfs write"
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index c9ceb48..7f8a158 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -66,6 +66,9 @@
 #define AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME   "audio_pdr_adsprpc"
 #define AUDIO_PDR_ADSP_SERVICE_NAME              "avs/audio"
 
+#define SENSORS_PDR_SERVICE_LOCATION_CLIENT_NAME   "sensors_pdr_adsprpc"
+#define SENSORS_PDR_ADSP_SERVICE_NAME              "tms/servreg"
+
 #define RPC_TIMEOUT	(5 * HZ)
 #define BALIGN		128
 #define NUM_CHANNELS	4	/* adsp, mdsp, slpi, cdsp*/
@@ -120,7 +123,7 @@
 
 static int fastrpc_glink_open(int cid);
 static void fastrpc_glink_close(void *chan, int cid);
-static int fastrpc_audio_pdr_notifier_cb(struct notifier_block *nb,
+static int fastrpc_pdr_notifier_cb(struct notifier_block *nb,
 					unsigned long code,
 					void *data);
 static struct dentry *debugfs_root;
@@ -230,6 +233,7 @@
 	int faults;
 	int secure;
 	int coherent;
+	int sharedcb;
 };
 
 struct fastrpc_session_ctx {
@@ -366,6 +370,7 @@
 	int pd;
 	char *spdname;
 	int file_close;
+	int sharedcb;
 	struct fastrpc_apps *apps;
 	struct hlist_head perf;
 	struct dentry *debugfs_file;
@@ -391,7 +396,13 @@
 				.spdname =
 					AUDIO_PDR_SERVICE_LOCATION_CLIENT_NAME,
 				.pdrnb.notifier_call =
-						fastrpc_audio_pdr_notifier_cb,
+						fastrpc_pdr_notifier_cb,
+			},
+			{
+				.spdname =
+				SENSORS_PDR_SERVICE_LOCATION_CLIENT_NAME,
+				.pdrnb.notifier_call =
+						fastrpc_pdr_notifier_cb,
 			}
 		},
 	},
@@ -582,16 +593,20 @@
 	return -ENOTTY;
 }
 
-static int dma_alloc_memory(dma_addr_t *region_phys, void **vaddr, size_t size)
+static int dma_alloc_memory(dma_addr_t *region_phys, size_t size)
 {
 	struct fastrpc_apps *me = &gfa;
+	void *vaddr = NULL;
+	unsigned long dma_attrs = 0;
 
 	if (me->dev == NULL) {
 		pr_err("device adsprpc-mem is not initialized\n");
 		return -ENODEV;
 	}
-	*vaddr = dma_alloc_coherent(me->dev, size, region_phys, GFP_KERNEL);
-	if (!*vaddr) {
+	dma_attrs |= DMA_ATTR_SKIP_ZEROING | DMA_ATTR_NO_KERNEL_MAPPING;
+	vaddr = dma_alloc_attrs(me->dev, size, region_phys, GFP_KERNEL,
+								dma_attrs);
+	if (!vaddr) {
 		pr_err("ADSPRPC: Failed to allocate %x remote heap memory\n",
 						(unsigned int)size);
 		return -ENOMEM;
@@ -665,14 +680,17 @@
 	}
 	if (map->flags == ADSP_MMAP_HEAP_ADDR ||
 				map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
+		unsigned long dma_attrs = 0;
 
 		if (me->dev == NULL) {
 			pr_err("failed to free remote heap allocation\n");
 			return;
 		}
 		if (map->phys) {
-			dma_free_coherent(me->dev, map->size,
-				(void *)map->va, (dma_addr_t)map->phys);
+			dma_attrs |=
+			DMA_ATTR_SKIP_ZEROING | DMA_ATTR_NO_KERNEL_MAPPING;
+			dma_free_attrs(me->dev, map->size, (void *)map->va,
+					(dma_addr_t)map->phys, dma_attrs);
 		}
 	} else if (map->flags == FASTRPC_DMAHANDLE_NOMAP) {
 		if (!IS_ERR_OR_NULL(map->handle))
@@ -729,7 +747,6 @@
 	struct fastrpc_mmap *map = NULL;
 	unsigned long attrs;
 	dma_addr_t region_phys = 0;
-	void *region_vaddr = NULL;
 	unsigned long flags;
 	int err = 0, vmid;
 
@@ -749,13 +766,12 @@
 				mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
 		map->apps = me;
 		map->fl = NULL;
-		VERIFY(err, !dma_alloc_memory(&region_phys, &region_vaddr,
-						 len));
+		VERIFY(err, !dma_alloc_memory(&region_phys, len));
 		if (err)
 			goto bail;
 		map->phys = (uintptr_t)region_phys;
 		map->size = len;
-		map->va = (uintptr_t)region_vaddr;
+		map->va = (uintptr_t)map->phys;
 	} else if (mflags == FASTRPC_DMAHANDLE_NOMAP) {
 		ion_phys_addr_t iphys;
 
@@ -1755,7 +1771,7 @@
 		if (err)
 			goto bail;
 
-		VERIFY(err, ((me->ctxtable[index]->ctxid == (rsp.ctx & ~1)) &&
+		VERIFY(err, ((me->ctxtable[index]->ctxid == (rsp.ctx & ~3)) &&
 			me->ctxtable[index]->magic == FASTRPC_CTX_MAGIC));
 		if (err)
 			goto bail;
@@ -1951,7 +1967,8 @@
 	VERIFY(err, 0 == (err = fastrpc_channel_open(fl)));
 	if (err)
 		goto bail;
-	if (init->flags == FASTRPC_INIT_ATTACH) {
+	if (init->flags == FASTRPC_INIT_ATTACH ||
+			init->flags == FASTRPC_INIT_ATTACH_SENSORS) {
 		remote_arg_t ra[1];
 		int tgid = fl->tgid;
 
@@ -1963,7 +1980,12 @@
 		ioctl.fds = NULL;
 		ioctl.attrs = NULL;
 		ioctl.crc = NULL;
-		fl->pd = 0;
+		if (init->flags == FASTRPC_INIT_ATTACH)
+			fl->pd = 0;
+		else if (init->flags == FASTRPC_INIT_ATTACH_SENSORS) {
+			fl->spdname = SENSORS_PDR_SERVICE_LOCATION_CLIENT_NAME;
+			fl->pd = 2;
+		}
 		VERIFY(err, !(err = fastrpc_internal_invoke(fl,
 			FASTRPC_MODE_PARALLEL, 1, &ioctl)));
 		if (err)
@@ -2073,6 +2095,7 @@
 		if (err)
 			goto bail;
 
+		fl->pd = 1;
 		inbuf.pgid = current->tgid;
 		inbuf.namelen = init->filelen;
 		inbuf.pageslen = 0;
@@ -2536,15 +2559,17 @@
 static void fastrpc_context_list_dtor(struct fastrpc_file *fl);
 
 static int fastrpc_session_alloc_locked(struct fastrpc_channel_ctx *chan,
-			int secure, struct fastrpc_session_ctx **session)
+	int secure, int sharedcb, struct fastrpc_session_ctx **session)
 {
 	struct fastrpc_apps *me = &gfa;
 	int idx = 0, err = 0;
 
 	if (chan->sesscount) {
 		for (idx = 0; idx < chan->sesscount; ++idx) {
-			if (!chan->session[idx].used &&
-				chan->session[idx].smmu.secure == secure) {
+			if ((sharedcb && chan->session[idx].smmu.sharedcb) ||
+					(!chan->session[idx].used &&
+					chan->session[idx].smmu.secure
+					== secure && !sharedcb)) {
 				chan->session[idx].used = 1;
 				break;
 			}
@@ -2600,7 +2625,7 @@
 	if (err)
 		goto bail;
 
-	VERIFY(err, ((me->ctxtable[index]->ctxid == (rsp->ctx & ~1)) &&
+	VERIFY(err, ((me->ctxtable[index]->ctxid == (rsp->ctx & ~3)) &&
 		me->ctxtable[index]->magic == FASTRPC_CTX_MAGIC));
 	if (err)
 		goto bail;
@@ -2645,7 +2670,7 @@
 
 	mutex_lock(&me->smd_mutex);
 	if (!*session)
-		err = fastrpc_session_alloc_locked(chan, secure, session);
+		err = fastrpc_session_alloc_locked(chan, secure, 0, session);
 	mutex_unlock(&me->smd_mutex);
 	return err;
 }
@@ -2663,7 +2688,7 @@
 static int fastrpc_file_free(struct fastrpc_file *fl)
 {
 	struct hlist_node *n = NULL;
-	struct fastrpc_mmap *map = NULL;
+	struct fastrpc_mmap *map = NULL, *lmap = NULL;
 	struct fastrpc_perf *perf = NULL, *fperf = NULL;
 	int cid;
 
@@ -2687,9 +2712,15 @@
 	fastrpc_context_list_dtor(fl);
 	fastrpc_buf_list_free(fl);
 	mutex_lock(&fl->fl_map_mutex);
-	hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
-		fastrpc_mmap_free(map, 1);
-	}
+	do {
+		lmap = NULL;
+		hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
+			hlist_del_init(&map->hn);
+			lmap = map;
+			break;
+		}
+		fastrpc_mmap_free(lmap, 1);
+	} while (lmap);
 	mutex_unlock(&fl->fl_map_mutex);
 	if (fl->refcount && (fl->ssrcount == fl->apps->channel[cid].ssrcount))
 		kref_put_mutex(&fl->apps->channel[cid].kref,
@@ -3085,7 +3116,7 @@
 		fl->cid = cid;
 		fl->ssrcount = fl->apps->channel[cid].ssrcount;
 		VERIFY(err, !fastrpc_session_alloc_locked(
-				&fl->apps->channel[cid], 0, &fl->sctx));
+			&fl->apps->channel[cid], 0, fl->sharedcb, &fl->sctx));
 		if (err)
 			goto bail;
 	}
@@ -3124,6 +3155,9 @@
 		} else
 			pm_qos_update_request(&fl->pm_qos_req, latency);
 		break;
+	case FASTRPC_CONTROL_SMMU:
+		fl->sharedcb = cp->smmu.sharedcb;
+		break;
 	default:
 		err = -ENOTTY;
 		break;
@@ -3364,7 +3398,7 @@
 	return NOTIFY_DONE;
 }
 
-static int fastrpc_audio_pdr_notifier_cb(struct notifier_block *pdrnb,
+static int fastrpc_pdr_notifier_cb(struct notifier_block *pdrnb,
 					unsigned long code,
 					void *data)
 {
@@ -3401,7 +3435,7 @@
 {
 	struct fastrpc_static_pd *spd;
 	struct pd_qmi_client_data *pdr = data;
-	int curr_state = 0;
+	int curr_state = 0, i = 0;
 
 	spd = container_of(nb, struct fastrpc_static_pd, get_service_nb);
 	if (opcode == LOCATOR_DOWN) {
@@ -3409,15 +3443,21 @@
 		return NOTIFY_DONE;
 	}
 
-	if (pdr->total_domains == 1) {
-		spd->pdrhandle = service_notif_register_notifier(
-				pdr->domain_list[0].name,
-				pdr->domain_list[0].instance_id,
+	for (i = 0; i < pdr->total_domains; i++) {
+		if ((!strcmp(pdr->domain_list[i].name,
+					"msm/adsp/audio_pd")) ||
+					(!strcmp(pdr->domain_list[i].name,
+					"msm/adsp/sensor_pd"))) {
+			spd->pdrhandle =
+				service_notif_register_notifier(
+				pdr->domain_list[i].name,
+				pdr->domain_list[i].instance_id,
 				&spd->pdrnb, &curr_state);
-		if (IS_ERR(spd->pdrhandle))
-			pr_err("ADSPRPC: Unable to register notifier\n");
-	} else
-		pr_err("ADSPRPC: Service returned invalid domains\n");
+			if (IS_ERR(spd->pdrhandle))
+				pr_err("ADSPRPC: Unable to register notifier\n");
+			break;
+		}
+	}
 
 	return NOTIFY_DONE;
 }
@@ -3476,6 +3516,8 @@
 	sess->used = 0;
 	sess->smmu.coherent = of_property_read_bool(dev->of_node,
 						"dma-coherent");
+	sess->smmu.sharedcb = of_property_read_bool(dev->of_node,
+						"shared-cb");
 	sess->smmu.secure = of_property_read_bool(dev->of_node,
 						"qcom,secure-context-bank");
 	if (sess->smmu.secure)
@@ -3505,7 +3547,6 @@
 
 static int fastrpc_cb_legacy_probe(struct device *dev)
 {
-	struct fastrpc_apps *me = &gfa;
 	struct fastrpc_channel_ctx *chan;
 	struct fastrpc_session_ctx *first_sess = NULL, *sess = NULL;
 	const char *name;
@@ -3574,7 +3615,6 @@
 		sess->smmu.secure = false;
 		chan->sesscount++;
 	}
-	me->legacy = 1;
 bail:
 	kfree(sids);
 	return err;
@@ -3627,7 +3667,6 @@
 	int err = 0;
 	struct fastrpc_apps *me = &gfa;
 	struct device *dev = &pdev->dev;
-	struct smq_phy_page range;
 	struct device_node *ion_node, *node;
 	struct platform_device *ion_pdev;
 	struct cma *cma;
@@ -3651,6 +3690,7 @@
 	if (of_device_is_compatible(dev->of_node,
 					"qcom,msm-fastrpc-legacy-compute")) {
 		me->glink = false;
+		me->legacy = 1;
 	}
 
 	if (of_device_is_compatible(dev->of_node,
@@ -3661,7 +3701,6 @@
 	if (of_device_is_compatible(dev->of_node,
 					"qcom,msm-adsprpc-mem-region")) {
 		me->dev = dev;
-		range.addr = 0;
 		ion_node = of_find_compatible_node(NULL, NULL, "qcom,msm-ion");
 		if (ion_node) {
 			for_each_available_child_of_node(ion_node, node) {
@@ -3674,13 +3713,14 @@
 					break;
 				cma = dev_get_cma_area(&ion_pdev->dev);
 				if (cma) {
-					range.addr = cma_get_base(cma);
-					range.size = (size_t)cma_get_size(cma);
+					me->range.addr = cma_get_base(cma);
+					me->range.size =
+						(size_t)cma_get_size(cma);
 				}
 				break;
 			}
 		}
-		if (range.addr && !of_property_read_bool(dev->of_node,
+		if (me->range.addr && !of_property_read_bool(dev->of_node,
 							 "restrict-access")) {
 			int srcVM[1] = {VMID_HLOS};
 			int destVM[4] = {VMID_HLOS, VMID_MSS_MSA, VMID_SSC_Q6,
@@ -3691,12 +3731,11 @@
 				PERM_READ | PERM_WRITE | PERM_EXEC,
 				};
 
-			VERIFY(err, !hyp_assign_phys(range.addr, range.size,
-					srcVM, 1, destVM, destVMperm, 4));
+			VERIFY(err, !hyp_assign_phys(me->range.addr,
+					me->range.size, srcVM, 1,
+					destVM, destVMperm, 4));
 			if (err)
 				goto bail;
-			me->range.addr = range.addr;
-			me->range.size = range.size;
 		}
 		return 0;
 	}
@@ -3718,6 +3757,24 @@
 			pr_err("ADSPRPC: Get service location failed: %d\n",
 								ret);
 	}
+	if (of_property_read_bool(dev->of_node,
+					"qcom,fastrpc-adsp-sensors-pdr")) {
+		int session;
+
+		VERIFY(err, !fastrpc_get_adsp_session(
+			SENSORS_PDR_SERVICE_LOCATION_CLIENT_NAME, &session));
+		if (err)
+			goto spdbail;
+		me->channel[0].spd[session].get_service_nb.notifier_call =
+					fastrpc_get_service_location_notify;
+		ret = get_service_location(
+				SENSORS_PDR_SERVICE_LOCATION_CLIENT_NAME,
+				SENSORS_PDR_ADSP_SERVICE_NAME,
+				&me->channel[0].spd[session].get_service_nb);
+		if (ret)
+			pr_err("ADSPRPC: Get service location failed: %d\n",
+								ret);
+	}
 spdbail:
 	err = 0;
 	VERIFY(err, !of_platform_populate(pdev->dev.of_node,
diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c
index 2868dd3..0f07483 100644
--- a/drivers/char/adsprpc_compat.c
+++ b/drivers/char/adsprpc_compat.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -77,13 +77,13 @@
 struct compat_fastrpc_ioctl_mmap {
 	compat_int_t fd;	/* ion fd */
 	compat_uint_t flags;	/* flags for dsp to map with */
-	compat_u64 vaddrin;	/* optional virtual address */
+	compat_uptr_t vaddrin;	/* optional virtual address */
 	compat_size_t size;	/* size */
-	compat_u64 vaddrout;	/* dsps virtual address */
+	compat_uptr_t vaddrout;	/* dsps virtual address */
 };
 
 struct compat_fastrpc_ioctl_munmap {
-	compat_u64 vaddrout;	/* address to unmap */
+	compat_uptr_t vaddrout;	/* address to unmap */
 	compat_size_t size;	/* size */
 };
 
@@ -191,7 +191,7 @@
 	compat_uint_t u;
 	compat_int_t i;
 	compat_size_t s;
-	compat_u64 p;
+	compat_uptr_t p;
 	int err;
 
 	err = get_user(i, &map32->fd);
@@ -199,7 +199,7 @@
 	err |= get_user(u, &map32->flags);
 	err |= put_user(u, &map->flags);
 	err |= get_user(p, &map32->vaddrin);
-	err |= put_user(p, &map->vaddrin);
+	err |= put_user(p, (uintptr_t *)&map->vaddrin);
 	err |= get_user(s, &map32->size);
 	err |= put_user(s, &map->size);
 
@@ -210,7 +210,7 @@
 			struct compat_fastrpc_ioctl_mmap __user *map32,
 			struct fastrpc_ioctl_mmap __user *map)
 {
-	compat_u64 p;
+	compat_uptr_t p;
 	int err;
 
 	err = get_user(p, &map->vaddrout);
@@ -223,7 +223,7 @@
 			struct compat_fastrpc_ioctl_munmap __user *unmap32,
 			struct fastrpc_ioctl_munmap __user *unmap)
 {
-	compat_u64 p;
+	compat_uptr_t p;
 	compat_size_t s;
 	int err;
 
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index 37f3e63..de0dd01 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -66,6 +66,7 @@
 #define FASTRPC_INIT_ATTACH      0
 #define FASTRPC_INIT_CREATE      1
 #define FASTRPC_INIT_CREATE_STATIC  2
+#define FASTRPC_INIT_ATTACH_SENSORS 3
 
 /* Retrives number of input buffers from the scalars parameter */
 #define REMOTE_SCALARS_INBUFS(sc)        (((sc) >> 16) & 0x0ff)
@@ -199,16 +200,16 @@
 };
 
 struct fastrpc_ioctl_munmap {
-	uint64_t vaddrout;	/* address to unmap */
+	uintptr_t vaddrout;	/* address to unmap */
 	size_t size;		/* size */
 };
 
 struct fastrpc_ioctl_mmap {
 	int fd;				/* ion fd */
 	uint32_t flags;			/* flags for dsp to map with */
-	uint64_t vaddrin;		/* optional virtual address */
+	uintptr_t vaddrin;		/* optional virtual address */
 	size_t size;			/* size */
-	uint64_t vaddrout;		/* dsps virtual address */
+	uintptr_t vaddrout;		/* dsps virtual address */
 };
 
 struct fastrpc_ioctl_munmap_fd {
@@ -229,11 +230,15 @@
 	uint32_t enable;	//!latency control enable
 	uint32_t level;		//!level of control
 };
-
+#define FASTRPC_CONTROL_SMMU   (2)
+struct fastrpc_ctrl_smmu {
+	uint32_t sharedcb;
+};
 struct fastrpc_ioctl_control {
 	uint32_t req;
 	union {
 		struct fastrpc_ctrl_latency lp;
+		struct fastrpc_ctrl_smmu smmu;
 	};
 };
 
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index a469eb9..286418f 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -26,6 +26,7 @@
 #include <linux/reboot.h>
 #include <asm/current.h>
 #include <soc/qcom/restart.h>
+#include <linux/vmalloc.h>
 #ifdef CONFIG_DIAG_OVER_USB
 #include <linux/usb/usbdiag.h>
 #endif
@@ -259,7 +260,7 @@
 	switch (type) {
 	case DCI_BUF_PRIMARY:
 		buffer->capacity = IN_BUF_SIZE;
-		buffer->data = kzalloc(buffer->capacity, GFP_KERNEL);
+		buffer->data = vzalloc(buffer->capacity);
 		if (!buffer->data)
 			return -ENOMEM;
 		break;
@@ -269,7 +270,7 @@
 		break;
 	case DCI_BUF_CMD:
 		buffer->capacity = DIAG_MAX_REQ_SIZE + DCI_BUF_SIZE;
-		buffer->data = kzalloc(buffer->capacity, GFP_KERNEL);
+		buffer->data = vzalloc(buffer->capacity);
 		if (!buffer->data)
 			return -ENOMEM;
 		break;
@@ -687,7 +688,7 @@
 	byte_mask = 0x01 << (item_num % 8);
 	offset = equip_id * 514;
 
-	if (offset + byte_index > DCI_LOG_MASK_SIZE) {
+	if (offset + byte_index >= DCI_LOG_MASK_SIZE) {
 		pr_err("diag: In %s, invalid offset: %d, log_code: %d, byte_index: %d\n",
 				__func__, offset, log_code, byte_index);
 		return 0;
@@ -714,7 +715,7 @@
 	bit_index = event_id % 8;
 	byte_mask = 0x1 << bit_index;
 
-	if (byte_index > DCI_EVENT_MASK_SIZE) {
+	if (byte_index >= DCI_EVENT_MASK_SIZE) {
 		pr_err("diag: In %s, invalid, event_id: %d, byte_index: %d\n",
 				__func__, event_id, byte_index);
 		return 0;
@@ -2726,7 +2727,7 @@
 		create_dci_event_mask_tbl(temp->event_mask_composite);
 	}
 
-	partial_pkt.data = kzalloc(MAX_DCI_PACKET_SZ, GFP_KERNEL);
+	partial_pkt.data = vzalloc(MAX_DCI_PACKET_SZ);
 	if (!partial_pkt.data)
 		return -ENOMEM;
 
@@ -2780,7 +2781,7 @@
 		goto err;
 
 	if (driver->apps_dci_buf == NULL) {
-		driver->apps_dci_buf = kzalloc(DCI_BUF_SIZE, GFP_KERNEL);
+		driver->apps_dci_buf = vzalloc(DCI_BUF_SIZE);
 		if (driver->apps_dci_buf == NULL)
 			goto err;
 	}
@@ -2797,12 +2798,12 @@
 	return DIAG_DCI_NO_ERROR;
 err:
 	pr_err("diag: Could not initialize diag DCI buffers");
-	kfree(driver->apps_dci_buf);
+	vfree(driver->apps_dci_buf);
 	driver->apps_dci_buf = NULL;
 
 	if (driver->diag_dci_wq)
 		destroy_workqueue(driver->diag_dci_wq);
-	kfree(partial_pkt.data);
+	vfree(partial_pkt.data);
 	partial_pkt.data = NULL;
 	mutex_destroy(&driver->dci_mutex);
 	mutex_destroy(&dci_log_mask_mutex);
@@ -2822,9 +2823,9 @@
 
 void diag_dci_exit(void)
 {
-	kfree(partial_pkt.data);
+	vfree(partial_pkt.data);
 	partial_pkt.data = NULL;
-	kfree(driver->apps_dci_buf);
+	vfree(driver->apps_dci_buf);
 	driver->apps_dci_buf = NULL;
 	mutex_destroy(&driver->dci_mutex);
 	mutex_destroy(&dci_log_mask_mutex);
@@ -2962,7 +2963,7 @@
 	new_entry->in_service = 0;
 	INIT_LIST_HEAD(&new_entry->list_write_buf);
 	mutex_init(&new_entry->write_buf_mutex);
-	new_entry->dci_log_mask =  kzalloc(DCI_LOG_MASK_SIZE, GFP_KERNEL);
+	new_entry->dci_log_mask =  vzalloc(DCI_LOG_MASK_SIZE);
 	if (!new_entry->dci_log_mask) {
 		pr_err("diag: Unable to create log mask for client, %d",
 							driver->dci_client_id);
@@ -2970,14 +2971,14 @@
 	}
 	create_dci_log_mask_tbl(new_entry->dci_log_mask, DCI_LOG_MASK_CLEAN);
 
-	new_entry->dci_event_mask =  kzalloc(DCI_EVENT_MASK_SIZE, GFP_KERNEL);
+	new_entry->dci_event_mask =  vzalloc(DCI_EVENT_MASK_SIZE);
 	if (!new_entry->dci_event_mask)
 		goto fail_alloc;
 	create_dci_event_mask_tbl(new_entry->dci_event_mask);
 
 	new_entry->buffers = kzalloc(new_entry->num_buffers *
 				     sizeof(struct diag_dci_buf_peripheral_t),
-				     GFP_KERNEL);
+					GFP_KERNEL);
 	if (!new_entry->buffers) {
 		pr_err("diag: Unable to allocate buffers for peripherals in %s\n",
 								__func__);
@@ -3001,7 +3002,7 @@
 		if (!proc_buf->buf_primary)
 			goto fail_alloc;
 		proc_buf->buf_cmd = kzalloc(sizeof(struct diag_dci_buffer_t),
-					    GFP_KERNEL);
+					GFP_KERNEL);
 		if (!proc_buf->buf_cmd)
 			goto fail_alloc;
 		err = diag_dci_init_buffer(proc_buf->buf_primary,
@@ -3034,7 +3035,7 @@
 			if (proc_buf) {
 				mutex_destroy(&proc_buf->health_mutex);
 				if (proc_buf->buf_primary) {
-					kfree(proc_buf->buf_primary->data);
+					vfree(proc_buf->buf_primary->data);
 					proc_buf->buf_primary->data = NULL;
 					mutex_destroy(
 					   &proc_buf->buf_primary->data_mutex);
@@ -3042,7 +3043,7 @@
 				kfree(proc_buf->buf_primary);
 				proc_buf->buf_primary = NULL;
 				if (proc_buf->buf_cmd) {
-					kfree(proc_buf->buf_cmd->data);
+					vfree(proc_buf->buf_cmd->data);
 					proc_buf->buf_cmd->data = NULL;
 					mutex_destroy(
 					   &proc_buf->buf_cmd->data_mutex);
@@ -3051,9 +3052,9 @@
 				proc_buf->buf_cmd = NULL;
 			}
 		}
-		kfree(new_entry->dci_event_mask);
+		vfree(new_entry->dci_event_mask);
 		new_entry->dci_event_mask = NULL;
-		kfree(new_entry->dci_log_mask);
+		vfree(new_entry->dci_log_mask);
 		new_entry->dci_log_mask = NULL;
 		kfree(new_entry->buffers);
 		new_entry->buffers = NULL;
@@ -3088,7 +3089,7 @@
 	 * Clear the client's log and event masks, update the cumulative
 	 * masks and send the masks to peripherals
 	 */
-	kfree(entry->dci_log_mask);
+	vfree(entry->dci_log_mask);
 	entry->dci_log_mask = NULL;
 	diag_dci_invalidate_cumulative_log_mask(token);
 	if (token == DCI_LOCAL_PROC)
@@ -3096,7 +3097,7 @@
 	ret = dci_ops_tbl[token].send_log_mask(token);
 	if (ret != DIAG_DCI_NO_ERROR)
 		return ret;
-	kfree(entry->dci_event_mask);
+	vfree(entry->dci_event_mask);
 	entry->dci_event_mask = NULL;
 	diag_dci_invalidate_cumulative_event_mask(token);
 	if (token == DCI_LOCAL_PROC)
@@ -3159,12 +3160,12 @@
 		}
 
 		mutex_lock(&proc_buf->buf_primary->data_mutex);
-		kfree(proc_buf->buf_primary->data);
+		vfree(proc_buf->buf_primary->data);
 		proc_buf->buf_primary->data = NULL;
 		mutex_unlock(&proc_buf->buf_primary->data_mutex);
 
 		mutex_lock(&proc_buf->buf_cmd->data_mutex);
-		kfree(proc_buf->buf_cmd->data);
+		vfree(proc_buf->buf_cmd->data);
 		proc_buf->buf_cmd->data = NULL;
 		mutex_unlock(&proc_buf->buf_cmd->data_mutex);
 
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 223bc03..b7d56a9 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -27,9 +27,6 @@
 
 #define DIAG_SET_FEATURE_MASK(x) (feature_bytes[(x)/8] |= (1 << (x & 0x7)))
 
-#define diag_check_update(x)	\
-	(!info || (info && (info->peripheral_mask & MD_PERIPHERAL_MASK(x)))) \
-
 struct diag_mask_info msg_mask;
 struct diag_mask_info msg_bt_mask;
 struct diag_mask_info log_mask;
@@ -64,6 +61,20 @@
 	{ .ssid_first = MSG_SSID_25, .ssid_last = MSG_SSID_25_LAST }
 };
 
+static int diag_check_update(int md_peripheral, int pid)
+{
+	int ret;
+	struct diag_md_session_t *info = NULL;
+
+	mutex_lock(&driver->md_session_lock);
+	info = diag_md_session_get_pid(pid);
+	ret = (!info || (info &&
+		(info->peripheral_mask & MD_PERIPHERAL_MASK(md_peripheral))));
+	mutex_unlock(&driver->md_session_lock);
+
+	return ret;
+}
+
 static int diag_apps_responds(void)
 {
 	/*
@@ -825,7 +836,7 @@
 	mutex_unlock(&driver->msg_mask_lock);
 	mutex_unlock(&mask_info->lock);
 	mutex_unlock(&driver->md_session_lock);
-	if (diag_check_update(APPS_DATA))
+	if (diag_check_update(APPS_DATA, pid))
 		diag_update_userspace_clients(MSG_MASKS_TYPE);
 
 	/*
@@ -849,7 +860,7 @@
 	for (i = 0; i < NUM_MD_SESSIONS; i++) {
 		if (i == APPS_DATA)
 			continue;
-		if (!diag_check_update(i))
+		if (!diag_check_update(i, pid))
 			continue;
 		if (i > NUM_PERIPHERALS)
 			peripheral = diag_search_peripheral_by_pd(i);
@@ -919,7 +930,7 @@
 	mutex_unlock(&driver->msg_mask_lock);
 	mutex_unlock(&mask_info->lock);
 	mutex_unlock(&driver->md_session_lock);
-	if (diag_check_update(APPS_DATA))
+	if (diag_check_update(APPS_DATA, pid))
 		diag_update_userspace_clients(MSG_MASKS_TYPE);
 
 	/*
@@ -937,7 +948,7 @@
 	for (i = 0; i < NUM_MD_SESSIONS; i++) {
 		if (i == APPS_DATA)
 			continue;
-		if (!diag_check_update(i))
+		if (!diag_check_update(i, pid))
 			continue;
 		if (i > NUM_PERIPHERALS)
 			peripheral = diag_search_peripheral_by_pd(i);
@@ -1027,7 +1038,7 @@
 	mask_info->status = DIAG_CTRL_MASK_VALID;
 	mutex_unlock(&mask_info->lock);
 	mutex_unlock(&driver->md_session_lock);
-	if (diag_check_update(APPS_DATA))
+	if (diag_check_update(APPS_DATA, pid))
 		diag_update_userspace_clients(EVENT_MASKS_TYPE);
 
 	/*
@@ -1046,7 +1057,7 @@
 	for (i = 0; i < NUM_MD_SESSIONS; i++) {
 		if (i == APPS_DATA)
 			continue;
-		if (!diag_check_update(i))
+		if (!diag_check_update(i, pid))
 			continue;
 		if (i > NUM_PERIPHERALS)
 			peripheral = diag_search_peripheral_by_pd(i);
@@ -1098,7 +1109,7 @@
 	}
 	mutex_unlock(&mask_info->lock);
 	mutex_unlock(&driver->md_session_lock);
-	if (diag_check_update(APPS_DATA))
+	if (diag_check_update(APPS_DATA, pid))
 		diag_update_userspace_clients(EVENT_MASKS_TYPE);
 
 	/*
@@ -1110,7 +1121,7 @@
 	for (i = 0; i < NUM_MD_SESSIONS; i++) {
 		if (i == APPS_DATA)
 			continue;
-		if (!diag_check_update(i))
+		if (!diag_check_update(i, pid))
 			continue;
 		if (i > NUM_PERIPHERALS)
 			peripheral = diag_search_peripheral_by_pd(i);
@@ -1373,7 +1384,7 @@
 	}
 	mutex_unlock(&mask_info->lock);
 	mutex_unlock(&driver->md_session_lock);
-	if (diag_check_update(APPS_DATA))
+	if (diag_check_update(APPS_DATA, pid))
 		diag_update_userspace_clients(LOG_MASKS_TYPE);
 
 	/*
@@ -1404,7 +1415,7 @@
 	for (i = 0; i < NUM_MD_SESSIONS; i++) {
 		if (i == APPS_DATA)
 			continue;
-		if (!diag_check_update(i))
+		if (!diag_check_update(i, pid))
 			continue;
 		if (i > NUM_PERIPHERALS)
 			peripheral = diag_search_peripheral_by_pd(i);
@@ -1459,7 +1470,7 @@
 	}
 	mask_info->status = DIAG_CTRL_MASK_ALL_DISABLED;
 	mutex_unlock(&driver->md_session_lock);
-	if (diag_check_update(APPS_DATA))
+	if (diag_check_update(APPS_DATA, pid))
 		diag_update_userspace_clients(LOG_MASKS_TYPE);
 
 	/*
@@ -1477,7 +1488,7 @@
 	for (i = 0; i < NUM_MD_SESSIONS; i++) {
 		if (i == APPS_DATA)
 			continue;
-		if (!diag_check_update(i))
+		if (!diag_check_update(i, pid))
 			continue;
 		if (i > NUM_PERIPHERALS)
 			peripheral = diag_search_peripheral_by_pd(i);
@@ -2042,14 +2053,6 @@
 			__func__, mask_info->ptr, mask_info->update_buf);
 		return -EINVAL;
 	}
-	mutex_lock(&driver->diag_maskclear_mutex);
-	if (driver->mask_clear) {
-		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
-		"diag:%s: count = %zu\n", __func__, count);
-		mutex_unlock(&driver->diag_maskclear_mutex);
-		return -EIO;
-	}
-	mutex_unlock(&driver->diag_maskclear_mutex);
 	mutex_lock(&mask_info->lock);
 	mutex_lock(&driver->msg_mask_lock);
 
diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c
index ae2e00d..24a9f8a 100644
--- a/drivers/char/diag/diag_usb.c
+++ b/drivers/char/diag/diag_usb.c
@@ -139,8 +139,11 @@
 			 * Remove reference from the table if it is the
 			 * only instance of the buffer
 			 */
-			if (atomic_read(&entry->ref_count) == 0)
+			if (atomic_read(&entry->ref_count) == 0) {
 				list_del(&entry->track);
+				kfree(entry);
+				entry = NULL;
+			}
 			break;
 		}
 	}
@@ -332,6 +335,7 @@
 	buf = entry->buf;
 	len = entry->len;
 	kfree(entry);
+	entry = NULL;
 	diag_ws_on_copy_complete(DIAG_WS_MUX);
 
 	if (ch->ops && ch->ops->write_done)
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 9988291..fc18776 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -543,8 +543,6 @@
 	struct class *diagchar_class;
 	struct device *diag_dev;
 	int ref_count;
-	int mask_clear;
-	struct mutex diag_maskclear_mutex;
 	struct mutex diag_notifier_mutex;
 	struct mutex diagchar_mutex;
 	struct mutex diag_file_mutex;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index d4bae2e..0d3389a 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -459,10 +459,6 @@
 	if (diag_mask_clear_param)
 		diag_clear_masks(pid);
 
-	mutex_lock(&driver->diag_maskclear_mutex);
-	driver->mask_clear = 1;
-	mutex_unlock(&driver->diag_maskclear_mutex);
-
 	mutex_lock(&driver->diagchar_mutex);
 	p_mask =
 	diag_translate_kernel_to_user_mask(session_mask);
@@ -559,9 +555,7 @@
 	DIAG_LOG(DIAG_DEBUG_USERSPACE, "diag: process exit %s\n",
 		current->comm);
 	ret = diag_remove_client_entry(file);
-	mutex_lock(&driver->diag_maskclear_mutex);
-	driver->mask_clear = 0;
-	mutex_unlock(&driver->diag_maskclear_mutex);
+
 	return ret;
 }
 
@@ -1673,11 +1667,56 @@
 	return ret;
 }
 
+static void diag_switch_logging_clear_mask(
+		struct diag_logging_mode_param_t *param, int pid)
+{
+	int new_mode;
+	struct diag_md_session_t *session_info = NULL;
+
+	mutex_lock(&driver->md_session_lock);
+	session_info = diag_md_session_get_pid(pid);
+	if (!session_info) {
+		DIAG_LOG(DIAG_DEBUG_USERSPACE, "Invalid pid: %d\n", pid);
+		mutex_unlock(&driver->md_session_lock);
+		return;
+	}
+	mutex_unlock(&driver->md_session_lock);
+
+	if (!param)
+		return;
+
+	if (!param->peripheral_mask) {
+		DIAG_LOG(DIAG_DEBUG_USERSPACE,
+			"asking for mode switch with no peripheral mask set\n");
+		return;
+	}
+
+	switch (param->req_mode) {
+	case CALLBACK_MODE:
+	case UART_MODE:
+	case SOCKET_MODE:
+	case MEMORY_DEVICE_MODE:
+		new_mode = DIAG_MEMORY_DEVICE_MODE;
+		break;
+	case USB_MODE:
+		new_mode = DIAG_USB_MODE;
+		break;
+	default:
+		DIAG_LOG(DIAG_DEBUG_USERSPACE,
+			"Request to switch to invalid mode: %d\n",
+			param->req_mode);
+		return;
+	}
+	if ((new_mode == DIAG_USB_MODE) && diag_mask_clear_param)
+		diag_clear_masks(pid);
+
+}
+
 static int diag_switch_logging(struct diag_logging_mode_param_t *param)
 {
 	int new_mode, i = 0;
-	int curr_mode, err = 0;
-	uint8_t do_switch = 1, peripheral = 0;
+	int curr_mode, err = 0, peripheral = 0;
+	uint8_t do_switch = 1;
 	uint32_t peripheral_mask = 0, pd_mask = 0;
 
 	if (!param)
@@ -1691,6 +1730,10 @@
 
 	if (param->pd_mask) {
 		pd_mask = diag_translate_mask(param->pd_mask);
+		param->diag_id = 0;
+		param->pd_val = 0;
+		param->peripheral = -EINVAL;
+
 		for (i = UPD_WLAN; i < NUM_MD_SESSIONS; i++) {
 			if (pd_mask & (1 << i)) {
 				if (diag_search_diagid_by_pd(i, &param->diag_id,
@@ -1700,6 +1743,12 @@
 				}
 			}
 		}
+
+		DIAG_LOG(DIAG_DEBUG_USERSPACE,
+			"diag: pd_mask = %d, diag_id = %d, peripheral = %d, pd_val = %d\n",
+			param->pd_mask, param->diag_id,
+			param->peripheral, param->pd_val);
+
 		if (!param->diag_id ||
 			(param->pd_val < UPD_WLAN) ||
 			(param->pd_val >= NUM_MD_SESSIONS)) {
@@ -1709,22 +1758,26 @@
 			return -EINVAL;
 		}
 
-		DIAG_LOG(DIAG_DEBUG_USERSPACE,
-			"diag: pd_mask = %d, diag_id = %d, peripheral = %d, pd_val = %d\n",
-			param->pd_mask, param->diag_id,
-			param->peripheral, param->pd_val);
-
 		peripheral = param->peripheral;
+		if ((peripheral < PERIPHERAL_MODEM) ||
+			(peripheral >= NUM_PERIPHERALS)) {
+			DIAG_LOG(DIAG_DEBUG_USERSPACE,
+			"Invalid peripheral: %d\n", peripheral);
+			return -EINVAL;
+		}
 		i = param->pd_val - UPD_WLAN;
+		mutex_lock(&driver->md_session_lock);
 		if (driver->md_session_map[peripheral] &&
 			(MD_PERIPHERAL_MASK(peripheral) &
 			diag_mux->mux_mask) &&
 			!driver->pd_session_clear[i]) {
 			DIAG_LOG(DIAG_DEBUG_USERSPACE,
 			"diag_fr: User PD is already logging onto active peripheral logging\n");
+			mutex_unlock(&driver->md_session_lock);
 			driver->pd_session_clear[i] = 0;
 			return -EINVAL;
 		}
+		mutex_unlock(&driver->md_session_lock);
 		peripheral_mask =
 			diag_translate_mask(param->pd_mask);
 		param->peripheral_mask = peripheral_mask;
@@ -2500,6 +2553,7 @@
 		if (copy_from_user((void *)&mode_param, (void __user *)ioarg,
 				   sizeof(mode_param)))
 			return -EFAULT;
+		diag_switch_logging_clear_mask(&mode_param, current->tgid);
 		mutex_lock(&driver->diagchar_mutex);
 		result = diag_switch_logging(&mode_param);
 		mutex_unlock(&driver->diagchar_mutex);
@@ -2631,6 +2685,7 @@
 		if (copy_from_user((void *)&mode_param, (void __user *)ioarg,
 				   sizeof(mode_param)))
 			return -EFAULT;
+		diag_switch_logging_clear_mask(&mode_param, current->tgid);
 		mutex_lock(&driver->diagchar_mutex);
 		result = diag_switch_logging(&mode_param);
 		mutex_unlock(&driver->diagchar_mutex);
@@ -3902,7 +3957,6 @@
 	non_hdlc_data.len = 0;
 	mutex_init(&driver->hdlc_disable_mutex);
 	mutex_init(&driver->diagchar_mutex);
-	mutex_init(&driver->diag_maskclear_mutex);
 	mutex_init(&driver->diag_notifier_mutex);
 	mutex_init(&driver->diag_file_mutex);
 	mutex_init(&driver->delayed_rsp_mutex);
diff --git a/drivers/clk/msm/clock-cpu-8939.c b/drivers/clk/msm/clock-cpu-8939.c
index 68ea9a1..5ba6bd0 100644
--- a/drivers/clk/msm/clock-cpu-8939.c
+++ b/drivers/clk/msm/clock-cpu-8939.c
@@ -130,7 +130,16 @@
 
 static long cpu_clk_8939_round_rate(struct clk *c, unsigned long rate)
 {
-	return clk_round_rate(c->parent, rate);
+	int level;
+
+	for (level = 0; level < c->num_fmax; level++)
+		if (rate <= c->fmax[level])
+			break;
+
+	if (level == c->num_fmax)
+		return c->fmax[level-1];
+
+	return c->fmax[level];
 }
 
 static int cpu_clk_8939_set_rate(struct clk *c, unsigned long rate)
@@ -222,6 +231,12 @@
 	CLK_LIST(a53_bc_clk),
 };
 
+static struct clk_lookup cpu_clocks_sdm429[] = {
+	CLK_LIST(a53ssmux_bc),
+	CLK_LIST(a53ssmux_cci),
+	CLK_LIST(a53_bc_clk),
+	CLK_LIST(cci_clk),
+};
 
 static struct mux_div_clk *a53ssmux[] = {&a53ssmux_bc,
 						&a53ssmux_lc, &a53ssmux_cci};
@@ -230,19 +245,31 @@
 
 static struct clk *logical_cpu_to_clk(int cpu)
 {
-	struct device_node *cpu_node = of_get_cpu_node(cpu, NULL);
-	u32 reg;
+	struct device_node *cpu_node;
+	const u32 *cell;
+	u64 hwid;
 
-	/* CPU 0/1/2/3 --> a53_bc_clk and mask = 0x103
-	 * CPU 4/5/6/7 --> a53_lc_clk and mask = 0x3
-	 */
-	if (cpu_node && !of_property_read_u32(cpu_node, "reg", &reg)) {
-		if ((reg | a53_bc_clk.cpu_reg_mask) == a53_bc_clk.cpu_reg_mask)
-			return &a53_lc_clk.c;
-		if ((reg | a53_lc_clk.cpu_reg_mask) == a53_lc_clk.cpu_reg_mask)
-			return &a53_bc_clk.c;
+	cpu_node = of_get_cpu_node(cpu, NULL);
+	if (!cpu_node)
+		goto fail;
+
+	cell = of_get_property(cpu_node, "reg", NULL);
+	if (!cell) {
+		pr_err("%s: missing reg property\n", cpu_node->full_name);
+		goto fail;
 	}
 
+	/*
+	 * CPU 0/1/2/3 --> a53_bc_clk and mask = 0x103
+	 * CPU 4/5/6/7 --> a53_lc_clk and mask = 0x3
+	 */
+	hwid = of_read_number(cell, of_n_addr_cells(cpu_node));
+	if ((hwid | a53_bc_clk.cpu_reg_mask) == a53_bc_clk.cpu_reg_mask)
+		return &a53_lc_clk.c;
+	if ((hwid | a53_lc_clk.cpu_reg_mask) == a53_lc_clk.cpu_reg_mask)
+		return &a53_bc_clk.c;
+
+fail:
 	return NULL;
 }
 
@@ -477,6 +504,11 @@
 	struct dev_pm_opp *oppl;
 	int j = 1;
 
+	if (!cpudev) {
+		pr_warn("clock-cpu: NULL CPU device\n");
+		return -ENODEV;
+	}
+
 	rcu_read_lock();
 	/* Check if the regulator driver has already populated OPP tables */
 	oppl = dev_pm_opp_find_freq_exact(vregdev, 2, true);
@@ -674,6 +706,26 @@
 	return NOTIFY_DONE;
 }
 
+static int clock_sdm429_pm_event(struct notifier_block *this,
+				unsigned long event, void *ptr)
+{
+	switch (event) {
+	case PM_POST_HIBERNATION:
+	case PM_POST_SUSPEND:
+		clk_unprepare(&a53_bc_clk.c);
+		clk_unprepare(&cci_clk.c);
+		break;
+	case PM_HIBERNATION_PREPARE:
+	case PM_SUSPEND_PREPARE:
+		clk_prepare(&a53_bc_clk.c);
+		clk_prepare(&cci_clk.c);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
 static int clock_8939_pm_event_single_cluster(struct notifier_block *this,
 						unsigned long event, void *ptr)
 {
@@ -696,6 +748,10 @@
 	.notifier_call = clock_8939_pm_event,
 };
 
+static struct notifier_block clock_sdm429_pm_notifier = {
+	.notifier_call = clock_sdm429_pm_event,
+};
+
 static struct notifier_block clock_8939_pm_notifier_single_cluster = {
 	.notifier_call = clock_8939_pm_event_single_cluster,
 };
@@ -745,10 +801,14 @@
 	char prop_name[] = "qcom,speedX-bin-vX-XXX";
 	int mux_num;
 	bool single_cluster;
+	bool is_sdm429 = false;
 
 	single_cluster = of_property_read_bool(pdev->dev.of_node,
 						"qcom,num-cluster");
 
+	is_sdm429 = of_device_is_compatible(pdev->dev.of_node,
+						"qcom,cpu-clock-sdm429");
+
 	get_speed_bin(pdev, &speed_bin, &version);
 
 	mux_num = single_cluster ? A53SS_MUX_LC:A53SS_MUX_NUM;
@@ -781,11 +841,35 @@
 			dev_info(&pdev->dev, "Safe voltage plan loaded.\n");
 		}
 	}
-	if (single_cluster)
-		rc = of_msm_clock_register(pdev->dev.of_node,
+
+	if (is_sdm429) {
+		rc = cpu_parse_devicetree(pdev, A53SS_MUX_CCI);
+		if (rc)
+			return rc;
+
+		snprintf(prop_name, ARRAY_SIZE(prop_name),
+				"qcom,speed%d-bin-v%d-%s",
+				speed_bin, version, mux_names[A53SS_MUX_CCI]);
+
+		rc = of_get_fmax_vdd_class(pdev, &cpuclk[A53SS_MUX_CCI]->c,
+								prop_name);
+		if (rc) {
+			dev_err(&pdev->dev, "Unable to load voltage plan %s!\n",
+								prop_name);
+			return rc;
+		}
+	}
+
+	if (single_cluster) {
+		if (is_sdm429)
+			rc = of_msm_clock_register(pdev->dev.of_node,
+					cpu_clocks_sdm429,
+					ARRAY_SIZE(cpu_clocks_sdm429));
+		else
+			rc = of_msm_clock_register(pdev->dev.of_node,
 				cpu_clocks_8939_single_cluster,
 				ARRAY_SIZE(cpu_clocks_8939_single_cluster));
-	else
+	} else
 		rc = of_msm_clock_register(pdev->dev.of_node,
 				cpu_clocks_8939, ARRAY_SIZE(cpu_clocks_8939));
 
@@ -794,7 +878,7 @@
 		return rc;
 	}
 
-	if (!single_cluster) {
+	if (!single_cluster || is_sdm429) {
 		rate = clk_get_rate(&cci_clk.c);
 		clk_set_rate(&cci_clk.c, rate);
 	}
@@ -815,7 +899,7 @@
 	for_each_online_cpu(cpu) {
 		WARN(clk_prepare_enable(&cpuclk[cpu/4]->c),
 				"Unable to turn on CPU clock");
-		if (!single_cluster)
+		if (!single_cluster || is_sdm429)
 			clk_prepare_enable(&cci_clk.c);
 	}
 	put_online_cpus();
@@ -830,9 +914,13 @@
 	a53_lc_clk.hw_low_power_ctrl = true;
 	a53_bc_clk.hw_low_power_ctrl = true;
 
-	if (single_cluster)
-		register_pm_notifier(&clock_8939_pm_notifier_single_cluster);
-	else
+	if (single_cluster) {
+		if (is_sdm429)
+			register_pm_notifier(&clock_sdm429_pm_notifier);
+		else
+			register_pm_notifier(
+				&clock_8939_pm_notifier_single_cluster);
+	} else
 		register_pm_notifier(&clock_8939_pm_notifier);
 
 	populate_opp_table(pdev, single_cluster);
@@ -846,6 +934,8 @@
 static const struct of_device_id clock_a53_match_table[] = {
 	{.compatible = "qcom,cpu-clock-8939"},
 	{.compatible = "qcom,cpu-clock-8917"},
+	{.compatible = "qcom,cpu-clock-sdm429"},
+	{.compatible = "qcom,cpu-clock-sdm439"},
 	{}
 };
 
@@ -873,9 +963,16 @@
 
 	if (!ofnode)
 		ofnode = of_find_compatible_node(NULL, NULL,
-					"qcom,cpu-clock-gold");
+					"qcom,cpu-clock-8917");
 
 	if (!ofnode)
+		ofnode = of_find_compatible_node(NULL, NULL,
+					"qcom,cpu-clock-sdm439");
+
+	if (!ofnode)
+		ofnode = of_find_compatible_node(NULL, NULL,
+					"qcom,cpu-clock-sdm429");
+	if (!ofnode)
 		return 0;
 
 	single_cluster = of_property_read_bool(ofnode,
@@ -918,7 +1015,7 @@
 #define SRC_SEL				0x4
 #define SRC_DIV				0x3
 
-static void __init configure_enable_sr2_pll(void __iomem *base)
+static void __init configure_enable_sr2_pll(void __iomem *base, bool is_sdm439)
 {
 	/* Disable Mode */
 	writel_relaxed(0x0, base + C0_PLL_MODE);
@@ -930,7 +1027,11 @@
 
 	/* Configure USER_CTL and CONFIG_CTL value */
 	writel_relaxed(0x0100000f, base + C0_PLL_USER_CTL);
-	writel_relaxed(0x4c015765, base + C0_PLL_CONFIG_CTL);
+
+	if (is_sdm439)
+		writel_relaxed(0x44024665, base + C0_PLL_CONFIG_CTL);
+	else
+		writel_relaxed(0x4c015765, base + C0_PLL_CONFIG_CTL);
 
 	/* Enable PLL now */
 	writel_relaxed(0x2, base + C0_PLL_MODE);
@@ -948,13 +1049,21 @@
 {
 	void __iomem  *base;
 	int regval = 0, count;
+	bool is_sdm439 = false;
 	struct device_node *ofnode = of_find_compatible_node(NULL, NULL,
 							"qcom,cpu-clock-8939");
+
+	if (!ofnode)
+		ofnode = of_find_compatible_node(NULL, NULL,
+						"qcom,cpu-clock-sdm439");
+
 	if (!ofnode)
 		return 0;
 
+	is_sdm439 = of_device_is_compatible(ofnode, "qcom,cpu-clock-sdm439");
+
 	base = ioremap_nocache(APCS_C0_PLL, SZ_32);
-	configure_enable_sr2_pll(base);
+	configure_enable_sr2_pll(base, is_sdm439);
 	iounmap(base);
 
 	base = ioremap_nocache(APCS_ALIAS0_CMD_RCGR, SZ_8);
diff --git a/drivers/clk/msm/clock-cpu-8953.c b/drivers/clk/msm/clock-cpu-8953.c
index c771755..4ba2543 100644
--- a/drivers/clk/msm/clock-cpu-8953.c
+++ b/drivers/clk/msm/clock-cpu-8953.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -466,18 +466,27 @@
 
 static struct clk *logical_cpu_to_clk(int cpu)
 {
-	struct device_node *cpu_node = of_get_cpu_node(cpu, NULL);
-	u32 reg;
+	struct device_node *cpu_node;
+	const u32 *cell;
+	u64 hwid;
 
-	if (cpu_node && !of_property_read_u32(cpu_node, "reg", &reg)) {
-		if ((reg | a53_pwr_clk.cpu_reg_mask) ==
-						a53_pwr_clk.cpu_reg_mask)
-			return &a53_pwr_clk.c;
-		if ((reg | a53_perf_clk.cpu_reg_mask) ==
-						a53_perf_clk.cpu_reg_mask)
-			return &a53_perf_clk.c;
+	cpu_node = of_get_cpu_node(cpu, NULL);
+	if (!cpu_node)
+		goto fail;
+
+	cell = of_get_property(cpu_node, "reg", NULL);
+	if (!cell) {
+		pr_err("%s: missing reg property\n", cpu_node->full_name);
+		goto fail;
 	}
 
+	hwid = of_read_number(cell, of_n_addr_cells(cpu_node));
+	if ((hwid | a53_pwr_clk.cpu_reg_mask) == a53_pwr_clk.cpu_reg_mask)
+		return &a53_pwr_clk.c;
+	if ((hwid | a53_perf_clk.cpu_reg_mask) == a53_perf_clk.cpu_reg_mask)
+		return &a53_perf_clk.c;
+
+fail:
 	return NULL;
 }
 
@@ -490,6 +499,11 @@
 	bool first = true;
 	int j = 1;
 
+	if (!dev) {
+		pr_warn("clock-cpu: NULL CPU device\n");
+		return -ENODEV;
+	}
+
 	while (1) {
 		rate = c->fmax[j++];
 		level = find_vdd_level(c, rate);
diff --git a/drivers/clk/msm/clock-cpu-sdm632.c b/drivers/clk/msm/clock-cpu-sdm632.c
index 357c49c..58a2520 100644
--- a/drivers/clk/msm/clock-cpu-sdm632.c
+++ b/drivers/clk/msm/clock-cpu-sdm632.c
@@ -528,18 +528,28 @@
 
 static struct clk *logical_cpu_to_clk(int cpu)
 {
-	struct device_node *cpu_node = of_get_cpu_node(cpu, NULL);
-	u32 reg;
+	struct device_node *cpu_node;
+	const u32 *cell;
+	u64 hwid;
 
-	if (cpu_node && !of_property_read_u32(cpu_node, "reg", &reg)) {
-		if ((reg | pwr_clk.cpu_reg_mask) ==
-						pwr_clk.cpu_reg_mask)
-			return &pwr_clk.c;
-		if ((reg | perf_clk.cpu_reg_mask) ==
-						perf_clk.cpu_reg_mask)
-			return &perf_clk.c;
+	cpu_node = of_get_cpu_node(cpu, NULL);
+	if (!cpu_node)
+		goto fail;
+
+	cell = of_get_property(cpu_node, "reg", NULL);
+	if (!cell) {
+		pr_err("%s: missing reg property\n", cpu_node->full_name);
+		goto fail;
 	}
 
+	hwid = of_read_number(cell, of_n_addr_cells(cpu_node));
+	if ((hwid | pwr_clk.cpu_reg_mask) == pwr_clk.cpu_reg_mask)
+		return &pwr_clk.c;
+
+	if ((hwid | perf_clk.cpu_reg_mask) == perf_clk.cpu_reg_mask)
+		return &perf_clk.c;
+
+fail:
 	return NULL;
 }
 
@@ -676,6 +686,11 @@
 	long ret, uv, corner;
 	int j = 1;
 
+	if (!cpudev) {
+		pr_warn("clock-cpu: NULL CPU device\n");
+		return -ENODEV;
+	}
+
 	while (1) {
 		rate = c->fmax[j++];
 
diff --git a/drivers/clk/msm/clock-gcc-8952.c b/drivers/clk/msm/clock-gcc-8952.c
index 7da217c..6d7727f 100644
--- a/drivers/clk/msm/clock-gcc-8952.c
+++ b/drivers/clk/msm/clock-gcc-8952.c
@@ -202,7 +202,10 @@
 	F_APCS_PLL( 921600000,  48, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL( 998400000,  52, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL(1094400000,  57, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL(1171200000,  61, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL(1209600000,  63, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL(1305600000,  68, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL(1459200000,  76, 0x0, 0x1, 0x0, 0x0, 0x0),
 };
 
 static struct pll_clk a53ss_c0_pll = {
@@ -257,6 +260,7 @@
 	F_APCS_PLL(1209600000, 63, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL(1248000000, 65, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL(1267200000, 66, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL(1305600000, 68, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL(1344000000, 70, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL(1401000000, 73, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL(1420800000, 74, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -266,6 +270,9 @@
 	F_APCS_PLL(1516800000, 79, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL(1536000000, 80, 0x0, 0x1, 0x0, 0x0, 0x0),
 	F_APCS_PLL(1651200000, 86, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL(1708800000, 89, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL(1804800000, 94, 0x0, 0x1, 0x0, 0x0, 0x0),
+	F_APCS_PLL(1958400000, 102, 0x0, 0x1, 0x0, 0x0, 0x0),
 };
 
 static struct pll_clk a53ss_c1_pll = {
@@ -754,6 +761,29 @@
 	F_END
 };
 
+static struct clk_freq_tbl ftbl_gcc_oxili_gfx3d_clk_sdm439[] = {
+	F_SLEW( 19200000,  FIXED_CLK_SRC, xo,		1,	0,	0),
+	F_SLEW( 50000000,  FIXED_CLK_SRC, gpll0,	16,	0,	0),
+	F_SLEW( 80000000,  FIXED_CLK_SRC, gpll0,	10,	0,	0),
+	F_SLEW( 100000000, FIXED_CLK_SRC, gpll0,	8,	0,	0),
+	F_SLEW( 160000000, FIXED_CLK_SRC, gpll0,	5,	0,	0),
+	F_SLEW( 200000000, FIXED_CLK_SRC, gpll0,	4,	0,	0),
+	F_SLEW( 216000000, FIXED_CLK_SRC, gpll6_aux,	5,	0,	0),
+	F_SLEW( 228570000, FIXED_CLK_SRC, gpll0,	3.5,	0,	0),
+	F_SLEW( 240000000, FIXED_CLK_SRC, gpll6_aux,	4.5,	0,	0),
+	F_SLEW( 259200000, 1296000000,	  gpll3,	2.5,	0,	0),
+	F_SLEW( 266670000, FIXED_CLK_SRC, gpll0,	3,	0,	0),
+	F_SLEW( 320000000, FIXED_CLK_SRC, gpll0,	2.5,	0,	0),
+	F_SLEW( 355200000, 710400000,	  gpll3,	1,	0,	0),
+	F_SLEW( 375000000, 750000000,	  gpll3,	1,	0,	0),
+	F_SLEW( 400000000, FIXED_CLK_SRC, gpll0,	2,	0,	0),
+	F_SLEW( 450000000, 900000000,	  gpll3,	1,	0,	0),
+	F_SLEW( 510000000, 1020000000,	  gpll3,	1,	0,	0),
+	F_SLEW( 560000000, 1120000000,	  gpll3,	1,	0,	0),
+	F_SLEW( 650000000, 1300000000,	  gpll3,	1,	0,	0),
+	F_END
+};
+
 static struct clk_freq_tbl ftbl_gcc_oxili_gfx3d_clk_8937_475MHz[] = {
 	F_SLEW( 19200000,  FIXED_CLK_SRC, xo,		1,	0,	0),
 	F_SLEW( 50000000,  FIXED_CLK_SRC, gpll0,	16,	0,	0),
@@ -4046,6 +4076,26 @@
 	CLK_LIST(gcc_oxili_timer_clk),
 };
 
+static struct clk_lookup msm_clocks_lookup_sdm429[] = {
+	CLK_LIST(gpll0_clk_src_8937),
+	CLK_LIST(gpll0_ao_clk_src_8937),
+	CLK_LIST(gpll0_sleep_clk_src),
+	CLK_LIST(esc1_clk_src),
+	CLK_LIST(gcc_mdss_esc1_clk),
+	CLK_LIST(gcc_dcc_clk),
+	CLK_LIST(gcc_oxili_aon_clk),
+	CLK_LIST(gcc_qdss_dap_clk),
+	CLK_LIST(blsp1_qup1_i2c_apps_clk_src),
+	CLK_LIST(blsp1_qup1_spi_apps_clk_src),
+	CLK_LIST(gcc_blsp1_qup1_i2c_apps_clk),
+	CLK_LIST(gcc_blsp1_qup1_spi_apps_clk),
+	CLK_LIST(blsp2_qup4_i2c_apps_clk_src),
+	CLK_LIST(blsp2_qup4_spi_apps_clk_src),
+	CLK_LIST(gcc_blsp2_qup4_i2c_apps_clk),
+	CLK_LIST(gcc_blsp2_qup4_spi_apps_clk),
+	CLK_LIST(gcc_oxili_timer_clk),
+};
+
 static struct clk_lookup msm_clocks_lookup_8917[] = {
 	CLK_LIST(gpll0_clk_src_8937),
 	CLK_LIST(gpll0_ao_clk_src_8937),
@@ -4329,6 +4379,8 @@
 	bool compat_bin2 = false;
 	bool compat_bin3 = false;
 	bool compat_bin4 = false;
+	bool compat_bin5 = false;
+	bool compat_bin6 = false;
 
 	compat_bin = of_device_is_compatible(pdev->dev.of_node,
 						"qcom,gcc-8937");
@@ -4342,11 +4394,17 @@
 	compat_bin4 = of_device_is_compatible(pdev->dev.of_node,
 						"qcom,gcc-8920");
 
+	compat_bin5 = of_device_is_compatible(pdev->dev.of_node,
+						"qcom,gcc-sdm429");
+
+	compat_bin6 = of_device_is_compatible(pdev->dev.of_node,
+						"qcom,gcc-sdm439");
+
 	ret = vote_bimc(&bimc_clk, INT_MAX);
 	if (ret < 0)
 		return ret;
 
-	if (compat_bin2 || compat_bin4)
+	if (compat_bin2 || compat_bin4 || compat_bin5)
 		nbases = APCS_C0_PLL_BASE;
 
 	ret = get_mmio_addr(pdev, nbases);
@@ -4374,7 +4432,7 @@
 		return PTR_ERR(vdd_dig.regulator[0]);
 	}
 
-	if (!compat_bin2 && !compat_bin4) {
+	if (!compat_bin2 && !compat_bin4 && !compat_bin5) {
 		vdd_sr2_pll.regulator[0] = devm_regulator_get(&pdev->dev,
 							"vdd_sr2_pll");
 		if (IS_ERR(vdd_sr2_pll.regulator[0])) {
@@ -4417,16 +4475,43 @@
 	regval |= BIT(0);
 	writel_relaxed(regval, GCC_REG_BASE(APCS_GPLL_ENA_VOTE));
 
-	if (compat_bin || compat_bin3) {
+	if (compat_bin || compat_bin3 || compat_bin5 || compat_bin6) {
 		gpll0_clk_src.c.parent = &gpll0_clk_src_8937.c;
 		gpll0_ao_clk_src.c.parent = &gpll0_ao_clk_src_8937.c;
 		/* Oxili Ocmem in GX rail: OXILI_GMEM_CLAMP_IO */
 		regval = readl_relaxed(GCC_REG_BASE(GX_DOMAIN_MISC));
 		regval &= ~BIT(0);
 		writel_relaxed(regval, GCC_REG_BASE(GX_DOMAIN_MISC));
-		get_speed_bin(pdev, &speed_bin);
+
+		if (compat_bin5 || compat_bin6)
+			speed_bin = 0;
+		else
+			get_speed_bin(pdev, &speed_bin);
+
 		override_for_8937(speed_bin);
 
+		if (compat_bin5 || compat_bin6) {
+			vdd_dig.num_levels = VDD_DIG_NUM_439;
+			vdd_dig.cur_level = VDD_DIG_NUM_439;
+			vdd_sr2_pll.num_levels = VDD_SR2_PLL_NUM_439;
+			vdd_sr2_pll.cur_level = VDD_SR2_PLL_NUM_439;
+			vdd_hf_pll.num_levels = VDD_HF_PLL_NUM_439;
+			vdd_hf_pll.cur_level = VDD_HF_PLL_NUM_439;
+
+			gpll3_clk_src.vco_tbl = p_vco;
+			gpll3_clk_src.num_vco = ARRAY_SIZE(p_vco);
+			gpll3_clk_src.c.fmax[VDD_DIG_LOW] = 800000000;
+			gpll3_clk_src.c.fmax[VDD_DIG_NOMINAL] = 1400000000;
+			gfx3d_clk_src.freq_tbl =
+					ftbl_gcc_oxili_gfx3d_clk_sdm439;
+
+			gfx3d_clk_src.c.fmax[VDD_DIG_LOWER] = 320000000;
+			gfx3d_clk_src.c.fmax[VDD_DIG_LOW] = 400000000;
+			gfx3d_clk_src.c.fmax[VDD_DIG_NOMINAL] = 510000000;
+			gfx3d_clk_src.c.fmax[VDD_DIG_NOM_PLUS] = 560000000;
+			gfx3d_clk_src.c.fmax[VDD_DIG_HIGH] = 650000000;
+		}
+
 		if (compat_bin3) {
 			if (speed_bin) {
 				gfx3d_clk_src.freq_tbl =
@@ -4475,7 +4560,7 @@
 	if (ret)
 		return ret;
 
-	if (compat_bin)
+	if (compat_bin || compat_bin6)
 		ret = of_msm_clock_register(pdev->dev.of_node,
 					msm_clocks_lookup_8937,
 					ARRAY_SIZE(msm_clocks_lookup_8937));
@@ -4491,6 +4576,10 @@
 		ret = of_msm_clock_register(pdev->dev.of_node,
 					msm_clocks_lookup_8920,
 					ARRAY_SIZE(msm_clocks_lookup_8920));
+	else if (compat_bin5)
+		ret = of_msm_clock_register(pdev->dev.of_node,
+					msm_clocks_lookup_sdm429,
+					ARRAY_SIZE(msm_clocks_lookup_sdm429));
 	else
 		ret = of_msm_clock_register(pdev->dev.of_node,
 					msm_clocks_lookup_8952,
@@ -4512,15 +4601,8 @@
 	clk_prepare_enable(&pnoc_keepalive_a_clk.c);
 
 	clk_prepare_enable(&xo_a_clk_src.c);
-	clk_prepare_enable(&gcc_blsp1_ahb_clk.c);
-	clk_prepare_enable(&gcc_blsp2_ahb_clk.c);
-	clk_prepare_enable(&gcc_blsp1_uart2_apps_clk.c);
-	clk_prepare_enable(&gcc_blsp1_uart1_apps_clk.c);
-	clk_prepare_enable(&gcc_bimc_gpu_clk.c);
-	clk_prepare_enable(&sysmmnoc_msmbus_a_clk.c);
-	clk_prepare_enable(&sysmmnoc_a_clk.c);
 
-	if (!compat_bin && !compat_bin3) {
+	if (!compat_bin && !compat_bin3 && !compat_bin5 && !compat_bin6) {
 		/* Configure Sleep and Wakeup cycles for GMEM clock */
 		regval = readl_relaxed(GCC_REG_BASE(OXILI_GMEM_CBCR));
 		regval ^= 0xFF0;
@@ -4553,6 +4635,8 @@
 	{ .compatible = "qcom,gcc-8917" },
 	{ .compatible = "qcom,gcc-8940" },
 	{ .compatible = "qcom,gcc-8920" },
+	{ .compatible = "qcom,gcc-sdm439" },
+	{ .compatible = "qcom,gcc-sdm429" },
 	{}
 };
 
@@ -4772,6 +4856,14 @@
 		compat_bin = of_device_is_compatible(pdev->dev.of_node,
 				"qcom,gcc-mdss-8940");
 
+	if (!compat_bin)
+		compat_bin = of_device_is_compatible(pdev->dev.of_node,
+				"qcom,gcc-mdss-sdm439");
+
+	if (!compat_bin)
+		compat_bin = of_device_is_compatible(pdev->dev.of_node,
+				"qcom,gcc-mdss-sdm429");
+
 	curr_p = ext_pclk0_clk_src.c.parent = devm_clk_get(&pdev->dev,
 								"pclk0_src");
 	if (IS_ERR(curr_p)) {
@@ -4846,6 +4938,8 @@
 	{ .compatible = "qcom,gcc-mdss-8917" },
 	{ .compatible = "qcom,gcc-mdss-8940" },
 	{ .compatible = "qcom,gcc-mdss-8920" },
+	{ .compatible = "qcom,gcc-mdss-sdm439" },
+	{ .compatible = "qcom,gcc-mdss-sdm429" },
 	{}
 };
 
diff --git a/drivers/clk/msm/mdss/Makefile b/drivers/clk/msm/mdss/Makefile
index 6285714..3b884dc 100644
--- a/drivers/clk/msm/mdss/Makefile
+++ b/drivers/clk/msm/mdss/Makefile
@@ -5,3 +5,5 @@
 obj-$(CONFIG_MSM_MDSS_PLL) += mdss-dsi-pll-8996.o
 obj-$(CONFIG_MSM_MDSS_PLL) += mdss-dsi-pll-8996-util.o
 obj-$(CONFIG_MSM_MDSS_PLL) += mdss-hdmi-pll-8996.o
+obj-$(CONFIG_MSM_MDSS_PLL) += mdss-dsi-pll-12nm.o
+obj-$(CONFIG_MSM_MDSS_PLL) += mdss-dsi-pll-12nm-util.o
diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-12nm-util.c b/drivers/clk/msm/mdss/mdss-dsi-pll-12nm-util.c
new file mode 100644
index 0000000..f2ed36c
--- /dev/null
+++ b/drivers/clk/msm/mdss/mdss-dsi-pll-12nm-util.c
@@ -0,0 +1,820 @@
+/* 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.
+ */
+
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/iopoll.h>
+#include <linux/delay.h>
+#include <linux/clk/msm-clock-generic.h>
+
+#include "mdss-pll.h"
+#include "mdss-dsi-pll.h"
+#include "mdss-dsi-pll-12nm.h"
+
+#define DSI_PLL_POLL_MAX_READS                  15
+#define DSI_PLL_POLL_TIMEOUT_US                 1000
+
+int pixel_div_set_div(struct div_clk *clk, int div)
+{
+	struct mdss_pll_resources *pll = clk->priv;
+	struct dsi_pll_db *pdb;
+
+	pdb = (struct dsi_pll_db *)pll->priv;
+
+	/* Programming during vco_prepare. Keep this value */
+	pdb->param.pixel_divhf = (div - 1);
+
+	pr_debug("ndx=%d div=%d divhf=%d\n",
+			pll->index, div, pdb->param.pixel_divhf);
+
+	return 0;
+}
+
+int pixel_div_get_div(struct div_clk *clk)
+{
+	u32 div;
+	int rc;
+	struct mdss_pll_resources *pll = clk->priv;
+
+	if (is_gdsc_disabled(pll))
+		return 0;
+
+	rc = mdss_pll_resource_enable(pll, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	div = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_SSC9);
+	div &= 0x7f;
+	pr_debug("pixel_div = %d\n", (div+1));
+
+	mdss_pll_resource_enable(pll, false);
+
+	return (div + 1);
+}
+
+int set_post_div_mux_sel(struct mux_clk *clk, int sel)
+{
+	struct mdss_pll_resources *pll = clk->priv;
+	struct dsi_pll_db *pdb;
+
+	pdb = (struct dsi_pll_db *)pll->priv;
+
+	/* Programming during vco_prepare. Keep this value */
+	pdb->param.post_div_mux = sel;
+
+	pr_debug("ndx=%d post_div_mux_sel=%d p_div=%d\n",
+			pll->index, sel, (u32) BIT(sel));
+
+	return 0;
+}
+
+int get_post_div_mux_sel(struct mux_clk *clk)
+{
+	u32 sel = 0;
+	u32 vco_cntrl = 0, cpbias_cntrl = 0;
+	int rc;
+	struct mdss_pll_resources *pll = clk->priv;
+
+	if (is_gdsc_disabled(pll))
+		return 0;
+
+	rc = mdss_pll_resource_enable(pll, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	vco_cntrl = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_PLL_VCO_CTRL);
+	vco_cntrl &= 0x30;
+
+	cpbias_cntrl = MDSS_PLL_REG_R(pll->pll_base,
+		DSIPHY_PLL_CHAR_PUMP_BIAS_CTRL);
+	cpbias_cntrl = ((cpbias_cntrl >> 6) & 0x1);
+
+	if (cpbias_cntrl == 0) {
+		if (vco_cntrl == 0x00)
+			sel = 0;
+		else if (vco_cntrl == 0x10)
+			sel = 2;
+		else if (vco_cntrl == 0x20)
+			sel = 3;
+		else if (vco_cntrl == 0x30)
+			sel = 4;
+	} else if (cpbias_cntrl == 1) {
+		if (vco_cntrl == 0x30)
+			sel = 2;
+		else if (vco_cntrl == 0x00)
+			sel = 5;
+	}
+
+	mdss_pll_resource_enable(pll, false);
+
+	return sel;
+}
+
+int set_gp_mux_sel(struct mux_clk *clk, int sel)
+{
+	struct mdss_pll_resources *pll = clk->priv;
+	struct dsi_pll_db *pdb;
+
+	pdb = (struct dsi_pll_db *)pll->priv;
+
+	/* Programming during vco_prepare. Keep this value */
+	pdb->param.gp_div_mux = sel;
+
+	pr_debug("ndx=%d gp_div_mux_sel=%d gp_cntrl=%d\n",
+			pll->index, sel, (u32) BIT(sel));
+
+	return 0;
+}
+
+int get_gp_mux_sel(struct mux_clk *clk)
+{
+	u32 sel = 0;
+	int rc;
+	struct mdss_pll_resources *pll = clk->priv;
+
+	if (is_gdsc_disabled(pll))
+		return 0;
+
+	rc = mdss_pll_resource_enable(pll, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll resources\n");
+		return rc;
+	}
+
+	sel = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_PLL_CTRL);
+	sel = (sel >> 5) & 0x7;
+	pr_debug("gp_cntrl = %d\n", sel);
+
+	mdss_pll_resource_enable(pll, false);
+
+	return sel;
+}
+
+static bool pll_is_pll_locked_12nm(struct mdss_pll_resources *pll)
+{
+	u32 status;
+	bool pll_locked;
+
+	/* poll for PLL ready status */
+	if (readl_poll_timeout_atomic((pll->pll_base +
+			DSIPHY_STAT0),
+			status,
+			((status & BIT(1)) > 0),
+			DSI_PLL_POLL_MAX_READS,
+			DSI_PLL_POLL_TIMEOUT_US)) {
+		pr_err("DSI PLL ndx=%d status=%x failed to Lock\n",
+			pll->index, status);
+		pll_locked = false;
+	} else {
+		pll_locked = true;
+	}
+
+	return pll_locked;
+}
+
+int dsi_pll_enable_seq_12nm(struct mdss_pll_resources *pll)
+{
+	int rc = 0;
+	struct dsi_pll_db *pdb;
+	void __iomem *pll_base;
+
+	if (!pll) {
+		pr_err("Invalid PLL resources\n");
+		return -EINVAL;
+	}
+
+	pdb = (struct dsi_pll_db *)pll->priv;
+	if (!pdb) {
+		pr_err("No priv found\n");
+		return -EINVAL;
+	}
+
+	pll_base = pll->pll_base;
+
+	MDSS_PLL_REG_W(pll_base, DSIPHY_SYS_CTRL, 0x49);
+	wmb(); /* make sure register committed before enabling branch clocks */
+	udelay(5); /* h/w recommended delay */
+	MDSS_PLL_REG_W(pll_base, DSIPHY_SYS_CTRL, 0xc9);
+	wmb(); /* make sure register committed before enabling branch clocks */
+	udelay(50); /* h/w recommended delay */
+
+	if (!pll_is_pll_locked_12nm(pll)) {
+		pr_err("DSI PLL ndx=%d lock failed!\n",
+			pll->index);
+		rc = -EINVAL;
+		goto init_lock_err;
+	}
+
+	pr_debug("DSI PLL ndx:%d Locked!\n", pll->index);
+
+init_lock_err:
+	return rc;
+}
+
+static int dsi_pll_enable(struct clk *c)
+{
+	int i, rc = 0;
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *pll = vco->priv;
+
+	/* Try all enable sequences until one succeeds */
+	for (i = 0; i < vco->pll_en_seq_cnt; i++) {
+		rc = vco->pll_enable_seqs[i](pll);
+		pr_debug("DSI PLL %s after sequence #%d\n",
+			rc ? "unlocked" : "locked", i + 1);
+		if (!rc)
+			break;
+	}
+
+	if (rc)
+		pr_err("ndx=%d DSI PLL failed to lock\n", pll->index);
+	else
+		pll->pll_on = true;
+
+	return rc;
+}
+
+static int dsi_pll_relock(struct mdss_pll_resources *pll)
+{
+	void __iomem *pll_base = pll->pll_base;
+	u32 data = 0;
+	int rc = 0;
+
+	data = MDSS_PLL_REG_R(pll_base, DSIPHY_PLL_POWERUP_CTRL);
+	data &= ~BIT(1); /* remove ONPLL_OVR_EN bit */
+	data |= 0x1; /* set ONPLL_OVN to 0x1 */
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_POWERUP_CTRL, data);
+	ndelay(500); /* h/w recommended delay */
+
+	if (!pll_is_pll_locked_12nm(pll)) {
+		pr_err("DSI PLL ndx=%d lock failed!\n",
+			pll->index);
+		rc = -EINVAL;
+		goto relock_err;
+	}
+	ndelay(50); /* h/w recommended delay */
+
+	data = MDSS_PLL_REG_R(pll_base, DSIPHY_PLL_CTRL);
+	data |= 0x01; /* set CLK_SEL bits to 0x1 */
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CTRL, data);
+	ndelay(500); /* h/w recommended delay */
+	wmb(); /* make sure register committed before enabling branch clocks */
+	pll->pll_on = true;
+relock_err:
+	return rc;
+}
+
+static void dsi_pll_disable(struct clk *c)
+{
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *pll = vco->priv;
+	void __iomem *pll_base = pll->pll_base;
+	u32 data = 0;
+
+	if (!pll->pll_on &&
+		mdss_pll_resource_enable(pll, true)) {
+		pr_err("Failed to enable mdss dsi pll=%d\n", pll->index);
+		return;
+	}
+
+	data = MDSS_PLL_REG_R(pll_base, DSIPHY_SSC0);
+	data &= ~BIT(6); /* disable GP_CLK_EN */
+	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC0, data);
+	ndelay(500); /* h/w recommended delay */
+
+	data = MDSS_PLL_REG_R(pll_base, DSIPHY_PLL_CTRL);
+	data &= ~0x03; /* remove CLK_SEL bits */
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CTRL, data);
+	ndelay(500); /* h/w recommended delay */
+
+	data = MDSS_PLL_REG_R(pll_base, DSIPHY_PLL_POWERUP_CTRL);
+	data &= ~0x1; /* remove ONPLL_OVR bit */
+	data |= BIT(1); /* set ONPLL_OVR_EN to 0x1 */
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_POWERUP_CTRL, data);
+	ndelay(500); /* h/w recommended delay */
+	wmb(); /* make sure register committed before disabling branch clocks */
+	pll->handoff_resources = false;
+
+	mdss_pll_resource_enable(pll, false);
+
+	pll->pll_on = false;
+
+	pr_debug("DSI PLL ndx=%d Disabled\n", pll->index);
+}
+
+static u32 __mdss_dsi_get_hsfreqrange(u64 target_freq)
+{
+	u64 bitclk_rate_mhz = div_u64((target_freq * 2), 1000000);
+
+	if (bitclk_rate_mhz >= 80 && bitclk_rate_mhz < 90)
+		return 0x00;
+	else if (bitclk_rate_mhz >= 90 && bitclk_rate_mhz < 100)
+		return 0x10;
+	else if (bitclk_rate_mhz >= 100 && bitclk_rate_mhz < 110)
+		return  0x20;
+	else if (bitclk_rate_mhz >= 110 && bitclk_rate_mhz < 120)
+		return  0x30;
+	else if (bitclk_rate_mhz >= 120 && bitclk_rate_mhz < 130)
+		return  0x01;
+	else if (bitclk_rate_mhz >= 130 && bitclk_rate_mhz < 140)
+		return  0x11;
+	else if (bitclk_rate_mhz >= 140 && bitclk_rate_mhz < 150)
+		return  0x21;
+	else if (bitclk_rate_mhz >= 150 && bitclk_rate_mhz < 160)
+		return  0x31;
+	else if (bitclk_rate_mhz >= 160 && bitclk_rate_mhz < 170)
+		return  0x02;
+	else if (bitclk_rate_mhz >= 170 && bitclk_rate_mhz < 180)
+		return  0x12;
+	else if (bitclk_rate_mhz >= 180 && bitclk_rate_mhz < 190)
+		return  0x22;
+	else if (bitclk_rate_mhz >= 190 && bitclk_rate_mhz < 205)
+		return  0x32;
+	else if (bitclk_rate_mhz >= 205 && bitclk_rate_mhz < 220)
+		return  0x03;
+	else if (bitclk_rate_mhz >= 220 && bitclk_rate_mhz < 235)
+		return  0x13;
+	else if (bitclk_rate_mhz >= 235 && bitclk_rate_mhz < 250)
+		return  0x23;
+	else if (bitclk_rate_mhz >= 250 && bitclk_rate_mhz < 275)
+		return  0x33;
+	else if (bitclk_rate_mhz >= 275 && bitclk_rate_mhz < 300)
+		return  0x04;
+	else if (bitclk_rate_mhz >= 300 && bitclk_rate_mhz < 325)
+		return  0x14;
+	else if (bitclk_rate_mhz >= 325 && bitclk_rate_mhz < 350)
+		return  0x25;
+	else if (bitclk_rate_mhz >= 350 && bitclk_rate_mhz < 400)
+		return  0x35;
+	else if (bitclk_rate_mhz >= 400 && bitclk_rate_mhz < 450)
+		return  0x05;
+	else if (bitclk_rate_mhz >= 450 && bitclk_rate_mhz < 500)
+		return  0x16;
+	else if (bitclk_rate_mhz >= 500 && bitclk_rate_mhz < 550)
+		return  0x26;
+	else if (bitclk_rate_mhz >= 550 && bitclk_rate_mhz < 600)
+		return  0x37;
+	else if (bitclk_rate_mhz >= 600 && bitclk_rate_mhz < 650)
+		return  0x07;
+	else if (bitclk_rate_mhz >= 650 && bitclk_rate_mhz < 700)
+		return  0x18;
+	else if (bitclk_rate_mhz >= 700 && bitclk_rate_mhz < 750)
+		return  0x28;
+	else if (bitclk_rate_mhz >= 750 && bitclk_rate_mhz < 800)
+		return  0x39;
+	else if (bitclk_rate_mhz >= 800 && bitclk_rate_mhz < 850)
+		return  0x09;
+	else if (bitclk_rate_mhz >= 850 && bitclk_rate_mhz < 900)
+		return  0x19;
+	else if (bitclk_rate_mhz >= 900 && bitclk_rate_mhz < 950)
+		return  0x29;
+	else if (bitclk_rate_mhz >= 950 && bitclk_rate_mhz < 1000)
+		return  0x3a;
+	else if (bitclk_rate_mhz >= 1000 && bitclk_rate_mhz < 1050)
+		return  0x0a;
+	else if (bitclk_rate_mhz >= 1050 && bitclk_rate_mhz < 1100)
+		return  0x1a;
+	else if (bitclk_rate_mhz >= 1100 && bitclk_rate_mhz < 1150)
+		return  0x2a;
+	else if (bitclk_rate_mhz >= 1150 && bitclk_rate_mhz < 1200)
+		return  0x3b;
+	else if (bitclk_rate_mhz >= 1200 && bitclk_rate_mhz < 1250)
+		return  0x0b;
+	else if (bitclk_rate_mhz >= 1250 && bitclk_rate_mhz < 1300)
+		return  0x1b;
+	else if (bitclk_rate_mhz >= 1300 && bitclk_rate_mhz < 1350)
+		return  0x2b;
+	else if (bitclk_rate_mhz >= 1350 && bitclk_rate_mhz < 1400)
+		return  0x3c;
+	else if (bitclk_rate_mhz >= 1400 && bitclk_rate_mhz < 1450)
+		return  0x0c;
+	else if (bitclk_rate_mhz >= 1450 && bitclk_rate_mhz < 1500)
+		return  0x1c;
+	else if (bitclk_rate_mhz >= 1500 && bitclk_rate_mhz < 1550)
+		return  0x2c;
+	else if (bitclk_rate_mhz >= 1550 && bitclk_rate_mhz < 1600)
+		return  0x3d;
+	else if (bitclk_rate_mhz >= 1600 && bitclk_rate_mhz < 1650)
+		return  0x0d;
+	else if (bitclk_rate_mhz >= 1650 && bitclk_rate_mhz < 1700)
+		return  0x1d;
+	else if (bitclk_rate_mhz >= 1700 && bitclk_rate_mhz < 1750)
+		return  0x2e;
+	else if (bitclk_rate_mhz >= 1750 && bitclk_rate_mhz < 1800)
+		return  0x3e;
+	else if (bitclk_rate_mhz >= 1800 && bitclk_rate_mhz < 1850)
+		return  0x0e;
+	else if (bitclk_rate_mhz >= 1850 && bitclk_rate_mhz < 1900)
+		return  0x1e;
+	else if (bitclk_rate_mhz >= 1900 && bitclk_rate_mhz < 1950)
+		return  0x2f;
+	else if (bitclk_rate_mhz >= 1950 && bitclk_rate_mhz < 2000)
+		return  0x3f;
+	else if (bitclk_rate_mhz >= 2000 && bitclk_rate_mhz < 2050)
+		return  0x0f;
+	else if (bitclk_rate_mhz >= 2050 && bitclk_rate_mhz < 2100)
+		return  0x40;
+	else if (bitclk_rate_mhz >= 2100 && bitclk_rate_mhz < 2150)
+		return  0x41;
+	else if (bitclk_rate_mhz >= 2150 && bitclk_rate_mhz < 2200)
+		return  0x42;
+	else if (bitclk_rate_mhz >= 2200 && bitclk_rate_mhz < 2250)
+		return  0x43;
+	else if (bitclk_rate_mhz >= 2250 && bitclk_rate_mhz < 2300)
+		return  0x44;
+	else if (bitclk_rate_mhz >= 2300 && bitclk_rate_mhz < 2350)
+		return  0x45;
+	else if (bitclk_rate_mhz >= 2350 && bitclk_rate_mhz < 2400)
+		return  0x46;
+	else if (bitclk_rate_mhz >= 2400 && bitclk_rate_mhz < 2450)
+		return  0x47;
+	else if (bitclk_rate_mhz >= 2450 && bitclk_rate_mhz < 2500)
+		return  0x48;
+	else
+		return  0x49;
+}
+
+static void __mdss_dsi_get_pll_vco_cntrl(u64 target_freq, u32 post_div_mux,
+	u32 *vco_cntrl, u32 *cpbias_cntrl)
+{
+	u64 target_freq_mhz = div_u64(target_freq, 1000000);
+	u32 p_div = BIT(post_div_mux);
+
+	if (p_div == 1) {
+		*vco_cntrl = 0x00;
+		*cpbias_cntrl = 0;
+	} else if (p_div == 2) {
+		*vco_cntrl = 0x30;
+		*cpbias_cntrl = 1;
+	} else if (p_div == 4) {
+		*vco_cntrl = 0x10;
+		*cpbias_cntrl = 0;
+	} else if (p_div == 8) {
+		*vco_cntrl = 0x20;
+		*cpbias_cntrl = 0;
+	} else if (p_div == 16) {
+		*vco_cntrl = 0x30;
+		*cpbias_cntrl = 0;
+	} else {
+		*vco_cntrl = 0x00;
+		*cpbias_cntrl = 1;
+	}
+
+	if (target_freq_mhz <= 1250 && target_freq_mhz >= 1092)
+		*vco_cntrl = *vco_cntrl | 2;
+	else if (target_freq_mhz < 1092 && target_freq_mhz >= 950)
+		*vco_cntrl =  *vco_cntrl | 3;
+	else if (target_freq_mhz < 950 && target_freq_mhz >= 712)
+		*vco_cntrl = *vco_cntrl | 1;
+	else if (target_freq_mhz < 712 && target_freq_mhz >= 546)
+		*vco_cntrl =  *vco_cntrl | 2;
+	else if (target_freq_mhz < 546 && target_freq_mhz >= 475)
+		*vco_cntrl = *vco_cntrl | 3;
+	else if (target_freq_mhz < 475 && target_freq_mhz >= 356)
+		*vco_cntrl =  *vco_cntrl | 1;
+	else if (target_freq_mhz < 356 && target_freq_mhz >= 273)
+		*vco_cntrl = *vco_cntrl | 2;
+	else if (target_freq_mhz < 273 && target_freq_mhz >= 237)
+		*vco_cntrl =  *vco_cntrl | 3;
+	else if (target_freq_mhz < 237 && target_freq_mhz >= 178)
+		*vco_cntrl = *vco_cntrl | 1;
+	else if (target_freq_mhz < 178 && target_freq_mhz >= 136)
+		*vco_cntrl =  *vco_cntrl | 2;
+	else if (target_freq_mhz < 136 && target_freq_mhz >= 118)
+		*vco_cntrl = *vco_cntrl | 3;
+	else if (target_freq_mhz < 118 && target_freq_mhz >= 89)
+		*vco_cntrl =  *vco_cntrl | 1;
+	else if (target_freq_mhz < 89 && target_freq_mhz >= 68)
+		*vco_cntrl = *vco_cntrl | 2;
+	else if (target_freq_mhz < 68 && target_freq_mhz >= 57)
+		*vco_cntrl =  *vco_cntrl | 3;
+	else if (target_freq_mhz < 57 && target_freq_mhz >= 44)
+		*vco_cntrl = *vco_cntrl | 1;
+	else
+		*vco_cntrl =  *vco_cntrl | 2;
+}
+
+static u32 __mdss_dsi_get_osc_freq_target(u64 target_freq)
+{
+	u64 target_freq_mhz = div_u64(target_freq, 1000000);
+
+	if (target_freq_mhz <= 1000)
+		return 1315;
+	else if (target_freq_mhz > 1000 && target_freq_mhz <= 1500)
+		return 1839;
+	else
+		return 0;
+}
+
+static u64 __mdss_dsi_pll_get_m_div(u64 vco_rate)
+{
+	return div_u64((vco_rate * 4), 19200000);
+}
+
+static u32 __mdss_dsi_get_fsm_ovr_ctrl(u64 target_freq)
+{
+	u64 bitclk_rate_mhz = div_u64((target_freq * 2), 1000000);
+
+	if (bitclk_rate_mhz > 1500 && bitclk_rate_mhz <= 2500)
+		return 0;
+	else
+		return BIT(6);
+}
+
+static void mdss_dsi_pll_12nm_calc_reg(struct mdss_pll_resources *pll,
+					struct dsi_pll_db *pdb)
+{
+	struct dsi_pll_param *param = &pdb->param;
+	u64 target_freq = 0;
+
+	target_freq = div_u64(pll->vco_current_rate,
+		BIT(pdb->param.post_div_mux));
+
+	param->hsfreqrange = __mdss_dsi_get_hsfreqrange(target_freq);
+	__mdss_dsi_get_pll_vco_cntrl(target_freq, param->post_div_mux,
+		&param->vco_cntrl, &param->cpbias_cntrl);
+	param->osc_freq_target = __mdss_dsi_get_osc_freq_target(target_freq);
+	param->m_div = (u32) __mdss_dsi_pll_get_m_div(pll->vco_current_rate);
+	param->fsm_ovr_ctrl = __mdss_dsi_get_fsm_ovr_ctrl(target_freq);
+	param->prop_cntrl = 0x05;
+	param->int_cntrl = 0x00;
+	param->gmp_cntrl = 0x1;
+}
+
+static void pll_db_commit_12nm(struct mdss_pll_resources *pll,
+					struct dsi_pll_db *pdb)
+{
+	void __iomem *pll_base = pll->pll_base;
+	struct dsi_pll_param *param = &pdb->param;
+	char data = 0;
+
+	MDSS_PLL_REG_W(pll_base, DSIPHY_CTRL0, 0x01);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CTRL, 0x05);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_SLEWRATE_DDL_LOOP_CTRL, 0x01);
+
+	data = ((param->hsfreqrange & 0x7f) | BIT(7));
+	MDSS_PLL_REG_W(pll_base, DSIPHY_HS_FREQ_RAN_SEL, data);
+
+	data = ((param->vco_cntrl & 0x3f) | BIT(6));
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_VCO_CTRL, data);
+
+	data = (param->osc_freq_target & 0x7f);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_SLEWRATE_DDL_CYC_FRQ_ADJ_0, data);
+
+	data = ((param->osc_freq_target & 0xf80) >> 7);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_SLEWRATE_DDL_CYC_FRQ_ADJ_1, data);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_INPUT_LOOP_DIV_RAT_CTRL, 0x30);
+
+	data = (param->m_div & 0x3f);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_LOOP_DIV_RATIO_0, data);
+
+	data = ((param->m_div & 0xfc0) >> 6);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_LOOP_DIV_RATIO_1, data);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_INPUT_DIV_PLL_OVR, 0x60);
+
+	data = (param->prop_cntrl & 0x3f);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PROP_CHRG_PUMP_CTRL, data);
+
+	data = (param->int_cntrl & 0x3f);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_INTEG_CHRG_PUMP_CTRL, data);
+
+	data = ((param->gmp_cntrl & 0x3) << 4);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_GMP_CTRL_DIG_TST, data);
+
+	data = ((param->cpbias_cntrl & 0x1) << 6) | BIT(4);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CHAR_PUMP_BIAS_CTRL, data);
+
+	data = ((param->gp_div_mux & 0x7) << 5) | 0x5;
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_CTRL, data);
+
+	data = (param->pixel_divhf & 0x7f);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_SSC9, data);
+
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_ANA_PROG_CTRL, 0x03);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_ANA_TST_LOCK_ST_OVR_CTRL, 0x50);
+	MDSS_PLL_REG_W(pll_base,
+		DSIPHY_SLEWRATE_FSM_OVR_CTRL, param->fsm_ovr_ctrl);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PHA_ERR_CTRL_0, 0x01);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PHA_ERR_CTRL_1, 0x00);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_LOCK_FILTER, 0xff);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_UNLOCK_FILTER, 0x03);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_PRO_DLY_RELOCK, 0x0c);
+	MDSS_PLL_REG_W(pll_base, DSIPHY_PLL_LOCK_DET_MODE_SEL, 0x02);
+
+	pr_debug("pll:%d\n", pll->index);
+	wmb(); /* make sure register committed before preparing the clocks */
+}
+
+int pll_vco_set_rate_12nm(struct clk *c, unsigned long rate)
+{
+	int rc = 0;
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *pll = vco->priv;
+	struct dsi_pll_db *pdb;
+
+	pdb = (struct dsi_pll_db *)pll->priv;
+	if (!pdb) {
+		pr_err("pll pdb not found\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	pr_debug("%s: ndx=%d rate=%lu\n", __func__, pll->index, rate);
+
+	pll->vco_current_rate = rate;
+	pll->vco_ref_clk_rate = vco->ref_clk_rate;
+error:
+	return rc;
+}
+
+static unsigned long pll_vco_get_rate_12nm(struct clk *c)
+{
+	u64 vco_rate = 0;
+	u32 m_div_5_0 = 0, m_div_11_6 = 0, m_div = 0;
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	u64 ref_clk = vco->ref_clk_rate;
+	int rc;
+	struct mdss_pll_resources *pll = vco->priv;
+
+	if (is_gdsc_disabled(pll))
+		return 0;
+
+	rc = mdss_pll_resource_enable(pll, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll=%d\n", pll->index);
+		return rc;
+	}
+
+	m_div_5_0 = MDSS_PLL_REG_R(pll->pll_base,
+			DSIPHY_PLL_LOOP_DIV_RATIO_0);
+	m_div_5_0 &= 0x3f;
+	pr_debug("m_div_5_0 = 0x%x\n", m_div_5_0);
+
+	m_div_11_6 = MDSS_PLL_REG_R(pll->pll_base,
+			DSIPHY_PLL_LOOP_DIV_RATIO_1);
+	m_div_11_6 &= 0x3f;
+	pr_debug("m_div_11_6 = 0x%x\n", m_div_11_6);
+
+	m_div = ((m_div_11_6 << 6) | (m_div_5_0));
+
+	vco_rate = div_u64((ref_clk * m_div), 4);
+
+	pr_debug("returning vco rate = %lu\n", (unsigned long)vco_rate);
+
+	mdss_pll_resource_enable(pll, false);
+
+	return (unsigned long)vco_rate;
+}
+
+long pll_vco_round_rate_12nm(struct clk *c, unsigned long rate)
+{
+	unsigned long rrate = rate;
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+
+	if (rate < vco->min_rate)
+		rrate = vco->min_rate;
+	if (rate > vco->max_rate)
+		rrate = vco->max_rate;
+
+	return rrate;
+}
+
+enum handoff pll_vco_handoff_12nm(struct clk *c)
+{
+	int rc;
+	enum handoff ret = HANDOFF_DISABLED_CLK;
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *pll = vco->priv;
+
+	if (is_gdsc_disabled(pll))
+		return HANDOFF_DISABLED_CLK;
+
+	rc = mdss_pll_resource_enable(pll, true);
+	if (rc) {
+		pr_err("Failed to enable mdss dsi pll=%d\n", pll->index);
+		return ret;
+	}
+
+	if (pll_is_pll_locked_12nm(pll)) {
+		pll->handoff_resources = true;
+		pll->pll_on = true;
+		c->rate = pll_vco_get_rate_12nm(c);
+		ret = HANDOFF_ENABLED_CLK;
+	} else {
+		mdss_pll_resource_enable(pll, false);
+	}
+
+	return ret;
+}
+
+int pll_vco_prepare_12nm(struct clk *c)
+{
+	int rc = 0;
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *pll = vco->priv;
+	struct dsi_pll_db *pdb;
+	u32 data = 0;
+
+	if (!pll) {
+		pr_err("Dsi pll resources are not available\n");
+		return -EINVAL;
+	}
+
+	pdb = (struct dsi_pll_db *)pll->priv;
+	if (!pdb) {
+		pr_err("No prov found\n");
+		return -EINVAL;
+	}
+
+	rc = mdss_pll_resource_enable(pll, true);
+	if (rc) {
+		pr_err("ndx=%d Failed to enable mdss dsi pll resources\n",
+							pll->index);
+		return rc;
+	}
+
+	if ((pll->vco_cached_rate != 0)
+	    && (pll->vco_cached_rate == c->rate)) {
+		rc = c->ops->set_rate(c, pll->vco_cached_rate);
+		if (rc) {
+			pr_err("index=%d vco_set_rate failed. rc=%d\n",
+					rc, pll->index);
+			goto error;
+		}
+
+		data = MDSS_PLL_REG_R(pll->pll_base, DSIPHY_SYS_CTRL);
+		if (data & BIT(7)) { /* DSI PHY in LP-11 or ULPS */
+			rc = dsi_pll_relock(pll);
+			if (rc)
+				goto error;
+			else
+				goto end;
+		}
+	}
+
+	mdss_dsi_pll_12nm_calc_reg(pll, pdb);
+
+	/* commit DSI vco  */
+	pll_db_commit_12nm(pll, pdb);
+
+	rc = dsi_pll_enable(c);
+
+error:
+	if (rc) {
+		mdss_pll_resource_enable(pll, false);
+		pr_err("ndx=%d failed to enable dsi pll\n", pll->index);
+	}
+
+end:
+	return rc;
+}
+
+void pll_vco_unprepare_12nm(struct clk *c)
+{
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *pll = vco->priv;
+
+	if (!pll) {
+		pr_err("Dsi pll resources are not available\n");
+		return;
+	}
+
+	pll->vco_cached_rate = c->rate;
+	dsi_pll_disable(c);
+}
+
+int pll_vco_enable_12nm(struct clk *c)
+{
+	struct dsi_pll_vco_clk *vco = to_vco_clk(c);
+	struct mdss_pll_resources *pll = vco->priv;
+
+	if (!pll) {
+		pr_err("Dsi pll resources are not available\n");
+		return -EINVAL;
+	}
+
+	if (!pll->pll_on) {
+		pr_err("DSI PLL not enabled, return\n");
+		return -EINVAL;
+	}
+
+	MDSS_PLL_REG_W(pll->pll_base, DSIPHY_SSC0, 0x40);
+	wmb(); /* make sure register committed before enabling branch clocks */
+
+	return 0;
+}
diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-12nm.c b/drivers/clk/msm/mdss/mdss-dsi-pll-12nm.c
new file mode 100644
index 0000000..210742b
--- /dev/null
+++ b/drivers/clk/msm/mdss/mdss-dsi-pll-12nm.c
@@ -0,0 +1,738 @@
+/* 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.
+ *
+ */
+
+#define pr_fmt(fmt)	"%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/clk/msm-clk-provider.h>
+#include <linux/clk/msm-clk.h>
+#include <linux/workqueue.h>
+#include <linux/clk/msm-clock-generic.h>
+#include <dt-bindings/clock/msm-clocks-8952.h>
+
+#include "mdss-pll.h"
+#include "mdss-dsi-pll.h"
+#include "mdss-dsi-pll-12nm.h"
+
+/*
+ * Clock tree model for generating DSI byte clock and pclk for 12nm DSI PLL
+ *
+ *
+ *                                          +---------------+
+ *                               +----------|    vco_clk    |----------+
+ *                               |          +---------------+          |
+ *                               |                                     |
+ *                               |                                     |
+ *                               |                                     |
+ *      +---------+---------+----+----+---------+---------+            |
+ *      |         |         |         |         |         |            |
+ *      |         |         |         |         |         |            |
+ *      |         |         |         |         |         |            |
+ *  +---v---+ +---v---+ +---v---+ +---v---+ +---v---+ +---v---+        |
+ *  | DIV(1)| | DIV(2)| | DIV(4)| | DIV(8)| |DIV(16)| |DIV(32)|        |
+ *  +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+        |
+ *      |         |         |         |         |         |            |
+ *      |         |         +---+ +---+         |         |            |
+ *      |         +-----------+ | | +-----------+         |            |
+ *      +-------------------+ | | | | +-------------------+            |
+ *                          | | | | | |                                |
+ *                       +--v-v-v-v-v-v---+                            |
+ *                        \ post_div_mux /                             |
+ *                         \            /                              |
+ *                          +-----+----+         +---------------------+
+ *                                |              |
+ *       +------------------------+              |
+ *       |                                       |
+ *  +----v----+         +---------+---------+----+----+---------+---------+
+ *  |  DIV-4  |         |         |         |         |         |         |
+ *  +----+----+         |         |         |         |         |         |
+ *       |          +---v---+ +---v---+ +---v---+ +---v---+ +---v---+ +---v---+
+ *       |          | DIV(1)| | DIV(2)| | DIV(4)| | DIV(8)| |DIV(16)| |DIV(32)|
+ *       |          +---+---+ +---+---+ +---+---+ +---+---+ +---+---+ +---+---+
+ *       |              |         |         |         |         |         |
+ *       v              |         |         +---+ +---+         |         |
+ *  byte_clk_src        |         +-----------+ | | +-----------+         |
+ *                      +-------------------+ | | | | +-------------------+
+ *                                          | | | | | |
+ *                                       +--v-v-v-v-v-v---+
+ *                                        \ gp_cntrl_mux /
+ *                                         \            /
+ *                                          +-----+----+
+ *                                                |
+ *                                                |
+ *                                        +-------v-------+
+ *                                        |   (DIV + 1)   |
+ *                                        | DIV = 0...127 |
+ *                                        +-------+-------+
+ *                                                |
+ *                                                |
+ *                                                v
+ *                              dsi_pclk input to Clock Controller MND
+ */
+
+static struct dsi_pll_db pll_db[DSI_PLL_NUM];
+
+static struct clk_ops pixel_div_clk_src_ops;
+
+/* Op structures */
+static const struct clk_ops clk_ops_dsi_vco = {
+	.set_rate = pll_vco_set_rate_12nm,
+	.round_rate = pll_vco_round_rate_12nm,
+	.handoff = pll_vco_handoff_12nm,
+	.prepare = pll_vco_prepare_12nm,
+	.unprepare = pll_vco_unprepare_12nm,
+	.enable = pll_vco_enable_12nm,
+};
+
+static struct clk_div_ops pixel_div_ops = {
+	.set_div = pixel_div_set_div,
+	.get_div = pixel_div_get_div,
+};
+
+static struct clk_mux_ops post_div_mux_ops = {
+	.set_mux_sel = set_post_div_mux_sel,
+	.get_mux_sel = get_post_div_mux_sel,
+};
+
+static struct clk_mux_ops gp_div_mux_ops = {
+	.set_mux_sel = set_gp_mux_sel,
+	.get_mux_sel = get_gp_mux_sel,
+};
+
+static struct dsi_pll_vco_clk dsi0pll_vco_clk = {
+	.ref_clk_rate = 19200000UL,
+	.min_rate = 1000000000UL,
+	.max_rate = 2000000000UL,
+	.pll_en_seq_cnt = 1,
+	.pll_enable_seqs[0] = dsi_pll_enable_seq_12nm,
+	.c = {
+		.dbg_name = "dsi0pll_vco_clk_12nm",
+		.ops = &clk_ops_dsi_vco,
+		CLK_INIT(dsi0pll_vco_clk.c),
+	},
+};
+
+static struct dsi_pll_vco_clk dsi1pll_vco_clk = {
+	.ref_clk_rate = 19200000UL,
+	.min_rate = 1000000000UL,
+	.max_rate = 2000000000UL,
+	.pll_en_seq_cnt = 1,
+	.pll_enable_seqs[0] = dsi_pll_enable_seq_12nm,
+	.c = {
+		.dbg_name = "dsi1pll_vco_clk_12nm",
+		.ops = &clk_ops_dsi_vco,
+		CLK_INIT(dsi1pll_vco_clk.c),
+	},
+};
+
+static struct div_clk dsi0pll_post_div1 = {
+	.data = {
+		.div = 1,
+		.min_div = 1,
+		.max_div = 1,
+	},
+	.c = {
+		.parent = &dsi0pll_vco_clk.c,
+		.dbg_name = "dsi0pll_post_div1",
+		.ops = &clk_ops_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_post_div1.c),
+	},
+};
+
+static struct div_clk dsi0pll_post_div2 = {
+	.data = {
+		.div = 2,
+		.min_div = 2,
+		.max_div = 2,
+	},
+	.c = {
+		.parent = &dsi0pll_vco_clk.c,
+		.dbg_name = "dsi0pll_post_div2",
+		.ops = &clk_ops_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_post_div2.c),
+	},
+};
+
+static struct div_clk dsi0pll_post_div4 = {
+	.data = {
+		.div = 4,
+		.min_div = 4,
+		.max_div = 4,
+	},
+	.c = {
+		.parent = &dsi0pll_vco_clk.c,
+		.dbg_name = "dsi0pll_post_div4",
+		.ops = &clk_ops_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_post_div4.c),
+	},
+};
+
+static struct div_clk dsi0pll_post_div8 = {
+	.data = {
+		.div = 8,
+		.min_div = 8,
+		.max_div = 8,
+	},
+	.c = {
+		.parent = &dsi0pll_vco_clk.c,
+		.dbg_name = "dsi0pll_post_div8",
+		.ops = &clk_ops_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_post_div8.c),
+	},
+};
+
+static struct div_clk dsi0pll_post_div16 = {
+	.data = {
+		.div = 16,
+		.min_div = 16,
+		.max_div = 16,
+	},
+	.c = {
+		.parent = &dsi0pll_vco_clk.c,
+		.dbg_name = "dsi0pll_post_div16",
+		.ops = &clk_ops_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_post_div16.c),
+	},
+};
+
+static struct div_clk dsi0pll_post_div32 = {
+	.data = {
+		.div = 32,
+		.min_div = 32,
+		.max_div = 32,
+	},
+	.c = {
+		.parent = &dsi0pll_vco_clk.c,
+		.dbg_name = "dsi0pll_post_div32",
+		.ops = &clk_ops_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_post_div32.c),
+	},
+};
+
+static struct mux_clk dsi0pll_post_div_mux = {
+	.num_parents = 6,
+	.parents = (struct clk_src[]) {
+		{&dsi0pll_post_div1.c, 0},
+		{&dsi0pll_post_div2.c, 1},
+		{&dsi0pll_post_div4.c, 2},
+		{&dsi0pll_post_div8.c, 3},
+		{&dsi0pll_post_div16.c, 4},
+		{&dsi0pll_post_div32.c, 5},
+	},
+	.ops = &post_div_mux_ops,
+	.c = {
+		.parent = &dsi0pll_post_div1.c,
+		.dbg_name = "dsi0pll_post_div_mux",
+		.ops = &clk_ops_gen_mux,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_post_div_mux.c),
+	}
+};
+
+static struct div_clk dsi1pll_post_div1 = {
+	.data = {
+		.div = 1,
+		.min_div = 1,
+		.max_div = 1,
+	},
+	.c = {
+		.parent = &dsi1pll_vco_clk.c,
+		.dbg_name = "dsi1pll_post_div1",
+		.ops = &clk_ops_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_post_div1.c),
+	},
+};
+
+static struct div_clk dsi1pll_post_div2 = {
+	.data = {
+		.div = 2,
+		.min_div = 2,
+		.max_div = 2,
+	},
+	.c = {
+		.parent = &dsi1pll_vco_clk.c,
+		.dbg_name = "dsi1pll_post_div2",
+		.ops = &clk_ops_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_post_div2.c),
+	},
+};
+
+static struct div_clk dsi1pll_post_div4 = {
+	.data = {
+		.div = 4,
+		.min_div = 4,
+		.max_div = 4,
+	},
+	.c = {
+		.parent = &dsi1pll_vco_clk.c,
+		.dbg_name = "dsi1pll_post_div4",
+		.ops = &clk_ops_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_post_div4.c),
+	},
+};
+
+static struct div_clk dsi1pll_post_div8 = {
+	.data = {
+		.div = 8,
+		.min_div = 8,
+		.max_div = 8,
+	},
+	.c = {
+		.parent = &dsi1pll_vco_clk.c,
+		.dbg_name = "dsi1pll_post_div8",
+		.ops = &clk_ops_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_post_div8.c),
+	},
+};
+
+static struct div_clk dsi1pll_post_div16 = {
+	.data = {
+		.div = 16,
+		.min_div = 16,
+		.max_div = 16,
+	},
+	.c = {
+		.parent = &dsi1pll_vco_clk.c,
+		.dbg_name = "dsi1pll_post_div16",
+		.ops = &clk_ops_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_post_div16.c),
+	},
+};
+
+static struct div_clk dsi1pll_post_div32 = {
+	.data = {
+		.div = 32,
+		.min_div = 32,
+		.max_div = 32,
+	},
+	.c = {
+		.parent = &dsi1pll_vco_clk.c,
+		.dbg_name = "dsi1pll_post_div32",
+		.ops = &clk_ops_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_post_div32.c),
+	},
+};
+
+static struct mux_clk dsi1pll_post_div_mux = {
+	.num_parents = 6,
+	.parents = (struct clk_src[]) {
+		{&dsi1pll_post_div1.c, 0},
+		{&dsi1pll_post_div2.c, 1},
+		{&dsi1pll_post_div4.c, 2},
+		{&dsi1pll_post_div8.c, 3},
+		{&dsi1pll_post_div16.c, 4},
+		{&dsi1pll_post_div32.c, 5},
+	},
+	.ops = &post_div_mux_ops,
+	.c = {
+		.parent = &dsi1pll_post_div1.c,
+		.dbg_name = "dsi1pll_post_div_mux",
+		.ops = &clk_ops_gen_mux,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_post_div_mux.c),
+	}
+};
+
+static struct div_clk dsi0pll_gp_div1 = {
+	.data = {
+		.div = 1,
+		.min_div = 1,
+		.max_div = 1,
+	},
+	.c = {
+		.parent = &dsi0pll_vco_clk.c,
+		.dbg_name = "dsi0pll_gp_div1",
+		.ops = &clk_ops_slave_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_gp_div1.c),
+	},
+};
+
+static struct div_clk dsi0pll_gp_div2 = {
+	.data = {
+		.div = 2,
+		.min_div = 2,
+		.max_div = 2,
+	},
+	.c = {
+		.parent = &dsi0pll_vco_clk.c,
+		.dbg_name = "dsi0pll_gp_div2",
+		.ops = &clk_ops_slave_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_gp_div2.c),
+	},
+};
+
+static struct div_clk dsi0pll_gp_div4 = {
+	.data = {
+		.div = 4,
+		.min_div = 4,
+		.max_div = 4,
+	},
+	.c = {
+		.parent = &dsi0pll_vco_clk.c,
+		.dbg_name = "dsi0pll_gp_div4",
+		.ops = &clk_ops_slave_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_gp_div4.c),
+	},
+};
+
+static struct div_clk dsi0pll_gp_div8 = {
+	.data = {
+		.div = 8,
+		.min_div = 8,
+		.max_div = 8,
+	},
+	.c = {
+		.parent = &dsi0pll_vco_clk.c,
+		.dbg_name = "dsi0pll_gp_div8",
+		.ops = &clk_ops_slave_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_gp_div8.c),
+	},
+};
+
+static struct div_clk dsi0pll_gp_div16 = {
+	.data = {
+		.div = 16,
+		.min_div = 16,
+		.max_div = 16,
+	},
+	.c = {
+		.parent = &dsi0pll_vco_clk.c,
+		.dbg_name = "dsi0pll_gp_div16",
+		.ops = &clk_ops_slave_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_gp_div16.c),
+	},
+};
+
+static struct div_clk dsi0pll_gp_div32 = {
+	.data = {
+		.div = 32,
+		.min_div = 32,
+		.max_div = 32,
+	},
+	.c = {
+		.parent = &dsi0pll_vco_clk.c,
+		.dbg_name = "dsi0pll_gp_div32",
+		.ops = &clk_ops_slave_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_gp_div32.c),
+	},
+};
+
+static struct mux_clk dsi0pll_gp_div_mux = {
+	.num_parents = 6,
+	.parents = (struct clk_src[]) {
+		{&dsi0pll_gp_div1.c, 0},
+		{&dsi0pll_gp_div2.c, 1},
+		{&dsi0pll_gp_div4.c, 2},
+		{&dsi0pll_gp_div8.c, 3},
+		{&dsi0pll_gp_div16.c, 4},
+		{&dsi0pll_gp_div32.c, 5},
+	},
+	.ops = &gp_div_mux_ops,
+	.c = {
+		.parent = &dsi0pll_gp_div1.c,
+		.dbg_name = "dsi0pll_gp_div_mux",
+		.ops = &clk_ops_gen_mux,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_gp_div_mux.c),
+	}
+};
+
+static struct div_clk dsi1pll_gp_div1 = {
+	.data = {
+		.div = 1,
+		.min_div = 1,
+		.max_div = 1,
+	},
+	.c = {
+		.parent = &dsi1pll_vco_clk.c,
+		.dbg_name = "dsi1pll_gp_div1",
+		.ops = &clk_ops_slave_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_gp_div1.c),
+	},
+};
+
+static struct div_clk dsi1pll_gp_div2 = {
+	.data = {
+		.div = 2,
+		.min_div = 2,
+		.max_div = 2,
+	},
+	.c = {
+		.parent = &dsi1pll_vco_clk.c,
+		.dbg_name = "dsi1pll_gp_div2",
+		.ops = &clk_ops_slave_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_gp_div2.c),
+	},
+};
+
+static struct div_clk dsi1pll_gp_div4 = {
+	.data = {
+		.div = 4,
+		.min_div = 4,
+		.max_div = 4,
+	},
+	.c = {
+		.parent = &dsi1pll_vco_clk.c,
+		.dbg_name = "dsi1pll_gp_div4",
+		.ops = &clk_ops_slave_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_gp_div4.c),
+	},
+};
+
+static struct div_clk dsi1pll_gp_div8 = {
+	.data = {
+		.div = 8,
+		.min_div = 8,
+		.max_div = 8,
+	},
+	.c = {
+		.parent = &dsi1pll_vco_clk.c,
+		.dbg_name = "dsi1pll_gp_div8",
+		.ops = &clk_ops_slave_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_gp_div8.c),
+	},
+};
+
+static struct div_clk dsi1pll_gp_div16 = {
+	.data = {
+		.div = 16,
+		.min_div = 16,
+		.max_div = 16,
+	},
+	.c = {
+		.parent = &dsi1pll_vco_clk.c,
+		.dbg_name = "dsi1pll_gp_div16",
+		.ops = &clk_ops_slave_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_gp_div16.c),
+	},
+};
+
+static struct div_clk dsi1pll_gp_div32 = {
+	.data = {
+		.div = 32,
+		.min_div = 32,
+		.max_div = 32,
+	},
+	.c = {
+		.parent = &dsi1pll_vco_clk.c,
+		.dbg_name = "dsi1pll_gp_div32",
+		.ops = &clk_ops_slave_div,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_gp_div32.c),
+	},
+};
+
+static struct mux_clk dsi1pll_gp_div_mux = {
+	.num_parents = 6,
+	.parents = (struct clk_src[]) {
+		{&dsi1pll_gp_div1.c, 0},
+		{&dsi1pll_gp_div2.c, 1},
+		{&dsi1pll_gp_div4.c, 2},
+		{&dsi1pll_gp_div8.c, 3},
+		{&dsi1pll_gp_div16.c, 4},
+		{&dsi1pll_gp_div32.c, 5},
+	},
+	.ops = &gp_div_mux_ops,
+	.c = {
+		.parent = &dsi1pll_gp_div1.c,
+		.dbg_name = "dsi1pll_gp_div_mux",
+		.ops = &clk_ops_gen_mux,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_gp_div_mux.c),
+	}
+};
+
+static struct div_clk dsi0pll_pixel_clk_src = {
+	.data = {
+		.max_div = 128,
+		.min_div = 1,
+	},
+	.ops = &pixel_div_ops,
+	.c = {
+		.parent = &dsi0pll_gp_div_mux.c,
+		.dbg_name = "dsi0pll_pixel_clk_src",
+		.ops = &pixel_div_clk_src_ops,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi0pll_pixel_clk_src.c),
+	},
+};
+
+static struct div_clk dsi1pll_pixel_clk_src = {
+	.data = {
+		.max_div = 128,
+		.min_div = 1,
+	},
+	.ops = &pixel_div_ops,
+	.c = {
+		.parent = &dsi1pll_gp_div_mux.c,
+		.dbg_name = "dsi1pll_pixel_clk_src",
+		.ops = &pixel_div_clk_src_ops,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(dsi1pll_pixel_clk_src.c),
+	},
+};
+
+static struct div_clk dsi0pll_byte_clk_src = {
+	.data = {
+		.div = 4,
+		.min_div = 4,
+		.max_div = 4,
+	},
+	.c = {
+		.parent = &dsi0pll_post_div_mux.c,
+		.dbg_name = "dsi0pll_byte_clk_src",
+		.ops = &clk_ops_div,
+		CLK_INIT(dsi0pll_byte_clk_src.c),
+	},
+};
+
+static struct div_clk dsi1pll_byte_clk_src = {
+	.data = {
+		.div = 4,
+		.min_div = 4,
+		.max_div = 4,
+	},
+	.c = {
+		.parent = &dsi1pll_post_div_mux.c,
+		.dbg_name = "dsi1pll_byte_clk_src",
+		.ops = &clk_ops_div,
+		CLK_INIT(dsi1pll_byte_clk_src.c),
+	},
+};
+
+static struct clk_lookup mdss_dsi_pllcc_12nm[] = {
+	CLK_LIST(dsi0pll_byte_clk_src),
+	CLK_LIST(dsi0pll_pixel_clk_src),
+};
+
+static struct clk_lookup mdss_dsi_pllcc_12nm_1[] = {
+	CLK_LIST(dsi1pll_byte_clk_src),
+	CLK_LIST(dsi1pll_pixel_clk_src),
+};
+
+int dsi_pll_clock_register_12nm(struct platform_device *pdev,
+				struct mdss_pll_resources *pll_res)
+{
+	int rc = 0, ndx;
+	struct dsi_pll_db *pdb;
+
+	if (!pdev || !pdev->dev.of_node) {
+		pr_err("Invalid input parameters\n");
+		return -EINVAL;
+	}
+
+	if (!pll_res || !pll_res->pll_base) {
+		pr_err("Invalid PLL resources\n");
+		return -EPROBE_DEFER;
+	}
+
+	if (pll_res->index >= DSI_PLL_NUM) {
+		pr_err("pll ndx=%d is NOT supported\n", pll_res->index);
+		return -EINVAL;
+	}
+
+	ndx = pll_res->index;
+	pdb = &pll_db[ndx];
+	pll_res->priv = pdb;
+	pdb->pll = pll_res;
+	ndx++;
+	ndx %= DSI_PLL_NUM;
+	pdb->next = &pll_db[ndx];
+
+	/* Set clock source operations */
+
+	/* pixel_clk */
+	pixel_div_clk_src_ops = clk_ops_div;
+	pixel_div_clk_src_ops.prepare = dsi_pll_div_prepare;
+
+	/* Set client data to mux, div and vco clocks.  */
+	if (pll_res->index == DSI_PLL_1) {
+		dsi1pll_byte_clk_src.priv = pll_res;
+		dsi1pll_post_div_mux.priv = pll_res;
+		dsi1pll_post_div1.priv = pll_res;
+		dsi1pll_post_div2.priv = pll_res;
+		dsi1pll_post_div4.priv = pll_res;
+		dsi1pll_post_div8.priv = pll_res;
+		dsi1pll_post_div16.priv = pll_res;
+		dsi1pll_post_div32.priv = pll_res;
+		dsi1pll_pixel_clk_src.priv = pll_res;
+		dsi1pll_gp_div_mux.priv = pll_res;
+		dsi1pll_gp_div1.priv = pll_res;
+		dsi1pll_gp_div2.priv = pll_res;
+		dsi1pll_gp_div4.priv = pll_res;
+		dsi1pll_gp_div8.priv = pll_res;
+		dsi1pll_gp_div16.priv = pll_res;
+		dsi1pll_gp_div32.priv = pll_res;
+		dsi1pll_vco_clk.priv = pll_res;
+
+		if (pll_res->target_id == MDSS_PLL_TARGET_SDM439)
+			rc = of_msm_clock_register(pdev->dev.of_node,
+				mdss_dsi_pllcc_12nm_1,
+				ARRAY_SIZE(mdss_dsi_pllcc_12nm_1));
+	} else {
+		dsi0pll_byte_clk_src.priv = pll_res;
+		dsi0pll_post_div_mux.priv = pll_res;
+		dsi0pll_post_div1.priv = pll_res;
+		dsi0pll_post_div2.priv = pll_res;
+		dsi0pll_post_div4.priv = pll_res;
+		dsi0pll_post_div8.priv = pll_res;
+		dsi0pll_post_div16.priv = pll_res;
+		dsi0pll_post_div32.priv = pll_res;
+		dsi0pll_pixel_clk_src.priv = pll_res;
+		dsi0pll_gp_div_mux.priv = pll_res;
+		dsi0pll_gp_div1.priv = pll_res;
+		dsi0pll_gp_div2.priv = pll_res;
+		dsi0pll_gp_div4.priv = pll_res;
+		dsi0pll_gp_div8.priv = pll_res;
+		dsi0pll_gp_div16.priv = pll_res;
+		dsi0pll_gp_div32.priv = pll_res;
+		dsi0pll_vco_clk.priv = pll_res;
+
+		if (pll_res->target_id == MDSS_PLL_TARGET_SDM439)
+			rc = of_msm_clock_register(pdev->dev.of_node,
+				mdss_dsi_pllcc_12nm,
+				ARRAY_SIZE(mdss_dsi_pllcc_12nm));
+	}
+
+	if (!rc) {
+		pr_info("Registered DSI PLL ndx=%d clocks successfully\n",
+						pll_res->index);
+	}
+
+	return rc;
+}
diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-12nm.h b/drivers/clk/msm/mdss/mdss-dsi-pll-12nm.h
new file mode 100644
index 0000000..6912ff4
--- /dev/null
+++ b/drivers/clk/msm/mdss/mdss-dsi-pll-12nm.h
@@ -0,0 +1,89 @@
+/* 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 MDSS_DSI_PLL_12NM_H
+#define MDSS_DSI_PLL_12NM_H
+
+#define DSIPHY_PLL_POWERUP_CTRL					0x034
+#define DSIPHY_PLL_PROP_CHRG_PUMP_CTRL			0x038
+#define DSIPHY_PLL_INTEG_CHRG_PUMP_CTRL			0x03c
+#define DSIPHY_PLL_ANA_TST_LOCK_ST_OVR_CTRL	0x044
+#define DSIPHY_PLL_VCO_CTRL				0x048
+#define DSIPHY_PLL_GMP_CTRL_DIG_TST			0x04c
+#define DSIPHY_PLL_PHA_ERR_CTRL_0			0x050
+#define DSIPHY_PLL_LOCK_FILTER				0x054
+#define DSIPHY_PLL_UNLOCK_FILTER			0x058
+#define DSIPHY_PLL_INPUT_DIV_PLL_OVR			0x05c
+#define DSIPHY_PLL_LOOP_DIV_RATIO_0			0x060
+#define DSIPHY_PLL_INPUT_LOOP_DIV_RAT_CTRL		0x064
+#define DSIPHY_PLL_PRO_DLY_RELOCK			0x06c
+#define DSIPHY_PLL_CHAR_PUMP_BIAS_CTRL			0x070
+#define DSIPHY_PLL_LOCK_DET_MODE_SEL			0x074
+#define DSIPHY_PLL_ANA_PROG_CTRL			0x07c
+#define DSIPHY_HS_FREQ_RAN_SEL				0x110
+#define DSIPHY_SLEWRATE_FSM_OVR_CTRL			0x280
+#define DSIPHY_SLEWRATE_DDL_LOOP_CTRL			0x28c
+#define DSIPHY_SLEWRATE_DDL_CYC_FRQ_ADJ_0		0x290
+#define DSIPHY_PLL_PHA_ERR_CTRL_1			0x2e4
+#define DSIPHY_PLL_LOOP_DIV_RATIO_1			0x2e8
+#define DSIPHY_SLEWRATE_DDL_CYC_FRQ_ADJ_1		0x328
+#define DSIPHY_SSC0					0x394
+#define DSIPHY_SSC9					0x3b8
+#define DSIPHY_STAT0					0x3e0
+#define DSIPHY_CTRL0					0x3e8
+#define DSIPHY_SYS_CTRL					0x3f0
+#define DSIPHY_PLL_CTRL					0x3f8
+
+struct dsi_pll_param {
+	u32 hsfreqrange;
+	u32 vco_cntrl;
+	u32 osc_freq_target;
+	u32 m_div;
+	u32 prop_cntrl;
+	u32 int_cntrl;
+	u32 gmp_cntrl;
+	u32 cpbias_cntrl;
+
+	/* mux and dividers */
+	u32 gp_div_mux;
+	u32 post_div_mux;
+	u32 pixel_divhf;
+	u32 fsm_ovr_ctrl;
+};
+
+enum {
+	DSI_PLL_0,
+	DSI_PLL_1,
+	DSI_PLL_NUM
+};
+
+struct dsi_pll_db {
+	struct dsi_pll_db *next;
+	struct mdss_pll_resources *pll;
+	struct dsi_pll_param param;
+};
+
+int pll_vco_set_rate_12nm(struct clk *c, unsigned long rate);
+long pll_vco_round_rate_12nm(struct clk *c, unsigned long rate);
+enum handoff pll_vco_handoff_12nm(struct clk *c);
+int pll_vco_prepare_12nm(struct clk *c);
+void pll_vco_unprepare_12nm(struct clk *c);
+int pll_vco_enable_12nm(struct clk *c);
+int pixel_div_set_div(struct div_clk *clk, int div);
+int pixel_div_get_div(struct div_clk *clk);
+int set_post_div_mux_sel(struct mux_clk *clk, int sel);
+int get_post_div_mux_sel(struct mux_clk *clk);
+int set_gp_mux_sel(struct mux_clk *clk, int sel);
+int get_gp_mux_sel(struct mux_clk *clk);
+int dsi_pll_enable_seq_12nm(struct mdss_pll_resources *pll);
+
+#endif  /* MDSS_DSI_PLL_12NM_H */
diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll.h b/drivers/clk/msm/mdss/mdss-dsi-pll.h
index 4a9bb64..8498259 100644
--- a/drivers/clk/msm/mdss/mdss-dsi-pll.h
+++ b/drivers/clk/msm/mdss/mdss-dsi-pll.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -81,6 +81,8 @@
 				struct mdss_pll_resources *pll_res);
 int dsi_pll_clock_register_8996(struct platform_device *pdev,
 				struct mdss_pll_resources *pll_res);
+int dsi_pll_clock_register_12nm(struct platform_device *pdev,
+				struct mdss_pll_resources *pll_res);
 
 int set_byte_mux_sel(struct mux_clk *clk, int sel);
 int get_byte_mux_sel(struct mux_clk *clk);
diff --git a/drivers/clk/msm/mdss/mdss-pll.c b/drivers/clk/msm/mdss/mdss-pll.c
index 49f3d7b..b8b6883 100644
--- a/drivers/clk/msm/mdss/mdss-pll.c
+++ b/drivers/clk/msm/mdss/mdss-pll.c
@@ -136,6 +136,9 @@
 	} else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_8909")) {
 		pll_res->pll_interface_type = MDSS_DSI_PLL_LPM;
 		pll_res->target_id = MDSS_PLL_TARGET_8909;
+	} else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_sdm439")) {
+		pll_res->pll_interface_type = MDSS_DSI_PLL_12NM;
+		pll_res->target_id = MDSS_PLL_TARGET_SDM439;
 	} else if (!strcmp(compatible_stream, "qcom,mdss_dsi_pll_8996")) {
 		pll_res->pll_interface_type = MDSS_DSI_PLL_8996;
 		pll_res->target_id = MDSS_PLL_TARGET_8996;
@@ -186,6 +189,9 @@
 	case MDSS_DSI_PLL_8996:
 		rc = dsi_pll_clock_register_8996(pdev, pll_res);
 		break;
+	case MDSS_DSI_PLL_12NM:
+		rc = dsi_pll_clock_register_12nm(pdev, pll_res);
+		break;
 	case MDSS_HDMI_PLL_8996:
 		rc = hdmi_8996_v1_pll_clock_register(pdev, pll_res);
 		break;
@@ -403,6 +409,7 @@
 	{.compatible = "qcom,mdss_dsi_pll_8937"},
 	{.compatible = "qcom,mdss_dsi_pll_8909"},
 	{.compatible = "qcom,mdss_dsi_pll_8953"},
+	{.compatible = "qcom,mdss_dsi_pll_sdm439"},
 	{}
 };
 
diff --git a/drivers/clk/msm/mdss/mdss-pll.h b/drivers/clk/msm/mdss/mdss-pll.h
index 1fa5cff..026ac8e 100644
--- a/drivers/clk/msm/mdss/mdss-pll.h
+++ b/drivers/clk/msm/mdss/mdss-pll.h
@@ -31,6 +31,7 @@
 enum {
 	MDSS_DSI_PLL_LPM,
 	MDSS_DSI_PLL_8996,
+	MDSS_DSI_PLL_12NM,
 	MDSS_HDMI_PLL_8996,
 	MDSS_HDMI_PLL_8996_V2,
 	MDSS_HDMI_PLL_8996_V3,
@@ -44,6 +45,7 @@
 	MDSS_PLL_TARGET_8937,
 	MDSS_PLL_TARGET_8953,
 	MDSS_PLL_TARGET_8909,
+	MDSS_PLL_TARGET_SDM439,
 };
 
 struct mdss_pll_resources {
diff --git a/drivers/clk/qcom/gcc-sdxpoorwills.c b/drivers/clk/qcom/gcc-sdxpoorwills.c
index 4050683..b52002f 100644
--- a/drivers/clk/qcom/gcc-sdxpoorwills.c
+++ b/drivers/clk/qcom/gcc-sdxpoorwills.c
@@ -40,6 +40,7 @@
 #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
 
 static DEFINE_VDD_REGULATORS(vdd_cx, VDD_CX_NUM, 1, vdd_corner);
+static DEFINE_VDD_REGULATORS(vdd_cx_ao, VDD_CX_NUM, 1, vdd_corner);
 
 enum {
 	P_BI_TCXO,
@@ -64,6 +65,13 @@
 	"core_bi_pll_test_se",
 };
 
+static const char * const gcc_parent_names_ao_0[] = {
+	"bi_tcxo_ao",
+	"gpll0",
+	"gpll0_out_even",
+	"core_bi_pll_test_se",
+};
+
 static const struct parent_map gcc_parent_map_1[] = {
 	{ P_BI_TCXO, 0 },
 	{ P_CORE_BI_PLL_TEST_SE, 7 },
@@ -219,7 +227,6 @@
 		.name = "gcc_blsp1_qup1_i2c_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP3(
 			MIN, 9600000,
@@ -250,7 +257,6 @@
 		.name = "gcc_blsp1_qup1_spi_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 9600000,
@@ -270,7 +276,6 @@
 		.name = "gcc_blsp1_qup2_i2c_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP3(
 			MIN, 9600000,
@@ -289,7 +294,6 @@
 		.name = "gcc_blsp1_qup2_spi_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 9600000,
@@ -309,7 +313,6 @@
 		.name = "gcc_blsp1_qup3_i2c_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP3(
 			MIN, 9600000,
@@ -328,7 +331,6 @@
 		.name = "gcc_blsp1_qup3_spi_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 9600000,
@@ -348,7 +350,6 @@
 		.name = "gcc_blsp1_qup4_i2c_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP3(
 			MIN, 9600000,
@@ -367,7 +368,6 @@
 		.name = "gcc_blsp1_qup4_spi_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 9600000,
@@ -418,7 +418,6 @@
 		.name = "gcc_blsp1_uart1_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 9600000,
@@ -438,7 +437,6 @@
 		.name = "gcc_blsp1_uart2_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 9600000,
@@ -458,7 +456,6 @@
 		.name = "gcc_blsp1_uart3_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 9600000,
@@ -478,7 +475,6 @@
 		.name = "gcc_blsp1_uart4_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 9600000,
@@ -490,9 +486,6 @@
 
 static const struct freq_tbl ftbl_gcc_cpuss_ahb_clk_src[] = {
 	F(19200000, P_BI_TCXO, 1, 0, 0),
-	F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
-	F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
-	F(133333333, P_GPLL0_OUT_MAIN, 4.5, 0, 0),
 	{ }
 };
 
@@ -504,21 +497,16 @@
 	.freq_tbl = ftbl_gcc_cpuss_ahb_clk_src,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_cpuss_ahb_clk_src",
-		.parent_names = gcc_parent_names_0,
+		.parent_names = gcc_parent_names_ao_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
-		VDD_CX_FMAX_MAP4(
-			MIN, 19200000,
-			LOWER, 50000000,
-			NOMINAL, 100000000,
-			HIGH, 133333333),
+		VDD_CX_FMAX_MAP1_AO(
+				MIN, 19200000),
 	},
 };
 
 static const struct freq_tbl ftbl_gcc_cpuss_rbcpr_clk_src[] = {
 	F(19200000, P_BI_TCXO, 1, 0, 0),
-	F(50000000, P_GPLL0_OUT_MAIN, 12, 0, 0),
 	{ }
 };
 
@@ -530,13 +518,11 @@
 	.freq_tbl = ftbl_gcc_cpuss_rbcpr_clk_src,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_cpuss_rbcpr_clk_src",
-		.parent_names = gcc_parent_names_0,
+		.parent_names = gcc_parent_names_ao_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
-		VDD_CX_FMAX_MAP2(
-			MIN, 19200000,
-			NOMINAL, 50000000),
+		VDD_CX_FMAX_MAP1_AO(
+			MIN, 19200000),
 	},
 };
 
@@ -561,7 +547,6 @@
 		.name = "gcc_emac_clk_src",
 		.parent_names = gcc_parent_names_4,
 		.num_parents = 5,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 19200000,
@@ -571,17 +556,25 @@
 	},
 };
 
+static const struct freq_tbl ftbl_gcc_emac_ptp_clk_src[] = {
+	F(19200000, P_BI_TCXO, 1, 0, 0),
+	F(25000000, P_GPLL0_OUT_EVEN, 12, 0, 0),
+	F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
+	F(125000000, P_GPLL4_OUT_EVEN, 4, 0, 0),
+	F(250000000, P_GPLL4_OUT_EVEN, 2, 0, 0),
+	{ }
+};
+
 static struct clk_rcg2 gcc_emac_ptp_clk_src = {
 	.cmd_rcgr = 0x47038,
 	.mnd_width = 0,
 	.hid_width = 5,
 	.parent_map = gcc_parent_map_4,
-	.freq_tbl = ftbl_gcc_emac_clk_src,
+	.freq_tbl = ftbl_gcc_emac_ptp_clk_src,
 	.clkr.hw.init = &(struct clk_init_data){
 		.name = "gcc_emac_ptp_clk_src",
 		.parent_names = gcc_parent_names_4,
 		.num_parents = 5,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 19200000,
@@ -610,7 +603,6 @@
 		.name = "gcc_gp1_clk_src",
 		.parent_names = gcc_parent_names_2,
 		.num_parents = 5,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 19200000,
@@ -630,7 +622,6 @@
 		.name = "gcc_gp2_clk_src",
 		.parent_names = gcc_parent_names_2,
 		.num_parents = 5,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 19200000,
@@ -650,7 +641,6 @@
 		.name = "gcc_gp3_clk_src",
 		.parent_names = gcc_parent_names_2,
 		.num_parents = 5,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 19200000,
@@ -675,7 +665,6 @@
 		.name = "gcc_pcie_aux_phy_clk_src",
 		.parent_names = gcc_parent_names_3,
 		.num_parents = 3,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP1(
 			MIN, 19200000),
@@ -698,7 +687,6 @@
 		.name = "gcc_pcie_phy_refgen_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP2(
 			MIN, 19200000,
@@ -723,7 +711,6 @@
 		.name = "gcc_pdm2_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP3(
 			MIN, 9600000,
@@ -742,7 +729,6 @@
 		.name = "gcc_sdcc1_apps_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP4(
 			MIN, 19200000,
@@ -762,7 +748,6 @@
 		.name = "gcc_spmi_fetcher_clk_src",
 		.parent_names = gcc_parent_names_1,
 		.num_parents = 2,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP1(
 			MIN, 19200000),
@@ -788,7 +773,6 @@
 		.name = "gcc_usb30_master_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP5(
 			MIN, 50000000,
@@ -816,7 +800,6 @@
 		.name = "gcc_usb30_mock_utmi_clk_src",
 		.parent_names = gcc_parent_names_0,
 		.num_parents = 4,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP3(
 			MIN, 19200000,
@@ -841,7 +824,6 @@
 		.name = "gcc_usb3_phy_aux_clk_src",
 		.parent_names = gcc_parent_names_3,
 		.num_parents = 3,
-		.flags = CLK_SET_RATE_PARENT,
 		.ops = &clk_rcg2_ops,
 		VDD_CX_FMAX_MAP1(
 			MIN, 19200000),
@@ -1884,6 +1866,14 @@
 		return PTR_ERR(vdd_cx.regulator[0]);
 	}
 
+	vdd_cx_ao.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_cx_ao");
+	if (IS_ERR(vdd_cx_ao.regulator[0])) {
+		if (!(PTR_ERR(vdd_cx_ao.regulator[0]) == -EPROBE_DEFER))
+			dev_err(&pdev->dev,
+				"Unable to get vdd_cx_ao regulator\n");
+		return PTR_ERR(vdd_cx_ao.regulator[0]);
+	}
+
 	/* Register the dummy measurement clocks */
 	for (i = 0; i < ARRAY_SIZE(gcc_sdxpoorwills_hws); i++) {
 		clk = devm_clk_register(&pdev->dev, gcc_sdxpoorwills_hws[i]);
@@ -1922,6 +1912,15 @@
 }
 module_exit(gcc_sdxpoorwills_exit);
 
+static int gcc_cpuss_ahb_clk_update_rate(void)
+{
+	clk_set_rate(gcc_cpuss_ahb_clk.clkr.hw.clk, 19200000);
+	clk_set_rate(gcc_sys_noc_cpuss_ahb_clk.clkr.hw.clk, 19200000);
+
+	return 0;
+}
+late_initcall(gcc_cpuss_ahb_clk_update_rate);
+
 MODULE_DESCRIPTION("QTI GCC SDXPOORWILLS Driver");
 MODULE_LICENSE("GPL v2");
 MODULE_ALIAS("platform:gcc-sdxpoorwills");
diff --git a/drivers/cpuidle/lpm-levels-of.c b/drivers/cpuidle/lpm-levels-of.c
index 61c0ae8..fe3ef48 100644
--- a/drivers/cpuidle/lpm-levels-of.c
+++ b/drivers/cpuidle/lpm-levels-of.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -178,8 +178,8 @@
 	struct kernel_param kp;
 	struct lpm_level_avail *avail = get_avail_ptr(kobj, attr);
 
-	if (!avail)
-		pr_info("Error\n");
+	if (WARN_ON(!avail))
+		return -EINVAL;
 
 	kp.arg = &avail->latency_us;
 
@@ -197,8 +197,15 @@
 {
 	int ret = 0;
 	struct kernel_param kp;
+	struct lpm_level_avail *avail = get_avail_ptr(kobj, attr);
 
-	kp.arg = get_enabled_ptr(attr, get_avail_ptr(kobj, attr));
+	if (WARN_ON(!avail))
+		return -EINVAL;
+
+	kp.arg = get_enabled_ptr(attr, avail);
+	if (WARN_ON(!kp.arg))
+		return -EINVAL;
+
 	ret = param_get_bool(buf, &kp);
 	if (ret > 0) {
 		strlcat(buf, "\n", PAGE_SIZE);
@@ -453,10 +460,21 @@
 	if (ret)
 		goto fail;
 
+	key = "qcom,disable-prediction";
+	c->lpm_prediction = !(of_property_read_bool(node, key));
+
+	if (c->lpm_prediction) {
+		key = "qcom,clstr-tmr-add";
+		ret = of_property_read_u32(node, key, &c->tmr_add);
+		if (ret || c->tmr_add < TIMER_ADD_LOW ||
+					c->tmr_add > TIMER_ADD_HIGH)
+			c->tmr_add = DEFAULT_TIMER_ADD;
+	}
+
 	/* Set default_level to 0 as default */
 	c->default_level = 0;
 
-	return ret;
+	return 0;
 fail:
 	pr_err("Failed to read key: %s ret: %d\n", key, ret);
 
@@ -713,8 +731,28 @@
 	if (ret)
 		goto failed_parse_params;
 
-	key = "qcom,use-prediction";
-	cpu->lpm_prediction = of_property_read_bool(node, key);
+	key = "qcom,disable-prediction";
+	cpu->lpm_prediction = !(of_property_read_bool(node, key));
+
+	if (cpu->lpm_prediction) {
+		key = "qcom,ref-stddev";
+		ret = of_property_read_u32(node, key, &cpu->ref_stddev);
+		if (ret || cpu->ref_stddev < STDDEV_LOW ||
+					cpu->ref_stddev > STDDEV_HIGH)
+			cpu->ref_stddev = DEFAULT_STDDEV;
+
+		key = "qcom,tmr-add";
+		ret = of_property_read_u32(node, key, &cpu->tmr_add);
+		if (ret || cpu->tmr_add < TIMER_ADD_LOW ||
+					cpu->tmr_add > TIMER_ADD_HIGH)
+			cpu->tmr_add = DEFAULT_TIMER_ADD;
+
+		key = "qcom,ref-premature-cnt";
+		ret = of_property_read_u32(node, key, &cpu->ref_premature_cnt);
+		if (ret || cpu->ref_premature_cnt < PREMATURE_CNT_LOW ||
+				cpu->ref_premature_cnt > PREMATURE_CNT_HIGH)
+			cpu->ref_premature_cnt = DEFAULT_PREMATURE_CNT;
+	}
 
 	key = "parse_cpu";
 	ret = parse_cpu(node, cpu);
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 013b0c8..9ae640d 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -92,15 +92,6 @@
 static bool lpm_prediction = true;
 module_param_named(lpm_prediction, lpm_prediction, bool, 0664);
 
-static uint32_t ref_stddev = 500;
-module_param_named(ref_stddev, ref_stddev, uint, 0664);
-
-static uint32_t tmr_add = 1000;
-module_param_named(tmr_add, tmr_add, uint, 0664);
-
-static uint32_t ref_premature_cnt = 1;
-module_param_named(ref_premature_cnt, ref_premature_cnt, uint, 0664);
-
 static uint32_t bias_hyst;
 module_param_named(bias_hyst, bias_hyst, uint, 0664);
 
@@ -119,7 +110,7 @@
 static DEFINE_PER_CPU(struct lpm_cpu*, cpu_lpm);
 static bool suspend_in_progress;
 static struct hrtimer lpm_hrtimer;
-static struct hrtimer histtimer;
+static DEFINE_PER_CPU(struct hrtimer, histtimer);
 static struct lpm_debug *lpm_debug;
 static phys_addr_t lpm_debug_phys;
 static const int num_dbg_elements = 0x100;
@@ -348,7 +339,10 @@
 
 static void histtimer_cancel(void)
 {
-	hrtimer_try_to_cancel(&histtimer);
+	unsigned int cpu = raw_smp_processor_id();
+	struct hrtimer *cpu_histtimer = &per_cpu(histtimer, cpu);
+
+	hrtimer_try_to_cancel(cpu_histtimer);
 }
 
 static enum hrtimer_restart histtimer_fn(struct hrtimer *h)
@@ -364,9 +358,11 @@
 {
 	uint64_t time_ns = time_us * NSEC_PER_USEC;
 	ktime_t hist_ktime = ns_to_ktime(time_ns);
+	unsigned int cpu = raw_smp_processor_id();
+	struct hrtimer *cpu_histtimer = &per_cpu(histtimer, cpu);
 
-	histtimer.function = histtimer_fn;
-	hrtimer_start(&histtimer, hist_ktime, HRTIMER_MODE_REL_PINNED);
+	cpu_histtimer->function = histtimer_fn;
+	hrtimer_start(cpu_histtimer, hist_ktime, HRTIMER_MODE_REL_PINNED);
 }
 
 static void cluster_timer_init(struct lpm_cluster *cluster)
@@ -496,7 +492,7 @@
 	 * ignore one maximum sample and retry
 	 */
 	if (((avg > stddev * 6) && (divisor >= (MAXSAMPLES - 1)))
-					|| stddev <= ref_stddev) {
+					|| stddev <= cpu->ref_stddev) {
 		history->stime = ktime_to_us(ktime_get()) + avg;
 		return avg;
 	} else if (divisor  > (MAXSAMPLES - 1)) {
@@ -521,7 +517,7 @@
 					total += history->resi[i];
 				}
 			}
-			if (failed >= ref_premature_cnt) {
+			if (failed >= cpu->ref_premature_cnt) {
 				*idx_restrict = j;
 				do_div(total, failed);
 				for (i = 0; i < j; i++) {
@@ -545,8 +541,9 @@
 static inline void invalidate_predict_history(struct cpuidle_device *dev)
 {
 	struct lpm_history *history = &per_cpu(hist, dev->cpu);
+	struct lpm_cpu *lpm_cpu = per_cpu(cpu_lpm, dev->cpu);
 
-	if (!lpm_prediction)
+	if (!lpm_prediction || !lpm_cpu->lpm_prediction)
 		return;
 
 	if (history->hinvalid) {
@@ -561,8 +558,9 @@
 	struct lpm_history *history;
 	int i;
 	unsigned int cpu;
+	struct lpm_cpu *lpm_cpu = per_cpu(cpu_lpm, raw_smp_processor_id());
 
-	if (!lpm_prediction)
+	if (!lpm_prediction || !lpm_cpu->lpm_prediction)
 		return;
 
 	for_each_possible_cpu(cpu) {
@@ -681,8 +679,8 @@
 	if ((predicted || (idx_restrict != (cpu->nlevels + 1)))
 			&& ((best_level >= 0)
 			&& (best_level < (cpu->nlevels-1)))) {
-		htime = predicted + tmr_add;
-		if (htime == tmr_add)
+		htime = predicted + cpu->tmr_add;
+		if (htime == cpu->tmr_add)
 			htime = idx_restrict_time;
 		else if (htime > max_residency[best_level])
 			htime = max_residency[best_level];
@@ -746,14 +744,14 @@
 			next_event.tv64 = next_event_c->tv64;
 		}
 
-		if (from_idle && lpm_prediction) {
+		if (from_idle && lpm_prediction && cluster->lpm_prediction) {
 			history = &per_cpu(hist, cpu);
 			if (history->stime && (history->stime < prediction))
 				prediction = history->stime;
 		}
 	}
 
-	if (from_idle && lpm_prediction) {
+	if (from_idle && lpm_prediction && cluster->lpm_prediction) {
 		if (prediction > ktime_to_us(ktime_get()))
 			*pred_time = prediction - ktime_to_us(ktime_get());
 	}
@@ -772,7 +770,7 @@
 	struct cluster_history *history = &cluster->history;
 	int64_t cur_time = ktime_to_us(ktime_get());
 
-	if (!lpm_prediction)
+	if (!lpm_prediction || !cluster->lpm_prediction)
 		return 0;
 
 	if (history->hinvalid) {
@@ -847,7 +845,7 @@
 	struct lpm_cluster *cluster =
 			container_of(history, struct lpm_cluster, history);
 
-	if (!lpm_prediction)
+	if (!lpm_prediction || !cluster->lpm_prediction)
 		return;
 
 	if ((history->entry_idx == -1) || (history->entry_idx == idx)) {
@@ -908,7 +906,7 @@
 	struct lpm_cluster *cluster = lpm_root_node;
 	struct list_head *list;
 
-	if (!lpm_prediction)
+	if (!lpm_prediction || !cluster->lpm_prediction)
 		return;
 
 	clear_cl_history_each(&cluster->history);
@@ -955,17 +953,6 @@
 		latency_us = pm_qos_request_for_cpumask(PM_QOS_CPU_DMA_LATENCY,
 							&mask);
 
-	/*
-	 * If atleast one of the core in the cluster is online, the cluster
-	 * low power modes should be determined by the idle characteristics
-	 * even if the last core enters the low power mode as a part of
-	 * hotplug.
-	 */
-
-	if (!from_idle && num_online_cpus() > 1 &&
-		cpumask_intersects(&cluster->child_cpus, cpu_online_mask))
-		from_idle = true;
-
 	for (i = 0; i < cluster->nlevels; i++) {
 		struct lpm_cluster_level *level = &cluster->levels[i];
 		struct power_params *pwr_params = &level->pwr;
@@ -1045,14 +1032,24 @@
 			cluster->child_cpus.bits[0], from_idle);
 		lpm_stats_cluster_enter(cluster->stats, idx);
 
-		if (from_idle && lpm_prediction)
+		if (from_idle && lpm_prediction && cluster->lpm_prediction)
 			update_cluster_history_time(&cluster->history, idx,
 						ktime_to_us(ktime_get()));
 	}
 
 	if (level->notify_rpm) {
+		/*
+		 * Print the clocks which are enabled during system suspend
+		 * This debug information is useful to know which are the
+		 * clocks that are enabled and preventing the system level
+		 * LPMs(XO and Vmin).
+		 */
+		if (!from_idle)
+			clock_debug_print_enabled(true);
+
 		cpu = get_next_online_cpu(from_idle);
 		cpumask_copy(&cpumask, cpumask_of(cpu));
+
 		clear_predict_history();
 		clear_cl_predict_history();
 		if (sys_pm_ops && sys_pm_ops->enter)
@@ -1067,7 +1064,8 @@
 	if (predicted && (idx < (cluster->nlevels - 1))) {
 		struct power_params *pwr_params = &cluster->levels[idx].pwr;
 
-		clusttimer_start(cluster, pwr_params->max_residency + tmr_add);
+		clusttimer_start(cluster, pwr_params->max_residency +
+							cluster->tmr_add);
 	}
 
 	return 0;
@@ -1121,7 +1119,8 @@
 						&cluster->levels[0].pwr;
 
 			clusttimer_start(cluster,
-					pwr_params->max_residency + tmr_add);
+					pwr_params->max_residency +
+					cluster->tmr_add);
 
 			goto failed;
 		}
@@ -1336,8 +1335,9 @@
 {
 	struct lpm_history *history = &per_cpu(hist, dev->cpu);
 	uint32_t tmr = 0;
+	struct lpm_cpu *lpm_cpu = per_cpu(cpu_lpm, dev->cpu);
 
-	if (!lpm_prediction)
+	if (!lpm_prediction || !lpm_cpu->lpm_prediction)
 		return;
 
 	if (history->htmr_wkup) {
@@ -1395,13 +1395,37 @@
 	update_history(dev, idx);
 	trace_cpu_idle_exit(idx, success);
 	local_irq_enable();
-	if (lpm_prediction) {
+	if (lpm_prediction && cpu->lpm_prediction) {
 		histtimer_cancel();
 		clusttimer_cancel();
 	}
 	return idx;
 }
 
+static void lpm_cpuidle_freeze(struct cpuidle_device *dev,
+		struct cpuidle_driver *drv, int idx)
+{
+	struct lpm_cpu *cpu = per_cpu(cpu_lpm, dev->cpu);
+	const struct cpumask *cpumask = get_cpu_mask(dev->cpu);
+
+	for (; idx >= 0; idx--) {
+		if (lpm_cpu_mode_allow(dev->cpu, idx, false))
+			break;
+	}
+	if (idx < 0) {
+		pr_err("Failed suspend\n");
+		return;
+	}
+
+	cpu_prepare(cpu, idx, true);
+	cluster_prepare(cpu->parent, cpumask, idx, false, 0);
+
+	psci_enter_sleep(cpu, idx, false);
+
+	cluster_unprepare(cpu->parent, cpumask, idx, false, 0);
+	cpu_unprepare(cpu, idx, true);
+}
+
 #ifdef CONFIG_CPU_IDLE_MULTIPLE_DRIVERS
 static int cpuidle_register_cpu(struct cpuidle_driver *drv,
 		struct cpumask *mask)
@@ -1489,6 +1513,8 @@
 			st->power_usage = cpu_level->pwr.ss_power;
 			st->target_residency = 0;
 			st->enter = lpm_cpuidle_enter;
+			if (i == lpm_cpu->nlevels - 1)
+				st->enter_freeze = lpm_cpuidle_freeze;
 		}
 
 		lpm_cpu->drv->state_count = lpm_cpu->nlevels;
@@ -1623,14 +1649,6 @@
 	cpu_prepare(lpm_cpu, idx, false);
 	cluster_prepare(cluster, cpumask, idx, false, 0);
 
-	/*
-	 * Print the clocks which are enabled during system suspend
-	 * This debug information is useful to know which are the
-	 * clocks that are enabled and preventing the system level
-	 * LPMs(XO and Vmin).
-	 */
-	clock_debug_print_enabled(true);
-
 	psci_enter_sleep(lpm_cpu, idx, false);
 
 	cluster_unprepare(cluster, cpumask, idx, false, 0);
@@ -1645,10 +1663,17 @@
 	.wake = lpm_suspend_wake,
 };
 
+static const struct platform_freeze_ops lpm_freeze_ops = {
+	.prepare = lpm_suspend_prepare,
+	.restore = lpm_suspend_wake,
+};
+
 static int lpm_probe(struct platform_device *pdev)
 {
 	int ret;
 	int size;
+	unsigned int cpu;
+	struct hrtimer *cpu_histtimer;
 	struct kobject *module_kobj = NULL;
 	struct md_region md_entry;
 
@@ -1671,8 +1696,13 @@
 	 * how late lpm_levels gets initialized.
 	 */
 	suspend_set_ops(&lpm_suspend_ops);
+	freeze_set_ops(&lpm_freeze_ops);
 	hrtimer_init(&lpm_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-	hrtimer_init(&histtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	for_each_possible_cpu(cpu) {
+		cpu_histtimer = &per_cpu(histtimer, cpu);
+		hrtimer_init(cpu_histtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	}
+
 	cluster_timer_init(lpm_root_node);
 
 	size = num_dbg_elements * sizeof(struct lpm_debug);
diff --git a/drivers/cpuidle/lpm-levels.h b/drivers/cpuidle/lpm-levels.h
index 1ff69c8..0b598c0 100644
--- a/drivers/cpuidle/lpm-levels.h
+++ b/drivers/cpuidle/lpm-levels.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
@@ -16,6 +16,15 @@
 #define NR_LPM_LEVELS 8
 #define MAXSAMPLES 5
 #define CLUST_SMPL_INVLD_TIME 40000
+#define DEFAULT_PREMATURE_CNT 3
+#define DEFAULT_STDDEV 100
+#define DEFAULT_TIMER_ADD 100
+#define TIMER_ADD_LOW 100
+#define TIMER_ADD_HIGH 1500
+#define STDDEV_LOW 100
+#define STDDEV_HIGH 1000
+#define PREMATURE_CNT_LOW 1
+#define PREMATURE_CNT_HIGH 5
 
 struct power_params {
 	uint32_t latency_us;		/* Enter + Exit latency */
@@ -43,6 +52,9 @@
 	int nlevels;
 	unsigned int psci_mode_shift;
 	unsigned int psci_mode_mask;
+	uint32_t ref_stddev;
+	uint32_t ref_premature_cnt;
+	uint32_t tmr_add;
 	bool lpm_prediction;
 	struct cpuidle_driver *drv;
 	struct lpm_cluster *parent;
@@ -97,6 +109,8 @@
 	int min_child_level;
 	int default_level;
 	int last_level;
+	uint32_t tmr_add;
+	bool lpm_prediction;
 	struct list_head cpu;
 	spinlock_t sync_lock;
 	struct cpumask child_cpus;
diff --git a/drivers/crypto/msm/Makefile b/drivers/crypto/msm/Makefile
index 9ecb646..b712fc1 100644
--- a/drivers/crypto/msm/Makefile
+++ b/drivers/crypto/msm/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_CRYPTO_DEV_QCOM_MSM_QCE) += qce50.o
 obj-$(CONFIG_CRYPTO_DEV_QCEDEV) += qcedev.o
+obj-$(CONFIG_CRYPTO_DEV_QCEDEV) += qcedev_smmu.o
 obj-$(CONFIG_CRYPTO_DEV_QCRYPTO) += qcrypto.o
 obj-$(CONFIG_CRYPTO_DEV_OTA_CRYPTO) += ota_crypto.o
 obj-$(CONFIG_CRYPTO_DEV_QCOM_ICE) += ice.o
diff --git a/drivers/crypto/msm/compat_qcedev.c b/drivers/crypto/msm/compat_qcedev.c
index d61b6f3..41b13a7d 100644
--- a/drivers/crypto/msm/compat_qcedev.c
+++ b/drivers/crypto/msm/compat_qcedev.c
@@ -1,7 +1,7 @@
 /*
  * QTI CE 32-bit compatibility syscall for 64-bit systems
  *
- * 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
@@ -254,6 +254,75 @@
 	return err;
 }
 
+static int compat_xfer_qcedev_map_buf_req(
+			struct compat_qcedev_map_buf_req __user *data32,
+			struct qcedev_map_buf_req __user *data, bool to_get)
+{
+	int rc = 0, i = 0, fd = -1;
+	uint32_t fd_size, fd_offset, num_fds, buf_vaddr;
+
+	if (to_get) {
+		/* copy from compat struct */
+		for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
+			rc |= get_user(fd, &data32->fd[i]);
+			rc |= put_user(fd, &data->fd[i]);
+			rc |= get_user(fd_size, &data32->fd_size[i]);
+			rc |= put_user(fd_size, &data->fd_size[i]);
+			rc |= get_user(fd_offset, &data32->fd_offset[i]);
+			rc |= put_user(fd_offset, &data->fd_offset[i]);
+			rc |= get_user(buf_vaddr, &data32->buf_vaddr[i]);
+			rc |= put_user(buf_vaddr, &data->buf_vaddr[i]);
+		}
+
+		rc |= get_user(num_fds, &data32->num_fds);
+		rc |= put_user(num_fds, &data->num_fds);
+	} else {
+		/* copy to compat struct */
+		for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
+			rc |= get_user(fd, &data->fd[i]);
+			rc |= put_user(fd, &data32->fd[i]);
+			rc |= get_user(fd_size, &data->fd_size[i]);
+			rc |= put_user(fd_size, &data32->fd_size[i]);
+			rc |= get_user(fd_offset, &data->fd_offset[i]);
+			rc |= put_user(fd_offset, &data32->fd_offset[i]);
+			rc |= get_user(buf_vaddr, &data->buf_vaddr[i]);
+			rc |= put_user(buf_vaddr, &data32->buf_vaddr[i]);
+		}
+		rc |= get_user(num_fds, &data->num_fds);
+		rc |= put_user(num_fds, &data32->num_fds);
+	}
+
+	return rc;
+}
+
+static int compat_xfer_qcedev_unmap_buf_req(
+			struct compat_qcedev_unmap_buf_req __user *data32,
+			struct qcedev_unmap_buf_req __user *data, bool to_get)
+{
+	int i = 0, rc = 0, fd = -1;
+	uint32_t num_fds;
+
+	if (to_get) {
+		/* copy from compat struct */
+		for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
+			rc |= get_user(fd, &data32->fd[i]);
+			rc |= put_user(fd, &data->fd[i]);
+		}
+		rc |= get_user(num_fds, &data32->num_fds);
+		rc |= put_user(num_fds, &data->num_fds);
+	} else {
+		/* copy to compat struct */
+		for (i = 0; i < QCEDEV_MAX_BUFFERS; i++) {
+			rc |= get_user(fd, &data->fd[i]);
+			rc |= put_user(fd, &data32->fd[i]);
+		}
+		rc |= get_user(num_fds, &data->num_fds);
+		rc |= put_user(num_fds, &data32->num_fds);
+	}
+	return rc;
+}
+
+
 static int compat_get_qcedev_sha_op_req(
 		struct compat_qcedev_sha_op_req __user *data32,
 		struct qcedev_sha_op_req __user *data)
@@ -359,6 +428,10 @@
 		return QCEDEV_IOCTL_GET_SHA_REQ;
 	case COMPAT_QCEDEV_IOCTL_GET_CMAC_REQ:
 		return QCEDEV_IOCTL_GET_CMAC_REQ;
+	case COMPAT_QCEDEV_IOCTL_MAP_BUF_REQ:
+		return QCEDEV_IOCTL_MAP_BUF_REQ;
+	case COMPAT_QCEDEV_IOCTL_UNMAP_BUF_REQ:
+		return QCEDEV_IOCTL_UNMAP_BUF_REQ;
 	default:
 		return cmd;
 	}
@@ -412,6 +485,46 @@
 		err = compat_put_qcedev_sha_op_req(data32, data);
 		return ret ? ret : err;
 	}
+	case COMPAT_QCEDEV_IOCTL_MAP_BUF_REQ: {
+		struct compat_qcedev_map_buf_req __user *data32;
+		struct qcedev_map_buf_req __user *data;
+		int err;
+
+		data32 = compat_ptr(arg);
+		data = compat_alloc_user_space(sizeof(*data));
+		if (!data)
+			return -EINVAL;
+
+		err = compat_xfer_qcedev_map_buf_req(data32, data, true);
+		if (err)
+			return err;
+
+		ret = qcedev_ioctl(file, convert_cmd(cmd), (unsigned long)data);
+		err = compat_xfer_qcedev_map_buf_req(data32, data, false);
+		return ret ? ret : err;
+
+		break;
+	}
+	case COMPAT_QCEDEV_IOCTL_UNMAP_BUF_REQ: {
+		struct compat_qcedev_unmap_buf_req __user *data32;
+		struct qcedev_unmap_buf_req __user *data;
+		int err;
+
+		data32 = compat_ptr(arg);
+		data = compat_alloc_user_space(sizeof(*data));
+		if (!data)
+			return -EINVAL;
+
+		err = compat_xfer_qcedev_unmap_buf_req(data32, data, true);
+		if (err)
+			return err;
+
+		ret = qcedev_ioctl(file, convert_cmd(cmd), (unsigned long)data);
+		err = compat_xfer_qcedev_unmap_buf_req(data32, data, false);
+		return ret ? ret : err;
+
+		break;
+	}
 	default:
 		return -ENOIOCTLCMD;
 	}
diff --git a/drivers/crypto/msm/compat_qcedev.h b/drivers/crypto/msm/compat_qcedev.h
index 6c041cb..4cefd0a 100644
--- a/drivers/crypto/msm/compat_qcedev.h
+++ b/drivers/crypto/msm/compat_qcedev.h
@@ -151,6 +151,33 @@
 	enum qcedev_sha_alg_enum		alg;
 };
 
+/**
+ * struct compact_qcedev_map_buf_req - Holds the mapping request information
+ * fd (IN):            Array of fds.
+ * num_fds (IN):       Number of fds in fd[].
+ * fd_size (IN):       Array of sizes corresponding to each fd in fd[].
+ * fd_offset (IN):     Array of offset corresponding to each fd in fd[].
+ * vaddr (OUT):        Array of mapped virtual address corresponding to
+ *                     each fd in fd[].
+ */
+struct compat_qcedev_map_buf_req {
+	compat_long_t	fd[QCEDEV_MAX_BUFFERS];
+	compat_ulong_t	num_fds;
+	compat_ulong_t	fd_size[QCEDEV_MAX_BUFFERS];
+	compat_ulong_t	fd_offset[QCEDEV_MAX_BUFFERS];
+	compat_u64      buf_vaddr[QCEDEV_MAX_BUFFERS];
+};
+
+/**
+ * struct compat_qcedev_unmap_buf_req - Holds the hashing request information
+ * fd (IN):	       Array of fds to unmap
+ * num_fds (IN):       Number of fds in fd[].
+ */
+struct	compat_qcedev_unmap_buf_req {
+	compat_long_t	fd[QCEDEV_MAX_BUFFERS];
+	compat_ulong_t	num_fds;
+};
+
 struct file;
 extern long compat_qcedev_ioctl(struct file *file,
 			unsigned int cmd, unsigned long arg);
@@ -173,6 +200,9 @@
 	_IO(QCEDEV_IOC_MAGIC, 8)
 #define COMPAT_QCEDEV_IOCTL_GET_CMAC_REQ	\
 	_IOWR(QCEDEV_IOC_MAGIC, 9, struct compat_qcedev_sha_op_req)
-
+#define COMPAT_QCEDEV_IOCTL_MAP_BUF_REQ	\
+	_IOWR(QCEDEV_IOC_MAGIC, 10, struct compat_qcedev_map_buf_req)
+#define COMPAT_QCEDEV_IOCTL_UNMAP_BUF_REQ \
+	_IOWR(QCEDEV_IOC_MAGIC, 11, struct compat_qcedev_unmap_buf_req)
 #endif /* CONFIG_COMPAT */
 #endif /* _UAPI_COMPAT_QCEDEV__H */
diff --git a/drivers/crypto/msm/ice.c b/drivers/crypto/msm/ice.c
index 6fa91ae..3aa75aa 100644
--- a/drivers/crypto/msm/ice.c
+++ b/drivers/crypto/msm/ice.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -74,6 +74,9 @@
 #define QCOM_ICE_MAX_BIST_CHECK_COUNT 100
 #define QCOM_ICE_UFS		10
 #define QCOM_ICE_SDCC		20
+#define QCOM_ICE_ENCRYPT	0x1
+#define QCOM_ICE_DECRYPT	0x2
+#define QCOM_SECT_LEN_IN_BYTE	512
 
 struct ice_clk_info {
 	struct list_head list;
@@ -123,6 +126,11 @@
 	ktime_t			ice_reset_complete_time;
 };
 
+static int ice_fde_flag;
+static unsigned long userdata_start;
+static unsigned long userdata_end;
+static struct ice_crypto_setting ice_data;
+
 static int qti_ice_setting_config(struct request *req,
 		struct platform_device *pdev,
 		struct ice_crypto_setting *crypto_data,
@@ -149,20 +157,50 @@
 		memcpy(&setting->crypto_data, crypto_data,
 				sizeof(setting->crypto_data));
 
-		if (rq_data_dir(req) == WRITE)
+		if (rq_data_dir(req) == WRITE &&
+				(ice_fde_flag & QCOM_ICE_ENCRYPT))
 			setting->encr_bypass = false;
-		else if (rq_data_dir(req) == READ)
+		else if (rq_data_dir(req) == READ &&
+				(ice_fde_flag & QCOM_ICE_DECRYPT))
 			setting->decr_bypass = false;
 		else {
 			/* Should I say BUG_ON */
 			setting->encr_bypass = true;
 			setting->decr_bypass = true;
+			pr_debug("%s direction unknown", __func__);
 		}
 	}
 
 	return 0;
 }
 
+void qcom_ice_set_fde_flag(int flag)
+{
+	ice_fde_flag = flag;
+	pr_debug("%s read_write setting %d\n", __func__, ice_fde_flag);
+}
+EXPORT_SYMBOL(qcom_ice_set_fde_flag);
+
+int qcom_ice_set_fde_conf(sector_t s_sector, sector_t size,
+					int index, int mode)
+{
+	userdata_start = s_sector;
+	userdata_end = s_sector + size;
+	if (INT_MAX - s_sector < size) {
+		WARN_ON(1);
+		return -EINVAL;
+	}
+	ice_data.key_index = index;
+	ice_data.algo_mode = mode;
+	ice_data.key_size = ICE_CRYPTO_KEY_SIZE_256;
+	ice_data.key_mode = ICE_CRYPTO_USE_LUT_SW_KEY;
+
+	pr_debug("%s sector info set start %lu end %lu\n", __func__,
+		userdata_start, userdata_end);
+	return 0;
+}
+EXPORT_SYMBOL(qcom_ice_set_fde_conf);
+
 static int qcom_ice_enable_clocks(struct ice_device *, bool);
 
 #ifdef CONFIG_MSM_BUS_SCALING
@@ -1445,11 +1483,10 @@
 		struct request *req,
 		struct ice_data_setting *setting, bool async)
 {
-	struct ice_crypto_setting *crypto_data;
 	struct ice_crypto_setting pfk_crypto_data = {0};
-	union map_info *info;
 	int ret = 0;
 	bool is_pfe = false;
+	sector_t data_size;
 
 	if (!pdev || !req || !setting) {
 		pr_err("%s: Invalid params passed\n", __func__);
@@ -1484,28 +1521,22 @@
 				&pfk_crypto_data, setting);
 	}
 
+	if (ice_fde_flag == 0)
+		return 0;
+
+	if ((req->__sector >= userdata_start) &&
+			(req->__sector < userdata_end)) {
 	/*
-	 * info field in req->end_io_data could be used by mulitple dm or
-	 * non-dm entities. To ensure that we are running operation on dm
-	 * based request, check BIO_DONT_FREE flag
+	 * Ugly hack to address non-block-size aligned userdata end address in
+	 * eMMC based devices.
 	 */
-	if (bio_flagged(req->bio, BIO_INLINECRYPT)) {
-		info = dm_get_rq_mapinfo(req);
-		if (!info) {
-			pr_debug("%s info not available in request\n",
-				 __func__);
+		data_size = req->__data_len/QCOM_SECT_LEN_IN_BYTE;
+
+		if ((req->__sector + data_size) > userdata_end)
 			return 0;
-		}
-
-		crypto_data = (struct ice_crypto_setting *)info->ptr;
-		if (!crypto_data) {
-			pr_err("%s crypto_data not available in request\n",
-				 __func__);
-			return -EINVAL;
-		}
-
-		return qti_ice_setting_config(req, pdev,
-				crypto_data, setting);
+		else
+			return qti_ice_setting_config(req, pdev,
+				&ice_data, setting);
 	}
 
 	/*
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 958fb91..c8d1158 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -1,7 +1,7 @@
 /*
  * QTI CE device driver.
  *
- * Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-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,7 @@
 #include <crypto/hash.h>
 #include "qcedevi.h"
 #include "qce.h"
+#include "qcedev_smmu.h"
 
 #include <linux/compat.h>
 #include "compat_qcedev.h"
@@ -59,6 +60,14 @@
 static DEFINE_MUTEX(qcedev_sent_bw_req);
 static DEFINE_MUTEX(hash_access_lock);
 
+MODULE_DEVICE_TABLE(of, qcedev_match);
+
+static const struct of_device_id qcedev_match[] = {
+	{	.compatible = "qcom,qcedev"},
+	{	.compatible = "qcom,qcedev,context-bank"},
+	{}
+};
+
 static int qcedev_control_clocks(struct qcedev_control *podev, bool enable)
 {
 	unsigned int control_flag;
@@ -259,6 +268,9 @@
 	file->private_data = handle;
 	if (podev->platform_support.bus_scale_table != NULL)
 		qcedev_ce_high_bw_req(podev, true);
+
+	mutex_init(&handle->registeredbufs.lock);
+	INIT_LIST_HEAD(&handle->registeredbufs.list);
 	return 0;
 }
 
@@ -1857,6 +1869,62 @@
 		}
 		break;
 
+	case QCEDEV_IOCTL_MAP_BUF_REQ:
+		{
+			unsigned long long vaddr = 0;
+			struct qcedev_map_buf_req map_buf = { {0} };
+			int i = 0;
+
+			if (copy_from_user(&map_buf,
+					(void __user *)arg, sizeof(map_buf)))
+				return -EFAULT;
+
+			for (i = 0; i < map_buf.num_fds; i++) {
+				err = qcedev_check_and_map_buffer(handle,
+						map_buf.fd[i],
+						map_buf.fd_offset[i],
+						map_buf.fd_size[i],
+						&vaddr);
+				if (err) {
+					pr_err(
+						"%s: err: failed to map fd(%d) - %d\n",
+						__func__, map_buf.fd[i], err);
+					return err;
+				}
+				map_buf.buf_vaddr[i] = vaddr;
+				pr_info("%s: info: vaddr = %llx\n",
+					__func__, vaddr);
+			}
+
+			if (copy_to_user((void __user *)arg, &map_buf,
+					sizeof(map_buf)))
+				return -EFAULT;
+			break;
+		}
+
+	case QCEDEV_IOCTL_UNMAP_BUF_REQ:
+		{
+			struct qcedev_unmap_buf_req unmap_buf = { { 0 } };
+			int i = 0;
+
+			if (copy_from_user(&unmap_buf,
+					(void __user *)arg, sizeof(unmap_buf)))
+				return -EFAULT;
+
+			for (i = 0; i < unmap_buf.num_fds; i++) {
+				err = qcedev_check_and_unmap_buffer(handle,
+						unmap_buf.fd[i]);
+				if (err) {
+					pr_err(
+						"%s: err: failed to unmap fd(%d) - %d\n",
+						 __func__,
+						unmap_buf.fd[i], err);
+					return err;
+				}
+			}
+			break;
+		}
+
 	default:
 		return -ENOTTY;
 	}
@@ -1864,7 +1932,7 @@
 	return err;
 }
 
-static int qcedev_probe(struct platform_device *pdev)
+static int qcedev_probe_device(struct platform_device *pdev)
 {
 	void *handle = NULL;
 	int rc = 0;
@@ -1877,6 +1945,8 @@
 	INIT_LIST_HEAD(&podev->ready_commands);
 	podev->active_command = NULL;
 
+	INIT_LIST_HEAD(&podev->context_banks);
+
 	spin_lock_init(&podev->lock);
 
 	tasklet_init(&podev->done_tasklet, req_done, (unsigned long)podev);
@@ -1934,11 +2004,33 @@
 	}
 
 	rc = misc_register(&podev->miscdevice);
-	if (rc >= 0)
-		return 0;
+	if (rc) {
+		pr_err("%s: err: register failed for misc: %d\n", __func__, rc);
+		goto exit_qce_close;
+	}
+
+	podev->mem_client = qcedev_mem_new_client(MEM_ION);
+	if (!podev->mem_client) {
+		pr_err("%s: err: qcedev_mem_new_client failed\n", __func__);
+		goto err;
+	}
+
+	rc = of_platform_populate(pdev->dev.of_node, qcedev_match,
+			NULL, &pdev->dev);
+	if (rc) {
+		pr_err("%s: err: of_platform_populate failed: %d\n",
+			__func__, rc);
+		goto err;
+	}
+
+	return 0;
+
+err:
+	if (podev->mem_client)
+		qcedev_mem_delete_client(podev->mem_client);
+	podev->mem_client = NULL;
 
 	misc_deregister(&podev->miscdevice);
-
 exit_qce_close:
 	if (handle)
 		qce_close(handle);
@@ -1947,11 +2039,23 @@
 exit_unregister_bus_scale:
 	if (podev->platform_support.bus_scale_table != NULL)
 		msm_bus_scale_unregister_client(podev->bus_scale_handle);
+	podev->bus_scale_handle = 0;
 	platform_set_drvdata(pdev, NULL);
 	podev->pdev = NULL;
 	podev->qce = NULL;
 
 	return rc;
+}
+
+static int qcedev_probe(struct platform_device *pdev)
+{
+	if (of_device_is_compatible(pdev->dev.of_node, "qcom,qcedev"))
+		return qcedev_probe_device(pdev);
+	else if (of_device_is_compatible(pdev->dev.of_node,
+		"qcom,qcedev,context-bank"))
+		return qcedev_parse_context_bank(pdev);
+
+	return -EINVAL;
 };
 
 static int qcedev_remove(struct platform_device *pdev)
@@ -2017,12 +2121,6 @@
 	return 0;
 }
 
-static const struct of_device_id qcedev_match[] = {
-	{	.compatible = "qcom,qcedev",
-	},
-	{}
-};
-
 static struct platform_driver qcedev_plat_driver = {
 	.probe = qcedev_probe,
 	.remove = qcedev_remove,
diff --git a/drivers/crypto/msm/qcedev_smmu.c b/drivers/crypto/msm/qcedev_smmu.c
new file mode 100644
index 0000000..c99b493
--- /dev/null
+++ b/drivers/crypto/msm/qcedev_smmu.c
@@ -0,0 +1,546 @@
+/* Qti (or) Qualcomm Technologies Inc CE device driver.
+ *
+ * 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 <asm/dma-iommu.h>
+#include <linux/dma-mapping.h>
+#include <linux/list.h>
+#include <linux/qcedev.h>
+#include "qcedevi.h"
+#include "qcedev_smmu.h"
+#include "soc/qcom/secure_buffer.h"
+
+static bool compare_ion_buffers(struct qcedev_mem_client *mem_client,
+					struct ion_handle *hndl, int fd);
+
+static int qcedev_setup_context_bank(struct context_bank_info *cb,
+				struct device *dev)
+{
+	int rc = 0;
+	int secure_vmid = VMID_INVAL;
+	struct bus_type *bus;
+
+	if (!dev || !cb) {
+		pr_err("%s err: invalid input params\n", __func__);
+		return -EINVAL;
+	}
+	cb->dev = dev;
+
+	bus = cb->dev->bus;
+	if (IS_ERR_OR_NULL(bus)) {
+		pr_err("%s err: failed to get bus type\n", __func__);
+		rc = PTR_ERR(bus) ?: -ENODEV;
+		goto remove_cb;
+	}
+
+	cb->mapping = arm_iommu_create_mapping(bus, cb->start_addr, cb->size);
+	if (IS_ERR_OR_NULL(cb->mapping)) {
+		pr_err("%s err: failed to create mapping\n", __func__);
+		rc = PTR_ERR(cb->mapping) ?: -ENODEV;
+		goto remove_cb;
+	}
+
+	if (cb->is_secure) {
+		/* Hardcoded since we only have this vmid.*/
+		secure_vmid = VMID_CP_BITSTREAM;
+		rc = iommu_domain_set_attr(cb->mapping->domain,
+			DOMAIN_ATTR_SECURE_VMID, &secure_vmid);
+		if (rc) {
+			pr_err("%s err: programming secure vmid failed %s %d\n",
+				__func__, dev_name(dev), rc);
+			goto release_mapping;
+		}
+	}
+
+	rc = arm_iommu_attach_device(cb->dev, cb->mapping);
+	if (rc) {
+		pr_err("%s err: Failed to attach %s - %d\n",
+			__func__, dev_name(dev), rc);
+		goto release_mapping;
+	}
+
+	pr_info("%s Attached %s and create mapping\n", __func__, dev_name(dev));
+	pr_info("%s Context Bank name:%s, is_secure:%d, start_addr:%#x\n",
+			__func__, cb->name, cb->is_secure, cb->start_addr);
+	pr_info("%s size:%#x, dev:%pK, mapping:%pK\n", __func__, cb->size,
+			cb->dev, cb->mapping);
+	return rc;
+
+release_mapping:
+	arm_iommu_release_mapping(cb->mapping);
+remove_cb:
+	return rc;
+}
+
+int qcedev_parse_context_bank(struct platform_device *pdev)
+{
+	struct qcedev_control *podev;
+	struct context_bank_info *cb = NULL;
+	struct device_node *np = NULL;
+	int rc = 0;
+
+	if (!pdev) {
+		pr_err("%s err: invalid platform devices\n", __func__);
+		return -EINVAL;
+	}
+	if (!pdev->dev.parent) {
+		pr_err("%s err: failed to find a parent for %s\n",
+			__func__, dev_name(&pdev->dev));
+		return -EINVAL;
+	}
+
+	podev = dev_get_drvdata(pdev->dev.parent);
+	np = pdev->dev.of_node;
+	cb = devm_kzalloc(&pdev->dev, sizeof(*cb), GFP_KERNEL);
+	if (!cb) {
+		pr_err("%s ERROR = Failed to allocate cb\n", __func__);
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&cb->list);
+	list_add_tail(&cb->list, &podev->context_banks);
+
+	rc = of_property_read_string(np, "label", &cb->name);
+	if (rc)
+		pr_debug("%s ERROR = Unable to read label\n", __func__);
+
+	rc = of_property_read_u32(np, "virtual-addr", &cb->start_addr);
+	if (rc) {
+		pr_err("%s err: cannot read virtual region addr %d\n",
+			__func__, rc);
+		goto err_setup_cb;
+	}
+
+	rc = of_property_read_u32(np, "virtual-size", &cb->size);
+	if (rc) {
+		pr_err("%s err: cannot read virtual region size %d\n",
+			__func__, rc);
+		goto err_setup_cb;
+	}
+
+	cb->is_secure = of_property_read_bool(np, "qcom,secure-context-bank");
+
+	rc = qcedev_setup_context_bank(cb, &pdev->dev);
+	if (rc) {
+		pr_err("%s err: cannot setup context bank %d\n", __func__, rc);
+		goto err_setup_cb;
+	}
+
+	return 0;
+
+err_setup_cb:
+	devm_kfree(&pdev->dev, cb);
+	list_del(&cb->list);
+	return rc;
+}
+
+struct qcedev_mem_client *qcedev_mem_new_client(enum qcedev_mem_type mtype)
+{
+	struct qcedev_mem_client *mem_client = NULL;
+	struct ion_client *clnt = NULL;
+
+	switch (mtype) {
+	case MEM_ION:
+		clnt = msm_ion_client_create("qcedev_client");
+		if (!clnt)
+			pr_err("%s: err: failed to allocate ion client\n",
+				__func__);
+		break;
+
+	default:
+		pr_err("%s: err: Mem type not supported\n", __func__);
+	}
+
+	if (clnt) {
+		mem_client = kzalloc(sizeof(*mem_client), GFP_KERNEL);
+		if (!mem_client)
+			goto err;
+		mem_client->mtype = mtype;
+		mem_client->client = clnt;
+	}
+
+	return mem_client;
+
+err:
+	if (clnt)
+		ion_client_destroy(clnt);
+	return NULL;
+}
+
+void qcedev_mem_delete_client(struct qcedev_mem_client *mem_client)
+{
+	if (mem_client && mem_client->client)
+		ion_client_destroy(mem_client->client);
+
+	kfree(mem_client);
+}
+
+static bool is_iommu_present(struct qcedev_handle *qce_hndl)
+{
+	return !list_empty(&qce_hndl->cntl->context_banks);
+}
+
+static struct context_bank_info *get_context_bank(
+		struct qcedev_handle *qce_hndl, bool is_secure)
+{
+	struct qcedev_control *podev = qce_hndl->cntl;
+	struct context_bank_info *cb = NULL, *match = NULL;
+
+	list_for_each_entry(cb, &podev->context_banks, list) {
+		if (cb->is_secure == is_secure) {
+			match = cb;
+			break;
+		}
+	}
+	return match;
+}
+
+static int ion_map_buffer(struct qcedev_handle *qce_hndl,
+		struct qcedev_mem_client *mem_client, int fd,
+		unsigned int fd_size, struct qcedev_reg_buf_info *binfo)
+{
+	struct ion_client *clnt = mem_client->client;
+	struct ion_handle *hndl = NULL;
+	unsigned long ion_flags = 0;
+	int rc = 0;
+	struct dma_buf *buf = NULL;
+	struct dma_buf_attachment *attach = NULL;
+	struct sg_table *table = NULL;
+	struct context_bank_info *cb = NULL;
+
+	buf = dma_buf_get(fd);
+	if (IS_ERR_OR_NULL(buf))
+		return -EINVAL;
+
+	hndl = ion_import_dma_buf(clnt, buf);
+	if (IS_ERR_OR_NULL(hndl)) {
+		pr_err("%s: err: invalid ion_handle\n", __func__);
+		rc = -ENOMEM;
+		goto import_buf_err;
+	}
+
+	rc = ion_handle_get_flags(clnt, hndl, &ion_flags);
+	if (rc) {
+		pr_err("%s: err: failed to get ion flags: %d\n", __func__, rc);
+		goto map_err;
+	}
+
+	if (is_iommu_present(qce_hndl)) {
+		cb = get_context_bank(qce_hndl, ion_flags & ION_FLAG_SECURE);
+		if (!cb) {
+			pr_err("%s: err: failed to get context bank info\n",
+				__func__);
+			rc = -EIO;
+			goto map_err;
+		}
+
+		/* Prepare a dma buf for dma on the given device */
+		attach = dma_buf_attach(buf, cb->dev);
+		if (IS_ERR_OR_NULL(attach)) {
+			rc = PTR_ERR(attach) ?: -ENOMEM;
+			pr_err("%s: err: failed to attach dmabuf\n", __func__);
+			goto map_err;
+		}
+
+		/* Get the scatterlist for the given attachment */
+		table = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+		if (IS_ERR_OR_NULL(table)) {
+			rc = PTR_ERR(table) ?: -ENOMEM;
+			pr_err("%s: err: failed to map table\n", __func__);
+			goto map_table_err;
+		}
+
+		/* Map a scatterlist into an SMMU */
+		rc = msm_dma_map_sg_lazy(cb->dev, table->sgl, table->nents,
+				DMA_BIDIRECTIONAL, buf);
+		if (rc != table->nents) {
+			pr_err(
+				"%s: err: mapping failed with rc(%d), expected rc(%d)\n",
+				__func__, rc, table->nents);
+			rc = -ENOMEM;
+			goto map_sg_err;
+		}
+
+		if (table->sgl) {
+			binfo->ion_buf.iova = table->sgl->dma_address;
+			binfo->ion_buf.mapped_buf_size = sg_dma_len(table->sgl);
+			if (binfo->ion_buf.mapped_buf_size < fd_size) {
+				pr_err("%s: err: mapping failed, size mismatch",
+						__func__);
+				rc = -ENOMEM;
+				goto map_sg_err;
+			}
+
+
+		} else {
+			pr_err("%s: err: sg list is NULL\n", __func__);
+			rc = -ENOMEM;
+			goto map_sg_err;
+		}
+
+		binfo->ion_buf.mapping_info.dev = cb->dev;
+		binfo->ion_buf.mapping_info.mapping = cb->mapping;
+		binfo->ion_buf.mapping_info.table = table;
+		binfo->ion_buf.mapping_info.attach = attach;
+		binfo->ion_buf.mapping_info.buf = buf;
+		binfo->ion_buf.hndl = hndl;
+	} else {
+		pr_err("%s: err: smmu not enabled\n", __func__);
+		rc = -EIO;
+		goto map_err;
+	}
+
+	return 0;
+
+map_sg_err:
+	dma_buf_unmap_attachment(attach, table, DMA_BIDIRECTIONAL);
+map_table_err:
+	dma_buf_detach(buf, attach);
+map_err:
+	if (hndl)
+		ion_free(clnt, hndl);
+import_buf_err:
+	dma_buf_put(buf);
+	return rc;
+}
+
+static int ion_unmap_buffer(struct qcedev_handle *qce_hndl,
+		struct qcedev_reg_buf_info *binfo)
+{
+	struct dma_mapping_info *mapping_info = &binfo->ion_buf.mapping_info;
+	struct qcedev_mem_client *mem_client = qce_hndl->cntl->mem_client;
+
+	if (is_iommu_present(qce_hndl)) {
+		msm_dma_unmap_sg(mapping_info->dev, mapping_info->table->sgl,
+			 mapping_info->table->nents, DMA_BIDIRECTIONAL,
+			 mapping_info->buf);
+		dma_buf_unmap_attachment(mapping_info->attach,
+			mapping_info->table, DMA_BIDIRECTIONAL);
+		dma_buf_detach(mapping_info->buf, mapping_info->attach);
+		dma_buf_put(mapping_info->buf);
+
+		if (binfo->ion_buf.hndl)
+			ion_free(mem_client->client, binfo->ion_buf.hndl);
+
+	}
+	return 0;
+}
+
+static int qcedev_map_buffer(struct qcedev_handle *qce_hndl,
+		struct qcedev_mem_client *mem_client, int fd,
+		unsigned int fd_size, struct qcedev_reg_buf_info *binfo)
+{
+	int rc = 0;
+
+	switch (mem_client->mtype) {
+	case MEM_ION:
+		rc = ion_map_buffer(qce_hndl, mem_client, fd, fd_size, binfo);
+		break;
+	default:
+		pr_err("%s: err: Mem type not supported\n", __func__);
+		break;
+	}
+
+	if (rc)
+		pr_err("%s: err: failed to map buffer\n", __func__);
+
+	return rc;
+}
+
+static int qcedev_unmap_buffer(struct qcedev_handle *qce_hndl,
+		struct qcedev_mem_client *mem_client,
+		struct qcedev_reg_buf_info *binfo)
+{
+	int rc = 0;
+
+	switch (mem_client->mtype) {
+	case MEM_ION:
+		rc = ion_unmap_buffer(qce_hndl, binfo);
+		break;
+	default:
+		pr_err("%s: err: Mem type not supported\n", __func__);
+		break;
+	}
+
+	if (rc)
+		pr_err("%s: err: failed to unmap buffer\n", __func__);
+
+	return rc;
+}
+
+static bool compare_ion_buffers(struct qcedev_mem_client *mem_client,
+		struct ion_handle *hndl, int fd)
+{
+	bool match = false;
+	struct ion_handle *fd_hndl = NULL;
+	struct dma_buf *dma_buf;
+
+	dma_buf = dma_buf_get(fd);
+	if (IS_ERR_OR_NULL(dma_buf))
+		return false;
+
+	fd_hndl = ion_import_dma_buf(mem_client->client, dma_buf);
+	if (IS_ERR_OR_NULL(fd_hndl)) {
+		match = false;
+		goto err_exit;
+	}
+
+	match = fd_hndl == hndl ? true : false;
+
+	if (fd_hndl)
+		ion_free(mem_client->client, fd_hndl);
+err_exit:
+	dma_buf_put(dma_buf);
+	return match;
+}
+
+int qcedev_check_and_map_buffer(void *handle,
+		int fd, unsigned int offset, unsigned int fd_size,
+		unsigned long long *vaddr)
+{
+	bool found = false;
+	struct qcedev_reg_buf_info *binfo = NULL, *temp = NULL;
+	struct qcedev_mem_client *mem_client = NULL;
+	struct qcedev_handle *qce_hndl = handle;
+	int rc = 0;
+	unsigned long mapped_size = 0;
+
+	if (!handle || !vaddr || fd < 0 || offset >= fd_size) {
+		pr_err("%s: err: invalid input arguments\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!qce_hndl->cntl || !qce_hndl->cntl->mem_client) {
+		pr_err("%s: err: invalid qcedev handle\n", __func__);
+		return -EINVAL;
+	}
+	mem_client = qce_hndl->cntl->mem_client;
+
+	if (mem_client->mtype != MEM_ION)
+		return -EPERM;
+
+	/* Check if the buffer fd is already mapped */
+	mutex_lock(&qce_hndl->registeredbufs.lock);
+	list_for_each_entry(temp, &qce_hndl->registeredbufs.list, list) {
+		found = compare_ion_buffers(mem_client, temp->ion_buf.hndl, fd);
+		if (found) {
+			*vaddr = temp->ion_buf.iova;
+			mapped_size = temp->ion_buf.mapped_buf_size;
+			atomic_inc(&temp->ref_count);
+			break;
+		}
+	}
+	mutex_unlock(&qce_hndl->registeredbufs.lock);
+
+	/* If buffer fd is not mapped then create a fresh mapping */
+	if (!found) {
+		pr_debug("%s: info: ion fd not registered with driver\n",
+			__func__);
+		binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
+		if (!binfo) {
+			pr_err("%s: err: failed to allocate binfo\n",
+				__func__);
+			rc = -ENOMEM;
+			goto error;
+		}
+		rc = qcedev_map_buffer(qce_hndl, mem_client, fd,
+							fd_size, binfo);
+		if (rc) {
+			pr_err("%s: err: failed to map fd (%d) error = %d\n",
+				__func__, fd, rc);
+			goto error;
+		}
+
+		*vaddr = binfo->ion_buf.iova;
+		mapped_size = binfo->ion_buf.mapped_buf_size;
+		atomic_inc(&binfo->ref_count);
+
+		/* Add buffer mapping information to regd buffer list */
+		mutex_lock(&qce_hndl->registeredbufs.lock);
+		list_add_tail(&binfo->list, &qce_hndl->registeredbufs.list);
+		mutex_unlock(&qce_hndl->registeredbufs.lock);
+	}
+
+	/* Make sure the offset is within the mapped range */
+	if (offset >= mapped_size) {
+		pr_err(
+			"%s: err: Offset (%u) exceeds mapped size(%lu) for fd: %d\n",
+			__func__, offset, mapped_size, fd);
+		rc = -ERANGE;
+		goto unmap;
+	}
+
+	/* return the mapped virtual address adjusted by offset */
+	*vaddr += offset;
+
+	return 0;
+
+unmap:
+	if (!found)
+		qcedev_unmap_buffer(handle, mem_client, binfo);
+
+error:
+	kfree(binfo);
+	return rc;
+}
+
+int qcedev_check_and_unmap_buffer(void *handle, int fd)
+{
+	struct qcedev_reg_buf_info *binfo = NULL, *dummy = NULL;
+	struct qcedev_mem_client *mem_client = NULL;
+	struct qcedev_handle *qce_hndl = handle;
+	bool found = false;
+
+	if (!handle || fd < 0) {
+		pr_err("%s: err: invalid input arguments\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!qce_hndl->cntl || !qce_hndl->cntl->mem_client) {
+		pr_err("%s: err: invalid qcedev handle\n", __func__);
+		return -EINVAL;
+	}
+	mem_client = qce_hndl->cntl->mem_client;
+
+	if (mem_client->mtype != MEM_ION)
+		return -EPERM;
+
+	/* Check if the buffer fd is mapped and present in the regd list. */
+	mutex_lock(&qce_hndl->registeredbufs.lock);
+	list_for_each_entry_safe(binfo, dummy,
+		&qce_hndl->registeredbufs.list, list) {
+
+		found = compare_ion_buffers(mem_client,
+				binfo->ion_buf.hndl, fd);
+		if (found) {
+			atomic_dec(&binfo->ref_count);
+
+			/* Unmap only if there are no more references */
+			if (atomic_read(&binfo->ref_count) == 0) {
+				qcedev_unmap_buffer(qce_hndl,
+					mem_client, binfo);
+				list_del(&binfo->list);
+				kfree(binfo);
+			}
+			break;
+		}
+	}
+	mutex_unlock(&qce_hndl->registeredbufs.lock);
+
+	if (!found) {
+		pr_err("%s: err: calling unmap on unknown fd %d\n",
+			__func__, fd);
+		return -EINVAL;
+	}
+
+	return 0;
+}
diff --git a/drivers/crypto/msm/qcedev_smmu.h b/drivers/crypto/msm/qcedev_smmu.h
new file mode 100644
index 0000000..17e688a
--- /dev/null
+++ b/drivers/crypto/msm/qcedev_smmu.h
@@ -0,0 +1,89 @@
+/* Qti (or) Qualcomm Technologies Inc CE device driver.
+ *
+ * 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 _DRIVERS_CRYPTO_PARSE_H_
+#define _DRIVERS_CRYPTO_PARSE_H_
+
+#include <asm/dma-iommu.h>
+#include <linux/dma-buf.h>
+#include <linux/dma-direction.h>
+#include <linux/iommu.h>
+#include <linux/msm_dma_iommu_mapping.h>
+#include <linux/msm_ion.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+struct context_bank_info {
+	struct list_head list;
+	const char *name;
+	u32 buffer_type;
+	u32 start_addr;
+	u32 size;
+	bool is_secure;
+	struct device *dev;
+	struct dma_iommu_mapping *mapping;
+};
+
+enum qcedev_mem_type {
+	MEM_ION,
+};
+
+struct qcedev_mem_client {
+	enum qcedev_mem_type mtype;
+	void *client;
+};
+
+struct dma_mapping_info {
+	struct device *dev;
+	struct dma_iommu_mapping *mapping;
+	struct sg_table *table;
+	struct dma_buf_attachment *attach;
+	struct dma_buf *buf;
+};
+
+struct qcedev_ion_buf_info {
+	struct ion_handle *hndl;
+	struct dma_mapping_info mapping_info;
+	ion_phys_addr_t iova;
+	unsigned long mapped_buf_size;
+};
+
+struct qcedev_reg_buf_info {
+	struct list_head list;
+	union {
+		struct qcedev_ion_buf_info ion_buf;
+	};
+	atomic_t ref_count;
+};
+
+struct qcedev_buffer_list {
+	struct list_head list;
+	struct mutex lock;
+};
+
+int qcedev_parse_context_bank(struct platform_device *pdev);
+struct qcedev_mem_client *qcedev_mem_new_client(enum qcedev_mem_type mtype);
+void qcedev_mem_delete_client(struct qcedev_mem_client *mem_client);
+int qcedev_check_and_map_buffer(void *qce_hndl,
+		int fd, unsigned int offset, unsigned int fd_size,
+		unsigned long long *vaddr);
+int qcedev_check_and_unmap_buffer(void *handle, int fd);
+
+extern struct qcedev_reg_buf_info *global_binfo_in;
+extern struct qcedev_reg_buf_info *global_binfo_out;
+extern struct qcedev_reg_buf_info *global_binfo_res;
+#endif
+
diff --git a/drivers/crypto/msm/qcedevi.h b/drivers/crypto/msm/qcedevi.h
index c26ed71..f99adaf 100644
--- a/drivers/crypto/msm/qcedevi.h
+++ b/drivers/crypto/msm/qcedevi.h
@@ -1,6 +1,6 @@
 /* QTI crypto Driver
  *
- * 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
@@ -21,6 +21,7 @@
 #include <linux/platform_data/qcom_crypto_device.h>
 #include <linux/fips_status.h>
 #include "qce.h"
+#include "qcedev_smmu.h"
 
 #define CACHE_LINE_SIZE 32
 #define CE_SHA_BLOCK_SIZE SHA256_BLOCK_SIZE
@@ -107,6 +108,8 @@
 	struct qcedev_async_req *active_command;
 	spinlock_t lock;
 	struct tasklet_struct done_tasklet;
+	struct list_head context_banks;
+	struct qcedev_mem_client *mem_client;
 };
 
 struct qcedev_handle {
@@ -114,6 +117,8 @@
 	struct qcedev_control *cntl;
 	/* qce internal sha context*/
 	struct qcedev_sha_ctxt sha_ctxt;
+	/* qcedev mapped buffer list */
+	struct qcedev_buffer_list registeredbufs;
 };
 
 void qcedev_cipher_req_cb(void *cookie, unsigned char *icv,
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index a7df9cb..3357aaf 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -520,6 +520,7 @@
 		devfreq->profile->exit(devfreq->dev.parent);
 
 	mutex_destroy(&devfreq->lock);
+	mutex_destroy(&devfreq->sysfs_lock);
 	kfree(devfreq);
 }
 
@@ -576,6 +577,7 @@
 	}
 
 	mutex_init(&devfreq->lock);
+	mutex_init(&devfreq->sysfs_lock);
 	mutex_lock(&devfreq->lock);
 	devfreq->dev.parent = dev;
 	devfreq->dev.class = devfreq_class;
@@ -972,12 +974,13 @@
 		goto out;
 	}
 
+	mutex_lock(&df->sysfs_lock);
 	if (df->governor) {
 		ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL);
 		if (ret) {
 			dev_warn(dev, "%s: Governor %s not stopped(%d)\n",
 				 __func__, df->governor->name, ret);
-			goto out;
+			goto gov_stop_out;
 		}
 	}
 	prev_gov = df->governor;
@@ -995,6 +998,9 @@
 						    NULL);
 		}
 	}
+
+gov_stop_out:
+	mutex_unlock(&df->sysfs_lock);
 out:
 	mutex_unlock(&devfreq_list_lock);
 
@@ -1089,8 +1095,10 @@
 	if (ret != 1)
 		return -EINVAL;
 
+	mutex_lock(&df->sysfs_lock);
 	df->governor->event_handler(df, DEVFREQ_GOV_INTERVAL, &value);
 	ret = count;
+	mutex_unlock(&df->sysfs_lock);
 
 	return ret;
 }
@@ -1108,6 +1116,7 @@
 	if (ret != 1)
 		return -EINVAL;
 
+	mutex_lock(&df->sysfs_lock);
 	mutex_lock(&df->lock);
 	max = df->max_freq;
 	if (value && max && value > max) {
@@ -1120,6 +1129,7 @@
 	ret = count;
 unlock:
 	mutex_unlock(&df->lock);
+	mutex_unlock(&df->sysfs_lock);
 	return ret;
 }
 
@@ -1135,6 +1145,7 @@
 	if (ret != 1)
 		return -EINVAL;
 
+	mutex_lock(&df->sysfs_lock);
 	mutex_lock(&df->lock);
 	min = df->min_freq;
 	if (value && min && value < min) {
@@ -1147,6 +1158,7 @@
 	ret = count;
 unlock:
 	mutex_unlock(&df->lock);
+	mutex_unlock(&df->sysfs_lock);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 630b5fb..8952fc9 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -548,7 +548,7 @@
 	}
 
 	ret = dp_aux_cmd_fifo_tx(aux, msg);
-	if ((ret < 0) && aux->native && !atomic_read(&aux->aborted)) {
+	if ((ret < 0) && !atomic_read(&aux->aborted)) {
 		aux->retry_cnt++;
 		if (!(aux->retry_cnt % retry_count))
 			aux->catalog->update_aux_cfg(aux->catalog,
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 56a41b5..5e73dfa 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -54,17 +54,17 @@
 }
 
 static u8 const vm_pre_emphasis[4][4] = {
-	{0x00, 0x0B, 0x12, 0xFF},       /* pe0, 0 db */
-	{0x00, 0x0A, 0x12, 0xFF},       /* pe1, 3.5 db */
-	{0x00, 0x0C, 0xFF, 0xFF},       /* pe2, 6.0 db */
+	{0x00, 0x0B, 0x14, 0xFF},       /* pe0, 0 db */
+	{0x00, 0x0B, 0x12, 0xFF},       /* pe1, 3.5 db */
+	{0x00, 0x0B, 0xFF, 0xFF},       /* pe2, 6.0 db */
 	{0xFF, 0xFF, 0xFF, 0xFF}        /* pe3, 9.5 db */
 };
 
 /* voltage swing, 0.2v and 1.0v are not support */
 static u8 const vm_voltage_swing[4][4] = {
-	{0x07, 0x0F, 0x14, 0xFF}, /* sw0, 0.4v  */
-	{0x11, 0x1D, 0x1F, 0xFF}, /* sw1, 0.6 v */
-	{0x18, 0x1F, 0xFF, 0xFF}, /* sw1, 0.8 v */
+	{0x07, 0x0F, 0x16, 0xFF}, /* sw0, 0.4v  */
+	{0x11, 0x1E, 0x1F, 0xFF}, /* sw1, 0.6 v */
+	{0x19, 0x1F, 0xFF, 0xFF}, /* sw1, 0.8 v */
 	{0xFF, 0xFF, 0xFF, 0xFF}  /* sw1, 1.2 v, optional */
 };
 
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 2e2887e..f2e9085 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -130,7 +130,7 @@
 
 	ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
 
-	if (!ctrl->power_on || atomic_read(&ctrl->aborted)) {
+	if (!ctrl->power_on) {
 		pr_err("CTRL off, return\n");
 		return;
 	}
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index bf903b9..3e5cdc6 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -610,6 +610,8 @@
 		goto end;
 	}
 
+	atomic_set(&dp->aborted, 0);
+
 	dp_display_host_init(dp);
 
 	/* check for hpd high and framework ready */
@@ -694,10 +696,10 @@
 
 	/* wait for idle state */
 	cancel_delayed_work(&dp->connect_work);
+	cancel_work(&dp->attention_work);
 	flush_workqueue(dp->wq);
 
 	dp_display_handle_disconnect(dp);
-	atomic_set(&dp->aborted, 0);
 end:
 	return rc;
 }
@@ -801,6 +803,7 @@
 
 		/* wait for idle state */
 		cancel_delayed_work(&dp->connect_work);
+		cancel_work(&dp->attention_work);
 		flush_workqueue(dp->wq);
 
 		dp_display_handle_disconnect(dp);
diff --git a/drivers/gpu/drm/msm/dp/dp_usbpd.c b/drivers/gpu/drm/msm/dp/dp_usbpd.c
index 42eb9b0..3a14f7c 100644
--- a/drivers/gpu/drm/msm/dp/dp_usbpd.c
+++ b/drivers/gpu/drm/msm/dp/dp_usbpd.c
@@ -16,6 +16,7 @@
 
 #include <linux/slab.h>
 #include <linux/device.h>
+#include <linux/delay.h>
 
 #include "dp_usbpd.h"
 
@@ -314,11 +315,44 @@
 	return ret;
 }
 
+
+static int dp_usbpd_get_ss_lanes(struct dp_usbpd_private *pd)
+{
+	int rc = 0;
+	int timeout = 250;
+
+	/*
+	 * By default, USB reserves two lanes for Super Speed.
+	 * Which means DP has remaining two lanes to operate on.
+	 * If multi-function is not supported, request USB to
+	 * release the Super Speed lanes so that DP can use
+	 * all four lanes in case DPCD indicates support for
+	 * four lanes.
+	 */
+	if (!pd->dp_usbpd.multi_func) {
+		while (timeout) {
+			rc = pd->svid_handler.request_usb_ss_lane(
+					pd->pd, &pd->svid_handler);
+			if (rc != -EBUSY)
+				break;
+
+			pr_warn("USB busy, retry\n");
+
+			/* wait for hw recommended delay for usb */
+			msleep(20);
+			timeout--;
+		}
+	}
+
+	return rc;
+}
+
 static void dp_usbpd_response_cb(struct usbpd_svid_handler *hdlr, u8 cmd,
 				enum usbpd_svdm_cmd_type cmd_type,
 				const u32 *vdos, int num_vdos)
 {
 	struct dp_usbpd_private *pd;
+	int rc = 0;
 
 	pd = container_of(hdlr, struct dp_usbpd_private, svid_handler);
 
@@ -380,17 +414,11 @@
 
 		pd->dp_usbpd.orientation = usbpd_get_plug_orientation(pd->pd);
 
-		/*
-		 * By default, USB reserves two lanes for Super Speed.
-		 * Which means DP has remaining two lanes to operate on.
-		 * If multi-function is not supported, request USB to
-		 * release the Super Speed lanes so that DP can use
-		 * all four lanes in case DPCD indicates support for
-		 * four lanes.
-		 */
-		if (!pd->dp_usbpd.multi_func)
-			pd->svid_handler.request_usb_ss_lane(pd->pd,
-				&pd->svid_handler);
+		rc = dp_usbpd_get_ss_lanes(pd);
+		if (rc) {
+			pr_err("failed to get SuperSpeed lanes\n");
+			break;
+		}
 
 		if (pd->dp_cb && pd->dp_cb->configure)
 			pd->dp_cb->configure(pd->dev);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 1ab1de6..93e364de 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -275,12 +275,12 @@
 	switch (op) {
 	case DSI_CTRL_OP_POWER_STATE_CHANGE:
 		if (state->power_state == op_state) {
-			pr_debug("[%d] No change in state, pwr_state=%d\n",
+			pr_err("[%d] No change in state, pwr_state=%d\n",
 			       dsi_ctrl->cell_index, op_state);
 			rc = -EINVAL;
 		} else if (state->power_state == DSI_CTRL_POWER_VREG_ON) {
 			if (state->vid_engine_state == DSI_CTRL_ENGINE_ON) {
-				pr_debug("[%d]State error: op=%d: %d\n",
+				pr_err("[%d]State error: op=%d: %d\n",
 				       dsi_ctrl->cell_index,
 				       op_state,
 				       state->vid_engine_state);
@@ -290,12 +290,12 @@
 		break;
 	case DSI_CTRL_OP_CMD_ENGINE:
 		if (state->cmd_engine_state == op_state) {
-			pr_debug("[%d] No change in state, cmd_state=%d\n",
+			pr_err("[%d] No change in state, cmd_state=%d\n",
 			       dsi_ctrl->cell_index, op_state);
 			rc = -EINVAL;
 		} else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) ||
 			   (state->controller_state != DSI_CTRL_ENGINE_ON)) {
-			pr_debug("[%d]State error: op=%d: %d, %d\n",
+			pr_err("[%d]State error: op=%d: %d, %d\n",
 			       dsi_ctrl->cell_index,
 			       op,
 			       state->power_state,
@@ -305,12 +305,12 @@
 		break;
 	case DSI_CTRL_OP_VID_ENGINE:
 		if (state->vid_engine_state == op_state) {
-			pr_debug("[%d] No change in state, cmd_state=%d\n",
+			pr_err("[%d] No change in state, cmd_state=%d\n",
 			       dsi_ctrl->cell_index, op_state);
 			rc = -EINVAL;
 		} else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) ||
 			   (state->controller_state != DSI_CTRL_ENGINE_ON)) {
-			pr_debug("[%d]State error: op=%d: %d, %d\n",
+			pr_err("[%d]State error: op=%d: %d, %d\n",
 			       dsi_ctrl->cell_index,
 			       op,
 			       state->power_state,
@@ -320,11 +320,11 @@
 		break;
 	case DSI_CTRL_OP_HOST_ENGINE:
 		if (state->controller_state == op_state) {
-			pr_debug("[%d] No change in state, ctrl_state=%d\n",
+			pr_err("[%d] No change in state, ctrl_state=%d\n",
 			       dsi_ctrl->cell_index, op_state);
 			rc = -EINVAL;
 		} else if (state->power_state != DSI_CTRL_POWER_VREG_ON) {
-			pr_debug("[%d]State error (link is off): op=%d:, %d\n",
+			pr_err("[%d]State error (link is off): op=%d:, %d\n",
 			       dsi_ctrl->cell_index,
 			       op_state,
 			       state->power_state);
@@ -332,7 +332,7 @@
 		} else if ((op_state == DSI_CTRL_ENGINE_OFF) &&
 			   ((state->cmd_engine_state != DSI_CTRL_ENGINE_OFF) ||
 			    (state->vid_engine_state != DSI_CTRL_ENGINE_OFF))) {
-			pr_debug("[%d]State error (eng on): op=%d: %d, %d\n",
+			pr_err("[%d]State error (eng on): op=%d: %d, %d\n",
 				  dsi_ctrl->cell_index,
 				  op_state,
 				  state->cmd_engine_state,
@@ -344,7 +344,7 @@
 		if ((state->power_state != DSI_CTRL_POWER_VREG_ON) ||
 		    (state->host_initialized != true) ||
 		    (state->cmd_engine_state != DSI_CTRL_ENGINE_ON)) {
-			pr_debug("[%d]State error: op=%d: %d, %d, %d\n",
+			pr_err("[%d]State error: op=%d: %d, %d, %d\n",
 			       dsi_ctrl->cell_index,
 			       op,
 			       state->power_state,
@@ -355,23 +355,23 @@
 		break;
 	case DSI_CTRL_OP_HOST_INIT:
 		if (state->host_initialized == op_state) {
-			pr_debug("[%d] No change in state, host_init=%d\n",
+			pr_err("[%d] No change in state, host_init=%d\n",
 			       dsi_ctrl->cell_index, op_state);
 			rc = -EINVAL;
 		} else if (state->power_state != DSI_CTRL_POWER_VREG_ON) {
-			pr_debug("[%d]State error: op=%d: %d\n",
+			pr_err("[%d]State error: op=%d: %d\n",
 			       dsi_ctrl->cell_index, op, state->power_state);
 			rc = -EINVAL;
 		}
 		break;
 	case DSI_CTRL_OP_TPG:
 		if (state->tpg_enabled == op_state) {
-			pr_debug("[%d] No change in state, tpg_enabled=%d\n",
+			pr_err("[%d] No change in state, tpg_enabled=%d\n",
 			       dsi_ctrl->cell_index, op_state);
 			rc = -EINVAL;
 		} else if ((state->power_state != DSI_CTRL_POWER_VREG_ON) ||
 			   (state->controller_state != DSI_CTRL_ENGINE_ON)) {
-			pr_debug("[%d]State error: op=%d: %d, %d\n",
+			pr_err("[%d]State error: op=%d: %d, %d\n",
 			       dsi_ctrl->cell_index,
 			       op,
 			       state->power_state,
@@ -381,7 +381,7 @@
 		break;
 	case DSI_CTRL_OP_PHY_SW_RESET:
 		if (state->power_state != DSI_CTRL_POWER_VREG_ON) {
-			pr_debug("[%d]State error: op=%d: %d\n",
+			pr_err("[%d]State error: op=%d: %d\n",
 			       dsi_ctrl->cell_index, op, state->power_state);
 			rc = -EINVAL;
 		}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index c79a72a..199833d 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -488,7 +488,6 @@
 	int i, j = 0;
 	int len = 0, *lenp;
 	int group = 0, count = 0;
-	struct dsi_display_mode *mode;
 	struct drm_panel_esd_config *config;
 
 	if (!panel)
@@ -497,8 +496,7 @@
 	config = &(panel->esd_config);
 
 	lenp = config->status_valid_params ?: config->status_cmds_rlen;
-	mode = panel->cur_mode;
-	count = mode->priv_info->cmd_sets[DSI_CMD_SET_PANEL_STATUS].count;
+	count = config->status_cmd.count;
 
 	for (i = 0; i < count; i++)
 		len += lenp[i];
@@ -694,7 +692,7 @@
 	reinit_completion(&display->esd_te_gate);
 	if (!wait_for_completion_timeout(&display->esd_te_gate,
 				esd_te_timeout)) {
-		pr_err("ESD check failed\n");
+		pr_err("TE check failed\n");
 		rc = -EINVAL;
 	}
 
@@ -703,7 +701,7 @@
 	return rc;
 }
 
-int dsi_display_check_status(void *display)
+int dsi_display_check_status(void *display, bool te_check_override)
 {
 	struct dsi_display *dsi_display = display;
 	struct dsi_panel *panel;
@@ -713,18 +711,20 @@
 	if (dsi_display == NULL)
 		return -EINVAL;
 
-	panel = dsi_display->panel;
-
-	status_mode = panel->esd_config.status_mode;
-
 	mutex_lock(&dsi_display->display_lock);
 
+	panel = dsi_display->panel;
 	if (!panel->panel_initialized) {
 		pr_debug("Panel not initialized\n");
 		mutex_unlock(&dsi_display->display_lock);
 		return rc;
 	}
 
+	if (te_check_override && gpio_is_valid(dsi_display->disp_te_gpio))
+		status_mode = ESD_MODE_PANEL_TE;
+	else
+		status_mode = panel->esd_config.status_mode;
+
 	dsi_display_clk_ctrl(dsi_display->dsi_clk_handle,
 		DSI_ALL_CLKS, DSI_CLK_ON);
 
@@ -2706,7 +2706,7 @@
 				 const struct mipi_dsi_msg *msg)
 {
 	struct dsi_display *display = to_dsi_display(host);
-	int rc = 0;
+	int rc = 0, ret = 0;
 
 	if (!host || !msg) {
 		pr_err("Invalid params\n");
@@ -2764,13 +2764,17 @@
 	}
 
 error_disable_cmd_engine:
-	(void)dsi_display_cmd_engine_disable(display);
+	ret = dsi_display_cmd_engine_disable(display);
+	if (ret) {
+		pr_err("[%s]failed to disable DSI cmd engine, rc=%d\n",
+				display->name, ret);
+	}
 error_disable_clks:
-	rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
+	ret = dsi_display_clk_ctrl(display->dsi_clk_handle,
 			DSI_ALL_CLKS, DSI_CLK_OFF);
-	if (rc) {
+	if (ret) {
 		pr_err("[%s] failed to disable all DSI clocks, rc=%d\n",
-		       display->name, rc);
+		       display->name, ret);
 	}
 error:
 	return rc;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
index 85fd65c1..6b1c029 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
@@ -581,8 +581,9 @@
 /**
  * dsi_display_check_status() - check if panel is dead or alive
  * @display:            Handle to display.
+ * @te_check_override:	Whether check for TE from panel or default check
  */
-int dsi_display_check_status(void *display);
+int dsi_display_check_status(void *display, bool te_check_override);
 
 /**
  * dsi_display_cmd_transfer() - transfer command to the panel
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index 31d6fd1..e62c65e 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -2054,9 +2054,8 @@
 	int final_value, final_scale;
 	int ratio_index;
 
-	dsc->version = 0x11;
-	dsc->scr_rev = 0;
 	dsc->rc_model_size = 8192;
+
 	if (dsc->version == 0x11 && dsc->scr_rev == 0x1)
 		dsc->first_line_bpg_offset = 15;
 	else
@@ -2248,6 +2247,36 @@
 		return 0;
 	}
 
+	rc = of_property_read_u32(of_node, "qcom,mdss-dsc-version", &data);
+	if (rc) {
+		priv_info->dsc.version = 0x11;
+		rc = 0;
+	} else {
+		priv_info->dsc.version = data & 0xff;
+		/* only support DSC 1.1 rev */
+		if (priv_info->dsc.version != 0x11) {
+			pr_err("%s: DSC version:%d not supported\n", __func__,
+					priv_info->dsc.version);
+			rc = -EINVAL;
+			goto error;
+		}
+	}
+
+	rc = of_property_read_u32(of_node, "qcom,mdss-dsc-scr-version", &data);
+	if (rc) {
+		priv_info->dsc.scr_rev = 0x0;
+		rc = 0;
+	} else {
+		priv_info->dsc.scr_rev = data & 0xff;
+		/* only one scr rev supported */
+		if (priv_info->dsc.scr_rev > 0x1) {
+			pr_err("%s: DSC scr version:%d not supported\n",
+					__func__, priv_info->dsc.scr_rev);
+			rc = -EINVAL;
+			goto error;
+		}
+	}
+
 	rc = of_property_read_u32(of_node, "qcom,mdss-dsc-slice-height", &data);
 	if (rc) {
 		pr_err("failed to parse qcom,mdss-dsc-slice-height\n");
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 17a41d5..ce4197b 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -156,6 +156,8 @@
 	CRTC_PROP_IDLE_TIMEOUT,
 	CRTC_PROP_DEST_SCALER,
 
+	CRTC_PROP_ENABLE_SUI_ENHANCEMENT,
+
 	/* total # of properties */
 	CRTC_PROP_COUNT
 };
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c
index 919ed97..0f55b19 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.c
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c
@@ -1799,25 +1799,21 @@
 		goto exit;
 	}
 
-	node = _sde_cp_get_intr_node(DRM_EVENT_AD_BACKLIGHT, crtc);
+	node = container_of(ad_irq, struct sde_crtc_irq_info, irq);
 
 	if (!en) {
-		if (node) {
-			spin_lock_irqsave(&node->state_lock, flags);
-			if (node->state == IRQ_ENABLED) {
-				ret = sde_core_irq_disable(kms, &irq_idx, 1);
-				if (ret)
-					DRM_ERROR("disable irq %d error %d\n",
-						irq_idx, ret);
-				else
-					node->state = IRQ_NOINIT;
-			} else {
+		spin_lock_irqsave(&node->state_lock, flags);
+		if (node->state == IRQ_ENABLED) {
+			ret = sde_core_irq_disable(kms, &irq_idx, 1);
+			if (ret)
+				DRM_ERROR("disable irq %d error %d\n",
+					irq_idx, ret);
+			else
 				node->state = IRQ_NOINIT;
-			}
-			spin_unlock_irqrestore(&node->state_lock, flags);
 		} else {
-			DRM_ERROR("failed to get node from crtc event list\n");
+			node->state = IRQ_NOINIT;
 		}
+		spin_unlock_irqrestore(&node->state_lock, flags);
 		sde_core_irq_unregister_callback(kms, irq_idx, ad_irq);
 		ret = 0;
 		goto exit;
@@ -1831,32 +1827,18 @@
 		goto exit;
 	}
 
-	if (node) {
-		/* device resume or resume from IPC cases */
-		spin_lock_irqsave(&node->state_lock, flags);
-		if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) {
-			ret = sde_core_irq_enable(kms, &irq_idx, 1);
-			if (ret) {
-				DRM_ERROR("enable irq %d error %d\n",
-					irq_idx, ret);
-				sde_core_irq_unregister_callback(kms,
-					irq_idx, ad_irq);
-			} else {
-				node->state = IRQ_ENABLED;
-			}
-		}
-		spin_unlock_irqrestore(&node->state_lock, flags);
-	} else {
-		/* request from userspace to register the event
-		 * in this case, node has not been added into the event list
-		 */
+	spin_lock_irqsave(&node->state_lock, flags);
+	if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) {
 		ret = sde_core_irq_enable(kms, &irq_idx, 1);
 		if (ret) {
-			DRM_ERROR("failed to enable irq ret %d\n", ret);
-			sde_core_irq_unregister_callback(kms,
-				irq_idx, ad_irq);
+			DRM_ERROR("enable irq %d error %d\n", irq_idx, ret);
+			sde_core_irq_unregister_callback(kms, irq_idx, ad_irq);
+		} else {
+			node->state = IRQ_ENABLED;
 		}
 	}
+	spin_unlock_irqrestore(&node->state_lock, flags);
+
 exit:
 	return ret;
 }
@@ -1937,7 +1919,7 @@
 	spin_unlock_irqrestore(&crtc->spin_lock, flags);
 
 	if (!node) {
-		DRM_ERROR("cannot find histogram event node in crtc\n");
+		DRM_DEBUG_DRIVER("cannot find histogram event node in crtc\n");
 		return;
 	}
 
@@ -2082,26 +2064,29 @@
 		goto exit;
 	}
 
-	node = _sde_cp_get_intr_node(DRM_EVENT_HISTOGRAM, crtc);
+	node = container_of(hist_irq, struct sde_crtc_irq_info, irq);
 
 	/* deregister histogram irq */
 	if (!en) {
-		if (node) {
-			/* device suspend case or suspend to IPC cases */
+		spin_lock_irqsave(&node->state_lock, flags);
+		if (node->state == IRQ_ENABLED) {
+			node->state = IRQ_DISABLING;
+			spin_unlock_irqrestore(&node->state_lock, flags);
+			ret = sde_core_irq_disable(kms, &irq_idx, 1);
 			spin_lock_irqsave(&node->state_lock, flags);
-			if (node->state == IRQ_ENABLED) {
-				ret = sde_core_irq_disable(kms, &irq_idx, 1);
-				if (ret)
-					DRM_ERROR("disable irq %d error %d\n",
-						irq_idx, ret);
-				else
-					node->state = IRQ_NOINIT;
+			if (ret) {
+				DRM_ERROR("disable irq %d error %d\n",
+					irq_idx, ret);
+				node->state = IRQ_ENABLED;
 			} else {
 				node->state = IRQ_NOINIT;
 			}
 			spin_unlock_irqrestore(&node->state_lock, flags);
+		} else if (node->state == IRQ_DISABLED) {
+			node->state = IRQ_NOINIT;
+			spin_unlock_irqrestore(&node->state_lock, flags);
 		} else {
-			DRM_ERROR("failed to get node from crtc event list\n");
+			spin_unlock_irqrestore(&node->state_lock, flags);
 		}
 
 		sde_core_irq_unregister_callback(kms, irq_idx, hist_irq);
@@ -2117,32 +2102,19 @@
 		goto exit;
 	}
 
-	if (node) {
-		/* device resume or resume from IPC cases */
-		spin_lock_irqsave(&node->state_lock, flags);
-		if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) {
-			ret = sde_core_irq_enable(kms, &irq_idx, 1);
-			if (ret) {
-				DRM_ERROR("enable irq %d error %d\n",
-					irq_idx, ret);
-				sde_core_irq_unregister_callback(kms,
-					irq_idx, hist_irq);
-			} else {
-				node->state = IRQ_ENABLED;
-			}
-		}
-		spin_unlock_irqrestore(&node->state_lock, flags);
-	} else {
-		/* request from userspace to register the event
-		 * in this case, node has not been added into the event list
-		 */
+	spin_lock_irqsave(&node->state_lock, flags);
+	if (node->state == IRQ_DISABLED || node->state == IRQ_NOINIT) {
 		ret = sde_core_irq_enable(kms, &irq_idx, 1);
 		if (ret) {
-			DRM_ERROR("failed to enable irq ret %d\n", ret);
+			DRM_ERROR("enable irq %d error %d\n", irq_idx, ret);
 			sde_core_irq_unregister_callback(kms,
 				irq_idx, hist_irq);
+		} else {
+			node->state = IRQ_ENABLED;
 		}
 	}
+	spin_unlock_irqrestore(&node->state_lock, flags);
+
 exit:
 	return ret;
 }
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index e59c5f0..d2f8d12 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -1731,12 +1731,59 @@
 	return c_conn->encoder;
 }
 
+static void _sde_connector_report_panel_dead(struct sde_connector *conn)
+{
+	struct drm_event event;
+	bool panel_dead = true;
+
+	if (!conn)
+		return;
+
+	event.type = DRM_EVENT_PANEL_DEAD;
+	event.length = sizeof(bool);
+	msm_mode_object_event_notify(&conn->base.base,
+		conn->base.dev, &event, (u8 *)&panel_dead);
+	sde_encoder_display_failure_notification(conn->encoder);
+	SDE_EVT32(SDE_EVTLOG_ERROR);
+	SDE_ERROR("esd check failed report PANEL_DEAD conn_id: %d enc_id: %d\n",
+			conn->base.base.id, conn->encoder->base.id);
+}
+
+int sde_connector_esd_status(struct drm_connector *conn)
+{
+	struct sde_connector *sde_conn = NULL;
+	int ret = 0;
+
+	if (!conn)
+		return ret;
+
+	sde_conn = to_sde_connector(conn);
+	if (!sde_conn || !sde_conn->ops.check_status)
+		return ret;
+
+	/* protect this call with ESD status check call */
+	mutex_lock(&sde_conn->lock);
+	ret = sde_conn->ops.check_status(sde_conn->display, true);
+	mutex_unlock(&sde_conn->lock);
+
+	if (ret <= 0) {
+		/* cancel if any pending esd work */
+		sde_connector_schedule_status_work(conn, false);
+		_sde_connector_report_panel_dead(sde_conn);
+		ret = -ETIMEDOUT;
+	} else {
+		SDE_DEBUG("Successfully received TE from panel\n");
+		ret = 0;
+	}
+	SDE_EVT32(ret);
+
+	return ret;
+}
+
 static void sde_connector_check_status_work(struct work_struct *work)
 {
 	struct sde_connector *conn;
-	struct drm_event event;
 	int rc = 0;
-	bool panel_dead = false;
 
 	conn = container_of(to_delayed_work(work),
 			struct sde_connector, status_work);
@@ -1753,7 +1800,7 @@
 		return;
 	}
 
-	rc = conn->ops.check_status(conn->display);
+	rc = conn->ops.check_status(conn->display, false);
 	mutex_unlock(&conn->lock);
 
 	if (conn->force_panel_dead) {
@@ -1777,15 +1824,7 @@
 	}
 
 status_dead:
-	SDE_EVT32(rc, SDE_EVTLOG_ERROR);
-	SDE_ERROR("esd check failed report PANEL_DEAD conn_id: %d enc_id: %d\n",
-			conn->base.base.id, conn->encoder->base.id);
-	panel_dead = true;
-	event.type = DRM_EVENT_PANEL_DEAD;
-	event.length = sizeof(bool);
-	msm_mode_object_event_notify(&conn->base.base,
-		conn->base.dev, &event, (u8 *)&panel_dead);
-	sde_encoder_display_failure_notification(conn->encoder);
+	_sde_connector_report_panel_dead(conn);
 }
 
 static const struct drm_connector_helper_funcs sde_connector_helper_ops = {
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index ef2385e..c6f348e 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -228,9 +228,10 @@
 	/**
 	 * check_status - check status of connected display panel
 	 * @display: Pointer to private display handle
+	 * @te_check_override: Whether check TE from panel or default check
 	 * Returns: positive value for success, negetive or zero for failure
 	 */
-	int (*check_status)(void *display);
+	int (*check_status)(void *display, bool te_check_override);
 
 	/**
 	 * cmd_transfer - Transfer command to the connected display panel
@@ -770,4 +771,11 @@
  */
 int sde_connector_get_panel_vfp(struct drm_connector *connector,
 	struct drm_display_mode *mode);
+
+/**
+ * sde_connector_esd_status - helper function to check te status
+ * @connector: Pointer to DRM connector object
+ */
+int sde_connector_esd_status(struct drm_connector *connector);
+
 #endif /* _SDE_CONNECTOR_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 7bc01c3..ce2997d 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -1851,7 +1851,8 @@
 				ops |= (SDE_KMS_OPS_WAIT_FOR_TX_DONE  |
 					SDE_KMS_OPS_CLEANUP_PLANE_FB);
 			}
-			if (catalog->sui_misr_supported)
+			if (catalog->sui_misr_supported &&
+					sde_crtc->enable_sui_enhancement)
 				smmu_state->sui_misr_state =
 						SUI_MISR_ENABLE_REQ;
 		/* secure camera usecase */
@@ -1881,7 +1882,8 @@
 			if (old_valid_fb)
 				ops |= (SDE_KMS_OPS_WAIT_FOR_TX_DONE |
 				 SDE_KMS_OPS_CLEANUP_PLANE_FB);
-			if (catalog->sui_misr_supported)
+			if (catalog->sui_misr_supported &&
+					sde_crtc->enable_sui_enhancement)
 				smmu_state->sui_misr_state =
 						SUI_MISR_DISABLE_REQ;
 		}
@@ -4398,6 +4400,7 @@
 		return -EINVAL;
 	}
 
+	sde_crtc = to_sde_crtc(crtc);
 	cstate = to_sde_crtc_state(state);
 
 	secure = sde_crtc_get_property(cstate, CRTC_PROP_SECURITY_LEVEL);
@@ -4434,7 +4437,8 @@
 			}
 			plane = pstates[i].drm_pstate->plane;
 
-			if (!sde_plane_is_sec_ui_allowed(plane)) {
+			if (sde_crtc->enable_sui_enhancement &&
+					!sde_plane_is_sec_ui_allowed(plane)) {
 				SDE_ERROR("crtc%d: sec-ui not allowed in p%d\n",
 						crtc->base.id, plane->base.id);
 				return -EINVAL;
@@ -4475,7 +4479,6 @@
 						MSM_DISPLAY_CAP_VID_MODE);
 	}
 
-	sde_crtc = to_sde_crtc(crtc);
 	smmu_state = &sde_kms->smmu_state;
 	/*
 	 * In video mode check for null commit before transition
@@ -4987,6 +4990,10 @@
 		"idle_time", 0, 0, U64_MAX, 0,
 		CRTC_PROP_IDLE_TIMEOUT);
 
+	msm_property_install_range(&sde_crtc->property_info,
+		"enable_sui_enhancement", 0, 0, U64_MAX, 0,
+		CRTC_PROP_ENABLE_SUI_ENHANCEMENT);
+
 	msm_property_install_blob(&sde_crtc->property_info, "capabilities",
 		DRM_MODE_PROP_IMMUTABLE, CRTC_PROP_INFO);
 
@@ -5222,6 +5229,9 @@
 		cstate->bw_control = true;
 		cstate->bw_split_vote = true;
 		break;
+	case CRTC_PROP_ENABLE_SUI_ENHANCEMENT:
+		sde_crtc->enable_sui_enhancement = val ? true : false;
+		break;
 	case CRTC_PROP_OUTPUT_FENCE:
 		if (!val)
 			goto exit;
@@ -6032,10 +6042,10 @@
 			node = kzalloc(sizeof(*node), GFP_KERNEL);
 			if (!node)
 				return -ENOMEM;
-			node->event = event;
 			INIT_LIST_HEAD(&node->list);
 			node->func = custom_events[i].func;
 			node->event = event;
+			node->state = IRQ_NOINIT;
 			spin_lock_init(&node->state_lock);
 			break;
 		}
@@ -6066,8 +6076,6 @@
 
 	if (!ret) {
 		spin_lock_irqsave(&crtc->spin_lock, flags);
-		/* irq is regiestered and enabled and set the state */
-		node->state = IRQ_ENABLED;
 		list_add_tail(&node->list, &crtc->user_event_list);
 		spin_unlock_irqrestore(&crtc->spin_lock, flags);
 	} else {
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index bc1614c..64f3821 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -171,6 +171,8 @@
  * @misr_enable   : boolean entry indicates misr enable/disable status.
  * @misr_frame_count  : misr frame count provided by client
  * @misr_data     : store misr data before turning off the clocks.
+ * @enable_sui_enhancement: indicate enable/disable of sui_enhancement feature
+ *                           which is set by user-mode.
  * @sbuf_op_mode_old : inline rotator op mode for previous commit cycle
  * @sbuf_flush_mask_old: inline rotator flush mask for previous commit
  * @sbuf_flush_mask_all: inline rotator flush mask for all attached planes
@@ -242,6 +244,8 @@
 	u32 misr_frame_count;
 	u32 misr_data[CRTC_DUAL_MIXERS];
 
+	bool enable_sui_enhancement;
+
 	u32 sbuf_op_mode_old;
 	u32 sbuf_flush_mask_old;
 	u32 sbuf_flush_mask_all;
@@ -390,6 +394,7 @@
 enum sde_crtc_irq_state {
 	IRQ_NOINIT,
 	IRQ_ENABLED,
+	IRQ_DISABLING,
 	IRQ_DISABLED,
 };
 
@@ -690,6 +695,22 @@
 }
 
 /**
+ * sde_crtc_is_sui_enhancement_enabled - Checks if user-mode has enabled the
+ *                                        sui enhancement feature
+ * @crtc: Pointer to crtc
+ */
+static inline bool sde_crtc_is_sui_enhancement_enabled(struct drm_crtc *crtc)
+{
+	struct sde_crtc *sde_crtc;
+
+	if (!crtc)
+		return false;
+	sde_crtc = to_sde_crtc(crtc);
+
+	return sde_crtc->enable_sui_enhancement;
+}
+
+/**
  * sde_crtc_get_secure_transition - determines the operations to be
  * performed before transitioning to secure state
  * This function should be called after swapping the new state
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index 3edaed3..828d771 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -473,6 +473,10 @@
 			atomic_read(&phys_enc->pending_kickoff_cnt),
 			frame_event);
 
+	/* check if panel is still sending TE signal or not */
+	if (sde_connector_esd_status(phys_enc->connector))
+		goto exit;
+
 	if (cmd_enc->pp_timeout_report_cnt >= PP_TIMEOUT_MAX_TRIALS) {
 		cmd_enc->pp_timeout_report_cnt = PP_TIMEOUT_MAX_TRIALS;
 		frame_event |= SDE_ENCODER_FRAME_EVENT_PANEL_DEAD;
@@ -490,11 +494,12 @@
 		SDE_EVT32(DRMID(phys_enc->parent), SDE_EVTLOG_FATAL);
 	}
 
-	atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);
-
 	/* request a ctl reset before the next kickoff */
 	phys_enc->enable_state = SDE_ENC_ERR_NEEDS_HW_RESET;
 
+exit:
+	atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0);
+
 	if (phys_enc->parent_ops.handle_frame_done)
 		phys_enc->parent_ops.handle_frame_done(
 				phys_enc->parent, phys_enc, frame_event);
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index dd72665..862a8b3 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -846,7 +846,7 @@
 	if (phys_enc->parent_ops.handle_frame_done && event)
 		phys_enc->parent_ops.handle_frame_done(
 				phys_enc->parent, phys_enc,
-				SDE_ENCODER_FRAME_EVENT_DONE);
+				event);
 	return ret;
 }
 
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index 92c74d8..eacafe6 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -3245,12 +3245,20 @@
 		sde_cfg->perf.min_prefill_lines = 25;
 		sde_cfg->vbif_qos_nlvl = 4;
 		sde_cfg->ts_prefill_rev = 1;
-	} else if (IS_SDM845_TARGET(hw_rev) || IS_SDM670_TARGET(hw_rev)) {
+	} else if (IS_SDM845_TARGET(hw_rev)) {
 		/* update sdm845 target here */
 		sde_cfg->has_wb_ubwc = true;
 		sde_cfg->perf.min_prefill_lines = 24;
 		sde_cfg->vbif_qos_nlvl = 8;
 		sde_cfg->ts_prefill_rev = 2;
+		sde_cfg->sui_misr_supported = true;
+		sde_cfg->sui_block_xin_mask = 0x3F71;
+	} else if (IS_SDM670_TARGET(hw_rev)) {
+		/* update sdm670 target here */
+		sde_cfg->has_wb_ubwc = true;
+		sde_cfg->perf.min_prefill_lines = 24;
+		sde_cfg->vbif_qos_nlvl = 8;
+		sde_cfg->ts_prefill_rev = 2;
 	} else {
 		SDE_ERROR("unsupported chipset id:%X\n", hw_rev);
 		sde_cfg->perf.min_prefill_lines = 0xffff;
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 0412fc6..33bdec9 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -105,6 +105,32 @@
 	return sdecustom;
 }
 
+bool sde_kms_is_vbif_operation_allowed(struct sde_kms *sde_kms)
+{
+	struct drm_device *dev;
+	struct drm_crtc *crtc;
+	bool sui_enhancement = false;
+
+	if (!sde_kms || !sde_kms->dev)
+		return false;
+	dev = sde_kms->dev;
+
+	if (!sde_kms->catalog->sui_misr_supported)
+		return true;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (!crtc->state || !crtc->state->active)
+			continue;
+
+		sui_enhancement |= sde_crtc_is_sui_enhancement_enabled(crtc);
+	}
+
+	if (!sui_enhancement)
+		return true;
+
+	return !sde_kms_is_secure_session_inprogress(sde_kms);
+}
+
 #ifdef CONFIG_DEBUG_FS
 static int _sde_danger_signal_status(struct seq_file *s,
 		bool danger_status)
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index ad6d279..450695d 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -305,6 +305,16 @@
 bool sde_is_custom_client(void);
 
 /**
+ * sde_kms_is_vbif_operation_allowed - resticts the VBIF programming
+ * during secure-ui, if the sec_ui_misr feature is enabled
+ *
+ * @sde_kms: Pointer to sde_kms
+ *
+ * return: false if secure-session is in progress; true otherwise
+ */
+bool sde_kms_is_vbif_operation_allowed(struct sde_kms *sde_kms);
+
+/**
  * sde_kms_power_resource_is_enabled - whether or not power resource is enabled
  * @dev: Pointer to drm device
  * Return: true if power resource is enabled; false otherwise
@@ -372,25 +382,6 @@
 }
 
 /**
- * sde_kms_is_vbif_operation_allowed - resticts the VBIF programming
- * during secure-ui, if the sec_ui_misr feature is enabled
- *
- * @sde_kms: Pointer to sde_kms
- *
- * return: false if secure-session is in progress; true otherwise
- */
-static inline bool sde_kms_is_vbif_operation_allowed(struct sde_kms *sde_kms)
-{
-	if (!sde_kms)
-		return false;
-
-	if (!sde_kms->catalog->sui_misr_supported)
-		return true;
-
-	return !sde_kms_is_secure_session_inprogress(sde_kms);
-}
-
-/**
  * Debugfs functions - extra helper functions for debugfs support
  *
  * Main debugfs documentation is located at,
diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h
index 1fb76dd..f7e9eb3 100644
--- a/drivers/gpu/msm/adreno-gpulist.h
+++ b/drivers/gpu/msm/adreno-gpulist.h
@@ -202,6 +202,20 @@
 		.regfw_name = "a530v3_seq.fw2",
 	},
 	{
+		.gpurev = ADRENO_REV_A504,
+		.core = 5,
+		.major = 0,
+		.minor = 4,
+		.patchid = ANY_ID,
+		.features = ADRENO_PREEMPTION | ADRENO_64BIT,
+		.pm4fw_name = "a530_pm4.fw",
+		.pfpfw_name = "a530_pfp.fw",
+		.gpudev = &adreno_a5xx_gpudev,
+		.gmem_size = (SZ_128K + SZ_8K),
+		.num_protected_regs = 0x20,
+		.busy_mask = 0xFFFFFFFE,
+	},
+	{
 		.gpurev = ADRENO_REV_A505,
 		.core = 5,
 		.major = 0,
@@ -368,7 +382,8 @@
 		.minor = 5,
 		.patchid = ANY_ID,
 		.features = ADRENO_64BIT | ADRENO_RPMH | ADRENO_PREEMPTION |
-			ADRENO_GPMU | ADRENO_CONTENT_PROTECTION | ADRENO_IFPC,
+			ADRENO_GPMU | ADRENO_CONTENT_PROTECTION | ADRENO_IFPC |
+			ADRENO_IOCOHERENT,
 		.sqefw_name = "a630_sqe.fw",
 		.zap_name = "a615_zap",
 		.gpudev = &adreno_a6xx_gpudev,
@@ -386,7 +401,8 @@
 		.minor = 6,
 		.patchid = ANY_ID,
 		.features = ADRENO_64BIT | ADRENO_RPMH | ADRENO_PREEMPTION |
-			ADRENO_GPMU | ADRENO_CONTENT_PROTECTION | ADRENO_IFPC,
+			ADRENO_GPMU | ADRENO_CONTENT_PROTECTION | ADRENO_IFPC |
+			ADRENO_IOCOHERENT,
 		.sqefw_name = "a630_sqe.fw",
 		.zap_name = "a615_zap",
 		.gpudev = &adreno_a6xx_gpudev,
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 763dc18..cb916ae 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -643,7 +643,7 @@
 			if (fence_retries == FENCE_RETRY_MAX) {
 				KGSL_DRV_CRIT_RATELIMIT(device,
 						"AHB fence stuck in ISR\n");
-				return ret;
+				goto done;
 			}
 			fence_retries++;
 		} while (fence != 0);
@@ -687,6 +687,7 @@
 		adreno_writereg(adreno_dev, ADRENO_REG_RBBM_INT_CLEAR_CMD,
 				int_bit);
 
+done:
 	/* Turn off the KEEPALIVE vote from earlier unless hard fault set */
 	if (gpudev->gpu_keepalive) {
 		/* If hard fault, then let snapshot turn off the keepalive */
@@ -1014,6 +1015,46 @@
 	return -ENODEV;
 }
 
+static void
+l3_pwrlevel_probe(struct kgsl_device *device, struct device_node *node)
+{
+
+	struct device_node *pwrlevel_node, *child;
+
+	pwrlevel_node = of_find_node_by_name(node, "qcom,l3-pwrlevels");
+
+	if (pwrlevel_node == NULL)
+		return;
+
+	device->num_l3_pwrlevels = 0;
+
+	for_each_child_of_node(pwrlevel_node, child) {
+		unsigned int index;
+
+		if (of_property_read_u32(child, "reg", &index))
+			return;
+		if (index >= MAX_L3_LEVELS) {
+			dev_err(&device->pdev->dev, "L3 pwrlevel %d is out of range\n",
+					index);
+			continue;
+		}
+
+		if (index >= device->num_l3_pwrlevels)
+			device->num_l3_pwrlevels = index + 1;
+
+		if (of_property_read_u32(child, "qcom,l3-freq",
+				&device->l3_freq[index]))
+			return;
+	}
+
+	device->l3_clk = devm_clk_get(&device->pdev->dev, "l3_vote");
+
+	if (IS_ERR_OR_NULL(device->l3_clk)) {
+		dev_err(&device->pdev->dev, "Unable to get the l3_vote clock\n");
+		return;
+	}
+}
+
 static inline struct adreno_device *adreno_get_dev(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id =
@@ -1060,6 +1101,8 @@
 	/* Get context aware DCVS properties */
 	adreno_of_get_ca_aware_properties(adreno_dev, node);
 
+	l3_pwrlevel_probe(device, node);
+
 	/* get pm-qos-active-latency, set it to default if not found */
 	if (of_property_read_u32(node, "qcom,pm-qos-active-latency",
 		&device->pwrctrl.pm_qos_active_latency))
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 9ca22fd..686ed34 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -203,6 +203,7 @@
 	ADRENO_REV_A418 = 418,
 	ADRENO_REV_A420 = 420,
 	ADRENO_REV_A430 = 430,
+	ADRENO_REV_A504 = 504,
 	ADRENO_REV_A505 = 505,
 	ADRENO_REV_A506 = 506,
 	ADRENO_REV_A508 = 508,
@@ -1201,6 +1202,7 @@
 			ADRENO_GPUREV(adreno_dev) < 600;
 }
 
+ADRENO_TARGET(a504, ADRENO_REV_A504)
 ADRENO_TARGET(a505, ADRENO_REV_A505)
 ADRENO_TARGET(a506, ADRENO_REV_A506)
 ADRENO_TARGET(a508, ADRENO_REV_A508)
@@ -1227,9 +1229,9 @@
 		(ADRENO_CHIPID_PATCH(adreno_dev->chipid) == 2);
 }
 
-static inline int adreno_is_a505_or_a506(struct adreno_device *adreno_dev)
+static inline int adreno_is_a504_to_a506(struct adreno_device *adreno_dev)
 {
-	return ADRENO_GPUREV(adreno_dev) >= 505 &&
+	return ADRENO_GPUREV(adreno_dev) >= 504 &&
 			ADRENO_GPUREV(adreno_dev) <= 506;
 }
 
diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c
index 4775c3e..d37753e 100644
--- a/drivers/gpu/msm/adreno_a5xx.c
+++ b/drivers/gpu/msm/adreno_a5xx.c
@@ -56,6 +56,7 @@
 	{ adreno_is_a512, a540_vbif },
 	{ adreno_is_a510, a530_vbif },
 	{ adreno_is_a508, a530_vbif },
+	{ adreno_is_a504, a530_vbif },
 	{ adreno_is_a505, a530_vbif },
 	{ adreno_is_a506, a530_vbif },
 };
@@ -127,6 +128,7 @@
 } a5xx_efuse_funcs[] = {
 	{ adreno_is_a530, a530_efuse_leakage },
 	{ adreno_is_a530, a530_efuse_speed_bin },
+	{ adreno_is_a504, a530_efuse_speed_bin },
 	{ adreno_is_a505, a530_efuse_speed_bin },
 	{ adreno_is_a512, a530_efuse_speed_bin },
 	{ adreno_is_a508, a530_efuse_speed_bin },
@@ -152,7 +154,7 @@
 	uint64_t addr;
 	struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
 
-	if (adreno_is_a505_or_a506(adreno_dev) || adreno_is_a508(adreno_dev)) {
+	if (adreno_is_a504_to_a506(adreno_dev) || adreno_is_a508(adreno_dev)) {
 		gpudev->snapshot_data->sect_sizes->cp_meq = 32;
 		gpudev->snapshot_data->sect_sizes->cp_merciu = 1024;
 		gpudev->snapshot_data->sect_sizes->roq = 256;
@@ -1178,6 +1180,7 @@
 	{ adreno_is_a530, a530_hwcg_regs, ARRAY_SIZE(a530_hwcg_regs) },
 	{ adreno_is_a512, a512_hwcg_regs, ARRAY_SIZE(a512_hwcg_regs) },
 	{ adreno_is_a510, a510_hwcg_regs, ARRAY_SIZE(a510_hwcg_regs) },
+	{ adreno_is_a504, a50x_hwcg_regs, ARRAY_SIZE(a50x_hwcg_regs) },
 	{ adreno_is_a505, a50x_hwcg_regs, ARRAY_SIZE(a50x_hwcg_regs) },
 	{ adreno_is_a506, a50x_hwcg_regs, ARRAY_SIZE(a50x_hwcg_regs) },
 	{ adreno_is_a508, a50x_hwcg_regs, ARRAY_SIZE(a50x_hwcg_regs) },
@@ -1353,13 +1356,13 @@
 
 	/* todo double check the reg writes */
 	while ((cur - opcode) < length) {
-		if (cur[0] == 1 && ((cur + 4) - opcode) <= length) {
+		if (cur[0] == 1 && (length - (cur - opcode) >= 4)) {
 			/* Write a 32 bit value to a 64 bit reg */
 			reg = cur[2];
 			reg = (reg << 32) | cur[1];
 			kgsl_regwrite(KGSL_DEVICE(adreno_dev), reg, cur[3]);
 			cur += 4;
-		} else if (cur[0] == 2 && ((cur + 5) - opcode) <= length) {
+		} else if (cur[0] == 2 && (length - (cur - opcode) >= 5)) {
 			/* Write a 64 bit value to a 64 bit reg */
 			reg = cur[2];
 			reg = (reg << 32) | cur[1];
@@ -1367,7 +1370,7 @@
 			val = (val << 32) | cur[3];
 			kgsl_regwrite(KGSL_DEVICE(adreno_dev), reg, val);
 			cur += 5;
-		} else if (cur[0] == 3 && ((cur + 2) - opcode) <= length) {
+		} else if (cur[0] == 3 && (length - (cur - opcode) >= 2)) {
 			/* Delay for X usec */
 			udelay(cur[1]);
 			cur += 2;
@@ -1924,7 +1927,7 @@
 	 * Below CP registers are 0x0 by default, program init
 	 * values based on a5xx flavor.
 	 */
-	if (adreno_is_a505_or_a506(adreno_dev) || adreno_is_a508(adreno_dev)) {
+	if (adreno_is_a504_to_a506(adreno_dev) || adreno_is_a508(adreno_dev)) {
 		kgsl_regwrite(device, A5XX_CP_MEQ_THRESHOLDS, 0x20);
 		kgsl_regwrite(device, A5XX_CP_MERCIU_SIZE, 0x400);
 		kgsl_regwrite(device, A5XX_CP_ROQ_THRESHOLDS_2, 0x40000030);
@@ -1950,7 +1953,7 @@
 	 * vtxFifo and primFifo thresholds default values
 	 * are different.
 	 */
-	if (adreno_is_a505_or_a506(adreno_dev) || adreno_is_a508(adreno_dev))
+	if (adreno_is_a504_to_a506(adreno_dev) || adreno_is_a508(adreno_dev))
 		kgsl_regwrite(device, A5XX_PC_DBG_ECO_CNTL,
 						(0x100 << 11 | 0x100 << 22));
 	else if (adreno_is_a510(adreno_dev) || adreno_is_a512(adreno_dev))
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 7096d7c..7fd11d9 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -1708,6 +1708,10 @@
 	struct device *dev = &gmu->pdev->dev;
 	int val;
 
+	/* Only trigger wakeup sequence if sleep sequence was done earlier */
+	if (!test_bit(GMU_RSCC_SLEEP_SEQ_DONE, &gmu->flags))
+		return 0;
+
 	kgsl_gmu_regread(device, A6XX_GPU_CC_GX_DOMAIN_MISC, &val);
 	if (!(val & 0x1))
 		dev_err_ratelimited(&gmu->pdev->dev,
@@ -1737,6 +1741,9 @@
 
 	kgsl_gmu_regwrite(device, A6XX_GMU_RSCC_CONTROL_REQ, 0);
 
+	/* Clear sleep sequence flag as wakeup sequence is successful */
+	clear_bit(GMU_RSCC_SLEEP_SEQ_DONE, &gmu->flags);
+
 	/* Enable the power counter because it was disabled before slumber */
 	kgsl_gmu_regwrite(device, A6XX_GMU_CX_GMU_POWER_COUNTER_ENABLE, 1);
 
@@ -1752,6 +1759,9 @@
 	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
 	int ret;
 
+	if (test_bit(GMU_RSCC_SLEEP_SEQ_DONE, &gmu->flags))
+		return 0;
+
 	/* RSC sleep sequence is different on v1 */
 	if (adreno_is_a630v1(adreno_dev))
 		kgsl_gmu_regwrite(device, A6XX_RSCC_TIMESTAMP_UNIT1_EN_DRV0, 1);
@@ -1793,6 +1803,7 @@
 			test_bit(ADRENO_LM_CTRL, &adreno_dev->pwrctrl_flag))
 		kgsl_gmu_regwrite(device, A6XX_GMU_AO_SPARE_CNTL, 0);
 
+	set_bit(GMU_RSCC_SLEEP_SEQ_DONE, &gmu->flags);
 	return 0;
 }
 
@@ -1811,15 +1822,13 @@
 	unsigned int chipid = 0;
 
 	switch (boot_state) {
-	case GMU_RESET:
-		/* fall through */
 	case GMU_COLD_BOOT:
 		/* Turn on TCM retention */
 		kgsl_gmu_regwrite(device, A6XX_GMU_GENERAL_7, 1);
 
 		if (!test_and_set_bit(GMU_BOOT_INIT_DONE, &gmu->flags))
 			_load_gmu_rpmh_ucode(device);
-		else if (boot_state != GMU_RESET) {
+		else {
 			ret = a6xx_rpmh_power_on_gpu(device);
 			if (ret)
 				return ret;
diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c
index 97b0cb2..6c8e664 100644
--- a/drivers/gpu/msm/adreno_a6xx_preempt.c
+++ b/drivers/gpu/msm/adreno_a6xx_preempt.c
@@ -749,6 +749,9 @@
 	if (context->flags & KGSL_CONTEXT_SECURE)
 		flags |= KGSL_MEMFLAGS_SECURE;
 
+	if (kgsl_is_compat_task())
+		flags |= KGSL_MEMFLAGS_FORCE_32BIT;
+
 	/*
 	 * gpumem_alloc_entry takes an extra refcount. Put it only when
 	 * destroying the context to keep the context record valid
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index df93606..f7f01f5 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -762,54 +762,13 @@
 		sizedwords, 0, NULL);
 }
 
-static int
-l3_pwrlevel_probe(struct kgsl_device *device, struct device_node *node)
-{
 
-	struct device_node *pwrlevel_node, *child;
-
-	pwrlevel_node = of_find_node_by_name(node, "qcom,l3-pwrlevels");
-
-	if (pwrlevel_node == NULL) {
-		dev_err_once(&device->pdev->dev, "Unable to find 'qcom,l3-pwrlevels'\n");
-		return -EINVAL;
-	}
-
-	device->num_l3_pwrlevels = 0;
-
-	for_each_child_of_node(pwrlevel_node, child) {
-		unsigned int index;
-
-		if (of_property_read_u32(child, "reg", &index))
-			return -EINVAL;
-		if (index >= MAX_L3_LEVELS) {
-			dev_err(&device->pdev->dev, "L3 pwrlevel %d is out of range\n",
-					index);
-			continue;
-		}
-
-		if (index >= device->num_l3_pwrlevels)
-			device->num_l3_pwrlevels = index + 1;
-
-		if (of_property_read_u32(child, "qcom,l3-freq",
-					&device->l3_freq[index]))
-		return -EINVAL;
-
-	}
-
-	return 0;
-
-}
 
 static void adreno_ringbuffer_set_constraint(struct kgsl_device *device,
 			struct kgsl_drawobj *drawobj)
 {
 	struct kgsl_context *context = drawobj->context;
-	struct device *dev = &device->pdev->dev;
 	unsigned long flags = drawobj->flags;
-	struct device_node *node;
-
-	node = device->pdev->dev.of_node;
 
 	/*
 	 * Check if the context has a constraint and constraint flags are
@@ -821,22 +780,14 @@
 		kgsl_pwrctrl_set_constraint(device, &context->pwr_constraint,
 						context->id);
 
-	if (IS_ERR_OR_NULL(device->l3_clk))
-		device->l3_clk = devm_clk_get(dev, "l3_vote");
-
-	if (IS_ERR_OR_NULL(device->l3_clk)) {
-		KGSL_DEV_ERR_ONCE(device, "Unable to get the l3_vote clock. Cannot set the L3 constraint\n");
-		return;
-	}
-
 	if (context->l3_pwr_constraint.type &&
 			((context->flags & KGSL_CONTEXT_PWR_CONSTRAINT) ||
 				(flags & KGSL_CONTEXT_PWR_CONSTRAINT))) {
 
-		int ret =  l3_pwrlevel_probe(device, node);
-
-		if (ret)
+		if (IS_ERR_OR_NULL(device->l3_clk)) {
+			KGSL_DEV_ERR_ONCE(device, "Cannot set L3 constraint\n");
 			return;
+		}
 
 		switch (context->l3_pwr_constraint.type) {
 
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 913f9bf..a2d6071 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -458,6 +458,10 @@
 
 	type = kgsl_memdesc_usermem_type(&entry->memdesc);
 	entry->priv->stats[type].cur -= entry->memdesc.size;
+
+	if (type != KGSL_MEM_ENTRY_ION)
+		entry->priv->gpumem_mapped -= entry->memdesc.mapsize;
+
 	spin_unlock(&entry->priv->mem_lock);
 
 	kgsl_mmu_put_gpuaddr(&entry->memdesc);
@@ -977,24 +981,6 @@
 	}
 }
 
-static void process_release_sync_sources(struct kgsl_process_private *private)
-{
-	struct kgsl_syncsource *syncsource;
-	int next = 0;
-
-	while (1) {
-		spin_lock(&private->syncsource_lock);
-		syncsource = idr_get_next(&private->syncsource_idr, &next);
-		spin_unlock(&private->syncsource_lock);
-
-		if (syncsource == NULL)
-			break;
-
-		kgsl_syncsource_cleanup(private, syncsource);
-		next = next + 1;
-	}
-}
-
 static void kgsl_process_private_close(struct kgsl_device_private *dev_priv,
 		struct kgsl_process_private *private)
 {
@@ -1013,7 +999,8 @@
 
 	kgsl_process_uninit_sysfs(private);
 
-	process_release_sync_sources(private);
+	/* Release all syncsource objects from process private */
+	kgsl_syncsource_process_release_syncsources(private);
 
 	/* When using global pagetables, do not detach global pagetable */
 	if (private->pagetable->name != KGSL_MMU_GLOBAL_PT)
@@ -2419,6 +2406,9 @@
 	if (!MMU_FEATURE(mmu, KGSL_MMU_IO_COHERENT))
 		param->flags &= ~((uint64_t)KGSL_MEMFLAGS_IOCOHERENT);
 
+	if (kgsl_is_compat_task())
+		param->flags |= KGSL_MEMFLAGS_FORCE_32BIT;
+
 	entry->memdesc.flags = param->flags;
 
 	if (MMU_FEATURE(mmu, KGSL_MMU_NEED_GUARD_PAGE))
@@ -2709,8 +2699,10 @@
 	if (!MMU_FEATURE(mmu, KGSL_MMU_IO_COHERENT))
 		param->flags &= ~((uint64_t)KGSL_MEMFLAGS_IOCOHERENT);
 
-	entry->memdesc.flags = ((uint64_t) param->flags)
-		| KGSL_MEMFLAGS_FORCE_32BIT;
+	entry->memdesc.flags = (uint64_t) param->flags;
+
+	if (kgsl_is_compat_task())
+		entry->memdesc.flags |= KGSL_MEMFLAGS_FORCE_32BIT;
 
 	if (!kgsl_mmu_use_cpu_map(mmu))
 		entry->memdesc.flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP);
@@ -3214,6 +3206,9 @@
 	struct kgsl_gpuobj_alloc *param = data;
 	struct kgsl_mem_entry *entry;
 
+	if (kgsl_is_compat_task())
+		param->flags |= KGSL_MEMFLAGS_FORCE_32BIT;
+
 	entry = gpumem_alloc_entry(dev_priv, param->size, param->flags);
 
 	if (IS_ERR(entry))
@@ -3241,7 +3236,9 @@
 
 	/* Legacy functions doesn't support these advanced features */
 	flags &= ~((uint64_t) KGSL_MEMFLAGS_USE_CPU_MAP);
-	flags |= KGSL_MEMFLAGS_FORCE_32BIT;
+
+	if (kgsl_is_compat_task())
+		flags |= KGSL_MEMFLAGS_FORCE_32BIT;
 
 	entry = gpumem_alloc_entry(dev_priv, (uint64_t) param->size, flags);
 
@@ -3265,7 +3262,8 @@
 	struct kgsl_mem_entry *entry;
 	uint64_t flags = param->flags;
 
-	flags |= KGSL_MEMFLAGS_FORCE_32BIT;
+	if (kgsl_is_compat_task())
+		flags |= KGSL_MEMFLAGS_FORCE_32BIT;
 
 	entry = gpumem_alloc_entry(dev_priv, (uint64_t) param->size, flags);
 
@@ -4149,13 +4147,18 @@
 kgsl_gpumem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 {
 	struct kgsl_mem_entry *entry = vma->vm_private_data;
+	int ret;
 
 	if (!entry)
 		return VM_FAULT_SIGBUS;
 	if (!entry->memdesc.ops || !entry->memdesc.ops->vmfault)
 		return VM_FAULT_SIGBUS;
 
-	return entry->memdesc.ops->vmfault(&entry->memdesc, vma, vmf);
+	ret = entry->memdesc.ops->vmfault(&entry->memdesc, vma, vmf);
+	if ((ret == 0) || (ret == VM_FAULT_NOPAGE))
+		entry->priv->gpumem_mapped += PAGE_SIZE;
+
+	return ret;
 }
 
 static void
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index f4a2de5..1fa2717 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,6 +27,7 @@
 #include <linux/uaccess.h>
 #include <linux/kthread.h>
 #include <asm/cacheflush.h>
+#include <linux/compat.h>
 
 /*
  * --- kgsl drawobj flags ---
@@ -628,4 +629,9 @@
 
 	kernfs_create_link(dst->sd, dst_name, old);
 }
+
+static inline bool kgsl_is_compat_task(void)
+{
+	return (BITS_PER_LONG == 32) || is_compat_task();
+}
 #endif /* __KGSL_H */
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index c737801..c8c6456 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -446,6 +446,7 @@
  * @kobj: Pointer to a kobj for the sysfs directory for this process
  * @debug_root: Pointer to the debugfs root for this process
  * @stats: Memory allocation statistics for this process
+ * @gpumem_mapped: KGSL memory mapped in the process address space
  * @syncsource_idr: sync sources created by this process
  * @syncsource_lock: Spinlock to protect the syncsource idr
  * @fd_count: Counter for the number of FDs for this process
@@ -467,6 +468,7 @@
 		uint64_t cur;
 		uint64_t max;
 	} stats[KGSL_MEM_ENTRY_MAX];
+	uint64_t gpumem_mapped;
 	struct idr syncsource_idr;
 	spinlock_t syncsource_lock;
 	int fd_count;
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index dbf517a..61edcc8 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -1461,7 +1461,7 @@
 			gmu_irq_enable(device);
 
 			ret = gpudev->rpmh_gpu_pwrctrl(
-				adreno_dev, GMU_FW_START, GMU_RESET, 0);
+				adreno_dev, GMU_FW_START, GMU_COLD_BOOT, 0);
 			if (ret)
 				goto error_gmu;
 
@@ -1478,7 +1478,7 @@
 			hfi_stop(gmu);
 
 			ret = gpudev->rpmh_gpu_pwrctrl(adreno_dev, GMU_FW_START,
-					GMU_RESET, 0);
+					GMU_COLD_BOOT, 0);
 			if (ret)
 				goto error_gmu;
 
diff --git a/drivers/gpu/msm/kgsl_gmu.h b/drivers/gpu/msm/kgsl_gmu.h
index 19fa972..4ef182a 100644
--- a/drivers/gpu/msm/kgsl_gmu.h
+++ b/drivers/gpu/msm/kgsl_gmu.h
@@ -102,6 +102,7 @@
 	GMU_HFI_ON = 2,
 	GMU_FAULT = 3,
 	GMU_DCVS_REPLAY = 4,
+	GMU_RSCC_SLEEP_SEQ_DONE = 5,
 };
 
 /**
@@ -139,13 +140,11 @@
 
 /*
  * These are the different ways the GMU can boot. GMU_WARM_BOOT is waking up
- * from slumber. GMU_COLD_BOOT is booting for the first time. GMU_RESET
- * is a soft reset of the GMU.
+ * from slumber. GMU_COLD_BOOT is booting for the first time.
  */
 enum gmu_boot {
 	GMU_WARM_BOOT = 0,
 	GMU_COLD_BOOT = 1,
-	GMU_RESET = 2
 };
 
 enum gmu_load_mode {
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index c4296c8..0ce72f6 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1052,7 +1052,7 @@
 
 	if (pagetable->name != KGSL_MMU_GLOBAL_PT &&
 		pagetable->name != KGSL_MMU_SECURE_PT) {
-		if ((BITS_PER_LONG == 32) || is_compat_task()) {
+		if (kgsl_is_compat_task()) {
 			pt->svm_start = KGSL_IOMMU_SVM_BASE32;
 			pt->svm_end = KGSL_IOMMU_SECURE_BASE(mmu);
 		} else {
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 3702893..2e84bad 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -97,6 +97,75 @@
 
 static void kgsl_cma_unlock_secure(struct kgsl_memdesc *memdesc);
 
+static ssize_t
+imported_mem_show(struct kgsl_process_private *priv,
+				int type, char *buf)
+{
+	struct kgsl_mem_entry *entry;
+	uint64_t imported_mem = 0;
+	int id = 0;
+
+	spin_lock(&priv->mem_lock);
+	for (entry = idr_get_next(&priv->mem_idr, &id); entry;
+		id++, entry = idr_get_next(&priv->mem_idr, &id)) {
+
+		int egl_surface_count = 0, egl_image_count = 0;
+		struct kgsl_memdesc *m;
+
+		if (kgsl_mem_entry_get(entry) == 0)
+			continue;
+		spin_unlock(&priv->mem_lock);
+
+		m = &entry->memdesc;
+		if (kgsl_memdesc_usermem_type(m) == KGSL_MEM_ENTRY_ION) {
+			kgsl_get_egl_counts(entry, &egl_surface_count,
+					&egl_image_count);
+
+			if (kgsl_memdesc_get_memtype(m) ==
+						KGSL_MEMTYPE_EGL_SURFACE)
+				imported_mem += m->size;
+			else if (egl_surface_count == 0) {
+				uint64_t size = m->size;
+
+				do_div(size, (egl_image_count ?
+							egl_image_count : 1));
+				imported_mem += size;
+			}
+		}
+
+		kgsl_mem_entry_put(entry);
+		spin_lock(&priv->mem_lock);
+	}
+	spin_unlock(&priv->mem_lock);
+
+	return scnprintf(buf, PAGE_SIZE, "%llu\n", imported_mem);
+}
+
+static ssize_t
+gpumem_mapped_show(struct kgsl_process_private *priv,
+				int type, char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%llu\n",
+			priv->gpumem_mapped);
+}
+
+static ssize_t
+gpumem_unmapped_show(struct kgsl_process_private *priv, int type, char *buf)
+{
+	if (priv->gpumem_mapped > priv->stats[type].cur)
+		return -EIO;
+
+	return scnprintf(buf, PAGE_SIZE, "%llu\n",
+			priv->stats[type].cur - priv->gpumem_mapped);
+}
+
+static struct kgsl_mem_entry_attribute debug_memstats[] = {
+	__MEM_ENTRY_ATTR(0, imported_mem, imported_mem_show),
+	__MEM_ENTRY_ATTR(0, gpumem_mapped, gpumem_mapped_show),
+	__MEM_ENTRY_ATTR(KGSL_MEM_ENTRY_KERNEL, gpumem_unmapped,
+				gpumem_unmapped_show),
+};
+
 /**
  * Show the current amount of memory allocated for the given memtype
  */
@@ -219,7 +288,13 @@
 			&mem_stats[i].max_attr.attr))
 			WARN(1, "Couldn't create sysfs file '%s'\n",
 				mem_stats[i].max_attr.attr.name);
+	}
 
+	for (i = 0; i < ARRAY_SIZE(debug_memstats); i++) {
+		if (sysfs_create_file(&private->kobj,
+			&debug_memstats[i].attr))
+			WARN(1, "Couldn't create sysfs file '%s'\n",
+				debug_memstats[i].attr.name);
 	}
 }
 
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index a4de6a0..d484894 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -623,18 +623,11 @@
 		kref_put(&syncsource->refcount, kgsl_syncsource_destroy);
 }
 
-void kgsl_syncsource_cleanup(struct kgsl_process_private *private,
+static void kgsl_syncsource_cleanup(struct kgsl_process_private *private,
 				struct kgsl_syncsource *syncsource)
 {
 	struct kgsl_syncsource_fence *sfence, *next;
 
-	spin_lock(&private->syncsource_lock);
-	if (syncsource->id != 0) {
-		idr_remove(&private->syncsource_idr, syncsource->id);
-		syncsource->id = 0;
-	}
-	spin_unlock(&private->syncsource_lock);
-
 	/* Signal all fences to release any callbacks */
 	spin_lock(&syncsource->lock);
 
@@ -659,10 +652,17 @@
 
 	spin_lock(&private->syncsource_lock);
 	syncsource = idr_find(&private->syncsource_idr, param->id);
-	spin_unlock(&private->syncsource_lock);
 
-	if (syncsource == NULL)
+	if (syncsource == NULL) {
+		spin_unlock(&private->syncsource_lock);
 		return -EINVAL;
+	}
+
+	if (syncsource->id != 0) {
+		idr_remove(&private->syncsource_idr, syncsource->id);
+		syncsource->id = 0;
+	}
+	spin_unlock(&private->syncsource_lock);
 
 	kgsl_syncsource_cleanup(private, syncsource);
 	return 0;
@@ -807,6 +807,32 @@
 	kfree(sfence);
 }
 
+void kgsl_syncsource_process_release_syncsources(
+		struct kgsl_process_private *private)
+{
+	struct kgsl_syncsource *syncsource;
+	int next = 0;
+
+	while (1) {
+		spin_lock(&private->syncsource_lock);
+		syncsource = idr_get_next(&private->syncsource_idr, &next);
+
+		if (syncsource == NULL) {
+			spin_unlock(&private->syncsource_lock);
+			break;
+		}
+
+		if (syncsource->id != 0) {
+			idr_remove(&private->syncsource_idr, syncsource->id);
+			syncsource->id = 0;
+		}
+		spin_unlock(&private->syncsource_lock);
+
+		kgsl_syncsource_cleanup(private, syncsource);
+		next = next + 1;
+	}
+}
+
 static const char *kgsl_syncsource_get_timeline_name(struct fence *fence)
 {
 	struct kgsl_syncsource_fence *sfence =
diff --git a/drivers/gpu/msm/kgsl_sync.h b/drivers/gpu/msm/kgsl_sync.h
index 955401d..6998b40 100644
--- a/drivers/gpu/msm/kgsl_sync.h
+++ b/drivers/gpu/msm/kgsl_sync.h
@@ -108,8 +108,8 @@
 
 void kgsl_syncsource_put(struct kgsl_syncsource *syncsource);
 
-void kgsl_syncsource_cleanup(struct kgsl_process_private *private,
-					struct kgsl_syncsource *syncsource);
+void kgsl_syncsource_process_release_syncsources(
+		struct kgsl_process_private *private);
 
 void kgsl_dump_fence(struct kgsl_drawobj_sync_event *event,
 					char *fence_str, int len);
@@ -182,8 +182,8 @@
 
 }
 
-static inline void kgsl_syncsource_cleanup(struct kgsl_process_private *private,
-					struct kgsl_syncsource *syncsource)
+static inline void kgsl_syncsource_process_release_syncsources(
+		struct kgsl_process_private *private)
 {
 
 }
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index bedb812..9d2ab01 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -839,9 +839,10 @@
 	if (drvdata->mode == CS_MODE_SYSFS)
 		goto out;
 
-	if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM)
+	if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) {
 		drvdata->mode = CS_MODE_SYSFS;
 		tmc_etr_enable_hw(drvdata);
+	}
 
 	drvdata->enable = true;
 	drvdata->sticky_enable = true;
diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c
index 36d07c5..93c28ef 100644
--- a/drivers/input/misc/qpnp-power-on.c
+++ b/drivers/input/misc/qpnp-power-on.c
@@ -31,6 +31,8 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/of_regulator.h>
 #include <linux/input/qpnp-power-on.h>
+#include <linux/qpnp/qpnp-pbs.h>
+#include <linux/qpnp/qpnp-misc.h>
 #include <linux/power_supply.h>
 
 #define PMIC_VER_8941           0x01
@@ -203,6 +205,7 @@
 	struct list_head	list;
 	struct delayed_work	bark_work;
 	struct dentry		*debugfs;
+	struct device_node      *pbs_dev_node;
 	int			pon_trigger_reason;
 	int			pon_power_off_reason;
 	int			num_pon_reg;
@@ -220,6 +223,7 @@
 	u8			pon_ver;
 	u8			warm_reset_reason1;
 	u8			warm_reset_reason2;
+	u8                      twm_state;
 	bool			is_spon;
 	bool			store_hard_reset_reason;
 	bool			resin_hard_reset_disable;
@@ -227,8 +231,10 @@
 	bool			ps_hold_hard_reset_disable;
 	bool			ps_hold_shutdown_disable;
 	bool			kpdpwr_dbc_enable;
+	bool                    support_twm_config;
 	bool			resin_pon_reset;
 	ktime_t			kpdpwr_last_release_time;
+	struct notifier_block   pon_nb;
 	bool			legacy_hard_reset_offset;
 };
 
@@ -483,6 +489,7 @@
 
 static DEVICE_ATTR(debounce_us, 0664, qpnp_pon_dbc_show, qpnp_pon_dbc_store);
 
+#define PON_TWM_ENTRY_PBS_BIT           BIT(0)
 static int qpnp_pon_reset_config(struct qpnp_pon *pon,
 		enum pon_power_off_type type)
 {
@@ -490,6 +497,19 @@
 	bool disable = false;
 	u16 rst_en_reg;
 
+	/* Ignore the PS_HOLD reset config if TWM ENTRY is enabled */
+	if (pon->support_twm_config && pon->twm_state == PMIC_TWM_ENABLE) {
+		rc = qpnp_pbs_trigger_event(pon->pbs_dev_node,
+					PON_TWM_ENTRY_PBS_BIT);
+		if (rc < 0) {
+			pr_err("Unable to trigger PBS trigger for TWM entry rc=%d\n",
+							rc);
+			return rc;
+		}
+		pr_crit("PMIC configured for TWM entry\n");
+		return 0;
+	}
+
 	if (pon->pon_ver == QPNP_PON_GEN1_V1)
 		rst_en_reg = QPNP_PON_PS_HOLD_RST_CTL(pon);
 	else
@@ -2087,6 +2107,35 @@
 	return 0;
 }
 
+static int pon_twm_notifier_cb(struct notifier_block *nb,
+				unsigned long action, void *data)
+{
+	struct qpnp_pon *pon = container_of(nb, struct qpnp_pon, pon_nb);
+
+	if (action != PMIC_TWM_CLEAR &&
+			action != PMIC_TWM_ENABLE) {
+		pr_debug("Unsupported option %lu\n", action);
+		return NOTIFY_OK;
+	}
+
+	pon->twm_state = (u8)action;
+	pr_debug("TWM state = %d\n", pon->twm_state);
+
+	return NOTIFY_OK;
+}
+
+static int pon_register_twm_notifier(struct qpnp_pon *pon)
+{
+	int rc;
+
+	pon->pon_nb.notifier_call = pon_twm_notifier_cb;
+	rc = qpnp_misc_twm_notifier_register(&pon->pon_nb);
+	if (rc < 0)
+		pr_err("Failed to register pon_twm_notifier_cb rc=%d\n", rc);
+
+	return rc;
+}
+
 static int qpnp_pon_probe(struct platform_device *pdev)
 {
 	struct qpnp_pon *pon;
@@ -2364,6 +2413,22 @@
 		goto err_out;
 	}
 
+	if (of_property_read_bool(pon->pdev->dev.of_node,
+					"qcom,support-twm-config")) {
+		pon->support_twm_config = true;
+		rc = pon_register_twm_notifier(pon);
+		if (rc < 0) {
+			pr_err("Failed to register TWM notifier rc=%d\n", rc);
+			return rc;
+		}
+		pon->pbs_dev_node = of_parse_phandle(pon->pdev->dev.of_node,
+						"qcom,pbs-client", 0);
+		if (!pon->pbs_dev_node) {
+			pr_err("Missing qcom,pbs-client property\n");
+			return -EINVAL;
+		}
+	}
+
 	rc = of_property_read_u32(pon->pdev->dev.of_node,
 				"qcom,pon-dbc-delay", &delay);
 	if (rc) {
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index bcb861ec..25791c2 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1205,6 +1205,24 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called colibri_vf50_ts.
 
+config TOUCHSCREEN_FT5X06_PSENSOR
+       tristate "FocalTech proximity feature support"
+       depends on TOUCHSCREEN_FT5X06 && SENSORS
+       help
+         Say Y here if you want to support ft5x06's proximity
+         feature.
+
+         If unsure, say N.
+
+config TOUCHSCREEN_FT5X06_GESTURE
+       tristate "FocalTech gesture feature support"
+       depends on TOUCHSCREEN_FT5X06
+       help
+         Say Y here if you want to support ft5x06's gesture
+         feature.
+
+         If unsure, say N.
+
 config TOUCHSCREEN_ROHM_BU21023
 	tristate "ROHM BU21023/24 Dual touch support resistive touchscreens"
 	depends on I2C
@@ -1227,4 +1245,38 @@
 source "drivers/input/touchscreen/synaptics_dsx/Kconfig"
 source "drivers/input/touchscreen/focaltech_touch/Kconfig"
 
+config TOUCHSCREEN_FT5X06
+       tristate "FocalTech touchscreens"
+       depends on I2C
+       help
+         Say Y here if you have a ft5X06 touchscreen.
+	 Ft5x06 controllers are multi touch controllers which can
+	 report 5 touches at a time.
+
+         If unsure, say N.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ft5x06_ts.
+
+config TOUCHSCREEN_GEN_VKEYS
+	tristate "Touchscreen Virtual Keys Driver"
+	help
+         Say Y here if you want to generate a sysfs entry for virtual
+	 keys on Android.
+
+	 If unsure, say N.
+
+	 To compile this driver as a module, choose M here: the
+	 module will be called gen_vkeys.
+
+config FT_SECURE_TOUCH
+	bool "Secure Touch support for Focaltech Touchscreen"
+	depends on TOUCHSCREEN_FT5X06
+	help
+	  Say Y here
+	  -Focaltech touch driver is connected
+	  -To enable secure touch for Focaltech touch driver
+
+	  If unsure, say N.
+
 endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index f2749e4..34e8823 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -37,8 +37,10 @@
 obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
 obj-$(CONFIG_TOUCHSCREEN_EGALAX)	+= egalax_ts.o
 obj-$(CONFIG_TOUCHSCREEN_EGALAX_SERIAL)	+= egalax_ts_serial.o
+obj-$(CONFIG_TOUCHSCREEN_FT5X06)	+= ft5x06_ts.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_GOODIX)	+= goodix.o
+obj-$(CONFIG_TOUCHSCREEN_GEN_VKEYS)	+= gen_vkeys.o
 obj-$(CONFIG_TOUCHSCREEN_ILI210X)	+= ili210x.o
 obj-$(CONFIG_TOUCHSCREEN_IMX6UL_TSC)	+= imx6ul_tsc.o
 obj-$(CONFIG_TOUCHSCREEN_INEXIO)	+= inexio.o
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
new file mode 100644
index 0000000..7f320b3
--- /dev/null
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -0,0 +1,2781 @@
+/*
+ *
+ * FocalTech ft5x06 TouchScreen driver.
+ *
+ * Copyright (c) 2010  Focal tech Ltd.
+ * Copyright (c) 2012-2016, 2018 The Linux Foundation. All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/firmware.h>
+#include <linux/debugfs.h>
+#include <linux/input/ft5x06_ts.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+/* Early-suspend level */
+#define FT_SUSPEND_LEVEL 1
+#endif
+
+#if defined(CONFIG_FT_SECURE_TOUCH)
+#include <linux/completion.h>
+#include <linux/atomic.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+static irqreturn_t ft5x06_ts_interrupt(int irq, void *data);
+#endif
+
+#define FT_DRIVER_VERSION	0x02
+
+#define FT_META_REGS		3
+#define FT_ONE_TCH_LEN		6
+#define FT_TCH_LEN(x)		(FT_META_REGS + FT_ONE_TCH_LEN * x)
+
+#define FT_PRESS		0x7F
+#define FT_MAX_ID		0x0F
+#define FT_TOUCH_X_H_POS	3
+#define FT_TOUCH_X_L_POS	4
+#define FT_TOUCH_Y_H_POS	5
+#define FT_TOUCH_Y_L_POS	6
+#define FT_TD_STATUS		2
+#define FT_TOUCH_EVENT_POS	3
+#define FT_TOUCH_ID_POS		5
+#define FT_TOUCH_DOWN		0
+#define FT_TOUCH_CONTACT	2
+
+/* register address*/
+#define FT_REG_DEV_MODE		0x00
+#define FT_DEV_MODE_REG_CAL	0x02
+#define FT_REG_ID		0xA3
+#define FT_REG_PMODE		0xA5
+#define FT_REG_FW_VER		0xA6
+#define FT_REG_FW_VENDOR_ID	0xA8
+#define FT_REG_POINT_RATE	0x88
+#define FT_REG_THGROUP		0x80
+#define FT_REG_ECC		0xCC
+#define FT_REG_RESET_FW		0x07
+#define FT_REG_FW_MIN_VER	0xB2
+#define FT_REG_FW_SUB_MIN_VER	0xB3
+
+/* gesture register address*/
+#define FT_REG_GESTURE_ENABLE	0xD0
+#define FT_REG_GESTURE_OUTPUT	0xD3
+
+/* gesture register bits*/
+#define FT_GESTURE_DOUBLECLICK_COORD_X		100
+#define FT_GESTURE_DOUBLECLICK_COORD_Y		100
+#define FT_GESTURE_WAKEUP_TIMEOUT		500
+#define FT_GESTURE_DEFAULT_TRACKING_ID		0x0A
+#define FT_GESTURE_DOUBLECLICK_ID		0x24
+#define FT_GESTURE_POINTER_NUM_MAX		128
+#define FT_GESTURE_POINTER_SIZEOF		4
+#define FT_GESTURE_ID_FLAG_SIZE			1
+#define FT_GESTURE_POINTER_NUM_FLAG_SIZE	1
+/* 6 bytes are taken to mark which gesture is supported in firmware */
+#define FT_GESTURE_SET_FLAG_SIZE		6
+#define I2C_TRANSFER_MAX_BYTE			255
+#define FT_GESTURE_DATA_HEADER	(FT_GESTURE_ID_FLAG_SIZE + \
+				FT_GESTURE_POINTER_NUM_FLAG_SIZE + \
+				FT_GESTURE_SET_FLAG_SIZE)
+
+/* power register bits*/
+#define FT_PMODE_ACTIVE		0x00
+#define FT_PMODE_MONITOR	0x01
+#define FT_PMODE_STANDBY	0x02
+#define FT_PMODE_HIBERNATE	0x03
+#define FT_FACTORYMODE_VALUE	0x40
+#define FT_WORKMODE_VALUE	0x00
+#define FT_RST_CMD_REG1		0xFC
+#define FT_RST_CMD_REG2		0xBC
+#define FT_READ_ID_REG		0x90
+#define FT_ERASE_APP_REG	0x61
+#define FT_ERASE_PANEL_REG	0x63
+#define FT_FW_START_REG		0xBF
+
+#define FT_STATUS_NUM_TP_MASK	0x0F
+
+#define FT_VTG_MIN_UV		2600000
+#define FT_VTG_MAX_UV		3300000
+#define FT_I2C_VTG_MIN_UV	1800000
+#define FT_I2C_VTG_MAX_UV	1800000
+
+#define FT_COORDS_ARR_SIZE	4
+#define MAX_BUTTONS		4
+
+#define FT_8BIT_SHIFT		8
+#define FT_4BIT_SHIFT		4
+#define FT_FW_NAME_MAX_LEN	50
+
+#define FT5316_ID		0x0A
+#define FT5306I_ID		0x55
+#define FT6X06_ID		0x06
+#define FT6X36_ID		0x36
+
+#define FT_UPGRADE_AA		0xAA
+#define FT_UPGRADE_55		0x55
+
+#define FT_FW_MIN_SIZE		8
+#define FT_FW_MAX_SIZE		32768
+
+/* Firmware file is not supporting minor and sub minor so use 0 */
+#define FT_FW_FILE_MAJ_VER(x)	((x)->data[(x)->size - 2])
+#define FT_FW_FILE_MIN_VER(x)	0
+#define FT_FW_FILE_SUB_MIN_VER(x) 0
+#define FT_FW_FILE_VENDOR_ID(x)	((x)->data[(x)->size - 1])
+
+#define FT_FW_FILE_MAJ_VER_FT6X36(x)	((x)->data[0x10a])
+#define FT_FW_FILE_VENDOR_ID_FT6X36(x)	((x)->data[0x108])
+
+/**
+ * Application data verification will be run before upgrade flow.
+ * Firmware image stores some flags with negative and positive value
+ * in corresponding addresses, we need pick them out do some check to
+ * make sure the application data is valid.
+ */
+#define FT_FW_CHECK(x, ts_data) \
+	(ts_data->family_id == FT6X36_ID ? \
+	(((x)->data[0x104] ^ (x)->data[0x105]) == 0xFF \
+	&& ((x)->data[0x106] ^ (x)->data[0x107]) == 0xFF) : \
+	(((x)->data[(x)->size - 8] ^ (x)->data[(x)->size - 6]) == 0xFF \
+	&& ((x)->data[(x)->size - 7] ^ (x)->data[(x)->size - 5]) == 0xFF \
+	&& ((x)->data[(x)->size - 3] ^ (x)->data[(x)->size - 4]) == 0xFF))
+
+#define FT_MAX_TRIES		5
+#define FT_RETRY_DLY		20
+
+#define FT_MAX_WR_BUF		10
+#define FT_MAX_RD_BUF		2
+#define FT_FW_PKT_LEN		128
+#define FT_FW_PKT_META_LEN	6
+#define FT_FW_PKT_DLY_MS	20
+#define FT_FW_LAST_PKT		0x6ffa
+#define FT_EARSE_DLY_MS		100
+#define FT_55_AA_DLY_NS		5000
+
+#define FT_UPGRADE_LOOP		30
+#define FT_CAL_START		0x04
+#define FT_CAL_FIN		0x00
+#define FT_CAL_STORE		0x05
+#define FT_CAL_RETRY		100
+#define FT_REG_CAL		0x00
+#define FT_CAL_MASK		0x70
+
+#define FT_INFO_MAX_LEN		512
+
+#define FT_BLOADER_SIZE_OFF	12
+#define FT_BLOADER_NEW_SIZE	30
+#define FT_DATA_LEN_OFF_OLD_FW	8
+#define FT_DATA_LEN_OFF_NEW_FW	14
+#define FT_FINISHING_PKT_LEN_OLD_FW	6
+#define FT_FINISHING_PKT_LEN_NEW_FW	12
+#define FT_MAGIC_BLOADER_Z7	0x7bfa
+#define FT_MAGIC_BLOADER_LZ4	0x6ffa
+#define FT_MAGIC_BLOADER_GZF_30	0x7ff4
+#define FT_MAGIC_BLOADER_GZF	0x7bf4
+
+#define PINCTRL_STATE_ACTIVE	"pmx_ts_active"
+#define PINCTRL_STATE_SUSPEND	"pmx_ts_suspend"
+#define PINCTRL_STATE_RELEASE	"pmx_ts_release"
+
+static irqreturn_t ft5x06_ts_interrupt(int irq, void *data);
+
+enum {
+	FT_BLOADER_VERSION_LZ4 = 0,
+	FT_BLOADER_VERSION_Z7 = 1,
+	FT_BLOADER_VERSION_GZF = 2,
+};
+
+enum {
+	FT_FT5336_FAMILY_ID_0x11 = 0x11,
+	FT_FT5336_FAMILY_ID_0x12 = 0x12,
+	FT_FT5336_FAMILY_ID_0x13 = 0x13,
+	FT_FT5336_FAMILY_ID_0x14 = 0x14,
+};
+
+#define FT_STORE_TS_INFO(buf, id, fw_maj, fw_min, fw_sub_min) \
+			snprintf(buf, FT_INFO_MAX_LEN, \
+				"vendor name = Focaltech\n" \
+				"model = 0x%x\n" \
+				"fw_version = %d.%d.%d\n", \
+				id, fw_maj, fw_min, fw_sub_min)
+#define FT_TS_INFO_SYSFS_DIR_NAME "ts_info"
+static char *ts_info_buff;
+
+#define FT_STORE_TS_DBG_INFO(buf, id, name, max_tch, group_id, \
+			fw_vkey_support, fw_name, fw_maj, fw_min, fw_sub_min) \
+			snprintf(buf, FT_INFO_MAX_LEN, \
+				"controller\t= focaltech\n" \
+				"model\t\t= 0x%x\n" \
+				"name\t\t= %s\n" \
+				"max_touches\t= %d\n" \
+				"drv_ver\t\t= 0x%x\n" \
+				"group_id\t= 0x%x\n" \
+				"fw_vkey_support\t= %s\n" \
+				"fw_name\t\t= %s\n" \
+				"fw_ver\t\t= %d.%d.%d\n", id, name, \
+				max_tch, FT_DRIVER_VERSION, group_id, \
+				fw_vkey_support, fw_name, fw_maj, fw_min, \
+				fw_sub_min)
+
+#define FT_DEBUG_DIR_NAME	"ts_debug"
+
+struct ft5x06_ts_data {
+	struct i2c_client *client;
+	struct input_dev *input_dev;
+	const struct ft5x06_ts_platform_data *pdata;
+	struct ft5x06_gesture_platform_data *gesture_pdata;
+	struct regulator *vdd;
+	struct regulator *vcc_i2c;
+	struct mutex ft_clk_io_ctrl_mutex;
+	char fw_name[FT_FW_NAME_MAX_LEN];
+	bool loading_fw;
+	u8 family_id;
+	struct dentry *dir;
+	u16 addr;
+	bool suspended;
+	char *ts_info;
+	u8 *tch_data;
+	u32 tch_data_len;
+	u8 fw_ver[3];
+	u8 fw_vendor_id;
+	struct kobject *ts_info_kobj;
+#if defined(CONFIG_FB)
+	struct work_struct fb_notify_work;
+	struct notifier_block fb_notif;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	struct early_suspend early_suspend;
+#endif
+	struct pinctrl *ts_pinctrl;
+	struct pinctrl_state *pinctrl_state_active;
+	struct pinctrl_state *pinctrl_state_suspend;
+	struct pinctrl_state *pinctrl_state_release;
+#if defined(CONFIG_FT_SECURE_TOUCH)
+	atomic_t st_enabled;
+	atomic_t st_pending_irqs;
+	struct completion st_powerdown;
+	struct completion st_irq_processed;
+	bool st_initialized;
+	struct clk *core_clk;
+	struct clk *iface_clk;
+#endif
+};
+
+static int ft5x06_ts_start(struct device *dev);
+static int ft5x06_ts_stop(struct device *dev);
+
+#if defined(CONFIG_FT_SECURE_TOUCH)
+static void ft5x06_secure_touch_init(struct ft5x06_ts_data *data)
+{
+	data->st_initialized = 0;
+
+	init_completion(&data->st_powerdown);
+	init_completion(&data->st_irq_processed);
+
+	/* Get clocks */
+	data->core_clk = devm_clk_get(&data->client->dev, "core_clk");
+	if (IS_ERR(data->core_clk)) {
+		data->core_clk = NULL;
+		dev_warn(&data->client->dev,
+			"%s: core_clk is not defined\n", __func__);
+	}
+
+	data->iface_clk = devm_clk_get(&data->client->dev, "iface_clk");
+	if (IS_ERR(data->iface_clk)) {
+		data->iface_clk = NULL;
+		dev_warn(&data->client->dev,
+			"%s: iface_clk is not defined", __func__);
+	}
+	data->st_initialized = 1;
+}
+
+static void ft5x06_secure_touch_notify(struct ft5x06_ts_data *data)
+{
+	sysfs_notify(&data->input_dev->dev.kobj, NULL, "secure_touch");
+}
+
+static irqreturn_t ft5x06_filter_interrupt(struct ft5x06_ts_data *data)
+{
+	if (atomic_read(&data->st_enabled)) {
+		if (atomic_cmpxchg(&data->st_pending_irqs, 0, 1) == 0) {
+			reinit_completion(&data->st_irq_processed);
+			ft5x06_secure_touch_notify(data);
+			wait_for_completion_interruptible(
+						&data->st_irq_processed);
+		}
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+/*
+ * 'blocking' variable will have value 'true' when we want to prevent the driver
+ * from accessing the xPU/SMMU protected HW resources while the session is
+ * active.
+ */
+static void ft5x06_secure_touch_stop(struct ft5x06_ts_data *data, bool blocking)
+{
+	if (atomic_read(&data->st_enabled)) {
+		atomic_set(&data->st_pending_irqs, -1);
+		ft5x06_secure_touch_notify(data);
+		if (blocking)
+			wait_for_completion_interruptible(
+						&data->st_powerdown);
+	}
+}
+
+static int ft5x06_clk_prepare_enable(struct ft5x06_ts_data *data)
+{
+	int ret;
+
+	ret = clk_prepare_enable(data->iface_clk);
+	if (ret) {
+		dev_err(&data->client->dev,
+			"error on clk_prepare_enable(iface_clk):%d\n", ret);
+		return ret;
+	}
+
+	ret = clk_prepare_enable(data->core_clk);
+	if (ret) {
+		clk_disable_unprepare(data->iface_clk);
+		dev_err(&data->client->dev,
+			"error clk_prepare_enable(core_clk):%d\n", ret);
+	}
+	return ret;
+}
+
+static void ft5x06_clk_disable_unprepare(struct ft5x06_ts_data *data)
+{
+	clk_disable_unprepare(data->core_clk);
+	clk_disable_unprepare(data->iface_clk);
+}
+
+static int ft5x06_bus_get(struct ft5x06_ts_data *data)
+{
+	int retval;
+
+	mutex_lock(&data->ft_clk_io_ctrl_mutex);
+	retval = pm_runtime_get_sync(data->client->adapter->dev.parent);
+	if (retval >= 0 &&  data->core_clk != NULL && data->iface_clk != NULL) {
+		retval = ft5x06_clk_prepare_enable(data);
+		if (retval)
+			pm_runtime_put_sync(data->client->adapter->dev.parent);
+	}
+	mutex_unlock(&data->ft_clk_io_ctrl_mutex);
+	return retval;
+}
+
+static void ft5x06_bus_put(struct ft5x06_ts_data *data)
+{
+	mutex_lock(&data->ft_clk_io_ctrl_mutex);
+	if (data->core_clk != NULL && data->iface_clk != NULL)
+		ft5x06_clk_disable_unprepare(data);
+	pm_runtime_put_sync(data->client->adapter->dev.parent);
+	mutex_unlock(&data->ft_clk_io_ctrl_mutex);
+}
+
+static ssize_t ft5x06_secure_touch_enable_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%d", atomic_read(&data->st_enabled));
+}
+
+/*
+ * Accept only "0" and "1" valid values.
+ * "0" will reset the st_enabled flag, then wake up the reading process and
+ * the interrupt handler.
+ * The bus driver is notified via pm_runtime that it is not required to stay
+ * awake anymore.
+ * It will also make sure the queue of events is emptied in the controller,
+ * in case a touch happened in between the secure touch being disabled and
+ * the local ISR being ungated.
+ * "1" will set the st_enabled flag and clear the st_pending_irqs flag.
+ * The bus driver is requested via pm_runtime to stay awake.
+ */
+static ssize_t ft5x06_secure_touch_enable_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+	unsigned long value;
+	int err = 0;
+
+	if (count > 2)
+		return -EINVAL;
+	err = kstrtoul(buf, 10, &value);
+	if (err != 0)
+		return err;
+
+	if (!data->st_initialized)
+		return -EIO;
+
+	err = count;
+	switch (value) {
+	case 0:
+		if (atomic_read(&data->st_enabled) == 0)
+			break;
+		ft5x06_bus_put(data);
+		atomic_set(&data->st_enabled, 0);
+		ft5x06_secure_touch_notify(data);
+		complete(&data->st_irq_processed);
+		ft5x06_ts_interrupt(data->client->irq, data);
+		complete(&data->st_powerdown);
+		break;
+
+	case 1:
+		if (atomic_read(&data->st_enabled)) {
+			err = -EBUSY;
+			break;
+		}
+		synchronize_irq(data->client->irq);
+		if (ft5x06_bus_get(data) < 0) {
+			dev_err(&data->client->dev, "ft5x06_bus_get failed\n");
+			err = -EIO;
+			break;
+		}
+		reinit_completion(&data->st_powerdown);
+		reinit_completion(&data->st_irq_processed);
+		atomic_set(&data->st_enabled, 1);
+		atomic_set(&data->st_pending_irqs,  0);
+		break;
+
+	default:
+		dev_err(&data->client->dev, "unsupported value: %lu\n", value);
+		err = -EINVAL;
+		break;
+	}
+	return err;
+}
+
+/*
+ * This function returns whether there are pending interrupts, or
+ * other error conditions that need to be signaled to the userspace library,
+ * according tot he following logic:
+ * - st_enabled is 0 if secure touch is not enabled, returning -EBADF
+ * - st_pending_irqs is -1 to signal that secure touch is in being stopped,
+ *   returning -EINVAL
+ * - st_pending_irqs is 1 to signal that there is a pending irq, returning
+ *   the value "1" to the sysfs read operation
+ * - st_pending_irqs is 0 (only remaining case left) if the pending interrupt
+ *   has been processed, so the interrupt handler can be allowed to continue.
+ */
+static ssize_t ft5x06_secure_touch_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+	int val = 0;
+
+	if (atomic_read(&data->st_enabled) == 0)
+		return -EBADF;
+	if (atomic_cmpxchg(&data->st_pending_irqs, -1, 0) == -1)
+		return -EINVAL;
+	if (atomic_cmpxchg(&data->st_pending_irqs, 1, 0) == 1)
+		val = 1;
+	else
+		complete(&data->st_irq_processed);
+	return scnprintf(buf, PAGE_SIZE, "%u", val);
+}
+#else
+static void ft5x06_secure_touch_init(struct ft5x06_ts_data *data)
+{
+}
+static irqreturn_t ft5x06_filter_interrupt(struct ft5x06_ts_data *data)
+{
+	return IRQ_NONE;
+}
+static void ft5x06_secure_touch_stop(struct ft5x06_ts_data *data, bool blocking)
+{
+}
+#endif
+
+static struct device_attribute attrs[] = {
+#if defined(CONFIG_FT_SECURE_TOUCH)
+		__ATTR(secure_touch_enable, (0664),
+				ft5x06_secure_touch_enable_show,
+				ft5x06_secure_touch_enable_store),
+		__ATTR(secure_touch, 0444,
+				ft5x06_secure_touch_show, NULL),
+#endif
+};
+
+static inline bool ft5x06_gesture_support_enabled(void)
+{
+	return IS_ENABLED(CONFIG_TOUCHSCREEN_FT5X06_GESTURE);
+}
+
+static int ft5x06_i2c_read(struct i2c_client *client, char *writebuf,
+			   int writelen, char *readbuf, int readlen)
+{
+	int ret;
+
+	if (writelen > 0) {
+		struct i2c_msg msgs[] = {
+			{
+				 .addr = client->addr,
+				 .flags = 0,
+				 .len = writelen,
+				 .buf = writebuf,
+			 },
+			{
+				 .addr = client->addr,
+				 .flags = I2C_M_RD,
+				 .len = readlen,
+				 .buf = readbuf,
+			 },
+		};
+		ret = i2c_transfer(client->adapter, msgs, 2);
+		if (ret < 0)
+			dev_err(&client->dev, "%s: i2c read error.\n",
+				__func__);
+	} else {
+		struct i2c_msg msgs[] = {
+			{
+				 .addr = client->addr,
+				 .flags = I2C_M_RD,
+				 .len = readlen,
+				 .buf = readbuf,
+			 },
+		};
+		ret = i2c_transfer(client->adapter, msgs, 1);
+		if (ret < 0)
+			dev_err(&client->dev, "%s:i2c read error.\n", __func__);
+	}
+	return ret;
+}
+
+static int ft5x06_i2c_write(struct i2c_client *client, char *writebuf,
+			    int writelen)
+{
+	int ret;
+
+	struct i2c_msg msgs[] = {
+		{
+			 .addr = client->addr,
+			 .flags = 0,
+			 .len = writelen,
+			 .buf = writebuf,
+		 },
+	};
+	ret = i2c_transfer(client->adapter, msgs, 1);
+	if (ret < 0)
+		dev_err(&client->dev, "%s: i2c write error.\n", __func__);
+
+	return ret;
+}
+
+static int ft5x0x_write_reg(struct i2c_client *client, u8 addr, const u8 val)
+{
+	u8 buf[2] = {0};
+
+	buf[0] = addr;
+	buf[1] = val;
+
+	return ft5x06_i2c_write(client, buf, sizeof(buf));
+}
+
+static int ft5x0x_read_reg(struct i2c_client *client, u8 addr, u8 *val)
+{
+	return ft5x06_i2c_read(client, &addr, 1, val, 1);
+}
+
+#ifdef CONFIG_TOUCHSCREEN_FT5X06_GESTURE
+static ssize_t ft5x06_gesture_enable_to_set_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n",
+			data->gesture_pdata->gesture_enable_to_set);
+}
+
+static ssize_t ft5x06_gesture_enable_to_set_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+	unsigned long value = 0;
+	int ret;
+
+	if (data->suspended)
+		return -EINVAL;
+
+	ret = kstrtoul(buf, 16, &value);
+	if (ret < 0) {
+		dev_err(dev, "%s:kstrtoul failed, ret=0x%x\n",
+			__func__, ret);
+		return ret;
+	}
+
+	if (value == 1)
+		data->gesture_pdata->gesture_enable_to_set = 1;
+	else
+		data->gesture_pdata->gesture_enable_to_set = 0;
+	return size;
+}
+
+static DEVICE_ATTR(enable, 0664,
+		ft5x06_gesture_enable_to_set_show,
+		ft5x06_gesture_enable_to_set_store);
+
+static int ft5x06_entry_pocket(struct device *dev)
+{
+	return ft5x06_ts_stop(dev);
+}
+
+static int ft5x06_leave_pocket(struct device *dev)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+	int err;
+
+	ft5x06_ts_start(dev);
+	ft5x0x_write_reg(data->client, FT_REG_GESTURE_ENABLE, 1);
+	err = enable_irq_wake(data->client->irq);
+	if (err)
+		dev_err(&data->client->dev,
+			"%s: set_irq_wake failed\n", __func__);
+	data->suspended = true;
+
+	return err;
+}
+
+static ssize_t gesture_in_pocket_mode_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%d\n",
+			data->gesture_pdata->in_pocket);
+}
+
+static ssize_t gesture_in_pocket_mode_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+	unsigned long value = 0;
+	int ret;
+
+	ret = kstrtoul(buf, 16, &value);
+	if (ret < 0) {
+		dev_err(dev, "%s:kstrtoul failed, ret=0x%x\n",
+			__func__, ret);
+		return ret;
+	}
+
+	if (value == 1 && data->gesture_pdata->in_pocket == 0) {
+		data->gesture_pdata->in_pocket = 1;
+		ft5x06_entry_pocket(dev);
+	} else if (value == 0 && data->gesture_pdata->in_pocket == 1) {
+		ft5x06_leave_pocket(dev);
+		data->gesture_pdata->in_pocket = 0;
+	}
+	return size;
+}
+
+static DEVICE_ATTR(pocket, 0664,
+		gesture_in_pocket_mode_show,
+		gesture_in_pocket_mode_store);
+
+static int ft5x06_report_gesture_doubleclick(struct input_dev *ip_dev)
+{
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		input_mt_slot(ip_dev, FT_GESTURE_DEFAULT_TRACKING_ID);
+		input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1);
+		input_report_abs(ip_dev, ABS_MT_POSITION_X,
+					FT_GESTURE_DOUBLECLICK_COORD_X);
+		input_report_abs(ip_dev, ABS_MT_POSITION_Y,
+					FT_GESTURE_DOUBLECLICK_COORD_Y);
+		input_mt_report_pointer_emulation(ip_dev, false);
+		input_sync(ip_dev);
+		input_mt_slot(ip_dev, FT_GESTURE_DEFAULT_TRACKING_ID);
+		input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
+		input_mt_report_pointer_emulation(ip_dev, false);
+		input_sync(ip_dev);
+	}
+	return 0;
+}
+
+static int ft5x06_report_gesture(struct i2c_client *i2c_client,
+		struct input_dev *ip_dev)
+{
+	int i, temp, gesture_data_size;
+	int gesture_coord_x, gesture_coord_y;
+	int ret = -1;
+	short pointnum = 0;
+	unsigned char buf[FT_GESTURE_POINTER_NUM_MAX *
+			FT_GESTURE_POINTER_SIZEOF + FT_GESTURE_DATA_HEADER];
+
+	buf[0] = FT_REG_GESTURE_OUTPUT;
+	ret = ft5x06_i2c_read(i2c_client, buf, 1,
+				buf, FT_GESTURE_DATA_HEADER);
+	if (ret < 0) {
+		dev_err(&i2c_client->dev, "%s read touchdata failed.\n",
+			__func__);
+		return ret;
+	}
+
+	/* FW support doubleclick */
+	if (buf[0] == FT_GESTURE_DOUBLECLICK_ID) {
+		ft5x06_report_gesture_doubleclick(ip_dev);
+		return 0;
+	}
+
+	pointnum = (short)(buf[1]) & 0xff;
+	gesture_data_size = pointnum * FT_GESTURE_POINTER_SIZEOF +
+			FT_GESTURE_DATA_HEADER;
+	buf[0] = FT_REG_GESTURE_OUTPUT;
+	temp = gesture_data_size / I2C_TRANSFER_MAX_BYTE;
+	for (i = 0; i < temp; i++)
+		ret = ft5x06_i2c_read(i2c_client, buf, ((i == 0) ? 1 : 0),
+			buf + I2C_TRANSFER_MAX_BYTE * i, I2C_TRANSFER_MAX_BYTE);
+	ret = ft5x06_i2c_read(i2c_client, buf, ((temp == 0) ? 1 : 0),
+			buf + I2C_TRANSFER_MAX_BYTE * temp,
+			gesture_data_size - I2C_TRANSFER_MAX_BYTE * temp);
+	if (ret < 0) {
+		dev_err(&i2c_client->dev, "%s read touchdata failed.\n",
+			__func__);
+		return ret;
+	}
+
+	for (i = 0; i < pointnum; i++) {
+		gesture_coord_x = (((s16) buf[FT_GESTURE_DATA_HEADER +
+				(FT_GESTURE_POINTER_SIZEOF * i)]) & 0x0F) << 8 |
+				(((s16) buf[FT_GESTURE_DATA_HEADER + 1 +
+				(FT_GESTURE_POINTER_SIZEOF * i)]) & 0xFF);
+		gesture_coord_y = (((s16) buf[FT_GESTURE_DATA_HEADER + 2 +
+				(FT_GESTURE_POINTER_SIZEOF * i)]) & 0x0F) << 8 |
+				(((s16) buf[FT_GESTURE_DATA_HEADER + 3 +
+				(FT_GESTURE_POINTER_SIZEOF * i)]) & 0xFF);
+		input_mt_slot(ip_dev, FT_GESTURE_DEFAULT_TRACKING_ID);
+		input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1);
+		input_report_abs(ip_dev, ABS_MT_POSITION_X, gesture_coord_x);
+		input_report_abs(ip_dev, ABS_MT_POSITION_Y, gesture_coord_y);
+		input_mt_report_pointer_emulation(ip_dev, false);
+		input_sync(ip_dev);
+	}
+	input_mt_slot(ip_dev, FT_GESTURE_DEFAULT_TRACKING_ID);
+	input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
+	input_mt_report_pointer_emulation(ip_dev, false);
+	input_sync(ip_dev);
+
+	return 0;
+}
+#else
+static DEVICE_ATTR(pocket, 0664, NULL, NULL);
+static DEVICE_ATTR(enable, 0664, NULL, NULL);
+
+static int ft5x06_report_gesture(struct i2c_client *i2c_client,
+		struct input_dev *ip_dev)
+{
+	return 0;
+}
+#endif
+
+static void ft5x06_update_fw_vendor_id(struct ft5x06_ts_data *data)
+{
+	struct i2c_client *client = data->client;
+	u8 reg_addr;
+	int err;
+
+	reg_addr = FT_REG_FW_VENDOR_ID;
+	err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_vendor_id, 1);
+	if (err < 0)
+		dev_err(&client->dev, "fw vendor id read failed");
+}
+
+static void ft5x06_update_fw_ver(struct ft5x06_ts_data *data)
+{
+	struct i2c_client *client = data->client;
+	u8 reg_addr;
+	int err;
+
+	reg_addr = FT_REG_FW_VER;
+	err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_ver[0], 1);
+	if (err < 0)
+		dev_err(&client->dev, "fw major version read failed");
+
+	reg_addr = FT_REG_FW_MIN_VER;
+	err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_ver[1], 1);
+	if (err < 0)
+		dev_err(&client->dev, "fw minor version read failed");
+
+	reg_addr = FT_REG_FW_SUB_MIN_VER;
+	err = ft5x06_i2c_read(client, &reg_addr, 1, &data->fw_ver[2], 1);
+	if (err < 0)
+		dev_err(&client->dev, "fw sub minor version read failed");
+
+	dev_info(&client->dev, "Firmware version = %d.%d.%d\n",
+		data->fw_ver[0], data->fw_ver[1], data->fw_ver[2]);
+}
+
+static irqreturn_t ft5x06_ts_interrupt(int irq, void *dev_id)
+{
+	struct ft5x06_ts_data *data = dev_id;
+	struct input_dev *ip_dev;
+	int rc, i;
+	u32 id, x, y, status, num_touches;
+	u8 reg, *buf, gesture_is_active;
+	bool update_input = false;
+
+	if (!data) {
+		pr_err("%s: Invalid data\n", __func__);
+		return IRQ_HANDLED;
+	}
+
+	if (ft5x06_filter_interrupt(data) == IRQ_HANDLED)
+		return IRQ_HANDLED;
+
+	ip_dev = data->input_dev;
+	buf = data->tch_data;
+
+	if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support) {
+		ft5x0x_read_reg(data->client, FT_REG_GESTURE_ENABLE,
+					&gesture_is_active);
+		if (gesture_is_active) {
+			pm_wakeup_event(&(data->client->dev),
+					FT_GESTURE_WAKEUP_TIMEOUT);
+			ft5x06_report_gesture(data->client, ip_dev);
+			return IRQ_HANDLED;
+		}
+	}
+
+	/*
+	 * Read touch data start from register FT_REG_DEV_MODE.
+	 * The touch x/y value start from FT_TOUCH_X_H/L_POS and
+	 * FT_TOUCH_Y_H/L_POS in buf.
+	 */
+	reg = FT_REG_DEV_MODE;
+	rc = ft5x06_i2c_read(data->client, &reg, 1, buf, data->tch_data_len);
+	if (rc < 0) {
+		dev_err(&data->client->dev, "%s: read data fail\n", __func__);
+		return IRQ_HANDLED;
+	}
+
+	for (i = 0; i < data->pdata->num_max_touches; i++) {
+		/*
+		 * Getting the finger ID of the touch event incase of
+		 * multiple touch events
+		 */
+		id = (buf[FT_TOUCH_ID_POS + FT_ONE_TCH_LEN * i]) >> 4;
+		if (id >= FT_MAX_ID)
+			break;
+
+		update_input = true;
+
+		x = (buf[FT_TOUCH_X_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
+			(buf[FT_TOUCH_X_L_POS + FT_ONE_TCH_LEN * i]);
+		y = (buf[FT_TOUCH_Y_H_POS + FT_ONE_TCH_LEN * i] & 0x0F) << 8 |
+			(buf[FT_TOUCH_Y_L_POS + FT_ONE_TCH_LEN * i]);
+
+		status = buf[FT_TOUCH_EVENT_POS + FT_ONE_TCH_LEN * i] >> 6;
+
+		num_touches = buf[FT_TD_STATUS] & FT_STATUS_NUM_TP_MASK;
+
+		/* invalid combination */
+		if (!num_touches && !status && !id)
+			break;
+
+		input_mt_slot(ip_dev, id);
+		if (status == FT_TOUCH_DOWN || status == FT_TOUCH_CONTACT) {
+			input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 1);
+			input_report_abs(ip_dev, ABS_MT_POSITION_X, x);
+			input_report_abs(ip_dev, ABS_MT_POSITION_Y, y);
+		} else {
+			input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
+		}
+	}
+
+	if (update_input) {
+		input_mt_report_pointer_emulation(ip_dev, false);
+		input_sync(ip_dev);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int ft5x06_gpio_configure(struct ft5x06_ts_data *data, bool on)
+{
+	int err = 0;
+
+	if (on) {
+		if (gpio_is_valid(data->pdata->irq_gpio)) {
+			err = gpio_request(data->pdata->irq_gpio,
+						"ft5x06_irq_gpio");
+			if (err) {
+				dev_err(&data->client->dev,
+					"irq gpio request failed");
+				goto err_irq_gpio_req;
+			}
+
+			err = gpio_direction_input(data->pdata->irq_gpio);
+			if (err) {
+				dev_err(&data->client->dev,
+					"set_direction for irq gpio failed\n");
+				goto err_irq_gpio_dir;
+			}
+		}
+
+		if (gpio_is_valid(data->pdata->reset_gpio)) {
+			err = gpio_request(data->pdata->reset_gpio,
+						"ft5x06_reset_gpio");
+			if (err) {
+				dev_err(&data->client->dev,
+					"reset gpio request failed");
+				goto err_irq_gpio_dir;
+			}
+
+			err = gpio_direction_output(data->pdata->reset_gpio, 0);
+			if (err) {
+				dev_err(&data->client->dev,
+				"set_direction for reset gpio failed\n");
+				goto err_reset_gpio_dir;
+			}
+			msleep(data->pdata->hard_rst_dly);
+			gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
+		}
+
+		return 0;
+	}
+	if (gpio_is_valid(data->pdata->irq_gpio))
+		gpio_free(data->pdata->irq_gpio);
+	if (gpio_is_valid(data->pdata->reset_gpio)) {
+		/*
+		 * This is intended to save leakage current
+		 * only. Even if the call(gpio_direction_input)
+		 * fails, only leakage current will be more but
+		 * functionality will not be affected.
+		 */
+		err = gpio_direction_input(data->pdata->reset_gpio);
+		if (err) {
+			dev_err(&data->client->dev,
+				"unable to set direction for gpio [%d]\n",
+				data->pdata->irq_gpio);
+		}
+		gpio_free(data->pdata->reset_gpio);
+	}
+
+		return 0;
+
+err_reset_gpio_dir:
+	if (gpio_is_valid(data->pdata->reset_gpio))
+		gpio_free(data->pdata->reset_gpio);
+err_irq_gpio_dir:
+	if (gpio_is_valid(data->pdata->irq_gpio))
+		gpio_free(data->pdata->irq_gpio);
+err_irq_gpio_req:
+	return err;
+}
+
+static int ft5x06_power_on(struct ft5x06_ts_data *data, bool on)
+{
+	int rc;
+
+	if (!on)
+		goto power_off;
+
+	rc = regulator_enable(data->vdd);
+	if (rc) {
+		dev_err(&data->client->dev,
+			"Regulator vdd enable failed rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = regulator_enable(data->vcc_i2c);
+	if (rc) {
+		dev_err(&data->client->dev,
+			"Regulator vcc_i2c enable failed rc=%d\n", rc);
+		regulator_disable(data->vdd);
+	}
+
+	return rc;
+
+power_off:
+	rc = regulator_disable(data->vdd);
+	if (rc) {
+		dev_err(&data->client->dev,
+			"Regulator vdd disable failed rc=%d\n", rc);
+		return rc;
+	}
+
+	rc = regulator_disable(data->vcc_i2c);
+	if (rc) {
+		dev_err(&data->client->dev,
+			"Regulator vcc_i2c disable failed rc=%d\n", rc);
+		rc = regulator_enable(data->vdd);
+		if (rc) {
+			dev_err(&data->client->dev,
+				"Regulator vdd enable failed rc=%d\n", rc);
+		}
+	}
+
+	return rc;
+}
+
+static int ft5x06_power_init(struct ft5x06_ts_data *data, bool on)
+{
+	int rc;
+
+	if (!on)
+		goto pwr_deinit;
+
+	data->vdd = regulator_get(&data->client->dev, "vdd");
+	if (IS_ERR(data->vdd)) {
+		rc = PTR_ERR(data->vdd);
+		dev_err(&data->client->dev,
+			"Regulator get failed vdd rc=%d\n", rc);
+		return rc;
+	}
+
+	if (regulator_count_voltages(data->vdd) > 0) {
+		rc = regulator_set_voltage(data->vdd, FT_VTG_MIN_UV,
+					   FT_VTG_MAX_UV);
+		if (rc) {
+			dev_err(&data->client->dev,
+				"Regulator set_vtg failed vdd rc=%d\n", rc);
+			goto reg_vdd_put;
+		}
+	}
+
+	data->vcc_i2c = regulator_get(&data->client->dev, "vcc_i2c");
+	if (IS_ERR(data->vcc_i2c)) {
+		rc = PTR_ERR(data->vcc_i2c);
+		dev_err(&data->client->dev,
+			"Regulator get failed vcc_i2c rc=%d\n", rc);
+		goto reg_vdd_set_vtg;
+	}
+
+	if (regulator_count_voltages(data->vcc_i2c) > 0) {
+		rc = regulator_set_voltage(data->vcc_i2c, FT_I2C_VTG_MIN_UV,
+					   FT_I2C_VTG_MAX_UV);
+		if (rc) {
+			dev_err(&data->client->dev,
+			"Regulator set_vtg failed vcc_i2c rc=%d\n", rc);
+			goto reg_vcc_i2c_put;
+		}
+	}
+
+	return 0;
+
+reg_vcc_i2c_put:
+	regulator_put(data->vcc_i2c);
+reg_vdd_set_vtg:
+	if (regulator_count_voltages(data->vdd) > 0)
+		regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
+reg_vdd_put:
+	regulator_put(data->vdd);
+	return rc;
+
+pwr_deinit:
+	if (regulator_count_voltages(data->vdd) > 0)
+		regulator_set_voltage(data->vdd, 0, FT_VTG_MAX_UV);
+
+	regulator_put(data->vdd);
+
+	if (regulator_count_voltages(data->vcc_i2c) > 0)
+		regulator_set_voltage(data->vcc_i2c, 0, FT_I2C_VTG_MAX_UV);
+
+	regulator_put(data->vcc_i2c);
+	return 0;
+}
+
+static int ft5x06_ts_pinctrl_init(struct ft5x06_ts_data *ft5x06_data)
+{
+	int retval;
+
+	/* Get pinctrl if target uses pinctrl */
+	ft5x06_data->ts_pinctrl = devm_pinctrl_get(&(ft5x06_data->client->dev));
+	if (IS_ERR_OR_NULL(ft5x06_data->ts_pinctrl)) {
+		retval = PTR_ERR(ft5x06_data->ts_pinctrl);
+		dev_dbg(&ft5x06_data->client->dev,
+			"Target does not use pinctrl %d\n", retval);
+		goto err_pinctrl_get;
+	}
+
+	ft5x06_data->pinctrl_state_active
+		= pinctrl_lookup_state(ft5x06_data->ts_pinctrl,
+				PINCTRL_STATE_ACTIVE);
+	if (IS_ERR_OR_NULL(ft5x06_data->pinctrl_state_active)) {
+		retval = PTR_ERR(ft5x06_data->pinctrl_state_active);
+		dev_err(&ft5x06_data->client->dev,
+			"Can not lookup %s pinstate %d\n",
+			PINCTRL_STATE_ACTIVE, retval);
+		goto err_pinctrl_lookup;
+	}
+
+	ft5x06_data->pinctrl_state_suspend
+		= pinctrl_lookup_state(ft5x06_data->ts_pinctrl,
+			PINCTRL_STATE_SUSPEND);
+	if (IS_ERR_OR_NULL(ft5x06_data->pinctrl_state_suspend)) {
+		retval = PTR_ERR(ft5x06_data->pinctrl_state_suspend);
+		dev_err(&ft5x06_data->client->dev,
+			"Can not lookup %s pinstate %d\n",
+			PINCTRL_STATE_SUSPEND, retval);
+		goto err_pinctrl_lookup;
+	}
+
+	ft5x06_data->pinctrl_state_release
+		= pinctrl_lookup_state(ft5x06_data->ts_pinctrl,
+			PINCTRL_STATE_RELEASE);
+	if (IS_ERR_OR_NULL(ft5x06_data->pinctrl_state_release)) {
+		retval = PTR_ERR(ft5x06_data->pinctrl_state_release);
+		dev_dbg(&ft5x06_data->client->dev,
+			"Can not lookup %s pinstate %d\n",
+			PINCTRL_STATE_RELEASE, retval);
+	}
+
+	return 0;
+
+err_pinctrl_lookup:
+	devm_pinctrl_put(ft5x06_data->ts_pinctrl);
+err_pinctrl_get:
+	ft5x06_data->ts_pinctrl = NULL;
+	return retval;
+}
+
+#ifdef CONFIG_PM
+static int ft5x06_ts_start(struct device *dev)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+	int err;
+
+	if (data->pdata->power_on) {
+		err = data->pdata->power_on(true);
+		if (err) {
+			dev_err(dev, "power on failed");
+			return err;
+		}
+	} else {
+		err = ft5x06_power_on(data, true);
+		if (err) {
+			dev_err(dev, "power on failed");
+			return err;
+		}
+	}
+
+	if (data->ts_pinctrl) {
+		err = pinctrl_select_state(data->ts_pinctrl,
+				data->pinctrl_state_active);
+		if (err < 0)
+			dev_err(dev, "Cannot get active pinctrl state\n");
+	}
+
+	err = ft5x06_gpio_configure(data, true);
+	if (err < 0) {
+		dev_err(&data->client->dev,
+			"failed to put gpios in resue state\n");
+		goto err_gpio_configuration;
+	}
+
+	if (gpio_is_valid(data->pdata->reset_gpio)) {
+		gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
+		msleep(data->pdata->hard_rst_dly);
+		gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
+	}
+
+	msleep(data->pdata->soft_rst_dly);
+
+	enable_irq(data->client->irq);
+	data->suspended = false;
+
+	return 0;
+
+err_gpio_configuration:
+	if (data->ts_pinctrl) {
+		err = pinctrl_select_state(data->ts_pinctrl,
+					data->pinctrl_state_suspend);
+		if (err < 0)
+			dev_err(dev, "Cannot get suspend pinctrl state\n");
+	}
+	if (data->pdata->power_on) {
+		err = data->pdata->power_on(false);
+		if (err)
+			dev_err(dev, "power off failed");
+	} else {
+		err = ft5x06_power_on(data, false);
+		if (err)
+			dev_err(dev, "power off failed");
+	}
+	return err;
+}
+
+static int ft5x06_ts_stop(struct device *dev)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+	char txbuf[2];
+	int i, err;
+
+	disable_irq(data->client->irq);
+
+	/* release all touches */
+	for (i = 0; i < data->pdata->num_max_touches; i++) {
+		input_mt_slot(data->input_dev, i);
+		input_mt_report_slot_state(data->input_dev, MT_TOOL_FINGER, 0);
+	}
+	input_mt_report_pointer_emulation(data->input_dev, false);
+	input_sync(data->input_dev);
+
+	if (gpio_is_valid(data->pdata->reset_gpio)) {
+		txbuf[0] = FT_REG_PMODE;
+		txbuf[1] = FT_PMODE_HIBERNATE;
+		ft5x06_i2c_write(data->client, txbuf, sizeof(txbuf));
+	}
+
+	if (data->pdata->power_on) {
+		err = data->pdata->power_on(false);
+		if (err) {
+			dev_err(dev, "power off failed");
+			goto pwr_off_fail;
+		}
+	} else {
+		err = ft5x06_power_on(data, false);
+		if (err) {
+			dev_err(dev, "power off failed");
+			goto pwr_off_fail;
+		}
+	}
+
+	if (data->ts_pinctrl) {
+		err = pinctrl_select_state(data->ts_pinctrl,
+					data->pinctrl_state_suspend);
+		if (err < 0)
+			dev_err(dev, "Cannot get suspend pinctrl state\n");
+	}
+
+	err = ft5x06_gpio_configure(data, false);
+	if (err < 0) {
+		dev_err(&data->client->dev,
+			"failed to put gpios in suspend state\n");
+		goto gpio_configure_fail;
+	}
+
+	data->suspended = true;
+
+	return 0;
+
+gpio_configure_fail:
+	if (data->ts_pinctrl) {
+		err = pinctrl_select_state(data->ts_pinctrl,
+					data->pinctrl_state_active);
+		if (err < 0)
+			dev_err(dev, "Cannot get active pinctrl state\n");
+	}
+	if (data->pdata->power_on) {
+		err = data->pdata->power_on(true);
+		if (err)
+			dev_err(dev, "power on failed");
+	} else {
+		err = ft5x06_power_on(data, true);
+		if (err)
+			dev_err(dev, "power on failed");
+	}
+pwr_off_fail:
+	if (gpio_is_valid(data->pdata->reset_gpio)) {
+		gpio_set_value_cansleep(data->pdata->reset_gpio, 0);
+		msleep(data->pdata->hard_rst_dly);
+		gpio_set_value_cansleep(data->pdata->reset_gpio, 1);
+	}
+	enable_irq(data->client->irq);
+	return err;
+}
+
+static int ft5x06_ts_suspend(struct device *dev)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+	int err;
+
+	if (data->loading_fw) {
+		dev_info(dev, "Firmware loading in process...\n");
+		return 0;
+	}
+
+	if (data->suspended) {
+		dev_info(dev, "Already in suspend state\n");
+		return 0;
+	}
+
+	ft5x06_secure_touch_stop(data, true);
+
+	if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support &&
+		device_may_wakeup(dev) &&
+		data->gesture_pdata->gesture_enable_to_set) {
+
+		ft5x0x_write_reg(data->client, FT_REG_GESTURE_ENABLE, 1);
+		err = enable_irq_wake(data->client->irq);
+		if (err)
+			dev_err(&data->client->dev,
+				"%s: set_irq_wake failed\n", __func__);
+		data->suspended = true;
+		return err;
+	}
+
+	return ft5x06_ts_stop(dev);
+}
+
+static int ft5x06_ts_resume(struct device *dev)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+	int err;
+
+	if (!data->suspended) {
+		dev_dbg(dev, "Already in awake state\n");
+		return 0;
+	}
+
+	ft5x06_secure_touch_stop(data, true);
+
+	if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support &&
+		device_may_wakeup(dev) &&
+		!(data->gesture_pdata->in_pocket) &&
+		data->gesture_pdata->gesture_enable_to_set) {
+
+		ft5x0x_write_reg(data->client, FT_REG_GESTURE_ENABLE, 0);
+		err = disable_irq_wake(data->client->irq);
+		if (err)
+			dev_err(dev, "%s: disable_irq_wake failed\n",
+				__func__);
+		data->suspended = false;
+		return err;
+	}
+
+	err = ft5x06_ts_start(dev);
+	if (err < 0)
+		return err;
+
+	if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support &&
+		device_may_wakeup(dev) &&
+		data->gesture_pdata->in_pocket &&
+		data->gesture_pdata->gesture_enable_to_set) {
+
+		ft5x0x_write_reg(data->client, FT_REG_GESTURE_ENABLE, 0);
+		err = disable_irq_wake(data->client->irq);
+		if (err)
+			dev_err(dev, "%s: disable_irq_wake failed\n",
+				__func__);
+		data->suspended = false;
+		data->gesture_pdata->in_pocket = 0;
+	}
+	return 0;
+}
+
+static const struct dev_pm_ops ft5x06_ts_pm_ops = {
+#if (!defined(CONFIG_FB) && !defined(CONFIG_HAS_EARLYSUSPEND))
+	.suspend = ft5x06_ts_suspend,
+	.resume = ft5x06_ts_resume,
+#endif
+};
+
+#else
+static int ft5x06_ts_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static int ft5x06_ts_resume(struct device *dev)
+{
+	return 0;
+}
+
+#endif
+
+#if defined(CONFIG_FB)
+static void fb_notify_resume_work(struct work_struct *work)
+{
+	struct ft5x06_ts_data *ft5x06_data =
+		container_of(work, struct ft5x06_ts_data, fb_notify_work);
+	ft5x06_ts_resume(&ft5x06_data->client->dev);
+}
+
+static int fb_notifier_callback(struct notifier_block *self,
+				 unsigned long event, void *data)
+{
+	struct fb_event *evdata = data;
+	int *blank;
+	struct ft5x06_ts_data *ft5x06_data =
+		container_of(self, struct ft5x06_ts_data, fb_notif);
+
+	if (evdata && evdata->data && ft5x06_data && ft5x06_data->client) {
+		blank = evdata->data;
+		if (ft5x06_data->pdata->resume_in_workqueue) {
+			if (event == FB_EARLY_EVENT_BLANK &&
+						 *blank == FB_BLANK_UNBLANK)
+				schedule_work(&ft5x06_data->fb_notify_work);
+			else if (event == FB_EVENT_BLANK &&
+						 *blank == FB_BLANK_POWERDOWN) {
+				flush_work(&ft5x06_data->fb_notify_work);
+				ft5x06_ts_suspend(&ft5x06_data->client->dev);
+			}
+		} else {
+			if (event == FB_EVENT_BLANK) {
+				if (*blank == FB_BLANK_UNBLANK)
+					ft5x06_ts_resume(
+						&ft5x06_data->client->dev);
+				else if (*blank == FB_BLANK_POWERDOWN)
+					ft5x06_ts_suspend(
+						&ft5x06_data->client->dev);
+			}
+		}
+	}
+
+	return 0;
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+static void ft5x06_ts_early_suspend(struct early_suspend *handler)
+{
+	struct ft5x06_ts_data *data = container_of(handler,
+						   struct ft5x06_ts_data,
+						   early_suspend);
+
+	/*
+	 * During early suspend/late resume, the driver doesn't access xPU/SMMU
+	 * protected HW resources. So, there is no compelling need to block,
+	 * but notifying the userspace that a power event has occurred is
+	 * enough. Hence 'blocking' variable can be set to false.
+	 */
+	ft5x06_secure_touch_stop(data, false);
+	ft5x06_ts_suspend(&data->client->dev);
+}
+
+static void ft5x06_ts_late_resume(struct early_suspend *handler)
+{
+	struct ft5x06_ts_data *data = container_of(handler,
+						   struct ft5x06_ts_data,
+						   early_suspend);
+
+	ft5x06_secure_touch_stop(data, false);
+	ft5x06_ts_resume(&data->client->dev);
+}
+#endif
+
+static int ft5x06_auto_cal(struct i2c_client *client)
+{
+	struct ft5x06_ts_data *data = i2c_get_clientdata(client);
+	u8 temp = 0, i;
+
+	/* set to factory mode */
+	msleep(2 * data->pdata->soft_rst_dly);
+	ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
+	msleep(data->pdata->soft_rst_dly);
+
+	/* start calibration */
+	ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_START);
+	msleep(2 * data->pdata->soft_rst_dly);
+	for (i = 0; i < FT_CAL_RETRY; i++) {
+		ft5x0x_read_reg(client, FT_REG_CAL, &temp);
+		/* return to normal mode, calibration finish */
+		if (((temp & FT_CAL_MASK) >> FT_4BIT_SHIFT) == FT_CAL_FIN)
+			break;
+	}
+
+	/*calibration OK */
+	msleep(2 * data->pdata->soft_rst_dly);
+	ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_FACTORYMODE_VALUE);
+	msleep(data->pdata->soft_rst_dly);
+
+	/* store calibration data */
+	ft5x0x_write_reg(client, FT_DEV_MODE_REG_CAL, FT_CAL_STORE);
+	msleep(2 * data->pdata->soft_rst_dly);
+
+	/* set to normal mode */
+	ft5x0x_write_reg(client, FT_REG_DEV_MODE, FT_WORKMODE_VALUE);
+	msleep(2 * data->pdata->soft_rst_dly);
+
+	return 0;
+}
+
+static int ft5x06_fw_upgrade_start(struct i2c_client *client,
+			const u8 *data, u32 data_len)
+{
+	struct ft5x06_ts_data *ts_data = i2c_get_clientdata(client);
+	struct fw_upgrade_info info = ts_data->pdata->info;
+	u8 reset_reg;
+	u8 w_buf[FT_MAX_WR_BUF] = {0}, r_buf[FT_MAX_RD_BUF] = {0};
+	u8 pkt_buf[FT_FW_PKT_LEN + FT_FW_PKT_META_LEN];
+	int i, j, temp;
+	u32 pkt_num, pkt_len;
+	u8 is_5336_new_bootloader = false;
+	u8 is_5336_fwsize_30 = false;
+	u8 fw_ecc;
+
+	/* determine firmware size */
+	if (*(data + data_len - FT_BLOADER_SIZE_OFF) == FT_BLOADER_NEW_SIZE)
+		is_5336_fwsize_30 = true;
+	else
+		is_5336_fwsize_30 = false;
+
+	for (i = 0, j = 0; i < FT_UPGRADE_LOOP; i++) {
+		msleep(FT_EARSE_DLY_MS);
+		/* reset - write 0xaa and 0x55 to reset register */
+		if (ts_data->family_id == FT6X06_ID
+			|| ts_data->family_id == FT6X36_ID)
+			reset_reg = FT_RST_CMD_REG2;
+		else
+			reset_reg = FT_RST_CMD_REG1;
+
+		ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_AA);
+		msleep(info.delay_aa);
+
+		ft5x0x_write_reg(client, reset_reg, FT_UPGRADE_55);
+		if (i <= (FT_UPGRADE_LOOP / 2))
+			msleep(info.delay_55 + i * 3);
+		else
+			msleep(info.delay_55 - (i - (FT_UPGRADE_LOOP / 2)) * 2);
+
+		/* Enter upgrade mode */
+		w_buf[0] = FT_UPGRADE_55;
+		ft5x06_i2c_write(client, w_buf, 1);
+		usleep_range(FT_55_AA_DLY_NS, FT_55_AA_DLY_NS + 1);
+		w_buf[0] = FT_UPGRADE_AA;
+		ft5x06_i2c_write(client, w_buf, 1);
+
+		/* check READ_ID */
+		msleep(info.delay_readid);
+		w_buf[0] = FT_READ_ID_REG;
+		w_buf[1] = 0x00;
+		w_buf[2] = 0x00;
+		w_buf[3] = 0x00;
+
+		ft5x06_i2c_read(client, w_buf, 4, r_buf, 2);
+
+		if (r_buf[0] != info.upgrade_id_1
+			|| r_buf[1] != info.upgrade_id_2) {
+			dev_err(&client->dev, "Upgrade ID mismatch(%d), IC=0x%x 0x%x, info=0x%x 0x%x\n",
+				i, r_buf[0], r_buf[1],
+				info.upgrade_id_1, info.upgrade_id_2);
+		} else
+			break;
+	}
+
+	if (i >= FT_UPGRADE_LOOP) {
+		dev_err(&client->dev, "Abort upgrade\n");
+		return -EIO;
+	}
+
+	w_buf[0] = 0xcd;
+	ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
+
+	if (r_buf[0] <= 4)
+		is_5336_new_bootloader = FT_BLOADER_VERSION_LZ4;
+	else if (r_buf[0] == 7)
+		is_5336_new_bootloader = FT_BLOADER_VERSION_Z7;
+	else if (r_buf[0] >= 0x0f &&
+		((ts_data->family_id == FT_FT5336_FAMILY_ID_0x11) ||
+		(ts_data->family_id == FT_FT5336_FAMILY_ID_0x12) ||
+		(ts_data->family_id == FT_FT5336_FAMILY_ID_0x13) ||
+		(ts_data->family_id == FT_FT5336_FAMILY_ID_0x14)))
+		is_5336_new_bootloader = FT_BLOADER_VERSION_GZF;
+	else
+		is_5336_new_bootloader = FT_BLOADER_VERSION_LZ4;
+
+	dev_dbg(&client->dev, "bootloader type=%d, r_buf=0x%x, family_id=0x%x\n",
+		is_5336_new_bootloader, r_buf[0], ts_data->family_id);
+	/* is_5336_new_bootloader = FT_BLOADER_VERSION_GZF; */
+
+	/* erase app and panel paramenter area */
+	w_buf[0] = FT_ERASE_APP_REG;
+	ft5x06_i2c_write(client, w_buf, 1);
+	msleep(info.delay_erase_flash);
+
+	if (is_5336_fwsize_30) {
+		w_buf[0] = FT_ERASE_PANEL_REG;
+		ft5x06_i2c_write(client, w_buf, 1);
+	}
+	msleep(FT_EARSE_DLY_MS);
+
+	/* program firmware */
+	if (is_5336_new_bootloader == FT_BLOADER_VERSION_LZ4
+		|| is_5336_new_bootloader == FT_BLOADER_VERSION_Z7)
+		data_len = data_len - FT_DATA_LEN_OFF_OLD_FW;
+	else
+		data_len = data_len - FT_DATA_LEN_OFF_NEW_FW;
+
+	pkt_num = (data_len) / FT_FW_PKT_LEN;
+	pkt_len = FT_FW_PKT_LEN;
+	pkt_buf[0] = FT_FW_START_REG;
+	pkt_buf[1] = 0x00;
+	fw_ecc = 0;
+
+	for (i = 0; i < pkt_num; i++) {
+		temp = i * FT_FW_PKT_LEN;
+		pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
+		pkt_buf[3] = (u8) temp;
+		pkt_buf[4] = (u8) (pkt_len >> FT_8BIT_SHIFT);
+		pkt_buf[5] = (u8) pkt_len;
+
+		for (j = 0; j < FT_FW_PKT_LEN; j++) {
+			pkt_buf[6 + j] = data[i * FT_FW_PKT_LEN + j];
+			fw_ecc ^= pkt_buf[6 + j];
+		}
+
+		ft5x06_i2c_write(client, pkt_buf,
+				FT_FW_PKT_LEN + FT_FW_PKT_META_LEN);
+		msleep(FT_FW_PKT_DLY_MS);
+	}
+
+	/* send remaining bytes */
+	if ((data_len) % FT_FW_PKT_LEN > 0) {
+		temp = pkt_num * FT_FW_PKT_LEN;
+		pkt_buf[2] = (u8) (temp >> FT_8BIT_SHIFT);
+		pkt_buf[3] = (u8) temp;
+		temp = (data_len) % FT_FW_PKT_LEN;
+		pkt_buf[4] = (u8) (temp >> FT_8BIT_SHIFT);
+		pkt_buf[5] = (u8) temp;
+
+		for (i = 0; i < temp; i++) {
+			pkt_buf[6 + i] = data[pkt_num * FT_FW_PKT_LEN + i];
+			fw_ecc ^= pkt_buf[6 + i];
+		}
+
+		ft5x06_i2c_write(client, pkt_buf, temp + FT_FW_PKT_META_LEN);
+		msleep(FT_FW_PKT_DLY_MS);
+	}
+
+	/* send the finishing packet */
+	if (is_5336_new_bootloader == FT_BLOADER_VERSION_LZ4 ||
+		is_5336_new_bootloader == FT_BLOADER_VERSION_Z7) {
+		for (i = 0; i < FT_FINISHING_PKT_LEN_OLD_FW; i++) {
+			if (is_5336_new_bootloader  == FT_BLOADER_VERSION_Z7)
+				temp = FT_MAGIC_BLOADER_Z7 + i;
+			else if (is_5336_new_bootloader ==
+						FT_BLOADER_VERSION_LZ4)
+				temp = FT_MAGIC_BLOADER_LZ4 + i;
+			pkt_buf[2] = (u8)(temp >> 8);
+			pkt_buf[3] = (u8)temp;
+			temp = 1;
+			pkt_buf[4] = (u8)(temp >> 8);
+			pkt_buf[5] = (u8)temp;
+			pkt_buf[6] = data[data_len + i];
+			fw_ecc ^= pkt_buf[6];
+
+			ft5x06_i2c_write(client,
+				pkt_buf, temp + FT_FW_PKT_META_LEN);
+			msleep(FT_FW_PKT_DLY_MS);
+		}
+	} else if (is_5336_new_bootloader == FT_BLOADER_VERSION_GZF) {
+		for (i = 0; i < FT_FINISHING_PKT_LEN_NEW_FW; i++) {
+			if (is_5336_fwsize_30)
+				temp = FT_MAGIC_BLOADER_GZF_30 + i;
+			else
+				temp = FT_MAGIC_BLOADER_GZF + i;
+			pkt_buf[2] = (u8)(temp >> 8);
+			pkt_buf[3] = (u8)temp;
+			temp = 1;
+			pkt_buf[4] = (u8)(temp >> 8);
+			pkt_buf[5] = (u8)temp;
+			pkt_buf[6] = data[data_len + i];
+			fw_ecc ^= pkt_buf[6];
+
+			ft5x06_i2c_write(client,
+				pkt_buf, temp + FT_FW_PKT_META_LEN);
+			msleep(FT_FW_PKT_DLY_MS);
+
+		}
+	}
+
+	/* verify checksum */
+	w_buf[0] = FT_REG_ECC;
+	ft5x06_i2c_read(client, w_buf, 1, r_buf, 1);
+	if (r_buf[0] != fw_ecc) {
+		dev_err(&client->dev, "ECC error! dev_ecc=%02x fw_ecc=%02x\n",
+					r_buf[0], fw_ecc);
+		return -EIO;
+	}
+
+	/* reset */
+	w_buf[0] = FT_REG_RESET_FW;
+	ft5x06_i2c_write(client, w_buf, 1);
+	msleep(ts_data->pdata->soft_rst_dly);
+
+	dev_info(&client->dev, "Firmware upgrade successful\n");
+
+	return 0;
+}
+
+static int ft5x06_fw_upgrade(struct device *dev, bool force)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+	const struct firmware *fw = NULL;
+	int rc;
+	u8 fw_file_maj, fw_file_min, fw_file_sub_min, fw_file_vendor_id;
+	bool fw_upgrade = false;
+
+	if (data->suspended) {
+		dev_err(dev, "Device is in suspend state: Exit FW upgrade\n");
+		return -EBUSY;
+	}
+
+	rc = request_firmware(&fw, data->fw_name, dev);
+	if (rc < 0) {
+		dev_err(dev, "Request firmware failed - %s (%d)\n",
+						data->fw_name, rc);
+		return rc;
+	}
+
+	if (fw->size < FT_FW_MIN_SIZE || fw->size > FT_FW_MAX_SIZE) {
+		dev_err(dev, "Invalid firmware size (%zu)\n", fw->size);
+		rc = -EIO;
+		goto rel_fw;
+	}
+
+	if (data->family_id == FT6X36_ID) {
+		fw_file_maj = FT_FW_FILE_MAJ_VER_FT6X36(fw);
+		fw_file_vendor_id = FT_FW_FILE_VENDOR_ID_FT6X36(fw);
+	} else {
+		fw_file_maj = FT_FW_FILE_MAJ_VER(fw);
+		fw_file_vendor_id = FT_FW_FILE_VENDOR_ID(fw);
+	}
+	fw_file_min = FT_FW_FILE_MIN_VER(fw);
+	fw_file_sub_min = FT_FW_FILE_SUB_MIN_VER(fw);
+	fw_file_vendor_id = FT_FW_FILE_VENDOR_ID(fw);
+
+	dev_info(dev, "Current firmware: %d.%d.%d", data->fw_ver[0],
+				data->fw_ver[1], data->fw_ver[2]);
+	dev_info(dev, "New firmware: %d.%d.%d", fw_file_maj,
+				fw_file_min, fw_file_sub_min);
+
+	if (force)
+		fw_upgrade = true;
+	else if ((data->fw_ver[0] < fw_file_maj) &&
+		data->fw_vendor_id == fw_file_vendor_id)
+		fw_upgrade = true;
+
+	if (!fw_upgrade) {
+		dev_info(dev, "Exiting fw upgrade...\n");
+		rc = -EFAULT;
+		goto rel_fw;
+	}
+
+	/* start firmware upgrade */
+	if (FT_FW_CHECK(fw, data)) {
+		rc = ft5x06_fw_upgrade_start(data->client, fw->data, fw->size);
+		if (rc < 0)
+			dev_err(dev, "update failed (%d). try later...\n", rc);
+		else if (data->pdata->info.auto_cal)
+			ft5x06_auto_cal(data->client);
+	} else {
+		dev_err(dev, "FW format error\n");
+		rc = -EIO;
+	}
+
+	ft5x06_update_fw_ver(data);
+
+	FT_STORE_TS_DBG_INFO(data->ts_info, data->family_id, data->pdata->name,
+			data->pdata->num_max_touches, data->pdata->group_id,
+			data->pdata->fw_vkey_support ? "yes" : "no",
+			data->pdata->fw_name, data->fw_ver[0],
+			data->fw_ver[1], data->fw_ver[2]);
+	FT_STORE_TS_INFO(ts_info_buff, data->family_id, data->fw_ver[0],
+			 data->fw_ver[1], data->fw_ver[2]);
+rel_fw:
+	release_firmware(fw);
+	return rc;
+}
+
+static ssize_t ft5x06_update_fw_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+	return snprintf(buf, 2, "%d\n", data->loading_fw);
+}
+
+static ssize_t ft5x06_update_fw_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+	unsigned long val;
+	int rc;
+
+	if (size > 2)
+		return -EINVAL;
+
+	rc = kstrtoul(buf, 10, &val);
+	if (rc != 0)
+		return rc;
+
+	if (data->suspended) {
+		dev_info(dev, "In suspend state, try again later...\n");
+		return size;
+	}
+
+	mutex_lock(&data->input_dev->mutex);
+	if (!data->loading_fw  && val) {
+		data->loading_fw = true;
+		ft5x06_fw_upgrade(dev, false);
+		data->loading_fw = false;
+	}
+	mutex_unlock(&data->input_dev->mutex);
+
+	return size;
+}
+
+static DEVICE_ATTR(update_fw, 0664, ft5x06_update_fw_show,
+				ft5x06_update_fw_store);
+
+static ssize_t ft5x06_force_update_fw_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+	unsigned long val;
+	int rc;
+
+	if (size > 2)
+		return -EINVAL;
+
+	rc = kstrtoul(buf, 10, &val);
+	if (rc != 0)
+		return rc;
+
+	mutex_lock(&data->input_dev->mutex);
+	if (!data->loading_fw  && val) {
+		data->loading_fw = true;
+		ft5x06_fw_upgrade(dev, true);
+		data->loading_fw = false;
+	}
+	mutex_unlock(&data->input_dev->mutex);
+
+	return size;
+}
+
+static DEVICE_ATTR(force_update_fw, 0664, ft5x06_update_fw_show,
+				ft5x06_force_update_fw_store);
+
+static ssize_t ft5x06_fw_name_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+	return snprintf(buf, FT_FW_NAME_MAX_LEN - 1, "%s\n", data->fw_name);
+}
+
+static ssize_t ft5x06_fw_name_store(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct ft5x06_ts_data *data = dev_get_drvdata(dev);
+
+	if (size > FT_FW_NAME_MAX_LEN - 1)
+		return -EINVAL;
+
+	strlcpy(data->fw_name, buf, size);
+	if (data->fw_name[size-1] == '\n')
+		data->fw_name[size-1] = 0;
+
+	return size;
+}
+
+static DEVICE_ATTR(fw_name, 0664, ft5x06_fw_name_show, ft5x06_fw_name_store);
+
+static ssize_t ts_info_show(struct kobject *kobj,
+		struct kobj_attribute *attr, char *buf)
+{
+	strlcpy(buf, ts_info_buff, FT_INFO_MAX_LEN);
+	return strnlen(buf, FT_INFO_MAX_LEN);
+}
+static struct kobj_attribute ts_info_attr = __ATTR_RO(ts_info);
+
+static bool ft5x06_debug_addr_is_valid(int addr)
+{
+	if (addr < 0 || addr > 0xFF) {
+		pr_err("FT reg address is invalid: 0x%x\n", addr);
+		return false;
+	}
+
+	return true;
+}
+
+static int ft5x06_debug_data_set(void *_data, u64 val)
+{
+	struct ft5x06_ts_data *data = _data;
+
+	mutex_lock(&data->input_dev->mutex);
+
+	if (ft5x06_debug_addr_is_valid(data->addr))
+		dev_info(&data->client->dev,
+			"Writing into FT registers not supported\n");
+
+	mutex_unlock(&data->input_dev->mutex);
+
+	return 0;
+}
+
+static int ft5x06_debug_data_get(void *_data, u64 *val)
+{
+	struct ft5x06_ts_data *data = _data;
+	int rc;
+	u8 reg = 0;
+
+	mutex_lock(&data->input_dev->mutex);
+
+	if (ft5x06_debug_addr_is_valid(data->addr)) {
+		rc = ft5x0x_read_reg(data->client, data->addr, &reg);
+		if (rc < 0)
+			dev_err(&data->client->dev,
+				"FT read register 0x%x failed (%d)\n",
+				data->addr, rc);
+		else
+			*val = reg;
+	}
+
+	mutex_unlock(&data->input_dev->mutex);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_data_fops, ft5x06_debug_data_get,
+			ft5x06_debug_data_set, "0x%02llX\n");
+
+static int ft5x06_debug_addr_set(void *_data, u64 val)
+{
+	struct ft5x06_ts_data *data = _data;
+
+	if (ft5x06_debug_addr_is_valid(val)) {
+		mutex_lock(&data->input_dev->mutex);
+		data->addr = val;
+		mutex_unlock(&data->input_dev->mutex);
+	}
+
+	return 0;
+}
+
+static int ft5x06_debug_addr_get(void *_data, u64 *val)
+{
+	struct ft5x06_ts_data *data = _data;
+
+	mutex_lock(&data->input_dev->mutex);
+
+	if (ft5x06_debug_addr_is_valid(data->addr))
+		*val = data->addr;
+
+	mutex_unlock(&data->input_dev->mutex);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_addr_fops, ft5x06_debug_addr_get,
+			ft5x06_debug_addr_set, "0x%02llX\n");
+
+static int ft5x06_debug_suspend_set(void *_data, u64 val)
+{
+	struct ft5x06_ts_data *data = _data;
+
+	mutex_lock(&data->input_dev->mutex);
+
+	if (val)
+		ft5x06_ts_suspend(&data->client->dev);
+	else
+		ft5x06_ts_resume(&data->client->dev);
+
+	mutex_unlock(&data->input_dev->mutex);
+
+	return 0;
+}
+
+static int ft5x06_debug_suspend_get(void *_data, u64 *val)
+{
+	struct ft5x06_ts_data *data = _data;
+
+	mutex_lock(&data->input_dev->mutex);
+	*val = data->suspended;
+	mutex_unlock(&data->input_dev->mutex);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(debug_suspend_fops, ft5x06_debug_suspend_get,
+			ft5x06_debug_suspend_set, "%lld\n");
+
+static int ft5x06_debug_dump_info(struct seq_file *m, void *v)
+{
+	struct ft5x06_ts_data *data = m->private;
+
+	seq_printf(m, "%s\n", data->ts_info);
+
+	return 0;
+}
+
+static int debugfs_dump_info_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, ft5x06_debug_dump_info, inode->i_private);
+}
+
+static const struct file_operations debug_dump_info_fops = {
+	.owner		= THIS_MODULE,
+	.open		= debugfs_dump_info_open,
+	.read		= seq_read,
+	.release	= single_release,
+};
+
+#ifdef CONFIG_OF
+static int ft5x06_get_dt_coords(struct device *dev, char *name,
+				struct ft5x06_ts_platform_data *pdata)
+{
+	u32 coords[FT_COORDS_ARR_SIZE];
+	struct property *prop;
+	struct device_node *np = dev->of_node;
+	int coords_size, rc;
+
+	prop = of_find_property(np, name, NULL);
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+
+	coords_size = prop->length / sizeof(u32);
+	if (coords_size != FT_COORDS_ARR_SIZE) {
+		dev_err(dev, "invalid %s\n", name);
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32_array(np, name, coords, coords_size);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read %s\n", name);
+		return rc;
+	}
+
+	if (!strcmp(name, "focaltech,panel-coords")) {
+		pdata->panel_minx = coords[0];
+		pdata->panel_miny = coords[1];
+		pdata->panel_maxx = coords[2];
+		pdata->panel_maxy = coords[3];
+	} else if (!strcmp(name, "focaltech,display-coords")) {
+		pdata->x_min = coords[0];
+		pdata->y_min = coords[1];
+		pdata->x_max = coords[2];
+		pdata->y_max = coords[3];
+	} else {
+		dev_err(dev, "unsupported property %s\n", name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ft5x06_parse_dt(struct device *dev,
+			struct ft5x06_ts_platform_data *pdata)
+{
+	int rc;
+	struct device_node *np = dev->of_node;
+	struct property *prop;
+	u32 temp_val, num_buttons;
+	u32 button_map[MAX_BUTTONS];
+
+	pdata->name = "focaltech";
+	rc = of_property_read_string(np, "focaltech,name", &pdata->name);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read name\n");
+		return rc;
+	}
+
+	rc = ft5x06_get_dt_coords(dev, "focaltech,panel-coords", pdata);
+	if (rc && (rc != -EINVAL))
+		return rc;
+
+	rc = ft5x06_get_dt_coords(dev, "focaltech,display-coords", pdata);
+	if (rc)
+		return rc;
+
+	pdata->i2c_pull_up = of_property_read_bool(np,
+						"focaltech,i2c-pull-up");
+
+	pdata->no_force_update = of_property_read_bool(np,
+						"focaltech,no-force-update");
+	/* reset, irq gpio info */
+	pdata->reset_gpio = of_get_named_gpio_flags(np, "focaltech,reset-gpio",
+				0, &pdata->reset_gpio_flags);
+	if (pdata->reset_gpio < 0)
+		return pdata->reset_gpio;
+
+	pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio",
+				0, &pdata->irq_gpio_flags);
+	if (pdata->irq_gpio < 0)
+		return pdata->irq_gpio;
+
+	pdata->fw_name = "ft_fw.bin";
+	rc = of_property_read_string(np, "focaltech,fw-name", &pdata->fw_name);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read fw name\n");
+		return rc;
+	}
+
+	rc = of_property_read_u32(np, "focaltech,group-id", &temp_val);
+	if (!rc)
+		pdata->group_id = temp_val;
+	else
+		return rc;
+
+	rc = of_property_read_u32(np, "focaltech,hard-reset-delay-ms",
+							&temp_val);
+	if (!rc)
+		pdata->hard_rst_dly = temp_val;
+	else
+		return rc;
+
+	rc = of_property_read_u32(np, "focaltech,soft-reset-delay-ms",
+							&temp_val);
+	if (!rc)
+		pdata->soft_rst_dly = temp_val;
+	else
+		return rc;
+
+	rc = of_property_read_u32(np, "focaltech,num-max-touches", &temp_val);
+	if (!rc)
+		pdata->num_max_touches = temp_val;
+	else
+		return rc;
+
+	rc = of_property_read_u32(np, "focaltech,fw-delay-aa-ms", &temp_val);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read fw delay aa\n");
+		return rc;
+	} else if (rc != -EINVAL)
+		pdata->info.delay_aa =  temp_val;
+
+	rc = of_property_read_u32(np, "focaltech,fw-delay-55-ms", &temp_val);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read fw delay 55\n");
+		return rc;
+	} else if (rc != -EINVAL)
+		pdata->info.delay_55 =  temp_val;
+
+	rc = of_property_read_u32(np, "focaltech,fw-upgrade-id1", &temp_val);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read fw upgrade id1\n");
+		return rc;
+	} else if (rc != -EINVAL)
+		pdata->info.upgrade_id_1 =  temp_val;
+
+	rc = of_property_read_u32(np, "focaltech,fw-upgrade-id2", &temp_val);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read fw upgrade id2\n");
+		return rc;
+	} else if (rc != -EINVAL)
+		pdata->info.upgrade_id_2 =  temp_val;
+
+	rc = of_property_read_u32(np, "focaltech,fw-delay-readid-ms",
+							&temp_val);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read fw delay read id\n");
+		return rc;
+	} else if (rc != -EINVAL)
+		pdata->info.delay_readid =  temp_val;
+
+	rc = of_property_read_u32(np, "focaltech,fw-delay-era-flsh-ms",
+							&temp_val);
+	if (rc && (rc != -EINVAL)) {
+		dev_err(dev, "Unable to read fw delay erase flash\n");
+		return rc;
+	} else if (rc != -EINVAL)
+		pdata->info.delay_erase_flash =  temp_val;
+
+	pdata->info.auto_cal = of_property_read_bool(np,
+					"focaltech,fw-auto-cal");
+
+	pdata->fw_vkey_support = of_property_read_bool(np,
+						"focaltech,fw-vkey-support");
+
+	pdata->ignore_id_check = of_property_read_bool(np,
+						"focaltech,ignore-id-check");
+
+	pdata->gesture_support = of_property_read_bool(np,
+						"focaltech,gesture-support");
+
+	pdata->resume_in_workqueue = of_property_read_bool(np,
+					"focaltech,resume-in-workqueue");
+
+	rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
+	if (!rc)
+		pdata->family_id = temp_val;
+	else
+		return rc;
+
+	prop = of_find_property(np, "focaltech,button-map", NULL);
+	if (prop) {
+		num_buttons = prop->length / sizeof(temp_val);
+		if (num_buttons > MAX_BUTTONS)
+			return -EINVAL;
+
+		rc = of_property_read_u32_array(np,
+			"focaltech,button-map", button_map,
+			num_buttons);
+		if (rc) {
+			dev_err(dev, "Unable to read key codes\n");
+			return rc;
+		}
+	}
+
+	return 0;
+}
+#else
+static int ft5x06_parse_dt(struct device *dev,
+			struct ft5x06_ts_platform_data *pdata)
+{
+	return -ENODEV;
+}
+#endif
+
+static int ft5x06_ts_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct ft5x06_ts_platform_data *pdata;
+	struct ft5x06_gesture_platform_data *gesture_pdata;
+	struct ft5x06_ts_data *data;
+	struct input_dev *input_dev;
+	struct dentry *temp;
+	u8 reg_value = 0;
+	u8 reg_addr;
+	int err, len, retval, attr_count;
+
+	if (client->dev.of_node) {
+		pdata = devm_kzalloc(&client->dev,
+			sizeof(struct ft5x06_ts_platform_data), GFP_KERNEL);
+		if (!pdata)
+			return -ENOMEM;
+
+		err = ft5x06_parse_dt(&client->dev, pdata);
+		if (err) {
+			dev_err(&client->dev, "DT parsing failed\n");
+			return err;
+		}
+	} else
+		pdata = client->dev.platform_data;
+
+	if (!pdata) {
+		dev_err(&client->dev, "Invalid pdata\n");
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "I2C not supported\n");
+		return -ENODEV;
+	}
+
+	data = devm_kzalloc(&client->dev,
+			sizeof(struct ft5x06_ts_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	if (pdata->fw_name) {
+		len = strlen(pdata->fw_name);
+		if (len > FT_FW_NAME_MAX_LEN - 1) {
+			dev_err(&client->dev, "Invalid firmware name\n");
+			return -EINVAL;
+		}
+
+		strlcpy(data->fw_name, pdata->fw_name, len + 1);
+	}
+
+	data->tch_data_len = FT_TCH_LEN(pdata->num_max_touches);
+	data->tch_data = devm_kzalloc(&client->dev,
+				data->tch_data_len, GFP_KERNEL);
+	if (!data->tch_data)
+		return -ENOMEM;
+
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		dev_err(&client->dev, "failed to allocate input device\n");
+		return -ENOMEM;
+	}
+
+	data->input_dev = input_dev;
+	data->client = client;
+	data->pdata = pdata;
+
+	input_dev->name = "ft5x06_ts";
+	input_dev->id.bustype = BUS_I2C;
+	input_dev->dev.parent = &client->dev;
+
+	input_set_drvdata(input_dev, data);
+	i2c_set_clientdata(client, data);
+
+	__set_bit(EV_KEY, input_dev->evbit);
+	__set_bit(EV_ABS, input_dev->evbit);
+	__set_bit(BTN_TOUCH, input_dev->keybit);
+	__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+	input_mt_init_slots(input_dev, pdata->num_max_touches, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
+			     pdata->x_max, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
+			     pdata->y_max, 0, 0);
+
+	err = input_register_device(input_dev);
+	if (err) {
+		dev_err(&client->dev, "Input device registration failed\n");
+		input_free_device(input_dev);
+		return err;
+	}
+
+	if (pdata->power_init) {
+		err = pdata->power_init(true);
+		if (err) {
+			dev_err(&client->dev, "power init failed");
+			goto unreg_inputdev;
+		}
+	} else {
+		err = ft5x06_power_init(data, true);
+		if (err) {
+			dev_err(&client->dev, "power init failed");
+			goto unreg_inputdev;
+		}
+	}
+
+	if (pdata->power_on) {
+		err = pdata->power_on(true);
+		if (err) {
+			dev_err(&client->dev, "power on failed");
+			goto pwr_deinit;
+		}
+	} else {
+		err = ft5x06_power_on(data, true);
+		if (err) {
+			dev_err(&client->dev, "power on failed");
+			goto pwr_deinit;
+		}
+	}
+
+	err = ft5x06_ts_pinctrl_init(data);
+	if (!err && data->ts_pinctrl) {
+		/*
+		 * Pinctrl handle is optional. If pinctrl handle is found
+		 * let pins to be configured in active state. If not
+		 * found continue further without error.
+		 */
+		err = pinctrl_select_state(data->ts_pinctrl,
+					data->pinctrl_state_active);
+		if (err < 0) {
+			dev_err(&client->dev,
+				"failed to select pin to active state");
+		}
+	}
+
+	err = ft5x06_gpio_configure(data, true);
+	if (err < 0) {
+		dev_err(&client->dev,
+			"Failed to configure the gpios\n");
+		goto err_gpio_req;
+	}
+
+	/* make sure CTP already finish startup process */
+	msleep(data->pdata->soft_rst_dly);
+
+	/* check the controller id */
+	reg_addr = FT_REG_ID;
+	err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
+	if (err < 0) {
+		dev_err(&client->dev, "version read failed");
+		goto free_gpio;
+	}
+
+	dev_info(&client->dev, "Device ID = 0x%x\n", reg_value);
+
+	if ((pdata->family_id != reg_value) && (!pdata->ignore_id_check)) {
+		dev_err(&client->dev, "%s:Unsupported controller\n", __func__);
+		goto free_gpio;
+	}
+
+	data->family_id = pdata->family_id;
+
+	err = request_threaded_irq(client->irq, NULL,
+				ft5x06_ts_interrupt,
+	/*
+	 * the interrupt trigger mode will be set in Device Tree with property
+	 * "interrupts", so here we just need to set the flag IRQF_ONESHOT
+	 */
+				IRQF_ONESHOT,
+				client->dev.driver->name, data);
+	if (err) {
+		dev_err(&client->dev, "request irq failed\n");
+		goto free_gpio;
+	}
+
+	if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support) {
+		device_init_wakeup(&client->dev, 1);
+		gesture_pdata = devm_kzalloc(&client->dev,
+				sizeof(struct ft5x06_gesture_platform_data),
+				GFP_KERNEL);
+		if (!gesture_pdata) {
+			dev_err(&client->dev, "Failed to allocate memory\n");
+			goto free_gesture_dev;
+		}
+		data->gesture_pdata = gesture_pdata;
+		gesture_pdata->data = data;
+
+		gesture_pdata->gesture_class =
+					class_create(THIS_MODULE, "gesture");
+		if (IS_ERR(gesture_pdata->gesture_class)) {
+			err = PTR_ERR(gesture_pdata->gesture_class);
+			dev_err(&client->dev, "Failed to create class.\n");
+			goto free_gesture_pdata;
+		}
+
+		gesture_pdata->dev = device_create(gesture_pdata->gesture_class,
+				NULL, 0, NULL, "gesture_ft5x06");
+		if (IS_ERR(gesture_pdata->dev)) {
+			err = PTR_ERR(gesture_pdata->dev);
+			dev_err(&client->dev, "Failed to create device.\n");
+			goto free_gesture_class;
+		}
+
+		dev_set_drvdata(gesture_pdata->dev, data);
+		err = device_create_file(gesture_pdata->dev,
+					&dev_attr_enable);
+		if (err) {
+			dev_err(gesture_pdata->dev,
+					"sys file creation failed\n");
+			goto free_gesture_dev;
+		}
+		err = device_create_file(gesture_pdata->dev,
+					&dev_attr_pocket);
+		if (err) {
+			dev_err(gesture_pdata->dev,
+					"sys file creation failed\n");
+			goto free_enable_sys;
+		}
+	}
+
+	err = device_create_file(&client->dev, &dev_attr_fw_name);
+	if (err) {
+		dev_err(&client->dev, "sys file creation failed\n");
+		goto free_pocket_sys;
+	}
+
+	err = device_create_file(&client->dev, &dev_attr_update_fw);
+	if (err) {
+		dev_err(&client->dev, "sys file creation failed\n");
+		goto free_fw_name_sys;
+	}
+
+	err = device_create_file(&client->dev, &dev_attr_force_update_fw);
+	if (err) {
+		dev_err(&client->dev, "sys file creation failed\n");
+		goto free_update_fw_sys;
+	}
+
+	data->dir = debugfs_create_dir(FT_DEBUG_DIR_NAME, NULL);
+	if (data->dir == NULL || IS_ERR(data->dir)) {
+		pr_err("debugfs_create_dir failed(%ld)\n", PTR_ERR(data->dir));
+		err = PTR_ERR(data->dir);
+		goto free_force_update_fw_sys;
+	}
+
+	temp = debugfs_create_file("addr", 0600, data->dir, data,
+				   &debug_addr_fops);
+	if (temp == NULL || IS_ERR(temp)) {
+		pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
+		err = PTR_ERR(temp);
+		goto free_debug_dir;
+	}
+
+	temp = debugfs_create_file("data", 0600, data->dir, data,
+				   &debug_data_fops);
+	if (temp == NULL || IS_ERR(temp)) {
+		pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
+		err = PTR_ERR(temp);
+		goto free_debug_dir;
+	}
+
+	temp = debugfs_create_file("suspend", 0600, data->dir,
+					data, &debug_suspend_fops);
+	if (temp == NULL || IS_ERR(temp)) {
+		pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
+		err = PTR_ERR(temp);
+		goto free_debug_dir;
+	}
+
+	temp = debugfs_create_file("dump_info", 0600, data->dir,
+					data, &debug_dump_info_fops);
+	if (temp == NULL || IS_ERR(temp)) {
+		pr_err("debugfs_create_file failed: rc=%ld\n", PTR_ERR(temp));
+		err = PTR_ERR(temp);
+		goto free_debug_dir;
+	}
+
+	data->ts_info = devm_kzalloc(&client->dev,
+				FT_INFO_MAX_LEN, GFP_KERNEL);
+	if (!data->ts_info)
+		goto free_debug_dir;
+
+	/*get some register information */
+	reg_addr = FT_REG_POINT_RATE;
+	ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
+	if (err < 0)
+		dev_err(&client->dev, "report rate read failed");
+
+	dev_info(&client->dev, "report rate = %dHz\n", reg_value * 10);
+
+	reg_addr = FT_REG_THGROUP;
+	err = ft5x06_i2c_read(client, &reg_addr, 1, &reg_value, 1);
+	if (err < 0)
+		dev_err(&client->dev, "threshold read failed");
+
+	dev_dbg(&client->dev, "touch threshold = %d\n", reg_value * 4);
+
+	/*creation touch panel info kobj*/
+	data->ts_info_kobj = kobject_create_and_add(FT_TS_INFO_SYSFS_DIR_NAME,
+					kernel_kobj);
+	if (!data->ts_info_kobj) {
+		dev_err(&client->dev, "kobject creation failed.\n");
+	} else {
+		err = sysfs_create_file(data->ts_info_kobj, &ts_info_attr.attr);
+		if (err) {
+			kobject_put(data->ts_info_kobj);
+			dev_err(&client->dev, "sysfs creation failed.\n");
+		} else {
+			ts_info_buff = devm_kzalloc(&client->dev,
+						 FT_INFO_MAX_LEN, GFP_KERNEL);
+			if (!ts_info_buff)
+				goto free_debug_dir;
+		}
+	}
+
+	/*Initialize secure touch */
+	ft5x06_secure_touch_init(data);
+	ft5x06_secure_touch_stop(data, true);
+	mutex_init(&(data->ft_clk_io_ctrl_mutex));
+
+	/* Creation of secure touch sysfs files */
+	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+		retval = sysfs_create_file(&data->input_dev->dev.kobj,
+						&attrs[attr_count].attr);
+		if (retval < 0) {
+			dev_err(&client->dev,
+				"%s: Failed to create sysfs attributes\n",
+							__func__);
+			goto free_secure_touch_sysfs;
+		}
+	}
+
+	ft5x06_update_fw_ver(data);
+	ft5x06_update_fw_vendor_id(data);
+
+	FT_STORE_TS_DBG_INFO(data->ts_info, data->family_id, data->pdata->name,
+			data->pdata->num_max_touches, data->pdata->group_id,
+			data->pdata->fw_vkey_support ? "yes" : "no",
+			data->pdata->fw_name, data->fw_ver[0],
+			data->fw_ver[1], data->fw_ver[2]);
+	FT_STORE_TS_INFO(ts_info_buff, data->family_id, data->fw_ver[0],
+			 data->fw_ver[1], data->fw_ver[2]);
+#if defined(CONFIG_FB)
+	INIT_WORK(&data->fb_notify_work, fb_notify_resume_work);
+	data->fb_notif.notifier_call = fb_notifier_callback;
+
+	err = fb_register_client(&data->fb_notif);
+
+	if (err)
+		dev_err(&client->dev, "Unable to register fb_notifier: %d\n",
+			err);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
+						    FT_SUSPEND_LEVEL;
+	data->early_suspend.suspend = ft5x06_ts_early_suspend;
+	data->early_suspend.resume = ft5x06_ts_late_resume;
+	register_early_suspend(&data->early_suspend);
+#endif
+	return 0;
+
+free_secure_touch_sysfs:
+	for (attr_count--; attr_count >= 0; attr_count--) {
+		sysfs_remove_file(&data->input_dev->dev.kobj,
+					&attrs[attr_count].attr);
+	}
+free_debug_dir:
+	debugfs_remove_recursive(data->dir);
+free_force_update_fw_sys:
+	device_remove_file(&client->dev, &dev_attr_force_update_fw);
+free_update_fw_sys:
+	device_remove_file(&client->dev, &dev_attr_update_fw);
+free_fw_name_sys:
+	device_remove_file(&client->dev, &dev_attr_fw_name);
+free_pocket_sys:
+	if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support)
+		device_remove_file(&client->dev, &dev_attr_pocket);
+free_enable_sys:
+	if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support)
+		device_remove_file(&client->dev, &dev_attr_enable);
+free_gesture_dev:
+	if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support)
+		device_destroy(gesture_pdata->gesture_class, 0);
+free_gesture_class:
+	if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support)
+		class_destroy(gesture_pdata->gesture_class);
+free_gesture_pdata:
+	if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support) {
+		devm_kfree(&client->dev, gesture_pdata);
+		data->gesture_pdata = NULL;
+	}
+
+free_gpio:
+	if (gpio_is_valid(pdata->reset_gpio))
+		gpio_free(pdata->reset_gpio);
+	if (gpio_is_valid(pdata->irq_gpio))
+		gpio_free(pdata->irq_gpio);
+err_gpio_req:
+	if (data->ts_pinctrl) {
+		if (IS_ERR_OR_NULL(data->pinctrl_state_release)) {
+			devm_pinctrl_put(data->ts_pinctrl);
+			data->ts_pinctrl = NULL;
+		} else {
+			err = pinctrl_select_state(data->ts_pinctrl,
+					data->pinctrl_state_release);
+			if (err)
+				pr_err("failed to select relase pinctrl state\n");
+		}
+	}
+	if (pdata->power_on)
+		pdata->power_on(false);
+	else
+		ft5x06_power_on(data, false);
+pwr_deinit:
+	if (pdata->power_init)
+		pdata->power_init(false);
+	else
+		ft5x06_power_init(data, false);
+unreg_inputdev:
+	input_unregister_device(input_dev);
+	return err;
+}
+
+static int ft5x06_ts_remove(struct i2c_client *client)
+{
+	struct ft5x06_ts_data *data = i2c_get_clientdata(client);
+	int retval, attr_count;
+
+	if (ft5x06_gesture_support_enabled() && data->pdata->gesture_support) {
+		device_init_wakeup(&client->dev, 0);
+		device_remove_file(&client->dev, &dev_attr_pocket);
+		device_remove_file(&client->dev, &dev_attr_enable);
+		device_destroy(data->gesture_pdata->gesture_class, 0);
+		class_destroy(data->gesture_pdata->gesture_class);
+		devm_kfree(&client->dev, data->gesture_pdata);
+		data->gesture_pdata = NULL;
+	}
+
+	debugfs_remove_recursive(data->dir);
+	device_remove_file(&client->dev, &dev_attr_force_update_fw);
+	device_remove_file(&client->dev, &dev_attr_update_fw);
+	device_remove_file(&client->dev, &dev_attr_fw_name);
+
+#if defined(CONFIG_FB)
+	if (fb_unregister_client(&data->fb_notif))
+		dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	unregister_early_suspend(&data->early_suspend);
+#endif
+	free_irq(client->irq, data);
+
+	if (gpio_is_valid(data->pdata->reset_gpio))
+		gpio_free(data->pdata->reset_gpio);
+
+	if (gpio_is_valid(data->pdata->irq_gpio))
+		gpio_free(data->pdata->irq_gpio);
+
+	if (data->ts_pinctrl) {
+		if (IS_ERR_OR_NULL(data->pinctrl_state_release)) {
+			devm_pinctrl_put(data->ts_pinctrl);
+			data->ts_pinctrl = NULL;
+		} else {
+			retval = pinctrl_select_state(data->ts_pinctrl,
+					data->pinctrl_state_release);
+			if (retval < 0)
+				pr_err("failed to select release pinctrl state\n");
+		}
+	}
+
+	for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
+		sysfs_remove_file(&data->input_dev->dev.kobj,
+					&attrs[attr_count].attr);
+	}
+
+	if (data->pdata->power_on)
+		data->pdata->power_on(false);
+	else
+		ft5x06_power_on(data, false);
+
+	if (data->pdata->power_init)
+		data->pdata->power_init(false);
+	else
+		ft5x06_power_init(data, false);
+
+	input_unregister_device(data->input_dev);
+	kobject_put(data->ts_info_kobj);
+	return 0;
+}
+
+static const struct i2c_device_id ft5x06_ts_id[] = {
+	{"ft5x06_ts", 0},
+	{},
+};
+
+MODULE_DEVICE_TABLE(i2c, ft5x06_ts_id);
+
+#ifdef CONFIG_OF
+static const struct of_device_id ft5x06_match_table[] = {
+	{ .compatible = "focaltech,5x06",},
+	{ },
+};
+#else
+#define ft5x06_match_table NULL
+#endif
+
+static struct i2c_driver ft5x06_ts_driver = {
+	.probe = ft5x06_ts_probe,
+	.remove = ft5x06_ts_remove,
+	.driver = {
+		   .name = "ft5x06_ts",
+		   .owner = THIS_MODULE,
+		.of_match_table = ft5x06_match_table,
+#ifdef CONFIG_PM
+		   .pm = &ft5x06_ts_pm_ops,
+#endif
+		   },
+	.id_table = ft5x06_ts_id,
+};
+
+static int __init ft5x06_ts_init(void)
+{
+	return i2c_add_driver(&ft5x06_ts_driver);
+}
+module_init(ft5x06_ts_init);
+
+static void __exit ft5x06_ts_exit(void)
+{
+	i2c_del_driver(&ft5x06_ts_driver);
+}
+module_exit(ft5x06_ts_exit);
+
+MODULE_DESCRIPTION("FocalTech ft5x06 TouchScreen driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/gen_vkeys.c b/drivers/input/touchscreen/gen_vkeys.c
new file mode 100644
index 0000000..67b32ea
--- /dev/null
+++ b/drivers/input/touchscreen/gen_vkeys.c
@@ -0,0 +1,226 @@
+/* Copyright (c) 2013, 2018 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/input.h>
+#include <linux/input/gen_vkeys.h>
+
+#define MAX_BUF_SIZE	256
+#define VKEY_VER_CODE	"0x01"
+
+#define HEIGHT_SCALE_NUM 8
+#define HEIGHT_SCALE_DENOM 10
+
+#define VKEY_Y_OFFSET_DEFAULT 0
+
+/* numerator and denomenator for border equations */
+#define BORDER_ADJUST_NUM 3
+#define BORDER_ADJUST_DENOM 4
+
+static struct kobject *vkey_obj;
+static char *vkey_buf;
+
+static ssize_t vkey_show(struct kobject  *obj,
+		struct kobj_attribute *attr, char *buf)
+{
+	strlcpy(buf, vkey_buf, MAX_BUF_SIZE);
+	return strnlen(buf, MAX_BUF_SIZE);
+}
+
+static struct kobj_attribute vkey_obj_attr = {
+	.attr = {
+		.mode = 0444,
+	},
+	.show = vkey_show,
+};
+
+static struct attribute *vkey_attr[] = {
+	&vkey_obj_attr.attr,
+	NULL,
+};
+
+static struct attribute_group vkey_grp = {
+	.attrs = vkey_attr,
+};
+
+static int vkey_parse_dt(struct device *dev,
+			struct vkeys_platform_data *pdata)
+{
+	struct device_node *np = dev->of_node;
+	struct property *prop;
+	int rc, val;
+
+	rc = of_property_read_string(np, "label", &pdata->name);
+	if (rc) {
+		dev_err(dev, "Failed to read label\n");
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32(np, "qcom,disp-maxx", &pdata->disp_maxx);
+	if (rc) {
+		dev_err(dev, "Failed to read display max x\n");
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32(np, "qcom,disp-maxy", &pdata->disp_maxy);
+	if (rc) {
+		dev_err(dev, "Failed to read display max y\n");
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32(np, "qcom,panel-maxx", &pdata->panel_maxx);
+	if (rc) {
+		dev_err(dev, "Failed to read panel max x\n");
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32(np, "qcom,panel-maxy", &pdata->panel_maxy);
+	if (rc) {
+		dev_err(dev, "Failed to read panel max y\n");
+		return -EINVAL;
+	}
+
+	prop = of_find_property(np, "qcom,key-codes", NULL);
+	if (prop) {
+		pdata->num_keys = prop->length / sizeof(u32);
+		pdata->keycodes = devm_kzalloc(dev,
+			sizeof(u32) * pdata->num_keys, GFP_KERNEL);
+		if (!pdata->keycodes)
+			return -ENOMEM;
+		rc = of_property_read_u32_array(np, "qcom,key-codes",
+				pdata->keycodes, pdata->num_keys);
+		if (rc) {
+			dev_err(dev, "Failed to read key codes\n");
+			return -EINVAL;
+		}
+	}
+
+	pdata->y_offset = VKEY_Y_OFFSET_DEFAULT;
+	rc = of_property_read_u32(np, "qcom,y-offset", &val);
+	if (!rc)
+		pdata->y_offset = val;
+	else if (rc != -EINVAL) {
+		dev_err(dev, "Failed to read y position offset\n");
+		return rc;
+	}
+	return 0;
+}
+
+static int vkeys_probe(struct platform_device *pdev)
+{
+	struct vkeys_platform_data *pdata;
+	int width, height, center_x, center_y;
+	int x1 = 0, x2 = 0, i, c = 0, ret, border;
+	char *name;
+
+	vkey_buf = devm_kzalloc(&pdev->dev, MAX_BUF_SIZE, GFP_KERNEL);
+	if (!vkey_buf)
+		return -ENOMEM;
+
+	if (pdev->dev.of_node) {
+		pdata = devm_kzalloc(&pdev->dev,
+			sizeof(struct vkeys_platform_data), GFP_KERNEL);
+		if (!pdata)
+			return -ENOMEM;
+
+		ret = vkey_parse_dt(&pdev->dev, pdata);
+		if (ret) {
+			dev_err(&pdev->dev, "Parsing DT failed(%d)", ret);
+			return ret;
+		}
+	} else
+		pdata = pdev->dev.platform_data;
+
+	if (!pdata || !pdata->name || !pdata->keycodes || !pdata->num_keys ||
+		!pdata->disp_maxx || !pdata->disp_maxy || !pdata->panel_maxy) {
+		dev_err(&pdev->dev, "pdata is invalid\n");
+		return -EINVAL;
+	}
+
+	border = (pdata->panel_maxx - pdata->disp_maxx) * 2;
+	width = ((pdata->disp_maxx - (border * (pdata->num_keys - 1)))
+			/ pdata->num_keys);
+	height = (pdata->panel_maxy - pdata->disp_maxy);
+	center_y = pdata->disp_maxy + (height / 2) + pdata->y_offset;
+	height = height * HEIGHT_SCALE_NUM / HEIGHT_SCALE_DENOM;
+
+	x2 -= border * BORDER_ADJUST_NUM / BORDER_ADJUST_DENOM;
+
+	for (i = 0; i < pdata->num_keys; i++) {
+		x1 = x2 + border;
+		x2 = x2 + border + width;
+		center_x = x1 + (x2 - x1) / 2;
+		c += snprintf(vkey_buf + c, MAX_BUF_SIZE - c,
+				"%s:%d:%d:%d:%d:%d\n",
+				VKEY_VER_CODE, pdata->keycodes[i],
+				center_x, center_y, width, height);
+	}
+
+	vkey_buf[c] = '\0';
+
+	name = devm_kzalloc(&pdev->dev, sizeof(*name) * MAX_BUF_SIZE,
+					GFP_KERNEL);
+	if (!name)
+		return -ENOMEM;
+
+	snprintf(name, MAX_BUF_SIZE,
+				"virtualkeys.%s", pdata->name);
+	vkey_obj_attr.attr.name = name;
+
+	vkey_obj = kobject_create_and_add("board_properties", NULL);
+	if (!vkey_obj) {
+		dev_err(&pdev->dev, "unable to create kobject\n");
+		return -ENOMEM;
+	}
+
+	ret = sysfs_create_group(vkey_obj, &vkey_grp);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to create attributes\n");
+		goto destroy_kobj;
+	}
+	return 0;
+
+destroy_kobj:
+	kobject_put(vkey_obj);
+
+	return ret;
+}
+
+static int vkeys_remove(struct platform_device *pdev)
+{
+	sysfs_remove_group(vkey_obj, &vkey_grp);
+	kobject_put(vkey_obj);
+
+	return 0;
+}
+
+static const struct of_device_id vkey_match_table[] = {
+	{ .compatible = "qcom,gen-vkeys",},
+	{ },
+};
+
+static struct platform_driver vkeys_driver = {
+	.probe = vkeys_probe,
+	.remove = vkeys_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "gen_vkeys",
+		.of_match_table = vkey_match_table,
+	},
+};
+
+module_platform_driver(vkeys_driver);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c
index 7633767..21a9e8f 100644
--- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c
+++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.c
@@ -56,8 +56,6 @@
 #define TYPE_B_PROTOCOL
 #endif
 
-#define WAKEUP_GESTURE false
-
 #define NO_0D_WHILE_2D
 #define REPORT_2D_Z
 #define REPORT_2D_W
@@ -1014,8 +1012,10 @@
 
 	input = input > 0 ? 1 : 0;
 
-	if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture)
+	if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture) {
 		rmi4_data->enable_wakeup_gesture = input;
+		rmi4_data->wakeup_gesture_en = input;
+	}
 
 	return count;
 }
@@ -1089,7 +1089,6 @@
 			input_sync(rmi4_data->input_dev);
 			input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 0);
 			input_sync(rmi4_data->input_dev);
-			rmi4_data->suspend = false;
 		}
 
 		return 0;
@@ -1250,7 +1249,6 @@
 			input_sync(rmi4_data->input_dev);
 			input_report_key(rmi4_data->input_dev, KEY_WAKEUP, 0);
 			input_sync(rmi4_data->input_dev);
-			rmi4_data->suspend = false;
 		}
 
 		return 0;
@@ -3114,7 +3112,7 @@
 	}
 
 	if (rmi4_data->f11_wakeup_gesture || rmi4_data->f12_wakeup_gesture)
-		rmi4_data->enable_wakeup_gesture = WAKEUP_GESTURE;
+		rmi4_data->enable_wakeup_gesture = rmi4_data->wakeup_gesture_en;
 	else
 		rmi4_data->enable_wakeup_gesture = false;
 
@@ -3954,6 +3952,7 @@
 	rmi4_data->suspend = false;
 	rmi4_data->irq_enabled = false;
 	rmi4_data->fingers_on_2d = false;
+	rmi4_data->wakeup_gesture_en = bdata->wakeup_gesture_en;
 
 	rmi4_data->reset_device = synaptics_rmi4_reset_device;
 	rmi4_data->irq_enable = synaptics_rmi4_irq_enable;
@@ -4423,7 +4422,8 @@
 				synaptics_secure_touch_stop(rmi4_data, false);
 			} else if (event == FB_EVENT_BLANK) {
 				transition = evdata->data;
-				if (*transition == FB_BLANK_POWERDOWN) {
+				if (*transition == FB_BLANK_POWERDOWN ||
+					*transition == FB_BLANK_VSYNC_SUSPEND) {
 					flush_work(
 						&(rmi4_data->fb_notify_work));
 					synaptics_rmi4_suspend(
@@ -4564,8 +4564,10 @@
 	synaptics_secure_touch_stop(rmi4_data, true);
 
 	if (rmi4_data->enable_wakeup_gesture) {
-		synaptics_rmi4_wakeup_gesture(rmi4_data, true);
-		enable_irq_wake(rmi4_data->irq);
+		if (!rmi4_data->suspend) {
+			synaptics_rmi4_wakeup_gesture(rmi4_data, true);
+			enable_irq_wake(rmi4_data->irq);
+		}
 		goto exit;
 	}
 
@@ -4578,9 +4580,10 @@
 	if (rmi4_data->ts_pinctrl) {
 		retval = pinctrl_select_state(rmi4_data->ts_pinctrl,
 		rmi4_data->pinctrl_state_suspend);
-		if (retval < 0)
+		if (retval < 0) {
 			dev_err(dev, "Cannot get idle pinctrl state\n");
 			goto err_pinctrl;
+		}
 	}
 exit:
 	mutex_lock(&exp_data.mutex);
@@ -4591,10 +4594,9 @@
 	}
 	mutex_unlock(&exp_data.mutex);
 
-	if (!rmi4_data->suspend) {
+	if (!rmi4_data->suspend && !rmi4_data->enable_wakeup_gesture)
 		synaptics_rmi4_enable_reg(rmi4_data, false);
-		synaptics_rmi4_get_reg(rmi4_data, false);
-	}
+
 	rmi4_data->suspend = true;
 
 	return 0;
@@ -4620,17 +4622,17 @@
 	synaptics_secure_touch_stop(rmi4_data, true);
 
 	if (rmi4_data->enable_wakeup_gesture) {
-		synaptics_rmi4_wakeup_gesture(rmi4_data, false);
-		disable_irq_wake(rmi4_data->irq);
+		if (rmi4_data->suspend) {
+			synaptics_rmi4_wakeup_gesture(rmi4_data, false);
+			disable_irq_wake(rmi4_data->irq);
+		}
 		goto exit;
 	}
 
 	rmi4_data->current_page = MASK_8BIT;
 
-	if (rmi4_data->suspend) {
-		synaptics_rmi4_get_reg(rmi4_data, true);
+	if (rmi4_data->suspend)
 		synaptics_rmi4_enable_reg(rmi4_data, true);
-	}
 
 	synaptics_rmi4_sleep_enable(rmi4_data, false);
 	synaptics_rmi4_irq_enable(rmi4_data, true, false);
diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.h b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.h
index 39fec9a..f2fdaf1 100644
--- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.h
+++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_core.h
@@ -372,6 +372,7 @@
 	bool fb_ready;
 	bool f11_wakeup_gesture;
 	bool f12_wakeup_gesture;
+	bool wakeup_gesture_en;
 	bool enable_wakeup_gesture;
 	bool wedge_sensor;
 	bool report_pressure;
diff --git a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c
index df17a0b..f634f17 100644
--- a/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c
+++ b/drivers/input/touchscreen/synaptics_dsx_2.6/synaptics_dsx_i2c.c
@@ -81,6 +81,9 @@
 	bdata->resume_in_workqueue = of_property_read_bool(np,
 			"synaptics,resume-in-workqueue");
 
+	bdata->wakeup_gesture_en = of_property_read_bool(np,
+			"synaptics,wakeup-gestures-en");
+
 	retval = of_property_read_string(np, "synaptics,pwr-reg-name", &name);
 	if (retval < 0)
 		bdata->pwr_reg_name = NULL;
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 40d4a2c..8005ab8 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -542,6 +542,7 @@
 	bool				qsmmuv500_errata1_init;
 	bool				qsmmuv500_errata1_client;
 	bool				qsmmuv500_errata2_min_align;
+	bool				is_force_guard_page;
 };
 
 static DEFINE_SPINLOCK(arm_smmu_devices_lock);
@@ -3245,6 +3246,12 @@
 		*((int *)data) = smmu_domain->qsmmuv500_errata2_min_align;
 		ret = 0;
 		break;
+	case DOMAIN_ATTR_FORCE_IOVA_GUARD_PAGE:
+		*((int *)data) = !!(smmu_domain->attributes
+			& (1 << DOMAIN_ATTR_FORCE_IOVA_GUARD_PAGE));
+		ret = 0;
+		break;
+
 	default:
 		ret = -ENODEV;
 		break;
@@ -3447,6 +3454,28 @@
 				1 << DOMAIN_ATTR_CB_STALL_DISABLE;
 		ret = 0;
 		break;
+
+	case DOMAIN_ATTR_FORCE_IOVA_GUARD_PAGE: {
+		int force_iova_guard_page = *((int *)data);
+
+		if (smmu_domain->smmu != NULL) {
+			dev_err(smmu_domain->smmu->dev,
+			  "cannot change force guard page attribute while attached\n");
+			ret = -EBUSY;
+			break;
+		}
+
+		if (force_iova_guard_page)
+			smmu_domain->attributes |=
+				1 << DOMAIN_ATTR_FORCE_IOVA_GUARD_PAGE;
+		else
+			smmu_domain->attributes &=
+				~(1 << DOMAIN_ATTR_FORCE_IOVA_GUARD_PAGE);
+
+		ret = 0;
+		break;
+	}
+
 	default:
 		ret = -ENODEV;
 	}
@@ -5486,7 +5515,11 @@
 
 	pdev = container_of(dev, struct platform_device, dev);
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tcu-base");
-	data->tcu_base = devm_ioremap_resource(dev, res);
+	if (!res) {
+		dev_err(dev, "Unable to get the tcu-base\n");
+		return -EINVAL;
+	}
+	data->tcu_base = devm_ioremap(dev, res->start, resource_size(res));
 	if (IS_ERR(data->tcu_base))
 		return PTR_ERR(data->tcu_base);
 
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 57ae0dd..36c84df 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -45,6 +45,7 @@
 	spinlock_t		msi_lock;
 	u32			min_iova_align;
 	struct page		*guard_page;
+	u32			force_guard_page_len;
 };
 
 static inline struct iova_domain *cookie_iovad(struct iommu_domain *domain)
@@ -130,20 +131,31 @@
 	struct iommu_dma_cookie *cookie = domain->iova_cookie;
 	int vmid = VMID_HLOS;
 	int min_iova_align = 0;
+	int force_iova_guard_page = 0;
+
 
 	iommu_domain_get_attr(domain,
 			DOMAIN_ATTR_MMU500_ERRATA_MIN_ALIGN,
 			&min_iova_align);
 	iommu_domain_get_attr(domain, DOMAIN_ATTR_SECURE_VMID, &vmid);
+	iommu_domain_get_attr(domain,
+			      DOMAIN_ATTR_FORCE_IOVA_GUARD_PAGE,
+			      &force_iova_guard_page);
+
 	if (vmid >= VMID_LAST || vmid < 0)
 		vmid = VMID_HLOS;
 
-	if (min_iova_align) {
-		cookie->min_iova_align = ARM_SMMU_MIN_IOVA_ALIGN;
-		cookie->guard_page = arm_smmu_errata_get_guard_page(vmid);
-		if (!cookie->guard_page)
-			return -ENOMEM;
-	}
+	cookie->min_iova_align = (min_iova_align) ? ARM_SMMU_MIN_IOVA_ALIGN :
+		PAGE_SIZE;
+
+	if (force_iova_guard_page)
+		cookie->force_guard_page_len = PAGE_SIZE;
+
+	cookie->guard_page =
+		arm_smmu_errata_get_guard_page(vmid);
+	if (!cookie->guard_page)
+		return -ENOMEM;
+
 	return 0;
 }
 
@@ -244,7 +256,8 @@
 	dma_addr_t ret_iova;
 
 	if (cookie->min_iova_align)
-		guard_len = ALIGN(size, cookie->min_iova_align) - size;
+		guard_len = ALIGN(size + cookie->force_guard_page_len,
+				  cookie->min_iova_align) - size;
 	else
 		guard_len = 0;
 	iova_len = (size + guard_len) >> shift;
@@ -290,12 +303,14 @@
 	unsigned long shift = iova_shift(iovad);
 	unsigned long guard_len;
 
-	if (cookie->min_iova_align) {
-		guard_len = ALIGN(size, cookie->min_iova_align) - size;
-		iommu_unmap(domain, iova + size, guard_len);
-	} else {
+	if (cookie->min_iova_align)
+		guard_len = ALIGN(size + cookie->force_guard_page_len,
+				  cookie->min_iova_align) - size;
+	else
 		guard_len = 0;
-	}
+
+	if (guard_len)
+		iommu_unmap(domain, iova + size, guard_len);
 
 	free_iova_fast(iovad, iova >> shift, (size + guard_len) >> shift);
 }
diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c
index eac7b41..7e6287c 100644
--- a/drivers/iommu/dma-mapping-fast.c
+++ b/drivers/iommu/dma-mapping-fast.c
@@ -163,7 +163,8 @@
 	dma_addr_t iova;
 
 	if (mapping->min_iova_align)
-		guard_len = ALIGN(size, mapping->min_iova_align) - size;
+		guard_len = ALIGN(size + mapping->force_guard_page_len,
+				  mapping->min_iova_align) - size;
 	else
 		guard_len = 0;
 
@@ -311,12 +312,15 @@
 	unsigned long nbits;
 	unsigned long guard_len;
 
-	if (mapping->min_iova_align) {
-		guard_len = ALIGN(size, mapping->min_iova_align) - size;
-		iommu_unmap(mapping->domain, iova + size, guard_len);
-	} else {
+	if (mapping->min_iova_align)
+		guard_len = ALIGN(size + mapping->force_guard_page_len,
+				  mapping->min_iova_align) - size;
+	else
 		guard_len = 0;
-	}
+
+	if (guard_len)
+		iommu_unmap(mapping->domain, iova + size, guard_len);
+
 	nbits = (size + guard_len) >> FAST_PAGE_SHIFT;
 
 
@@ -898,20 +902,30 @@
 	struct dma_fast_smmu_mapping *fast = mapping->fast;
 	int vmid = VMID_HLOS;
 	int min_iova_align = 0;
+	int force_iova_guard_page = 0;
 
 	iommu_domain_get_attr(mapping->domain,
-			DOMAIN_ATTR_MMU500_ERRATA_MIN_ALIGN,
-			&min_iova_align);
+			      DOMAIN_ATTR_MMU500_ERRATA_MIN_ALIGN,
+			      &min_iova_align);
 	iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_SECURE_VMID, &vmid);
+	iommu_domain_get_attr(mapping->domain,
+			      DOMAIN_ATTR_FORCE_IOVA_GUARD_PAGE,
+			      &force_iova_guard_page);
+
 	if (vmid >= VMID_LAST || vmid < 0)
 		vmid = VMID_HLOS;
 
-	if (min_iova_align) {
-		fast->min_iova_align = ARM_SMMU_MIN_IOVA_ALIGN;
-		fast->guard_page = arm_smmu_errata_get_guard_page(vmid);
-		if (!fast->guard_page)
-			return -ENOMEM;
-	}
+	fast->min_iova_align = (min_iova_align) ?  ARM_SMMU_MIN_IOVA_ALIGN :
+		PAGE_SIZE;
+
+	if (force_iova_guard_page)
+		fast->force_guard_page_len = PAGE_SIZE;
+
+	fast->guard_page =
+		arm_smmu_errata_get_guard_page(vmid);
+	if (!fast->guard_page)
+		return -ENOMEM;
+
 	return 0;
 }
 
diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h
index 83b72f4..623e572 100644
--- a/drivers/irqchip/irq-gic-common.h
+++ b/drivers/irqchip/irq-gic-common.h
@@ -30,6 +30,12 @@
 extern bool from_suspend;
 extern struct irq_chip gic_arch_extn;
 
+#ifdef CONFIG_QCOM_SHOW_RESUME_IRQ
+extern int msm_show_resume_irq_mask;
+#else
+#define msm_show_resume_irq_mask 0
+#endif
+
 int gic_configure_irq(unsigned int irq, unsigned int type,
                        void __iomem *base, void (*sync_access)(void));
 void gic_dist_config(void __iomem *base, int gic_irqs,
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index cb52fb0..307d545 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -40,6 +40,8 @@
 #include <asm/smp_plat.h>
 #include <asm/virt.h>
 
+#include <linux/syscore_ops.h>
+
 #include "irq-gic-common.h"
 
 struct redist_region {
@@ -370,6 +372,69 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM
+
+static int gic_suspend(void)
+{
+	return 0;
+}
+
+static void gic_show_resume_irq(struct gic_chip_data *gic)
+{
+	unsigned int i;
+	u32 enabled;
+	u32 pending[32];
+	void __iomem *base = gic_data.dist_base;
+
+	if (!msm_show_resume_irq_mask)
+		return;
+
+	for (i = 0; i * 32 < gic->irq_nr; i++) {
+		enabled = readl_relaxed(base + GICD_ICENABLER + i * 4);
+		pending[i] = readl_relaxed(base + GICD_ISPENDR + i * 4);
+		pending[i] &= enabled;
+	}
+
+	for (i = find_first_bit((unsigned long *)pending, gic->irq_nr);
+	     i < gic->irq_nr;
+	     i = find_next_bit((unsigned long *)pending, gic->irq_nr, i+1)) {
+		unsigned int irq = irq_find_mapping(gic->domain, i);
+		struct irq_desc *desc = irq_to_desc(irq);
+		const char *name = "null";
+
+		if (desc == NULL)
+			name = "stray irq";
+		else if (desc->action && desc->action->name)
+			name = desc->action->name;
+
+		pr_warn("%s: %d triggered %s\n", __func__, irq, name);
+	}
+}
+
+static void gic_resume_one(struct gic_chip_data *gic)
+{
+	gic_show_resume_irq(gic);
+}
+
+static void gic_resume(void)
+{
+	gic_resume_one(&gic_data);
+}
+
+static struct syscore_ops gic_syscore_ops = {
+	.suspend = gic_suspend,
+	.resume = gic_resume,
+};
+
+static int __init gic_init_sys(void)
+{
+	register_syscore_ops(&gic_syscore_ops);
+	return 0;
+}
+arch_initcall(gic_init_sys);
+
+#endif
+
 static u64 gic_mpidr_to_affinity(unsigned long mpidr)
 {
 	u64 aff;
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 6c9446e..8f3aa54 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -41,6 +41,7 @@
 #include <linux/irqchip.h>
 #include <linux/irqchip/chained_irq.h>
 #include <linux/irqchip/arm-gic.h>
+#include <linux/msm_rtb.h>
 
 #include <asm/cputype.h>
 #include <asm/irq.h>
@@ -48,6 +49,7 @@
 #include <asm/smp_plat.h>
 #include <asm/virt.h>
 
+#include <linux/syscore_ops.h>
 #include "irq-gic-common.h"
 
 #ifdef CONFIG_ARM64
@@ -363,6 +365,7 @@
 				writel_relaxed_no_log(irqstat,
 						cpu_base + GIC_CPU_EOI);
 			handle_domain_irq(gic->domain, irqnr, regs);
+			uncached_logk(LOGK_IRQ, (void *)(uintptr_t)irqnr);
 			continue;
 		}
 		if (irqnr < 16) {
@@ -381,6 +384,7 @@
 			smp_rmb();
 			handle_IPI(irqnr, regs);
 #endif
+			uncached_logk(LOGK_IRQ, (void *)(uintptr_t)irqnr);
 			continue;
 		}
 		break;
@@ -1232,6 +1236,70 @@
 	return ret;
 }
 
+#ifdef CONFIG_PM
+static int gic_suspend(void)
+{
+	return 0;
+}
+
+static void gic_show_resume_irq(struct gic_chip_data *gic)
+{
+	unsigned int i;
+	u32 enabled;
+	u32 pending[32];
+	void __iomem *base = gic_data_dist_base(gic);
+
+	if (!msm_show_resume_irq_mask)
+		return;
+
+	for (i = 0; i * 32 < gic->gic_irqs; i++) {
+		enabled = readl_relaxed(base + GIC_DIST_ENABLE_CLEAR + i * 4);
+		pending[i] = readl_relaxed(base + GIC_DIST_PENDING_SET + i * 4);
+		pending[i] &= enabled;
+	}
+
+	for (i = find_first_bit((unsigned long *)pending, gic->gic_irqs);
+	i < gic->gic_irqs;
+	i = find_next_bit((unsigned long *)pending, gic->gic_irqs, i+1)) {
+		unsigned int irq = irq_find_mapping(gic->domain, i);
+		struct irq_desc *desc = irq_to_desc(irq);
+		const char *name = "null";
+
+		if (desc == NULL)
+			name = "stray irq";
+		else if (desc->action && desc->action->name)
+			name = desc->action->name;
+
+		pr_warn("%s: %d triggered %s\n", __func__, i, name);
+	}
+}
+
+static void gic_resume_one(struct gic_chip_data *gic)
+{
+	gic_show_resume_irq(gic);
+}
+
+static void gic_resume(void)
+{
+	int i;
+
+	for (i = 0; i < CONFIG_ARM_GIC_MAX_NR; i++)
+		gic_resume_one(&gic_data[i]);
+}
+
+static struct syscore_ops gic_syscore_ops = {
+	.suspend = gic_suspend,
+	.resume = gic_resume,
+};
+
+static int __init gic_init_sys(void)
+{
+	register_syscore_ops(&gic_syscore_ops);
+	return 0;
+}
+arch_initcall(gic_init_sys);
+#endif
+
 void __init gic_init(unsigned int gic_nr, int irq_start,
 		     void __iomem *dist_base, void __iomem *cpu_base)
 {
diff --git a/drivers/irqchip/qcom/Makefile b/drivers/irqchip/qcom/Makefile
index 8871f9a..e30f074 100644
--- a/drivers/irqchip/qcom/Makefile
+++ b/drivers/irqchip/qcom/Makefile
@@ -2,4 +2,4 @@
 obj-$(CONFIG_QTI_PDC_SDM845)		+= pdc-sdm845.o
 obj-$(CONFIG_QTI_PDC_SDM670)		+= pdc-sdm670.o
 obj-$(CONFIG_QTI_PDC_SDXPOORWILLS)	+= pdc-sdxpoorwills.o
-obj-$(CONFIG_QTI_MPM)			+= mpm.o mpm-8953.o mpm-8937.o
+obj-$(CONFIG_QTI_MPM)			+= mpm.o mpm-8909.o mpm-8953.o mpm-8937.o
diff --git a/drivers/irqchip/qcom/mpm-8909.c b/drivers/irqchip/qcom/mpm-8909.c
new file mode 100644
index 0000000..2767171
--- /dev/null
+++ b/drivers/irqchip/qcom/mpm-8909.c
@@ -0,0 +1,70 @@
+/* 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 "mpm.h"
+
+const struct mpm_pin mpm_msm8909_gic_chip_data[] = {
+	{2, 216}, /* tsens_upper_lower_int */
+	{48, 168}, /* usb_phy_id_irq */
+	{49, 172}, /* usb1_hs_async_wakeup_irq */
+	{58, 166}, /* usb_hs_irq */
+	{53, 104}, /* mdss_irq */
+	{62, 222}, /* ee0_krait_hlos_spmi_periph_irq */
+	{-1},
+};
+
+const struct mpm_pin mpm_msm8909_gpio_chip_data[] = {
+	{3, 65 },
+	{4, 5},
+	{5, 11},
+	{6, 12},
+	{7, 64},
+	{8, 58},
+	{9, 50},
+	{10, 13},
+	{11, 49},
+	{12, 20},
+	{13, 21},
+	{14, 25},
+	{15, 46},
+	{16, 45},
+	{17, 28},
+	{18, 44},
+	{19, 31},
+	{20, 43},
+	{21, 42},
+	{22, 34},
+	{23, 35},
+	{24, 36},
+	{25, 37},
+	{26, 38},
+	{27, 39},
+	{28, 40},
+	{29, 41},
+	{30, 90},
+	{32, 91},
+	{33, 92},
+	{34, 94},
+	{35, 95},
+	{36, 96},
+	{37, 97},
+	{38, 98},
+	{39, 110},
+	{40, 111},
+	{41, 112},
+	{42, 105},
+	{43, 107},
+	{50, 47},
+	{51, 48},
+	{-1},
+};
diff --git a/drivers/irqchip/qcom/mpm.c b/drivers/irqchip/qcom/mpm.c
index a8b8b9b..5e352f4 100644
--- a/drivers/irqchip/qcom/mpm.c
+++ b/drivers/irqchip/qcom/mpm.c
@@ -466,6 +466,8 @@
 	}
 
 	msm_mpm_timer_write((uint32_t *)&wakeup);
+	trace_mpm_wakeup_time(from_idle, wakeup, arch_counter_get_cntvct());
+
 	return 0;
 }
 
@@ -595,6 +597,10 @@
 		.compatible = "qcom,mpm-gic-msm8937",
 		.data = mpm_msm8937_gic_chip_data,
 	},
+	{
+		.compatible = "qcom,mpm-gic-msm8909",
+		.data = mpm_msm8909_gic_chip_data,
+	},
 	{}
 };
 
@@ -609,6 +615,10 @@
 		.compatible = "qcom,mpm-gpio-msm8937",
 		.data = mpm_msm8937_gpio_chip_data,
 	},
+	{
+		.compatible = "qcom,mpm-gpio-msm8909",
+		.data = mpm_msm8909_gpio_chip_data,
+	},
 	{}
 };
 
diff --git a/drivers/irqchip/qcom/mpm.h b/drivers/irqchip/qcom/mpm.h
index 50a127f..c82191e 100644
--- a/drivers/irqchip/qcom/mpm.h
+++ b/drivers/irqchip/qcom/mpm.h
@@ -27,4 +27,7 @@
 extern const struct mpm_pin mpm_msm8937_gic_chip_data[];
 extern const struct mpm_pin mpm_msm8937_gpio_chip_data[];
 
+extern const struct mpm_pin mpm_msm8909_gic_chip_data[];
+extern const struct mpm_pin mpm_msm8909_gpio_chip_data[];
+
 #endif /* __QCOM_MPM_H__ */
diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c
index d4b64ba..759d853 100644
--- a/drivers/leds/leds-qpnp-flash-v2.c
+++ b/drivers/leds/leds-qpnp-flash-v2.c
@@ -353,7 +353,7 @@
 	if (!ires_ua || !target_curr_ma || (target_curr_ma < (ires_ua / 1000)))
 		return 0;
 
-	return DIV_ROUND_UP(target_curr_ma * 1000, ires_ua) - 1;
+	return DIV_ROUND_CLOSEST(target_curr_ma * 1000, ires_ua) - 1;
 }
 
 static int qpnp_flash_led_read(struct qpnp_flash_led *led, u16 addr, u8 *data)
diff --git a/drivers/leds/leds-qti-tri-led.c b/drivers/leds/leds-qti-tri-led.c
index f638bc9..c303893 100644
--- a/drivers/leds/leds-qti-tri-led.c
+++ b/drivers/leds/leds-qti-tri-led.c
@@ -53,6 +53,7 @@
 	u32			off_ms;
 	enum led_brightness	brightness;
 	bool			blink;
+	bool			breath;
 };
 
 struct qpnp_led_dev {
@@ -66,6 +67,7 @@
 	const char		*default_trigger;
 	u8			id;
 	bool			blinking;
+	bool			breathing;
 };
 
 struct qpnp_tri_led_chip {
@@ -119,6 +121,10 @@
 	pstate.enabled = !!(pwm->duty_ns != 0);
 	pstate.period = pwm->period_ns;
 	pstate.duty_cycle = pwm->duty_ns;
+	pstate.output_type = led->led_setting.breath ?
+		PWM_OUTPUT_MODULATED : PWM_OUTPUT_FIXED;
+	/* Use default pattern in PWM device */
+	pstate.output_pattern = NULL;
 	rc = pwm_apply_state(led->pwm_dev, &pstate);
 
 	if (rc < 0)
@@ -183,7 +189,9 @@
 		/* Use initial period if no blinking is required */
 		period_ns = led->pwm_setting.pre_period_ns;
 
-		if (period_ns > INT_MAX / brightness)
+		if (brightness == LED_OFF)
+			duty_ns = 0;
+		else if (period_ns > INT_MAX / brightness)
 			duty_ns = (period_ns / LED_FULL) * brightness;
 		else
 			duty_ns = (period_ns * brightness) / LED_FULL;
@@ -207,9 +215,15 @@
 	if (led->led_setting.blink) {
 		led->cdev.brightness = LED_FULL;
 		led->blinking = true;
+		led->breathing = false;
+	} else if (led->led_setting.breath) {
+		led->cdev.brightness = LED_FULL;
+		led->blinking = false;
+		led->breathing = true;
 	} else {
 		led->cdev.brightness = led->led_setting.brightness;
 		led->blinking = false;
+		led->breathing = false;
 	}
 
 	return rc;
@@ -227,7 +241,7 @@
 		brightness = LED_FULL;
 
 	if (brightness == led->led_setting.brightness &&
-				!led->blinking) {
+			!led->blinking && !led->breathing) {
 		mutex_unlock(&led->lock);
 		return 0;
 	}
@@ -238,6 +252,7 @@
 	else
 		led->led_setting.on_ms = 0;
 	led->led_setting.blink = false;
+	led->led_setting.breath = false;
 
 	rc = qpnp_tri_led_set(led);
 	if (rc)
@@ -273,14 +288,17 @@
 
 	if (*on_ms == 0) {
 		led->led_setting.blink = false;
+		led->led_setting.breath = false;
 		led->led_setting.brightness = LED_OFF;
 	} else if (*off_ms == 0) {
 		led->led_setting.blink = false;
+		led->led_setting.breath = false;
 		led->led_setting.brightness = led->cdev.brightness;
 	} else {
 		led->led_setting.on_ms = *on_ms;
 		led->led_setting.off_ms = *off_ms;
 		led->led_setting.blink = true;
+		led->led_setting.breath = false;
 	}
 
 	rc = qpnp_tri_led_set(led);
@@ -292,6 +310,52 @@
 	return rc;
 }
 
+static ssize_t breath_show(struct device *dev, struct device_attribute *attr,
+							char *buf)
+{
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct qpnp_led_dev *led =
+		container_of(led_cdev, struct qpnp_led_dev, cdev);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", led->led_setting.breath);
+}
+
+static ssize_t breath_store(struct device *dev, struct device_attribute *attr,
+						const char *buf, size_t count)
+{
+	int rc;
+	bool breath;
+	struct led_classdev *led_cdev = dev_get_drvdata(dev);
+	struct qpnp_led_dev *led =
+		container_of(led_cdev, struct qpnp_led_dev, cdev);
+
+	rc = kstrtobool(buf, &breath);
+	if (rc < 0)
+		return rc;
+
+	mutex_lock(&led->lock);
+	if (led->breathing == breath)
+		goto unlock;
+
+	led->led_setting.blink = false;
+	led->led_setting.breath = breath;
+	led->led_setting.brightness = breath ? LED_FULL : LED_OFF;
+	rc = qpnp_tri_led_set(led);
+	if (rc < 0)
+		dev_err(led->chip->dev, "Set led failed for %s, rc=%d\n",
+				led->label, rc);
+
+unlock:
+	mutex_unlock(&led->lock);
+	return (rc < 0) ? rc : count;
+}
+
+static DEVICE_ATTR(breath, 0644, breath_show, breath_store);
+static const struct attribute *breath_attrs[] = {
+	&dev_attr_breath.attr,
+	NULL
+};
+
 static int qpnp_tri_led_register(struct qpnp_tri_led_chip *chip)
 {
 	struct qpnp_led_dev *led;
@@ -313,15 +377,30 @@
 		if (rc < 0) {
 			dev_err(chip->dev, "%s led class device registering failed, rc=%d\n",
 							led->label, rc);
-			goto destroy;
+			goto err_out;
+		}
+
+		if (pwm_get_output_type_supported(led->pwm_dev)
+				& PWM_OUTPUT_MODULATED) {
+			rc = sysfs_create_files(&led->cdev.dev->kobj,
+					breath_attrs);
+			if (rc < 0) {
+				dev_err(chip->dev, "Create breath file for %s led failed, rc=%d\n",
+						led->label, rc);
+				goto err_out;
+			}
 		}
 	}
 
 	return 0;
-destroy:
-	for (j = 0; j <= i; j++)
-		mutex_destroy(&chip->leds[i].lock);
 
+err_out:
+	for (j = 0; j <= i; j++) {
+		if (j < i)
+			sysfs_remove_files(&chip->leds[j].cdev.dev->kobj,
+					breath_attrs);
+		mutex_destroy(&chip->leds[j].lock);
+	}
 	return rc;
 }
 
@@ -483,8 +562,10 @@
 	struct qpnp_tri_led_chip *chip = dev_get_drvdata(&pdev->dev);
 
 	mutex_destroy(&chip->bus_lock);
-	for (i = 0; i < chip->num_leds; i++)
+	for (i = 0; i < chip->num_leds; i++) {
+		sysfs_remove_files(&chip->leds[i].cdev.dev->kobj, breath_attrs);
 		mutex_destroy(&chip->leds[i].lock);
+	}
 	dev_set_drvdata(chip->dev, NULL);
 	return 0;
 }
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.h b/drivers/media/platform/msm/camera/cam_core/cam_context.h
index 8324e78..ffceea2 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.h
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.h
@@ -70,7 +70,7 @@
 	uint32_t                      num_in_map_entries;
 	struct cam_hw_fence_map_entry out_map_entries[CAM_CTX_CFG_MAX];
 	uint32_t                      num_out_map_entries;
-	uint32_t                      num_in_acked;
+	atomic_t                      num_in_acked;
 	uint32_t                      num_out_acked;
 	int                           flushed;
 	struct cam_context           *ctx;
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 b4f83f7..f167ef7 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
@@ -189,8 +189,7 @@
 		return;
 	}
 
-	req->num_in_acked++;
-	if (req->num_in_acked == req->num_in_map_entries) {
+	if (atomic_inc_return(&req->num_in_acked) == req->num_in_map_entries) {
 		apply.request_id = req->request_id;
 		/*
 		 * take mutex to ensure that another thread does
@@ -342,6 +341,7 @@
 	req->num_hw_update_entries = cfg.num_hw_update_entries;
 	req->num_out_map_entries = cfg.num_out_map_entries;
 	req->num_in_map_entries = cfg.num_in_map_entries;
+	atomic_set(&req->num_in_acked, 0);
 	req->request_id = packet->header.request_id;
 	req->status = 1;
 	req->req_priv = cfg.priv;
@@ -492,6 +492,7 @@
 	struct cam_ctx_request *req;
 	uint32_t i;
 	int rc = 0;
+	bool free_req;
 
 	CAM_DBG(CAM_CTXT, "[%s] E: NRT flush ctx", ctx->dev_name);
 
@@ -528,6 +529,21 @@
 
 		flush_args.flush_req_pending[flush_args.num_req_pending++] =
 			req->req_priv;
+
+		free_req = false;
+		for (i = 0; i < req->num_in_map_entries; i++) {
+			rc = cam_sync_deregister_callback(
+				cam_context_sync_callback,
+				(void *)req,
+				req->in_map_entries[i].sync_id);
+			if (!rc) {
+				cam_context_putref(ctx);
+				if (atomic_inc_return(&req->num_in_acked) ==
+					req->num_in_map_entries)
+					free_req = true;
+			}
+		}
+
 		for (i = 0; i < req->num_out_map_entries; i++) {
 			if (req->out_map_entries[i].sync_id != -1) {
 				rc = cam_sync_signal(
@@ -543,6 +559,17 @@
 			}
 		}
 
+		/*
+		 * If we have deregistered the last sync callback, req will
+		 * not be put on the free list. So put it on the free list here
+		 */
+		if (free_req) {
+			req->ctx = NULL;
+			spin_lock(&ctx->lock);
+			list_add_tail(&req->list, &ctx->free_req_list);
+			spin_unlock(&ctx->lock);
+		}
+
 		if (cam_debug_ctx_req_list & ctx->dev_id)
 			CAM_INFO(CAM_CTXT,
 				"[%s][%d] : Deleting req[%llu] from temp_list",
@@ -630,6 +657,7 @@
 	uint32_t i;
 	int32_t sync_id = 0;
 	int rc = 0;
+	bool free_req = false;
 
 	CAM_DBG(CAM_CTXT, "[%s] E: NRT flush req", ctx->dev_name);
 
@@ -682,6 +710,22 @@
 	}
 
 	if (req) {
+		if (flush_args.num_req_pending) {
+			for (i = 0; i < req->num_in_map_entries; i++) {
+				rc = cam_sync_deregister_callback(
+					cam_context_sync_callback,
+					(void *)req,
+					req->in_map_entries[i].sync_id);
+				if (rc)
+					continue;
+
+				cam_context_putref(ctx);
+				if (atomic_inc_return(&req->num_in_acked) ==
+					req->num_in_map_entries)
+					free_req = true;
+			}
+		}
+
 		if (flush_args.num_req_pending || flush_args.num_req_active) {
 			for (i = 0; i < req->num_out_map_entries; i++) {
 				sync_id =
@@ -697,17 +741,20 @@
 					}
 				}
 			}
-			if (flush_args.num_req_active) {
+			if (flush_args.num_req_active || free_req) {
+				req->ctx = NULL;
 				spin_lock(&ctx->lock);
 				list_add_tail(&req->list, &ctx->free_req_list);
 				spin_unlock(&ctx->lock);
-				req->ctx = NULL;
 
 				if (cam_debug_ctx_req_list & ctx->dev_id)
 					CAM_INFO(CAM_CTXT,
-						"[%s][%d] : Moving req[%llu] from active_list to free_list",
+						"[%s][%d] : Moving req[%llu] from %s to free_list",
 						ctx->dev_name, ctx->ctx_id,
-						req->request_id);
+						req->request_id,
+						flush_args.num_req_active ?
+							"active_list" :
+							"pending_list");
 			}
 		}
 	}
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
index 74f349a..158bbb9 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
@@ -374,7 +374,8 @@
 		if ((payload->irq_status & camnoc_info->irq_err[i].sbm_port) &&
 			(camnoc_info->irq_err[i].enable)) {
 			irq_type = camnoc_info->irq_err[i].irq_type;
-			CAM_ERR(CAM_CPAS, "Error occurred, type=%d", irq_type);
+			CAM_ERR_RATE_LIMIT(CAM_CPAS,
+				"Error occurred, type=%d", irq_type);
 			memset(&irq_data, 0x0, sizeof(irq_data));
 			irq_data.irq_type = (enum cam_camnoc_irq_type)irq_type;
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
index f556780..2c364e01 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_intf.h
@@ -121,6 +121,12 @@
 int hfi_set_debug_level(u64 a5_dbg_type, uint32_t lvl);
 
 /**
+ * hfi_set_fw_dump_level() - set firmware dump level
+ * @lvl: level of firmware dump level
+ */
+int hfi_set_fw_dump_level(uint32_t lvl);
+
+/**
  * hfi_enable_ipe_bps_pc() - Enable interframe pc
  * Host sends a command to firmware to enable interframe
  * power collapse for IPE and BPS hardware.
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_sys_defs.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_sys_defs.h
index 91190b6..311886f 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_sys_defs.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_sys_defs.h
@@ -160,6 +160,7 @@
 #define HFI_PROP_SYS_IMAGE_VER         (HFI_PROPERTY_ICP_COMMON_START + 0x3)
 #define HFI_PROP_SYS_SUPPORTED         (HFI_PROPERTY_ICP_COMMON_START + 0x4)
 #define HFI_PROP_SYS_IPEBPS_PC         (HFI_PROPERTY_ICP_COMMON_START + 0x5)
+#define HFI_PROP_SYS_FW_DUMP_CFG       (HFI_PROPERTY_ICP_COMMON_START + 0x8)
 
 /* Capabilities reported at sys init */
 #define HFI_CAPS_PLACEHOLDER_1         (HFI_COMMON_BASE + 0x1)
@@ -180,6 +181,18 @@
 /* Disable ARM9 watchdog. */
 #define  HFI_DEBUG_CFG_ARM9WD   0x10000000
 
+
+/*
+ * HFI_FW_DUMP levels
+ * HFI_FW_DUMP_xx
+ */
+#define HFI_FW_DUMP_DISABLED    0x00000000
+#define HFI_FW_DUMP_ON_FAILURE  0x00000001
+#define HFI_FW_DUMP_ALWAYS      0x00000002
+
+/* Number of available dump levels. */
+#define NUM_HFI_DUMP_LVL        0x00000003
+
 /* Debug Msg Communication types:
  * Section describes different modes (HFI_DEBUG_MODE_X)
  * available to communicate the debug messages
diff --git a/drivers/media/platform/msm/camera/cam_icp/hfi.c b/drivers/media/platform/msm/camera/cam_icp/hfi.c
index b75719b..a0752f5 100644
--- a/drivers/media/platform/msm/camera/cam_icp/hfi.c
+++ b/drivers/media/platform/msm/camera/cam_icp/hfi.c
@@ -324,6 +324,42 @@
 	return 0;
 }
 
+int hfi_set_fw_dump_level(uint32_t lvl)
+{
+	uint8_t *prop = NULL;
+	struct hfi_cmd_prop *fw_dump_level_switch_prop = NULL;
+	uint32_t size = 0;
+
+	CAM_DBG(CAM_HFI, "fw dump ENTER");
+
+	size = sizeof(struct hfi_cmd_prop) + sizeof(lvl);
+	prop = kzalloc(size, GFP_KERNEL);
+	if (!prop)
+		return -ENOMEM;
+
+	fw_dump_level_switch_prop = (struct hfi_cmd_prop *)prop;
+	fw_dump_level_switch_prop->size = size;
+	fw_dump_level_switch_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
+	fw_dump_level_switch_prop->num_prop = 1;
+	fw_dump_level_switch_prop->prop_data[0] = HFI_PROP_SYS_FW_DUMP_CFG;
+	fw_dump_level_switch_prop->prop_data[1] = lvl;
+
+	CAM_DBG(CAM_HFI, "prop->size = %d\n"
+			 "prop->pkt_type = %d\n"
+			 "prop->num_prop = %d\n"
+			 "prop->prop_data[0] = %d\n"
+			 "prop->prop_data[1] = %d\n",
+			 fw_dump_level_switch_prop->size,
+			 fw_dump_level_switch_prop->pkt_type,
+			 fw_dump_level_switch_prop->num_prop,
+			 fw_dump_level_switch_prop->prop_data[0],
+			 fw_dump_level_switch_prop->prop_data[1]);
+
+	hfi_write_cmd(prop);
+	kfree(prop);
+	return 0;
+}
+
 void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size)
 {
 	switch (type) {
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 9ed71d2..16e97ea 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
@@ -57,6 +57,8 @@
 #define ICP_DEV_TYPE_TO_CLK_TYPE(dev_type) \
 	((dev_type == CAM_ICP_RES_TYPE_BPS) ? ICP_CLK_HW_BPS : ICP_CLK_HW_IPE)
 
+#define ICP_DEVICE_IDLE_TIMEOUT 400
+
 static struct cam_icp_hw_mgr icp_hw_mgr;
 
 static int cam_icp_send_ubwc_cfg(struct cam_icp_hw_mgr *hw_mgr)
@@ -549,7 +551,7 @@
 	for (i = 0; i < ICP_CLK_HW_MAX; i++)  {
 		if (!hw_mgr->clk_info[i].watch_dog) {
 			rc = crm_timer_init(&hw_mgr->clk_info[i].watch_dog,
-				3000, &hw_mgr->clk_info[i],
+				ICP_DEVICE_IDLE_TIMEOUT, &hw_mgr->clk_info[i],
 				&cam_icp_device_timer_cb);
 
 			if (rc)
@@ -1283,6 +1285,22 @@
 DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_type_fs, cam_icp_get_a5_dbg_type,
 	cam_icp_set_a5_dbg_type, "%08llu");
 
+static int cam_icp_set_a5_fw_dump_lvl(void *data, u64 val)
+{
+	if (val < NUM_HFI_DUMP_LVL)
+		icp_hw_mgr.a5_fw_dump_lvl = val;
+	return 0;
+}
+
+static int cam_icp_get_a5_fw_dump_lvl(void *data, u64 *val)
+{
+	*val = icp_hw_mgr.a5_fw_dump_lvl;
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_fw_dump, cam_icp_get_a5_fw_dump_lvl,
+	cam_icp_set_a5_fw_dump_lvl, "%08llu");
+
 static int cam_icp_hw_mgr_create_debugfs_entry(void)
 {
 	int rc = 0;
@@ -1333,7 +1351,7 @@
 		0644,
 		icp_hw_mgr.dentry,
 		NULL, &cam_icp_debug_type_fs)) {
-		CAM_ERR(CAM_ICP, "failed to create a5_debug_type\n");
+		CAM_ERR(CAM_ICP, "failed to create a5_debug_type");
 		rc = -ENOMEM;
 		goto err;
 	}
@@ -1342,7 +1360,16 @@
 		0644,
 		icp_hw_mgr.dentry,
 		NULL, &cam_icp_debug_fs)) {
-		CAM_ERR(CAM_ICP, "failed to create a5_dbg_lvl\n");
+		CAM_ERR(CAM_ICP, "failed to create a5_dbg_lvl");
+		rc = -ENOMEM;
+		goto err;
+	}
+
+	if (!debugfs_create_file("a5_fw_dump_lvl",
+		0644,
+		icp_hw_mgr.dentry,
+		NULL, &cam_icp_debug_fw_dump)) {
+		CAM_ERR(CAM_ICP, "failed to create a5_fw_dump_lvl");
 		rc = -ENOMEM;
 		goto err;
 	}
@@ -2258,13 +2285,7 @@
 	unsigned long rem_jiffies;
 	size_t packet_size;
 	int timeout = 100;
-	struct hfi_cmd_work_data *task_data;
 	struct hfi_cmd_ipebps_async *abort_cmd;
-	struct crm_workq_task *task;
-
-	task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
-	if (!task)
-		return -ENOMEM;
 
 	packet_size =
 		sizeof(struct hfi_cmd_ipebps_async) +
@@ -2290,13 +2311,7 @@
 	abort_cmd->user_data1 = (uint64_t)ctx_data;
 	abort_cmd->user_data2 = (uint64_t)0x0;
 
-	task_data = (struct hfi_cmd_work_data *)task->payload;
-	task_data->data = (void *)abort_cmd;
-	task_data->request_id = 0;
-	task_data->type = ICP_WORKQ_TASK_CMD_TYPE;
-	task->process_cb = cam_icp_mgr_process_cmd;
-	rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
-		CRM_TASK_PRIORITY_0);
+	rc = hfi_write_cmd(abort_cmd);
 	if (rc) {
 		kfree(abort_cmd);
 		return rc;
@@ -2310,6 +2325,7 @@
 		CAM_ERR(CAM_ICP, "FW timeout/err in abort handle command");
 	}
 
+	kfree(abort_cmd);
 	return rc;
 }
 
@@ -2320,13 +2336,7 @@
 	int timeout = 100;
 	unsigned long rem_jiffies;
 	size_t packet_size;
-	struct hfi_cmd_work_data *task_data;
 	struct hfi_cmd_ipebps_async *destroy_cmd;
-	struct crm_workq_task *task;
-
-	task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
-	if (!task)
-		return -ENOMEM;
 
 	packet_size =
 		sizeof(struct hfi_cmd_ipebps_async) +
@@ -2353,13 +2363,7 @@
 	memcpy(destroy_cmd->payload.direct, &ctx_data->temp_payload,
 		sizeof(uint64_t));
 
-	task_data = (struct hfi_cmd_work_data *)task->payload;
-	task_data->data = (void *)destroy_cmd;
-	task_data->request_id = 0;
-	task_data->type = ICP_WORKQ_TASK_CMD_TYPE;
-	task->process_cb = cam_icp_mgr_process_cmd;
-	rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
-		CRM_TASK_PRIORITY_0);
+	rc = hfi_write_cmd(destroy_cmd);
 	if (rc) {
 		kfree(destroy_cmd);
 		return rc;
@@ -2376,6 +2380,7 @@
 			HFI_DEBUG_MODE_QUEUE)
 			cam_icp_mgr_process_dbg_buf();
 	}
+	kfree(destroy_cmd);
 	return rc;
 }
 
@@ -3864,6 +3869,8 @@
 			hfi_set_debug_level(icp_hw_mgr.a5_debug_type,
 				icp_hw_mgr.a5_dbg_lvl);
 
+		hfi_set_fw_dump_level(icp_hw_mgr.a5_fw_dump_lvl);
+
 		rc = cam_icp_send_ubwc_cfg(hw_mgr);
 		if (rc)
 			goto ubwc_cfg_failed;
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
index c94550d..8746ee2 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
@@ -279,6 +279,7 @@
  * @a5_jtag_debug: entry to enable A5 JTAG debugging
  * @a5_debug_type : entry to enable FW debug message/qdss
  * @a5_dbg_lvl : debug level set to FW.
+ * @a5_fw_dump_lvl : level set for dumping the FW data
  * @ipe0_enable: Flag for IPE0
  * @ipe1_enable: Flag for IPE1
  * @bps_enable: Flag for BPS
@@ -325,6 +326,7 @@
 	bool a5_jtag_debug;
 	u64 a5_debug_type;
 	u64 a5_dbg_lvl;
+	u64 a5_fw_dump_lvl;
 	bool ipe0_enable;
 	bool ipe1_enable;
 	bool bps_enable;
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 1106453..97e977d 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
@@ -447,6 +447,33 @@
 	return rc;
 }
 
+static void __cam_isp_ctx_send_sof_boot_timestamp(
+	struct cam_isp_context *ctx_isp, uint64_t request_id,
+	uint32_t sof_event_status)
+{
+	struct cam_req_mgr_message   req_msg;
+
+	req_msg.session_hdl = ctx_isp->base->session_hdl;
+	req_msg.u.frame_msg.frame_id = ctx_isp->frame_id;
+	req_msg.u.frame_msg.request_id = request_id;
+	req_msg.u.frame_msg.timestamp = ctx_isp->boot_timestamp;
+	req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl;
+	req_msg.u.frame_msg.sof_status = sof_event_status;
+
+	CAM_DBG(CAM_ISP,
+		"request id:%lld frame number:%lld boot time stamp:0x%llx",
+		 request_id, ctx_isp->frame_id,
+		 ctx_isp->boot_timestamp);
+
+	if (cam_req_mgr_notify_message(&req_msg,
+		V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS,
+		V4L_EVENT_CAM_REQ_MGR_EVENT))
+		CAM_ERR(CAM_ISP,
+			"Error in notifying the boot time for req id:%lld",
+			request_id);
+}
+
+
 static void __cam_isp_ctx_send_sof_timestamp(
 	struct cam_isp_context *ctx_isp, uint64_t request_id,
 	uint32_t sof_event_status)
@@ -464,13 +491,17 @@
 		"request id:%lld frame number:%lld SOF time stamp:0x%llx",
 		 request_id, ctx_isp->frame_id,
 		ctx_isp->sof_timestamp_val);
-	CAM_DBG(CAM_ISP, " sof status:%d", sof_event_status);
+	CAM_DBG(CAM_ISP, "sof status:%d", sof_event_status);
 
 	if (cam_req_mgr_notify_message(&req_msg,
 		V4L_EVENT_CAM_REQ_MGR_SOF, V4L_EVENT_CAM_REQ_MGR_EVENT))
 		CAM_ERR(CAM_ISP,
 			"Error in notifying the sof time for req id:%lld",
 			request_id);
+
+	__cam_isp_ctx_send_sof_boot_timestamp(ctx_isp,
+		request_id, sof_event_status);
+
 }
 
 static int __cam_isp_ctx_reg_upd_in_activated_state(
@@ -617,6 +648,7 @@
 
 	ctx_isp->frame_id++;
 	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	ctx_isp->boot_timestamp = sof_event_data->boot_time;
 	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
 		CAM_ISP_STATE_CHANGE_TRIGGER_SOF, req->request_id);
 	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
@@ -773,6 +805,7 @@
 
 	ctx_isp->frame_id++;
 	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	ctx_isp->boot_timestamp = sof_event_data->boot_time;
 
 	if (list_empty(&ctx->active_req_list))
 		ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
@@ -1045,6 +1078,7 @@
 	}
 	ctx_isp->frame_id++;
 	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	ctx_isp->boot_timestamp = sof_event_data->boot_time;
 	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
 		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
 
@@ -1470,6 +1504,8 @@
 
 	ctx_isp->frame_id++;
 	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	ctx_isp->boot_timestamp = sof_event_data->boot_time;
+
 	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
 		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
 
@@ -1523,6 +1559,7 @@
 
 	ctx_isp->frame_id++;
 	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	ctx_isp->boot_timestamp = sof_event_data->boot_time;
 	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
 		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
 
@@ -1554,6 +1591,7 @@
 
 	ctx_isp->frame_id++;
 	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	ctx_isp->boot_timestamp = sof_event_data->boot_time;
 	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
 		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
 
@@ -1639,6 +1677,7 @@
 
 	ctx_isp->frame_id++;
 	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	ctx_isp->boot_timestamp = sof_event_data->boot_time;
 	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
 		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
 	/*
@@ -1701,6 +1740,7 @@
 	struct cam_req_mgr_trigger_notify  notify;
 	uint64_t  request_id  = 0;
 
+	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
 	/* notify reqmgr with sof signal*/
 	if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger) {
 		if (list_empty(&ctx->pending_req_list)) {
@@ -1712,13 +1752,19 @@
 		list_del_init(&req->list);
 
 		req_isp = (struct cam_isp_ctx_req *) req->req_priv;
-		request_id = req->request_id;
+		request_id =
+			(req_isp->hw_update_data.packet_opcode_type ==
+				CAM_ISP_PACKET_INIT_DEV) ?
+			0 : req->request_id;
+
 		if (req_isp->num_fence_map_out != 0) {
 			list_add_tail(&req->list, &ctx->active_req_list);
 			ctx_isp->active_req_cnt++;
 			CAM_DBG(CAM_ISP,
 				"move request %lld to active list(cnt = %d)",
 				req->request_id, ctx_isp->active_req_cnt);
+			/* if packet has buffers, set correct request id */
+			request_id = req->request_id;
 		} else {
 			/* no io config, so the request is completed. */
 			list_add_tail(&req->list, &ctx->free_req_list);
@@ -1738,10 +1784,11 @@
 	} else {
 		CAM_ERR(CAM_ISP, "Can not notify SOF to CRM");
 	}
+	if (request_id)
+		ctx_isp->reported_req_id = request_id;
+
 	__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
 		CAM_REQ_MGR_SOF_EVENT_SUCCESS);
-
-	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH;
 	CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
 
 	return 0;
@@ -2042,7 +2089,7 @@
 	req->request_id = packet->header.request_id;
 	req->status = 1;
 
-	CAM_DBG(CAM_ISP, "Packet request id 0x%llx packet opcode:%d",
+	CAM_DBG(CAM_ISP, "Packet request id %lld packet opcode:%d",
 		packet->header.request_id,
 		req_isp->hw_update_data.packet_opcode_type);
 
@@ -2185,6 +2232,7 @@
 			cam_isp_ctx_activated_state_machine;
 	}
 
+	ctx_isp->rdi_only_context = hw_cmd_args.u.is_rdi_only_context;
 	ctx_isp->hw_ctx = param.ctxt_to_hw_map;
 
 	req_hdl_param.session_hdl = cmd->session_handle;
@@ -2330,7 +2378,8 @@
 	ctx_isp->frame_id = 0;
 	ctx_isp->active_req_cnt = 0;
 	ctx_isp->reported_req_id = 0;
-	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
+	ctx_isp->substate_activated = ctx_isp->rdi_only_context ?
+		CAM_ISP_CTX_ACTIVATED_APPLIED : CAM_ISP_CTX_ACTIVATED_SOF;
 
 	/*
 	 * Only place to change state before calling the hw due to
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
index 1eae89f..a939f2d 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
@@ -149,6 +149,7 @@
  * @req_isp:                   ISP private request object storage
  * @hw_ctx:                    HW object returned by the acquire device command
  * @sof_timestamp_val:         Captured time stamp value at sof hw event
+ * @boot_timestamp:            Boot time stamp for a given req_id
  * @active_req_cnt:            Counter for the active request
  * @reported_req_id:           Last reported request id
  * @subscribe_event:           The irq event mask that CRM subscribes to, IFE
@@ -157,6 +158,8 @@
  * @frame_skip_count:          Number of frame to skip before change state
  * @state_monitor_head:        Write index to the state monitoring array
  * @cam_isp_ctx_state_monitor: State monitoring array
+ * @rdi_only_context:          Get context type information.
+ *                             true, if context is rdi only context
  *
  */
 struct cam_isp_context {
@@ -172,6 +175,7 @@
 
 	void                            *hw_ctx;
 	uint64_t                         sof_timestamp_val;
+	uint64_t                         boot_timestamp;
 	int32_t                          active_req_cnt;
 	int64_t                          reported_req_id;
 	uint32_t                         subscribe_event;
@@ -180,6 +184,7 @@
 	atomic64_t                       state_monitor_head;
 	struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[
 		CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES];
+	bool                             rdi_only_context;
 };
 
 /**
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 6e140e2..0a127ef 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
@@ -1418,7 +1418,7 @@
 
 		in_port = memdup_user((void __user *)isp_resource[i].res_hdl,
 			isp_resource[i].length);
-		if (in_port > 0) {
+		if (!IS_ERR(in_port)) {
 			rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port,
 				&num_pix_port_per_in, &num_rdi_port_per_in);
 			total_pix_port += num_pix_port_per_in;
@@ -1611,6 +1611,9 @@
 			cdm_cmd->cmd[i].len = cmd->len;
 		}
 
+		if (cfg->request_id == 1)
+			init_completion(&ctx->config_done_complete);
+
 		CAM_DBG(CAM_ISP, "Submit to CDM");
 		rc = cam_cdm_submit_bls(ctx->cdm_handle, cdm_cmd);
 		if (rc) {
@@ -1619,7 +1622,6 @@
 		}
 
 		if (cfg->request_id == 1) {
-			init_completion(&ctx->config_done_complete);
 			rc = wait_for_completion_timeout(
 				&ctx->config_done_complete,
 				msecs_to_jiffies(30));
@@ -2675,7 +2677,8 @@
 
 static int cam_ife_mgr_cmd_get_sof_timestamp(
 	struct cam_ife_hw_mgr_ctx      *ife_ctx,
-	uint64_t                       *time_stamp)
+	uint64_t                       *time_stamp,
+	uint64_t                       *boot_time_stamp)
 {
 	int rc = -EINVAL;
 	uint32_t i;
@@ -2704,9 +2707,12 @@
 					&csid_get_time,
 					sizeof(
 					struct cam_csid_get_time_stamp_args));
-				if (!rc)
+				if (!rc) {
 					*time_stamp =
 						csid_get_time.time_stamp_val;
+					*boot_time_stamp =
+						csid_get_time.boot_timestamp;
+				}
 			/*
 			 * Single VFE case, Get the time stamp from available
 			 * one csid hw in the context
@@ -3537,7 +3543,8 @@
 				if (!sof_status && !sof_sent) {
 					cam_ife_mgr_cmd_get_sof_timestamp(
 						ife_hw_mgr_ctx,
-						&sof_done_event_data.timestamp);
+						&sof_done_event_data.timestamp,
+						&sof_done_event_data.boot_time);
 
 					ife_hw_irq_sof_cb(
 						ife_hw_mgr_ctx->common.cb_priv,
@@ -3558,7 +3565,8 @@
 			if (!sof_status && !sof_sent) {
 				cam_ife_mgr_cmd_get_sof_timestamp(
 					ife_hw_mgr_ctx,
-					&sof_done_event_data.timestamp);
+					&sof_done_event_data.timestamp,
+					&sof_done_event_data.boot_time);
 
 				ife_hw_irq_sof_cb(
 					ife_hw_mgr_ctx->common.cb_priv,
@@ -4172,6 +4180,8 @@
 		g_ife_hw_mgr.ctx_pool[i].common.tasklet_info =
 			g_ife_hw_mgr.mgr_common.tasklet_pool[i];
 
+
+		init_completion(&g_ife_hw_mgr.ctx_pool[i].config_done_complete);
 		list_add_tail(&g_ife_hw_mgr.ctx_pool[i].list,
 			&g_ife_hw_mgr.free_ctx_list);
 	}
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 2601190..5410858 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
@@ -108,11 +108,13 @@
 /**
  * struct cam_isp_hw_sof_event_data - Event payload for CAM_HW_EVENT_SOF
  *
- * @timestamp:     Time stamp for the sof event
+ * @timestamp:   Time stamp for the sof event
+ * @boot_time:   Boot time stamp for the sof event
  *
  */
 struct cam_isp_hw_sof_event_data {
 	uint64_t       timestamp;
+	uint64_t       boot_time;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index 34f8c41..053eb00 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -856,7 +856,27 @@
 	path_data->height  = reserve->in_port->height;
 	path_data->start_line = reserve->in_port->line_start;
 	path_data->end_line = reserve->in_port->line_stop;
-	path_data->crop_enable = true;
+
+	/* Enable RDI crop for single ife use case only */
+	switch (reserve->res_id) {
+	case CAM_IFE_PIX_PATH_RES_RDI_0:
+	case CAM_IFE_PIX_PATH_RES_RDI_1:
+	case CAM_IFE_PIX_PATH_RES_RDI_2:
+	case CAM_IFE_PIX_PATH_RES_RDI_3:
+		if (reserve->in_port->usage_type)
+			path_data->crop_enable = false;
+		else
+			path_data->crop_enable = true;
+
+		break;
+	case CAM_IFE_PIX_PATH_RES_IPP:
+		path_data->crop_enable = true;
+		break;
+	default:
+		rc = -EINVAL;
+		goto end;
+	}
+
 	CAM_DBG(CAM_ISP, "Res id: %d height:%d line_start %d line_stop %d",
 		reserve->res_id, reserve->in_port->height,
 		reserve->in_port->line_start, reserve->in_port->line_stop);
@@ -1884,6 +1904,7 @@
 	struct cam_ife_csid_reg_offset       *csid_reg;
 	struct cam_hw_soc_info               *soc_info;
 	struct cam_ife_csid_rdi_reg_offset   *rdi_reg;
+	struct timespec64 ts;
 	uint32_t  time_32, id;
 
 	time_stamp = (struct cam_csid_get_time_stamp_args  *)cmd_args;
@@ -1932,6 +1953,10 @@
 		CAM_IFE_CSID_QTIMER_MUL_FACTOR,
 		CAM_IFE_CSID_QTIMER_DIV_FACTOR);
 
+	get_monotonic_boottime64(&ts);
+	time_stamp->boot_timestamp = (uint64_t)((ts.tv_sec * 1000000000) +
+		ts.tv_nsec);
+
 	return 0;
 }
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
index ceeacbe..8911f99 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h
@@ -138,12 +138,13 @@
 /**
  * struct cam_csid_get_time_stamp_args-  time stamp capture arguments
  * @res_node :   resource to get the time stamp
- * @ time_stamp_val : captured time stamp
- *
+ * @time_stamp_val : captured time stamp
+ * @boot_timestamp : boot time stamp
  */
 struct cam_csid_get_time_stamp_args {
 	struct cam_isp_resource_node      *node_res;
 	uint64_t                           time_stamp_val;
+	uint64_t                           boot_timestamp;
 };
 
 /**
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 969b75a..3c37b83 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
@@ -106,6 +106,7 @@
 	struct cam_vfe_bus_irq_evt_payload          evt_payload[
 		CAM_VFE_BUS_VER2_PAYLOAD_MAX];
 	struct list_head                            free_payload_list;
+	spinlock_t                                  spin_lock;
 	struct mutex                                bus_mutex;
 	uint32_t                                    secure_mode;
 	uint32_t                                    num_sec_out;
@@ -214,16 +215,23 @@
 	struct cam_vfe_bus_ver2_common_data  *common_data,
 	struct cam_vfe_bus_irq_evt_payload  **evt_payload)
 {
+	int rc;
+
+	spin_lock(&common_data->spin_lock);
 	if (list_empty(&common_data->free_payload_list)) {
 		*evt_payload = NULL;
 		CAM_ERR_RATE_LIMIT(CAM_ISP, "No free payload");
-		return -ENODEV;
+		rc = -ENODEV;
+		goto done;
 	}
 
 	*evt_payload = list_first_entry(&common_data->free_payload_list,
 		struct cam_vfe_bus_irq_evt_payload, list);
 	list_del_init(&(*evt_payload)->list);
-	return 0;
+	rc = 0;
+done:
+	spin_unlock(&common_data->spin_lock);
+	return rc;
 }
 
 static enum cam_vfe_bus_comp_grp_id
@@ -254,6 +262,7 @@
 	struct cam_vfe_bus_ver2_common_data *common_data = NULL;
 	uint32_t  *ife_irq_regs = NULL;
 	uint32_t   status_reg0, status_reg1, status_reg2;
+	unsigned long flags;
 
 	if (!core_info) {
 		CAM_ERR(CAM_ISP, "Invalid param core_info NULL");
@@ -276,8 +285,12 @@
 	}
 
 	common_data = core_info;
+
+	spin_lock_irqsave(&common_data->spin_lock, flags);
 	list_add_tail(&(*evt_payload)->list,
 		&common_data->free_payload_list);
+	spin_unlock_irqrestore(&common_data->spin_lock, flags);
+
 	*evt_payload = NULL;
 
 	CAM_DBG(CAM_ISP, "Done");
@@ -863,34 +876,16 @@
 			rsrc_data->stride = rsrc_data->width;
 			break;
 		case CAM_FORMAT_PLAIN16_10:
+		case CAM_FORMAT_PLAIN16_12:
+		case CAM_FORMAT_PLAIN16_14:
+		case CAM_FORMAT_PLAIN16_16:
+		case CAM_FORMAT_PLAIN32_20:
 			rsrc_data->width = CAM_VFE_RDI_BUS_DEFAULT_WIDTH;
 			rsrc_data->height = 0;
 			rsrc_data->stride = CAM_VFE_RDI_BUS_DEFAULT_STRIDE;
 			rsrc_data->pack_fmt = 0x0;
 			rsrc_data->en_cfg = 0x3;
 			break;
-		case CAM_FORMAT_PLAIN16_12:
-			rsrc_data->en_cfg = 0x1;
-			rsrc_data->pack_fmt = 0x3;
-			rsrc_data->width = rsrc_data->width * 2;
-			rsrc_data->stride = rsrc_data->width;
-			break;
-		case CAM_FORMAT_PLAIN16_14:
-			rsrc_data->en_cfg = 0x1;
-			rsrc_data->pack_fmt = 0x4;
-			rsrc_data->width = rsrc_data->width * 2;
-			rsrc_data->stride = rsrc_data->width;
-			break;
-		case CAM_FORMAT_PLAIN16_16:
-			rsrc_data->en_cfg = 0x1;
-			rsrc_data->pack_fmt = 0x5;
-			rsrc_data->width = rsrc_data->width * 2;
-			rsrc_data->stride = rsrc_data->width;
-			break;
-		case CAM_FORMAT_PLAIN32_20:
-			rsrc_data->en_cfg = 0x1;
-			rsrc_data->pack_fmt = 0x9;
-			break;
 		case CAM_FORMAT_PLAIN64:
 			rsrc_data->en_cfg = 0x1;
 			rsrc_data->pack_fmt = 0xA;
@@ -2961,6 +2956,7 @@
 		}
 	}
 
+	spin_lock_init(&bus_priv->common_data.spin_lock);
 	INIT_LIST_HEAD(&bus_priv->common_data.free_payload_list);
 	for (i = 0; i < CAM_VFE_BUS_VER2_PAYLOAD_MAX; i++) {
 		INIT_LIST_HEAD(&bus_priv->common_data.evt_payload[i].list);
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
index 643b0afc..93e4249 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_mem_mgr.c
@@ -646,6 +646,10 @@
 			CAM_SMMU_REGION_IO);
 		if (rc)
 			goto map_fail;
+	} else {
+		rc = ion_handle_get_size(tbl.client, ion_hdl, &len);
+		if (rc)
+			return rc;
 	}
 
 	idx = cam_mem_get_slot();
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 aaba481..65052e1 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
@@ -230,7 +230,7 @@
 					traverse_data->in_q, curr_idx);
 				apply_data[tbl->pd].idx = curr_idx;
 
-				CAM_DBG(CAM_CRM, "req_id: %d with pd of %d",
+				CAM_DBG(CAM_CRM, "req_id: %lld with pd of %d",
 				apply_data[tbl->pd].req_id,
 				apply_data[tbl->pd].pd);
 				/*
@@ -248,6 +248,11 @@
 		}
 	} else {
 		/* This pd table is not ready to proceed with asked idx */
+		CAM_INFO(CAM_CRM,
+			"Skip Frame: req: %lld not ready pd: %d open_req count: %d",
+			CRM_GET_REQ_ID(traverse_data->in_q, curr_idx),
+			tbl->pd,
+			traverse_data->open_req_cnt);
 		SET_FAILURE_BIT(traverse_data->result, tbl->pd);
 		return -EAGAIN;
 	}
@@ -450,6 +455,9 @@
 				rc = dev->ops->apply_req(&apply_req);
 				if (rc < 0)
 					break;
+
+				if (pd == link->max_delay)
+					link->open_req_cnt--;
 			}
 		}
 	}
@@ -460,6 +468,7 @@
 		for (; i >= 0; i--) {
 			dev = &link->l_dev[i];
 			evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_ERR;
+			evt_data.dev_hdl = dev->dev_hdl;
 			evt_data.link_hdl =  link->link_hdl;
 			evt_data.req_id = apply_req.request_id;
 			evt_data.u.error = CRM_KMD_ERR_BUBBLE;
@@ -509,6 +518,7 @@
 	traverse_data.result = 0;
 	traverse_data.validate_only = validate_only;
 	traverse_data.self_link = self_link;
+	traverse_data.open_req_cnt = link->open_req_cnt;
 	/*
 	 *  Traverse through all pd tables, if result is success,
 	 *  apply the settings
@@ -1513,6 +1523,7 @@
 	slot->sync_mode = sched_req->sync_mode;
 	slot->skip_idx = 0;
 	slot->recover = sched_req->bubble_enable;
+	link->open_req_cnt++;
 	__cam_req_mgr_inc_idx(&in_q->wr_idx, 1, in_q->num_slots);
 	mutex_unlock(&link->req.lock);
 
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 e15b3b0..5ad23b7 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
@@ -134,6 +134,7 @@
  * @validate_only : Whether to validate only and/or update settings
  * @self_link     : To indicate whether the check is for the given link or the
  *                  other sync link
+ * @open_req_cnt  : Count of open requests yet to be serviced in the kernel.
  */
 struct cam_req_mgr_traverse {
 	int32_t                       idx;
@@ -143,6 +144,7 @@
 	struct cam_req_mgr_req_queue *in_q;
 	bool                          validate_only;
 	bool                          self_link;
+	int32_t                      open_req_cnt;
 };
 
 /**
@@ -301,6 +303,8 @@
  * @sync_link_sof_skip   : flag determines if a pkt is not available for a given
  *                         frame in a particular link skip corresponding
  *                         frame in sync link as well.
+ * @open_req_cnt         : Counter to keep track of open requests that are yet
+ *                         to be serviced in the kernel.
  *
  */
 struct cam_req_mgr_core_link {
@@ -324,6 +328,7 @@
 	int64_t                              sync_self_ref;
 	bool                                 frame_skip_flag;
 	bool                                 sync_link_sof_skip;
+	int32_t                              open_req_cnt;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
index 9f26635..2f74765 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
@@ -488,6 +488,7 @@
 				i2c_reg_settings->request_id = 0;
 				i2c_reg_settings->is_settings_valid = 1;
 				rc = cam_sensor_i2c_command_parser(
+					&a_ctrl->io_master_info,
 					i2c_reg_settings,
 					&cmd_desc[i], 1);
 				if (rc < 0) {
@@ -544,7 +545,9 @@
 		offset = (uint32_t *)&csl_packet->payload;
 		offset += csl_packet->cmd_buf_offset / sizeof(uint32_t);
 		cmd_desc = (struct cam_cmd_buf_desc *)(offset);
-		rc = cam_sensor_i2c_command_parser(i2c_reg_settings,
+		rc = cam_sensor_i2c_command_parser(
+			&a_ctrl->io_master_info,
+			i2c_reg_settings,
 			cmd_desc, 1);
 		if (rc < 0) {
 			CAM_ERR(CAM_ACTUATOR,
@@ -570,7 +573,9 @@
 		offset = (uint32_t *)&csl_packet->payload;
 		offset += csl_packet->cmd_buf_offset / sizeof(uint32_t);
 		cmd_desc = (struct cam_cmd_buf_desc *)(offset);
-		rc = cam_sensor_i2c_command_parser(i2c_reg_settings,
+		rc = cam_sensor_i2c_command_parser(
+			&a_ctrl->io_master_info,
+			i2c_reg_settings,
 			cmd_desc, 1);
 		if (rc < 0) {
 			CAM_ERR(CAM_ACTUATOR,
@@ -631,6 +636,12 @@
 		return -EINVAL;
 	}
 
+	if (cmd->handle_type != CAM_HANDLE_USER_POINTER) {
+		CAM_ERR(CAM_ACTUATOR, "Invalid handle type: %d",
+			cmd->handle_type);
+		return -EINVAL;
+	}
+
 	CAM_DBG(CAM_ACTUATOR, "Opcode to Actuator: %d", cmd->op_code);
 
 	mutex_lock(&(a_ctrl->actuator_mutex));
@@ -764,6 +775,7 @@
 		rc = cam_actuator_i2c_pkt_parse(a_ctrl, arg);
 		if (rc < 0) {
 			CAM_ERR(CAM_ACTUATOR, "Failed in actuator Parsing");
+			goto release_mutex;
 		}
 
 		if (a_ctrl->setting_apply_state ==
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index e978a40..dbbac08 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -438,6 +438,12 @@
 		return -EINVAL;
 	}
 
+	if (cmd->handle_type != CAM_HANDLE_USER_POINTER) {
+		CAM_ERR(CAM_CSIPHY, "Invalid handle type: %d",
+			cmd->handle_type);
+		return -EINVAL;
+	}
+
 	CAM_DBG(CAM_CSIPHY, "Opcode received: %d", cmd->op_code);
 	mutex_lock(&csiphy_dev->mutex);
 	switch (cmd->op_code) {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index b0fbead..30b9d96 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -707,11 +707,6 @@
 
 	ioctl_ctrl = (struct cam_control *)arg;
 
-	if (ioctl_ctrl->handle_type != CAM_HANDLE_USER_POINTER) {
-		CAM_ERR(CAM_EEPROM, "Invalid Handle Type");
-		return -EINVAL;
-	}
-
 	if (copy_from_user(&dev_config, (void __user *) ioctl_ctrl->handle,
 		sizeof(dev_config)))
 		return -EFAULT;
@@ -852,8 +847,14 @@
 	struct cam_eeprom_query_cap_t  eeprom_cap = {0};
 	struct cam_control            *cmd = (struct cam_control *)arg;
 
-	if (!e_ctrl) {
-		CAM_ERR(CAM_EEPROM, "e_ctrl is NULL");
+	if (!e_ctrl || !cmd) {
+		CAM_ERR(CAM_EEPROM, "Invalid Arguments");
+		return -EINVAL;
+	}
+
+	if (cmd->handle_type != CAM_HANDLE_USER_POINTER) {
+		CAM_ERR(CAM_EEPROM, "Invalid handle type: %d",
+			cmd->handle_type);
 		return -EINVAL;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
index 68c5eea..b8c32d4 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -69,6 +69,9 @@
 		cci_client->retries = 3;
 		cci_client->id_map = 0;
 		cci_client->i2c_freq_mode = i2c_info->i2c_freq_mode;
+	} else if (e_ctrl->io_master_info.master_type == I2C_MASTER) {
+		e_ctrl->io_master_info.client->addr = i2c_info->slave_addr;
+		CAM_DBG(CAM_EEPROM, "Slave addr: 0x%x", i2c_info->slave_addr);
 	}
 	return 0;
 }
@@ -188,6 +191,9 @@
 	e_ctrl->io_master_info.master_type = I2C_MASTER;
 	e_ctrl->io_master_info.client = client;
 	e_ctrl->eeprom_device_type = MSM_CAMERA_I2C_DEVICE;
+	e_ctrl->cal_data.mapdata = NULL;
+	e_ctrl->cal_data.map = NULL;
+	e_ctrl->userspace_probe = false;
 
 	rc = cam_eeprom_parse_dt(e_ctrl);
 	if (rc) {
@@ -205,10 +211,6 @@
 	if (rc)
 		goto free_soc;
 
-	e_ctrl->cal_data.mapdata = NULL;
-	e_ctrl->cal_data.map = NULL;
-	e_ctrl->userspace_probe = false;
-
 	if (soc_private->i2c_info.slave_addr != 0)
 		e_ctrl->io_master_info.client->addr =
 			soc_private->i2c_info.slave_addr;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c
index 6120e02..f9411fc 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.c
@@ -29,6 +29,12 @@
 		return -EINVAL;
 	}
 
+	if (cmd->handle_type != CAM_HANDLE_USER_POINTER) {
+		CAM_ERR(CAM_FLASH, "Invalid handle type: %d",
+			cmd->handle_type);
+		return -EINVAL;
+	}
+
 	mutex_lock(&(fctrl->flash_mutex));
 	switch (cmd->op_code) {
 	case CAM_ACQUIRE_DEV: {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
index fbdaee7..196df08 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
@@ -517,6 +517,7 @@
 				i2c_reg_settings->is_settings_valid = 1;
 				i2c_reg_settings->request_id = 0;
 				rc = cam_sensor_i2c_command_parser(
+					&o_ctrl->io_master_info,
 					i2c_reg_settings,
 					&cmd_desc[i], 1);
 				if (rc < 0) {
@@ -533,6 +534,7 @@
 				i2c_reg_settings->is_settings_valid = 1;
 				i2c_reg_settings->request_id = 0;
 				rc = cam_sensor_i2c_command_parser(
+					&o_ctrl->io_master_info,
 					i2c_reg_settings,
 					&cmd_desc[i], 1);
 				if (rc < 0) {
@@ -604,7 +606,8 @@
 		i2c_reg_settings = &(o_ctrl->i2c_mode_data);
 		i2c_reg_settings->is_settings_valid = 1;
 		i2c_reg_settings->request_id = 0;
-		rc = cam_sensor_i2c_command_parser(i2c_reg_settings,
+		rc = cam_sensor_i2c_command_parser(&o_ctrl->io_master_info,
+			i2c_reg_settings,
 			cmd_desc, 1);
 		if (rc < 0) {
 			CAM_ERR(CAM_OIS, "OIS pkt parsing failed: %d", rc);
@@ -669,8 +672,14 @@
 	struct cam_ois_query_cap_t     ois_cap = {0};
 	struct cam_control            *cmd = (struct cam_control *)arg;
 
-	if (!o_ctrl) {
-		CAM_ERR(CAM_OIS, "e_ctrl is NULL");
+	if (!o_ctrl || !arg) {
+		CAM_ERR(CAM_OIS, "Invalid arguments");
+		return -EINVAL;
+	}
+
+	if (cmd->handle_type != CAM_HANDLE_USER_POINTER) {
+		CAM_ERR(CAM_OIS, "Invalid handle type: %d",
+			cmd->handle_type);
 		return -EINVAL;
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index b3f3a35..d5bee96 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -230,7 +230,8 @@
 	offset += csl_packet->cmd_buf_offset / 4;
 	cmd_desc = (struct cam_cmd_buf_desc *)(offset);
 
-	rc = cam_sensor_i2c_command_parser(i2c_reg_settings, cmd_desc, 1);
+	rc = cam_sensor_i2c_command_parser(&s_ctrl->io_master_info,
+			i2c_reg_settings, cmd_desc, 1);
 	if (rc < 0) {
 		CAM_ERR(CAM_SENSOR, "Fail parsing I2C Pkt: %d", rc);
 		return rc;
@@ -562,12 +563,19 @@
 	struct cam_sensor_power_setting *pd = NULL;
 	struct cam_sensor_power_ctrl_t *power_info =
 		&s_ctrl->sensordata->power_info;
-
 	if (!s_ctrl || !arg) {
 		CAM_ERR(CAM_SENSOR, "s_ctrl is NULL");
 		return -EINVAL;
 	}
 
+	if (cmd->op_code != CAM_SENSOR_PROBE_CMD) {
+		if (cmd->handle_type != CAM_HANDLE_USER_POINTER) {
+			CAM_ERR(CAM_SENSOR, "Invalid handle type: %d",
+				cmd->handle_type);
+			return -EINVAL;
+		}
+	}
+
 	mutex_lock(&(s_ctrl->cam_sensor_mutex));
 	switch (cmd->op_code) {
 	case CAM_SENSOR_PROBE_CMD: {
@@ -607,6 +615,7 @@
 		} else {
 			CAM_ERR(CAM_SENSOR, "Invalid Command Type: %d",
 				 cmd->handle_type);
+			return -EINVAL;
 		}
 
 		/* Parse and fill vreg params for powerup settings */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/Makefile b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/Makefile
index 98ee3ae..9f0843d 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/Makefile
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/Makefile
@@ -4,5 +4,6 @@
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_cci
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr
 ccflags-y += -Idrivers/media/platform/msm/camera/cam_smmu/
+ccflags-y += -Idrivers/media/platform/msm/camera/cam_cpas/include
 
 obj-$(CONFIG_SPECTRA_CAMERA) +=  cam_sensor_util.o
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
index ac60dc8..a399963 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
@@ -242,6 +242,41 @@
 	return rc;
 }
 
+static int cam_sensor_handle_slave_info(
+	struct camera_io_master *io_master,
+	uint32_t *cmd_buf)
+{
+	int rc = 0;
+	struct cam_cmd_i2c_info *i2c_info = (struct cam_cmd_i2c_info *)cmd_buf;
+
+	if (io_master == NULL || cmd_buf == NULL) {
+		CAM_ERR(CAM_SENSOR, "Invalid args");
+		return -EINVAL;
+	}
+
+	switch (io_master->master_type) {
+	case CCI_MASTER:
+		io_master->cci_client->sid = (i2c_info->slave_addr >> 1);
+		io_master->cci_client->i2c_freq_mode = i2c_info->i2c_freq_mode;
+		break;
+
+	case I2C_MASTER:
+		io_master->client->addr = i2c_info->slave_addr;
+		break;
+
+	case SPI_MASTER:
+		break;
+
+	default:
+		CAM_ERR(CAM_SENSOR, "Invalid master type: %d",
+			io_master->master_type);
+		rc = -EINVAL;
+		break;
+	}
+
+	return rc;
+}
+
 /**
  * Name : cam_sensor_i2c_command_parser
  * Description : Parse CSL CCI packet and apply register settings
@@ -253,12 +288,16 @@
  * WAIT + n x RND_WR with num_cmd_buf = 1. Do not exepect RD/WR
  * with different cmd_type and op_code in one command buffer.
  */
-int cam_sensor_i2c_command_parser(struct i2c_settings_array *i2c_reg_settings,
-	struct cam_cmd_buf_desc   *cmd_desc, int32_t num_cmd_buffers)
+int cam_sensor_i2c_command_parser(
+	struct camera_io_master *io_master,
+	struct i2c_settings_array *i2c_reg_settings,
+	struct cam_cmd_buf_desc   *cmd_desc,
+	int32_t num_cmd_buffers)
 {
 	int16_t                   rc = 0, i = 0;
 	size_t                    len_of_buff = 0;
 	uint64_t                  generic_ptr;
+	uint16_t                  cmd_length_in_bytes = 0;
 
 	for (i = 0; i < num_cmd_buffers; i++) {
 		uint32_t                  *cmd_buf = NULL;
@@ -272,7 +311,6 @@
 		 * It is not expected the same settings to
 		 * be spread across multiple cmd buffers
 		 */
-
 		CAM_DBG(CAM_SENSOR, "Total cmd Buf in Bytes: %d",
 			cmd_desc[i].length);
 
@@ -373,6 +411,22 @@
 				}
 				break;
 			}
+			case CAMERA_SENSOR_CMD_TYPE_I2C_INFO: {
+				rc = cam_sensor_handle_slave_info(
+					io_master, cmd_buf);
+				if (rc) {
+					CAM_ERR(CAM_SENSOR,
+						"Handle slave info failed with rc: %d",
+						rc);
+					return rc;
+				}
+				cmd_length_in_bytes =
+					sizeof(struct cam_cmd_i2c_info);
+				cmd_buf +=
+					cmd_length_in_bytes / sizeof(uint32_t);
+				byte_cnt += cmd_length_in_bytes;
+				break;
+			}
 			default:
 				CAM_ERR(CAM_SENSOR, "Invalid Command Type:%d",
 					 cmm_hdr->cmd_type);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
index d2079b0..c9ccc5c 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -24,6 +24,7 @@
 #include <cam_mem_mgr.h>
 #include "cam_soc_util.h"
 #include "cam_debug_util.h"
+#include "cam_sensor_io.h"
 
 #define INVALID_VREG 100
 
@@ -34,7 +35,8 @@
 int msm_camera_pinctrl_init
 	(struct msm_pinctrl_info *sensor_pctrl, struct device *dev);
 
-int cam_sensor_i2c_command_parser(struct i2c_settings_array *i2c_reg_settings,
+int cam_sensor_i2c_command_parser(struct camera_io_master *io_master,
+	struct i2c_settings_array *i2c_reg_settings,
 	struct cam_cmd_buf_desc *cmd_desc, int32_t num_cmd_buffers);
 
 int32_t delete_request(struct i2c_settings_array *i2c_array);
diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
index 0d03df0..ecfc566 100644
--- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
@@ -145,6 +145,7 @@
 	struct mutex payload_list_lock;
 	struct list_head payload_list;
 	u32 non_fatal_fault;
+	u32 enable_iova_guard;
 };
 
 static const struct of_device_id msm_cam_smmu_dt_match[] = {
@@ -3048,6 +3049,15 @@
 				"Error: failed to set non fatal fault attribute");
 		}
 
+		if (!strcmp(cb->name, "icp")) {
+			iommu_cb_set.enable_iova_guard = 1;
+			if (iommu_domain_set_attr(cb->mapping->domain,
+				DOMAIN_ATTR_FORCE_IOVA_GUARD_PAGE,
+				&iommu_cb_set.enable_iova_guard) < 0) {
+				CAM_ERR(CAM_SMMU,
+					"Failed to set iova guard pagei attr");
+			}
+		}
 	} else {
 		CAM_ERR(CAM_SMMU, "Context bank does not have IO region");
 		rc = -ENODEV;
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
index d625a20..517b7df 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
@@ -123,6 +123,7 @@
 {
 	struct sync_table_row *row = NULL;
 	struct sync_callback_info *sync_cb, *temp;
+	bool found = false;
 
 	if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0)
 		return -EINVAL;
@@ -145,11 +146,12 @@
 			sync_cb->cb_data == userdata) {
 			list_del_init(&sync_cb->list);
 			kfree(sync_cb);
+			found = true;
 		}
 	}
 
 	spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
-	return 0;
+	return found ? 0 : -ENOENT;
 }
 
 int cam_sync_signal(int32_t sync_obj, uint32_t status)
diff --git a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
index 08c8575..1d74309 100644
--- a/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera_v2/common/cam_smmu_api.c
@@ -270,53 +270,6 @@
 	}
 }
 
-
-static int cam_smmu_query_vaddr_in_range(int handle,
-	unsigned long fault_addr, unsigned long *start_addr,
-	unsigned long *end_addr, int *fd)
-{
-	int idx, rc = -EINVAL;
-	struct cam_dma_buff_info *mapping;
-	unsigned long sa, ea;
-
-	if (!start_addr || !end_addr || !fd) {
-		pr_err("Invalid params\n");
-		return -EINVAL;
-	}
-
-	idx = GET_SMMU_TABLE_IDX(handle);
-	if (handle == HANDLE_INIT || idx < 0 || idx >= iommu_cb_set.cb_num) {
-		pr_err("Error: handle or index invalid. idx = %d hdl = %x\n",
-			idx, handle);
-		return -EINVAL;
-	}
-
-	mutex_lock(&iommu_cb_set.cb_info[idx].lock);
-	if (iommu_cb_set.cb_info[idx].handle != handle) {
-		pr_err("Error: hdl is not valid, table_hdl = %x, hdl = %x\n",
-				iommu_cb_set.cb_info[idx].handle, handle);
-		mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
-		return -EINVAL;
-	}
-
-	list_for_each_entry(mapping,
-		&iommu_cb_set.cb_info[idx].smmu_buf_list, list) {
-		sa = (unsigned long)mapping->paddr;
-		ea = (unsigned long)mapping->paddr + mapping->len;
-
-		if (sa <= fault_addr && fault_addr < ea) {
-			*start_addr = sa;
-			*end_addr = ea;
-			*fd = mapping->ion_fd;
-			rc = 0;
-			break;
-		}
-	}
-	mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
-	return rc;
-}
-EXPORT_SYMBOL(cam_smmu_query_vaddr_in_range);
-
 static void cam_smmu_check_vaddr_in_range(int idx, void *vaddr)
 {
 	struct cam_dma_buff_info *mapping;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 7a8e621..19b1aac 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -35,12 +35,13 @@
 #define VFE40_STATS_BURST_LEN_8916_VERSION 2
 #define VFE40_FETCH_BURST_LEN 3
 #define VFE40_UB_SIZE 1536 /* 1536 * 128 bits = 24KB */
+#define VFE40_STATS_SIZE 392
 #define VFE40_UB_SIZE_8952 2048 /* 2048 * 128 bits = 32KB */
 #define VFE40_UB_SIZE_8916 3072 /* 3072 * 128 bits = 48KB */
 #define VFE40_EQUAL_SLICE_UB 190 /* (UB_SIZE - STATS SIZE)/6 */
 #define VFE40_EQUAL_SLICE_UB_8916 236
 #define VFE40_TOTAL_WM_UB 1144 /* UB_SIZE - STATS SIZE */
-#define VFE40_TOTAL_WM_UB_8916 1656
+#define VFE40_TOTAL_WM_UB_8916 2680
 #define VFE40_WM_BASE(idx) (0x6C + 0x24 * idx)
 #define VFE40_RDI_BASE(idx) (0x2E8 + 0x4 * idx)
 #define VFE40_XBAR_BASE(idx) (0x58 + 0x4 * (idx / 2))
@@ -104,7 +105,11 @@
 
 static uint32_t msm_vfe40_get_ub_size(struct vfe_device *vfe_dev)
 {
-	if (vfe_dev->vfe_hw_version == VFE40_8916_VERSION) {
+	if (vfe_dev->vfe_hw_version == VFE40_8916_VERSION ||
+		vfe_dev->vfe_hw_version == VFE40_8939_VERSION ||
+		vfe_dev->vfe_hw_version == VFE40_8937_VERSION ||
+		vfe_dev->vfe_hw_version == VFE40_8953_VERSION ||
+		vfe_dev->vfe_hw_version == VFE40_8917_VERSION) {
 		vfe_dev->ub_info->wm_ub = VFE40_TOTAL_WM_UB_8916;
 		return VFE40_TOTAL_WM_UB_8916;
 	}
@@ -580,6 +585,11 @@
 
 	*irq_status0 &= vfe_dev->irq0_mask;
 	*irq_status1 &= vfe_dev->irq1_mask;
+	if (*irq_status0 &&
+		(*irq_status0 == msm_camera_io_r(vfe_dev->vfe_base + 0x38))) {
+		msm_camera_io_w(*irq_status0, vfe_dev->vfe_base + 0x30);
+		msm_camera_io_w_mb(1, vfe_dev->vfe_base + 0x24);
+	}
 
 	if (*irq_status1 & (1 << 0)) {
 		vfe_dev->error_info.camif_status =
@@ -2208,7 +2218,7 @@
 	.num_comp_mask = 3,
 	.num_rdi = 3,
 	.num_rdi_master = 3,
-	.min_wm_ub = 64,
+	.min_wm_ub = 96,
 	.scratch_buf_range = SZ_32M + SZ_4M,
 };
 
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 73a5ebc..0b84327 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -3154,7 +3154,7 @@
 		return -EINVAL;
 
 	msm_isp_get_timestamp(&timestamp, vfe_dev_ioctl);
-
+	mutex_lock(&vfe_dev_ioctl->buf_mgr->lock);
 	for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
 		if (stream_cfg_cmd->stream_handle[i] == 0)
 			continue;
@@ -3162,6 +3162,7 @@
 			HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i]));
 		if (!stream_info) {
 			pr_err("%s: stream_info is NULL", __func__);
+			mutex_unlock(&vfe_dev_ioctl->buf_mgr->lock);
 			return -EINVAL;
 		}
 		if (SRC_TO_INTF(stream_info->stream_src) < VFE_SRC_MAX)
@@ -3171,6 +3172,7 @@
 		else {
 			ISP_DBG("%s: invalid src info index\n", __func__);
 			rc = -EINVAL;
+			mutex_unlock(&vfe_dev_ioctl->buf_mgr->lock);
 			goto error;
 		}
 		spin_lock_irqsave(&stream_info->lock, flags);
@@ -3182,6 +3184,7 @@
 		}
 		if (rc) {
 			spin_unlock_irqrestore(&stream_info->lock, flags);
+			mutex_unlock(&vfe_dev_ioctl->buf_mgr->lock);
 			goto error;
 		}
 
@@ -3204,6 +3207,7 @@
 				HANDLE_TO_IDX(
 				stream_cfg_cmd->stream_handle[i]));
 			spin_unlock_irqrestore(&stream_info->lock, flags);
+			mutex_unlock(&vfe_dev_ioctl->buf_mgr->lock);
 			goto error;
 		}
 		for (k = 0; k < stream_info->num_isp; k++) {
@@ -3262,6 +3266,7 @@
 		spin_unlock_irqrestore(&stream_info->lock, flags);
 		streams[num_streams++] = stream_info;
 	}
+	mutex_unlock(&vfe_dev_ioctl->buf_mgr->lock);
 
 	for (i = 0; i < MAX_VFE; i++) {
 		vfe_dev = update_vfes[i];
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index 0d7a1e0..0634c0f 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -1105,6 +1105,7 @@
 	struct vfe_device *vfe_dev;
 
 	msm_isp_get_timestamp(&timestamp, vfe_dev_ioctl);
+	mutex_lock(&vfe_dev_ioctl->buf_mgr->lock);
 
 	num_stats_comp_mask =
 		vfe_dev_ioctl->hw_info->stats_hw_info->num_stats_comp_mask;
@@ -1125,6 +1126,7 @@
 		}
 		if (rc) {
 			spin_unlock_irqrestore(&stream_info->lock, flags);
+			mutex_unlock(&vfe_dev_ioctl->buf_mgr->lock);
 			goto error;
 		}
 		rc = msm_isp_init_stats_ping_pong_reg(
@@ -1132,6 +1134,7 @@
 		if (rc < 0) {
 			spin_unlock_irqrestore(&stream_info->lock, flags);
 			pr_err("%s: No buffer for stream%d\n", __func__, idx);
+			mutex_unlock(&vfe_dev_ioctl->buf_mgr->lock);
 			return rc;
 		}
 		init_completion(&stream_info->active_comp);
@@ -1166,6 +1169,7 @@
 				stats_data->num_active_stream);
 		streams[num_stream++] = stream_info;
 	}
+	mutex_unlock(&vfe_dev_ioctl->buf_mgr->lock);
 
 	for (k = 0; k < MAX_VFE; k++) {
 		if (!update_vfes[k] || num_active_streams[k])
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index d3a68b1..b589afa 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -896,9 +896,7 @@
 	case VIDIOC_MSM_ISP_CFG_STREAM:
 		mutex_lock(&vfe_dev->core_mutex);
 		MSM_ISP_DUAL_VFE_MUTEX_LOCK(vfe_dev);
-		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = msm_isp_cfg_axi_stream(vfe_dev, arg);
-		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
 		mutex_unlock(&vfe_dev->core_mutex);
 		break;
@@ -1015,9 +1013,7 @@
 	case VIDIOC_MSM_ISP_CFG_STATS_STREAM:
 		mutex_lock(&vfe_dev->core_mutex);
 		MSM_ISP_DUAL_VFE_MUTEX_LOCK(vfe_dev);
-		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = msm_isp_cfg_stats_stream(vfe_dev, arg);
-		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
 		mutex_unlock(&vfe_dev->core_mutex);
 		break;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_10_0_0_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_10_0_0_hwreg.h
new file mode 100644
index 0000000..87c759c
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/include/msm_csiphy_10_0_0_hwreg.h
@@ -0,0 +1,143 @@
+/* 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 MSM_CSIPHY_10_0_0_HWREG_H
+#define MSM_CSIPHY_10_0_0_HWREG_H
+
+#include <sensor/csiphy/msm_csiphy.h>
+
+#define LANE_MASK_AGGR_MODE     0x1F
+#define LANE_MASK_PHY_A         0x13
+#define LANE_MASK_PHY_B         0x2C
+#define mask_phy_enable_A       0x3
+#define mask_phy_enable_B       0xC
+#define mask_base_dir_A         0x1
+#define mask_base_dir_B         0x2
+#define mask_force_mode_A       0x3
+#define mask_force_mode_B       0xC
+#define mask_enable_clk_A       0x1
+#define mask_enable_clk_B       0x2
+#define mask_ctrl_1_A           0x5
+#define mask_ctrl_1_B           0xA
+#define mask_hs_freq_range      0x7F
+#define mask_osc_freq_2         0xFF
+#define mask_osc_freq_3         0xF00
+
+static struct csiphy_reg_parms_t csiphy_v10_0_0 = {
+	//ToDo: Fill these addresses from SWI
+	.mipi_csiphy_interrupt_status0_addr = 0x5B4,
+	.mipi_csiphy_interrupt_clear0_addr = 0x59C,
+	.mipi_csiphy_glbl_irq_cmd_addr = 0x588,
+	.mipi_csiphy_interrupt_clk_status0_addr = 0x5D8,
+	.mipi_csiphy_interrupt_clk_clear0_addr = 0x5D0,
+};
+
+static struct csiphy_reg_snps_parms_t csiphy_v10_0_0_snps = {
+	/*MIPI CSI PHY registers*/
+	{0x560, 0x9},    /* mipi_csiphy_sys_ctrl */
+	{0x5Ac, 0x9},    /* mipi_csiphy_sys_ctrl_1 */
+	{0x564, 0xF},    /* mipi_csiphy_ctrl_1 */
+	{0x568, 0x49},   /* mipi_csiphy_ctrl_2 */
+	{0x56C, 0x49},   /* mipi_csiphy_ctrl_3 */
+	{0x580, 0x7F},   /* mipi_csiphy_fifo_ctrl */
+	{0x570, 0x0},    /* mipi_csiphy_enable */
+	{0x578, 0x0},    /* mipi_csiphy_basedir */
+	{0x57C, 0x0},    /* mipi_csiphy_force_mode */
+	{0x574, 0x0},    /* mipi_csiphy_enable_clk */
+	{0x58C, 0xFF},   /* mipi_csiphy_irq_mask_ctrl_lane_0 */
+	{0x5C8, 0xFF},   /* mipi_csiphy_irq_mask_ctrl_lane_clk_0 */
+	{0x20, 0x0},     /* mipi_csiphy_rx_sys_7_00 */
+	{0x28, 0x43},    /* mipi_csiphy_rx_sys_9_00 */
+	{0x380, 0x0},    /* mipi_csiphy_rx_startup_ovr_0_00 */
+	{0x384, 0x0},    /* mipi_csiphy_rx_startup_ovr_1_00 */
+	{0x388, 0xCC},   /* mipi_csiphy_rx_startup_ovr_2_00 */
+	{0x38C, 0x1},    /* mipi_csiphy_rx_startup_ovr_3_00 */
+	{0x390, 0x1},    /* mipi_csiphy_rx_startup_ovr_4_00 */
+	{0x394, 0x1},    /* mipi_csiphy_rx_startup_ovr_5_00 */
+	{0x324, 0x0},    /* mipi_csiphy_rx_startup_obs_2_00 */
+	{0x6B0, 0x0},    /* mipi_csiphy_rx_cb_2_00 */
+	{0x4CC, 0x1},    /* mipi_csiphy_rx_dual_phy_0_00 */
+	{0xC0, 0x0},     /* mipi_csiphy_rx_clk_lane_3_00 */
+	{0xC4, 0xA},     /* mipi_csiphy_rx_clk_lane_4_00 */
+	{0xC8, 0x0},     /* mipi_csiphy_rx_clk_lane_6_00 */
+	{0x12c, 0x0},    /* mipi_csiphy_rx_lane_0_7_00 */
+	{0x220, 0x0},    /* mipi_csiphy_rx_lane_1_7_00 */
+	{0xCC, 0x0},     /* mipi_csiphy_rx_clk_lane_7_00 */
+};
+
+static struct snps_freq_value snps_v100_freq_values[] = {
+	{80,   0x0,  460 },  /*        80 - 97.125*/
+	{90,   0x10, 460 },  /*       80 - 107.625*/
+	{100,  0x20, 460 },  /*   83.125 - 118.125*/
+	{110,  0x30, 460 },  /*   92.625 - 128.625*/
+	{120,  0x1,  460 },  /*  102.125 - 139.125*/
+	{130,  0x11, 460 },  /*  111.625 - 149.625*/
+	{140,  0x21, 460 },  /*  121.125 - 160.125*/
+	{150,  0x31, 460 },  /*  130.625 - 170.625*/
+	{160,  0x2,  460 },  /*  140.125 - 181.125*/
+	{170,  0x12, 460 },  /*  149.625 - 191.625*/
+	{180,  0x22, 460 },  /*  159.125 - 202.125*/
+	{190,  0x32, 460 },  /*  168.625 - 212.625*/
+	{205,  0x3,  460 },  /*  182.875 - 228.375*/
+	{220,  0x13, 460 },  /*  197.125 - 244.125*/
+	{235,  0x23, 460 },  /*  211.375 - 259.875*/
+	{250,  0x33, 460 },  /*  225.625 - 275.625*/
+	{275,  0x4,  460 },  /*  249.375 - 301.875*/
+	{300,  0x14, 460 },  /*  273.125 - 328.125*/
+	{325,  0x25, 460 },  /*  296.875 - 354.375*/
+	{350,  0x35, 460 },  /*  320.625 - 380.625*/
+	{400,  0x5,  460 },  /*  368.125 - 433.125*/
+	{450,  0x16, 460 },  /*  415.625 - 485.625*/
+	{500,  0x26, 460 },  /*  463.125 - 538.125*/
+	{550,  0x37, 460 },  /*  510.625 - 590.625*/
+	{600,  0x7,  460 },  /*  558.125 - 643.125*/
+	{650,  0x18, 460 },  /*  605.625 - 695.625*/
+	{700,  0x28, 460 },  /*  653.125 - 748.125*/
+	{750,  0x39, 460 },  /*  700.625 - 800.625*/
+	{800,  0x9,  460 },  /*  748.125 - 853.125*/
+	{850,  0x19, 460 },  /*  795.625 - 905.625*/
+	{900,  0x29, 460 },  /*  843.125 - 958.125*/
+	{950,  0x3a, 460 },  /* 890.625 - 1010.625*/
+	{1000, 0xa,  460 },  /* 938.125 - 1063.125*/
+	{1050, 0x1a, 460 },  /* 985.625 - 1115.625*/
+	{1100, 0x2a, 460 },  /*1033.125 - 1168.125*/
+	{1150, 0x3b, 460 },  /*1080.625 - 1220.625*/
+	{1200, 0xb,  460 },  /*1128.125 - 1273.125*/
+	{1250, 0x1b, 460 },  /*1175.625 - 1325.625*/
+	{1300, 0x2b, 460 },  /*1223.125 - 1378.125*/
+	{1350, 0x3c, 460 },  /*1270.625 - 1430.625*/
+	{1400, 0xc,  460 },  /*1318.125 - 1483.125*/
+	{1450, 0x1c, 460},   /*1365.625 - 1535.625*/
+	{1500, 0x2c, 460 },  /*1413.125 - 1588.125*/
+	{1550, 0x3d, 285 },  /*1460.625 - 1640.625*/
+	{1600, 0xd,  295 },  /*1508.125 - 1693.125*/
+	{1650, 0x1d, 304 },  /*1555.625 - 1745.625*/
+	{1700, 0x2e, 313 },  /*1603.125 - 1798.125*/
+	{1750, 0x3e, 322 },  /*1650.625 - 1850.625*/
+	{1800, 0xe,  331 },  /*1698.125 - 1903.125*/
+	{1850, 0x1e, 341 },  /*1745.625 - 1955.625*/
+	{1900, 0x2f, 350 },  /*1793.125 - 2008.125*/
+	{1950, 0x3f, 359 },  /*1840.625 - 2060.625*/
+	{2000, 0xf,  368 },  /*1888.125 - 2113.125*/
+	{2050, 0x40, 377 },  /*1935.625 - 2165.625*/
+	{2100, 0x41, 387 },  /*1983.125 - 2218.125*/
+	{2150, 0x42, 396 },  /*2030.625 - 2270.625*/
+	{2200, 0x43, 405 },  /*2078.125 - 2323.125*/
+	{2250, 0x44, 414 },  /*2125.625 - 2375.625*/
+	{2300, 0x45, 423 },  /*2173.125 - 2428.125*/
+	{2350, 0x46, 432 },  /*2220.625 - 2480.625*/
+	{2400, 0x47, 442 },  /*    2268.125 - 2500*/
+	{2450, 0x48, 451 },  /*    2315.625 - 2500*/
+	{2500, 0x49, 460 },  /*    2363.125 - 2500*/
+};
+
+#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
index edf022e..58a4390 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
@@ -27,6 +27,8 @@
 #include "include/msm_csiphy_3_5_hwreg.h"
 #include "include/msm_csiphy_5_0_hwreg.h"
 #include "include/msm_csiphy_5_0_1_hwreg.h"
+#include "include/msm_csiphy_10_0_0_hwreg.h"
+
 #include "cam_hw_ops.h"
 
 #define DBG_CSIPHY 0
@@ -43,6 +45,7 @@
 #define CSIPHY_VERSION_V35                        0x35
 #define CSIPHY_VERSION_V50                        0x500
 #define CSIPHY_VERSION_V501                       0x501
+#define CSIPHY_VERSION_V1000                      0x1000
 #define MSM_CSIPHY_DRV_NAME                      "msm_csiphy"
 #define CLK_LANE_OFFSET                             1
 #define NUM_LANES_OFFSET                            4
@@ -52,6 +55,9 @@
 #define MAX_DPHY_DATA_LN                            4
 #define CLOCK_OFFSET                              0x700
 #define CSIPHY_SOF_DEBUG_COUNT                      2
+#define MBPS                                      1000000
+#define SNPS_INTERPHY_OFFSET                      0x800
+#define SET_THE_BIT(x)                            (0x1 << x)
 
 #undef CDBG
 #define CDBG(fmt, args...) pr_debug(fmt, ##args)
@@ -74,6 +80,42 @@
 	}
 }
 
+static void snps_irq_config(
+	struct csiphy_device *csiphy_dev, bool enable)
+{
+	uint16_t offset = 0x4;
+	uint16_t data;
+	void __iomem *csiphybase;
+
+	csiphybase = csiphy_dev->base;
+
+	if (enable)
+		data = csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_irq_mask_ctrl_lane_0.data;
+	else
+		data = 0;
+
+	msm_camera_io_w(data,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_irq_mask_ctrl_lane_0.addr);
+	msm_camera_io_w(data,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_irq_mask_ctrl_lane_0.addr + offset);
+	msm_camera_io_w(data,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_irq_mask_ctrl_lane_0.addr + 2 * offset);
+	msm_camera_io_w(data,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_irq_mask_ctrl_lane_0.addr + 3 * offset);
+
+	msm_camera_io_w(data,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_irq_mask_ctrl_lane_clk_0.addr);
+	msm_camera_io_w(data,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_irq_mask_ctrl_lane_clk_0.addr + offset);
+}
+
 static void msm_csiphy_cphy_irq_config(
 	struct csiphy_device *csiphy_dev,
 	struct msm_camera_csiphy_params *csiphy_params)
@@ -81,50 +123,459 @@
 	void __iomem *csiphybase;
 
 	csiphybase = csiphy_dev->base;
-	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl11.data,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl11.addr);
-	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl12.data,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl12.addr);
-	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl13.data,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl13.addr);
-	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl14.data,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl14.addr);
-	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl15.data,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl15.addr);
-	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl16.data,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl16.addr);
-	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl17.data,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl17.addr);
-	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl18.data,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl18.addr);
-	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl19.data,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl19.addr);
-	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl20.data,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl20.addr);
-	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl21.data,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl21.addr);
+	if (csiphy_dev->is_snps_phy) {
+		snps_irq_config(csiphy_dev, true);
+	} else {
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl11.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl11.addr);
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl12.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl12.addr);
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl13.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl13.addr);
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl14.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl14.addr);
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl15.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl15.addr);
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl16.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl16.addr);
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl17.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl17.addr);
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl18.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl18.addr);
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl19.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl19.addr);
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl20.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl20.addr);
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl21.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl21.addr);
+	}
+}
+
+static int msm_csiphy_snps_2_lane_config(
+	struct csiphy_device *csiphy_dev,
+	struct msm_camera_csiphy_params *csiphy_params,
+	enum snps_csiphy_mode mode, int num_lanes)
+
+{
+	uint32_t offset;
+	uint32_t value, i, diff, diff_i;
+	void __iomem *csiphybase;
+
+	csiphybase = csiphy_dev->base;
+
+	if (mode == TWO_LANE_PHY_A)
+		offset = 0x0;
+	else if (mode == TWO_LANE_PHY_B)
+		offset = SNPS_INTERPHY_OFFSET;
+	else
+		return -EINVAL;
+
+	diff = abs(snps_v100_freq_values[0].default_bit_rate -
+		((csiphy_params->data_rate / num_lanes) / MBPS));
+	/* ToDo: Can be optimized to a O(1) search */
+	for (i = 1; i < sizeof(snps_v100_freq_values)/
+		sizeof(snps_v100_freq_values[0]); i++) {
+		diff_i = abs(snps_v100_freq_values[i].default_bit_rate -
+			((csiphy_params->data_rate / num_lanes) / MBPS));
+		if (diff_i > diff) {
+			i--;
+			break;
+		}
+		diff = diff_i;
+	}
+
+	if (i == (sizeof(snps_v100_freq_values)/
+		sizeof(snps_v100_freq_values[0]))) {
+		if (((csiphy_params->data_rate / num_lanes) / MBPS) >
+			snps_v100_freq_values[--i].default_bit_rate) {
+			pr_err("unsupported data rate\n");
+			return -EINVAL;
+		}
+	}
+
+	if (mode == TWO_LANE_PHY_A) {
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_sys_ctrl.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_sys_ctrl.addr + offset);
+
+		msm_camera_io_w((snps_v100_freq_values[i].hs_freq &
+			mask_hs_freq_range),
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_ctrl_3.addr + offset);
+	} else {
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_sys_ctrl_1.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_sys_ctrl_1.addr);
+
+		msm_camera_io_w((snps_v100_freq_values[i].hs_freq &
+			mask_hs_freq_range),
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_ctrl_2.addr);
+	}
+
+	value = msm_camera_io_r(csiphybase +
+		csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_rx_sys_7_00.addr + offset);
+	value |= SET_THE_BIT(5);
+	msm_camera_io_w(value,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_rx_sys_7_00.addr + offset);
+
+	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_rx_sys_9_00.data,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_rx_sys_9_00.addr + offset);
+
+	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_rx_startup_ovr_4_00.data,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_rx_startup_ovr_4_00.addr + offset);
+
+	msm_camera_io_w((snps_v100_freq_values[i].osc_freq &
+		mask_osc_freq_2),
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_rx_startup_ovr_2_00.addr + offset);
+
+	msm_camera_io_w((snps_v100_freq_values[i].osc_freq &
+		mask_osc_freq_3) >> 8,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_rx_startup_ovr_3_00.addr + offset);
+
+	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_rx_startup_ovr_5_00.data,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_rx_startup_ovr_5_00.addr + offset);
+
+	value = msm_camera_io_r(csiphybase +
+		csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_rx_cb_2_00.addr + offset);
+	value |= SET_THE_BIT(6);
+	msm_camera_io_w(value,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_rx_cb_2_00.addr + offset);
+
+	return 0;
+}
+
+static int msm_csiphy_snps_lane_config(
+	struct csiphy_device *csiphy_dev,
+	struct msm_camera_csiphy_params *csiphy_params)
+{
+	int ret;
+	uint16_t lane_mask = 0;
+	void __iomem *csiphybase;
+	enum snps_csiphy_mode mode = INVALID_MODE;
+	uint32_t value, num_tries, num_lanes, offset;
+
+	csiphybase = csiphy_dev->base;
+	/* lane mask usage
+	 * BIT	  LANE
+	 * 0(LSB)  PHY A data 0
+	 * 1       PHY A data 1
+	 * 2       PHY B data 0
+	 * 3       PHY B data 1
+	 * 4       PHY A clk (clk 0)
+	 * 5       PHY B clk (clk 1)
+	 */
+
+	lane_mask = csiphy_params->lane_mask & 0x3f;
+	CDBG("%s:%d lane_maks: %d, cur_snps_state = %d\n",
+		__func__, __LINE__, lane_mask, csiphy_dev->snps_state);
+
+	if (lane_mask == LANE_MASK_AGGR_MODE) { /* Aggregate mdoe */
+		/* 4 lane config */
+		mode = AGGREGATE_MODE;
+		num_lanes = 4;
+		if (csiphy_dev->snps_state != NOT_CONFIGURED) {
+			pr_err("%s: invalid request\n", __func__);
+			return -EINVAL;
+		}
+		csiphy_dev->snps_state = CONFIGURED_AGGREGATE_MODE;
+	} else if (lane_mask == LANE_MASK_PHY_A) { /* PHY A */
+		/* 2 lane config */
+		num_lanes = 2;
+		if (csiphy_dev->snps_state != NOT_CONFIGURED) {
+			mode = TWO_LANE_PHY_A;
+			csiphy_dev->snps_state = CONFIGURED_TWO_LANE_PHY_A;
+		} else if (csiphy_dev->snps_state ==
+			CONFIGURED_TWO_LANE_PHY_B) {
+			/* 2 lane + 2 lane config */
+			mode = TWO_LANE_PHY_A;
+			csiphy_dev->snps_state = CONFIGURED_COMBO_MODE;
+		} else {
+			pr_err("%s: invalid request\n", __func__);
+			return -EINVAL;
+		}
+	} else if (lane_mask == LANE_MASK_PHY_B) { /* PHY B */
+		/* 2 lane config */
+		num_lanes = 2;
+		if (csiphy_dev->snps_state != NOT_CONFIGURED) {
+			mode = TWO_LANE_PHY_B;
+			csiphy_dev->snps_state = CONFIGURED_TWO_LANE_PHY_B;
+		} else if (csiphy_dev->snps_state ==
+			CONFIGURED_TWO_LANE_PHY_A) {
+			/* 2 lane + 2 lane config */
+			mode = TWO_LANE_PHY_B;
+			csiphy_dev->snps_state = CONFIGURED_COMBO_MODE;
+		} else {
+			pr_err("%s: invalid request\n", __func__);
+			return -EINVAL;
+		}
+	} else { /* None of available configurations */
+		pr_err("%s: invalid configuration requested\n", __func__);
+		return -EINVAL;
+	}
+
+	if (mode == AGGREGATE_MODE || mode == TWO_LANE_PHY_A) {
+		ret = msm_csiphy_snps_2_lane_config(csiphy_dev,
+			csiphy_params, TWO_LANE_PHY_A, num_lanes);
+		if (ret < 0) {
+			pr_err("%s:%d: Error in setting lane configuration\n",
+				__func__, __LINE__);
+			return ret;
+		}
+	}
+
+	if (mode == AGGREGATE_MODE || mode == TWO_LANE_PHY_B) {
+		ret = msm_csiphy_snps_2_lane_config(csiphy_dev,
+			csiphy_params, TWO_LANE_PHY_B, num_lanes);
+		if (ret < 0) {
+			pr_err("%s:%d: Error in setting lane configuration\n",
+				__func__, __LINE__);
+			return ret;
+		}
+	}
+
+	snps_irq_config(csiphy_dev, csiphy_params);
+
+	value = 0x0;
+	if (mode == AGGREGATE_MODE || mode == TWO_LANE_PHY_A)
+		value |= mask_force_mode_A;
+	if (mode == AGGREGATE_MODE || mode == TWO_LANE_PHY_B)
+		value |= mask_force_mode_B;
+	msm_camera_io_w(value,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_force_mode.addr);
+
+	if (mode == AGGREGATE_MODE) {
+		/* Programming PHY A as master and PHY B as slave  */
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_dual_phy_0_00.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_dual_phy_0_00.addr);
+
+		msm_camera_io_w(!(csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_dual_phy_0_00.data),
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_dual_phy_0_00.addr +
+			SNPS_INTERPHY_OFFSET);
+
+		value = msm_camera_io_r(csiphybase +
+			csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_lane_0_7_00.addr);
+		value |= SET_THE_BIT(5);
+		msm_camera_io_w(value,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_lane_0_7_00.addr);
+
+		value = msm_camera_io_r(csiphybase +
+			csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_lane_0_7_00.addr +
+			SNPS_INTERPHY_OFFSET);
+		value |= SET_THE_BIT(5);
+		msm_camera_io_w(value,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_lane_0_7_00.addr +
+			SNPS_INTERPHY_OFFSET);
+
+		value = msm_camera_io_r(csiphybase +
+			csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_lane_1_7_00.addr);
+		value |= SET_THE_BIT(5);
+		msm_camera_io_w(value,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_lane_1_7_00.addr);
+
+		value = msm_camera_io_r(csiphybase +
+			csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_lane_1_7_00.addr +
+			SNPS_INTERPHY_OFFSET);
+		value |= SET_THE_BIT(5);
+		msm_camera_io_w(value,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_lane_1_7_00.addr +
+			SNPS_INTERPHY_OFFSET);
+
+		value = csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_clk_lane_7_00.data;
+		msm_camera_io_w(value,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_clk_lane_7_00.addr);
+		value |= SET_THE_BIT(3);
+		msm_camera_io_w(value,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_clk_lane_7_00.addr +
+			SNPS_INTERPHY_OFFSET);
+
+		value = msm_camera_io_r(csiphybase +
+			csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_startup_ovr_0_00.addr +
+			SNPS_INTERPHY_OFFSET);
+		value |= SET_THE_BIT(0);
+		value |= SET_THE_BIT(1);
+		msm_camera_io_w(value,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_startup_ovr_0_00.addr +
+			SNPS_INTERPHY_OFFSET);
+
+		value = msm_camera_io_r(csiphybase +
+			csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_startup_ovr_1_00.addr +
+			SNPS_INTERPHY_OFFSET);
+		value &= ~(SET_THE_BIT(0));
+		value |= SET_THE_BIT(1);
+		msm_camera_io_w(value,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_startup_ovr_1_00.addr +
+			SNPS_INTERPHY_OFFSET);
+
+		value = msm_camera_io_r(csiphybase +
+			csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_clk_lane_6_00.addr);
+		value |= SET_THE_BIT(2);
+		msm_camera_io_w(value,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_clk_lane_6_00.addr);
+
+		value = msm_camera_io_r(csiphybase +
+			csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_clk_lane_6_00.addr +
+			SNPS_INTERPHY_OFFSET);
+		value |= SET_THE_BIT(3);
+		value |= SET_THE_BIT(7);
+		value &= ~(SET_THE_BIT(2));
+		msm_camera_io_w(value,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_clk_lane_6_00.addr +
+			SNPS_INTERPHY_OFFSET);
+
+		value = msm_camera_io_r(csiphybase +
+			csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_clk_lane_3_00.addr +
+			SNPS_INTERPHY_OFFSET);
+		value |= SET_THE_BIT(7);
+		msm_camera_io_w(value,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_clk_lane_3_00.addr +
+			SNPS_INTERPHY_OFFSET);
+
+		msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_clk_lane_4_00.data,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_clk_lane_4_00.addr +
+			SNPS_INTERPHY_OFFSET);
+
+		value = csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_fifo_ctrl.data;
+		value &= ~(SET_THE_BIT(0));
+		msm_camera_io_w(value,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_fifo_ctrl.addr);
+		value |= SET_THE_BIT(0);
+		msm_camera_io_w(value,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_fifo_ctrl.addr);
+	}
+
+	value = 0x0;
+	if (mode == AGGREGATE_MODE || mode == TWO_LANE_PHY_A)
+		value |= mask_phy_enable_A;
+	if (mode == AGGREGATE_MODE || mode == TWO_LANE_PHY_B)
+		value |= mask_phy_enable_B;
+	msm_camera_io_w(value,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_enable.addr);
+
+	value = 0x0;
+	if (mode == AGGREGATE_MODE || mode == TWO_LANE_PHY_A)
+		value |= mask_base_dir_A;
+	if (mode == AGGREGATE_MODE || mode == TWO_LANE_PHY_B)
+		value |= mask_base_dir_B;
+	msm_camera_io_w(value,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_basedir.addr);
+
+	value = 0x0;
+	if (mode == AGGREGATE_MODE || mode == TWO_LANE_PHY_A)
+		value |= mask_enable_clk_A;
+	if (mode == AGGREGATE_MODE || mode == TWO_LANE_PHY_B)
+		value |= mask_enable_clk_B;
+	msm_camera_io_w(value,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_enable_clk.addr);
+
+	value = 0x0;
+	if (mode == AGGREGATE_MODE || mode == TWO_LANE_PHY_A)
+		value |= mask_ctrl_1_A;
+	if (mode == AGGREGATE_MODE || mode == TWO_LANE_PHY_B)
+		value |= mask_ctrl_1_B;
+	msm_camera_io_w(value,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_ctrl_1.addr);
+
+	if (mode == AGGREGATE_MODE || mode == TWO_LANE_PHY_A)
+		offset = 0x0;
+	else
+		offset = SNPS_INTERPHY_OFFSET;
+
+	value = 0x0;
+	num_tries = 0;
+
+	do {
+		num_tries++;
+		value = msm_camera_io_r(csiphybase +
+			csiphy_dev->ctrl_reg->csiphy_snps_reg.
+			mipi_csiphy_rx_startup_obs_2_00.addr + offset);
+		if ((value | SET_THE_BIT(4)) == value)
+			break;
+		usleep_range(100, 150);
+	} while (num_tries < 6);
+
+	if ((value | SET_THE_BIT(4)) != value) {
+		pr_err("%s: SNPS phy config failed\n", __func__);
+		return -EINVAL;
+	}
+
+	msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_force_mode.data,
+		csiphybase + csiphy_dev->ctrl_reg->csiphy_snps_reg.
+		mipi_csiphy_force_mode.addr);
+
+	return 0;
 }
 
 static int msm_csiphy_3phase_lane_config(
@@ -782,14 +1233,26 @@
 		ratio = csiphy_dev->csiphy_max_clk/clk_rate;
 		csiphy_params->settle_cnt = csiphy_params->settle_cnt/ratio;
 	}
-	CDBG("%s csiphy_params, mask = 0x%x cnt = %d\n",
+	CDBG("%s csiphy_params, mask = 0x%x cnt = %d, data rate = %lu\n",
 		__func__,
 		csiphy_params->lane_mask,
-		csiphy_params->lane_cnt);
+		csiphy_params->lane_cnt, csiphy_params->data_rate);
 	CDBG("%s csiphy_params, settle cnt = 0x%x csid %d\n",
 		__func__, csiphy_params->settle_cnt,
 		csiphy_params->csid_core);
 
+	if (csiphy_dev->is_snps_phy) {
+		rc = msm_csiphy_snps_lane_config(csiphy_dev,
+					csiphy_params);
+		if (rc < 0) {
+			pr_err("%s:%d: Error in setting lane configuration\n",
+				__func__, __LINE__);
+		}
+		csiphy_dev->num_irq_registers = 4;
+		csiphy_dev->num_clk_irq_registers = 2;
+		return rc;
+	}
+
 	if (csiphy_dev->hw_version >= CSIPHY_VERSION_V30 &&
 		csiphy_dev->clk_mux_base != NULL &&
 		csiphy_dev->hw_version < CSIPHY_VERSION_V50) {
@@ -943,39 +1406,43 @@
 	void __iomem *csiphybase;
 
 	csiphybase = csiphy_dev->base;
-	msm_camera_io_w(0,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl11.addr);
-	msm_camera_io_w(0,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl12.addr);
-	msm_camera_io_w(0,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl13.addr);
-	msm_camera_io_w(0,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl14.addr);
-	msm_camera_io_w(0,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl15.addr);
-	msm_camera_io_w(0,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl16.addr);
-	msm_camera_io_w(0,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl17.addr);
-	msm_camera_io_w(0,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl18.addr);
-	msm_camera_io_w(0,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl19.addr);
-	msm_camera_io_w(0,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl20.addr);
-	msm_camera_io_w(0,
-		csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
-		mipi_csiphy_3ph_cmn_ctrl21.addr);
+	if (csiphy_dev->is_snps_phy) {
+		snps_irq_config(csiphy_dev, false);
+	} else {
+		msm_camera_io_w(0,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl11.addr);
+		msm_camera_io_w(0,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl12.addr);
+		msm_camera_io_w(0,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl13.addr);
+		msm_camera_io_w(0,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl14.addr);
+		msm_camera_io_w(0,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl15.addr);
+		msm_camera_io_w(0,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl16.addr);
+		msm_camera_io_w(0,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl17.addr);
+		msm_camera_io_w(0,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl18.addr);
+		msm_camera_io_w(0,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl19.addr);
+		msm_camera_io_w(0,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl20.addr);
+		msm_camera_io_w(0,
+			csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg.
+			mipi_csiphy_3ph_cmn_ctrl21.addr);
+	}
 }
 
 static irqreturn_t msm_csiphy_irq(int irq_num, void *data)
@@ -1010,12 +1477,33 @@
 			csiphy_dev->ctrl_reg->csiphy_reg.
 			mipi_csiphy_interrupt_clear0_addr + 0x4*i);
 	}
+
+	if (csiphy_dev->is_snps_phy) {
+		for (i = 0; i < csiphy_dev->num_clk_irq_registers; i++) {
+			irq = msm_camera_io_r(
+				csiphy_dev->base +
+				csiphy_dev->ctrl_reg->csiphy_reg.
+				mipi_csiphy_interrupt_clk_status0_addr + 0x4*i);
+			msm_camera_io_w(irq,
+				csiphy_dev->base +
+				csiphy_dev->ctrl_reg->csiphy_reg.
+				mipi_csiphy_interrupt_clk_clear0_addr + 0x4*i);
+			pr_err_ratelimited(
+				"%s CSIPHY%d_IRQ_CLK_STATUS_ADDR%d = 0x%x\n",
+				__func__, csiphy_dev->pdev->id, i, irq);
+			msm_camera_io_w(0x0,
+				csiphy_dev->base +
+				csiphy_dev->ctrl_reg->csiphy_reg.
+				mipi_csiphy_interrupt_clk_clear0_addr + 0x4*i);
+		}
+	}
 	msm_camera_io_w(0x1, csiphy_dev->base +
 		csiphy_dev->ctrl_reg->
 		csiphy_reg.mipi_csiphy_glbl_irq_cmd_addr);
 	msm_camera_io_w(0x0, csiphy_dev->base +
 		csiphy_dev->ctrl_reg->
 		csiphy_reg.mipi_csiphy_glbl_irq_cmd_addr);
+
 	return IRQ_HANDLED;
 }
 
@@ -1039,6 +1527,23 @@
 		mipi_csiphy_3ph_cmn_ctrl0.addr);
 }
 
+static void msm_csiphy_snps_reset(struct csiphy_device *csiphy_dev)
+{
+	//Need to toggle this register to enable IRQ
+	msm_camera_io_w(0x1, csiphy_dev->base +
+			csiphy_dev->ctrl_reg->
+			csiphy_reg.mipi_csiphy_glbl_irq_cmd_addr);
+	usleep_range(5000, 8000);
+	msm_camera_io_w(0x0, csiphy_dev->base +
+			csiphy_dev->ctrl_reg->
+			csiphy_reg.mipi_csiphy_glbl_irq_cmd_addr);
+}
+
+static void msm_csiphy_snps_release(struct csiphy_device *csiphy_dev)
+{
+	CDBG("Releasing SNPS phy\n");
+}
+
 #if DBG_CSIPHY
 static int msm_csiphy_init(struct csiphy_device *csiphy_dev)
 {
@@ -1112,7 +1617,9 @@
 	if (rc < 0)
 		pr_err("%s: irq enable failed\n", __func__);
 
-	if (csiphy_dev->csiphy_3phase == CSI_3PHASE_HW)
+	if (csiphy_dev->is_snps_phy)
+		msm_csiphy_snps_reset(csiphy_dev);
+	else if (csiphy_dev->csiphy_3phase == CSI_3PHASE_HW)
 		msm_csiphy_3ph_reset(csiphy_dev);
 	else
 		msm_csiphy_reset(csiphy_dev);
@@ -1130,6 +1637,7 @@
 	CDBG("%s:%d called csiphy_dev->hw_version 0x%x\n", __func__, __LINE__,
 		csiphy_dev->hw_version);
 	csiphy_dev->csiphy_state = CSIPHY_POWER_UP;
+	csiphy_dev->snps_state = NOT_CONFIGURED;
 	return 0;
 
 csiphy_enable_clk_fail:
@@ -1214,7 +1722,9 @@
 	}
 	CDBG("%s:%d clk enable success\n", __func__, __LINE__);
 
-	if (csiphy_dev->csiphy_3phase == CSI_3PHASE_HW)
+	if (csiphy_dev->is_snps_phy)
+		msm_csiphy_snps_reset(csiphy_dev);
+	else if (csiphy_dev->csiphy_3phase == CSI_3PHASE_HW)
 		msm_csiphy_3ph_reset(csiphy_dev);
 	else
 		msm_csiphy_reset(csiphy_dev);
@@ -1233,6 +1743,7 @@
 	CDBG("%s:%d called csiphy_dev->hw_version 0x%x\n", __func__, __LINE__,
 		csiphy_dev->hw_version);
 	csiphy_dev->csiphy_state = CSIPHY_POWER_UP;
+	csiphy_dev->snps_state = NOT_CONFIGURED;
 	return 0;
 
 csiphy_enable_clk_fail:
@@ -1322,28 +1833,41 @@
 
 		csiphy_dev->lane_mask[csiphy_dev->pdev->id] &=
 			~(csi_lane_mask);
-		i = 0;
-		while (csi_lane_mask) {
-			if (csi_lane_mask & 0x1) {
-				msm_camera_io_w(0x0, csiphy_dev->base +
-					csiphy_dev->ctrl_reg->csiphy_reg.
-					mipi_csiphy_lnn_cfg2_addr + 0x40*i);
-				msm_camera_io_w(0x0, csiphy_dev->base +
-					csiphy_dev->ctrl_reg->csiphy_reg.
-					mipi_csiphy_lnn_misc1_addr + 0x40*i);
-				msm_camera_io_w(0x0, csiphy_dev->base +
-					csiphy_dev->ctrl_reg->csiphy_reg.
-					mipi_csiphy_lnn_test_imp + 0x40*i);
+		if (csiphy_dev->is_snps_phy) {
+			msm_csiphy_snps_release(csiphy_dev);
+		} else {
+			i = 0;
+			while (csi_lane_mask) {
+				if (csi_lane_mask & 0x1) {
+					msm_camera_io_w(0x0,
+						csiphy_dev->base +
+						csiphy_dev->ctrl_reg->
+						csiphy_reg.
+						mipi_csiphy_lnn_cfg2_addr +
+						0x40*i);
+					msm_camera_io_w(0x0,
+						csiphy_dev->base +
+						csiphy_dev->ctrl_reg->
+						csiphy_reg.
+						mipi_csiphy_lnn_misc1_addr +
+						0x40*i);
+					msm_camera_io_w(0x0,
+						csiphy_dev->base +
+						csiphy_dev->ctrl_reg->
+						csiphy_reg.
+						mipi_csiphy_lnn_test_imp +
+						0x40*i);
+				}
+				csi_lane_mask >>= 1;
+				i++;
 			}
-			csi_lane_mask >>= 1;
-			i++;
+			msm_camera_io_w(0x0, csiphy_dev->base +
+				csiphy_dev->ctrl_reg->csiphy_reg.
+				mipi_csiphy_lnck_cfg2_addr);
+			msm_camera_io_w(0x0, csiphy_dev->base +
+				csiphy_dev->ctrl_reg->csiphy_reg.
+				mipi_csiphy_glbl_pwr_cfg_addr);
 		}
-		msm_camera_io_w(0x0, csiphy_dev->base +
-			csiphy_dev->ctrl_reg->csiphy_reg.
-			mipi_csiphy_lnck_cfg2_addr);
-		msm_camera_io_w(0x0, csiphy_dev->base +
-			csiphy_dev->ctrl_reg->csiphy_reg.
-			mipi_csiphy_glbl_pwr_cfg_addr);
 	}
 
 	rc = msm_camera_enable_irq(csiphy_dev->irq, false);
@@ -1368,6 +1892,7 @@
 		NULL, 0, &csiphy_dev->csiphy_reg_ptr[0], 0);
 
 	csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN;
+	csiphy_dev->snps_state = NOT_CONFIGURED;
 
 	if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSIPHY,
 		 CAM_AHB_SUSPEND_VOTE) < 0)
@@ -1442,28 +1967,41 @@
 
 		csiphy_dev->lane_mask[csiphy_dev->pdev->id] &=
 			~(csi_lane_mask);
-		i = 0;
-		while (csi_lane_mask) {
-			if (csi_lane_mask & 0x1) {
-				msm_camera_io_w(0x0, csiphy_dev->base +
-					csiphy_dev->ctrl_reg->csiphy_reg.
-					mipi_csiphy_lnn_cfg2_addr + 0x40*i);
-				msm_camera_io_w(0x0, csiphy_dev->base +
-					csiphy_dev->ctrl_reg->csiphy_reg.
-					mipi_csiphy_lnn_misc1_addr + 0x40*i);
-				msm_camera_io_w(0x0, csiphy_dev->base +
-					csiphy_dev->ctrl_reg->csiphy_reg.
-					mipi_csiphy_lnn_test_imp + 0x40*i);
+		if (csiphy_dev->is_snps_phy) {
+			msm_csiphy_snps_release(csiphy_dev);
+		} else {
+			i = 0;
+			while (csi_lane_mask) {
+				if (csi_lane_mask & 0x1) {
+					msm_camera_io_w(0x0,
+						csiphy_dev->base +
+						csiphy_dev->ctrl_reg->
+						csiphy_reg.
+						mipi_csiphy_lnn_cfg2_addr +
+						0x40*i);
+					msm_camera_io_w(0x0,
+						csiphy_dev->base +
+						csiphy_dev->ctrl_reg->
+						csiphy_reg.
+						mipi_csiphy_lnn_misc1_addr +
+						0x40*i);
+					msm_camera_io_w(0x0,
+						csiphy_dev->base +
+						csiphy_dev->ctrl_reg->
+						csiphy_reg.
+						mipi_csiphy_lnn_test_imp +
+						0x40*i);
+				}
+				csi_lane_mask >>= 1;
+				i++;
 			}
-			csi_lane_mask >>= 1;
-			i++;
+			msm_camera_io_w(0x0, csiphy_dev->base +
+				csiphy_dev->ctrl_reg->csiphy_reg.
+				mipi_csiphy_lnck_cfg2_addr);
+			msm_camera_io_w(0x0, csiphy_dev->base +
+				csiphy_dev->ctrl_reg->csiphy_reg.
+				mipi_csiphy_glbl_pwr_cfg_addr);
 		}
-		msm_camera_io_w(0x0, csiphy_dev->base +
-			csiphy_dev->ctrl_reg->csiphy_reg.
-			mipi_csiphy_lnck_cfg2_addr);
-		msm_camera_io_w(0x0, csiphy_dev->base +
-			csiphy_dev->ctrl_reg->csiphy_reg.
-			mipi_csiphy_glbl_pwr_cfg_addr);
 	}
 	if (csiphy_dev->csiphy_sof_debug == SOF_DEBUG_ENABLE)
 		rc = msm_camera_enable_irq(csiphy_dev->irq, false);
@@ -1486,6 +2024,7 @@
 		NULL, 0, &csiphy_dev->csiphy_reg_ptr[0], 0);
 
 	csiphy_dev->csiphy_state = CSIPHY_POWER_DOWN;
+	csiphy_dev->snps_state = NOT_CONFIGURED;
 
 	if (cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSIPHY,
 		 CAM_AHB_SUSPEND_VOTE) < 0)
@@ -1803,6 +2342,12 @@
 		new_csiphy_dev->csiphy_3phase = CSI_3PHASE_HW;
 		new_csiphy_dev->ctrl_reg->csiphy_combo_mode_settings =
 			csiphy_combo_mode_v5_0_1;
+	} else if (of_device_is_compatible(new_csiphy_dev->pdev->dev.of_node,
+		"qcom,csiphy-v10.00")) {
+		new_csiphy_dev->ctrl_reg->csiphy_snps_reg = csiphy_v10_0_0_snps;
+		new_csiphy_dev->ctrl_reg->csiphy_reg = csiphy_v10_0_0;
+		new_csiphy_dev->hw_dts_version = CSIPHY_VERSION_V1000;
+		new_csiphy_dev->is_snps_phy = 1;
 	} else {
 		pr_err("%s:%d, invalid hw version : 0x%x\n", __func__, __LINE__,
 		new_csiphy_dev->hw_dts_version);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h
index bc8f2d9..79baf3c 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.h
@@ -64,6 +64,41 @@
 	uint32_t mipi_csiphy_t_wakeup_cfg0_addr;
 	uint32_t csiphy_version;
 	uint32_t combo_clk_mask;
+	uint32_t mipi_csiphy_interrupt_clk_status0_addr;
+	uint32_t mipi_csiphy_interrupt_clk_clear0_addr;
+};
+
+struct csiphy_reg_snps_parms_t {
+	/*MIPI CSI PHY registers*/
+	struct csiphy_reg_t mipi_csiphy_sys_ctrl;
+	struct csiphy_reg_t mipi_csiphy_sys_ctrl_1;
+	struct csiphy_reg_t mipi_csiphy_ctrl_1;
+	struct csiphy_reg_t mipi_csiphy_ctrl_2;
+	struct csiphy_reg_t mipi_csiphy_ctrl_3;
+	struct csiphy_reg_t mipi_csiphy_fifo_ctrl;
+	struct csiphy_reg_t mipi_csiphy_enable;
+	struct csiphy_reg_t mipi_csiphy_basedir;
+	struct csiphy_reg_t mipi_csiphy_force_mode;
+	struct csiphy_reg_t mipi_csiphy_enable_clk;
+	struct csiphy_reg_t mipi_csiphy_irq_mask_ctrl_lane_0;
+	struct csiphy_reg_t mipi_csiphy_irq_mask_ctrl_lane_clk_0;
+	struct csiphy_reg_t mipi_csiphy_rx_sys_7_00;
+	struct csiphy_reg_t mipi_csiphy_rx_sys_9_00;
+	struct csiphy_reg_t mipi_csiphy_rx_startup_ovr_0_00;
+	struct csiphy_reg_t mipi_csiphy_rx_startup_ovr_1_00;
+	struct csiphy_reg_t mipi_csiphy_rx_startup_ovr_2_00;
+	struct csiphy_reg_t mipi_csiphy_rx_startup_ovr_3_00;
+	struct csiphy_reg_t mipi_csiphy_rx_startup_ovr_4_00;
+	struct csiphy_reg_t mipi_csiphy_rx_startup_ovr_5_00;
+	struct csiphy_reg_t mipi_csiphy_rx_startup_obs_2_00;
+	struct csiphy_reg_t mipi_csiphy_rx_cb_2_00;
+	struct csiphy_reg_t mipi_csiphy_rx_dual_phy_0_00;
+	struct csiphy_reg_t mipi_csiphy_rx_clk_lane_3_00;
+	struct csiphy_reg_t mipi_csiphy_rx_clk_lane_4_00;
+	struct csiphy_reg_t mipi_csiphy_rx_clk_lane_6_00;
+	struct csiphy_reg_t mipi_csiphy_rx_lane_0_7_00;
+	struct csiphy_reg_t mipi_csiphy_rx_lane_1_7_00;
+	struct csiphy_reg_t mipi_csiphy_rx_clk_lane_7_00;
 };
 
 struct csiphy_reg_3ph_parms_t {
@@ -150,6 +185,7 @@
 	struct csiphy_reg_parms_t csiphy_reg;
 	struct csiphy_reg_3ph_parms_t csiphy_3ph_reg;
 	struct csiphy_settings_t csiphy_combo_mode_settings;
+	struct csiphy_reg_snps_parms_t csiphy_snps_reg;
 };
 
 enum msm_csiphy_state_t {
@@ -157,6 +193,27 @@
 	CSIPHY_POWER_DOWN,
 };
 
+enum snps_csiphy_mode {
+	AGGREGATE_MODE,
+	TWO_LANE_PHY_A,
+	TWO_LANE_PHY_B,
+	INVALID_MODE,
+};
+
+enum snps_csiphy_state {
+	NOT_CONFIGURED,
+	CONFIGURED_AGGREGATE_MODE,
+	CONFIGURED_TWO_LANE_PHY_A,
+	CONFIGURED_TWO_LANE_PHY_B,
+	CONFIGURED_COMBO_MODE,
+};
+
+struct snps_freq_value {
+	uint32_t default_bit_rate;
+	uint8_t hs_freq;
+	uint16_t osc_freq;
+};
+
 struct csiphy_device {
 	struct platform_device *pdev;
 	struct msm_sd_subdev msm_sd;
@@ -190,6 +247,9 @@
 	struct camera_vreg_t *csiphy_vreg;
 	struct regulator *csiphy_reg_ptr[MAX_REGULATOR];
 	int32_t regulator_count;
+	uint8_t is_snps_phy;
+	enum snps_csiphy_state snps_state;
+	uint8_t num_clk_irq_registers;
 };
 
 #define VIDIOC_MSM_CSIPHY_RELEASE \
diff --git a/drivers/media/platform/msm/vidc_3x/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc_3x/msm_v4l2_vidc.c
index 9d5f255..9d05086 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc_3x/msm_v4l2_vidc.c
@@ -628,6 +628,12 @@
 		msm_vidc_read_efuse_version(
 			pdev, core->resources.pf_cap_tbl, "efuse2");
 
+	rc = call_hfi_op(core->device, core_early_init,
+		core->device->hfi_device_data);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to early init core\n");
+		goto err_fail_sub_device_probe;
+	}
 	dprintk(VIDC_DBG, "populating sub devices\n");
 	/*
 	 * Trigger probe for each sub-device i.e. qcom,msm-vidc,context-bank.
@@ -639,8 +645,12 @@
 			&pdev->dev);
 	if (rc) {
 		dprintk(VIDC_ERR, "Failed to trigger probe for sub-devices\n");
+		call_hfi_op(core->device, core_early_release,
+			core->device->hfi_device_data);
 		goto err_fail_sub_device_probe;
 	}
+	call_hfi_op(core->device, core_early_release,
+		core->device->hfi_device_data);
 
 	return rc;
 
diff --git a/drivers/media/platform/msm/vidc_3x/msm_venc.c b/drivers/media/platform/msm/vidc_3x/msm_venc.c
index a728b69..f9760cf 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_venc.c
+++ b/drivers/media/platform/msm/vidc_3x/msm_venc.c
@@ -2327,6 +2327,11 @@
 		}
 		max = temp_ctrl->maximum;
 		temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_VPX_MIN_QP);
+		if (!temp_ctrl) {
+			dprintk(VIDC_ERR,
+				"failed to get control");
+			return -EINVAL;
+		}
 		min = temp_ctrl->minimum;
 		if (!VALIDATE_BOUNDARIES(min, max, qp_value))
 			rc = -EINVAL;
@@ -2341,6 +2346,11 @@
 		}
 		max = temp_ctrl->maximum;
 		temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP);
+		if (!temp_ctrl) {
+			dprintk(VIDC_ERR,
+				"failed to get control");
+			return -EINVAL;
+		}
 		min = temp_ctrl->minimum;
 		if (!VALIDATE_BOUNDARIES(min, max, qp_value))
 			rc = -EINVAL;
@@ -2355,6 +2365,11 @@
 		}
 		max = temp_ctrl->maximum;
 		temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_MIN_QP);
+		if (!temp_ctrl) {
+			dprintk(VIDC_ERR,
+				"failed to get control");
+			return -EINVAL;
+		}
 		min = temp_ctrl->minimum;
 		if (!VALIDATE_BOUNDARIES(min, max, qp_value))
 			rc = -EINVAL;
diff --git a/drivers/media/platform/msm/vidc_3x/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc_3x/msm_vidc_res_parse.c
index 82e3b40..f2c93cd 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc_3x/msm_vidc_res_parse.c
@@ -22,16 +22,11 @@
 #include "venus_boot.h"
 #include "soc/qcom/secure_buffer.h"
 #include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/regulator/consumer.h>
 
 enum clock_properties {
 	CLOCK_PROP_HAS_SCALING = 1 << 0,
 };
 
-struct regulator *gdsc_venus;
-struct regulator *gdsc_venus_core0;
-
 static inline struct device *msm_iommu_get_ctx(const char *ctx_name)
 {
 	return NULL;
@@ -64,118 +59,6 @@
 	return 0;
 }
 
-static int venus_regulator_setup(struct msm_vidc_platform_resources *res)
-{
-	const char *reg_name = "venus";
-	const char *reg_name_core0 = "venus-core0";
-	int rc = 0;
-
-	gdsc_venus = devm_regulator_get(&res->pdev->dev, reg_name);
-	if (IS_ERR(gdsc_venus))
-		dprintk(VIDC_ERR, "Failed to get Venus GDSC\n");
-
-	rc = regulator_enable(gdsc_venus);
-	if (rc)
-		dprintk(VIDC_ERR, "Venus GDSC enable failed\n");
-
-	gdsc_venus_core0 = devm_regulator_get(&res->pdev->dev, reg_name_core0);
-	if (IS_ERR(gdsc_venus_core0))
-		dprintk(VIDC_ERR, "Failed to get Venus-Core0 GDSC\n");
-
-	rc = regulator_enable(gdsc_venus_core0);
-	if (rc)
-		dprintk(VIDC_ERR, "Venus-Core0 GDSC enable failed\n");
-
-	dprintk(VIDC_DBG, "Vensu, Venus-Core0 GDSC's are enabled\n");
-	return rc;
-}
-
-
-static int venus_clock_setup(struct msm_vidc_platform_resources *res,
-		unsigned long rate)
-{
-	int i, rc = 0;
-	struct clock_info *cl;
-	struct clk *clk = NULL;
-
-	dprintk(VIDC_DBG, " %s In\n", __func__);
-	for (i = 0; i < res->clock_set.count; i++) {
-	cl = &res->clock_set.clock_tbl[i];
-		if (!cl->has_scaling)
-			continue;
-
-		clk = clk_get(&res->pdev->dev, cl->name);
-		rc = clk_set_rate(clk, clk_round_rate(clk, rate));
-
-		if (rc)
-			dprintk(VIDC_ERR,
-				"%s: Failed to set clock rate %s: %d\n",
-				__func__, cl->name, rc);
-
-		dprintk(VIDC_DBG, "%s clock set clock rate to %lu\n",
-				cl->name, rate);
-	}
-
-	dprintk(VIDC_DBG, " %s exit\n", __func__);
-	return rc;
-}
-
-static int venus_clock_prepare_enable(struct msm_vidc_platform_resources *res)
-{
-	int i, rc = 0;
-	struct clock_info *cl;
-	struct clk *clk = NULL;
-
-	dprintk(VIDC_DBG, " %s In\n", __func__);
-	for (i = 0; i < res->clock_set.count; i++) {
-		cl = &res->clock_set.clock_tbl[i];
-		clk = clk_get(&res->pdev->dev, cl->name);
-		rc = clk_prepare_enable(clk);
-
-		if (rc) {
-			dprintk(VIDC_ERR, "failed to enable %s clock\n",
-					cl->name);
-			for (i--; i >= 0; i--) {
-				cl = &res->clock_set.clock_tbl[i];
-				clk = clk_get(&res->pdev->dev, cl->name);
-				clk_disable_unprepare(clk);
-				dprintk(VIDC_ERR, "clock %s unprepared\n",
-						cl->name);
-			}
-			return rc;
-		}
-		dprintk(VIDC_DBG, " Clock : %s enabled\n", cl->name);
-	}
-
-	dprintk(VIDC_DBG, " %s exit\n", __func__);
-	return rc;
-}
-
-static void venus_clk_disable_unprepare(struct msm_vidc_platform_resources *res)
-{
-	int i;
-	struct clock_info *cl;
-	struct clk *clk = NULL;
-
-	for (i = 0; i < res->clock_set.count; i++) {
-		cl = &res->clock_set.clock_tbl[i];
-		clk = clk_get(&res->pdev->dev, cl->name);
-		dprintk(VIDC_DBG, "clock %s unprepared\n", cl->name);
-		clk_disable_unprepare(clk);
-	}
-
-	if (gdsc_venus) {
-		regulator_disable(gdsc_venus);
-		dprintk(VIDC_DBG, "Venus Regulator disabled\n");
-		gdsc_venus = NULL;
-	}
-	if (gdsc_venus_core0) {
-		regulator_disable(gdsc_venus_core0);
-		dprintk(VIDC_DBG, "Venus-Core0 Regulator disabled\n");
-		gdsc_venus_core0 = NULL;
-	}
-}
-
 static inline enum imem_type read_imem_type(struct platform_device *pdev)
 {
 	bool is_compatible(char *compat)
@@ -961,7 +844,6 @@
 	dprintk(VIDC_DBG, "Found bus %s [%d->%d] with governor %s\n",
 			bus->name, bus->master, bus->slave, bus->governor);
 
-	venus_clk_disable_unprepare(res);
 err_bus:
 	return rc;
 }
@@ -1352,11 +1234,6 @@
 			"qcom,max-secure-instances",
 			&res->max_secure_inst_count);
 
-	venus_regulator_setup(res);
-	venus_clock_setup(res, 0);
-	venus_clock_prepare_enable(res);
-	venus_clock_setup(res, 1);
-
 	return rc;
 
 err_setup_legacy_cb:
diff --git a/drivers/media/platform/msm/vidc_3x/venus_hfi.c b/drivers/media/platform/msm/vidc_3x/venus_hfi.c
index ec6f9b0..b83606a 100644
--- a/drivers/media/platform/msm/vidc_3x/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc_3x/venus_hfi.c
@@ -4001,6 +4001,32 @@
 	return rc;
 }
 
+static int __early_init_resources(struct venus_hfi_device *device,
+				struct msm_vidc_platform_resources *res)
+{
+	int rc = 0;
+
+	rc = __init_regulators(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to get all regulators\n");
+		return -ENODEV;
+	}
+
+	rc = __init_clocks(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to init clocks\n");
+		rc = -ENODEV;
+		goto err_init_clocks;
+	}
+
+	return rc;
+
+err_init_clocks:
+	__deinit_regulators(device);
+	return rc;
+}
+
+
 static void __deinit_resources(struct venus_hfi_device *device)
 {
 	__deinit_bus(device);
@@ -4010,6 +4036,12 @@
 	device->sys_init_capabilities = NULL;
 }
 
+static void __early_deinit_resources(struct venus_hfi_device *device)
+{
+	__deinit_clocks(device);
+	__deinit_regulators(device);
+}
+
 static int __protect_cp_mem(struct venus_hfi_device *device)
 {
 	struct tzbsp_memprot memprot;
@@ -4235,6 +4267,41 @@
 	return rc;
 }
 
+static int __venus_early_power_on(struct venus_hfi_device *device)
+{
+	int rc = 0;
+
+	if (device->power_enabled)
+		return 0;
+
+	device->power_enabled = true;
+
+	rc = __enable_regulators(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to enable GDSC, err = %d\n", rc);
+		goto fail_enable_gdsc;
+	}
+
+	rc = __prepare_enable_clks(device);
+	if (rc) {
+		dprintk(VIDC_ERR, "Failed to enable clocks: %d\n", rc);
+		goto fail_enable_clks;
+	}
+
+	rc = __scale_clocks(device, 0, NULL, 0);
+	if (rc) {
+		dprintk(VIDC_WARN,
+				"Failed to scale clocks, performance might be affected\n");
+		rc = 0;
+	}
+	return rc;
+
+fail_enable_clks:
+	__disable_regulators(device);
+fail_enable_gdsc:
+	return rc;
+}
+
 static void __venus_power_off(struct venus_hfi_device *device, bool halt_axi)
 {
 	if (!device->power_enabled)
@@ -4261,6 +4328,14 @@
 	device->power_enabled = false;
 }
 
+static void __venus_early_power_off(struct venus_hfi_device *device)
+{
+	__disable_unprepare_clks(device);
+	if (__disable_regulators(device))
+		dprintk(VIDC_WARN, "Failed to disable regulators\n");
+	device->power_enabled = false;
+}
+
 static inline int __suspend(struct venus_hfi_device *device)
 {
 	int rc = 0;
@@ -4446,7 +4521,7 @@
 	struct venus_hfi_device *device = dev;
 	u32 smem_block_size = 0;
 	u8 *smem_table_ptr;
-	char version[VENUS_VERSION_LENGTH];
+	char version[VENUS_VERSION_LENGTH] = "";
 	const u32 smem_image_index_venus = 14 * 128;
 
 	if (!device || !fw_info) {
@@ -4652,10 +4727,35 @@
 	}
 }
 
+static int venus_hfi_core_early_init(void *device)
+{
+	int rc = 0;
+	struct venus_hfi_device *dev = device;
+
+	mutex_lock(&dev->lock);
+	rc = __early_init_resources(dev, dev->res);
+	rc = __venus_early_power_on(device);
+	mutex_unlock(&dev->lock);
+	return rc;
+}
+
+static int venus_hfi_core_early_release(void *device)
+{
+	struct venus_hfi_device *dev = device;
+
+	mutex_lock(&dev->lock);
+	__venus_early_power_off(dev);
+	__early_deinit_resources(dev);
+	mutex_unlock(&dev->lock);
+	return 0;
+}
+
 static void venus_init_hfi_callbacks(struct hfi_device *hdev)
 {
 	hdev->core_init = venus_hfi_core_init;
 	hdev->core_release = venus_hfi_core_release;
+	hdev->core_early_init = venus_hfi_core_early_init;
+	hdev->core_early_release = venus_hfi_core_early_release;
 	hdev->core_ping = venus_hfi_core_ping;
 	hdev->core_trigger_ssr = venus_hfi_core_trigger_ssr;
 	hdev->session_init = venus_hfi_session_init;
diff --git a/drivers/media/platform/msm/vidc_3x/vidc_hfi_api.h b/drivers/media/platform/msm/vidc_3x/vidc_hfi_api.h
index 04bf5a8..1a25a58 100644
--- a/drivers/media/platform/msm/vidc_3x/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc_3x/vidc_hfi_api.h
@@ -1483,7 +1483,9 @@
 
 	/*Add function pointers for all the hfi functions below*/
 	int (*core_init)(void *device);
+	int (*core_early_init)(void *device);
 	int (*core_release)(void *device);
+	int (*core_early_release)(void *device);
 	int (*core_ping)(void *device);
 	int (*core_trigger_ssr)(void *device, enum hal_ssr_trigger_type);
 	int (*session_init)(void *device, void *session_id,
diff --git a/drivers/misc/qpnp-misc.c b/drivers/misc/qpnp-misc.c
index 690b28b..eec0875 100644
--- a/drivers/misc/qpnp-misc.c
+++ b/drivers/misc/qpnp-misc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014,2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014,2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,7 @@
 #include <linux/regmap.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
+#include <linux/notifier.h>
 #include <linux/qpnp/qpnp-misc.h>
 
 #define QPNP_MISC_DEV_NAME "qcom,qpnp-misc"
@@ -29,8 +30,20 @@
 #define PWM_SEL_MAX		0x03
 #define GP_DRIVER_EN_BIT	BIT(0)
 
+enum twm {
+	TWM_MODE_1 = 1,
+	TWM_MODE_2,
+	TWM_MODE_3,
+};
+
+enum twm_attrib {
+	TWM_ENABLE,
+	TWM_EXIT,
+};
+
 static DEFINE_MUTEX(qpnp_misc_dev_list_mutex);
 static LIST_HEAD(qpnp_misc_dev_list);
+static RAW_NOTIFIER_HEAD(twm_notifier);
 
 struct qpnp_misc_version {
 	u8	subtype;
@@ -55,10 +68,14 @@
 	struct device			*dev;
 	struct regmap			*regmap;
 	struct qpnp_misc_version	version;
+	struct class			twm_class;
 
+	u8				twm_mode;
 	u32				base;
 	u8				pwm_sel;
 	bool				enable_gp_driver;
+	bool				support_twm_config;
+	bool				twm_enable;
 };
 
 static const struct of_device_id qpnp_misc_match_table[] = {
@@ -211,12 +228,100 @@
 	return __misc_irqs_available(mdev_found);
 }
 
+#define MISC_SPARE_1		0x50
+#define MISC_SPARE_2		0x51
+#define ENABLE_TWM_MODE		0x80
+#define DISABLE_TWM_MODE	0x0
+#define TWM_EXIT_BIT		BIT(0)
+static ssize_t twm_enable_store(struct class *c,
+			struct class_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct qpnp_misc_dev *mdev = container_of(c,
+			struct qpnp_misc_dev, twm_class);
+	u8 val = 0;
+	ssize_t rc = 0;
+
+	rc = kstrtou8(buf, 10, &val);
+	if (rc < 0)
+		return rc;
+
+	mdev->twm_enable = val ? true : false;
+
+	/* Notify the TWM state */
+	raw_notifier_call_chain(&twm_notifier,
+		mdev->twm_enable ? PMIC_TWM_ENABLE : PMIC_TWM_CLEAR, NULL);
+
+	return count;
+}
+
+static ssize_t twm_enable_show(struct class *c,
+			struct class_attribute *attr, char *buf)
+{
+	struct qpnp_misc_dev *mdev = container_of(c,
+			struct qpnp_misc_dev, twm_class);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", mdev->twm_enable);
+}
+
+static ssize_t twm_exit_show(struct class *c,
+			struct class_attribute *attr, char *buf)
+{
+	struct qpnp_misc_dev *mdev = container_of(c,
+			struct qpnp_misc_dev, twm_class);
+	int rc = 0;
+	u8 val = 0;
+
+	rc = qpnp_read_byte(mdev, MISC_SPARE_1, &val);
+	if (rc < 0) {
+		pr_err("Failed to read TWM enable (misc_spare_1) rc=%d\n", rc);
+		return rc;
+	}
+
+	pr_debug("TWM_EXIT (misc_spare_1) register = 0x%02x\n", val);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", !!(val & TWM_EXIT_BIT));
+}
+
+static struct class_attribute twm_attributes[] = {
+	[TWM_ENABLE]		= __ATTR(twm_enable, 0644,
+					twm_enable_show, twm_enable_store),
+	[TWM_EXIT]		= __ATTR(twm_exit, 0644,
+					twm_exit_show, NULL),
+	__ATTR_NULL,
+};
+
+int qpnp_misc_twm_notifier_register(struct notifier_block *nb)
+{
+	return raw_notifier_chain_register(&twm_notifier, nb);
+}
+EXPORT_SYMBOL(qpnp_misc_twm_notifier_register);
+
+int qpnp_misc_twm_notifier_unregister(struct notifier_block *nb)
+{
+	return raw_notifier_chain_unregister(&twm_notifier, nb);
+}
+EXPORT_SYMBOL(qpnp_misc_twm_notifier_unregister);
+
 static int qpnp_misc_dt_init(struct qpnp_misc_dev *mdev)
 {
 	struct device_node *node = mdev->dev->of_node;
 	u32 val;
 	int rc;
 
+	if (of_property_read_bool(mdev->dev->of_node,
+				"qcom,support-twm-config")) {
+		mdev->support_twm_config = true;
+		mdev->twm_mode = TWM_MODE_3;
+		rc = of_property_read_u8(mdev->dev->of_node, "qcom,twm-mode",
+							&mdev->twm_mode);
+		if (!rc && (mdev->twm_mode < TWM_MODE_1 ||
+				mdev->twm_mode > TWM_MODE_3)) {
+			pr_err("Invalid TWM mode %d\n", mdev->twm_mode);
+			return -EINVAL;
+		}
+	}
+
 	rc = of_property_read_u32(node, "reg", &mdev->base);
 	if (rc < 0 || !mdev->base) {
 		dev_err(mdev->dev, "Base address not defined or invalid\n");
@@ -270,6 +375,18 @@
 		break;
 	}
 
+	if (mdev->support_twm_config) {
+		mdev->twm_class.name = "pmic_twm",
+		mdev->twm_class.owner = THIS_MODULE,
+		mdev->twm_class.class_attrs = twm_attributes;
+
+		rc = class_register(&mdev->twm_class);
+		if (rc < 0) {
+			pr_err("Failed to register pmic_twm class rc=%d\n", rc);
+			return rc;
+		}
+	}
+
 	return 0;
 }
 
@@ -283,6 +400,7 @@
 		return -ENOMEM;
 
 	mdev->dev = &pdev->dev;
+	dev_set_drvdata(&pdev->dev, mdev);
 	mdev->regmap = dev_get_regmap(mdev->dev->parent, NULL);
 	if (!mdev->regmap) {
 		dev_err(mdev->dev, "Parent regmap is unavailable\n");
@@ -325,8 +443,33 @@
 	return 0;
 }
 
+static void qpnp_misc_shutdown(struct platform_device *pdev)
+{
+	struct qpnp_misc_dev *mdev = dev_get_drvdata(&pdev->dev);
+	int rc;
+
+	if (mdev->support_twm_config) {
+		rc = qpnp_write_byte(mdev, MISC_SPARE_2,
+				mdev->twm_enable ? mdev->twm_mode : 0x0);
+		if (rc < 0)
+			pr_err("Failed to write MISC_SPARE_2 (twm_mode) val=%d rc=%d\n",
+				mdev->twm_enable ? mdev->twm_mode : 0x0, rc);
+
+		rc = qpnp_write_byte(mdev, MISC_SPARE_1,
+				mdev->twm_enable ? ENABLE_TWM_MODE : 0x0);
+		if (rc < 0)
+			pr_err("Failed to write MISC_SPARE_1 (twm_state) val=%d rc=%d\n",
+				mdev->twm_enable ? ENABLE_TWM_MODE : 0x0, rc);
+
+		pr_debug("PMIC configured for TWM-%s MODE=%d\n",
+				mdev->twm_enable ? "enabled" : "disabled",
+				mdev->twm_mode);
+	}
+}
+
 static struct platform_driver qpnp_misc_driver = {
 	.probe	= qpnp_misc_probe,
+	.shutdown = qpnp_misc_shutdown,
 	.driver	= {
 		.name		= QPNP_MISC_DEV_NAME,
 		.owner		= THIS_MODULE,
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 232b4ae..c0143db 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -4444,11 +4444,8 @@
 
 	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data) {
-		if (ret == 0) {
-			kfree(*handle);
-			*handle = NULL;
-		}
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto exit_handle_free;
 	}
 	data->abort = 0;
 	data->type = QSEECOM_CLIENT_APP;
@@ -4463,10 +4460,8 @@
 				ION_HEAP(ION_QSECOM_HEAP_ID), 0);
 	if (IS_ERR_OR_NULL(data->client.ihandle)) {
 		pr_err("Ion client could not retrieve the handle\n");
-		kfree(data);
-		kfree(*handle);
-		*handle = NULL;
-		return -EINVAL;
+		ret = -ENOMEM;
+		goto exit_data_free;
 	}
 	mutex_lock(&app_access_lock);
 
@@ -4474,7 +4469,7 @@
 	strlcpy(app_ireq.app_name, app_name, MAX_APP_NAME_SIZE);
 	ret = __qseecom_check_app_exists(app_ireq, &app_id);
 	if (ret)
-		goto err;
+		goto exit_ion_free;
 
 	strlcpy(data->client.app_name, app_name, MAX_APP_NAME_SIZE);
 	if (app_id) {
@@ -4500,23 +4495,22 @@
 				qseecom.pdev->init_name);
 		ret = __qseecom_load_fw(data, app_name, &app_id);
 		if (ret < 0)
-			goto err;
+			goto exit_ion_free;
 	}
 	data->client.app_id = app_id;
 	if (!found_app) {
 		entry = kmalloc(sizeof(*entry), GFP_KERNEL);
 		if (!entry) {
 			pr_err("kmalloc for app entry failed\n");
-			ret =  -ENOMEM;
-			goto err;
+			ret = -ENOMEM;
+			goto exit_ion_free;
 		}
 		entry->app_id = app_id;
 		entry->ref_cnt = 1;
 		strlcpy(entry->app_name, app_name, MAX_APP_NAME_SIZE);
 		if (__qseecom_get_fw_size(app_name, &fw_size, &app_arch)) {
 			ret = -EIO;
-			kfree(entry);
-			goto err;
+			goto exit_entry_free;
 		}
 		entry->app_arch = app_arch;
 		entry->app_blocked = false;
@@ -4532,7 +4526,7 @@
 	if (ret) {
 		pr_err("Cannot get phys_addr for the Ion Client, ret = %d\n",
 			ret);
-		goto err;
+		goto exit_entry_free;
 	}
 
 	/* Populate the structure for sending scm call to load image */
@@ -4541,7 +4535,7 @@
 	if (IS_ERR_OR_NULL(data->client.sb_virt)) {
 		pr_err("ION memory mapping for client shared buf failed\n");
 		ret = -ENOMEM;
-		goto err;
+		goto exit_entry_free;
 	}
 	data->client.user_virt_sb_base = (uintptr_t)data->client.sb_virt;
 	data->client.sb_phys = (phys_addr_t)pa;
@@ -4552,7 +4546,7 @@
 	kclient_entry = kzalloc(sizeof(*kclient_entry), GFP_KERNEL);
 	if (!kclient_entry) {
 		ret = -ENOMEM;
-		goto err;
+		goto exit_ion_unmap_kernel;
 	}
 	kclient_entry->handle = *handle;
 
@@ -4564,11 +4558,24 @@
 	mutex_unlock(&app_access_lock);
 	return 0;
 
-err:
-	kfree(data);
-	kfree(*handle);
-	*handle = NULL;
+exit_ion_unmap_kernel:
+	if (!IS_ERR_OR_NULL(data->client.ihandle))
+		ion_unmap_kernel(qseecom.ion_clnt, data->client.ihandle);
+exit_entry_free:
+	kfree(entry);
+exit_ion_free:
 	mutex_unlock(&app_access_lock);
+	if (!IS_ERR_OR_NULL(data->client.ihandle)) {
+		ion_free(qseecom.ion_clnt, data->client.ihandle);
+		data->client.ihandle = NULL;
+	}
+exit_data_free:
+	kfree(data);
+exit_handle_free:
+	if (*handle) {
+		kfree(*handle);
+		*handle = NULL;
+	}
 	return ret;
 }
 EXPORT_SYMBOL(qseecom_start_app);
@@ -6959,6 +6966,31 @@
 			pr_err("failed qseecom_register_listener: %d\n", ret);
 		break;
 	}
+	case QSEECOM_IOCTL_SET_ICE_INFO: {
+		struct qseecom_ice_data_t ice_data;
+
+		ret = copy_from_user(&ice_data, argp, sizeof(ice_data));
+		if (ret) {
+			pr_err("copy_from_user failed\n");
+			return -EFAULT;
+		}
+		qcom_ice_set_fde_flag(ice_data.flag);
+		break;
+	}
+
+	case QSEECOM_IOCTL_SET_ENCDEC_INFO: {
+		struct qseecom_encdec_conf_t conf;
+
+		ret = copy_from_user(&conf, argp, sizeof(conf));
+		if (ret) {
+			pr_err("copy_from_user failed\n");
+			return -EFAULT;
+		}
+		ret = qcom_ice_set_fde_conf(conf.start_sector, conf.fs_size,
+					conf.index, conf.mode);
+		break;
+	}
+
 	case QSEECOM_IOCTL_UNREGISTER_LISTENER_REQ: {
 		if ((data->listener.id == 0) ||
 			(data->type != QSEECOM_LISTENER_SERVICE)) {
diff --git a/drivers/misc/uid_sys_stats.c b/drivers/misc/uid_sys_stats.c
index 42a513c..728c65a 100644
--- a/drivers/misc/uid_sys_stats.c
+++ b/drivers/misc/uid_sys_stats.c
@@ -345,13 +345,13 @@
 		uid_entry->active_utime = 0;
 	}
 
-	read_lock(&tasklist_lock);
+	rcu_read_lock();
 	do_each_thread(temp, task) {
 		uid = from_kuid_munged(user_ns, task_uid(task));
 		if (!uid_entry || uid_entry->uid != uid)
 			uid_entry = find_or_register_uid(uid);
 		if (!uid_entry) {
-			read_unlock(&tasklist_lock);
+			rcu_read_unlock();
 			rt_mutex_unlock(&uid_lock);
 			pr_err("%s: failed to find the uid_entry for uid %d\n",
 				__func__, uid);
@@ -361,7 +361,7 @@
 		uid_entry->active_utime += utime;
 		uid_entry->active_stime += stime;
 	} while_each_thread(temp, task);
-	read_unlock(&tasklist_lock);
+	rcu_read_unlock();
 
 	hash_for_each(hash_table, bkt, uid_entry, hash) {
 		cputime_t total_utime = uid_entry->utime +
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index e04e0f0..2405ae3 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -3196,11 +3196,11 @@
 static void mmc_blk_cmdq_requeue_rw_rq(struct mmc_queue *mq,
 				struct request *req)
 {
-	struct mmc_card *card = mq->card;
-	struct mmc_host *host = card->host;
+	struct request_queue *q = req->q;
 
-	blk_requeue_request(req->q, req);
-	mmc_put_card(host->card);
+	spin_lock_irq(q->queue_lock);
+	blk_requeue_request(q, req);
+	spin_unlock_irq(q->queue_lock);
 }
 
 static int mmc_blk_cmdq_issue_rw_rq(struct mmc_queue *mq, struct request *req)
@@ -4090,9 +4090,16 @@
 			 * If issuing of the request fails with eitehr EBUSY or
 			 * EAGAIN error, re-queue the request.
 			 * This case would occur with ICE calls.
+			 * For request which gets completed successfully or
+			 * errored out, we release host lock in completion or
+			 * error handling softirq context. But here the request
+			 * is neither completed nor erred-out, so release the
+			 * host lock explicitly.
 			 */
-			if (ret == -EBUSY || ret == -EAGAIN)
+			if (ret == -EBUSY || ret == -EAGAIN) {
 				mmc_blk_cmdq_requeue_rw_rq(mq, req);
+				mmc_put_card(host->card);
+			}
 		}
 	}
 
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 205a32c..d00f0d8 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -470,7 +470,7 @@
 		mmc_host_clear_sdr104(host);
 		err = mmc_hw_reset(host);
 		host->card->sdr104_blocked = true;
-	} else {
+	} else if (mmc_card_sd(host->card)) {
 		/* If sdr104_wa is not present, just return status */
 		err = host->bus_ops->alive(host);
 	}
@@ -1665,7 +1665,8 @@
 		    mmc_card_removed(host->card)) {
 			if (cmd->error && !cmd->retries &&
 			     cmd->opcode != MMC_SEND_STATUS &&
-			     cmd->opcode != MMC_SEND_TUNING_BLOCK)
+			     cmd->opcode != MMC_SEND_TUNING_BLOCK &&
+			     cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200)
 				mmc_recovery_fallback_lower_speed(host);
 			break;
 		}
@@ -4591,7 +4592,9 @@
 
 	mmc_bus_put(host);
 
+	mmc_claim_host(host);
 	mmc_power_off(host);
+	mmc_release_host(host);
 
 	return ret;
 }
@@ -4612,8 +4615,8 @@
 		return -EINVAL;
 	}
 
-	mmc_power_up(host, host->card->ocr);
 	mmc_claim_host(host);
+	mmc_power_up(host, host->card->ocr);
 	ret = host->bus_ops->power_restore(host);
 	mmc_release_host(host);
 
diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c
index ba44cfd..831963a 100644
--- a/drivers/mmc/core/quirks.c
+++ b/drivers/mmc/core/quirks.c
@@ -79,6 +79,13 @@
 #define SDIO_DEVICE_ID_QCA9377		0x701
 #endif
 
+#ifndef SDIO_VENDOR_ID_QCA9379
+#define SDIO_VENDOR_ID_QCA9379          0x271
+#endif
+
+#ifndef SDIO_DEVICE_ID_QCA9379
+#define SDIO_DEVICE_ID_QCA9379          0x801
+#endif
 
 /*
  * This hook just adds a quirk for all sdio devices
@@ -131,6 +138,9 @@
 
 	SDIO_FIXUP(SDIO_VENDOR_ID_QCA9377, SDIO_DEVICE_ID_QCA9377,
 		add_quirk, MMC_QUIRK_QCA9377_SETTINGS),
+
+	SDIO_FIXUP(SDIO_VENDOR_ID_QCA9379, SDIO_DEVICE_ID_QCA9379,
+		add_quirk, MMC_QUIRK_QCA9379_SETTINGS),
 	END_FIXUP
 };
 
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 9ebe730..e749a97 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -227,7 +227,8 @@
 	u8 settings;
 
 	if (mmc_enable_qca6574_settings(card) ||
-		mmc_enable_qca9377_settings(card)) {
+		mmc_enable_qca9377_settings(card) ||
+		mmc_enable_qca9379_settings(card)) {
 		ret = mmc_io_rw_direct(card, 1, 0, 0xF2, 0x0F, NULL);
 		if (ret) {
 			pr_crit("%s: failed to write to fn 0xf2 %d\n",
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 47094d5..d91eb67 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -175,6 +175,8 @@
 #define MAX_DRV_TYPES_SUPPORTED_HS200	4
 #define MSM_AUTOSUSPEND_DELAY_MS 100
 
+#define RCLK_TOGGLE 0x2
+
 struct sdhci_msm_offset {
 	u32 CORE_MCI_DATA_CNT;
 	u32 CORE_MCI_STATUS;
@@ -3497,6 +3499,33 @@
 					| CORE_HC_SELECT_IN_EN), host->ioaddr +
 					msm_host_offset->CORE_VENDOR_SPEC);
 		}
+		/*
+		 * After MCLK ugating, toggle the FIFO write clock to get
+		 * the FIFO pointers and flags to valid state.
+		 */
+		if (msm_host->tuning_done ||
+				(card && mmc_card_strobe(card) &&
+				msm_host->enhanced_strobe)) {
+			/*
+			 * set HC_REG_DLL_CONFIG_3[1] to select MCLK as
+			 * DLL input clock
+			 */
+			writel_relaxed(((readl_relaxed(host->ioaddr +
+				msm_host_offset->CORE_DDR_CONFIG))
+				| RCLK_TOGGLE), host->ioaddr +
+				msm_host_offset->CORE_DDR_CONFIG);
+			/* ensure above write as toggling same bit quickly */
+			wmb();
+			udelay(2);
+			/*
+			 * clear HC_REG_DLL_CONFIG_3[1] to select RCLK as
+			 * DLL input clock
+			 */
+			writel_relaxed(((readl_relaxed(host->ioaddr +
+				msm_host_offset->CORE_DDR_CONFIG))
+				& ~RCLK_TOGGLE), host->ioaddr +
+				msm_host_offset->CORE_DDR_CONFIG);
+		}
 		if (!host->mmc->ios.old_rate && !msm_host->use_cdclp533) {
 			/*
 			 * Poll on DLL_LOCK and DDR_DLL_LOCK bits in
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 5c33140..917a876 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -31,3 +31,4 @@
 obj-$(CONFIG_WCNSS_MEM_PRE_ALLOC) += cnss_prealloc/
 obj-$(CONFIG_CNSS_UTILS) += cnss_utils/
 obj-$(CONFIG_CNSS_GENL) += cnss_genl/
+obj-$(CONFIG_CNSS_CRYPTO) += cnss_crypto/
diff --git a/drivers/net/wireless/cnss/cnss_sdio.c b/drivers/net/wireless/cnss/cnss_sdio.c
index c35ba38..8ed2630 100644
--- a/drivers/net/wireless/cnss/cnss_sdio.c
+++ b/drivers/net/wireless/cnss/cnss_sdio.c
@@ -123,6 +123,7 @@
 /* SDIO manufacturer ID and Codes */
 #define MANUFACTURER_ID_AR6320_BASE        0x500
 #define MANUFACTURER_ID_QCA9377_BASE       0x700
+#define MANUFACTURER_ID_QCA9379_BASE       0x800
 #define MANUFACTURER_CODE                  0x271
 
 static const struct sdio_device_id ar6k_id_table[] = {
@@ -158,6 +159,22 @@
 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xD))},
 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xE))},
 	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9377_BASE | 0xF))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x0))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x1))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x2))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x3))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x4))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x5))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x6))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x7))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x8))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0x9))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xA))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xB))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xC))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xD))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xE))},
+	{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_QCA9379_BASE | 0xF))},
 	{},
 };
 MODULE_DEVICE_TABLE(sdio, ar6k_id_table);
@@ -257,11 +274,6 @@
 		return ret;
 	}
 
-	if (!cnss_pdata->regulator.wlan_vreg) {
-		pr_debug("wlan_vreg regulator is invalid\n");
-		return 0;
-	}
-
 	ret = mmc_power_save_host(host);
 	if (ret) {
 		pr_err("Failed to Power Save Host err:%d\n",
@@ -269,7 +281,11 @@
 		return ret;
 	}
 
-	regulator_disable(cnss_pdata->regulator.wlan_vreg);
+	if (cnss_pdata->regulator.wlan_vreg)
+		regulator_disable(cnss_pdata->regulator.wlan_vreg);
+	else
+		pr_debug("wlan_vreg regulator is invalid\n");
+
 	info->cnss_hw_state = CNSS_HW_SLEEP;
 
 	return ret;
@@ -303,22 +319,23 @@
 		return ret;
 	}
 
-	if (!cnss_pdata->regulator.wlan_vreg) {
+	if (cnss_pdata->regulator.wlan_vreg) {
+		ret = regulator_enable(cnss_pdata->regulator.wlan_vreg);
+		if (ret) {
+			pr_err("Failed to enable wlan vreg\n");
+			return ret;
+		}
+	} else {
 		pr_debug("wlan_vreg regulator is invalid\n");
-		return 0;
 	}
 
-	ret = regulator_enable(cnss_pdata->regulator.wlan_vreg);
-	if (ret) {
-		pr_err("Failed to enable wlan vreg\n");
-		return ret;
-	}
 
 	ret = mmc_power_restore_host(host);
 	if (ret) {
 		pr_err("Failed to restore host power ret:%d\n",
 		       ret);
-		regulator_disable(cnss_pdata->regulator.wlan_vreg);
+		if (cnss_pdata->regulator.wlan_vreg)
+			regulator_disable(cnss_pdata->regulator.wlan_vreg);
 		return ret;
 	}
 
diff --git a/drivers/net/wireless/cnss2/debug.c b/drivers/net/wireless/cnss2/debug.c
index 5e2d44c..b1fbbd8 100644
--- a/drivers/net/wireless/cnss2/debug.c
+++ b/drivers/net/wireless/cnss2/debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,8 +17,6 @@
 #include "debug.h"
 #include "pci.h"
 
-#define CNSS_IPC_LOG_PAGES		32
-
 void *cnss_ipc_log_context;
 
 static int cnss_pin_connect_show(struct seq_file *s, void *data)
@@ -139,11 +137,17 @@
 {
 	struct cnss_plat_data *plat_priv =
 		((struct seq_file *)fp->private_data)->private;
+	struct cnss_pci_data *pci_priv;
 	char buf[64];
 	char *cmd;
 	unsigned int len = 0;
 	int ret = 0;
 
+	if (!plat_priv)
+		return -ENODEV;
+
+	pci_priv = plat_priv->bus_priv;
+
 	len = min(count, sizeof(buf) - 1);
 	if (copy_from_user(buf, user_buf, len))
 		return -EFAULT;
@@ -159,11 +163,11 @@
 		ret = cnss_pci_init(plat_priv);
 	} else if (sysfs_streq(cmd, "download")) {
 		set_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
-		ret = cnss_pci_start_mhi(plat_priv->bus_priv);
+		ret = cnss_pci_start_mhi(pci_priv);
 	} else if (sysfs_streq(cmd, "linkup")) {
-		ret = cnss_resume_pci_link(plat_priv->bus_priv);
+		ret = cnss_resume_pci_link(pci_priv);
 	} else if (sysfs_streq(cmd, "linkdown")) {
-		ret = cnss_suspend_pci_link(plat_priv->bus_priv);
+		ret = cnss_suspend_pci_link(pci_priv);
 	} else if (sysfs_streq(cmd, "powerup")) {
 		set_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
 		ret = cnss_driver_event_post(plat_priv,
@@ -172,8 +176,10 @@
 	} else if (sysfs_streq(cmd, "shutdown")) {
 		ret = cnss_driver_event_post(plat_priv,
 					     CNSS_DRIVER_EVENT_POWER_DOWN,
-					     CNSS_EVENT_SYNC, NULL);
+					     0, NULL);
 		clear_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
+	} else if (sysfs_streq(cmd, "assert")) {
+		ret = cnss_force_fw_assert(&pci_priv->pci_dev->dev);
 	} else {
 		cnss_pr_err("Device boot debugfs command is invalid\n");
 		ret = -EINVAL;
@@ -197,6 +203,7 @@
 	seq_puts(s, "linkdown: bring down PCIe link\n");
 	seq_puts(s, "powerup: full power on sequence to boot device, download FW and do QMI handshake with FW\n");
 	seq_puts(s, "shutdown: full power off sequence to shutdown device\n");
+	seq_puts(s, "assert: trigger firmware assert\n");
 
 	return 0;
 }
diff --git a/drivers/net/wireless/cnss2/debug.h b/drivers/net/wireless/cnss2/debug.h
index decc84a..f31fdfe 100644
--- a/drivers/net/wireless/cnss2/debug.h
+++ b/drivers/net/wireless/cnss2/debug.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -16,6 +16,8 @@
 #include <linux/ipc_logging.h>
 #include <linux/printk.h>
 
+#define CNSS_IPC_LOG_PAGES		32
+
 extern void *cnss_ipc_log_context;
 
 #define cnss_ipc_log_string(_x...) do {					\
diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c
index bcea74a..9142758 100644
--- a/drivers/net/wireless/cnss2/main.c
+++ b/drivers/net/wireless/cnss2/main.c
@@ -571,7 +571,8 @@
 		goto out;
 	}
 
-	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
+	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
+	    test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
 		ret = plat_priv->driver_ops->reinit(pci_priv->pci_dev,
 						    pci_priv->pci_device_id);
 		if (ret) {
@@ -588,6 +589,7 @@
 				    ret);
 			goto out;
 		}
+		clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
 		clear_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
 		set_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
 	}
@@ -614,7 +616,8 @@
 		return -EINVAL;
 	}
 
-	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
+	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
+	    test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
 		plat_priv->driver_ops->shutdown(pci_priv->pci_dev);
 	} else if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) {
 		plat_priv->driver_ops->remove(pci_priv->pci_dev);
@@ -652,7 +655,9 @@
 		complete(&plat_priv->power_up_complete);
 	}
 
-	if (ret)
+	if (ret && test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state))
+		goto out;
+	else if (ret)
 		goto shutdown;
 
 	return 0;
@@ -662,6 +667,10 @@
 	cnss_suspend_pci_link(plat_priv->bus_priv);
 	cnss_power_off_device(plat_priv);
 
+	clear_bit(CNSS_FW_READY, &plat_priv->driver_state);
+	clear_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
+
+out:
 	return ret;
 }
 
@@ -940,7 +949,7 @@
 		of_property_read_bool(dev->of_node,
 				      "qcom,notify-modem-status");
 
-	if (esoc_info->notify_modem_status)
+	if (!esoc_info->notify_modem_status)
 		goto out;
 
 	ret = of_property_read_string_index(dev->of_node, "esoc-names", 0,
@@ -1172,23 +1181,16 @@
 static void cnss_qca6290_crash_shutdown(struct cnss_plat_data *plat_priv)
 {
 	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
-	int ret = 0;
 
 	cnss_pr_dbg("Crash shutdown with driver_state 0x%lx\n",
 		    plat_priv->driver_state);
 
-	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) ||
-	    test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
-	    test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state))
-		return;
-
-	ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RDDM_KERNEL_PANIC);
-	if (ret) {
-		cnss_pr_err("Fail to complete RDDM, err = %d\n", ret);
+	if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
+		cnss_pr_dbg("Ignore crash shutdown\n");
 		return;
 	}
 
-	cnss_pci_collect_dump_info(pci_priv);
+	cnss_pci_collect_dump_info(pci_priv, true);
 }
 
 static int cnss_powerup(struct cnss_plat_data *plat_priv)
@@ -1443,7 +1445,6 @@
 	struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
 	struct cnss_subsys_info *subsys_info =
 		&plat_priv->subsys_info;
-	int ret = 0;
 
 	plat_priv->recovery_count++;
 
@@ -1467,12 +1468,7 @@
 		break;
 	case CNSS_REASON_RDDM:
 		clear_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
-		ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RDDM);
-		if (ret) {
-			cnss_pr_err("Failed to complete RDDM, err = %d\n", ret);
-			break;
-		}
-		cnss_pci_collect_dump_info(pci_priv);
+		cnss_pci_collect_dump_info(pci_priv, false);
 		break;
 	case CNSS_REASON_DEFAULT:
 	case CNSS_REASON_TIMEOUT:
@@ -1538,11 +1534,6 @@
 		if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
 			set_bit(CNSS_FW_BOOT_RECOVERY,
 				&plat_priv->driver_state);
-		} else if (test_bit(CNSS_DRIVER_LOADING,
-			   &plat_priv->driver_state)) {
-			cnss_pr_err("Driver probe is in progress, ignore recovery\n");
-			ret = -EINVAL;
-			goto out;
 		}
 		break;
 	}
diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h
index 81b5de8..c11b206 100644
--- a/drivers/net/wireless/cnss2/main.h
+++ b/drivers/net/wireless/cnss2/main.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -109,6 +109,12 @@
 	bool valid;
 };
 
+enum cnss_fw_dump_type {
+	CNSS_FW_IMAGE,
+	CNSS_FW_RDDM,
+	CNSS_FW_REMOTE_HEAP,
+};
+
 enum cnss_driver_event_type {
 	CNSS_DRIVER_EVENT_SERVER_ARRIVE,
 	CNSS_DRIVER_EVENT_SERVER_EXIT,
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index 795b905..9d1fbf9 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -16,6 +16,7 @@
 #include <linux/msi.h>
 #include <linux/of.h>
 #include <linux/pm_runtime.h>
+#include <linux/memblock.h>
 
 #include "main.h"
 #include "debug.h"
@@ -33,13 +34,11 @@
 
 #define PCI_BAR_NUM			0
 
-#ifdef CONFIG_ARM_LPAE
-#define PCI_DMA_MASK			64
-#else
-#define PCI_DMA_MASK			32
-#endif
+#define PCI_DMA_MASK_32_BIT		32
+#define PCI_DMA_MASK_64_BIT		64
 
 #define MHI_NODE_NAME			"qcom,mhi"
+#define MHI_MSI_NAME			"MHI"
 
 #define MAX_M3_FILE_NAME_LENGTH		13
 #define DEFAULT_M3_FILE_NAME		"m3.bin"
@@ -164,6 +163,14 @@
 
 	pci_priv->pci_link_state = PCI_LINK_UP;
 
+	if (pci_priv->pci_dev->device != QCA6174_DEVICE_ID) {
+		ret = pci_set_power_state(pci_priv->pci_dev, PCI_D0);
+		if (ret) {
+			cnss_pr_err("Failed to set D0, err = %d\n", ret);
+			goto out;
+		}
+	}
+
 	ret = cnss_set_pci_config_space(pci_priv, RESTORE_PCI_CONFIG_SPACE);
 	if (ret)
 		goto out;
@@ -209,7 +216,6 @@
 
 	cnss_pr_err("PCI link down is detected by host driver, schedule recovery!\n");
 
-	cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_NOTIFY_LINK_ERROR);
 	cnss_schedule_recovery(dev, CNSS_REASON_LINK_DOWN);
 
 	return 0;
@@ -324,7 +330,6 @@
 		spin_unlock_irqrestore(&pci_link_down_lock, flags);
 
 		cnss_pr_err("PCI link down, schedule recovery!\n");
-		cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_NOTIFY_LINK_ERROR);
 		if (pci_dev->device == QCA6174_DEVICE_ID)
 			disable_irq(pci_dev->irq);
 		cnss_schedule_recovery(&pci_dev->dev, CNSS_REASON_LINK_DOWN);
@@ -830,8 +835,8 @@
 	.total_vectors = 32,
 	.total_users = 4,
 	.users = (struct cnss_msi_user[]) {
-		{ .name = "MHI", .num_vectors = 2, .base_vector = 0 },
-		{ .name = "CE", .num_vectors = 11, .base_vector = 2 },
+		{ .name = "MHI", .num_vectors = 3, .base_vector = 0 },
+		{ .name = "CE", .num_vectors = 10, .base_vector = 3 },
 		{ .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
 		{ .name = "DP", .num_vectors = 18, .base_vector = 14 },
 	},
@@ -975,6 +980,7 @@
 	int ret = 0;
 	struct pci_dev *pci_dev = pci_priv->pci_dev;
 	u16 device_id;
+	u32 pci_dma_mask = PCI_DMA_MASK_64_BIT;
 
 	pci_read_config_word(pci_dev, PCI_DEVICE_ID, &device_id);
 	if (device_id != pci_priv->pci_device_id->device)  {
@@ -1002,17 +1008,20 @@
 		goto disable_device;
 	}
 
-	ret = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(PCI_DMA_MASK));
+	if (device_id == QCA6174_DEVICE_ID)
+		pci_dma_mask = PCI_DMA_MASK_32_BIT;
+
+	ret = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(pci_dma_mask));
 	if (ret) {
 		cnss_pr_err("Failed to set PCI DMA mask (%d), err = %d\n",
-			    ret, PCI_DMA_MASK);
+			    ret, pci_dma_mask);
 		goto release_region;
 	}
 
-	ret = pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(PCI_DMA_MASK));
+	ret = pci_set_consistent_dma_mask(pci_dev, DMA_BIT_MASK(pci_dma_mask));
 	if (ret) {
 		cnss_pr_err("Failed to set PCI consistent DMA mask (%d), err = %d\n",
-			    ret, PCI_DMA_MASK);
+			    ret, pci_dma_mask);
 		goto release_region;
 	}
 
@@ -1047,17 +1056,23 @@
 
 	pci_clear_master(pci_dev);
 	pci_release_region(pci_dev, PCI_BAR_NUM);
-	pci_disable_device(pci_dev);
+	if (pci_is_enabled(pci_dev))
+		pci_disable_device(pci_dev);
 }
 
-static int cnss_mhi_pm_runtime_get(struct pci_dev *pci_dev)
+static int cnss_mhi_pm_runtime_get(struct mhi_controller *mhi_ctrl, void *priv)
 {
-	return pm_runtime_get(&pci_dev->dev);
+	struct cnss_pci_data *pci_priv = priv;
+
+	return pm_runtime_get(&pci_priv->pci_dev->dev);
 }
 
-static void cnss_mhi_pm_runtime_put_noidle(struct pci_dev *pci_dev)
+static void cnss_mhi_pm_runtime_put_noidle(struct mhi_controller *mhi_ctrl,
+					   void *priv)
 {
-	pm_runtime_put_noidle(&pci_dev->dev);
+	struct cnss_pci_data *pci_priv = priv;
+
+	pm_runtime_put_noidle(&pci_priv->pci_dev->dev);
 }
 
 static char *cnss_mhi_state_to_str(enum cnss_mhi_state mhi_state)
@@ -1071,76 +1086,85 @@
 		return "POWER_ON";
 	case CNSS_MHI_POWER_OFF:
 		return "POWER_OFF";
+	case CNSS_MHI_FORCE_POWER_OFF:
+		return "FORCE_POWER_OFF";
 	case CNSS_MHI_SUSPEND:
 		return "SUSPEND";
 	case CNSS_MHI_RESUME:
 		return "RESUME";
 	case CNSS_MHI_TRIGGER_RDDM:
 		return "TRIGGER_RDDM";
-	case CNSS_MHI_RDDM:
-		return "RDDM";
-	case CNSS_MHI_RDDM_KERNEL_PANIC:
-		return "RDDM_KERNEL_PANIC";
-	case CNSS_MHI_NOTIFY_LINK_ERROR:
-		return "NOTIFY_LINK_ERROR";
 	default:
 		return "UNKNOWN";
 	}
 };
 
-static void *cnss_pci_collect_dump_seg(struct cnss_pci_data *pci_priv,
-				       enum mhi_rddm_segment type,
-				       void *start_addr)
+void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic)
 {
-	int count;
-	struct scatterlist *sg_list, *s;
-	unsigned int i;
 	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
 	struct cnss_dump_data *dump_data =
 		&plat_priv->ramdump_info_v2.dump_data;
-	struct cnss_dump_seg *dump_seg = start_addr;
+	struct cnss_dump_seg *dump_seg =
+		plat_priv->ramdump_info_v2.dump_data_vaddr;
+	struct image_info *fw_image, *rddm_image;
+	struct cnss_fw_mem *fw_mem = &plat_priv->fw_mem;
+	int ret, i;
 
-	count = mhi_xfer_rddm(&pci_priv->mhi_dev, type, &sg_list);
-	if (count <= 0 || !sg_list) {
-		cnss_pr_err("Invalid dump_seg for type %u, count %u, sg_list %pK\n",
-			    type, count, sg_list);
-		return start_addr;
+	ret = mhi_download_rddm_img(pci_priv->mhi_ctrl, in_panic);
+	if (ret) {
+		cnss_pr_err("Failed to download RDDM image, err = %d\n", ret);
+		return;
 	}
 
-	cnss_pr_dbg("Collect dump seg: type %u, nentries %d\n", type, count);
+	fw_image = pci_priv->mhi_ctrl->fbc_image;
+	rddm_image = pci_priv->mhi_ctrl->rddm_image;
+	dump_data->nentries = 0;
 
-	for_each_sg(sg_list, s, count, i) {
-		dump_seg->address = sg_dma_address(s);
-		dump_seg->v_address = sg_virt(s);
-		dump_seg->size = s->length;
-		dump_seg->type = type;
+	cnss_pr_dbg("Collect FW image dump segment, nentries %d\n",
+		    fw_image->entries);
+
+	for (i = 0; i < fw_image->entries; i++) {
+		dump_seg->address = fw_image->mhi_buf[i].dma_addr;
+		dump_seg->v_address = fw_image->mhi_buf[i].buf;
+		dump_seg->size = fw_image->mhi_buf[i].len;
+		dump_seg->type = CNSS_FW_IMAGE;
 		cnss_pr_dbg("seg-%d: address 0x%lx, v_address %pK, size 0x%lx\n",
 			    i, dump_seg->address,
 			    dump_seg->v_address, dump_seg->size);
 		dump_seg++;
 	}
 
-	dump_data->nentries += count;
+	dump_data->nentries += fw_image->entries;
 
-	return dump_seg;
-}
+	cnss_pr_dbg("Collect RDDM image dump segment, nentries %d\n",
+		    rddm_image->entries);
 
-void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv)
-{
-	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
-	struct cnss_dump_data *dump_data =
-		&plat_priv->ramdump_info_v2.dump_data;
-	void *start_addr, *end_addr;
+	for (i = 0; i < rddm_image->entries; i++) {
+		dump_seg->address = rddm_image->mhi_buf[i].dma_addr;
+		dump_seg->v_address = rddm_image->mhi_buf[i].buf;
+		dump_seg->size = rddm_image->mhi_buf[i].len;
+		dump_seg->type = CNSS_FW_RDDM;
+		cnss_pr_dbg("seg-%d: address 0x%lx, v_address %pK, size 0x%lx\n",
+			    i, dump_seg->address,
+			    dump_seg->v_address, dump_seg->size);
+		dump_seg++;
+	}
 
-	dump_data->nentries = 0;
+	dump_data->nentries += rddm_image->entries;
 
-	start_addr = plat_priv->ramdump_info_v2.dump_data_vaddr;
-	end_addr = cnss_pci_collect_dump_seg(pci_priv,
-					     MHI_RDDM_FW_SEGMENT, start_addr);
+	if (fw_mem->pa && fw_mem->va && fw_mem->size) {
+		cnss_pr_dbg("Collect remote heap dump segment, nentries 1\n");
 
-	start_addr = end_addr;
-	end_addr = cnss_pci_collect_dump_seg(pci_priv,
-					     MHI_RDDM_RD_SEGMENT, start_addr);
+		dump_seg->address = fw_mem->pa;
+		dump_seg->v_address = fw_mem->va;
+		dump_seg->size = fw_mem->size;
+		dump_seg->type = CNSS_FW_REMOTE_HEAP;
+		cnss_pr_dbg("seg-0: address 0x%lx, v_address %pK, size 0x%lx\n",
+			    dump_seg->address, dump_seg->v_address,
+			    dump_seg->size);
+		dump_seg++;
+		dump_data->nentries++;
+	}
 
 	if (dump_data->nentries > 0)
 		plat_priv->ramdump_info_v2.dump_data_valid = true;
@@ -1154,65 +1178,148 @@
 	plat_priv->ramdump_info_v2.dump_data_valid = false;
 }
 
-static void cnss_mhi_notify_status(enum MHI_CB_REASON reason, void *priv)
+static int cnss_mhi_link_status(struct mhi_controller *mhi_ctrl, void *priv)
 {
 	struct cnss_pci_data *pci_priv = priv;
-	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
-	enum cnss_recovery_reason cnss_reason = CNSS_REASON_RDDM;
+	u16 device_id;
 
-	if (!pci_priv)
+	if (!pci_priv) {
+		cnss_pr_err("pci_priv is NULL\n");
+		return -EINVAL;
+	}
+
+	pci_read_config_word(pci_priv->pci_dev, PCI_DEVICE_ID, &device_id);
+	if (device_id != pci_priv->device_id)  {
+		cnss_pr_err("PCI device ID mismatch, link possibly down, current read ID: 0x%x, record ID: 0x%x\n",
+			    device_id, pci_priv->device_id);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void cnss_mhi_notify_status(struct mhi_controller *mhi_ctrl, void *priv,
+				   enum MHI_CB reason)
+{
+	struct cnss_pci_data *pci_priv = priv;
+	struct cnss_plat_data *plat_priv;
+	enum cnss_recovery_reason cnss_reason;
+
+	if (!pci_priv) {
+		cnss_pr_err("pci_priv is NULL");
 		return;
+	}
+
+	plat_priv = pci_priv->plat_priv;
 
 	cnss_pr_dbg("MHI status cb is called with reason %d\n", reason);
 
+	if (plat_priv->driver_ops && plat_priv->driver_ops->update_status)
+		plat_priv->driver_ops->update_status(pci_priv->pci_dev,
+						     CNSS_FW_DOWN);
+
+	switch (reason) {
+	case MHI_CB_EE_RDDM:
+		cnss_reason = CNSS_REASON_RDDM;
+		break;
+	default:
+		cnss_pr_err("Unsupported MHI status cb reason: %d\n", reason);
+		return;
+	}
+
 	set_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state);
 	del_timer(&plat_priv->fw_boot_timer);
 
-	if (reason == MHI_CB_SYS_ERROR)
-		cnss_reason = CNSS_REASON_TIMEOUT;
-
 	cnss_schedule_recovery(&pci_priv->pci_dev->dev,
 			       cnss_reason);
 }
 
+static int cnss_pci_get_mhi_msi(struct cnss_pci_data *pci_priv)
+{
+	int ret, num_vectors, i;
+	u32 user_base_data, base_vector;
+	int *irq;
+
+	ret = cnss_get_user_msi_assignment(&pci_priv->pci_dev->dev,
+					   MHI_MSI_NAME, &num_vectors,
+					   &user_base_data, &base_vector);
+	if (ret)
+		return ret;
+
+	cnss_pr_dbg("Number of assigned MSI for MHI is %d, base vector is %d\n",
+		    num_vectors, base_vector);
+
+	irq = kcalloc(num_vectors, sizeof(int), GFP_KERNEL);
+	if (!irq)
+		return -ENOMEM;
+
+	for (i = 0; i < num_vectors; i++)
+		irq[i] = cnss_get_msi_irq(&pci_priv->pci_dev->dev,
+					  base_vector + i);
+
+	pci_priv->mhi_ctrl->irq = irq;
+	pci_priv->mhi_ctrl->msi_allocated = num_vectors;
+
+	return 0;
+}
+
 static int cnss_pci_register_mhi(struct cnss_pci_data *pci_priv)
 {
 	int ret = 0;
+	struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
 	struct pci_dev *pci_dev = pci_priv->pci_dev;
-	struct mhi_device *mhi_dev = &pci_priv->mhi_dev;
+	struct mhi_controller *mhi_ctrl;
 
-	mhi_dev->dev = &pci_priv->plat_priv->plat_dev->dev;
-	mhi_dev->pci_dev = pci_dev;
-
-	mhi_dev->resources[0].start = (resource_size_t)pci_priv->bar;
-	mhi_dev->resources[0].end = (resource_size_t)pci_priv->bar +
-		pci_resource_len(pci_dev, PCI_BAR_NUM);
-	mhi_dev->resources[0].flags =
-		pci_resource_flags(pci_dev, PCI_BAR_NUM);
-	mhi_dev->resources[0].name = "BAR";
-	cnss_pr_dbg("BAR start is %pa, BAR end is %pa\n",
-		    &mhi_dev->resources[0].start, &mhi_dev->resources[0].end);
-
-	if (!mhi_dev->resources[1].start) {
-		mhi_dev->resources[1].start = pci_dev->irq;
-		mhi_dev->resources[1].end = pci_dev->irq + 1;
-		mhi_dev->resources[1].flags = IORESOURCE_IRQ;
-		mhi_dev->resources[1].name = "IRQ";
+	mhi_ctrl = mhi_alloc_controller(0);
+	if (!mhi_ctrl) {
+		cnss_pr_err("Invalid MHI controller context\n");
+		return -EINVAL;
 	}
-	cnss_pr_dbg("IRQ start is %pa, IRQ end is %pa\n",
-		    &mhi_dev->resources[1].start, &mhi_dev->resources[1].end);
 
-	mhi_dev->pm_runtime_get = cnss_mhi_pm_runtime_get;
-	mhi_dev->pm_runtime_put_noidle = cnss_mhi_pm_runtime_put_noidle;
+	pci_priv->mhi_ctrl = mhi_ctrl;
 
-	mhi_dev->support_rddm = true;
-	mhi_dev->rddm_size = pci_priv->plat_priv->ramdump_info_v2.ramdump_size;
-	mhi_dev->status_cb = cnss_mhi_notify_status;
+	mhi_ctrl->priv_data = pci_priv;
+	mhi_ctrl->dev = &pci_dev->dev;
+	mhi_ctrl->of_node = (&plat_priv->plat_dev->dev)->of_node;
+	mhi_ctrl->dev_id = pci_priv->device_id;
+	mhi_ctrl->domain = pci_domain_nr(pci_dev->bus);
+	mhi_ctrl->bus = pci_dev->bus->number;
+	mhi_ctrl->slot = PCI_SLOT(pci_dev->devfn);
 
-	ret = mhi_register_device(mhi_dev, MHI_NODE_NAME, pci_priv);
+	mhi_ctrl->regs = pci_priv->bar;
+	cnss_pr_dbg("BAR starts at %pa\n",
+		    &pci_resource_start(pci_priv->pci_dev, PCI_BAR_NUM));
+
+	ret = cnss_pci_get_mhi_msi(pci_priv);
 	if (ret) {
-		cnss_pr_err("Failed to register as MHI device, err = %d\n",
-			    ret);
+		cnss_pr_err("Failed to get MSI for MHI\n");
+		return ret;
+	}
+
+	if (pci_priv->smmu_s1_enable) {
+		mhi_ctrl->iova_start = pci_priv->smmu_iova_start;
+		mhi_ctrl->iova_stop = pci_priv->smmu_iova_start +
+					pci_priv->smmu_iova_len;
+	} else {
+		mhi_ctrl->iova_start = memblock_start_of_DRAM();
+		mhi_ctrl->iova_stop = memblock_end_of_DRAM();
+	}
+
+	mhi_ctrl->link_status = cnss_mhi_link_status;
+	mhi_ctrl->status_cb = cnss_mhi_notify_status;
+	mhi_ctrl->runtime_get = cnss_mhi_pm_runtime_get;
+	mhi_ctrl->runtime_put = cnss_mhi_pm_runtime_put_noidle;
+
+	mhi_ctrl->rddm_size = pci_priv->plat_priv->ramdump_info_v2.ramdump_size;
+
+	mhi_ctrl->log_buf = ipc_log_context_create(CNSS_IPC_LOG_PAGES,
+						   "cnss-mhi", 0);
+	if (!mhi_ctrl->log_buf)
+		cnss_pr_err("Unable to create CNSS MHI IPC log context\n");
+
+	ret = of_register_mhi_controller(mhi_ctrl);
+	if (ret) {
+		cnss_pr_err("Failed to register to MHI bus, err = %d\n", ret);
 		return ret;
 	}
 
@@ -1221,35 +1328,11 @@
 
 static void cnss_pci_unregister_mhi(struct cnss_pci_data *pci_priv)
 {
-}
+	struct mhi_controller *mhi_ctrl = pci_priv->mhi_ctrl;
 
-static enum mhi_dev_ctrl cnss_to_mhi_dev_state(enum cnss_mhi_state state)
-{
-	switch (state) {
-	case CNSS_MHI_INIT:
-		return MHI_DEV_CTRL_INIT;
-	case CNSS_MHI_DEINIT:
-		return MHI_DEV_CTRL_DE_INIT;
-	case CNSS_MHI_POWER_ON:
-		return MHI_DEV_CTRL_POWER_ON;
-	case CNSS_MHI_POWER_OFF:
-		return MHI_DEV_CTRL_POWER_OFF;
-	case CNSS_MHI_SUSPEND:
-		return MHI_DEV_CTRL_SUSPEND;
-	case CNSS_MHI_RESUME:
-		return MHI_DEV_CTRL_RESUME;
-	case CNSS_MHI_TRIGGER_RDDM:
-		return MHI_DEV_CTRL_TRIGGER_RDDM;
-	case CNSS_MHI_RDDM:
-		return MHI_DEV_CTRL_RDDM;
-	case CNSS_MHI_RDDM_KERNEL_PANIC:
-		return MHI_DEV_CTRL_RDDM_KERNEL_PANIC;
-	case CNSS_MHI_NOTIFY_LINK_ERROR:
-		return MHI_DEV_CTRL_NOTIFY_LINK_ERROR;
-	default:
-		cnss_pr_err("Unknown CNSS MHI state (%d)\n", state);
-		return -EINVAL;
-	}
+	mhi_unregister_mhi_controller(mhi_ctrl);
+	ipc_log_context_destroy(mhi_ctrl->log_buf);
+	kfree(mhi_ctrl->irq);
 }
 
 static int cnss_pci_check_mhi_state_bit(struct cnss_pci_data *pci_priv,
@@ -1266,6 +1349,10 @@
 		    !test_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state))
 			return 0;
 		break;
+	case CNSS_MHI_FORCE_POWER_OFF:
+		if (test_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state))
+			return 0;
+		break;
 	case CNSS_MHI_POWER_OFF:
 	case CNSS_MHI_SUSPEND:
 		if (test_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state) &&
@@ -1277,9 +1364,6 @@
 			return 0;
 		break;
 	case CNSS_MHI_TRIGGER_RDDM:
-	case CNSS_MHI_RDDM:
-	case CNSS_MHI_RDDM_KERNEL_PANIC:
-	case CNSS_MHI_NOTIFY_LINK_ERROR:
 		return 0;
 	default:
 		cnss_pr_err("Unhandled MHI state: %s(%d)\n",
@@ -1307,6 +1391,7 @@
 		set_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state);
 		break;
 	case CNSS_MHI_POWER_OFF:
+	case CNSS_MHI_FORCE_POWER_OFF:
 		clear_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state);
 		break;
 	case CNSS_MHI_SUSPEND:
@@ -1316,9 +1401,6 @@
 		clear_bit(CNSS_MHI_SUSPEND, &pci_priv->mhi_state);
 		break;
 	case CNSS_MHI_TRIGGER_RDDM:
-	case CNSS_MHI_RDDM:
-	case CNSS_MHI_RDDM_KERNEL_PANIC:
-	case CNSS_MHI_NOTIFY_LINK_ERROR:
 		break;
 	default:
 		cnss_pr_err("Unhandled MHI state (%d)\n", mhi_state);
@@ -1329,7 +1411,6 @@
 			   enum cnss_mhi_state mhi_state)
 {
 	int ret = 0;
-	enum mhi_dev_ctrl mhi_dev_state = cnss_to_mhi_dev_state(mhi_state);
 
 	if (!pci_priv) {
 		cnss_pr_err("pci_priv is NULL!\n");
@@ -1339,8 +1420,8 @@
 	if (pci_priv->device_id == QCA6174_DEVICE_ID)
 		return 0;
 
-	if (mhi_dev_state < 0) {
-		cnss_pr_err("Invalid MHI DEV state (%d)\n", mhi_dev_state);
+	if (mhi_state < 0) {
+		cnss_pr_err("Invalid MHI state (%d)\n", mhi_state);
 		return -EINVAL;
 	}
 
@@ -1350,16 +1431,50 @@
 
 	cnss_pr_dbg("Setting MHI state: %s(%d)\n",
 		    cnss_mhi_state_to_str(mhi_state), mhi_state);
-	ret = mhi_pm_control_device(&pci_priv->mhi_dev, mhi_dev_state);
-	if (ret) {
-		cnss_pr_err("Failed to set MHI state: %s(%d)\n",
-			    cnss_mhi_state_to_str(mhi_state), mhi_state);
-		goto out;
+
+	switch (mhi_state) {
+	case CNSS_MHI_INIT:
+		ret = mhi_prepare_for_power_up(pci_priv->mhi_ctrl);
+		break;
+	case CNSS_MHI_DEINIT:
+		mhi_unprepare_after_power_down(pci_priv->mhi_ctrl);
+		ret = 0;
+		break;
+	case CNSS_MHI_POWER_ON:
+		ret = mhi_sync_power_up(pci_priv->mhi_ctrl);
+		break;
+	case CNSS_MHI_POWER_OFF:
+		mhi_power_down(pci_priv->mhi_ctrl, true);
+		ret = 0;
+		break;
+	case CNSS_MHI_FORCE_POWER_OFF:
+		mhi_power_down(pci_priv->mhi_ctrl, false);
+		ret = 0;
+		break;
+	case CNSS_MHI_SUSPEND:
+		ret = mhi_pm_suspend(pci_priv->mhi_ctrl);
+		break;
+	case CNSS_MHI_RESUME:
+		ret = mhi_pm_resume(pci_priv->mhi_ctrl);
+		break;
+	case CNSS_MHI_TRIGGER_RDDM:
+		ret = mhi_force_rddm_mode(pci_priv->mhi_ctrl);
+		break;
+	default:
+		cnss_pr_err("Unhandled MHI state (%d)\n", mhi_state);
+		ret = -EINVAL;
 	}
 
+	if (ret)
+		goto out;
+
 	cnss_pci_set_mhi_state_bit(pci_priv, mhi_state);
 
+	return 0;
+
 out:
+	cnss_pr_err("Failed to set MHI state: %s(%d)\n",
+		    cnss_mhi_state_to_str(mhi_state), mhi_state);
 	return ret;
 }
 
@@ -1404,7 +1519,10 @@
 	plat_priv = pci_priv->plat_priv;
 
 	cnss_pci_set_mhi_state_bit(pci_priv, CNSS_MHI_RESUME);
-	cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_POWER_OFF);
+	if (!pci_priv->pci_link_down_ind)
+		cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_POWER_OFF);
+	else
+		cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_FORCE_POWER_OFF);
 
 	if (plat_priv->ramdump_info_v2.dump_data_valid ||
 	    test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state))
@@ -1424,20 +1542,6 @@
 	cnss_pr_dbg("PCI is probing, vendor ID: 0x%x, device ID: 0x%x\n",
 		    id->vendor, pci_dev->device);
 
-	switch (pci_dev->device) {
-	case QCA6290_EMULATION_DEVICE_ID:
-	case QCA6290_DEVICE_ID:
-		if (!mhi_is_device_ready(&plat_priv->plat_dev->dev,
-					 MHI_NODE_NAME)) {
-			cnss_pr_err("MHI driver is not ready, defer PCI probe!\n");
-			ret = -EPROBE_DEFER;
-			goto out;
-		}
-		break;
-	default:
-		break;
-	}
-
 	pci_priv = devm_kzalloc(&pci_dev->dev, sizeof(*pci_priv),
 				GFP_KERNEL);
 	if (!pci_priv) {
diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h
index 4a82998..4b2f6bc 100644
--- a/drivers/net/wireless/cnss2/pci.h
+++ b/drivers/net/wireless/cnss2/pci.h
@@ -15,7 +15,7 @@
 
 #include <asm/dma-iommu.h>
 #include <linux/iommu.h>
-#include <linux/msm_mhi.h>
+#include <linux/mhi.h>
 #include <linux/msm_pcie.h>
 #include <linux/pci.h>
 
@@ -34,14 +34,13 @@
 enum cnss_mhi_state {
 	CNSS_MHI_INIT,
 	CNSS_MHI_DEINIT,
+	CNSS_MHI_POWER_ON,
+	CNSS_MHI_POWER_OFF,
+	CNSS_MHI_FORCE_POWER_OFF,
 	CNSS_MHI_SUSPEND,
 	CNSS_MHI_RESUME,
-	CNSS_MHI_POWER_OFF,
-	CNSS_MHI_POWER_ON,
 	CNSS_MHI_TRIGGER_RDDM,
 	CNSS_MHI_RDDM,
-	CNSS_MHI_RDDM_KERNEL_PANIC,
-	CNSS_MHI_NOTIFY_LINK_ERROR,
 };
 
 struct cnss_msi_user {
@@ -76,7 +75,7 @@
 	void __iomem *bar;
 	struct cnss_msi_config *msi_config;
 	u32 msi_ep_base_data;
-	struct mhi_device mhi_dev;
+	struct mhi_controller *mhi_ctrl;
 	unsigned long mhi_state;
 };
 
@@ -137,7 +136,7 @@
 			   enum cnss_mhi_state state);
 int cnss_pci_start_mhi(struct cnss_pci_data *pci_priv);
 void cnss_pci_stop_mhi(struct cnss_pci_data *pci_priv);
-void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv);
+void cnss_pci_collect_dump_info(struct cnss_pci_data *pci_priv, bool in_panic);
 void cnss_pci_clear_dump_info(struct cnss_pci_data *pci_priv);
 int cnss_pm_request_resume(struct cnss_pci_data *pci_priv);
 
diff --git a/drivers/net/wireless/cnss_crypto/Makefile b/drivers/net/wireless/cnss_crypto/Makefile
new file mode 100644
index 0000000..cfe0285
--- /dev/null
+++ b/drivers/net/wireless/cnss_crypto/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_CNSS_CRYPTO) += cnss_secif.o
diff --git a/drivers/net/wireless/cnss_crypto/cnss_secif.c b/drivers/net/wireless/cnss_crypto/cnss_secif.c
new file mode 100644
index 0000000..690809e
--- /dev/null
+++ b/drivers/net/wireless/cnss_crypto/cnss_secif.c
@@ -0,0 +1,170 @@
+/* Copyright (c) 2011-2013, 2015, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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/export.h>
+#include <linux/qcomwlan_secif.h>
+#include <crypto/aes.h>
+
+/* APIs for calling crypto routines from kernel
+ */
+struct crypto_ahash *wcnss_wlan_crypto_alloc_ahash(const char *alg_name,
+						   u32 type, u32 mask)
+{
+	return crypto_alloc_ahash(alg_name, type, mask);
+}
+EXPORT_SYMBOL(wcnss_wlan_crypto_alloc_ahash);
+
+int wcnss_wlan_crypto_ahash_digest(struct ahash_request *req)
+{
+	return crypto_ahash_digest(req);
+}
+EXPORT_SYMBOL(wcnss_wlan_crypto_ahash_digest);
+
+void wcnss_wlan_crypto_free_ahash(struct crypto_ahash *tfm)
+{
+	crypto_free_ahash(tfm);
+}
+EXPORT_SYMBOL(wcnss_wlan_crypto_free_ahash);
+
+int wcnss_wlan_crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
+				   unsigned int keylen)
+{
+	return crypto_ahash_setkey(tfm, key, keylen);
+}
+EXPORT_SYMBOL(wcnss_wlan_crypto_ahash_setkey);
+
+void wcnss_wlan_ablkcipher_request_free(struct ablkcipher_request *req)
+{
+	ablkcipher_request_free(req);
+}
+EXPORT_SYMBOL(wcnss_wlan_ablkcipher_request_free);
+
+void wcnss_wlan_crypto_free_ablkcipher(struct crypto_ablkcipher *tfm)
+{
+	crypto_free_ablkcipher(tfm);
+}
+EXPORT_SYMBOL(wcnss_wlan_crypto_free_ablkcipher);
+
+void wcnss_wlan_crypto_free_cipher(struct crypto_cipher *tfm)
+{
+	crypto_free_cipher(tfm);
+}
+EXPORT_SYMBOL(wcnss_wlan_crypto_free_cipher);
+
+struct crypto_cipher *
+wcnss_wlan_crypto_alloc_cipher(const char *alg_name, u32 type, u32 mask)
+{
+	return crypto_alloc_cipher(alg_name, type, mask);
+}
+EXPORT_SYMBOL(wcnss_wlan_crypto_alloc_cipher);
+
+static inline void xor_128(const u8 *a, const u8 *b, u8 *out)
+{
+	u8 i;
+
+	for (i = 0; i < AES_BLOCK_SIZE; i++)
+		out[i] = a[i] ^ b[i];
+}
+
+static inline void leftshift_onebit(const u8 *input, u8 *output)
+{
+	int i, overflow = 0;
+
+	for (i = (AES_BLOCK_SIZE - 1); i >= 0; i--) {
+		output[i] = input[i] << 1;
+		output[i] |= overflow;
+		overflow = (input[i] & 0x80) ? 1 : 0;
+	}
+}
+
+static void generate_subkey(struct crypto_cipher *tfm, u8 *k1, u8 *k2)
+{
+	u8 l[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
+	u8 const_rb[AES_BLOCK_SIZE] = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87};
+	u8 const_zero[AES_BLOCK_SIZE] = {
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+	crypto_cipher_encrypt_one(tfm, l, const_zero);
+
+	if ((l[0] & 0x80) == 0) { /* If MSB(l) = 0, then k1 = l << 1 */
+		leftshift_onebit(l, k1);
+	} else {    /* Else k1 = ( l << 1 ) (+) Rb */
+		leftshift_onebit(l, tmp);
+		xor_128(tmp, const_rb, k1);
+	}
+
+	if ((k1[0] & 0x80) == 0) {
+		leftshift_onebit(k1, k2);
+	} else {
+		leftshift_onebit(k1, tmp);
+		xor_128(tmp, const_rb, k2);
+	}
+}
+
+static inline void padding(u8 *lastb, u8 *pad, u16 length)
+{
+	u8 j;
+
+	/* original last block */
+	for (j = 0; j < AES_BLOCK_SIZE; j++)  {
+		if (j < length)
+			pad[j] = lastb[j];
+		else if (j == length)
+			pad[j] = 0x80;
+		else
+			pad[j] = 0x00;
+	}
+}
+
+void wcnss_wlan_cmac_calc_mic(struct crypto_cipher *tfm, u8 *m,
+			      u16 length, u8 *mac)
+{
+	u8 x[AES_BLOCK_SIZE], y[AES_BLOCK_SIZE];
+	u8 m_last[AES_BLOCK_SIZE], padded[AES_BLOCK_SIZE];
+	u8 k1[AES_KEYSIZE_128], k2[AES_KEYSIZE_128];
+	int cmpBlk;
+	int i, nblocks = (length + 15) / AES_BLOCK_SIZE;
+
+	generate_subkey(tfm, k1, k2);
+
+	if (nblocks == 0) {
+		nblocks = 1;
+		cmpBlk = 0;
+	} else {
+		cmpBlk = ((length % AES_BLOCK_SIZE) == 0) ? 1 : 0;
+	}
+
+	if (cmpBlk) { /* Last block is complete block */
+		xor_128(&m[AES_BLOCK_SIZE * (nblocks - 1)], k1, m_last);
+	} else { /* Last block is not complete block */
+		padding(&m[AES_BLOCK_SIZE * (nblocks - 1)], padded,
+			length % AES_BLOCK_SIZE);
+		xor_128(padded, k2, m_last);
+	}
+
+	for (i = 0; i < AES_BLOCK_SIZE; i++)
+		x[i] = 0;
+
+	for (i = 0; i < (nblocks - 1); i++) {
+		xor_128(x, &m[AES_BLOCK_SIZE * i], y); /* y = Mi (+) x */
+		crypto_cipher_encrypt_one(tfm, x, y); /* x = AES-128(KEY, y) */
+	}
+
+	xor_128(x, m_last, y);
+	crypto_cipher_encrypt_one(tfm, x, y);
+
+	memcpy(mac, x, CMAC_TLEN);
+}
+EXPORT_SYMBOL(wcnss_wlan_cmac_calc_mic);
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c
index 20d48a0..b67a94d 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -63,12 +63,12 @@
 #define PCIE_N_SW_RESET(n)			(PCS_PORT(n) + 0x00)
 #define PCIE_N_POWER_DOWN_CONTROL(n)		(PCS_PORT(n) + 0x04)
 
-#define PCIE_GEN3_COM_INTEGLOOP_GAIN1_MODE0	0x0154
-#define PCIE_GEN3_L0_DRVR_CTRL0			0x080c
-#define PCIE_GEN3_L0_RESET_GEN			0x0890
-#define PCIE_GEN3_L0_BIST_ERR_CNT1_STATUS	0x08a8
-#define PCIE_GEN3_L0_BIST_ERR_CNT2_STATUS	0x08ac
-#define PCIE_GEN3_L0_DEBUG_BUS_STATUS4		0x08bc
+#define PCIE_GEN3_SPCIE_CAP			0x0154
+#define PCIE_GEN3_GEN2_CTRL			0x080c
+#define PCIE_GEN3_RELATED			0x0890
+#define PCIE_GEN3_EQ_CONTROL			0x08a8
+#define PCIE_GEN3_EQ_FB_MODE_DIR_CHANGE		0x08ac
+#define PCIE_GEN3_MISC_CONTROL			0x08bc
 
 #define PCIE20_PARF_SYS_CTRL	     0x00
 #define PCIE20_PARF_PM_CTRL		0x20
@@ -130,7 +130,6 @@
 #define PCIE_IATU_UTAR(n)	(PCIE_IATU_BASE(n) + 0x18)
 
 #define PCIE20_PORT_LINK_CTRL_REG	0x710
-#define PCIE20_GEN3_RELATED_REG	0x890
 #define PCIE20_PIPE_LOOPBACK_CONTROL	0x8b8
 #define LOOPBACK_BASE_ADDR_OFFSET	0x8000
 
@@ -1552,6 +1551,13 @@
 			break;
 		}
 
+		if (((base_sel - 1) >= MSM_PCIE_MAX_RES) ||
+					(!dev->res[base_sel - 1].resource)) {
+			PCIE_DBG_FS(dev, "PCIe: RC%d Resource does not exist\n",
+								dev->rc_idx);
+			break;
+		}
+
 		PCIE_DBG_FS(dev,
 			"base: %s: 0x%pK\nwr_offset: 0x%x\nwr_mask: 0x%x\nwr_value: 0x%x\n",
 			dev->res[base_sel - 1].name,
@@ -1571,6 +1577,13 @@
 
 		break;
 	case MSM_PCIE_DUMP_PCIE_REGISTER_SPACE:
+		if (((base_sel - 1) >= MSM_PCIE_MAX_RES) ||
+					(!dev->res[base_sel - 1].resource)) {
+			PCIE_DBG_FS(dev, "PCIe: RC%d Resource does not exist\n",
+								dev->rc_idx);
+			break;
+		}
+
 		if (!base_sel) {
 			PCIE_DBG_FS(dev, "Invalid base_sel: 0x%x\n", base_sel);
 			break;
@@ -1685,13 +1698,13 @@
 			dev->rc_idx);
 
 		writel_relaxed(0x10000,
-			dev->dm_core + PCIE20_GEN3_RELATED_REG);
+			dev->dm_core + PCIE_GEN3_RELATED);
 		PCIE_DBG_FS(dev,
 			"PCIe: RC%d: 0x%x: 0x%x\n",
 			dev->rc_idx,
-			dbi_base_addr + PCIE20_GEN3_RELATED_REG,
+			dbi_base_addr + PCIE_GEN3_RELATED,
 			readl_relaxed(dev->dm_core +
-				PCIE20_GEN3_RELATED_REG));
+				PCIE_GEN3_RELATED));
 
 		writel_relaxed(0x80000001,
 			dev->dm_core + PCIE20_PIPE_LOOPBACK_CONTROL);
@@ -3694,25 +3707,25 @@
 	PCIE_DBG(dev, "PCIe: RC%d: Setting up Gen3\n", dev->rc_idx);
 
 	msm_pcie_write_reg_field(dev->dm_core,
-		PCIE_GEN3_L0_DRVR_CTRL0, 0x1ff00, BIT(0));
+		PCIE_GEN3_GEN2_CTRL, 0x1ff00, BIT(0));
 
 	msm_pcie_write_reg(dev->dm_core,
-		PCIE_GEN3_L0_BIST_ERR_CNT2_STATUS,
+		PCIE_GEN3_EQ_FB_MODE_DIR_CHANGE,
 		(0x05 << 14) | (0x05 << 10) | (0x0d <<  5));
 
-	msm_pcie_write_mask(dev->dm_core +
-		PCIE_GEN3_L0_BIST_ERR_CNT1_STATUS, BIT(4), 0);
+	msm_pcie_write_reg(dev->dm_core,
+		PCIE_GEN3_EQ_CONTROL, 0x20);
 
 	msm_pcie_write_mask(dev->dm_core +
-		PCIE_GEN3_L0_RESET_GEN, BIT(0), 0);
+		PCIE_GEN3_RELATED, BIT(0), 0);
 
 	/* configure PCIe preset */
 	msm_pcie_write_reg(dev->dm_core,
-		PCIE_GEN3_L0_DEBUG_BUS_STATUS4, 1);
+		PCIE_GEN3_MISC_CONTROL, 1);
 	msm_pcie_write_reg(dev->dm_core,
-		PCIE_GEN3_COM_INTEGLOOP_GAIN1_MODE0, 0x77777777);
+		PCIE_GEN3_SPCIE_CAP, 0x77777777);
 	msm_pcie_write_reg(dev->dm_core,
-		PCIE_GEN3_L0_DEBUG_BUS_STATUS4, 1);
+		PCIE_GEN3_MISC_CONTROL, 1);
 
 	msm_pcie_write_reg_field(dev->dm_core,
 		PCIE20_CAP + PCI_EXP_LNKCTL2,
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 9e1c8d2..f51ab9e 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -30,6 +30,7 @@
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
+#include <linux/syscore_ops.h>
 #include <linux/reboot.h>
 #include <linux/pm.h>
 #include <linux/log2.h>
@@ -74,6 +75,8 @@
 	void __iomem *pdc_regs;
 };
 
+static struct msm_pinctrl *msm_pinctrl_data;
+
 static int msm_get_groups_count(struct pinctrl_dev *pctldev)
 {
 	struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
@@ -1520,6 +1523,52 @@
 		}
 }
 
+#ifdef CONFIG_PM
+static int msm_pinctrl_suspend(void)
+{
+	return 0;
+}
+
+static void msm_pinctrl_resume(void)
+{
+	int i, irq;
+	u32 val;
+	unsigned long flags;
+	struct irq_desc *desc;
+	const struct msm_pingroup *g;
+	const char *name = "null";
+	struct msm_pinctrl *pctrl = msm_pinctrl_data;
+
+	if (!msm_show_resume_irq_mask)
+		return;
+
+	spin_lock_irqsave(&pctrl->lock, flags);
+	for_each_set_bit(i, pctrl->enabled_irqs, pctrl->chip.ngpio) {
+		g = &pctrl->soc->groups[i];
+		val = readl_relaxed(pctrl->regs + g->intr_status_reg);
+		if (val & BIT(g->intr_status_bit)) {
+			irq = irq_find_mapping(pctrl->chip.irqdomain, i);
+			desc = irq_to_desc(irq);
+			if (desc == NULL)
+				name = "stray irq";
+			else if (desc->action && desc->action->name)
+				name = desc->action->name;
+
+			pr_warn("%s: %d triggered %s\n", __func__, irq, name);
+		}
+	}
+	spin_unlock_irqrestore(&pctrl->lock, flags);
+}
+#else
+#define msm_pinctrl_suspend NULL
+#define msm_pinctrl_resume NULL
+#endif
+
+static struct syscore_ops msm_pinctrl_pm_ops = {
+	.suspend = msm_pinctrl_suspend,
+	.resume = msm_pinctrl_resume,
+};
+
 int msm_pinctrl_probe(struct platform_device *pdev,
 		      const struct msm_pinctrl_soc_data *soc_data)
 {
@@ -1527,7 +1576,8 @@
 	struct resource *res;
 	int ret;
 
-	pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
+	msm_pinctrl_data = pctrl = devm_kzalloc(&pdev->dev,
+				sizeof(*pctrl), GFP_KERNEL);
 	if (!pctrl) {
 		dev_err(&pdev->dev, "Can't allocate msm_pinctrl\n");
 		return -ENOMEM;
@@ -1570,6 +1620,7 @@
 
 	platform_set_drvdata(pdev, pctrl);
 
+	register_syscore_ops(&msm_pinctrl_pm_ops);
 	dev_dbg(&pdev->dev, "Probed Qualcomm pinctrl driver\n");
 
 	return 0;
@@ -1583,6 +1634,7 @@
 	gpiochip_remove(&pctrl->chip);
 
 	unregister_restart_handler(&pctrl->restart_nb);
+	unregister_syscore_ops(&msm_pinctrl_pm_ops);
 
 	return 0;
 }
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.h b/drivers/pinctrl/qcom/pinctrl-msm.h
index 9fc6660..b8185ae 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.h
+++ b/drivers/pinctrl/qcom/pinctrl-msm.h
@@ -174,4 +174,10 @@
 		      const struct msm_pinctrl_soc_data *soc_data);
 int msm_pinctrl_remove(struct platform_device *pdev);
 
+#ifdef CONFIG_QCOM_SHOW_RESUME_IRQ
+extern int msm_show_resume_irq_mask;
+#else
+#define msm_show_resume_irq_mask 0
+#endif
+
 #endif
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm670.c b/drivers/pinctrl/qcom/pinctrl-sdm670.c
index 37a6199..196559c 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm670.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm670.c
@@ -1586,7 +1586,7 @@
 	[154] = SDC_QDSD_PINGROUP(sdc2_clk, 0x9a000, 14, 6),
 	[155] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x9a000, 11, 3),
 	[156] = SDC_QDSD_PINGROUP(sdc2_data, 0x9a000, 9, 0),
-	[157] = UFS_RESET(ufs_reset, 0x9f000),
+	[157] = UFS_RESET(ufs_reset, 0x99d000),
 };
 static struct msm_dir_conn sdm670_dir_conn[] = {
 	{1, 510},
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
index db6f689..4558530 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
@@ -526,12 +526,14 @@
 		ep_pcie_write_reg(dev->parf, PCIE20_PARF_DEVICE_TYPE, 0x0);
 
 		/* adjust DBI base address */
-		if (dev->dbi_base_reg)
-			writel_relaxed(0x3FFFE000,
-				dev->parf + dev->dbi_base_reg);
-		else
-			writel_relaxed(0x3FFFE000,
-				dev->parf + PCIE20_PARF_DBI_BASE_ADDR);
+		if (dev->phy_rev < 6) {
+			if (dev->dbi_base_reg)
+				writel_relaxed(0x3FFFE000,
+					dev->parf + dev->dbi_base_reg);
+			else
+				writel_relaxed(0x3FFFE000,
+					dev->parf + PCIE20_PARF_DBI_BASE_ADDR);
+		}
 
 		/* Configure PCIe core to support 1GB aperture */
 		if (dev->slv_space_reg)
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index b99435d..fdcf44d 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -294,6 +294,46 @@
 	return dest;
 }
 
+int ipa_smmu_store_sgt(struct sg_table **out_ch_ptr,
+	struct sg_table *in_sgt_ptr)
+{
+	unsigned int nents;
+
+	if (in_sgt_ptr != NULL) {
+		*out_ch_ptr = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
+		if (*out_ch_ptr == NULL)
+			return -ENOMEM;
+
+		nents = in_sgt_ptr->nents;
+
+		(*out_ch_ptr)->sgl =
+			kcalloc(nents, sizeof(struct scatterlist),
+				GFP_KERNEL);
+		if ((*out_ch_ptr)->sgl == NULL) {
+			kfree(*out_ch_ptr);
+			*out_ch_ptr = NULL;
+			return -ENOMEM;
+		}
+
+		memcpy((*out_ch_ptr)->sgl, in_sgt_ptr->sgl,
+			nents*sizeof((*out_ch_ptr)->sgl));
+		(*out_ch_ptr)->nents = nents;
+		(*out_ch_ptr)->orig_nents = in_sgt_ptr->orig_nents;
+	}
+	return 0;
+}
+
+int ipa_smmu_free_sgt(struct sg_table **out_sgt_ptr)
+{
+	if (*out_sgt_ptr != NULL) {
+		kfree((*out_sgt_ptr)->sgl);
+		(*out_sgt_ptr)->sgl = NULL;
+		kfree(*out_sgt_ptr);
+		*out_sgt_ptr = NULL;
+	}
+	return 0;
+}
+
 /**
  * ipa_connect() - low-level IPA client connect
  * @in:	[in] input parameters from client
@@ -343,13 +383,13 @@
 EXPORT_SYMBOL(ipa_disconnect);
 
 /**
-* ipa_clear_endpoint_delay() - Clear ep_delay.
-* @clnt_hdl:	[in] IPA client handle
-*
-* Returns:	0 on success, negative on failure
-*
-* Note:		Should not be called from atomic context
-*/
+ * ipa_clear_endpoint_delay() - Clear ep_delay.
+ * @clnt_hdl:	[in] IPA client handle
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:		Should not be called from atomic context
+ */
 int ipa_clear_endpoint_delay(u32 clnt_hdl)
 {
 	int ret;
@@ -361,13 +401,13 @@
 EXPORT_SYMBOL(ipa_clear_endpoint_delay);
 
 /**
-* ipa_reset_endpoint() - reset an endpoint from BAM perspective
-* @clnt_hdl:	[in] IPA client handle
-*
-* Returns:	0 on success, negative on failure
-*
-* Note:		Should not be called from atomic context
-*/
+ * ipa_reset_endpoint() - reset an endpoint from BAM perspective
+ * @clnt_hdl:	[in] IPA client handle
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:		Should not be called from atomic context
+ */
 int ipa_reset_endpoint(u32 clnt_hdl)
 {
 	int ret;
@@ -379,13 +419,13 @@
 EXPORT_SYMBOL(ipa_reset_endpoint);
 
 /**
-* ipa_disable_endpoint() - Disable an endpoint from IPA perspective
-* @clnt_hdl:	[in] IPA client handle
-*
-* Returns:	0 on success, negative on failure
-*
-* Note:		Should not be called from atomic context
-*/
+ * ipa_disable_endpoint() - Disable an endpoint from IPA perspective
+ * @clnt_hdl:	[in] IPA client handle
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:		Should not be called from atomic context
+ */
 int ipa_disable_endpoint(u32 clnt_hdl)
 {
 	int ret;
@@ -439,14 +479,14 @@
 EXPORT_SYMBOL(ipa_cfg_ep_nat);
 
 /**
-* ipa_cfg_ep_conn_track() - IPA end-point IPv6CT configuration
-* @clnt_hdl:		[in] opaque client handle assigned by IPA to client
-* @ep_conn_track:	[in] IPA IPv6CT end-point configuration params
-*
-* Returns:	0 on success, negative on failure
-*
-* Note:	Should not be called from atomic context
-*/
+ * ipa_cfg_ep_conn_track() - IPA end-point IPv6CT configuration
+ * @clnt_hdl:		[in] opaque client handle assigned by IPA to client
+ * @ep_conn_track:	[in] IPA IPv6CT end-point configuration params
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
 int ipa_cfg_ep_conn_track(u32 clnt_hdl,
 	const struct ipa_ep_cfg_conn_track *ep_conn_track)
 {
@@ -700,6 +740,26 @@
 EXPORT_SYMBOL(ipa_add_hdr);
 
 /**
+ * ipa_add_hdr_usr() - add the specified headers to SW and optionally
+ * commit them to IPA HW
+ * @hdrs:		[inout] set of headers to add
+ * @user_only:	[in] indicate rules installed by userspace
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+int ipa_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool user_only)
+{
+	int ret;
+
+	IPA_API_DISPATCH_RETURN(ipa_add_hdr_usr, hdrs, user_only);
+
+	return ret;
+}
+EXPORT_SYMBOL(ipa_add_hdr_usr);
+
+/**
  * ipa_del_hdr() - Remove the specified headers from SW and optionally
  * commit them to IPA HW
  * @hdls:	[inout] set of headers to delete
@@ -739,15 +799,16 @@
  * ipa_reset_hdr() - reset the current header table in SW (does not commit to
  * HW)
  *
+ * @user_only:	[in] indicate delete rules installed by userspace
  * Returns:	0 on success, negative on failure
  *
  * Note:	Should not be called from atomic context
  */
-int ipa_reset_hdr(void)
+int ipa_reset_hdr(bool user_only)
 {
 	int ret;
 
-	IPA_API_DISPATCH_RETURN(ipa_reset_hdr);
+	IPA_API_DISPATCH_RETURN(ipa_reset_hdr, user_only);
 
 	return ret;
 }
@@ -817,16 +878,18 @@
  * ipa_add_hdr_proc_ctx() - add the specified headers to SW
  * and optionally commit them to IPA HW
  * @proc_ctxs:	[inout] set of processing context headers to add
+ * @user_only:	[in] indicate rules installed by userspace
  *
  * Returns:	0 on success, negative on failure
  *
  * Note:	Should not be called from atomic context
  */
-int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs)
+int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs,
+							bool user_only)
 {
 	int ret;
 
-	IPA_API_DISPATCH_RETURN(ipa_add_hdr_proc_ctx, proc_ctxs);
+	IPA_API_DISPATCH_RETURN(ipa_add_hdr_proc_ctx, proc_ctxs, user_only);
 
 	return ret;
 }
@@ -872,6 +935,26 @@
 EXPORT_SYMBOL(ipa_add_rt_rule);
 
 /**
+ * ipa_add_rt_rule_usr() - Add the specified routing rules to SW and optionally
+ * commit to IPA HW
+ * @rules:	[inout] set of routing rules to add
+ * @user_only:	[in] indicate rules installed by userspace
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+int ipa_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, bool user_only)
+{
+	int ret;
+
+	IPA_API_DISPATCH_RETURN(ipa_add_rt_rule_usr, rules, user_only);
+
+	return ret;
+}
+EXPORT_SYMBOL(ipa_add_rt_rule_usr);
+
+/**
  * ipa_del_rt_rule() - Remove the specified routing rules to SW and optionally
  * commit to IPA HW
  * @hdls:	[inout] set of routing rules to delete
@@ -913,16 +996,17 @@
  * ipa_reset_rt() - reset the current SW routing table of specified type
  * (does not commit to HW)
  * @ip:	The family of routing tables
+ * @user_only:	[in] indicate delete rules installed by userspace
  *
  * Returns:	0 on success, negative on failure
  *
  * Note:	Should not be called from atomic context
  */
-int ipa_reset_rt(enum ipa_ip_type ip)
+int ipa_reset_rt(enum ipa_ip_type ip, bool user_only)
 {
 	int ret;
 
-	IPA_API_DISPATCH_RETURN(ipa_reset_rt, ip);
+	IPA_API_DISPATCH_RETURN(ipa_reset_rt, ip, user_only);
 
 	return ret;
 }
@@ -1005,6 +1089,7 @@
 /**
  * ipa_add_flt_rule() - Add the specified filtering rules to SW and optionally
  * commit to IPA HW
+ * @rules:	[inout] set of filtering rules to add
  *
  * Returns:	0 on success, negative on failure
  *
@@ -1021,6 +1106,26 @@
 EXPORT_SYMBOL(ipa_add_flt_rule);
 
 /**
+ * ipa_add_flt_rule_usr() - Add the specified filtering rules to
+ * SW and optionally commit to IPA HW
+ * @rules:		[inout] set of filtering rules to add
+ * @user_only:	[in] indicate rules installed by userspace
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+int ipa_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, bool user_only)
+{
+	int ret;
+
+	IPA_API_DISPATCH_RETURN(ipa_add_flt_rule_usr, rules, user_only);
+
+	return ret;
+}
+EXPORT_SYMBOL(ipa_add_flt_rule_usr);
+
+/**
  * ipa_del_flt_rule() - Remove the specified filtering rules from SW and
  * optionally commit to IPA HW
  *
@@ -1078,17 +1183,18 @@
 /**
  * ipa_reset_flt() - Reset the current SW filtering table of specified type
  * (does not commit to HW)
- * @ip:	[in] the family of routing tables
+ * @ip:			[in] the family of routing tables
+ * @user_only:	[in] indicate delete rules installed by userspace
  *
  * Returns:	0 on success, negative on failure
  *
  * Note:	Should not be called from atomic context
  */
-int ipa_reset_flt(enum ipa_ip_type ip)
+int ipa_reset_flt(enum ipa_ip_type ip, bool user_only)
 {
 	int ret;
 
-	IPA_API_DISPATCH_RETURN(ipa_reset_flt, ip);
+	IPA_API_DISPATCH_RETURN(ipa_reset_flt, ip, user_only);
 
 	return ret;
 }
@@ -1865,20 +1971,20 @@
 EXPORT_SYMBOL(ipa_uc_dereg_rdyCB);
 
 /**
-* teth_bridge_init() - Initialize the Tethering bridge driver
-* @params - in/out params for USB initialization API (please look at struct
-*  definition for more info)
-*
-* USB driver gets a pointer to a callback function (usb_notify_cb) and an
-* associated data. USB driver installs this callback function in the call to
-* ipa_connect().
-*
-* Builds IPA resource manager dependency graph.
-*
-* Return codes: 0: success,
-*		-EINVAL - Bad parameter
-*		Other negative value - Failure
-*/
+ * teth_bridge_init() - Initialize the Tethering bridge driver
+ * @params - in/out params for USB initialization API (please look at struct
+ *  definition for more info)
+ *
+ * USB driver gets a pointer to a callback function (usb_notify_cb) and an
+ * associated data. USB driver installs this callback function in the call to
+ * ipa_connect().
+ *
+ * Builds IPA resource manager dependency graph.
+ *
+ * Return codes: 0: success,
+ *		-EINVAL - Bad parameter
+ *		Other negative value - Failure
+ */
 int teth_bridge_init(struct teth_bridge_init_params *params)
 {
 	int ret;
@@ -1890,8 +1996,8 @@
 EXPORT_SYMBOL(teth_bridge_init);
 
 /**
-* teth_bridge_disconnect() - Disconnect tethering bridge module
-*/
+ * teth_bridge_disconnect() - Disconnect tethering bridge module
+ */
 int teth_bridge_disconnect(enum ipa_client_type client)
 {
 	int ret;
@@ -1903,14 +2009,14 @@
 EXPORT_SYMBOL(teth_bridge_disconnect);
 
 /**
-* teth_bridge_connect() - Connect bridge for a tethered Rmnet / MBIM call
-* @connect_params:	Connection info
-*
-* Return codes: 0: success
-*		-EINVAL: invalid parameters
-*		-EPERM: Operation not permitted as the bridge is already
-*		connected
-*/
+ * teth_bridge_connect() - Connect bridge for a tethered Rmnet / MBIM call
+ * @connect_params:	Connection info
+ *
+ * Return codes: 0: success
+ *		-EINVAL: invalid parameters
+ *		-EPERM: Operation not permitted as the bridge is already
+ *		connected
+ */
 int teth_bridge_connect(struct teth_bridge_connect_params *connect_params)
 {
 	int ret;
@@ -2387,16 +2493,16 @@
 EXPORT_SYMBOL(ipa_write_qmap_id);
 
 /**
-* ipa_add_interrupt_handler() - Adds handler to an interrupt type
-* @interrupt:		Interrupt type
-* @handler:		The handler to be added
-* @deferred_flag:	whether the handler processing should be deferred in
-*			a workqueue
-* @private_data:	the client's private data
-*
-* Adds handler to an interrupt type and enable the specific bit
-* in IRQ_EN register, associated interrupt in IRQ_STTS register will be enabled
-*/
+ * ipa_add_interrupt_handler() - Adds handler to an interrupt type
+ * @interrupt:		Interrupt type
+ * @handler:		The handler to be added
+ * @deferred_flag:	whether the handler processing should be deferred in
+ *			a workqueue
+ * @private_data:	the client's private data
+ *
+ * Adds handler to an interrupt type and enable the specific bit
+ * in IRQ_EN register, associated interrupt in IRQ_STTS register will be enabled
+ */
 int ipa_add_interrupt_handler(enum ipa_irq_type interrupt,
 	ipa_irq_handler_t handler,
 	bool deferred_flag,
@@ -2412,11 +2518,11 @@
 EXPORT_SYMBOL(ipa_add_interrupt_handler);
 
 /**
-* ipa_remove_interrupt_handler() - Removes handler to an interrupt type
-* @interrupt:		Interrupt type
-*
-* Removes the handler and disable the specific bit in IRQ_EN register
-*/
+ * ipa_remove_interrupt_handler() - Removes handler to an interrupt type
+ * @interrupt:		Interrupt type
+ *
+ * Removes the handler and disable the specific bit in IRQ_EN register
+ */
 int ipa_remove_interrupt_handler(enum ipa_irq_type interrupt)
 {
 	int ret;
@@ -2428,12 +2534,12 @@
 EXPORT_SYMBOL(ipa_remove_interrupt_handler);
 
 /**
-* ipa_restore_suspend_handler() - restores the original suspend IRQ handler
-* as it was registered in the IPA init sequence.
-* Return codes:
-* 0: success
-* -EPERM: failed to remove current handler or failed to add original handler
-*/
+ * ipa_restore_suspend_handler() - restores the original suspend IRQ handler
+ * as it was registered in the IPA init sequence.
+ * Return codes:
+ * 0: success
+ * -EPERM: failed to remove current handler or failed to add original handler
+ */
 int ipa_restore_suspend_handler(void)
 {
 	int ret;
@@ -2728,14 +2834,14 @@
 EXPORT_SYMBOL(ipa_start_gsi_channel);
 
 /**
-* ipa_is_vlan_mode - check if a LAN driver should load in VLAN mode
-* @iface - type of vlan capable device
-* @res - query result: true for vlan mode, false for non vlan mode
-*
-* API must be called after ipa_is_ready() returns true, otherwise it will fail
-*
-* Returns: 0 on success, negative on failure
-*/
+ * ipa_is_vlan_mode - check if a LAN driver should load in VLAN mode
+ * @iface - type of vlan capable device
+ * @res - query result: true for vlan mode, false for non vlan mode
+ *
+ * API must be called after ipa_is_ready() returns true, otherwise it will fail
+ *
+ * Returns: 0 on success, negative on failure
+ */
 int ipa_is_vlan_mode(enum ipa_vlan_ifaces iface, bool *res)
 {
 	int ret;
@@ -2814,10 +2920,10 @@
 {
 	int result;
 
-	/*
-	* IPA probe function can be called for multiple times as the same probe
-	* function handles multiple compatibilities
-	*/
+/**
+ * IPA probe function can be called for multiple times as the same probe
+ * function handles multiple compatibilities
+ */
 	pr_debug("ipa: IPA driver probing started for %s\n",
 		pdev_p->dev.of_node->name);
 
@@ -2905,7 +3011,7 @@
  *
  * Return codes:
  * None
-*/
+ */
 void ipa_inc_client_enable_clks(struct ipa_active_client_logging_info *id)
 {
 	IPA_API_DISPATCH(ipa_inc_client_enable_clks, id);
@@ -2921,7 +3027,7 @@
  *
  * Return codes:
  * None
-*/
+ */
 void ipa_dec_client_disable_clks(struct ipa_active_client_logging_info *id)
 {
 	IPA_API_DISPATCH(ipa_dec_client_disable_clks, id);
@@ -2951,14 +3057,14 @@
 EXPORT_SYMBOL(ipa_inc_client_enable_clks_no_block);
 
 /**
-* ipa_suspend_resource_no_block() - suspend client endpoints related to the
-* IPA_RM resource and decrement active clients counter. This function is
-* guaranteed to avoid sleeping.
-*
-* @resource: [IN] IPA Resource Manager resource
-*
-* Return codes: 0 on success, negative on failure.
-*/
+ * ipa_suspend_resource_no_block() - suspend client endpoints related to the
+ * IPA_RM resource and decrement active clients counter. This function is
+ * guaranteed to avoid sleeping.
+ *
+ * @resource: [IN] IPA Resource Manager resource
+ *
+ * Return codes: 0 on success, negative on failure.
+ */
 int ipa_suspend_resource_no_block(enum ipa_rm_resource_name resource)
 {
 	int ret;
@@ -3111,12 +3217,12 @@
  * ipa_tear_down_uc_offload_pipes() - tear down uc offload pipes
  */
 int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul,
-		int ipa_ep_idx_dl)
+		int ipa_ep_idx_dl, struct ipa_ntn_conn_in_params *params)
 {
 	int ret;
 
 	IPA_API_DISPATCH_RETURN(ipa_tear_down_uc_offload_pipes, ipa_ep_idx_ul,
-		ipa_ep_idx_dl);
+		ipa_ep_idx_dl, params);
 
 	return ret;
 }
diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h
index fc4362f..b7edb6f 100644
--- a/drivers/platform/msm/ipa/ipa_api.h
+++ b/drivers/platform/msm/ipa/ipa_api.h
@@ -73,11 +73,13 @@
 
 	int (*ipa_add_hdr)(struct ipa_ioc_add_hdr *hdrs);
 
+	int (*ipa_add_hdr_usr)(struct ipa_ioc_add_hdr *hdrs, bool user_only);
+
 	int (*ipa_del_hdr)(struct ipa_ioc_del_hdr *hdls);
 
 	int (*ipa_commit_hdr)(void);
 
-	int (*ipa_reset_hdr)(void);
+	int (*ipa_reset_hdr)(bool user_only);
 
 	int (*ipa_get_hdr)(struct ipa_ioc_get_hdr *lookup);
 
@@ -85,17 +87,21 @@
 
 	int (*ipa_copy_hdr)(struct ipa_ioc_copy_hdr *copy);
 
-	int (*ipa_add_hdr_proc_ctx)(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs);
+	int (*ipa_add_hdr_proc_ctx)(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs,
+								bool user_only);
 
 	int (*ipa_del_hdr_proc_ctx)(struct ipa_ioc_del_hdr_proc_ctx *hdls);
 
 	int (*ipa_add_rt_rule)(struct ipa_ioc_add_rt_rule *rules);
 
+	int (*ipa_add_rt_rule_usr)(struct ipa_ioc_add_rt_rule *rules,
+							bool user_only);
+
 	int (*ipa_del_rt_rule)(struct ipa_ioc_del_rt_rule *hdls);
 
 	int (*ipa_commit_rt)(enum ipa_ip_type ip);
 
-	int (*ipa_reset_rt)(enum ipa_ip_type ip);
+	int (*ipa_reset_rt)(enum ipa_ip_type ip, bool user_only);
 
 	int (*ipa_get_rt_tbl)(struct ipa_ioc_get_rt_tbl *lookup);
 
@@ -107,13 +113,16 @@
 
 	int (*ipa_add_flt_rule)(struct ipa_ioc_add_flt_rule *rules);
 
+	int (*ipa_add_flt_rule_usr)(struct ipa_ioc_add_flt_rule *rules,
+								bool user_only);
+
 	int (*ipa_del_flt_rule)(struct ipa_ioc_del_flt_rule *hdls);
 
 	int (*ipa_mdfy_flt_rule)(struct ipa_ioc_mdfy_flt_rule *rules);
 
 	int (*ipa_commit_flt)(enum ipa_ip_type ip);
 
-	int (*ipa_reset_flt)(enum ipa_ip_type ip);
+	int (*ipa_reset_flt)(enum ipa_ip_type ip, bool user_only);
 
 	int (*ipa_allocate_nat_device)(struct ipa_ioc_nat_alloc_mem *mem);
 
@@ -394,7 +403,7 @@
 		struct ipa_ntn_conn_out_params *);
 
 	int (*ipa_tear_down_uc_offload_pipes)(int ipa_ep_idx_ul,
-		int ipa_ep_idx_dl);
+		int ipa_ep_idx_dl, struct ipa_ntn_conn_in_params *params);
 
 	struct device *(*ipa_get_pdev)(void);
 
diff --git a/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c b/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c
index 9f8bfbe..f7de806 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c
@@ -1445,6 +1445,10 @@
 	usb_to_ipa_ep_cfg.route.rt_tbl_hdl = 0;
 	usb_to_ipa_ep_cfg.mode.dst = IPA_CLIENT_A5_LAN_WAN_CONS;
 	usb_to_ipa_ep_cfg.mode.mode = IPA_BASIC;
+
+	/* enable hdr_metadata_reg_valid */
+	usb_to_ipa_ep_cfg.hdr.hdr_metadata_reg_valid = true;
+
 	result = ipa_cfg_ep(usb_to_ipa_hdl, &usb_to_ipa_ep_cfg);
 	if (result) {
 		ECM_IPA_ERROR("failed to configure USB to IPA point\n");
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c b/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c
index f0c67b1..b16cc0c 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -73,6 +73,7 @@
 	ipa_notify_cb notify;
 	struct completion ntn_completion;
 	u32 pm_hdl;
+	struct ipa_ntn_conn_in_params conn;
 };
 
 static struct ipa_uc_offload_ctx *ipa_uc_offload_ctx[IPA_UC_MAX_PROT_SIZE];
@@ -403,6 +404,51 @@
 	}
 }
 
+static int ipa_uc_ntn_alloc_conn_smmu_info(struct ipa_ntn_setup_info *dest,
+	struct ipa_ntn_setup_info *source)
+{
+	int result;
+
+	IPA_UC_OFFLOAD_DBG("Allocating smmu info\n");
+
+	memcpy(dest, source, sizeof(struct ipa_ntn_setup_info));
+
+	dest->data_buff_list =
+		kcalloc(dest->num_buffers, sizeof(struct ntn_buff_smmu_map),
+			GFP_KERNEL);
+	if (dest->data_buff_list == NULL) {
+		IPA_UC_OFFLOAD_ERR("failed to alloc smmu info\n");
+		return -ENOMEM;
+	}
+
+	memcpy(dest->data_buff_list, source->data_buff_list,
+		sizeof(struct ntn_buff_smmu_map) * dest->num_buffers);
+
+	result = ipa_smmu_store_sgt(&dest->buff_pool_base_sgt,
+		source->buff_pool_base_sgt);
+	if (result) {
+		kfree(dest->data_buff_list);
+		return result;
+	}
+
+	result = ipa_smmu_store_sgt(&dest->ring_base_sgt,
+		source->ring_base_sgt);
+	if (result) {
+		kfree(dest->data_buff_list);
+		ipa_smmu_free_sgt(&dest->buff_pool_base_sgt);
+		return result;
+	}
+
+	return 0;
+}
+
+static void ipa_uc_ntn_free_conn_smmu_info(struct ipa_ntn_setup_info *params)
+{
+	kfree(params->data_buff_list);
+	ipa_smmu_free_sgt(&params->buff_pool_base_sgt);
+	ipa_smmu_free_sgt(&params->ring_base_sgt);
+}
+
 int ipa_uc_ntn_conn_pipes(struct ipa_ntn_conn_in_params *inp,
 			struct ipa_ntn_conn_out_params *outp,
 			struct ipa_uc_offload_ctx *ntn_ctx)
@@ -410,6 +456,11 @@
 	int result = 0;
 	enum ipa_uc_offload_state prev_state;
 
+	if (ntn_ctx->conn.dl.smmu_enabled != ntn_ctx->conn.ul.smmu_enabled) {
+		IPA_UC_OFFLOAD_ERR("ul and dl smmu enablement do not match\n");
+		return -EINVAL;
+	}
+
 	prev_state = ntn_ctx->state;
 	if (inp->dl.ring_base_pa % IPA_NTN_DMA_POOL_ALIGNMENT ||
 		inp->dl.buff_pool_base_pa % IPA_NTN_DMA_POOL_ALIGNMENT) {
@@ -467,7 +518,21 @@
 		goto fail;
 	}
 
-	return 0;
+	if (ntn_ctx->conn.dl.smmu_enabled) {
+		result = ipa_uc_ntn_alloc_conn_smmu_info(&ntn_ctx->conn.dl,
+			&inp->dl);
+		if (result) {
+			IPA_UC_OFFLOAD_ERR("alloc failure on TX\n");
+			goto fail;
+		}
+		result = ipa_uc_ntn_alloc_conn_smmu_info(&ntn_ctx->conn.ul,
+			&inp->ul);
+		if (result) {
+			ipa_uc_ntn_free_conn_smmu_info(&ntn_ctx->conn.dl);
+			IPA_UC_OFFLOAD_ERR("alloc failure on RX\n");
+			goto fail;
+		}
+	}
 
 fail:
 	if (!ipa_pm_is_used())
@@ -563,6 +628,11 @@
 	int ipa_ep_idx_ul, ipa_ep_idx_dl;
 	int ret = 0;
 
+	if (ntn_ctx->conn.dl.smmu_enabled != ntn_ctx->conn.ul.smmu_enabled) {
+		IPA_UC_OFFLOAD_ERR("ul and dl smmu enablement do not match\n");
+		return -EINVAL;
+	}
+
 	ntn_ctx->state = IPA_UC_OFFLOAD_STATE_INITIALIZED;
 
 #ifdef CONFIG_IPA3
@@ -594,12 +664,16 @@
 
 	ipa_ep_idx_ul = ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_PROD);
 	ipa_ep_idx_dl = ipa_get_ep_mapping(IPA_CLIENT_ETHERNET_CONS);
-	ret = ipa_tear_down_uc_offload_pipes(ipa_ep_idx_ul, ipa_ep_idx_dl);
+	ret = ipa_tear_down_uc_offload_pipes(ipa_ep_idx_ul, ipa_ep_idx_dl,
+		&ntn_ctx->conn);
 	if (ret) {
 		IPA_UC_OFFLOAD_ERR("fail to tear down ntn offload pipes, %d\n",
 						 ret);
 		return -EFAULT;
 	}
+	if (ntn_ctx->conn.dl.smmu_enabled)
+		ipa_uc_ntn_free_conn_smmu_info(&ntn_ctx->conn.dl);
+		ipa_uc_ntn_free_conn_smmu_info(&ntn_ctx->conn.ul);
 
 	return ret;
 }
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
index e23541c..ebf1d29 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
@@ -1149,7 +1149,8 @@
 		if (ipa3_usb_ctx->smmu_reg_map.cnt == 0) {
 			ipa3_usb_ctx->smmu_reg_map.addr = gevntcount_r;
 			result = ipa3_smmu_map_peer_reg(
-				ipa3_usb_ctx->smmu_reg_map.addr, true);
+				ipa3_usb_ctx->smmu_reg_map.addr, true,
+				IPA_SMMU_CB_AP);
 			if (result) {
 				IPA_USB_ERR("failed to map USB regs %d\n",
 					result);
@@ -1172,7 +1173,8 @@
 
 		if (ipa3_usb_ctx->smmu_reg_map.cnt == 1) {
 			result = ipa3_smmu_map_peer_reg(
-				ipa3_usb_ctx->smmu_reg_map.addr, false);
+				ipa3_usb_ctx->smmu_reg_map.addr, false,
+				IPA_SMMU_CB_AP);
 			if (result) {
 				IPA_USB_ERR("failed to unmap USB regs %d\n",
 					result);
@@ -1184,14 +1186,16 @@
 
 
 	result = ipa3_smmu_map_peer_buff(params->xfer_ring_base_addr_iova,
-		params->xfer_ring_len, map, params->sgt_xfer_rings);
+		params->xfer_ring_len, map, params->sgt_xfer_rings,
+		IPA_SMMU_CB_AP);
 	if (result) {
 		IPA_USB_ERR("failed to map Xfer ring %d\n", result);
 		return result;
 	}
 
 	result = ipa3_smmu_map_peer_buff(params->data_buff_base_addr_iova,
-		params->data_buff_base_len, map, params->sgt_data_buff);
+		params->data_buff_base_len, map, params->sgt_data_buff,
+		IPA_SMMU_CB_AP);
 	if (result) {
 		IPA_USB_ERR("failed to map TRBs buff %d\n", result);
 		return result;
@@ -1200,43 +1204,6 @@
 	return 0;
 }
 
-static int ipa3_usb_smmu_store_sgt(struct sg_table **out_ch_ptr,
-	struct sg_table *in_sgt_ptr)
-{
-	unsigned int nents;
-
-	if (in_sgt_ptr != NULL) {
-		*out_ch_ptr = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
-		if (*out_ch_ptr == NULL)
-			return -ENOMEM;
-
-		nents = in_sgt_ptr->nents;
-
-		(*out_ch_ptr)->sgl =
-			kcalloc(nents, sizeof(struct scatterlist),
-				GFP_KERNEL);
-		if ((*out_ch_ptr)->sgl == NULL)
-			return -ENOMEM;
-
-		memcpy((*out_ch_ptr)->sgl, in_sgt_ptr->sgl,
-			nents*sizeof((*out_ch_ptr)->sgl));
-		(*out_ch_ptr)->nents = nents;
-		(*out_ch_ptr)->orig_nents = in_sgt_ptr->orig_nents;
-	}
-	return 0;
-}
-
-static int ipa3_usb_smmu_free_sgt(struct sg_table **out_sgt_ptr)
-{
-	if (*out_sgt_ptr != NULL) {
-		kfree((*out_sgt_ptr)->sgl);
-		(*out_sgt_ptr)->sgl = NULL;
-		kfree(*out_sgt_ptr);
-		*out_sgt_ptr = NULL;
-	}
-	return 0;
-}
-
 static int ipa3_usb_request_xdci_channel(
 	struct ipa_usb_xdci_chan_params *params,
 	enum ipa_usb_direction dir,
@@ -1327,18 +1294,17 @@
 		xdci_ch_params = &ipa3_usb_ctx->ttype_ctx[ttype].dl_ch_params;
 
 	*xdci_ch_params = *params;
-	result = ipa3_usb_smmu_store_sgt(
+	result = ipa_smmu_store_sgt(
 		&xdci_ch_params->sgt_xfer_rings,
 		params->sgt_xfer_rings);
-	if (result) {
-		ipa3_usb_smmu_free_sgt(&xdci_ch_params->sgt_xfer_rings);
+	if (result)
 		return result;
-	}
-	result = ipa3_usb_smmu_store_sgt(
+
+	result = ipa_smmu_store_sgt(
 		&xdci_ch_params->sgt_data_buff,
 		params->sgt_data_buff);
 	if (result) {
-		ipa3_usb_smmu_free_sgt(&xdci_ch_params->sgt_data_buff);
+		ipa_smmu_free_sgt(&xdci_ch_params->sgt_xfer_rings);
 		return result;
 	}
 	chan_params.keep_ipa_awake = params->keep_ipa_awake;
@@ -1443,9 +1409,9 @@
 	result = ipa3_usb_smmu_map_xdci_channel(xdci_ch_params, false);
 
 	if (xdci_ch_params->sgt_xfer_rings != NULL)
-		ipa3_usb_smmu_free_sgt(&xdci_ch_params->sgt_xfer_rings);
+		ipa_smmu_free_sgt(&xdci_ch_params->sgt_xfer_rings);
 	if (xdci_ch_params->sgt_data_buff != NULL)
-		ipa3_usb_smmu_free_sgt(&xdci_ch_params->sgt_data_buff);
+		ipa_smmu_free_sgt(&xdci_ch_params->sgt_data_buff);
 
 	/* Change ipa_usb state to INITIALIZED */
 	if (!ipa3_usb_set_state(IPA_USB_INITIALIZED, false, ttype))
diff --git a/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c b/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c
index 4980167..51890dd 100644
--- a/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c
@@ -363,7 +363,7 @@
 			sizeof(struct rndis_pkt_hdr),
 		.hdr_a5_mux = false,
 		.hdr_remove_additional = false,
-		.hdr_metadata_reg_valid = false,
+		.hdr_metadata_reg_valid = true,
 	},
 	.hdr_ext = {
 		.hdr_pad_to_alignment = 0,
@@ -410,7 +410,7 @@
 		.hdr_ofst_pkt_size = 3 * sizeof(u32),
 		.hdr_a5_mux = false,
 		.hdr_remove_additional = false,
-		.hdr_metadata_reg_valid = false,
+		.hdr_metadata_reg_valid = true,
 	},
 	.hdr_ext = {
 		.hdr_pad_to_alignment = 0,
@@ -2184,6 +2184,9 @@
 		ipa_to_usb_ep_cfg.aggr.aggr_time_limit,
 		ipa_to_usb_ep_cfg.aggr.aggr_pkt_limit);
 
+	/* enable hdr_metadata_reg_valid */
+	usb_to_ipa_ep_cfg->hdr.hdr_metadata_reg_valid = true;
+
 	result = ipa_cfg_ep(ipa_to_usb_hdl, &ipa_to_usb_ep_cfg);
 	if (result) {
 		pr_err("failed to configure IPA to USB end-point\n");
diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h
index b37a127..b8a517e 100644
--- a/drivers/platform/msm/ipa/ipa_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_common_i.h
@@ -333,11 +333,13 @@
  * @link: entry's link in global header offset entries list
  * @offset: the offset
  * @bin: bin
+ * @ipacm_installed: indicate if installed by ipacm
  */
 struct ipa_hdr_offset_entry {
 	struct list_head link;
 	u32 offset;
 	u32 bin;
+	bool ipacm_installed;
 };
 
 extern const char *ipa_clients_strings[];
@@ -408,7 +410,8 @@
 	ipa_notify_cb notify, void *priv, u8 hdr_len,
 	struct ipa_ntn_conn_out_params *outp);
 
-int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl);
+int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl,
+	struct ipa_ntn_conn_in_params *params);
 u8 *ipa_write_64(u64 w, u8 *dest);
 u8 *ipa_write_32(u32 w, u8 *dest);
 u8 *ipa_write_16(u16 hw, u8 *dest);
@@ -434,4 +437,8 @@
 
 bool ipa_pm_is_used(void);
 
+int ipa_smmu_store_sgt(struct sg_table **out_ch_ptr,
+		struct sg_table *in_sgt_ptr);
+int ipa_smmu_free_sgt(struct sg_table **out_sgt_ptr);
+
 #endif /* _IPA_COMMON_I_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_uc_offload_common_i.h b/drivers/platform/msm/ipa/ipa_uc_offload_common_i.h
index 0bc4b76..3caac8c 100644
--- a/drivers/platform/msm/ipa/ipa_uc_offload_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_uc_offload_common_i.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,7 +19,9 @@
 int ipa_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
 	ipa_notify_cb notify, void *priv, u8 hdr_len,
 	struct ipa_ntn_conn_out_params *outp);
-int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl);
+
+int ipa_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl,
+	struct ipa_ntn_conn_in_params *params);
 
 int ipa_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *user_data),
 			      void *user_data);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index e43a201..10468f3 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -278,6 +278,28 @@
 	return cnt;
 }
 
+
+static int ipa2_clean_modem_rule(void)
+{
+	struct ipa_install_fltr_rule_req_msg_v01 *req;
+	int val = 0;
+
+	req = kzalloc(
+		sizeof(struct ipa_install_fltr_rule_req_msg_v01),
+		GFP_KERNEL);
+	if (!req) {
+		IPAERR("mem allocated failed!\n");
+		return -ENOMEM;
+	}
+	req->filter_spec_list_valid = false;
+	req->filter_spec_list_len = 0;
+	req->source_pipe_index_valid = 0;
+	val = qmi_filter_request_send(req);
+	kfree(req);
+
+	return val;
+}
+
 static int ipa2_active_clients_panic_notifier(struct notifier_block *this,
 		unsigned long event, void *ptr)
 {
@@ -532,7 +554,8 @@
 	kfree(buff);
 }
 
-static int ipa_send_wan_msg(unsigned long usr_param, uint8_t msg_type, bool is_cache)
+static int ipa_send_wan_msg(unsigned long usr_param, uint8_t msg_type,
+	bool is_cache)
 {
 	int retval;
 	struct ipa_wan_msg *wan_msg;
@@ -715,7 +738,8 @@
 			retval = -EFAULT;
 			break;
 		}
-		if (ipa2_add_hdr((struct ipa_ioc_add_hdr *)param)) {
+		if (ipa2_add_hdr_usr((struct ipa_ioc_add_hdr *)param,
+			true)) {
 			retval = -EFAULT;
 			break;
 		}
@@ -795,7 +819,8 @@
 			retval = -EFAULT;
 			break;
 		}
-		if (ipa2_add_rt_rule((struct ipa_ioc_add_rt_rule *)param)) {
+		if (ipa2_add_rt_rule_usr((struct ipa_ioc_add_rt_rule *)param,
+				true)) {
 			retval = -EFAULT;
 			break;
 		}
@@ -914,7 +939,8 @@
 			retval = -EFAULT;
 			break;
 		}
-		if (ipa2_add_flt_rule((struct ipa_ioc_add_flt_rule *)param)) {
+		if (ipa2_add_flt_rule_usr((struct ipa_ioc_add_flt_rule *)param,
+				true)) {
 			retval = -EFAULT;
 			break;
 		}
@@ -1008,19 +1034,19 @@
 		retval = ipa2_commit_hdr();
 		break;
 	case IPA_IOC_RESET_HDR:
-		retval = ipa2_reset_hdr();
+		retval = ipa2_reset_hdr(false);
 		break;
 	case IPA_IOC_COMMIT_RT:
 		retval = ipa2_commit_rt(arg);
 		break;
 	case IPA_IOC_RESET_RT:
-		retval = ipa2_reset_rt(arg);
+		retval = ipa2_reset_rt(arg, false);
 		break;
 	case IPA_IOC_COMMIT_FLT:
 		retval = ipa2_commit_flt(arg);
 		break;
 	case IPA_IOC_RESET_FLT:
-		retval = ipa2_reset_flt(arg);
+		retval = ipa2_reset_flt(arg, false);
 		break;
 	case IPA_IOC_GET_RT_TBL:
 		if (copy_from_user(header, (u8 *)arg,
@@ -1400,7 +1426,7 @@
 			break;
 		}
 		if (ipa2_add_hdr_proc_ctx(
-			(struct ipa_ioc_add_hdr_proc_ctx *)param)) {
+			(struct ipa_ioc_add_hdr_proc_ctx *)param, true)) {
 			retval = -EFAULT;
 			break;
 		}
@@ -1464,6 +1490,21 @@
 		}
 		break;
 
+	case IPA_IOC_CLEANUP:
+		/*Route and filter rules will also be clean*/
+		IPADBG("Got IPA_IOC_CLEANUP\n");
+		retval = ipa2_reset_hdr(true);
+		memset(&nat_del, 0, sizeof(nat_del));
+		nat_del.table_index = 0;
+		retval = ipa2_nat_del_cmd(&nat_del);
+		retval = ipa2_clean_modem_rule();
+		break;
+
+	case IPA_IOC_QUERY_WLAN_CLIENT:
+		IPADBG("Got IPA_IOC_QUERY_WLAN_CLIENT\n");
+		retval = ipa2_resend_wlan_msg();
+		break;
+
 	default:
 		IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 		return -ENOTTY;
@@ -4206,6 +4247,10 @@
 	init_waitqueue_head(&ipa_ctx->msg_waitq);
 	mutex_init(&ipa_ctx->msg_lock);
 
+	/* store wlan client-connect-msg-list */
+	INIT_LIST_HEAD(&ipa_ctx->msg_wlan_client_list);
+	mutex_init(&ipa_ctx->msg_wlan_client_lock);
+
 	mutex_init(&ipa_ctx->lock);
 	mutex_init(&ipa_ctx->nat_mem.lock);
 	mutex_init(&ipa_ctx->ipa_cne_evt_lock);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c
index bc54023..84dce6f 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1008,7 +1008,7 @@
 
 static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip,
 			      const struct ipa_flt_rule *rule, u8 add_rear,
-			      u32 *rule_hdl)
+			      u32 *rule_hdl, bool user)
 {
 	struct ipa_flt_entry *entry;
 	struct ipa_rt_tbl *rt_tbl = NULL;
@@ -1076,6 +1076,7 @@
 	}
 	*rule_hdl = id;
 	entry->id = id;
+	entry->ipacm_installed = user;
 	IPADBG_LOW("add flt rule rule_cnt=%d\n", tbl->rule_cnt);
 
 	return 0;
@@ -1198,12 +1199,12 @@
 	tbl = &ipa_ctx->glob_flt_tbl[ip];
 	IPADBG_LOW("add global flt rule ip=%d\n", ip);
 
-	return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl);
+	return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl, false);
 }
 
 static int __ipa_add_ep_flt_rule(enum ipa_ip_type ip, enum ipa_client_type ep,
 				 const struct ipa_flt_rule *rule, u8 add_rear,
-				 u32 *rule_hdl)
+				 u32 *rule_hdl, bool user)
 {
 	struct ipa_flt_tbl *tbl;
 	int ipa_ep_idx;
@@ -1225,12 +1226,13 @@
 	tbl = &ipa_ctx->flt_tbl[ipa_ep_idx][ip];
 	IPADBG_LOW("add ep flt rule ip=%d ep=%d\n", ip, ep);
 
-	return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl);
+	return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl, user);
 }
 
 /**
  * ipa2_add_flt_rule() - Add the specified filtering rules to SW and optionally
  * commit to IPA HW
+ * @rules:	[inout] set of filtering rules to add
  *
  * Returns:	0 on success, negative on failure
  *
@@ -1238,6 +1240,21 @@
  */
 int ipa2_add_flt_rule(struct ipa_ioc_add_flt_rule *rules)
 {
+	return ipa2_add_flt_rule_usr(rules, false);
+}
+
+/**
+ * ipa2_add_flt_rule_usr() - Add the specified filtering rules
+ * to SW and optionally commit to IPA HW
+ * @rules:	[inout] set of filtering rules to add
+ * @user_only:	[in] indicate rules installed by userspace
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+int ipa2_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, bool user_only)
+{
 	int i;
 	int result;
 
@@ -1259,7 +1276,8 @@
 			result = __ipa_add_ep_flt_rule(rules->ip, rules->ep,
 					&rules->rules[i].rule,
 					rules->rules[i].at_rear,
-					&rules->rules[i].flt_rule_hdl);
+					&rules->rules[i].flt_rule_hdl,
+					user_only);
 		if (result) {
 			IPAERR_RL("failed to add flt rule %d\n", i);
 			rules->rules[i].status = IPA_FLT_STATUS_OF_ADD_FAILED;
@@ -1396,13 +1414,14 @@
 /**
  * ipa2_reset_flt() - Reset the current SW filtering table of specified type
  * (does not commit to HW)
- * @ip:	[in] the family of routing tables
+ * @ip:			[in] the family of routing tables
+ * @user_only:	[in] indicate rules deleted by userspace
  *
  * Returns:	0 on success, negative on failure
  *
  * Note:	Should not be called from atomic context
  */
-int ipa2_reset_flt(enum ipa_ip_type ip)
+int ipa2_reset_flt(enum ipa_ip_type ip, bool user_only)
 {
 	struct ipa_flt_tbl *tbl;
 	struct ipa_flt_entry *entry;
@@ -1435,16 +1454,19 @@
 		      IPA_INVALID_L4_PROTOCOL))
 			continue;
 
-		list_del(&entry->link);
-		entry->tbl->rule_cnt--;
-		if (entry->rt_tbl)
-			entry->rt_tbl->ref_cnt--;
-		entry->cookie = 0;
-		id = entry->id;
-		kmem_cache_free(ipa_ctx->flt_rule_cache, entry);
+		if (!user_only ||
+				entry->ipacm_installed) {
+			list_del(&entry->link);
+			entry->tbl->rule_cnt--;
+			if (entry->rt_tbl)
+				entry->rt_tbl->ref_cnt--;
+			entry->cookie = 0;
+			id = entry->id;
+			kmem_cache_free(ipa_ctx->flt_rule_cache, entry);
 
-		/* remove the handle from the database */
-		ipa_id_remove(id);
+			/* remove the handle from the database */
+			ipa_id_remove(id);
+		}
 	}
 
 	for (i = 0; i < ipa_ctx->ipa_num_pipes; i++) {
@@ -1456,16 +1478,21 @@
 				mutex_unlock(&ipa_ctx->lock);
 				return -EFAULT;
 			}
-			list_del(&entry->link);
-			entry->tbl->rule_cnt--;
-			if (entry->rt_tbl)
-				entry->rt_tbl->ref_cnt--;
-			entry->cookie = 0;
-			id = entry->id;
-			kmem_cache_free(ipa_ctx->flt_rule_cache, entry);
 
-			/* remove the handle from the database */
-			ipa_id_remove(id);
+			if (!user_only ||
+				entry->ipacm_installed) {
+				list_del(&entry->link);
+				entry->tbl->rule_cnt--;
+				if (entry->rt_tbl)
+					entry->rt_tbl->ref_cnt--;
+				entry->cookie = 0;
+				id = entry->id;
+				kmem_cache_free(ipa_ctx->flt_rule_cache,
+					entry);
+
+				/* remove the handle from the database */
+				ipa_id_remove(id);
+			}
 		}
 	}
 	mutex_unlock(&ipa_ctx->lock);
@@ -1485,14 +1512,14 @@
 	tbl = &ipa_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v4];
 	rule.action = IPA_PASS_TO_EXCEPTION;
 	__ipa_add_flt_rule(tbl, IPA_IP_v4, &rule, true,
-			&ep->dflt_flt4_rule_hdl);
+			&ep->dflt_flt4_rule_hdl, false);
 	ipa_ctx->ctrl->ipa_commit_flt(IPA_IP_v4);
 	tbl->sticky_rear = true;
 
 	tbl = &ipa_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v6];
 	rule.action = IPA_PASS_TO_EXCEPTION;
 	__ipa_add_flt_rule(tbl, IPA_IP_v6, &rule, true,
-			&ep->dflt_flt6_rule_hdl);
+			&ep->dflt_flt6_rule_hdl, false);
 	ipa_ctx->ctrl->ipa_commit_flt(IPA_IP_v6);
 	tbl->sticky_rear = true;
 	mutex_unlock(&ipa_ctx->lock);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
index 5459590..6285130 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -543,7 +543,7 @@
 }
 
 static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx,
-	bool add_ref_hdr)
+	bool add_ref_hdr, bool user_only)
 {
 	struct ipa_hdr_entry *hdr_entry;
 	struct ipa_hdr_proc_ctx_entry *entry;
@@ -581,6 +581,7 @@
 	if (add_ref_hdr)
 		hdr_entry->ref_cnt++;
 	entry->cookie = IPA_PROC_HDR_COOKIE;
+	entry->ipacm_installed = user_only;
 
 	needed_len = (proc_ctx->type == IPA_HDR_PROC_NONE) ?
 			sizeof(struct ipa_hdr_proc_ctx_add_hdr_seq) :
@@ -619,6 +620,7 @@
 		 */
 		offset->offset = htbl->end;
 		offset->bin = bin;
+		offset->ipacm_installed = user_only;
 		htbl->end += ipa_hdr_proc_ctx_bin_sz[bin];
 		list_add(&offset->link,
 				&htbl->head_offset_list[bin]);
@@ -627,6 +629,7 @@
 		offset =
 		    list_first_entry(&htbl->head_free_offset_list[bin],
 				    struct ipa_hdr_proc_ctx_offset_entry, link);
+		offset->ipacm_installed = user_only;
 		list_move(&offset->link, &htbl->head_offset_list[bin]);
 	}
 
@@ -664,7 +667,7 @@
 }
 
 
-static int __ipa_add_hdr(struct ipa_hdr_add *hdr)
+static int __ipa_add_hdr(struct ipa_hdr_add *hdr, bool user)
 {
 	struct ipa_hdr_entry *entry;
 	struct ipa_hdr_offset_entry *offset = NULL;
@@ -700,6 +703,7 @@
 	entry->is_eth2_ofst_valid = hdr->is_eth2_ofst_valid;
 	entry->eth2_ofst = hdr->eth2_ofst;
 	entry->cookie = IPA_HDR_COOKIE;
+	entry->ipacm_installed = user;
 
 	if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN0])
 		bin = IPA_HDR_BIN0;
@@ -760,6 +764,7 @@
 			list_add(&offset->link,
 					&htbl->head_offset_list[bin]);
 			entry->offset_entry = offset;
+			offset->ipacm_installed = user;
 		}
 	} else {
 		entry->is_hdr_proc_ctx = false;
@@ -769,6 +774,7 @@
 				struct ipa_hdr_offset_entry, link);
 		list_move(&offset->link, &htbl->head_offset_list[bin]);
 		entry->offset_entry = offset;
+		offset->ipacm_installed = user;
 	}
 
 	list_add(&entry->link, &htbl->head_hdr_entry_list);
@@ -800,7 +806,7 @@
 		IPADBG("adding processing context for header %s\n", hdr->name);
 		proc_ctx.type = IPA_HDR_PROC_NONE;
 		proc_ctx.hdr_hdl = id;
-		if (__ipa_add_hdr_proc_ctx(&proc_ctx, false)) {
+		if (__ipa_add_hdr_proc_ctx(&proc_ctx, false, user)) {
 			IPAERR("failed to add hdr proc ctx\n");
 			goto fail_add_proc_ctx;
 		}
@@ -960,6 +966,21 @@
  */
 int ipa2_add_hdr(struct ipa_ioc_add_hdr *hdrs)
 {
+	return ipa2_add_hdr_usr(hdrs, false);
+}
+
+/**
+ * ipa2_add_hdr_usr() - add the specified headers to SW
+ * and optionally commit them to IPA HW
+ * @hdrs:		[inout] set of headers to add
+ * @user_only:	[in] indicate installed from user
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+int ipa2_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool user_only)
+{
 	int i;
 	int result = -EFAULT;
 
@@ -977,7 +998,7 @@
 	IPADBG("adding %d headers to IPA driver internal data struct\n",
 			hdrs->num_hdrs);
 	for (i = 0; i < hdrs->num_hdrs; i++) {
-		if (__ipa_add_hdr(&hdrs->hdr[i])) {
+		if (__ipa_add_hdr(&hdrs->hdr[i], user_only)) {
 			IPAERR_RL("failed to add hdr %d\n", i);
 			hdrs->hdr[i].status = -1;
 		} else {
@@ -997,7 +1018,6 @@
 	mutex_unlock(&ipa_ctx->lock);
 	return result;
 }
-
 /**
  * ipa2_del_hdr_by_user() - Remove the specified headers
  * from SW and optionally commit them to IPA HW
@@ -1063,12 +1083,14 @@
  * ipa2_add_hdr_proc_ctx() - add the specified headers to SW
  * and optionally commit them to IPA HW
  * @proc_ctxs:	[inout] set of processing context headers to add
+ * @user_only:	[in] indicate installed by user-space module
  *
  * Returns:	0 on success, negative on failure
  *
  * Note:	Should not be called from atomic context
  */
-int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs)
+int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs,
+							bool user_only)
 {
 	int i;
 	int result = -EFAULT;
@@ -1089,7 +1111,8 @@
 	IPADBG("adding %d header processing contextes to IPA driver\n",
 			proc_ctxs->num_proc_ctxs);
 	for (i = 0; i < proc_ctxs->num_proc_ctxs; i++) {
-		if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i], true)) {
+		if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i],
+				true, user_only)) {
 			IPAERR_RL("failed to add hdr pric ctx %d\n", i);
 			proc_ctxs->proc_ctx[i].status = -1;
 		} else {
@@ -1211,11 +1234,12 @@
  * ipa2_reset_hdr() - reset the current header table in SW (does not commit to
  * HW)
  *
+ * @user_only:	[in] indicate delete rules installed by userspace
  * Returns:	0 on success, negative on failure
  *
  * Note:	Should not be called from atomic context
  */
-int ipa2_reset_hdr(void)
+int ipa2_reset_hdr(bool user_only)
 {
 	struct ipa_hdr_entry *entry;
 	struct ipa_hdr_entry *next;
@@ -1225,15 +1249,16 @@
 	struct ipa_hdr_offset_entry *off_next;
 	struct ipa_hdr_proc_ctx_offset_entry *ctx_off_entry;
 	struct ipa_hdr_proc_ctx_offset_entry *ctx_off_next;
-	int i;
+	int i, end = 0;
+	bool user_rule = false;
 
 	/*
 	 * issue a reset on the routing module since routing rules point to
 	 * header table entries
 	 */
-	if (ipa2_reset_rt(IPA_IP_v4))
+	if (ipa2_reset_rt(IPA_IP_v4, user_only))
 		IPAERR("fail to reset v4 rt\n");
-	if (ipa2_reset_rt(IPA_IP_v6))
+	if (ipa2_reset_rt(IPA_IP_v6, user_only))
 		IPAERR("fail to reset v4 rt\n");
 
 	mutex_lock(&ipa_ctx->lock);
@@ -1262,21 +1287,27 @@
 			WARN_ON(1);
 			return -EFAULT;
 		}
-		if (entry->is_hdr_proc_ctx) {
-			dma_unmap_single(ipa_ctx->pdev,
-				entry->phys_base,
-				entry->hdr_len,
-				DMA_TO_DEVICE);
-			entry->proc_ctx = NULL;
+
+		if (entry->ipacm_installed)
+			user_rule = true;
+
+		if (!user_only || entry->ipacm_installed) {
+			if (entry->is_hdr_proc_ctx) {
+				dma_unmap_single(ipa_ctx->pdev,
+					entry->phys_base,
+					entry->hdr_len,
+					DMA_TO_DEVICE);
+				entry->proc_ctx = NULL;
+			}
+			list_del(&entry->link);
+			ipa_ctx->hdr_tbl.hdr_cnt--;
+			entry->ref_cnt = 0;
+			entry->cookie = 0;
+
+			/* remove the handle from the database */
+			ipa_id_remove(entry->id);
+			kmem_cache_free(ipa_ctx->hdr_cache, entry);
 		}
-		list_del(&entry->link);
-		entry->ref_cnt = 0;
-		entry->cookie = 0;
-
-		/* remove the handle from the database */
-		ipa_id_remove(entry->id);
-		kmem_cache_free(ipa_ctx->hdr_cache, entry);
-
 	}
 	for (i = 0; i < IPA_HDR_BIN_MAX; i++) {
 		list_for_each_entry_safe(off_entry, off_next,
@@ -1290,21 +1321,41 @@
 			if (off_entry->offset == 0)
 				continue;
 
-			list_del(&off_entry->link);
-			kmem_cache_free(ipa_ctx->hdr_offset_cache, off_entry);
+			if (!user_only ||
+					off_entry->ipacm_installed) {
+				list_del(&off_entry->link);
+				kmem_cache_free(ipa_ctx->hdr_offset_cache,
+					off_entry);
+			} else {
+				if (off_entry->offset +
+					ipa_hdr_bin_sz[off_entry->bin] > end) {
+					end = off_entry->offset +
+						ipa_hdr_bin_sz[off_entry->bin];
+					IPADBG("replace end = %d\n", end);
+				}
+			}
 		}
 		list_for_each_entry_safe(off_entry, off_next,
 				&ipa_ctx->hdr_tbl.head_free_offset_list[i],
 				link) {
-			list_del(&off_entry->link);
-			kmem_cache_free(ipa_ctx->hdr_offset_cache, off_entry);
+
+			if (!user_only ||
+					off_entry->ipacm_installed) {
+				list_del(&off_entry->link);
+				kmem_cache_free(ipa_ctx->hdr_offset_cache,
+					off_entry);
+			}
 		}
 	}
-	/* there is one header of size 8 */
-	ipa_ctx->hdr_tbl.end = 8;
-	ipa_ctx->hdr_tbl.hdr_cnt = 1;
 
+	IPADBG("hdr_tbl.end = %d\n", end);
+	if (user_rule) {
+		ipa_ctx->hdr_tbl.end = end;
+		IPADBG("hdr_tbl.end = %d\n", end);
+	}
 	IPADBG("reset hdr proc ctx\n");
+	user_rule = false;
+	end = 0;
 	list_for_each_entry_safe(
 		ctx_entry,
 		ctx_next,
@@ -1316,34 +1367,63 @@
 			WARN_ON(1);
 			return -EFAULT;
 		}
-		list_del(&ctx_entry->link);
-		ctx_entry->ref_cnt = 0;
-		ctx_entry->cookie = 0;
 
-		/* remove the handle from the database */
-		ipa_id_remove(ctx_entry->id);
-		kmem_cache_free(ipa_ctx->hdr_proc_ctx_cache, ctx_entry);
+		if (entry->ipacm_installed)
+			user_rule = true;
 
+		if (!user_only ||
+				ctx_entry->ipacm_installed) {
+			list_del(&ctx_entry->link);
+			ipa_ctx->hdr_proc_ctx_tbl.proc_ctx_cnt--;
+			ctx_entry->ref_cnt = 0;
+			ctx_entry->cookie = 0;
+
+			/* remove the handle from the database */
+			ipa_id_remove(ctx_entry->id);
+			kmem_cache_free(ipa_ctx->hdr_proc_ctx_cache,
+				ctx_entry);
+		}
 	}
 	for (i = 0; i < IPA_HDR_PROC_CTX_BIN_MAX; i++) {
 		list_for_each_entry_safe(ctx_off_entry, ctx_off_next,
 				&ipa_ctx->hdr_proc_ctx_tbl.head_offset_list[i],
 				link) {
 
-			list_del(&ctx_off_entry->link);
-			kmem_cache_free(ipa_ctx->hdr_proc_ctx_offset_cache,
+			if (!user_only ||
+					ctx_off_entry->ipacm_installed) {
+				list_del(&ctx_off_entry->link);
+				kmem_cache_free(
+					ipa_ctx->hdr_proc_ctx_offset_cache,
 					ctx_off_entry);
+			} else {
+				if (ctx_off_entry->offset +
+					ipa_hdr_bin_sz[ctx_off_entry->bin]
+					> end) {
+					end = ctx_off_entry->offset +
+					ipa_hdr_bin_sz[ctx_off_entry->bin];
+					IPADBG("replace hdr_proc as %d\n", end);
+				}
+			}
 		}
 		list_for_each_entry_safe(ctx_off_entry, ctx_off_next,
 			    &ipa_ctx->hdr_proc_ctx_tbl.head_free_offset_list[i],
 			    link) {
-			list_del(&ctx_off_entry->link);
-			kmem_cache_free(ipa_ctx->hdr_proc_ctx_offset_cache,
-				ctx_off_entry);
+
+			if (!user_only ||
+					ctx_off_entry->ipacm_installed) {
+				list_del(&ctx_off_entry->link);
+				kmem_cache_free(
+					ipa_ctx->hdr_proc_ctx_offset_cache,
+					ctx_off_entry);
+			}
 		}
 	}
-	ipa_ctx->hdr_proc_ctx_tbl.end = 0;
-	ipa_ctx->hdr_proc_ctx_tbl.proc_ctx_cnt = 0;
+
+	IPADBG("hdr_proc_tbl.end = %d\n", end);
+	if (user_rule) {
+		ipa_ctx->hdr_proc_ctx_tbl.end = end;
+		IPADBG("hdr_proc_tbl.end = %d\n", end);
+	}
 	mutex_unlock(&ipa_ctx->lock);
 
 	return 0;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index bd7f600..9bc80b8 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -252,6 +252,8 @@
  * @tbl: filter table
  * @rt_tbl: routing table
  * @hw_len: entry's size
+ * @id: rule handle - globally unique
+ * @ipacm_installed: indicate if installed by ipacm
  */
 struct ipa_flt_entry {
 	struct list_head link;
@@ -261,6 +263,7 @@
 	struct ipa_rt_tbl *rt_tbl;
 	u32 hw_len;
 	int id;
+	bool ipacm_installed;
 };
 
 /**
@@ -315,6 +318,7 @@
  * @is_eth2_ofst_valid: is eth2_ofst field valid?
  * @eth2_ofst: offset to start of Ethernet-II/802.3 header
  * @user_deleted: is the header deleted by the user?
+ * @ipacm_installed: indicate if installed by ipacm
  */
 struct ipa_hdr_entry {
 	struct list_head link;
@@ -333,6 +337,7 @@
 	u8 is_eth2_ofst_valid;
 	u16 eth2_ofst;
 	bool user_deleted;
+	bool ipacm_installed;
 };
 
 /**
@@ -356,11 +361,13 @@
  * @link: entry's link in global processing context header offset entries list
  * @offset: the offset
  * @bin: bin
+ * @ipacm_installed: indicate if installed by ipacm
  */
 struct ipa_hdr_proc_ctx_offset_entry {
 	struct list_head link;
 	u32 offset;
 	u32 bin;
+	bool ipacm_installed;
 };
 
 /**
@@ -397,6 +404,7 @@
  * @ref_cnt: reference counter of routing table
  * @id: processing context header entry id
  * @user_deleted: is the hdr processing context deleted by the user?
+ * @ipacm_installed: indicate if installed by ipacm
  */
 struct ipa_hdr_proc_ctx_entry {
 	struct list_head link;
@@ -407,6 +415,7 @@
 	u32 ref_cnt;
 	int id;
 	bool user_deleted;
+	bool ipacm_installed;
 };
 
 /**
@@ -456,6 +465,8 @@
  * @hdr: header table
  * @proc_ctx: processing context table
  * @hw_len: the length of the table
+ * @id: rule handle - globaly unique
+ * @ipacm_installed: indicate if installed by ipacm
  */
 struct ipa_rt_entry {
 	struct list_head link;
@@ -466,6 +477,7 @@
 	struct ipa_hdr_proc_ctx_entry *proc_ctx;
 	u32 hw_len;
 	int id;
+	bool ipacm_installed;
 };
 
 /**
@@ -1160,6 +1172,8 @@
 	struct list_head msg_list;
 	struct list_head pull_msg_list;
 	struct mutex msg_lock;
+	struct list_head msg_wlan_client_list;
+	struct mutex msg_wlan_client_lock;
 	wait_queue_head_t msg_waitq;
 	enum ipa_hw_type ipa_hw_type;
 	enum ipa_hw_mode ipa_hw_mode;
@@ -1445,13 +1459,15 @@
  */
 int ipa2_add_hdr(struct ipa_ioc_add_hdr *hdrs);
 
+int ipa2_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool by_user);
+
 int ipa2_del_hdr(struct ipa_ioc_del_hdr *hdls);
 
 int ipa2_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user);
 
 int ipa2_commit_hdr(void);
 
-int ipa2_reset_hdr(void);
+int ipa2_reset_hdr(bool user_only);
 
 int ipa2_get_hdr(struct ipa_ioc_get_hdr *lookup);
 
@@ -1462,7 +1478,8 @@
 /*
  * Header Processing Context
  */
-int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs);
+int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs,
+							bool user_only);
 
 int ipa2_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls);
 
@@ -1474,11 +1491,14 @@
  */
 int ipa2_add_rt_rule(struct ipa_ioc_add_rt_rule *rules);
 
+int ipa2_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules,
+	bool user_only);
+
 int ipa2_del_rt_rule(struct ipa_ioc_del_rt_rule *hdls);
 
 int ipa2_commit_rt(enum ipa_ip_type ip);
 
-int ipa2_reset_rt(enum ipa_ip_type ip);
+int ipa2_reset_rt(enum ipa_ip_type ip, bool user_only);
 
 int ipa2_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup);
 
@@ -1493,13 +1513,16 @@
  */
 int ipa2_add_flt_rule(struct ipa_ioc_add_flt_rule *rules);
 
+int ipa2_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules,
+	bool user_only);
+
 int ipa2_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls);
 
 int ipa2_mdfy_flt_rule(struct ipa_ioc_mdfy_flt_rule *rules);
 
 int ipa2_commit_flt(enum ipa_ip_type ip);
 
-int ipa2_reset_flt(enum ipa_ip_type ip);
+int ipa2_reset_flt(enum ipa_ip_type ip, bool user_only);
 
 /*
  * NAT
@@ -1517,6 +1540,7 @@
  */
 int ipa2_send_msg(struct ipa_msg_meta *meta, void *buff,
 		  ipa_msg_free_fn callback);
+int ipa2_resend_wlan_msg(void);
 int ipa2_register_pull_msg(struct ipa_msg_meta *meta, ipa_msg_pull_fn callback);
 int ipa2_deregister_pull_msg(struct ipa_msg_meta *meta);
 
@@ -1584,7 +1608,8 @@
 int ipa2_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *inp,
 		ipa_notify_cb notify, void *priv, u8 hdr_len,
 		struct ipa_ntn_conn_out_params *outp);
-int ipa2_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl);
+int ipa2_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl,
+	struct ipa_ntn_conn_in_params *params);
 int ipa2_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *), void *priv);
 void ipa2_ntn_uc_dereg_rdyCB(void);
 
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
index 9e68843..f1f6b90 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,7 @@
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include "ipa_i.h"
+#include <linux/msm_ipa.h>
 
 struct ipa_intf {
 	char name[IPA_RESOURCE_NAME_MAX];
@@ -379,6 +380,108 @@
 	kfree(buff);
 }
 
+static int wlan_msg_process(struct ipa_msg_meta *meta, void *buff)
+{
+	struct ipa_push_msg *msg_dup;
+	struct ipa_wlan_msg_ex *event_ex_cur_con = NULL;
+	struct ipa_wlan_msg_ex *event_ex_list = NULL;
+	struct ipa_wlan_msg *event_ex_cur_discon = NULL;
+	void *data_dup = NULL;
+	struct ipa_push_msg *entry;
+	struct ipa_push_msg *next;
+	int cnt = 0, total = 0, max = 0;
+	uint8_t mac[IPA_MAC_ADDR_SIZE];
+	uint8_t mac2[IPA_MAC_ADDR_SIZE];
+
+	if (meta->msg_type == WLAN_CLIENT_CONNECT_EX) {
+		/* debug print */
+		event_ex_cur_con = buff;
+		for (cnt = 0; cnt < event_ex_cur_con->num_of_attribs; cnt++) {
+			if (event_ex_cur_con->attribs[cnt].attrib_type ==
+				WLAN_HDR_ATTRIB_MAC_ADDR) {
+				IPADBG("%02x:%02x:%02x:%02x:%02x:%02x,(%d)\n",
+				event_ex_cur_con->attribs[cnt].u.mac_addr[0],
+				event_ex_cur_con->attribs[cnt].u.mac_addr[1],
+				event_ex_cur_con->attribs[cnt].u.mac_addr[2],
+				event_ex_cur_con->attribs[cnt].u.mac_addr[3],
+				event_ex_cur_con->attribs[cnt].u.mac_addr[4],
+				event_ex_cur_con->attribs[cnt].u.mac_addr[5],
+				meta->msg_type);
+			}
+		}
+
+		mutex_lock(&ipa_ctx->msg_wlan_client_lock);
+		msg_dup = kzalloc(sizeof(struct ipa_push_msg), GFP_KERNEL);
+		if (msg_dup == NULL) {
+			IPAERR("fail to alloc ipa_msg container\n");
+			return -ENOMEM;
+		}
+		msg_dup->meta = *meta;
+		if (meta->msg_len > 0 && buff) {
+			data_dup = kmalloc(meta->msg_len, GFP_KERNEL);
+			if (data_dup == NULL) {
+				IPAERR("fail to alloc data_dup container\n");
+				kfree(msg_dup);
+				return -ENOMEM;
+			}
+			memcpy(data_dup, buff, meta->msg_len);
+			msg_dup->buff = data_dup;
+			msg_dup->callback = ipa2_send_msg_free;
+		}
+		list_add_tail(&msg_dup->link, &ipa_ctx->msg_wlan_client_list);
+		mutex_unlock(&ipa_ctx->msg_wlan_client_lock);
+	}
+
+	/* remove the cache */
+	if (meta->msg_type == WLAN_CLIENT_DISCONNECT) {
+		/* debug print */
+		event_ex_cur_discon = buff;
+		IPADBG("Mac %02x:%02x:%02x:%02x:%02x:%02x,msg %d\n",
+		event_ex_cur_discon->mac_addr[0],
+		event_ex_cur_discon->mac_addr[1],
+		event_ex_cur_discon->mac_addr[2],
+		event_ex_cur_discon->mac_addr[3],
+		event_ex_cur_discon->mac_addr[4],
+		event_ex_cur_discon->mac_addr[5],
+		meta->msg_type);
+		memcpy(mac2,
+			event_ex_cur_discon->mac_addr,
+			sizeof(mac2));
+
+		mutex_lock(&ipa_ctx->msg_wlan_client_lock);
+		list_for_each_entry_safe(entry, next,
+				&ipa_ctx->msg_wlan_client_list,
+				link) {
+			event_ex_list = entry->buff;
+			max = event_ex_list->num_of_attribs;
+			for (cnt = 0; cnt < max; cnt++) {
+				memcpy(mac,
+					event_ex_list->attribs[cnt].u.mac_addr,
+					sizeof(mac));
+				if (event_ex_list->attribs[cnt].attrib_type ==
+					WLAN_HDR_ATTRIB_MAC_ADDR) {
+					pr_debug("%02x:%02x:%02x:%02x:%02x:%02x\n",
+					mac[0],	mac[1], mac[2],
+					mac[3],	mac[4],	mac[5]);
+
+					/* compare to delete one*/
+					if (memcmp(mac2,
+						mac,
+						sizeof(mac)) == 0) {
+						IPADBG("clean %d\n", total);
+						list_del(&entry->link);
+						kfree(entry);
+						break;
+					}
+				}
+			}
+			total++;
+		}
+		mutex_unlock(&ipa_ctx->msg_wlan_client_lock);
+	}
+	return 0;
+}
+
 /**
  * ipa2_send_msg() - Send "message" from kernel client to IPA driver
  * @meta: [in] message meta-data
@@ -438,6 +541,11 @@
 
 	mutex_lock(&ipa_ctx->msg_lock);
 	list_add_tail(&msg->link, &ipa_ctx->msg_list);
+	/* support for softap client event cache */
+	if (wlan_msg_process(meta, buff))
+		IPAERR("wlan_msg_process failed\n");
+
+	/* unlock only after process */
 	mutex_unlock(&ipa_ctx->msg_lock);
 	IPA_STATS_INC_CNT(ipa_ctx->stats.msg_w[meta->msg_type]);
 
@@ -449,6 +557,73 @@
 }
 
 /**
+ * ipa2_resend_wlan_msg() - Resend cached "message" to IPACM
+ *
+ * resend wlan client connect events to user-space
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+int ipa2_resend_wlan_msg(void)
+{
+	struct ipa_wlan_msg_ex *event_ex_list = NULL;
+	struct ipa_push_msg *entry;
+	struct ipa_push_msg *next;
+	int cnt = 0, total = 0;
+	struct ipa_push_msg *msg;
+	void *data = NULL;
+
+	IPADBG("\n");
+
+	mutex_lock(&ipa_ctx->msg_wlan_client_lock);
+	list_for_each_entry_safe(entry, next, &ipa_ctx->msg_wlan_client_list,
+			link) {
+
+		event_ex_list = entry->buff;
+		for (cnt = 0; cnt < event_ex_list->num_of_attribs; cnt++) {
+			if (event_ex_list->attribs[cnt].attrib_type ==
+				WLAN_HDR_ATTRIB_MAC_ADDR) {
+				IPADBG("%d-Mac %02x:%02x:%02x:%02x:%02x:%02x\n",
+				total,
+				event_ex_list->attribs[cnt].u.mac_addr[0],
+				event_ex_list->attribs[cnt].u.mac_addr[1],
+				event_ex_list->attribs[cnt].u.mac_addr[2],
+				event_ex_list->attribs[cnt].u.mac_addr[3],
+				event_ex_list->attribs[cnt].u.mac_addr[4],
+				event_ex_list->attribs[cnt].u.mac_addr[5]);
+			}
+		}
+
+		msg = kzalloc(sizeof(struct ipa_push_msg), GFP_KERNEL);
+		if (msg == NULL) {
+			IPAERR("fail to alloc ipa_msg container\n");
+			mutex_unlock(&ipa_ctx->msg_wlan_client_lock);
+			return -ENOMEM;
+		}
+		msg->meta = entry->meta;
+		data = kmalloc(entry->meta.msg_len, GFP_KERNEL);
+		if (data == NULL) {
+			IPAERR("fail to alloc data container\n");
+			kfree(msg);
+			mutex_unlock(&ipa_ctx->msg_wlan_client_lock);
+			return -ENOMEM;
+		}
+		memcpy(data, entry->buff, entry->meta.msg_len);
+		msg->buff = data;
+		msg->callback = ipa2_send_msg_free;
+		mutex_lock(&ipa_ctx->msg_lock);
+		list_add_tail(&msg->link, &ipa_ctx->msg_list);
+		mutex_unlock(&ipa_ctx->msg_lock);
+		wake_up(&ipa_ctx->msg_waitq);
+
+		total++;
+	}
+	mutex_unlock(&ipa_ctx->msg_wlan_client_lock);
+	return 0;
+}
+
+/**
  * ipa2_register_pull_msg() - register pull message type
  * @meta: [in] message meta-data
  * @callback: [in] pull callback
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c
index 50b2706..c043bad 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -769,12 +769,6 @@
 		base_addr = ipa_ctx->nat_mem.tmp_dma_handle;
 	}
 
-	if (del->public_ip_addr == 0) {
-		IPADBG("Bad Parameter\n");
-		result = -EPERM;
-		goto bail;
-	}
-
 	memset(&desc, 0, sizeof(desc));
 	/* NO-OP IC for ensuring that IPA pipeline is empty */
 	reg_write_nop = kzalloc(sizeof(*reg_write_nop), flag);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c
index 4ffbd55..17576de 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -514,6 +514,14 @@
 	int rc;
 	int i;
 
+	/* check if modem up */
+	if (!qmi_indication_fin ||
+		!qmi_modem_init_fin ||
+		!ipa_q6_clnt) {
+		IPAWANDBG("modem QMI haven't up yet\n");
+		return -EINVAL;
+	}
+
 	/* check if the filter rules from IPACM is valid */
 	if (req->filter_spec_list_len == 0) {
 		IPAWANDBG("IPACM pass zero rules to Q6\n");
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
index 66a8d0b..7710279 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
@@ -1027,7 +1027,8 @@
 }
 
 static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name,
-		const struct ipa_rt_rule *rule, u8 at_rear, u32 *rule_hdl)
+		const struct ipa_rt_rule *rule, u8 at_rear, u32 *rule_hdl,
+		bool user)
 {
 	struct ipa_rt_tbl *tbl;
 	struct ipa_rt_entry *entry;
@@ -1102,6 +1103,7 @@
 	IPADBG_LOW("rule_cnt=%d\n", tbl->rule_cnt);
 	*rule_hdl = id;
 	entry->id = id;
+	entry->ipacm_installed = user;
 
 	return 0;
 
@@ -1127,6 +1129,21 @@
  */
 int ipa2_add_rt_rule(struct ipa_ioc_add_rt_rule *rules)
 {
+	return ipa2_add_rt_rule_usr(rules, false);
+}
+
+/**
+ * ipa2_add_rt_rule_usr() - Add the specified routing rules to SW and optionally
+ * commit to IPA HW
+ * @rules:		[inout] set of routing rules to add
+ * @user_only:	[in] indicate installed by userspace module
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+int ipa2_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, bool user_only)
+{
 	int i;
 	int ret;
 
@@ -1141,7 +1158,8 @@
 		if (__ipa_add_rt_rule(rules->ip, rules->rt_tbl_name,
 					&rules->rules[i].rule,
 					rules->rules[i].at_rear,
-					&rules->rules[i].rt_rule_hdl)) {
+					&rules->rules[i].rt_rule_hdl,
+					user_only)) {
 			IPAERR_RL("failed to add rt rule %d\n", i);
 			rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED;
 		} else {
@@ -1310,13 +1328,14 @@
 /**
  * ipa2_reset_rt() - reset the current SW routing table of specified type
  * (does not commit to HW)
- * @ip:	The family of routing tables
+ * @ip:			[in] The family of routing tables
+ * @user_only:	[in] indicate delete rules installed by userspace
  *
  * Returns:	0 on success, negative on failure
  *
  * Note:	Should not be called from atomic context
  */
-int ipa2_reset_rt(enum ipa_ip_type ip)
+int ipa2_reset_rt(enum ipa_ip_type ip, bool user_only)
 {
 	struct ipa_rt_tbl *tbl;
 	struct ipa_rt_tbl *tbl_next;
@@ -1326,6 +1345,7 @@
 	struct ipa_rt_tbl_set *rset;
 	u32 apps_start_idx;
 	int id;
+	bool tbl_user = false;
 
 	if (ip >= IPA_IP_MAX) {
 		IPAERR_RL("bad parm\n");
@@ -1345,7 +1365,7 @@
 	 * issue a reset on the filtering module of same IP type since
 	 * filtering rules point to routing tables
 	 */
-	if (ipa2_reset_flt(ip))
+	if (ipa2_reset_flt(ip, user_only))
 		IPAERR_RL("fail to reset flt ip=%d\n", ip);
 
 	set = &ipa_ctx->rt_tbl_set[ip];
@@ -1353,6 +1373,7 @@
 	mutex_lock(&ipa_ctx->lock);
 	IPADBG("reset rt ip=%d\n", ip);
 	list_for_each_entry_safe(tbl, tbl_next, &set->head_rt_tbl_list, link) {
+		tbl_user = false;
 		list_for_each_entry_safe(rule, rule_next,
 					 &tbl->head_rt_rule_list, link) {
 			if (ipa_id_find(rule->id) == NULL) {
@@ -1361,25 +1382,34 @@
 				return -EFAULT;
 			}
 
+			/* indicate if tbl used for user-specified rules*/
+			if (rule->ipacm_installed) {
+				IPADBG("tbl_user %d, tbl-index %d\n",
+				tbl_user, tbl->id);
+				tbl_user = true;
+			}
 			/*
 			 * for the "default" routing tbl, remove all but the
 			 *  last rule
 			 */
 			if (tbl->idx == apps_start_idx && tbl->rule_cnt == 1)
 				continue;
+			if (!user_only ||
+				rule->ipacm_installed) {
+				list_del(&rule->link);
+				tbl->rule_cnt--;
+				if (rule->hdr)
+					__ipa_release_hdr(rule->hdr->id);
+				else if (rule->proc_ctx)
+					__ipa_release_hdr_proc_ctx(
+						rule->proc_ctx->id);
+				rule->cookie = 0;
+				id = rule->id;
+				kmem_cache_free(ipa_ctx->rt_rule_cache, rule);
 
-			list_del(&rule->link);
-			tbl->rule_cnt--;
-			if (rule->hdr)
-				__ipa_release_hdr(rule->hdr->id);
-			else if (rule->proc_ctx)
-				__ipa_release_hdr_proc_ctx(rule->proc_ctx->id);
-			rule->cookie = 0;
-			id = rule->id;
-			kmem_cache_free(ipa_ctx->rt_rule_cache, rule);
-
-			/* remove the handle from the database */
-			ipa_id_remove(id);
+				/* remove the handle from the database */
+				ipa_id_remove(id);
+			}
 		}
 
 		if (ipa_id_find(tbl->id) == NULL) {
@@ -1391,24 +1421,28 @@
 
 		/* do not remove the "default" routing tbl which has index 0 */
 		if (tbl->idx != apps_start_idx) {
-			if (!tbl->in_sys) {
-				list_del(&tbl->link);
-				set->tbl_cnt--;
-				clear_bit(tbl->idx,
-					  &ipa_ctx->rt_idx_bitmap[ip]);
-				IPADBG("rst rt tbl_idx=%d tbl_cnt=%d\n",
-						tbl->idx, set->tbl_cnt);
-				kmem_cache_free(ipa_ctx->rt_tbl_cache, tbl);
-			} else {
-				list_move(&tbl->link, &rset->head_rt_tbl_list);
-				clear_bit(tbl->idx,
-					  &ipa_ctx->rt_idx_bitmap[ip]);
-				set->tbl_cnt--;
-				IPADBG("rst sys rt tbl_idx=%d tbl_cnt=%d\n",
-						tbl->idx, set->tbl_cnt);
+			if (!user_only || tbl_user) {
+				if (!tbl->in_sys) {
+					list_del(&tbl->link);
+					set->tbl_cnt--;
+					clear_bit(tbl->idx,
+						&ipa_ctx->rt_idx_bitmap[ip]);
+					IPADBG("rst rt tbl_idx=%d tbl_cnt=%d\n",
+							tbl->idx, set->tbl_cnt);
+					kmem_cache_free(ipa_ctx->rt_tbl_cache,
+						tbl);
+				} else {
+					list_move(&tbl->link,
+						&rset->head_rt_tbl_list);
+					clear_bit(tbl->idx,
+						&ipa_ctx->rt_idx_bitmap[ip]);
+					set->tbl_cnt--;
+					IPADBG("rst tbl_idx=%d cnt=%d\n",
+							tbl->idx, set->tbl_cnt);
+				}
+				/* remove the handle from the database */
+				ipa_id_remove(id);
 			}
-			/* remove the handle from the database */
-			ipa_id_remove(id);
 		}
 	}
 	mutex_unlock(&ipa_ctx->lock);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_ntn.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_ntn.c
index d4116eb..6b671da 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_ntn.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_ntn.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -377,7 +377,7 @@
  */
 
 int ipa2_tear_down_uc_offload_pipes(int ipa_ep_idx_ul,
-		int ipa_ep_idx_dl)
+		int ipa_ep_idx_dl, struct ipa_ntn_conn_in_params *params)
 {
 	struct ipa_mem_buffer cmd;
 	struct ipa_ep_context *ep_ul, *ep_dl;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
index c9273ec..d76c208 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
@@ -5020,6 +5020,7 @@
 	api_ctrl->ipa_cfg_ep_holb_by_client = ipa2_cfg_ep_holb_by_client;
 	api_ctrl->ipa_cfg_ep_ctrl = ipa2_cfg_ep_ctrl;
 	api_ctrl->ipa_add_hdr = ipa2_add_hdr;
+	api_ctrl->ipa_add_hdr_usr = ipa2_add_hdr_usr;
 	api_ctrl->ipa_del_hdr = ipa2_del_hdr;
 	api_ctrl->ipa_commit_hdr = ipa2_commit_hdr;
 	api_ctrl->ipa_reset_hdr = ipa2_reset_hdr;
@@ -5029,6 +5030,7 @@
 	api_ctrl->ipa_add_hdr_proc_ctx = ipa2_add_hdr_proc_ctx;
 	api_ctrl->ipa_del_hdr_proc_ctx = ipa2_del_hdr_proc_ctx;
 	api_ctrl->ipa_add_rt_rule = ipa2_add_rt_rule;
+	api_ctrl->ipa_add_rt_rule_usr = ipa2_add_rt_rule_usr;
 	api_ctrl->ipa_del_rt_rule = ipa2_del_rt_rule;
 	api_ctrl->ipa_commit_rt = ipa2_commit_rt;
 	api_ctrl->ipa_reset_rt = ipa2_reset_rt;
@@ -5037,6 +5039,7 @@
 	api_ctrl->ipa_query_rt_index = ipa2_query_rt_index;
 	api_ctrl->ipa_mdfy_rt_rule = ipa2_mdfy_rt_rule;
 	api_ctrl->ipa_add_flt_rule = ipa2_add_flt_rule;
+	api_ctrl->ipa_add_flt_rule_usr = ipa2_add_flt_rule_usr;
 	api_ctrl->ipa_del_flt_rule = ipa2_del_flt_rule;
 	api_ctrl->ipa_mdfy_flt_rule = ipa2_mdfy_flt_rule;
 	api_ctrl->ipa_commit_flt = ipa2_commit_flt;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index da60ff5..0fc7b0e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -368,12 +368,49 @@
 	return cnt;
 }
 
+static int ipa3_clean_modem_rule(void)
+{
+	struct ipa_install_fltr_rule_req_msg_v01 *req;
+	struct ipa_install_fltr_rule_req_ex_msg_v01 *req_ex;
+	int val = 0;
+
+	if (ipa3_ctx->ipa_hw_type < IPA_HW_v3_0) {
+		req = kzalloc(
+			sizeof(struct ipa_install_fltr_rule_req_msg_v01),
+			GFP_KERNEL);
+		if (!req) {
+			IPAERR("mem allocated failed!\n");
+			return -ENOMEM;
+		}
+		req->filter_spec_list_valid = false;
+		req->filter_spec_list_len = 0;
+		req->source_pipe_index_valid = 0;
+		val = ipa3_qmi_filter_request_send(req);
+		kfree(req);
+	} else {
+		req_ex = kzalloc(
+			sizeof(struct ipa_install_fltr_rule_req_ex_msg_v01),
+			GFP_KERNEL);
+		if (!req_ex) {
+			IPAERR("mem allocated failed!\n");
+			return -ENOMEM;
+		}
+		req_ex->filter_spec_ex_list_valid = false;
+		req_ex->filter_spec_ex_list_len = 0;
+		req_ex->source_pipe_index_valid = 0;
+		val = ipa3_qmi_filter_request_ex_send(req_ex);
+		kfree(req_ex);
+	}
+
+	return val;
+}
+
 static int ipa3_active_clients_panic_notifier(struct notifier_block *this,
 		unsigned long event, void *ptr)
 {
 	ipa3_active_clients_log_print_table(active_clients_table_buf,
 			IPA3_ACTIVE_CLIENTS_TABLE_BUF_SIZE);
-	IPAERR("%s", active_clients_table_buf);
+	IPAERR("%s\n", active_clients_table_buf);
 
 	return NOTIFY_DONE;
 }
@@ -501,6 +538,19 @@
 	return NULL;
 }
 
+struct iommu_domain *ipa3_get_smmu_domain_by_type(enum ipa_smmu_cb_type cb_type)
+{
+
+	if (cb_type == IPA_SMMU_CB_WLAN && smmu_cb[IPA_SMMU_CB_WLAN].valid)
+		return smmu_cb[IPA_SMMU_CB_WLAN].iommu;
+
+	if (smmu_cb[cb_type].valid)
+		return smmu_cb[cb_type].mapping->domain;
+
+	IPAERR("CB#%d not valid\n", cb_type);
+
+	return NULL;
+}
 
 struct device *ipa3_get_dma_dev(void)
 {
@@ -542,7 +592,8 @@
 	kfree(buff);
 }
 
-static int ipa3_send_wan_msg(unsigned long usr_param, uint8_t msg_type, bool is_cache)
+static int ipa3_send_wan_msg(unsigned long usr_param, uint8_t msg_type,
+								bool is_cache)
 {
 	int retval;
 	struct ipa_wan_msg *wan_msg;
@@ -904,7 +955,8 @@
 			retval = -EFAULT;
 			break;
 		}
-		if (ipa3_add_hdr((struct ipa_ioc_add_hdr *)param)) {
+		if (ipa3_add_hdr_usr((struct ipa_ioc_add_hdr *)param,
+			true)) {
 			retval = -EFAULT;
 			break;
 		}
@@ -984,7 +1036,8 @@
 			retval = -EFAULT;
 			break;
 		}
-		if (ipa3_add_rt_rule((struct ipa_ioc_add_rt_rule *)param)) {
+		if (ipa3_add_rt_rule_usr((struct ipa_ioc_add_rt_rule *)param,
+				true)) {
 			retval = -EFAULT;
 			break;
 		}
@@ -1188,7 +1241,8 @@
 			retval = -EFAULT;
 			break;
 		}
-		if (ipa3_add_flt_rule((struct ipa_ioc_add_flt_rule *)param)) {
+		if (ipa3_add_flt_rule_usr((struct ipa_ioc_add_flt_rule *)param,
+				true)) {
 			retval = -EFAULT;
 			break;
 		}
@@ -1325,19 +1379,19 @@
 		retval = ipa3_commit_hdr();
 		break;
 	case IPA_IOC_RESET_HDR:
-		retval = ipa3_reset_hdr();
+		retval = ipa3_reset_hdr(false);
 		break;
 	case IPA_IOC_COMMIT_RT:
 		retval = ipa3_commit_rt(arg);
 		break;
 	case IPA_IOC_RESET_RT:
-		retval = ipa3_reset_rt(arg);
+		retval = ipa3_reset_rt(arg, false);
 		break;
 	case IPA_IOC_COMMIT_FLT:
 		retval = ipa3_commit_flt(arg);
 		break;
 	case IPA_IOC_RESET_FLT:
-		retval = ipa3_reset_flt(arg);
+		retval = ipa3_reset_flt(arg, false);
 		break;
 	case IPA_IOC_GET_RT_TBL:
 		if (copy_from_user(header, (const void __user *)arg,
@@ -1725,7 +1779,7 @@
 			break;
 		}
 		if (ipa3_add_hdr_proc_ctx(
-			(struct ipa_ioc_add_hdr_proc_ctx *)param)) {
+			(struct ipa_ioc_add_hdr_proc_ctx *)param, true)) {
 			retval = -EFAULT;
 			break;
 		}
@@ -1817,6 +1871,21 @@
 		}
 		break;
 
+	case IPA_IOC_CLEANUP:
+		/*Route and filter rules will also be clean*/
+		IPADBG("Got IPA_IOC_CLEANUP\n");
+		retval = ipa3_reset_hdr(true);
+		memset(&nat_del, 0, sizeof(nat_del));
+		nat_del.table_index = 0;
+		retval = ipa3_nat_del_cmd(&nat_del);
+		retval = ipa3_clean_modem_rule();
+		break;
+
+	case IPA_IOC_QUERY_WLAN_CLIENT:
+		IPADBG("Got IPA_IOC_QUERY_WLAN_CLIENT\n");
+		retval = ipa3_resend_wlan_msg();
+		break;
+
 	default:
 		IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 		return -ENOTTY;
@@ -1828,13 +1897,13 @@
 }
 
 /**
-* ipa3_setup_dflt_rt_tables() - Setup default routing tables
-*
-* Return codes:
-* 0: success
-* -ENOMEM: failed to allocate memory
-* -EPERM: failed to add the tables
-*/
+ * ipa3_setup_dflt_rt_tables() - Setup default routing tables
+ *
+ * Return codes:
+ * 0: success
+ * -ENOMEM: failed to allocate memory
+ * -EPERM: failed to add the tables
+ */
 int ipa3_setup_dflt_rt_tables(void)
 {
 	struct ipa_ioc_add_rt_rule *rt_rule;
@@ -1997,14 +2066,14 @@
 }
 
 /**
-* ipa3_init_q6_smem() - Initialize Q6 general memory and
-*                      header memory regions in IPA.
-*
-* Return codes:
-* 0: success
-* -ENOMEM: failed to allocate dma memory
-* -EFAULT: failed to send IPA command to initialize the memory
-*/
+ * ipa3_init_q6_smem() - Initialize Q6 general memory and
+ *                      header memory regions in IPA.
+ *
+ * Return codes:
+ * 0: success
+ * -ENOMEM: failed to allocate dma memory
+ * -EFAULT: failed to send IPA command to initialize the memory
+ */
 int ipa3_init_q6_smem(void)
 {
 	int rc;
@@ -2541,12 +2610,12 @@
 }
 
 /**
-* ipa3_q6_pre_shutdown_cleanup() - A cleanup for all Q6 related configuration
-*                    in IPA HW. This is performed in case of SSR.
-*
-* This is a mandatory procedure, in case one of the steps fails, the
-* AP needs to restart.
-*/
+ * ipa3_q6_pre_shutdown_cleanup() - A cleanup for all Q6 related configuration
+ *                    in IPA HW. This is performed in case of SSR.
+ *
+ * This is a mandatory procedure, in case one of the steps fails, the
+ * AP needs to restart.
+ */
 void ipa3_q6_pre_shutdown_cleanup(void)
 {
 	IPADBG_LOW("ENTER\n");
@@ -2564,8 +2633,8 @@
 		BUG();
 	}
 	/* Remove delay from Q6 PRODs to avoid pending descriptors
-	  * on pipe reset procedure
-	  */
+	 * on pipe reset procedure
+	 */
 	ipa3_q6_pipe_delay(false);
 
 	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
@@ -3479,11 +3548,11 @@
 }
 
 /**
-* ipa3_enable_clks() - Turn on IPA clocks
-*
-* Return codes:
-* None
-*/
+ * ipa3_enable_clks() - Turn on IPA clocks
+ *
+ * Return codes:
+ * None
+ */
 void ipa3_enable_clks(void)
 {
 	if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) {
@@ -3515,11 +3584,11 @@
 }
 
 /**
-* ipa3_disable_clks() - Turn off IPA clocks
-*
-* Return codes:
-* None
-*/
+ * ipa3_disable_clks() - Turn off IPA clocks
+ *
+ * Return codes:
+ * None
+ */
 void ipa3_disable_clks(void)
 {
 	if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) {
@@ -3561,28 +3630,28 @@
 }
 
 /**
-* ipa3_active_clients_log_mod() - Log a modification in the active clients
-* reference count
-*
-* This method logs any modification in the active clients reference count:
-* It logs the modification in the circular history buffer
-* It logs the modification in the hash table - looking for an entry,
-* creating one if needed and deleting one if needed.
-*
-* @id: ipa3_active client logging info struct to hold the log information
-* @inc: a boolean variable to indicate whether the modification is an increase
-* or decrease
-* @int_ctx: a boolean variable to indicate whether this call is being made from
-* an interrupt context and therefore should allocate GFP_ATOMIC memory
-*
-* Method process:
-* - Hash the unique identifier string
-* - Find the hash in the table
-*    1)If found, increase or decrease the reference count
-*    2)If not found, allocate a new hash table entry struct and initialize it
-* - Remove and deallocate unneeded data structure
-* - Log the call in the circular history buffer (unless it is a simple call)
-*/
+ * ipa3_active_clients_log_mod() - Log a modification in the active clients
+ * reference count
+ *
+ * This method logs any modification in the active clients reference count:
+ * It logs the modification in the circular history buffer
+ * It logs the modification in the hash table - looking for an entry,
+ * creating one if needed and deleting one if needed.
+ *
+ * @id: ipa3_active client logging info struct to hold the log information
+ * @inc: a boolean variable to indicate whether the modification is an increase
+ * or decrease
+ * @int_ctx: a boolean variable to indicate whether this call is being made from
+ * an interrupt context and therefore should allocate GFP_ATOMIC memory
+ *
+ * Method process:
+ * - Hash the unique identifier string
+ * - Find the hash in the table
+ *    1)If found, increase or decrease the reference count
+ *    2)If not found, allocate a new hash table entry struct and initialize it
+ * - Remove and deallocate unneeded data structure
+ * - Log the call in the circular history buffer (unless it is a simple call)
+ */
 void ipa3_active_clients_log_mod(struct ipa_active_client_logging_info *id,
 		bool inc, bool int_ctx)
 {
@@ -3660,12 +3729,12 @@
 }
 
 /**
-* ipa3_inc_client_enable_clks() - Increase active clients counter, and
-* enable ipa clocks if necessary
-*
-* Return codes:
-* None
-*/
+ * ipa3_inc_client_enable_clks() - Increase active clients counter, and
+ * enable ipa clocks if necessary
+ *
+ * Return codes:
+ * None
+ */
 void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id)
 {
 	int ret;
@@ -3698,13 +3767,13 @@
 }
 
 /**
-* ipa3_inc_client_enable_clks_no_block() - Only increment the number of active
-* clients if no asynchronous actions should be done. Asynchronous actions are
-* locking a mutex and waking up IPA HW.
-*
-* Return codes: 0 for success
-*		-EPERM if an asynchronous action should have been done
-*/
+ * ipa3_inc_client_enable_clks_no_block() - Only increment the number of active
+ * clients if no asynchronous actions should be done. Asynchronous actions are
+ * locking a mutex and waking up IPA HW.
+ *
+ * Return codes: 0 for success
+ *		-EPERM if an asynchronous action should have been done
+ */
 int ipa3_inc_client_enable_clks_no_block(struct ipa_active_client_logging_info
 		*id)
 {
@@ -3810,12 +3879,12 @@
 }
 
 /**
-* ipa3_inc_acquire_wakelock() - Increase active clients counter, and
-* acquire wakelock if necessary
-*
-* Return codes:
-* None
-*/
+ * ipa3_inc_acquire_wakelock() - Increase active clients counter, and
+ * acquire wakelock if necessary
+ *
+ * Return codes:
+ * None
+ */
 void ipa3_inc_acquire_wakelock(void)
 {
 	unsigned long flags;
@@ -3997,12 +4066,12 @@
 }
 
 /**
-* ipa3_suspend_handler() - Handles the suspend interrupt:
-* wakes up the suspended peripheral by requesting its consumer
-* @interrupt:		Interrupt type
-* @private_data:	The client's private data
-* @interrupt_data:	Interrupt specific information data
-*/
+ * ipa3_suspend_handler() - Handles the suspend interrupt:
+ * wakes up the suspended peripheral by requesting its consumer
+ * @interrupt:		Interrupt type
+ * @private_data:	The client's private data
+ * @interrupt_data:	Interrupt specific information data
+ */
 void ipa3_suspend_handler(enum ipa_irq_type interrupt,
 				void *private_data,
 				void *interrupt_data)
@@ -4081,12 +4150,12 @@
 }
 
 /**
-* ipa3_restore_suspend_handler() - restores the original suspend IRQ handler
-* as it was registered in the IPA init sequence.
-* Return codes:
-* 0: success
-* -EPERM: failed to remove current handler or failed to add original handler
-*/
+ * ipa3_restore_suspend_handler() - restores the original suspend IRQ handler
+ * as it was registered in the IPA init sequence.
+ * Return codes:
+ * 0: success
+ * -EPERM: failed to remove current handler or failed to add original handler
+ */
 int ipa3_restore_suspend_handler(void)
 {
 	int result = 0;
@@ -4280,6 +4349,9 @@
 	if (res)
 		IPAERR("uC panic handler failed %d\n", res);
 
+	if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) != 0)
+		ipahal_print_all_regs();
+
 	return NOTIFY_DONE;
 }
 
@@ -4532,13 +4604,18 @@
 
 	/*
 	 * IPAv3.5 and above requires to disable prefetch for USB in order
-	 * to allow MBIM to work, currently MBIM is not needed in MHI mode.
+	 * to allow MBIM to work.
 	 */
 	if ((ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5
 		&& ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) &&
 		(!ipa3_ctx->ipa_config_is_mhi))
 		ipa3_disable_prefetch(IPA_CLIENT_USB_CONS);
 
+	if ((ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5
+		&& ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) &&
+		(ipa3_ctx->ipa_config_is_mhi))
+		ipa3_disable_prefetch(IPA_CLIENT_MHI_CONS);
+
 	memset(&gsi_props, 0, sizeof(gsi_props));
 	gsi_props.ver = ipa3_get_gsi_ver(resource_p->ipa_hw_type);
 	gsi_props.ee = resource_p->ee;
@@ -4919,37 +4996,37 @@
 }
 
 /**
-* ipa3_pre_init() - Initialize the IPA Driver.
-* This part contains all initialization which doesn't require IPA HW, such
-* as structure allocations and initializations, register writes, etc.
-*
-* @resource_p:	contain platform specific values from DST file
-* @pdev:	The platform device structure representing the IPA driver
-*
-* Function initialization process:
-* Allocate memory for the driver context data struct
-* Initializing the ipa3_ctx with :
-*    1)parsed values from the dts file
-*    2)parameters passed to the module initialization
-*    3)read HW values(such as core memory size)
-* Map IPA core registers to CPU memory
-* Restart IPA core(HW reset)
-* Initialize the look-aside caches(kmem_cache/slab) for filter,
-*   routing and IPA-tree
-* Create memory pool with 4 objects for DMA operations(each object
-*   is 512Bytes long), this object will be use for tx(A5->IPA)
-* Initialize lists head(routing, hdr, system pipes)
-* Initialize mutexes (for ipa_ctx and NAT memory mutexes)
-* Initialize spinlocks (for list related to A5<->IPA pipes)
-* Initialize 2 single-threaded work-queue named "ipa rx wq" and "ipa tx wq"
-* Initialize Red-Black-Tree(s) for handles of header,routing rule,
-*  routing table ,filtering rule
-* Initialize the filter block by committing IPV4 and IPV6 default rules
-* Create empty routing table in system memory(no committing)
-* Create a char-device for IPA
-* Initialize IPA RM (resource manager)
-* Configure GSI registers (in GSI case)
-*/
+ * ipa3_pre_init() - Initialize the IPA Driver.
+ * This part contains all initialization which doesn't require IPA HW, such
+ * as structure allocations and initializations, register writes, etc.
+ *
+ * @resource_p:	contain platform specific values from DST file
+ * @pdev:	The platform device structure representing the IPA driver
+ *
+ * Function initialization process:
+ * Allocate memory for the driver context data struct
+ * Initializing the ipa3_ctx with :
+ *    1)parsed values from the dts file
+ *    2)parameters passed to the module initialization
+ *    3)read HW values(such as core memory size)
+ * Map IPA core registers to CPU memory
+ * Restart IPA core(HW reset)
+ * Initialize the look-aside caches(kmem_cache/slab) for filter,
+ *   routing and IPA-tree
+ * Create memory pool with 4 objects for DMA operations(each object
+ *   is 512Bytes long), this object will be use for tx(A5->IPA)
+ * Initialize lists head(routing, hdr, system pipes)
+ * Initialize mutexes (for ipa_ctx and NAT memory mutexes)
+ * Initialize spinlocks (for list related to A5<->IPA pipes)
+ * Initialize 2 single-threaded work-queue named "ipa rx wq" and "ipa tx wq"
+ * Initialize Red-Black-Tree(s) for handles of header,routing rule,
+ *  routing table ,filtering rule
+ * Initialize the filter block by committing IPV4 and IPV6 default rules
+ * Create empty routing table in system memory(no committing)
+ * Create a char-device for IPA
+ * Initialize IPA RM (resource manager)
+ * Configure GSI registers (in GSI case)
+ */
 static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
 		struct platform_device *ipa_pdev)
 {
@@ -4994,6 +5071,7 @@
 	ipa3_ctx->gsi_ch20_wa = resource_p->gsi_ch20_wa;
 	ipa3_ctx->use_ipa_pm = resource_p->use_ipa_pm;
 	ipa3_ctx->ipa3_active_clients_logging.log_rdy = false;
+	ipa3_ctx->ipa_config_is_mhi = resource_p->ipa_mhi_dynamic_config;
 	ipa3_ctx->mhi_evid_limits[0] = resource_p->mhi_evid_limits[0];
 	ipa3_ctx->mhi_evid_limits[1] = resource_p->mhi_evid_limits[1];
 
@@ -5229,6 +5307,10 @@
 	init_waitqueue_head(&ipa3_ctx->msg_waitq);
 	mutex_init(&ipa3_ctx->msg_lock);
 
+	/* store wlan client-connect-msg-list */
+	INIT_LIST_HEAD(&ipa3_ctx->msg_wlan_client_list);
+	mutex_init(&ipa3_ctx->msg_wlan_client_lock);
+
 	mutex_init(&ipa3_ctx->lock);
 	mutex_init(&ipa3_ctx->q6_proxy_clk_vote_mutex);
 	mutex_init(&ipa3_ctx->ipa_cne_evt_lock);
@@ -5520,6 +5602,7 @@
 	ipa_drv_res->ipa3_hw_mode = 0;
 	ipa_drv_res->modem_cfg_emb_pipe_flt = false;
 	ipa_drv_res->ipa_wdi2 = false;
+	ipa_drv_res->ipa_mhi_dynamic_config = false;
 	ipa_drv_res->use_64_bit_dma_mask = false;
 	ipa_drv_res->use_bw_vote = false;
 	ipa_drv_res->wan_rx_ring_size = IPA_GENERIC_RX_POOL_SZ;
@@ -5582,6 +5665,13 @@
 		ipa_drv_res->use_ipa_teth_bridge
 		? "True" : "False");
 
+	ipa_drv_res->ipa_mhi_dynamic_config =
+			of_property_read_bool(pdev->dev.of_node,
+			"qcom,use-ipa-in-mhi-mode");
+	IPADBG(": ipa_mhi_dynamic_config (%s)\n",
+		ipa_drv_res->ipa_mhi_dynamic_config
+		? "True" : "False");
+
 	ipa_drv_res->modem_cfg_emb_pipe_flt =
 			of_property_read_bool(pdev->dev.of_node,
 			"qcom,modem-cfg-emb-pipe-flt");
@@ -6385,7 +6475,7 @@
  *
  * Returns -EAGAIN to runtime_pm framework in case IPA is in use by AP.
  * This will postpone the suspend operation until IPA is no longer used by AP.
-*/
+ */
 int ipa3_ap_suspend(struct device *dev)
 {
 	int i;
@@ -6418,14 +6508,14 @@
 }
 
 /**
-* ipa3_ap_resume() - resume callback for runtime_pm
-* @dev: pointer to device
-*
-* This callback will be invoked by the runtime_pm framework when an AP resume
-* operation is invoked.
-*
-* Always returns 0 since resume should always succeed.
-*/
+ * ipa3_ap_resume() - resume callback for runtime_pm
+ * @dev: pointer to device
+ *
+ * This callback will be invoked by the runtime_pm framework when an AP resume
+ * operation is invoked.
+ *
+ * Always returns 0 since resume should always succeed.
+ */
 int ipa3_ap_resume(struct device *dev)
 {
 	return 0;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
index 93f2597..fe39440 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
@@ -516,15 +516,23 @@
 		return true;
 }
 
-int ipa3_smmu_map_peer_reg(phys_addr_t phys_addr, bool map)
+int ipa3_smmu_map_peer_reg(phys_addr_t phys_addr, bool map,
+	enum ipa_smmu_cb_type cb_type)
 {
 	struct iommu_domain *smmu_domain;
 	int res;
 
-	if (ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_AP])
-		return 0;
+	if (cb_type >= IPA_SMMU_CB_MAX) {
+		IPAERR("invalid cb_type\n");
+		return -EINVAL;
+	}
 
-	smmu_domain = ipa3_get_smmu_domain();
+	if (ipa3_ctx->s1_bypass_arr[cb_type]) {
+		IPADBG("CB# %d is set to s1 bypass\n", cb_type);
+		return 0;
+	}
+
+	smmu_domain = ipa3_get_smmu_domain_by_type(cb_type);
 	if (!smmu_domain) {
 		IPAERR("invalid smmu domain\n");
 		return -EINVAL;
@@ -548,7 +556,8 @@
 	return 0;
 }
 
-int ipa3_smmu_map_peer_buff(u64 iova, u32 size, bool map, struct sg_table *sgt)
+int ipa3_smmu_map_peer_buff(u64 iova, u32 size, bool map, struct sg_table *sgt,
+	enum ipa_smmu_cb_type cb_type)
 {
 	struct iommu_domain *smmu_domain;
 	int res;
@@ -560,10 +569,17 @@
 	int i;
 	struct page *page;
 
-	if (ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_AP])
-		return 0;
+	if (cb_type >= IPA_SMMU_CB_MAX) {
+		IPAERR("invalid cb_type\n");
+		return -EINVAL;
+	}
 
-	smmu_domain = ipa3_get_smmu_domain();
+	if (ipa3_ctx->s1_bypass_arr[cb_type]) {
+		IPADBG("CB# %d is set to s1 bypass\n", cb_type);
+		return 0;
+	}
+
+	smmu_domain = ipa3_get_smmu_domain_by_type(cb_type);
 	if (!smmu_domain) {
 		IPAERR("invalid smmu domain\n");
 		return -EINVAL;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index 07773eb..ee9c49c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -1894,6 +1894,16 @@
 	return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt);
 }
 
+static ssize_t ipa3_read_ipahal_regs(struct file *file, char __user *ubuf,
+		size_t count, loff_t *ppos)
+{
+	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
+	ipahal_print_all_regs();
+	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
+
+	return 0;
+}
+
 static void ipa_dump_status(struct ipahal_pkt_status *status)
 {
 	IPA_DUMP_STATUS_FIELD(status_opcode);
@@ -2160,6 +2170,10 @@
 		"enable_low_prio_print", IPA_WRITE_ONLY_MODE, NULL, {
 			.write = ipa3_enable_ipc_low,
 		}
+	}, {
+		"ipa_dump_regs", IPA_READ_ONLY_MODE, NULL, {
+			.read = ipa3_read_ipahal_regs,
+		}
 	}
 };
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
index 0f3940f..29fd547 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -809,7 +809,7 @@
 
 static int __ipa_create_flt_entry(struct ipa3_flt_entry **entry,
 		const struct ipa_flt_rule *rule, struct ipa3_rt_tbl *rt_tbl,
-		struct ipa3_flt_tbl *tbl)
+		struct ipa3_flt_tbl *tbl, bool user)
 {
 	int id;
 
@@ -834,6 +834,7 @@
 		}
 	}
 	(*entry)->rule_id = id;
+	(*entry)->ipacm_installed = user;
 
 	return 0;
 
@@ -871,7 +872,7 @@
 
 static int __ipa_add_flt_rule(struct ipa3_flt_tbl *tbl, enum ipa_ip_type ip,
 			      const struct ipa_flt_rule *rule, u8 add_rear,
-			      u32 *rule_hdl)
+			      u32 *rule_hdl, bool user)
 {
 	struct ipa3_flt_entry *entry;
 	struct ipa3_rt_tbl *rt_tbl = NULL;
@@ -879,7 +880,7 @@
 	if (__ipa_validate_flt_rule(rule, &rt_tbl, ip))
 		goto error;
 
-	if (__ipa_create_flt_entry(&entry, rule, rt_tbl, tbl))
+	if (__ipa_create_flt_entry(&entry, rule, rt_tbl, tbl, user))
 		goto error;
 
 	if (add_rear) {
@@ -929,7 +930,7 @@
 	if (__ipa_validate_flt_rule(rule, &rt_tbl, ip))
 		goto error;
 
-	if (__ipa_create_flt_entry(&entry, rule, rt_tbl, tbl))
+	if (__ipa_create_flt_entry(&entry, rule, rt_tbl, tbl, true))
 		goto error;
 
 	list_add(&entry->link, &((*add_after_entry)->link));
@@ -1079,7 +1080,7 @@
 
 static int __ipa_add_ep_flt_rule(enum ipa_ip_type ip, enum ipa_client_type ep,
 				 const struct ipa_flt_rule *rule, u8 add_rear,
-				 u32 *rule_hdl)
+				 u32 *rule_hdl, bool user)
 {
 	struct ipa3_flt_tbl *tbl;
 	int ipa_ep_idx;
@@ -1097,12 +1098,13 @@
 	tbl = &ipa3_ctx->flt_tbl[ipa_ep_idx][ip];
 	IPADBG_LOW("add ep flt rule ip=%d ep=%d\n", ip, ep);
 
-	return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl);
+	return __ipa_add_flt_rule(tbl, ip, rule, add_rear, rule_hdl, user);
 }
 
 /**
  * ipa3_add_flt_rule() - Add the specified filtering rules to SW and optionally
  * commit to IPA HW
+ * @rules:	[inout] set of filtering rules to add
  *
  * Returns:	0 on success, negative on failure
  *
@@ -1110,6 +1112,20 @@
  */
 int ipa3_add_flt_rule(struct ipa_ioc_add_flt_rule *rules)
 {
+	return ipa3_add_flt_rule_usr(rules, false);
+}
+/**
+ * ipa3_add_flt_rule_usr() - Add the specified filtering rules to
+ * SW and optionally commit to IPA HW
+ * @rules:	[inout] set of filtering rules to add
+ * @user_only:	[in] indicate rules installed by userspace
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+int ipa3_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, bool user_only)
+{
 	int i;
 	int result;
 
@@ -1125,7 +1141,8 @@
 			result = __ipa_add_ep_flt_rule(rules->ip, rules->ep,
 					&rules->rules[i].rule,
 					rules->rules[i].at_rear,
-					&rules->rules[i].flt_rule_hdl);
+					&rules->rules[i].flt_rule_hdl,
+					user_only);
 		else
 			result = -1;
 
@@ -1372,18 +1389,20 @@
  * ipa3_reset_flt() - Reset the current SW filtering table of specified type
  * (does not commit to HW)
  * @ip:	[in] the family of routing tables
+ * @user_only:	[in] indicate rules deleted by userspace
  *
  * Returns:	0 on success, negative on failure
  *
  * Note:	Should not be called from atomic context
  */
-int ipa3_reset_flt(enum ipa_ip_type ip)
+int ipa3_reset_flt(enum ipa_ip_type ip, bool user_only)
 {
 	struct ipa3_flt_tbl *tbl;
 	struct ipa3_flt_entry *entry;
 	struct ipa3_flt_entry *next;
 	int i;
 	int id;
+	int rule_id;
 
 	if (ip >= IPA_IP_MAX) {
 		IPAERR_RL("bad parm\n");
@@ -1403,21 +1422,27 @@
 				mutex_unlock(&ipa3_ctx->lock);
 				return -EFAULT;
 			}
-			list_del(&entry->link);
-			entry->tbl->rule_cnt--;
-			if (entry->rt_tbl)
-				entry->rt_tbl->ref_cnt--;
-			/* if rule id was allocated from idr, remove it */
-			if ((entry->rule_id < ipahal_get_rule_id_hi_bit()) &&
-				(entry->rule_id >= ipahal_get_low_rule_id()))
-				idr_remove(entry->tbl->rule_ids,
-					entry->rule_id);
-			entry->cookie = 0;
-			id = entry->id;
-			kmem_cache_free(ipa3_ctx->flt_rule_cache, entry);
 
-			/* remove the handle from the database */
-			ipa3_id_remove(id);
+			if (!user_only ||
+					entry->ipacm_installed) {
+				list_del(&entry->link);
+				entry->tbl->rule_cnt--;
+				if (entry->rt_tbl)
+					entry->rt_tbl->ref_cnt--;
+				/* if rule id was allocated from idr, remove */
+				rule_id = entry->rule_id;
+				id = entry->id;
+				if ((rule_id < ipahal_get_rule_id_hi_bit()) &&
+					(rule_id >= ipahal_get_low_rule_id()))
+					idr_remove(entry->tbl->rule_ids,
+						rule_id);
+				entry->cookie = 0;
+				kmem_cache_free(ipa3_ctx->flt_rule_cache,
+								entry);
+
+				/* remove the handle from the database */
+				ipa3_id_remove(id);
+			}
 		}
 	}
 	mutex_unlock(&ipa3_ctx->lock);
@@ -1443,14 +1468,14 @@
 	tbl = &ipa3_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v4];
 	rule.action = IPA_PASS_TO_EXCEPTION;
 	__ipa_add_flt_rule(tbl, IPA_IP_v4, &rule, true,
-			&ep->dflt_flt4_rule_hdl);
+			&ep->dflt_flt4_rule_hdl, false);
 	ipa3_ctx->ctrl->ipa3_commit_flt(IPA_IP_v4);
 	tbl->sticky_rear = true;
 
 	tbl = &ipa3_ctx->flt_tbl[ipa_ep_idx][IPA_IP_v6];
 	rule.action = IPA_PASS_TO_EXCEPTION;
 	__ipa_add_flt_rule(tbl, IPA_IP_v6, &rule, true,
-			&ep->dflt_flt6_rule_hdl);
+			&ep->dflt_flt6_rule_hdl, false);
 	ipa3_ctx->ctrl->ipa3_commit_flt(IPA_IP_v6);
 	tbl->sticky_rear = true;
 	mutex_unlock(&ipa3_ctx->lock);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
index f885368..cecbef0 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -317,7 +317,7 @@
 }
 
 static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx,
-	bool add_ref_hdr)
+	bool add_ref_hdr, bool user_only)
 {
 	struct ipa3_hdr_entry *hdr_entry;
 	struct ipa3_hdr_proc_ctx_entry *entry;
@@ -363,6 +363,7 @@
 	if (add_ref_hdr)
 		hdr_entry->ref_cnt++;
 	entry->cookie = IPA_PROC_HDR_COOKIE;
+	entry->ipacm_installed = user_only;
 
 	needed_len = ipahal_get_proc_ctx_needed_len(proc_ctx->type);
 
@@ -399,6 +400,7 @@
 		 */
 		offset->offset = htbl->end;
 		offset->bin = bin;
+		offset->ipacm_installed = user_only;
 		htbl->end += ipa_hdr_proc_ctx_bin_sz[bin];
 		list_add(&offset->link,
 				&htbl->head_offset_list[bin]);
@@ -407,6 +409,7 @@
 		offset =
 		    list_first_entry(&htbl->head_free_offset_list[bin],
 				struct ipa3_hdr_proc_ctx_offset_entry, link);
+		offset->ipacm_installed = user_only;
 		list_move(&offset->link, &htbl->head_offset_list[bin]);
 	}
 
@@ -444,7 +447,7 @@
 }
 
 
-static int __ipa_add_hdr(struct ipa_hdr_add *hdr)
+static int __ipa_add_hdr(struct ipa_hdr_add *hdr, bool user)
 {
 	struct ipa3_hdr_entry *entry;
 	struct ipa_hdr_offset_entry *offset = NULL;
@@ -479,6 +482,7 @@
 	entry->is_eth2_ofst_valid = hdr->is_eth2_ofst_valid;
 	entry->eth2_ofst = hdr->eth2_ofst;
 	entry->cookie = IPA_HDR_COOKIE;
+	entry->ipacm_installed = user;
 
 	if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN0])
 		bin = IPA_HDR_BIN0;
@@ -530,6 +534,7 @@
 			list_add(&offset->link,
 					&htbl->head_offset_list[bin]);
 			entry->offset_entry = offset;
+			offset->ipacm_installed = user;
 		}
 	} else {
 		entry->is_hdr_proc_ctx = false;
@@ -538,6 +543,7 @@
 			struct ipa_hdr_offset_entry, link);
 		list_move(&offset->link, &htbl->head_offset_list[bin]);
 		entry->offset_entry = offset;
+		offset->ipacm_installed = user;
 	}
 
 	list_add(&entry->link, &htbl->head_hdr_entry_list);
@@ -569,7 +575,7 @@
 		IPADBG("adding processing context for header %s\n", hdr->name);
 		proc_ctx.type = IPA_HDR_PROC_NONE;
 		proc_ctx.hdr_hdl = id;
-		if (__ipa_add_hdr_proc_ctx(&proc_ctx, false)) {
+		if (__ipa_add_hdr_proc_ctx(&proc_ctx, false, user)) {
 			IPAERR("failed to add hdr proc ctx\n");
 			goto fail_add_proc_ctx;
 		}
@@ -651,7 +657,6 @@
 	return 0;
 }
 
-
 int __ipa3_del_hdr(u32 hdr_hdl, bool by_user)
 {
 	struct ipa3_hdr_entry *entry;
@@ -731,6 +736,21 @@
  */
 int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs)
 {
+	return ipa3_add_hdr_usr(hdrs, false);
+}
+
+/**
+ * ipa3_add_hdr_usr() - add the specified headers to SW
+ * and optionally commit them to IPA HW
+ * @hdrs:		[inout] set of headers to add
+ * @user_only:	[in] indicate installed from user
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+int ipa3_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool user_only)
+{
 	int i;
 	int result = -EFAULT;
 
@@ -743,7 +763,7 @@
 	IPADBG("adding %d headers to IPA driver internal data struct\n",
 			hdrs->num_hdrs);
 	for (i = 0; i < hdrs->num_hdrs; i++) {
-		if (__ipa_add_hdr(&hdrs->hdr[i])) {
+		if (__ipa_add_hdr(&hdrs->hdr[i], user_only)) {
 			IPAERR_RL("failed to add hdr %d\n", i);
 			hdrs->hdr[i].status = -1;
 		} else {
@@ -824,12 +844,14 @@
  * ipa3_add_hdr_proc_ctx() - add the specified headers to SW
  * and optionally commit them to IPA HW
  * @proc_ctxs:	[inout] set of processing context headers to add
+ * @user_only:	[in] indicate installed by user-space module
  *
  * Returns:	0 on success, negative on failure
  *
  * Note:	Should not be called from atomic context
  */
-int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs)
+int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs,
+							bool user_only)
 {
 	int i;
 	int result = -EFAULT;
@@ -843,7 +865,8 @@
 	IPADBG("adding %d header processing contextes to IPA driver\n",
 			proc_ctxs->num_proc_ctxs);
 	for (i = 0; i < proc_ctxs->num_proc_ctxs; i++) {
-		if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i], true)) {
+		if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i],
+				true, user_only)) {
 			IPAERR_RL("failed to add hdr pric ctx %d\n", i);
 			proc_ctxs->proc_ctx[i].status = -1;
 		} else {
@@ -958,11 +981,12 @@
  * ipa3_reset_hdr() - reset the current header table in SW (does not commit to
  * HW)
  *
+ * @user_only:	[in] indicate delete rules installed by userspace
  * Returns:	0 on success, negative on failure
  *
  * Note:	Should not be called from atomic context
  */
-int ipa3_reset_hdr(void)
+int ipa3_reset_hdr(bool user_only)
 {
 	struct ipa3_hdr_entry *entry;
 	struct ipa3_hdr_entry *next;
@@ -972,15 +996,16 @@
 	struct ipa_hdr_offset_entry *off_next;
 	struct ipa3_hdr_proc_ctx_offset_entry *ctx_off_entry;
 	struct ipa3_hdr_proc_ctx_offset_entry *ctx_off_next;
-	int i;
+	int i, end = 0;
+	bool user_rule = false;
 
 	/*
 	 * issue a reset on the routing module since routing rules point to
 	 * header table entries
 	 */
-	if (ipa3_reset_rt(IPA_IP_v4))
+	if (ipa3_reset_rt(IPA_IP_v4, user_only))
 		IPAERR("fail to reset v4 rt\n");
-	if (ipa3_reset_rt(IPA_IP_v6))
+	if (ipa3_reset_rt(IPA_IP_v6, user_only))
 		IPAERR("fail to reset v4 rt\n");
 
 	mutex_lock(&ipa3_ctx->lock);
@@ -1009,21 +1034,27 @@
 			WARN_ON_RATELIMIT_IPA(1);
 			return -EFAULT;
 		}
-		if (entry->is_hdr_proc_ctx) {
-			dma_unmap_single(ipa3_ctx->pdev,
-				entry->phys_base,
-				entry->hdr_len,
-				DMA_TO_DEVICE);
-			entry->proc_ctx = NULL;
+
+		if (entry->ipacm_installed)
+			user_rule = true;
+
+		if (!user_only || entry->ipacm_installed) {
+			if (entry->is_hdr_proc_ctx) {
+				dma_unmap_single(ipa3_ctx->pdev,
+					entry->phys_base,
+					entry->hdr_len,
+					DMA_TO_DEVICE);
+				entry->proc_ctx = NULL;
+			}
+			list_del(&entry->link);
+			ipa3_ctx->hdr_tbl.hdr_cnt--;
+			entry->ref_cnt = 0;
+			entry->cookie = 0;
+
+			/* remove the handle from the database */
+			ipa3_id_remove(entry->id);
+			kmem_cache_free(ipa3_ctx->hdr_cache, entry);
 		}
-		list_del(&entry->link);
-		entry->ref_cnt = 0;
-		entry->cookie = 0;
-
-		/* remove the handle from the database */
-		ipa3_id_remove(entry->id);
-		kmem_cache_free(ipa3_ctx->hdr_cache, entry);
-
 	}
 	for (i = 0; i < IPA_HDR_BIN_MAX; i++) {
 		list_for_each_entry_safe(off_entry, off_next,
@@ -1037,21 +1068,41 @@
 			if (off_entry->offset == 0)
 				continue;
 
-			list_del(&off_entry->link);
-			kmem_cache_free(ipa3_ctx->hdr_offset_cache, off_entry);
+			if (!user_only ||
+					off_entry->ipacm_installed) {
+				list_del(&off_entry->link);
+				kmem_cache_free(ipa3_ctx->hdr_offset_cache,
+					off_entry);
+			} else {
+				if (off_entry->offset +
+					ipa_hdr_bin_sz[off_entry->bin] > end) {
+					end = off_entry->offset +
+						ipa_hdr_bin_sz[off_entry->bin];
+					IPADBG("replace end = %d\n", end);
+				}
+			}
 		}
 		list_for_each_entry_safe(off_entry, off_next,
 				&ipa3_ctx->hdr_tbl.head_free_offset_list[i],
 				link) {
-			list_del(&off_entry->link);
-			kmem_cache_free(ipa3_ctx->hdr_offset_cache, off_entry);
+
+			if (!user_only ||
+					off_entry->ipacm_installed) {
+				list_del(&off_entry->link);
+				kmem_cache_free(ipa3_ctx->hdr_offset_cache,
+					off_entry);
+			}
 		}
 	}
-	/* there is one header of size 8 */
-	ipa3_ctx->hdr_tbl.end = 8;
-	ipa3_ctx->hdr_tbl.hdr_cnt = 1;
 
+	IPADBG("hdr_tbl.end = %d\n", end);
+	if (user_rule) {
+		ipa3_ctx->hdr_tbl.end = end;
+		IPADBG("hdr_tbl.end = %d\n", end);
+	}
 	IPADBG("reset hdr proc ctx\n");
+	user_rule = false;
+	end = 0;
 	list_for_each_entry_safe(
 		ctx_entry,
 		ctx_next,
@@ -1063,34 +1114,63 @@
 			WARN_ON_RATELIMIT_IPA(1);
 			return -EFAULT;
 		}
-		list_del(&ctx_entry->link);
-		ctx_entry->ref_cnt = 0;
-		ctx_entry->cookie = 0;
 
-		/* remove the handle from the database */
-		ipa3_id_remove(ctx_entry->id);
-		kmem_cache_free(ipa3_ctx->hdr_proc_ctx_cache, ctx_entry);
+		if (entry->ipacm_installed)
+			user_rule = true;
 
+		if (!user_only ||
+				ctx_entry->ipacm_installed) {
+			list_del(&ctx_entry->link);
+			ipa3_ctx->hdr_proc_ctx_tbl.proc_ctx_cnt--;
+			ctx_entry->ref_cnt = 0;
+			ctx_entry->cookie = 0;
+
+			/* remove the handle from the database */
+			ipa3_id_remove(ctx_entry->id);
+			kmem_cache_free(ipa3_ctx->hdr_proc_ctx_cache,
+				ctx_entry);
+		}
 	}
 	for (i = 0; i < IPA_HDR_PROC_CTX_BIN_MAX; i++) {
 		list_for_each_entry_safe(ctx_off_entry, ctx_off_next,
 				&ipa3_ctx->hdr_proc_ctx_tbl.head_offset_list[i],
 				link) {
 
-			list_del(&ctx_off_entry->link);
-			kmem_cache_free(ipa3_ctx->hdr_proc_ctx_offset_cache,
+			if (!user_only ||
+					ctx_off_entry->ipacm_installed) {
+				list_del(&ctx_off_entry->link);
+				kmem_cache_free(
+					ipa3_ctx->hdr_proc_ctx_offset_cache,
 					ctx_off_entry);
+			} else {
+				if (ctx_off_entry->offset +
+					ipa_hdr_bin_sz[ctx_off_entry->bin]
+					> end) {
+					end = ctx_off_entry->offset +
+					ipa_hdr_bin_sz[ctx_off_entry->bin];
+					IPADBG("replace hdr_proc as %d\n", end);
+				}
+			}
 		}
 		list_for_each_entry_safe(ctx_off_entry, ctx_off_next,
 			&ipa3_ctx->hdr_proc_ctx_tbl.head_free_offset_list[i],
 			link) {
-			list_del(&ctx_off_entry->link);
-			kmem_cache_free(ipa3_ctx->hdr_proc_ctx_offset_cache,
-				ctx_off_entry);
+
+			if (!user_only ||
+					ctx_off_entry->ipacm_installed) {
+				list_del(&ctx_off_entry->link);
+				kmem_cache_free(
+					ipa3_ctx->hdr_proc_ctx_offset_cache,
+					ctx_off_entry);
+			}
 		}
 	}
-	ipa3_ctx->hdr_proc_ctx_tbl.end = 0;
-	ipa3_ctx->hdr_proc_ctx_tbl.proc_ctx_cnt = 0;
+
+	IPADBG("hdr_proc_tbl.end = %d\n", end);
+	if (user_rule) {
+		ipa3_ctx->hdr_proc_ctx_tbl.end = end;
+		IPADBG("hdr_proc_tbl.end = %d\n", end);
+	}
 	mutex_unlock(&ipa3_ctx->lock);
 
 	return 0;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 386ad51..50c1e3f 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -116,6 +116,14 @@
 		} \
 	} while (0)
 
+/* round addresses for closes page per SMMU requirements */
+#define IPA_SMMU_ROUND_TO_PAGE(iova, pa, size, iova_p, pa_p, size_p) \
+	do { \
+		(iova_p) = rounddown((iova), PAGE_SIZE); \
+		(pa_p) = rounddown((pa), PAGE_SIZE); \
+		(size_p) = roundup((size) + (pa) - (pa_p), PAGE_SIZE); \
+	} while (0)
+
 #define WLAN_AMPDU_TX_EP 15
 #define WLAN_PROD_TX_EP  19
 #define WLAN1_CONS_RX_EP  14
@@ -239,6 +247,7 @@
  * @prio: rule 10bit priority which defines the order of the rule
  *  among other rules at the same integrated table
  * @rule_id: rule 10bit ID to be returned in packet status
+ * @ipacm_installed: indicate if installed by ipacm
  */
 struct ipa3_flt_entry {
 	struct list_head link;
@@ -250,6 +259,7 @@
 	int id;
 	u16 prio;
 	u16 rule_id;
+	bool ipacm_installed;
 };
 
 /**
@@ -306,6 +316,7 @@
  * @is_eth2_ofst_valid: is eth2_ofst field valid?
  * @eth2_ofst: offset to start of Ethernet-II/802.3 header
  * @user_deleted: is the header deleted by the user?
+ * @ipacm_installed: indicate if installed by ipacm
  */
 struct ipa3_hdr_entry {
 	struct list_head link;
@@ -324,6 +335,7 @@
 	u8 is_eth2_ofst_valid;
 	u16 eth2_ofst;
 	bool user_deleted;
+	bool ipacm_installed;
 };
 
 /**
@@ -347,11 +359,13 @@
  * @link: entry's link in global processing context header offset entries list
  * @offset: the offset
  * @bin: bin
+ * @ipacm_installed: indicate if installed by ipacm
  */
 struct ipa3_hdr_proc_ctx_offset_entry {
 	struct list_head link;
 	u32 offset;
 	u32 bin;
+	bool ipacm_installed;
 };
 
 /**
@@ -365,6 +379,7 @@
  * @ref_cnt: reference counter of routing table
  * @id: processing context header entry id
  * @user_deleted: is the hdr processing context deleted by the user?
+ * @ipacm_installed: indicate if installed by ipacm
  */
 struct ipa3_hdr_proc_ctx_entry {
 	struct list_head link;
@@ -376,6 +391,7 @@
 	u32 ref_cnt;
 	int id;
 	bool user_deleted;
+	bool ipacm_installed;
 };
 
 /**
@@ -431,6 +447,8 @@
  * @prio: rule 10bit priority which defines the order of the rule
  *  among other rules at the integrated same table
  * @rule_id: rule 10bit ID to be returned in packet status
+ * @rule_id_valid: indicate if rule_id_valid valid or not?
+ * @ipacm_installed: indicate if installed by ipacm
  */
 struct ipa3_rt_entry {
 	struct list_head link;
@@ -444,6 +462,7 @@
 	u16 prio;
 	u16 rule_id;
 	u16 rule_id_valid;
+	bool ipacm_installed;
 };
 
 /**
@@ -782,12 +801,12 @@
 };
 
 /**
-* struct ipa_pdn_entry - IPA PDN config table entry
-* @public_ip: the PDN's public ip
-* @src_metadata: the PDN's metadata to be replaced for source NAT
-* @dst_metadata: the PDN's metadata to be replaced for destination NAT
-* @resrvd: reserved field
-*/
+ * struct ipa_pdn_entry - IPA PDN config table entry
+ * @public_ip: the PDN's public ip
+ * @src_metadata: the PDN's metadata to be replaced for source NAT
+ * @dst_metadata: the PDN's metadata to be replaced for destination NAT
+ * @resrvd: reserved field
+ */
 struct ipa_pdn_entry {
 	u32 public_ip;
 	u32 src_metadata;
@@ -881,9 +900,9 @@
 };
 
 /**
-* struct ipa3_ipv6ct_mem - IPA IPv6 connection tracking memory description
-* @dev: the memory device structure
-*/
+ * struct ipa3_ipv6ct_mem - IPA IPv6 connection tracking memory description
+ * @dev: the memory device structure
+ */
 struct ipa3_ipv6ct_mem {
 	struct ipa3_nat_ipv6ct_common_mem dev;
 };
@@ -1328,6 +1347,8 @@
 	struct list_head msg_list;
 	struct list_head pull_msg_list;
 	struct mutex msg_lock;
+	struct list_head msg_wlan_client_list;
+	struct mutex msg_wlan_client_lock;
 	wait_queue_head_t msg_waitq;
 	enum ipa_hw_type ipa_hw_type;
 	enum ipa3_hw_mode ipa3_hw_mode;
@@ -1420,6 +1441,7 @@
 	bool gsi_ch20_wa;
 	bool tethered_flow_control;
 	u32 mhi_evid_limits[2]; /* start and end values */
+	bool ipa_mhi_dynamic_config;
 	u32 ipa_tz_unlock_reg_num;
 	struct ipa_tz_unlock_reg_info *ipa_tz_unlock_reg;
 	bool use_ipa_pm;
@@ -1756,13 +1778,15 @@
  */
 int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs);
 
+int ipa3_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool by_user);
+
 int ipa3_del_hdr(struct ipa_ioc_del_hdr *hdls);
 
 int ipa3_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user);
 
 int ipa3_commit_hdr(void);
 
-int ipa3_reset_hdr(void);
+int ipa3_reset_hdr(bool user_only);
 
 int ipa3_get_hdr(struct ipa_ioc_get_hdr *lookup);
 
@@ -1773,7 +1797,8 @@
 /*
  * Header Processing Context
  */
-int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs);
+int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs,
+							bool user_only);
 
 int ipa3_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls);
 
@@ -1785,6 +1810,9 @@
  */
 int ipa3_add_rt_rule(struct ipa_ioc_add_rt_rule *rules);
 
+int ipa3_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules,
+	bool user_only);
+
 int ipa3_add_rt_rule_ext(struct ipa_ioc_add_rt_rule_ext *rules);
 
 int ipa3_add_rt_rule_after(struct ipa_ioc_add_rt_rule_after *rules);
@@ -1793,7 +1821,7 @@
 
 int ipa3_commit_rt(enum ipa_ip_type ip);
 
-int ipa3_reset_rt(enum ipa_ip_type ip);
+int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only);
 
 int ipa3_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup);
 
@@ -1808,6 +1836,9 @@
  */
 int ipa3_add_flt_rule(struct ipa_ioc_add_flt_rule *rules);
 
+int ipa3_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules,
+	bool user_only);
+
 int ipa3_add_flt_rule_after(struct ipa_ioc_add_flt_rule_after *rules);
 
 int ipa3_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls);
@@ -1816,7 +1847,7 @@
 
 int ipa3_commit_flt(enum ipa_ip_type ip);
 
-int ipa3_reset_flt(enum ipa_ip_type ip);
+int ipa3_reset_flt(enum ipa_ip_type ip, bool user_only);
 
 /*
  * NAT
@@ -1847,6 +1878,7 @@
  */
 int ipa3_send_msg(struct ipa_msg_meta *meta, void *buff,
 		  ipa_msg_free_fn callback);
+int ipa3_resend_wlan_msg(void);
 int ipa3_register_pull_msg(struct ipa_msg_meta *meta, ipa_msg_pull_fn callback);
 int ipa3_deregister_pull_msg(struct ipa_msg_meta *meta);
 
@@ -1879,7 +1911,7 @@
  * To transfer multiple data packets
  * While passing the data descriptor list, the anchor node
  * should be of type struct ipa_tx_data_desc not list_head
-*/
+ */
 int ipa3_tx_dp_mul(enum ipa_client_type dst,
 			struct ipa_tx_data_desc *data_desc);
 
@@ -1914,7 +1946,8 @@
 int ipa3_setup_uc_ntn_pipes(struct ipa_ntn_conn_in_params *in,
 		ipa_notify_cb notify, void *priv, u8 hdr_len,
 		struct ipa_ntn_conn_out_params *outp);
-int ipa3_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl);
+int ipa3_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl,
+	struct ipa_ntn_conn_in_params *params);
 int ipa3_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *), void *priv);
 void ipa3_ntn_uc_dereg_rdyCB(void);
 int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
@@ -2116,6 +2149,7 @@
 int __ipa3_release_hdr_proc_ctx(u32 proc_ctx_hdl);
 int _ipa_read_ep_reg_v3_0(char *buf, int max_len, int pipe);
 int _ipa_read_ep_reg_v4_0(char *buf, int max_len, int pipe);
+int _ipa_read_ipahal_regs(void);
 void _ipa_enable_clks_v3_0(void);
 void _ipa_disable_clks_v3_0(void);
 struct device *ipa3_get_dma_dev(void);
@@ -2290,6 +2324,8 @@
 struct iommu_domain *ipa3_get_smmu_domain(void);
 struct iommu_domain *ipa3_get_uc_smmu_domain(void);
 struct iommu_domain *ipa3_get_wlan_smmu_domain(void);
+struct iommu_domain *ipa3_get_smmu_domain_by_type
+	(enum ipa_smmu_cb_type cb_type);
 int ipa3_iommu_map(struct iommu_domain *domain, unsigned long iova,
 	phys_addr_t paddr, size_t size, int prot);
 int ipa3_ap_suspend(struct device *dev);
@@ -2324,8 +2360,10 @@
 int ipa_gsi_ch20_wa(void);
 int ipa3_rx_poll(u32 clnt_hdl, int budget);
 void ipa3_recycle_wan_skb(struct sk_buff *skb);
-int ipa3_smmu_map_peer_reg(phys_addr_t phys_addr, bool map);
-int ipa3_smmu_map_peer_buff(u64 iova, u32 size, bool map, struct sg_table *sgt);
+int ipa3_smmu_map_peer_reg(phys_addr_t phys_addr, bool map,
+	enum ipa_smmu_cb_type cb_type);
+int ipa3_smmu_map_peer_buff(u64 iova, u32 size, bool map, struct sg_table *sgt,
+	enum ipa_smmu_cb_type cb_type);
 void ipa3_reset_freeze_vote(void);
 int ipa3_ntn_init(void);
 int ipa3_get_ntn_stats(struct Ipa3HwStatsNTNInfoData_t *stats);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
index 40ef59a..c348e26 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,7 @@
 #include <linux/fs.h>
 #include <linux/sched.h>
 #include "ipa_i.h"
+#include <linux/msm_ipa.h>
 
 struct ipa3_intf {
 	char name[IPA_RESOURCE_NAME_MAX];
@@ -390,6 +391,108 @@
 	kfree(buff);
 }
 
+static int wlan_msg_process(struct ipa_msg_meta *meta, void *buff)
+{
+	struct ipa3_push_msg *msg_dup;
+	struct ipa_wlan_msg_ex *event_ex_cur_con = NULL;
+	struct ipa_wlan_msg_ex *event_ex_list = NULL;
+	struct ipa_wlan_msg *event_ex_cur_discon = NULL;
+	void *data_dup = NULL;
+	struct ipa3_push_msg *entry;
+	struct ipa3_push_msg *next;
+	int cnt = 0, total = 0, max = 0;
+	uint8_t mac[IPA_MAC_ADDR_SIZE];
+	uint8_t mac2[IPA_MAC_ADDR_SIZE];
+
+	if (meta->msg_type == WLAN_CLIENT_CONNECT_EX) {
+		/* debug print */
+		event_ex_cur_con = buff;
+		for (cnt = 0; cnt < event_ex_cur_con->num_of_attribs; cnt++) {
+			if (event_ex_cur_con->attribs[cnt].attrib_type ==
+				WLAN_HDR_ATTRIB_MAC_ADDR) {
+				IPADBG("%02x:%02x:%02x:%02x:%02x:%02x,(%d)\n",
+				event_ex_cur_con->attribs[cnt].u.mac_addr[0],
+				event_ex_cur_con->attribs[cnt].u.mac_addr[1],
+				event_ex_cur_con->attribs[cnt].u.mac_addr[2],
+				event_ex_cur_con->attribs[cnt].u.mac_addr[3],
+				event_ex_cur_con->attribs[cnt].u.mac_addr[4],
+				event_ex_cur_con->attribs[cnt].u.mac_addr[5],
+				meta->msg_type);
+			}
+		}
+
+		mutex_lock(&ipa3_ctx->msg_wlan_client_lock);
+		msg_dup = kzalloc(sizeof(struct ipa3_push_msg), GFP_KERNEL);
+		if (msg_dup == NULL) {
+			IPAERR("fail to alloc ipa_msg container\n");
+			return -ENOMEM;
+		}
+		msg_dup->meta = *meta;
+		if (meta->msg_len > 0 && buff) {
+			data_dup = kmalloc(meta->msg_len, GFP_KERNEL);
+			if (data_dup == NULL) {
+				IPAERR("fail to alloc data_dup container\n");
+				kfree(msg_dup);
+				return -ENOMEM;
+			}
+			memcpy(data_dup, buff, meta->msg_len);
+			msg_dup->buff = data_dup;
+			msg_dup->callback = ipa3_send_msg_free;
+		}
+		list_add_tail(&msg_dup->link, &ipa3_ctx->msg_wlan_client_list);
+		mutex_unlock(&ipa3_ctx->msg_wlan_client_lock);
+	}
+
+	/* remove the cache */
+	if (meta->msg_type == WLAN_CLIENT_DISCONNECT) {
+		/* debug print */
+		event_ex_cur_discon = buff;
+		IPADBG("Mac %02x:%02x:%02x:%02x:%02x:%02x,msg %d\n",
+		event_ex_cur_discon->mac_addr[0],
+		event_ex_cur_discon->mac_addr[1],
+		event_ex_cur_discon->mac_addr[2],
+		event_ex_cur_discon->mac_addr[3],
+		event_ex_cur_discon->mac_addr[4],
+		event_ex_cur_discon->mac_addr[5],
+		meta->msg_type);
+		memcpy(mac2,
+			event_ex_cur_discon->mac_addr,
+			sizeof(mac2));
+
+		mutex_lock(&ipa3_ctx->msg_wlan_client_lock);
+		list_for_each_entry_safe(entry, next,
+				&ipa3_ctx->msg_wlan_client_list,
+				link) {
+			event_ex_list = entry->buff;
+			max = event_ex_list->num_of_attribs;
+			for (cnt = 0; cnt < max; cnt++) {
+				memcpy(mac,
+					event_ex_list->attribs[cnt].u.mac_addr,
+					sizeof(mac));
+				if (event_ex_list->attribs[cnt].attrib_type ==
+					WLAN_HDR_ATTRIB_MAC_ADDR) {
+					pr_debug("%02x:%02x:%02x:%02x:%02x:%02x\n",
+					mac[0],	mac[1],	mac[2],
+					mac[3],	mac[4], mac[5]);
+
+					/* compare to delete one*/
+					if (memcmp(mac2,
+						mac,
+						sizeof(mac)) == 0) {
+						IPADBG("clean %d\n", total);
+						list_del(&entry->link);
+						kfree(entry);
+						break;
+					}
+				}
+			}
+			total++;
+		}
+		mutex_unlock(&ipa3_ctx->msg_wlan_client_lock);
+	}
+	return 0;
+}
+
 /**
  * ipa3_send_msg() - Send "message" from kernel client to IPA driver
  * @meta: [in] message meta-data
@@ -444,6 +547,11 @@
 
 	mutex_lock(&ipa3_ctx->msg_lock);
 	list_add_tail(&msg->link, &ipa3_ctx->msg_list);
+	/* support for softap client event cache */
+	if (wlan_msg_process(meta, buff))
+		IPAERR("wlan_msg_process failed\n");
+
+	/* unlock only after process */
 	mutex_unlock(&ipa3_ctx->msg_lock);
 	IPA_STATS_INC_CNT(ipa3_ctx->stats.msg_w[meta->msg_type]);
 
@@ -455,6 +563,73 @@
 }
 
 /**
+ * ipa3_resend_wlan_msg() - Resend cached "message" to IPACM
+ *
+ * resend wlan client connect events to user-space
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+int ipa3_resend_wlan_msg(void)
+{
+	struct ipa_wlan_msg_ex *event_ex_list = NULL;
+	struct ipa3_push_msg *entry;
+	struct ipa3_push_msg *next;
+	int cnt = 0, total = 0;
+	struct ipa3_push_msg *msg;
+	void *data = NULL;
+
+	IPADBG("\n");
+
+	mutex_lock(&ipa3_ctx->msg_wlan_client_lock);
+	list_for_each_entry_safe(entry, next, &ipa3_ctx->msg_wlan_client_list,
+			link) {
+
+		event_ex_list = entry->buff;
+		for (cnt = 0; cnt < event_ex_list->num_of_attribs; cnt++) {
+			if (event_ex_list->attribs[cnt].attrib_type ==
+				WLAN_HDR_ATTRIB_MAC_ADDR) {
+				IPADBG("%d-Mac %02x:%02x:%02x:%02x:%02x:%02x\n",
+				total,
+				event_ex_list->attribs[cnt].u.mac_addr[0],
+				event_ex_list->attribs[cnt].u.mac_addr[1],
+				event_ex_list->attribs[cnt].u.mac_addr[2],
+				event_ex_list->attribs[cnt].u.mac_addr[3],
+				event_ex_list->attribs[cnt].u.mac_addr[4],
+				event_ex_list->attribs[cnt].u.mac_addr[5]);
+			}
+		}
+
+		msg = kzalloc(sizeof(struct ipa3_push_msg), GFP_KERNEL);
+		if (msg == NULL) {
+			IPAERR("fail to alloc ipa_msg container\n");
+			mutex_unlock(&ipa3_ctx->msg_wlan_client_lock);
+			return -ENOMEM;
+		}
+		msg->meta = entry->meta;
+		data = kmalloc(entry->meta.msg_len, GFP_KERNEL);
+		if (data == NULL) {
+			IPAERR("fail to alloc data container\n");
+			kfree(msg);
+			mutex_unlock(&ipa3_ctx->msg_wlan_client_lock);
+			return -ENOMEM;
+		}
+		memcpy(data, entry->buff, entry->meta.msg_len);
+		msg->buff = data;
+		msg->callback = ipa3_send_msg_free;
+		mutex_lock(&ipa3_ctx->msg_lock);
+		list_add_tail(&msg->link, &ipa3_ctx->msg_list);
+		mutex_unlock(&ipa3_ctx->msg_lock);
+		wake_up(&ipa3_ctx->msg_waitq);
+
+		total++;
+	}
+	mutex_unlock(&ipa3_ctx->msg_wlan_client_lock);
+	return 0;
+}
+
+/**
  * ipa3_register_pull_msg() - register pull message type
  * @meta: [in] message meta-data
  * @callback: [in] pull callback
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
index 19d3d30..b48f2c4 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
@@ -1466,12 +1466,6 @@
 {
 	struct ipa_ioc_nat_ipv6ct_table_del tmp;
 
-	if ((ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) &&
-		(del->public_ip_addr == 0)) {
-		IPAERR_RL("Bad Parameter public IP address\n");
-		return -EPERM;
-	}
-
 	tmp.table_index = del->table_index;
 
 	return ipa3_del_nat_table(&tmp);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
index 88de06e..821abe2 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
@@ -605,6 +605,14 @@
 	int rc;
 	int i;
 
+	/* check if modem up */
+	if (!ipa3_qmi_indication_fin ||
+		!ipa3_qmi_modem_init_fin ||
+		!ipa_q6_clnt) {
+		IPAWANDBG("modem QMI haven't up yet\n");
+		return -EINVAL;
+	}
+
 	/* check if the filter rules from IPACM is valid */
 	if (req->filter_spec_list_len == 0) {
 		IPAWANDBG("IPACM pass zero rules to Q6\n");
@@ -689,6 +697,14 @@
 	int rc;
 	int i;
 
+	/* check if modem up */
+	if (!ipa3_qmi_indication_fin ||
+		!ipa3_qmi_modem_init_fin ||
+		!ipa_q6_clnt) {
+		IPAWANDBG("modem QMI haven't up yet\n");
+		return -EINVAL;
+	}
+
 	/* check if the filter rules from IPACM is valid */
 	if (req->filter_spec_ex_list_len == 0) {
 		IPAWANDBG("IPACM pass zero rules to Q6\n");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
index a0f1f54..7861896 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
@@ -940,7 +940,7 @@
 		const struct ipa_rt_rule *rule,
 		struct ipa3_rt_tbl *tbl, struct ipa3_hdr_entry *hdr,
 		struct ipa3_hdr_proc_ctx_entry *proc_ctx,
-		u16 rule_id)
+		u16 rule_id, bool user)
 {
 	int id;
 
@@ -967,6 +967,7 @@
 		}
 	}
 	(*(entry))->rule_id = id;
+	(*(entry))->ipacm_installed = user;
 
 	return 0;
 
@@ -1012,7 +1013,7 @@
 
 static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name,
 		const struct ipa_rt_rule *rule, u8 at_rear, u32 *rule_hdl,
-		u16 rule_id)
+		u16 rule_id, bool user)
 {
 	struct ipa3_rt_tbl *tbl;
 	struct ipa3_rt_entry *entry;
@@ -1041,7 +1042,7 @@
 	}
 
 	if (__ipa_create_rt_entry(&entry, rule, tbl, hdr, proc_ctx,
-		rule_id))
+		rule_id, user))
 		goto error;
 
 	if (at_rear)
@@ -1072,7 +1073,7 @@
 	if (__ipa_rt_validate_hndls(rule, &hdr, &proc_ctx))
 		goto error;
 
-	if (__ipa_create_rt_entry(&entry, rule, tbl, hdr, proc_ctx, 0))
+	if (__ipa_create_rt_entry(&entry, rule, tbl, hdr, proc_ctx, 0, true))
 		goto error;
 
 	list_add(&entry->link, &((*add_after_entry)->link));
@@ -1101,8 +1102,24 @@
  *
  * Note:	Should not be called from atomic context
  */
+
 int ipa3_add_rt_rule(struct ipa_ioc_add_rt_rule *rules)
 {
+	return ipa3_add_rt_rule_usr(rules, false);
+}
+/**
+ * ipa3_add_rt_rule_usr() - Add the specified routing rules to SW and optionally
+ * commit to IPA HW
+ * @rules:		[inout] set of routing rules to add
+ * @user_only:	[in] indicate installed by userspace module
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * Note:	Should not be called from atomic context
+ */
+
+int ipa3_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, bool user_only)
+{
 	int i;
 	int ret;
 
@@ -1118,7 +1135,8 @@
 					&rules->rules[i].rule,
 					rules->rules[i].at_rear,
 					&rules->rules[i].rt_rule_hdl,
-					0)) {
+					0,
+					user_only)) {
 			IPAERR("failed to add rt rule %d\n", i);
 			rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED;
 		} else {
@@ -1163,7 +1181,7 @@
 					&rules->rules[i].rule,
 					rules->rules[i].at_rear,
 					&rules->rules[i].rt_rule_hdl,
-					rules->rules[i].rule_id)) {
+					rules->rules[i].rule_id, true)) {
 			IPAERR("failed to add rt rule %d\n", i);
 			rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED;
 		} else {
@@ -1440,13 +1458,14 @@
 /**
  * ipa3_reset_rt() - reset the current SW routing table of specified type
  * (does not commit to HW)
- * @ip:	The family of routing tables
+ * @ip:			[in] The family of routing tables
+ * @user_only:	[in] indicate delete rules installed by userspace
  *
  * Returns:	0 on success, negative on failure
  *
  * Note:	Should not be called from atomic context
  */
-int ipa3_reset_rt(enum ipa_ip_type ip)
+int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only)
 {
 	struct ipa3_rt_tbl *tbl;
 	struct ipa3_rt_tbl *tbl_next;
@@ -1456,6 +1475,7 @@
 	struct ipa3_rt_tbl_set *rset;
 	u32 apps_start_idx;
 	int id;
+	bool tbl_user = false;
 
 	if (ip >= IPA_IP_MAX) {
 		IPAERR_RL("bad parm\n");
@@ -1473,7 +1493,7 @@
 	 * issue a reset on the filtering module of same IP type since
 	 * filtering rules point to routing tables
 	 */
-	if (ipa3_reset_flt(ip))
+	if (ipa3_reset_flt(ip, user_only))
 		IPAERR_RL("fail to reset flt ip=%d\n", ip);
 
 	set = &ipa3_ctx->rt_tbl_set[ip];
@@ -1481,6 +1501,7 @@
 	mutex_lock(&ipa3_ctx->lock);
 	IPADBG("reset rt ip=%d\n", ip);
 	list_for_each_entry_safe(tbl, tbl_next, &set->head_rt_tbl_list, link) {
+		tbl_user = false;
 		list_for_each_entry_safe(rule, rule_next,
 					 &tbl->head_rt_rule_list, link) {
 			if (ipa3_id_find(rule->id) == NULL) {
@@ -1489,6 +1510,12 @@
 				return -EFAULT;
 			}
 
+			/* indicate if tbl used for user-specified rules*/
+			if (rule->ipacm_installed) {
+				IPADBG("tbl_user %d, tbl-index %d\n",
+				tbl_user, tbl->id);
+				tbl_user = true;
+			}
 			/*
 			 * for the "default" routing tbl, remove all but the
 			 *  last rule
@@ -1496,19 +1523,23 @@
 			if (tbl->idx == apps_start_idx && tbl->rule_cnt == 1)
 				continue;
 
-			list_del(&rule->link);
-			tbl->rule_cnt--;
-			if (rule->hdr)
-				__ipa3_release_hdr(rule->hdr->id);
-			else if (rule->proc_ctx)
-				__ipa3_release_hdr_proc_ctx(rule->proc_ctx->id);
-			rule->cookie = 0;
-			idr_remove(tbl->rule_ids, rule->rule_id);
-			id = rule->id;
-			kmem_cache_free(ipa3_ctx->rt_rule_cache, rule);
+			if (!user_only ||
+				rule->ipacm_installed) {
+				list_del(&rule->link);
+				tbl->rule_cnt--;
+				if (rule->hdr)
+					__ipa3_release_hdr(rule->hdr->id);
+				else if (rule->proc_ctx)
+					__ipa3_release_hdr_proc_ctx(
+						rule->proc_ctx->id);
+				rule->cookie = 0;
+				idr_remove(tbl->rule_ids, rule->rule_id);
+				id = rule->id;
+				kmem_cache_free(ipa3_ctx->rt_rule_cache, rule);
 
-			/* remove the handle from the database */
-			ipa3_id_remove(id);
+				/* remove the handle from the database */
+				ipa3_id_remove(id);
+			}
 		}
 
 		if (ipa3_id_find(tbl->id) == NULL) {
@@ -1520,26 +1551,30 @@
 
 		/* do not remove the "default" routing tbl which has index 0 */
 		if (tbl->idx != apps_start_idx) {
-			tbl->rule_ids = NULL;
-			if (tbl->in_sys[IPA_RULE_HASHABLE] ||
-				tbl->in_sys[IPA_RULE_NON_HASHABLE]) {
-				list_move(&tbl->link, &rset->head_rt_tbl_list);
-				clear_bit(tbl->idx,
+			if (!user_only || tbl_user) {
+				tbl->rule_ids = NULL;
+				if (tbl->in_sys[IPA_RULE_HASHABLE] ||
+					tbl->in_sys[IPA_RULE_NON_HASHABLE]) {
+					list_move(&tbl->link,
+						&rset->head_rt_tbl_list);
+					clear_bit(tbl->idx,
 					  &ipa3_ctx->rt_idx_bitmap[ip]);
-				set->tbl_cnt--;
-				IPADBG("rst sys rt tbl_idx=%d tbl_cnt=%d\n",
+					set->tbl_cnt--;
+					IPADBG("rst tbl_idx=%d cnt=%d\n",
 						tbl->idx, set->tbl_cnt);
-			} else {
-				list_del(&tbl->link);
-				set->tbl_cnt--;
-				clear_bit(tbl->idx,
+				} else {
+					list_del(&tbl->link);
+					set->tbl_cnt--;
+					clear_bit(tbl->idx,
 					  &ipa3_ctx->rt_idx_bitmap[ip]);
-				IPADBG("rst rt tbl_idx=%d tbl_cnt=%d\n",
+					IPADBG("rst rt tbl_idx=%d tbl_cnt=%d\n",
 						tbl->idx, set->tbl_cnt);
-				kmem_cache_free(ipa3_ctx->rt_tbl_cache, tbl);
+					kmem_cache_free(ipa3_ctx->rt_tbl_cache,
+						tbl);
+				}
+				/* remove the handle from the database */
+				ipa3_id_remove(id);
 			}
-			/* remove the handle from the database */
-			ipa3_id_remove(id);
 		}
 	}
 	mutex_unlock(&ipa3_ctx->lock);
@@ -1655,6 +1690,7 @@
 	struct ipa3_hdr_proc_ctx_entry *proc_ctx = NULL;
 	struct ipa3_hdr_entry *hdr_entry;
 	struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry;
+
 	if (rtrule->rule.hdr_hdl) {
 		hdr = ipa3_id_find(rtrule->rule.hdr_hdl);
 		if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c
index f821dd2..f4068bf 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -221,8 +221,11 @@
 
 	IPADBG("ring_base_pa = 0x%pa\n",
 			&ntn_info->ring_base_pa);
+	IPADBG("ring_base_iova = 0x%pa\n",
+			&ntn_info->ring_base_iova);
 	IPADBG("ntn_ring_size = %d\n", ntn_info->ntn_ring_size);
 	IPADBG("buff_pool_base_pa = 0x%pa\n", &ntn_info->buff_pool_base_pa);
+	IPADBG("buff_pool_base_iova = 0x%pa\n", &ntn_info->buff_pool_base_iova);
 	IPADBG("num_buffers = %d\n", ntn_info->num_buffers);
 	IPADBG("data_buff_size = %d\n", ntn_info->data_buff_size);
 	IPADBG("tail_ptr_base_pa = 0x%pa\n", &ntn_info->ntn_reg_base_ptr_pa);
@@ -248,8 +251,15 @@
 		Ntn_params = &cmd_data->SetupCh_params.NtnSetupCh_params;
 	}
 
-	Ntn_params->ring_base_pa = ntn_info->ring_base_pa;
-	Ntn_params->buff_pool_base_pa = ntn_info->buff_pool_base_pa;
+	if (ntn_info->smmu_enabled) {
+		Ntn_params->ring_base_pa = (u32)ntn_info->ring_base_iova;
+		Ntn_params->buff_pool_base_pa =
+			(u32)ntn_info->buff_pool_base_iova;
+	} else {
+		Ntn_params->ring_base_pa = ntn_info->ring_base_pa;
+		Ntn_params->buff_pool_base_pa = ntn_info->buff_pool_base_pa;
+	}
+
 	Ntn_params->ntn_ring_size = ntn_info->ntn_ring_size;
 	Ntn_params->num_buffers = ntn_info->num_buffers;
 	Ntn_params->ntn_reg_base_ptr_pa = ntn_info->ntn_reg_base_ptr_pa;
@@ -268,6 +278,128 @@
 	return result;
 }
 
+static int ipa3_smmu_map_uc_ntn_pipes(struct ipa_ntn_setup_info *params,
+	bool map)
+{
+	struct iommu_domain *smmu_domain;
+	int result;
+	int i;
+	u64 iova;
+	phys_addr_t pa;
+	u64 iova_p;
+	phys_addr_t pa_p;
+	u32 size_p;
+
+	if (params->data_buff_size > PAGE_SIZE) {
+		IPAERR("invalid data buff size\n");
+		return -EINVAL;
+	}
+
+	result = ipa3_smmu_map_peer_reg(rounddown(params->ntn_reg_base_ptr_pa,
+		PAGE_SIZE), map, IPA_SMMU_CB_UC);
+	if (result) {
+		IPAERR("failed to %s uC regs %d\n",
+			map ? "map" : "unmap", result);
+		goto fail;
+	}
+
+	if (params->smmu_enabled) {
+		IPADBG("smmu is enabled on EMAC\n");
+		result = ipa3_smmu_map_peer_buff((u64)params->ring_base_iova,
+			params->ntn_ring_size, map, params->ring_base_sgt,
+			IPA_SMMU_CB_UC);
+		if (result) {
+			IPAERR("failed to %s ntn ring %d\n",
+				map ? "map" : "unmap", result);
+			goto fail_map_ring;
+		}
+		result = ipa3_smmu_map_peer_buff(
+			(u64)params->buff_pool_base_iova,
+			params->num_buffers * 4, map,
+			params->buff_pool_base_sgt, IPA_SMMU_CB_UC);
+		if (result) {
+			IPAERR("failed to %s pool buffs %d\n",
+				map ? "map" : "unmap", result);
+			goto fail_map_buffer_smmu_enabled;
+		}
+	} else {
+		IPADBG("smmu is disabled on EMAC\n");
+		result = ipa3_smmu_map_peer_buff((u64)params->ring_base_pa,
+			params->ntn_ring_size, map, NULL, IPA_SMMU_CB_UC);
+		if (result) {
+			IPAERR("failed to %s ntn ring %d\n",
+				map ? "map" : "unmap", result);
+			goto fail_map_ring;
+		}
+		result = ipa3_smmu_map_peer_buff(params->buff_pool_base_pa,
+			params->num_buffers * 4, map, NULL, IPA_SMMU_CB_UC);
+		if (result) {
+			IPAERR("failed to %s pool buffs %d\n",
+				map ? "map" : "unmap", result);
+			goto fail_map_buffer_smmu_disabled;
+		}
+	}
+
+	if (ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_AP]) {
+		IPADBG("AP SMMU is set to s1 bypass\n");
+		return 0;
+	}
+
+	smmu_domain = ipa3_get_smmu_domain();
+	if (!smmu_domain) {
+		IPAERR("invalid smmu domain\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < params->num_buffers; i++) {
+		iova = (u64)params->data_buff_list[i].iova;
+		pa = (phys_addr_t)params->data_buff_list[i].pa;
+		IPA_SMMU_ROUND_TO_PAGE(iova, pa, params->data_buff_size, iova_p,
+			pa_p, size_p);
+		IPADBG("%s 0x%llx to 0x%pa size %d\n", map ? "mapping" :
+			"unmapping", iova_p, &pa_p, size_p);
+		if (map) {
+			result = ipa3_iommu_map(smmu_domain, iova_p, pa_p,
+				size_p, IOMMU_READ | IOMMU_WRITE);
+			if (result)
+				IPAERR("Fail to map 0x%llx\n", iova);
+		} else {
+			result = iommu_unmap(smmu_domain, iova_p, size_p);
+			if (result != params->data_buff_size)
+				IPAERR("Fail to unmap 0x%llx\n", iova);
+		}
+		if (result) {
+			if (params->smmu_enabled)
+				goto fail_map_data_buff_smmu_enabled;
+			else
+				goto fail_map_data_buff_smmu_disabled;
+		}
+	}
+	return 0;
+
+fail_map_data_buff_smmu_enabled:
+	ipa3_smmu_map_peer_buff((u64)params->buff_pool_base_iova,
+		params->num_buffers * 4, !map, NULL, IPA_SMMU_CB_UC);
+	goto fail_map_buffer_smmu_enabled;
+fail_map_data_buff_smmu_disabled:
+	ipa3_smmu_map_peer_buff(params->buff_pool_base_pa,
+		params->num_buffers * 4, !map, NULL, IPA_SMMU_CB_UC);
+	goto fail_map_buffer_smmu_disabled;
+fail_map_buffer_smmu_enabled:
+	ipa3_smmu_map_peer_buff((u64)params->ring_base_iova,
+		params->ntn_ring_size, !map, params->ring_base_sgt,
+		IPA_SMMU_CB_UC);
+	goto fail_map_ring;
+fail_map_buffer_smmu_disabled:
+	ipa3_smmu_map_peer_buff((u64)params->ring_base_pa,
+			params->ntn_ring_size, !map, NULL, IPA_SMMU_CB_UC);
+fail_map_ring:
+	ipa3_smmu_map_peer_reg(rounddown(params->ntn_reg_base_ptr_pa,
+		PAGE_SIZE), !map, IPA_SMMU_CB_UC);
+fail:
+	return result;
+}
+
 /**
  * ipa3_setup_uc_ntn_pipes() - setup uc offload pipes
  */
@@ -324,10 +456,16 @@
 		goto fail;
 	}
 
+	result = ipa3_smmu_map_uc_ntn_pipes(&in->ul, true);
+	if (result) {
+		IPAERR("failed to map SMMU for UL %d\n", result);
+		goto fail;
+	}
+
 	if (ipa3_uc_send_ntn_setup_pipe_cmd(&in->ul, IPA_NTN_RX_DIR)) {
 		IPAERR("fail to send cmd to uc for ul pipe\n");
 		result = -EFAULT;
-		goto fail;
+		goto fail_smmu_map_ul;
 	}
 	ipa3_install_dflt_flt_rules(ipa_ep_idx_ul);
 	outp->ul_uc_db_pa = IPA_UC_NTN_DB_PA_RX;
@@ -346,13 +484,19 @@
 	if (ipa3_cfg_ep(ipa_ep_idx_dl, &ep_dl->cfg)) {
 		IPAERR("fail to setup dl pipe cfg\n");
 		result = -EFAULT;
-		goto fail;
+		goto fail_smmu_map_ul;
+	}
+
+	result = ipa3_smmu_map_uc_ntn_pipes(&in->dl, true);
+	if (result) {
+		IPAERR("failed to map SMMU for DL %d\n", result);
+		goto fail_smmu_map_ul;
 	}
 
 	if (ipa3_uc_send_ntn_setup_pipe_cmd(&in->dl, IPA_NTN_TX_DIR)) {
 		IPAERR("fail to send cmd to uc for dl pipe\n");
 		result = -EFAULT;
-		goto fail;
+		goto fail_smmu_map_dl;
 	}
 	outp->dl_uc_db_pa = IPA_UC_NTN_DB_PA_TX;
 	ep_dl->uc_offload_state |= IPA_UC_OFFLOAD_CONNECTED;
@@ -362,11 +506,17 @@
 		IPAERR("Enable data path failed res=%d clnt=%d.\n", result,
 			ipa_ep_idx_dl);
 		result = -EFAULT;
-		goto fail;
+		goto fail_smmu_map_dl;
 	}
 	IPADBG("client %d (ep: %d) connected\n", in->dl.client,
 		ipa_ep_idx_dl);
 
+	return 0;
+
+fail_smmu_map_dl:
+	ipa3_smmu_map_uc_ntn_pipes(&in->dl, false);
+fail_smmu_map_ul:
+	ipa3_smmu_map_uc_ntn_pipes(&in->ul, false);
 fail:
 	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 	return result;
@@ -377,7 +527,7 @@
  */
 
 int ipa3_tear_down_uc_offload_pipes(int ipa_ep_idx_ul,
-		int ipa_ep_idx_dl)
+		int ipa_ep_idx_dl, struct ipa_ntn_conn_in_params *params)
 {
 	struct ipa_mem_buffer cmd;
 	struct ipa3_ep_context *ep_ul, *ep_dl;
@@ -442,6 +592,13 @@
 		goto fail;
 	}
 
+	/* unmap the DL pipe */
+	result = ipa3_smmu_map_uc_ntn_pipes(&params->dl, false);
+	if (result) {
+		IPAERR("failed to unmap SMMU for DL %d\n", result);
+		goto fail;
+	}
+
 	/* teardown the UL pipe */
 	tear->params.ipa_pipe_number = ipa_ep_idx_ul;
 	result = ipa3_uc_send_cmd((u32)(cmd.phys_base),
@@ -453,6 +610,14 @@
 		result = -EFAULT;
 		goto fail;
 	}
+
+	/* unmap the UL pipe */
+	result = ipa3_smmu_map_uc_ntn_pipes(&params->ul, false);
+	if (result) {
+		IPAERR("failed to unmap SMMU for UL %d\n", result);
+		goto fail;
+	}
+
 	ipa3_delete_dflt_flt_rules(ipa_ep_idx_ul);
 	memset(&ipa3_ctx->ep[ipa_ep_idx_ul], 0, sizeof(struct ipa3_ep_context));
 	IPADBG("ul client (ep: %d) disconnected\n", ipa_ep_idx_ul);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index d33fc0f..80155f9 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -4386,6 +4386,7 @@
 	api_ctrl->ipa_cfg_ep_holb_by_client = ipa3_cfg_ep_holb_by_client;
 	api_ctrl->ipa_cfg_ep_ctrl = ipa3_cfg_ep_ctrl;
 	api_ctrl->ipa_add_hdr = ipa3_add_hdr;
+	api_ctrl->ipa_add_hdr_usr = ipa3_add_hdr_usr;
 	api_ctrl->ipa_del_hdr = ipa3_del_hdr;
 	api_ctrl->ipa_commit_hdr = ipa3_commit_hdr;
 	api_ctrl->ipa_reset_hdr = ipa3_reset_hdr;
@@ -4395,6 +4396,7 @@
 	api_ctrl->ipa_add_hdr_proc_ctx = ipa3_add_hdr_proc_ctx;
 	api_ctrl->ipa_del_hdr_proc_ctx = ipa3_del_hdr_proc_ctx;
 	api_ctrl->ipa_add_rt_rule = ipa3_add_rt_rule;
+	api_ctrl->ipa_add_rt_rule_usr = ipa3_add_rt_rule_usr;
 	api_ctrl->ipa_del_rt_rule = ipa3_del_rt_rule;
 	api_ctrl->ipa_commit_rt = ipa3_commit_rt;
 	api_ctrl->ipa_reset_rt = ipa3_reset_rt;
@@ -4403,6 +4405,7 @@
 	api_ctrl->ipa_query_rt_index = ipa3_query_rt_index;
 	api_ctrl->ipa_mdfy_rt_rule = ipa3_mdfy_rt_rule;
 	api_ctrl->ipa_add_flt_rule = ipa3_add_flt_rule;
+	api_ctrl->ipa_add_flt_rule_usr = ipa3_add_flt_rule_usr;
 	api_ctrl->ipa_del_flt_rule = ipa3_del_flt_rule;
 	api_ctrl->ipa_mdfy_flt_rule = ipa3_mdfy_flt_rule;
 	api_ctrl->ipa_commit_flt = ipa3_commit_flt;
@@ -5309,14 +5312,14 @@
 }
 
 /**
-* ipa3_disable_prefetch() - disable\enable tx prefetch
-*
-* @client: the client which is related to the TX where prefetch will be
-*          disabled
-*
-* Return value: Non applicable
-*
-*/
+ * ipa3_disable_prefetch() - disable\enable tx prefetch
+ *
+ * @client: the client which is related to the TX where prefetch will be
+ *          disabled
+ *
+ * Return value: Non applicable
+ *
+ */
 void ipa3_disable_prefetch(enum ipa_client_type client)
 {
 	struct ipahal_reg_tx_cfg cfg;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
index 8f78d56..26b7f0f 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -46,6 +46,15 @@
 			IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \
 	} while (0)
 
+#define IPAHAL_DBG_REG(fmt, args...) \
+	do { \
+		pr_err(fmt, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+			" %s:%d " fmt, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+			" %s:%d " fmt, ## args); \
+	} while (0)
+
 #define IPAHAL_ERR_RL(fmt, args...) \
 		do { \
 			pr_err_ratelimited_ipa(IPAHAL_DRV_NAME " %s:%d " fmt, \
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index 66837d0..ce59488 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -18,6 +18,8 @@
 #include "ipahal_reg.h"
 #include "ipahal_reg_i.h"
 
+#define IPA_MAX_MSG_LEN 4096
+
 static const char *ipareg_name_to_str[IPA_REG_MAX] = {
 	__stringify(IPA_ROUTE),
 	__stringify(IPA_IRQ_STTS_EE_n),
@@ -26,6 +28,9 @@
 	__stringify(IPA_IRQ_SUSPEND_INFO_EE_n),
 	__stringify(IPA_SUSPEND_IRQ_EN_EE_n),
 	__stringify(IPA_SUSPEND_IRQ_CLR_EE_n),
+	__stringify(IPA_HOLB_DROP_IRQ_INFO_EE_n),
+	__stringify(IPA_HOLB_DROP_IRQ_EN_EE_n),
+	__stringify(IPA_HOLB_DROP_IRQ_CLR_EE_n),
 	__stringify(IPA_BCR),
 	__stringify(IPA_ENABLED_PIPES),
 	__stringify(IPA_COMP_SW_RESET),
@@ -35,7 +40,20 @@
 	__stringify(IPA_SPARE_REG_1),
 	__stringify(IPA_SPARE_REG_2),
 	__stringify(IPA_COMP_CFG),
+	__stringify(IPA_STATE_TX_WRAPPER),
+	__stringify(IPA_STATE_TX1),
+	__stringify(IPA_STATE_FETCHER),
+	__stringify(IPA_STATE_FETCHER_MASK),
+	__stringify(IPA_STATE_DFETCHER),
+	__stringify(IPA_STATE_ACL),
+	__stringify(IPA_STATE),
+	__stringify(IPA_STATE_RX_ACTIVE),
+	__stringify(IPA_STATE_TX0),
 	__stringify(IPA_STATE_AGGR_ACTIVE),
+	__stringify(IPA_STATE_GSI_TLV),
+	__stringify(IPA_STATE_GSI_AOS),
+	__stringify(IPA_STATE_GSI_IF),
+	__stringify(IPA_STATE_GSI_SKIP),
 	__stringify(IPA_ENDP_INIT_HDR_n),
 	__stringify(IPA_ENDP_INIT_HDR_EXT_n),
 	__stringify(IPA_ENDP_INIT_AGGR_n),
@@ -46,6 +64,7 @@
 	__stringify(IPA_ENDP_INIT_CONN_TRACK_n),
 	__stringify(IPA_ENDP_INIT_CTRL_n),
 	__stringify(IPA_ENDP_INIT_CTRL_SCND_n),
+	__stringify(IPA_ENDP_INIT_CTRL_STATUS_n),
 	__stringify(IPA_ENDP_INIT_HOL_BLOCK_EN_n),
 	__stringify(IPA_ENDP_INIT_HOL_BLOCK_TIMER_n),
 	__stringify(IPA_ENDP_INIT_DEAGGR_n),
@@ -55,6 +74,7 @@
 	__stringify(IPA_IRQ_EE_UC_n),
 	__stringify(IPA_ENDP_INIT_HDR_METADATA_MASK_n),
 	__stringify(IPA_ENDP_INIT_HDR_METADATA_n),
+	__stringify(IPA_ENDP_INIT_PROD_CFG_n),
 	__stringify(IPA_ENDP_INIT_RSRC_GRP_n),
 	__stringify(IPA_SHARED_MEM_SIZE),
 	__stringify(IPA_SRAM_DIRECT_ACCESS_n),
@@ -66,6 +86,8 @@
 	__stringify(IPA_SYS_PKT_PROC_CNTXT_BASE),
 	__stringify(IPA_LOCAL_PKT_PROC_CNTXT_BASE),
 	__stringify(IPA_ENDP_STATUS_n),
+	__stringify(IPA_ENDP_WEIGHTS_n),
+	__stringify(IPA_ENDP_YELLOW_RED_MARKER),
 	__stringify(IPA_ENDP_FILTER_ROUTER_HSH_CFG_n),
 	__stringify(IPA_SRC_RSRC_GRP_01_RSRC_TYPE_n),
 	__stringify(IPA_SRC_RSRC_GRP_23_RSRC_TYPE_n),
@@ -105,6 +127,12 @@
 	__stringify(IPA_STAT_ROUTER_IPV6_END_ID),
 	__stringify(IPA_STAT_DROP_CNT_BASE_n),
 	__stringify(IPA_STAT_DROP_CNT_MASK_n),
+	__stringify(IPA_SNOC_FEC_EE_n),
+	__stringify(IPA_FEC_ADDR_EE_n),
+	__stringify(IPA_FEC_ADDR_MSB_EE_n),
+	__stringify(IPA_FEC_ATTR_EE_n),
+	__stringify(IPA_MBIM_DEAGGR_FEC_ATTR_EE_n),
+	__stringify(IPA_GEN_DEAGGR_FEC_ATTR_EE_n),
 };
 
 static void ipareg_construct_dummy(enum ipahal_reg_name reg,
@@ -1651,6 +1679,9 @@
  * @parse - CB to parse register value to abstracted structure
  * @offset - register offset relative to base address
  * @n_ofst - N parameterized register sub-offset
+ * @n_start - starting n for n_registers
+ * @n_end - ending n for n_registers
+ * @en_print - enable this register to be printed when the device crashes
  */
 struct ipahal_reg_obj {
 	void (*construct)(enum ipahal_reg_name reg, const void *fields,
@@ -1659,6 +1690,9 @@
 		u32 val);
 	u32 offset;
 	u32 n_ofst;
+	int n_start;
+	int n_end;
+	bool en_print;
 };
 
 /*
@@ -1676,365 +1710,543 @@
 	/* IPAv3 */
 	[IPA_HW_v3_0][IPA_ROUTE] = {
 		ipareg_construct_route, ipareg_parse_dummy,
-		0x00000048, 0},
+		0x00000048, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_IRQ_STTS_EE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00003008, 0x1000},
+		0x00003008, 0x1000, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_IRQ_EN_EE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x0000300c, 0x1000},
+		0x0000300c, 0x1000, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_IRQ_CLR_EE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00003010, 0x1000},
+		0x00003010, 0x1000, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_IRQ_SUSPEND_INFO_EE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00003098, 0x1000},
+		0x00003098, 0x1000, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_BCR] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x000001D0, 0},
+		0x000001D0, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENABLED_PIPES] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000038, 0},
+		0x00000038, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_COMP_SW_RESET] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000040, 0},
+		0x00000040, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_VERSION] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000034, 0},
+		0x00000034, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_TAG_TIMER] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000060, 0 },
+		0x00000060, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_COMP_HW_VERSION] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000030, 0},
+		0x00000030, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_SPARE_REG_1] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00005090, 0},
+		0x00005090, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_SPARE_REG_2] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00005094, 0},
+		0x00005094, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_COMP_CFG] = {
 		ipareg_construct_comp_cfg, ipareg_parse_comp_cfg,
-		0x0000003C, 0},
+		0x0000003C, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_STATE_AGGR_ACTIVE] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x0000010C, 0},
+		0x0000010C, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_HDR_n] = {
 		ipareg_construct_endp_init_hdr_n, ipareg_parse_dummy,
-		0x00000810, 0x70},
+		0x00000810, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_HDR_EXT_n] = {
 		ipareg_construct_endp_init_hdr_ext_n, ipareg_parse_dummy,
-		0x00000814, 0x70},
+		0x00000814, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_AGGR_n] = {
 		ipareg_construct_endp_init_aggr_n,
 		ipareg_parse_endp_init_aggr_n,
-		0x00000824, 0x70},
+		0x00000824, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_AGGR_FORCE_CLOSE] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x000001EC, 0},
+		0x000001EC, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_ROUTE_n] = {
 		ipareg_construct_endp_init_route_n, ipareg_parse_dummy,
-		0x00000828, 0x70},
+		0x00000828, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_MODE_n] = {
 		ipareg_construct_endp_init_mode_n, ipareg_parse_dummy,
-		0x00000820, 0x70},
+		0x00000820, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_NAT_n] = {
 		ipareg_construct_endp_init_nat_n, ipareg_parse_dummy,
-		0x0000080C, 0x70},
+		0x0000080C, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_CTRL_n] = {
 		ipareg_construct_endp_init_ctrl_n,
 		ipareg_parse_endp_init_ctrl_n,
-		0x00000800, 0x70},
+		0x00000800, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_CTRL_SCND_n] = {
 		ipareg_construct_endp_init_ctrl_scnd_n, ipareg_parse_dummy,
-		0x00000804, 0x70 },
+		0x00000804, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_HOL_BLOCK_EN_n] = {
 		ipareg_construct_endp_init_hol_block_en_n,
 		ipareg_parse_dummy,
-		0x0000082c, 0x70},
+		0x0000082c, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_HOL_BLOCK_TIMER_n] = {
 		ipareg_construct_endp_init_hol_block_timer_n,
 		ipareg_parse_dummy,
-		0x00000830, 0x70},
+		0x00000830, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_DEAGGR_n] = {
 		ipareg_construct_endp_init_deaggr_n,
 		ipareg_parse_dummy,
-		0x00000834, 0x70},
+		0x00000834, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_SEQ_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x0000083C, 0x70},
+		0x0000083C, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_DEBUG_CNT_REG_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000600, 0x4},
+		0x00000600, 0x4, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_CFG_n] = {
 		ipareg_construct_endp_init_cfg_n, ipareg_parse_dummy,
-		0x00000808, 0x70},
+		0x00000808, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_IRQ_EE_UC_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x0000301c, 0x1000},
+		0x0000301c, 0x1000, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_HDR_METADATA_MASK_n] = {
 		ipareg_construct_endp_init_hdr_metadata_mask_n,
 		ipareg_parse_dummy,
-		0x00000818, 0x70},
+		0x00000818, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_HDR_METADATA_n] = {
 		ipareg_construct_endp_init_hdr_metadata_n,
 		ipareg_parse_dummy,
-		0x0000081c, 0x70},
+		0x0000081c, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_INIT_RSRC_GRP_n] = {
 		ipareg_construct_endp_init_rsrc_grp_n,
 		ipareg_parse_dummy,
-		0x00000838, 0x70},
+		0x00000838, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_SHARED_MEM_SIZE] = {
 		ipareg_construct_dummy, ipareg_parse_shared_mem_size,
-		0x00000054, 0},
+		0x00000054, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_SRAM_DIRECT_ACCESS_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00007000, 0x4},
+		0x00007000, 0x4, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_DEBUG_CNT_CTRL_n] = {
 		ipareg_construct_debug_cnt_ctrl_n, ipareg_parse_dummy,
-		0x00000640, 0x4},
+		0x00000640, 0x4, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_UC_MAILBOX_m_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00032000, 0x4},
+		0x00032000, 0x4, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_FILT_ROUT_HASH_FLUSH] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000090, 0},
+		0x00000090, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_SINGLE_NDP_MODE] = {
 		ipareg_construct_single_ndp_mode, ipareg_parse_single_ndp_mode,
-		0x00000068, 0},
+		0x00000068, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_QCNCM] = {
 		ipareg_construct_qcncm, ipareg_parse_qcncm,
-		0x00000064, 0},
+		0x00000064, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_SYS_PKT_PROC_CNTXT_BASE] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x000001e0, 0},
+		0x000001e0, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_LOCAL_PKT_PROC_CNTXT_BASE] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x000001e8, 0},
+		0x000001e8, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_STATUS_n] = {
 		ipareg_construct_endp_status_n, ipareg_parse_dummy,
-		0x00000840, 0x70},
+		0x00000840, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_ENDP_FILTER_ROUTER_HSH_CFG_n] = {
 		ipareg_construct_hash_cfg_n, ipareg_parse_hash_cfg_n,
-		0x0000085C, 0x70},
+		0x0000085C, 0x70, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_SRC_RSRC_GRP_01_RSRC_TYPE_n] = {
 		ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
-		0x00000400, 0x20},
+		0x00000400, 0x20, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_SRC_RSRC_GRP_23_RSRC_TYPE_n] = {
 		ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
-		0x00000404, 0x20},
+		0x00000404, 0x20, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_SRC_RSRC_GRP_45_RSRC_TYPE_n] = {
 		ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
-		0x00000408, 0x20},
+		0x00000408, 0x20, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_SRC_RSRC_GRP_67_RSRC_TYPE_n] = {
 		ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
-		0x0000040C, 0x20},
+		0x0000040C, 0x20, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_DST_RSRC_GRP_01_RSRC_TYPE_n] = {
 		ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
-		0x00000500, 0x20},
+		0x00000500, 0x20, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_DST_RSRC_GRP_23_RSRC_TYPE_n] = {
 		ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
-		0x00000504, 0x20},
+		0x00000504, 0x20, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_DST_RSRC_GRP_45_RSRC_TYPE_n] = {
 		ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
-		0x00000508, 0x20},
+		0x00000508, 0x20, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_DST_RSRC_GRP_67_RSRC_TYPE_n] = {
 		ipareg_construct_rsrg_grp_xy, ipareg_parse_dummy,
-		0x0000050c, 0x20},
+		0x0000050c, 0x20, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_RX_HPS_CLIENTS_MIN_DEPTH_0] = {
 		ipareg_construct_rx_hps_clients_depth0, ipareg_parse_dummy,
-		0x000023C4, 0},
+		0x000023C4, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_RX_HPS_CLIENTS_MIN_DEPTH_1] = {
 		ipareg_construct_rx_hps_clients_depth1, ipareg_parse_dummy,
-		0x000023C8, 0},
+		0x000023C8, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_RX_HPS_CLIENTS_MAX_DEPTH_0] = {
 		ipareg_construct_rx_hps_clients_depth0, ipareg_parse_dummy,
-		0x000023CC, 0},
+		0x000023CC, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_RX_HPS_CLIENTS_MAX_DEPTH_1] = {
 		ipareg_construct_rx_hps_clients_depth1, ipareg_parse_dummy,
-		0x000023D0, 0},
+		0x000023D0, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_QSB_MAX_WRITES] = {
 		ipareg_construct_qsb_max_writes, ipareg_parse_dummy,
-		0x00000074, 0},
+		0x00000074, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_QSB_MAX_READS] = {
 		ipareg_construct_qsb_max_reads, ipareg_parse_dummy,
-		0x00000078, 0},
+		0x00000078, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_DPS_SEQUENCER_FIRST] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x0001e000, 0},
+		0x0001e000, 0, 0, 0, 0},
 	[IPA_HW_v3_0][IPA_HPS_SEQUENCER_FIRST] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x0001e080, 0},
+		0x0001e080, 0, 0, 0, 0},
 
 
 	/* IPAv3.1 */
 	[IPA_HW_v3_1][IPA_IRQ_SUSPEND_INFO_EE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00003030, 0x1000},
+		0x00003030, 0x1000, 0, 0, 0},
 	[IPA_HW_v3_1][IPA_SUSPEND_IRQ_EN_EE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00003034, 0x1000},
+		0x00003034, 0x1000, 0, 0, 0},
 	[IPA_HW_v3_1][IPA_SUSPEND_IRQ_CLR_EE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00003038, 0x1000},
+		0x00003038, 0x1000, 0, 0, 0},
 
 
 	/* IPAv3.5 */
 	[IPA_HW_v3_5][IPA_TX_CFG] = {
 		ipareg_construct_tx_cfg, ipareg_parse_tx_cfg,
-		0x000001FC, 0},
+		0x000001FC, 0, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_SRC_RSRC_GRP_01_RSRC_TYPE_n] = {
 		ipareg_construct_rsrg_grp_xy_v3_5, ipareg_parse_dummy,
-		0x00000400, 0x20},
+		0x00000400, 0x20, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_SRC_RSRC_GRP_23_RSRC_TYPE_n] = {
 		ipareg_construct_rsrg_grp_xy_v3_5, ipareg_parse_dummy,
-		0x00000404, 0x20},
+		0x00000404, 0x20, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_SRC_RSRC_GRP_45_RSRC_TYPE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		-1, 0},
+		-1, 0, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_SRC_RSRC_GRP_67_RSRC_TYPE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		-1, 0},
+		-1, 0, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_DST_RSRC_GRP_01_RSRC_TYPE_n] = {
 		ipareg_construct_rsrg_grp_xy_v3_5, ipareg_parse_dummy,
-		0x00000500, 0x20},
+		0x00000500, 0x20, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_DST_RSRC_GRP_23_RSRC_TYPE_n] = {
 		ipareg_construct_rsrg_grp_xy_v3_5, ipareg_parse_dummy,
-		0x00000504, 0x20},
+		0x00000504, 0x20, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_DST_RSRC_GRP_45_RSRC_TYPE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		-1, 0},
+		-1, 0, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_DST_RSRC_GRP_67_RSRC_TYPE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		-1, 0},
+		-1, 0, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_ENDP_INIT_RSRC_GRP_n] = {
 		ipareg_construct_endp_init_rsrc_grp_n_v3_5,
 		ipareg_parse_dummy,
-		0x00000838, 0x70},
+		0x00000838, 0x70, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_RX_HPS_CLIENTS_MIN_DEPTH_0] = {
 		ipareg_construct_rx_hps_clients_depth0_v3_5,
 		ipareg_parse_dummy,
-		0x000023C4, 0},
+		0x000023C4, 0, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_RX_HPS_CLIENTS_MIN_DEPTH_1] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		-1, 0},
+		-1, 0, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_RX_HPS_CLIENTS_MAX_DEPTH_0] = {
 		ipareg_construct_rx_hps_clients_depth0_v3_5,
 		ipareg_parse_dummy,
-		0x000023CC, 0},
+		0x000023CC, 0, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_RX_HPS_CLIENTS_MAX_DEPTH_1] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		-1, 0},
+		-1, 0, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_SPARE_REG_1] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00002780, 0},
+		0x00002780, 0, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_SPARE_REG_2] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00002784, 0},
+		0x00002784, 0, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_IDLE_INDICATION_CFG] = {
 		ipareg_construct_idle_indication_cfg, ipareg_parse_dummy,
-		0x00000220, 0},
+		0x00000220, 0, 0, 0, 0},
 	[IPA_HW_v3_5][IPA_HPS_FTCH_ARB_QUEUE_WEIGHT] = {
 		ipareg_construct_hps_queue_weights,
-		ipareg_parse_hps_queue_weights, 0x000005a4, 0},
+		ipareg_parse_hps_queue_weights, 0x000005a4, 0, 0, 0, 0},
 
 	/* IPAv4.0 */
+	[IPA_HW_v4_0][IPA_IRQ_SUSPEND_INFO_EE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00003030, 0x1000, 0, 1, 1},
+	[IPA_HW_v4_0][IPA_SUSPEND_IRQ_EN_EE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00003034, 0x1000, 0, 1, 1},
+	[IPA_HW_v4_0][IPA_SUSPEND_IRQ_CLR_EE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00003038, 0x1000, 0, 1, 1},
+	[IPA_HW_v4_0][IPA_IRQ_EN_EE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x0000300c, 0x1000, 0, 1, 1},
+	[IPA_HW_v4_0][IPA_TAG_TIMER] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000060, 0, 0, 0, 1},
 	[IPA_HW_v4_0][IPA_ENDP_INIT_CTRL_n] = {
 		ipareg_construct_endp_init_ctrl_n_v4_0, ipareg_parse_dummy,
-		0x00000800, 0x70 },
+		0x00000800, 0x70, 0, 23, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_HDR_EXT_n] = {
+		ipareg_construct_endp_init_hdr_ext_n, ipareg_parse_dummy,
+		0x00000814, 0x70, 0, 23, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_AGGR_n] = {
+		ipareg_construct_endp_init_aggr_n,
+		ipareg_parse_endp_init_aggr_n,
+		0x00000824, 0x70, 0, 23, 1},
 	[IPA_HW_v4_0][IPA_TX_CFG] = {
 		ipareg_construct_tx_cfg_v4_0, ipareg_parse_tx_cfg_v4_0,
-		0x000001FC, 0},
+		0x000001FC, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_DEBUG_CNT_REG_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		-1, 0},
+		-1, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_DEBUG_CNT_CTRL_n] = {
 		ipareg_construct_debug_cnt_ctrl_n, ipareg_parse_dummy,
-		-1, 0},
+		-1, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_QCNCM] = {
 		ipareg_construct_qcncm, ipareg_parse_qcncm,
-		-1, 0},
+		-1, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_SINGLE_NDP_MODE] = {
 		ipareg_construct_single_ndp_mode, ipareg_parse_single_ndp_mode,
-		-1, 0},
+		-1, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_QSB_MAX_READS] = {
 		ipareg_construct_qsb_max_reads_v4_0, ipareg_parse_dummy,
-		0x00000078, 0},
+		0x00000078, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_FILT_ROUT_HASH_FLUSH] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x0000014c, 0},
-	[IPA_HW_v4_0][IPA_STATE_AGGR_ACTIVE] = {
-		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x000000b4, 0},
+		0x0000014c, 0, 0, 0, 0},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_HDR_n] = {
+		ipareg_construct_endp_init_hdr_n, ipareg_parse_dummy,
+		0x00000810, 0x70, 0, 23, 1},
 	[IPA_HW_v4_0][IPA_ENDP_INIT_ROUTE_n] = {
 		ipareg_construct_endp_init_route_n, ipareg_parse_dummy,
-		-1, 0},
+		-1, 0, 0, 0, 0},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_MODE_n] = {
+		ipareg_construct_endp_init_mode_n, ipareg_parse_dummy,
+		0x00000820, 0x70, 0, 10, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_NAT_n] = {
+		ipareg_construct_endp_init_nat_n, ipareg_parse_dummy,
+		0x0000080C, 0x70, 0, 10, 1},
 	[IPA_HW_v4_0][IPA_ENDP_STATUS_n] = {
 		ipareg_construct_endp_status_n_v4_0, ipareg_parse_dummy,
-		0x00000840, 0x70},
-	[IPA_HW_v4_0][IPA_CLKON_CFG] = {
-		ipareg_construct_clkon_cfg, ipareg_parse_clkon_cfg,
-		0x00000044, 0},
+		0x00000840, 0x70, 0, 23, 1},
+	[IPA_HW_v4_0][IPA_ENDP_FILTER_ROUTER_HSH_CFG_n] = {
+		ipareg_construct_hash_cfg_n, ipareg_parse_hash_cfg_n,
+		0x0000085C, 0x70, 0, 32, 1},
 	[IPA_HW_v4_0][IPA_ENDP_INIT_CONN_TRACK_n] = {
 		ipareg_construct_endp_init_conn_track_n,
 		ipareg_parse_dummy,
-		0x00000850, 0x70},
+		0x00000850, 0x70, 0, 10, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_CTRL_SCND_n] = {
+		ipareg_construct_endp_init_ctrl_scnd_n, ipareg_parse_dummy,
+		0x00000804, 0x70, 0, 23, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_HOL_BLOCK_EN_n] = {
+		ipareg_construct_endp_init_hol_block_en_n,
+		ipareg_parse_dummy,
+		0x0000082c, 0x70, 10, 23, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_HOL_BLOCK_TIMER_n] = {
+		ipareg_construct_endp_init_hol_block_timer_n,
+		ipareg_parse_dummy,
+		0x00000830, 0x70, 10, 23, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_DEAGGR_n] = {
+		ipareg_construct_endp_init_deaggr_n,
+		ipareg_parse_dummy,
+		0x00000834, 0x70, 0, 10, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_SEQ_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x0000083C, 0x70, 0, 10, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_CFG_n] = {
+		ipareg_construct_endp_init_cfg_n, ipareg_parse_dummy,
+		0x00000808, 0x70, 0, 23, 1},
+	[IPA_HW_v4_0][IPA_IRQ_EE_UC_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x0000301c, 0x1000, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_HDR_METADATA_MASK_n] = {
+		ipareg_construct_endp_init_hdr_metadata_mask_n,
+		ipareg_parse_dummy,
+		0x00000818, 0x70, 10, 23, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_HDR_METADATA_n] = {
+		ipareg_construct_endp_init_hdr_metadata_n,
+		ipareg_parse_dummy,
+		0x0000081c, 0x70, 0, 10, 1},
+	[IPA_HW_v4_0][IPA_CLKON_CFG] = {
+		ipareg_construct_clkon_cfg, ipareg_parse_clkon_cfg,
+		0x00000044, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_QUOTA_BASE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000700, 0x4 },
+		0x00000700, 0x4, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_QUOTA_MASK_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000708, 0x4 },
+		0x00000708, 0x4, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_TETHERING_BASE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000710, 0x4 },
+		0x00000710, 0x4, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_TETHERING_MASK_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000718, 0x4 },
+		0x00000718, 0x4, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_FILTER_IPV4_BASE] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000720, 0x0 },
+		0x00000720, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_FILTER_IPV6_BASE] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000724, 0x0 },
+		0x00000724, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_ROUTER_IPV4_BASE] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000728, 0x0 },
+		0x00000728, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_ROUTER_IPV6_BASE] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x0000072C, 0x0 },
+		0x0000072C, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_FILTER_IPV4_START_ID] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000730, 0x0 },
+		0x00000730, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_FILTER_IPV6_START_ID] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000734, 0x0 },
+		0x00000734, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_ROUTER_IPV4_START_ID] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000738, 0x0 },
+		0x00000738, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_ROUTER_IPV6_START_ID] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x0000073C, 0x0 },
+		0x0000073C, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_FILTER_IPV4_END_ID] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000740, 0x0 },
+		0x00000740, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_FILTER_IPV6_END_ID] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000744, 0x0 },
+		0x00000744, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_ROUTER_IPV4_END_ID] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000748, 0x0 },
+		0x00000748, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_ROUTER_IPV6_END_ID] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x0000074C, 0x0 },
+		0x0000074C, 0, 0, 0, 0},
 	[IPA_HW_v4_0][IPA_STAT_DROP_CNT_BASE_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000750, 0x4 },
+		0x00000750, 0x4, 3, 1},
 	[IPA_HW_v4_0][IPA_STAT_DROP_CNT_MASK_n] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
-		0x00000758, 0x4 },
+		0x00000758, 0x4, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE_TX_WRAPPER] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000090, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE_TX1] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000094, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE_FETCHER] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000098, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE_FETCHER_MASK] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x0000009C, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE_DFETCHER] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x000000A0, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE_ACL] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x000000A4, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x000000A8, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE_RX_ACTIVE] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x000000AC, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE_TX0] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x000000B0, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE_AGGR_ACTIVE] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x000000B4, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE_GSI_TLV] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x000000B8, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE_GSI_AOS] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x000000B8, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE_GSI_IF] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x000000C0, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_STATE_GSI_SKIP] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x000000C4, 0, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_SNOC_FEC_EE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00003018, 0x1000, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_FEC_ADDR_EE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00003020, 0x1000, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_FEC_ADDR_MSB_EE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00003024, 0x1000, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_FEC_ATTR_EE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00003028, 0x1000, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_MBIM_DEAGGR_FEC_ATTR_EE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00003028, 0x1000, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_GEN_DEAGGR_FEC_ATTR_EE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00003028, 0x1000, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_HOLB_DROP_IRQ_INFO_EE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x0000303C, 0x1000, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_HOLB_DROP_IRQ_EN_EE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00003040, 0x1000, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_HOLB_DROP_IRQ_CLR_EE_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00003044, 0x1000, 0, 0, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_CTRL_STATUS_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000864, 0x70, 0, 23, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_PROD_CFG_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000CC8, 0x70, 10, 23, 1},
+	[IPA_HW_v4_0][IPA_ENDP_INIT_RSRC_GRP_n] = {
+		ipareg_construct_endp_init_rsrc_grp_n_v3_5,
+		ipareg_parse_dummy,
+		0x00000838, 0x70, 0, 23, 1},
+	[IPA_HW_v4_0][IPA_ENDP_WEIGHTS_n] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000CA4, 0x70, 10, 23, 1},
+	[IPA_HW_v4_0][IPA_ENDP_YELLOW_RED_MARKER] = {
+		ipareg_construct_dummy, ipareg_parse_dummy,
+		0x00000CC0, 0x70, 10, 23, 1},
 };
 
+int ipahal_print_all_regs(void)
+{
+	int i, j;
+
+	IPAHAL_DBG("Printing all registers for ipa_hw_type %d\n",
+		ipahal_ctx->hw_type);
+
+	if ((ipahal_ctx->hw_type < IPA_HW_v4_0) ||
+		(ipahal_ctx->hw_type >= IPA_HW_MAX)) {
+		IPAHAL_ERR("invalid IPA HW type (%d)\n", ipahal_ctx->hw_type);
+		return -EINVAL;
+	}
+
+	for (i = 0; i < IPA_REG_MAX ; i++) {
+		if (!ipahal_reg_objs[IPA_HW_v4_0][i].en_print)
+			continue;
+
+		j = ipahal_reg_objs[ipahal_ctx->hw_type][i].n_start;
+
+		if (j == ipahal_reg_objs[ipahal_ctx->hw_type][i].n_end)
+			IPAHAL_DBG_REG("%s=0x%x\n", ipahal_reg_name_str(i),
+				ipahal_read_reg_n(i, j));
+
+		for (; j < ipahal_reg_objs[ipahal_ctx->hw_type][i].n_end; j++)
+			IPAHAL_DBG_REG("%s_%u=0x%x\n", ipahal_reg_name_str(i),
+				j, ipahal_read_reg_n(i, j));
+	}
+	return 0;
+}
+
 /*
  * ipahal_reg_init() - Build the registers information table
  *  See ipahal_reg_objs[][] comments
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
index 2675771..7e8e8ba 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
@@ -29,6 +29,9 @@
 	IPA_IRQ_SUSPEND_INFO_EE_n,
 	IPA_SUSPEND_IRQ_EN_EE_n,
 	IPA_SUSPEND_IRQ_CLR_EE_n,
+	IPA_HOLB_DROP_IRQ_INFO_EE_n,
+	IPA_HOLB_DROP_IRQ_EN_EE_n,
+	IPA_HOLB_DROP_IRQ_CLR_EE_n,
 	IPA_BCR,
 	IPA_ENABLED_PIPES,
 	IPA_COMP_SW_RESET,
@@ -38,7 +41,20 @@
 	IPA_SPARE_REG_1,
 	IPA_SPARE_REG_2,
 	IPA_COMP_CFG,
+	IPA_STATE_TX_WRAPPER,
+	IPA_STATE_TX1,
+	IPA_STATE_FETCHER,
+	IPA_STATE_FETCHER_MASK,
+	IPA_STATE_DFETCHER,
+	IPA_STATE_ACL,
+	IPA_STATE,
+	IPA_STATE_RX_ACTIVE,
+	IPA_STATE_TX0,
 	IPA_STATE_AGGR_ACTIVE,
+	IPA_STATE_GSI_TLV,
+	IPA_STATE_GSI_AOS,
+	IPA_STATE_GSI_IF,
+	IPA_STATE_GSI_SKIP,
 	IPA_ENDP_INIT_HDR_n,
 	IPA_ENDP_INIT_HDR_EXT_n,
 	IPA_ENDP_INIT_AGGR_n,
@@ -49,6 +65,7 @@
 	IPA_ENDP_INIT_CONN_TRACK_n,
 	IPA_ENDP_INIT_CTRL_n,
 	IPA_ENDP_INIT_CTRL_SCND_n,
+	IPA_ENDP_INIT_CTRL_STATUS_n,
 	IPA_ENDP_INIT_HOL_BLOCK_EN_n,
 	IPA_ENDP_INIT_HOL_BLOCK_TIMER_n,
 	IPA_ENDP_INIT_DEAGGR_n,
@@ -58,6 +75,7 @@
 	IPA_IRQ_EE_UC_n,
 	IPA_ENDP_INIT_HDR_METADATA_MASK_n,
 	IPA_ENDP_INIT_HDR_METADATA_n,
+	IPA_ENDP_INIT_PROD_CFG_n,
 	IPA_ENDP_INIT_RSRC_GRP_n,
 	IPA_SHARED_MEM_SIZE,
 	IPA_SRAM_DIRECT_ACCESS_n,
@@ -69,6 +87,8 @@
 	IPA_SYS_PKT_PROC_CNTXT_BASE,
 	IPA_LOCAL_PKT_PROC_CNTXT_BASE,
 	IPA_ENDP_STATUS_n,
+	IPA_ENDP_WEIGHTS_n,
+	IPA_ENDP_YELLOW_RED_MARKER,
 	IPA_ENDP_FILTER_ROUTER_HSH_CFG_n,
 	IPA_SRC_RSRC_GRP_01_RSRC_TYPE_n,
 	IPA_SRC_RSRC_GRP_23_RSRC_TYPE_n,
@@ -108,6 +128,12 @@
 	IPA_STAT_ROUTER_IPV6_END_ID,
 	IPA_STAT_DROP_CNT_BASE_n,
 	IPA_STAT_DROP_CNT_MASK_n,
+	IPA_SNOC_FEC_EE_n,
+	IPA_FEC_ADDR_EE_n,
+	IPA_FEC_ADDR_MSB_EE_n,
+	IPA_FEC_ATTR_EE_n,
+	IPA_MBIM_DEAGGR_FEC_ATTR_EE_n,
+	IPA_GEN_DEAGGR_FEC_ATTR_EE_n,
 	IPA_REG_MAX,
 };
 
@@ -492,6 +518,9 @@
 	bool endp_delay;
 };
 
+
+int ipahal_print_all_regs(void);
+
 /*
  * ipahal_reg_name_str() - returns string that represent the register
  * @reg_name: [in] register name
diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c
index 47d5292..1c16e5a 100644
--- a/drivers/platform/msm/mhi_dev/mhi.c
+++ b/drivers/platform/msm/mhi_dev/mhi.c
@@ -38,6 +38,7 @@
 /* Wait time before suspend/resume is complete */
 #define MHI_SUSPEND_MIN			100
 #define MHI_SUSPEND_TIMEOUT		600
+#define MHI_WAKEUP_TIMEOUT_CNT		20
 #define MHI_MASK_CH_EV_LEN		32
 #define MHI_RING_CMD_ID			0
 #define MHI_RING_PRIMARY_EVT_ID		1
@@ -1326,6 +1327,8 @@
 	struct mhi_dev_channel *ch;
 	struct mhi_dev_ring *ring;
 	int ch_id = 0, rc = 0;
+	char *disconnected_12[2] = { "MHI_CHANNEL_STATE_12=DISCONNECTED", NULL};
+	char *disconnected_14[2] = { "MHI_CHANNEL_STATE_14=DISCONNECTED", NULL};
 
 	/* Hard stop all the channels */
 	for (ch_id = 0; ch_id < mhi->cfg.channels; ch_id++) {
@@ -1341,6 +1344,17 @@
 
 	/* Update ctrl node */
 	mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_DISCONNECTED);
+	mhi_update_state_info(MHI_CLIENT_MBIM_OUT, MHI_STATE_DISCONNECTED);
+	mhi_update_state_info(MHI_CLIENT_QMI_OUT, MHI_STATE_DISCONNECTED);
+	rc = kobject_uevent_env(&mhi_ctx->dev->kobj,
+				KOBJ_CHANGE, disconnected_12);
+	if (rc)
+		pr_err("Error sending uevent:%d\n", rc);
+
+	rc = kobject_uevent_env(&mhi_ctx->dev->kobj,
+				KOBJ_CHANGE, disconnected_14);
+	if (rc)
+		pr_err("Error sending uevent:%d\n", rc);
 
 	flush_workqueue(mhi->ring_init_wq);
 	flush_workqueue(mhi->pending_ring_wq);
@@ -2175,11 +2189,19 @@
 	}
 
 	while (atomic_read(&mhi_ctx->is_suspended) &&
-			suspend_wait_timeout < MHI_SUSPEND_TIMEOUT) {
+			suspend_wait_timeout < MHI_WAKEUP_TIMEOUT_CNT) {
 		/* wait for the suspend to finish */
 		msleep(MHI_SUSPEND_MIN);
 		suspend_wait_timeout++;
 	}
+
+	if (suspend_wait_timeout >= MHI_WAKEUP_TIMEOUT_CNT ||
+				mhi_ctx->ctrl_info != MHI_STATE_CONNECTED) {
+		pr_err("Failed to wake up core\n");
+		mutex_unlock(&mhi_ctx->mhi_write_test);
+		return -ENODEV;
+	}
+
 	handle_client = wreq->client;
 	ch = handle_client->channel;
 	ch->wr_request_active = true;
diff --git a/drivers/platform/msm/qcom-geni-se.c b/drivers/platform/msm/qcom-geni-se.c
index 348b287..6ce2161 100644
--- a/drivers/platform/msm/qcom-geni-se.c
+++ b/drivers/platform/msm/qcom-geni-se.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -165,6 +165,38 @@
 }
 EXPORT_SYMBOL(get_se_proto);
 
+/**
+ * get_se_m_fw() - Read the Firmware ver for the Main seqeuncer engine
+ * @base:	Base address of the serial engine's register block.
+ *
+ * Return:	Firmware version for the Main seqeuncer engine
+ */
+int get_se_m_fw(void __iomem *base)
+{
+	int fw_ver_m;
+
+	fw_ver_m = ((geni_read_reg(base, GENI_FW_REVISION_RO)
+			& FW_REV_VERSION_MSK));
+	return fw_ver_m;
+}
+EXPORT_SYMBOL(get_se_m_fw);
+
+/**
+ * get_se_s_fw() - Read the Firmware ver for the Secondry seqeuncer engine
+ * @base:	Base address of the serial engine's register block.
+ *
+ * Return:	Firmware version for the Secondry seqeuncer engine
+ */
+int get_se_s_fw(void __iomem *base)
+{
+	int fw_ver_s;
+
+	fw_ver_s = ((geni_read_reg(base, GENI_FW_S_REVISION_RO)
+			& FW_REV_VERSION_MSK));
+	return fw_ver_s;
+}
+EXPORT_SYMBOL(get_se_s_fw);
+
 static int se_geni_irq_en(void __iomem *base)
 {
 	unsigned int common_geni_m_irq_en;
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index b4cd640..9374bc8 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -26,6 +26,7 @@
 #include <linux/workqueue.h>
 #include <linux/dma-mapping.h>
 #include <linux/pm_runtime.h>
+#include <linux/usb/msm_hsusb.h>
 
 #define USB_THRESHOLD 512
 #define USB_BAM_MAX_STR_LEN 50
@@ -2969,9 +2970,6 @@
 	else
 		usb_bam_data->override_threshold = threshold;
 
-	usb_bam_data->enable_hsusb_bam_on_boot = of_property_read_bool(node,
-		"qcom,enable-hsusb-bam-on-boot");
-
 	for_each_child_of_node(pdev->dev.of_node, node)
 		max_connections++;
 
@@ -3095,48 +3093,42 @@
 	return NULL;
 }
 
-static int usb_bam_init(struct platform_device *pdev)
+static void msm_usb_bam_update_props(struct sps_bam_props *props,
+				struct platform_device *pdev)
 {
-	int ret;
 	struct usb_bam_ctx_type *ctx = dev_get_drvdata(&pdev->dev);
 	enum usb_ctrl bam_type = ctx->usb_bam_data->bam_type;
-	struct sps_bam_props props;
 	struct device *dev;
 
-	memset(&props, 0, sizeof(props));
-
-	pr_debug("%s: usb_bam_init - %s\n", __func__,
-		bam_enable_strings[bam_type]);
-
-	props.phys_addr = ctx->io_res->start;
-	props.virt_size = resource_size(ctx->io_res);
-	props.irq = ctx->irq;
-	props.summing_threshold = ctx->usb_bam_data->override_threshold;
-	props.event_threshold = ctx->usb_bam_data->override_threshold;
-	props.num_pipes = ctx->usb_bam_data->usb_bam_num_pipes;
-	props.callback = usb_bam_sps_events;
-	props.user = bam_enable_strings[bam_type];
+	props->phys_addr = ctx->io_res->start;
+	props->virt_addr = NULL;
+	props->virt_size = resource_size(ctx->io_res);
+	props->irq = ctx->irq;
+	props->summing_threshold = ctx->usb_bam_data->override_threshold;
+	props->event_threshold = ctx->usb_bam_data->override_threshold;
+	props->num_pipes = ctx->usb_bam_data->usb_bam_num_pipes;
+	props->callback = usb_bam_sps_events;
+	props->user = bam_enable_strings[bam_type];
 
 	/*
 	* HSUSB and HSIC Cores don't support RESET ACK signal to BAMs
 	* Hence, let BAM to ignore acknowledge from USB while resetting PIPE
 	*/
 	if (ctx->usb_bam_data->ignore_core_reset_ack && bam_type != DWC3_CTRL)
-		props.options = SPS_BAM_NO_EXT_P_RST;
+		props->options = SPS_BAM_NO_EXT_P_RST;
 
 	if (ctx->usb_bam_data->disable_clk_gating)
-		props.options |= SPS_BAM_NO_LOCAL_CLK_GATING;
+		props->options |= SPS_BAM_NO_LOCAL_CLK_GATING;
 
 	/*
-	 * HSUSB BAM is not NDP BAM and it must be enabled early before
+	 * HSUSB BAM is not NDP BAM and it must be enabled before
 	 * starting peripheral controller to avoid switching USB core mode
 	 * from legacy to BAM with ongoing data transfers.
 	 */
-	if (ctx->usb_bam_data->enable_hsusb_bam_on_boot
-					&& bam_type == CI_CTRL) {
-		pr_debug("Register and enable HSUSB BAM\n");
-		props.options |= SPS_BAM_OPT_ENABLE_AT_BOOT;
-		props.options |= SPS_BAM_FORCE_RESET;
+	if (bam_type == CI_CTRL) {
+		log_event_dbg("Register and enable HSUSB BAM\n");
+		props->options |= SPS_BAM_OPT_ENABLE_AT_BOOT;
+		props->options |= SPS_BAM_FORCE_RESET;
 	}
 
 	dev = &ctx->usb_bam_pdev->dev;
@@ -3145,9 +3137,29 @@
 						"qcom,smmu-s1-bypass")) {
 		pr_info("%s: setting SPS_BAM_SMMU_EN flag with (%s)\n",
 						__func__, dev_name(dev));
-		props.options |= SPS_BAM_SMMU_EN;
+		props->options |= SPS_BAM_SMMU_EN;
 	}
+}
 
+static int usb_bam_init(struct platform_device *pdev)
+{
+	int ret;
+	struct usb_bam_ctx_type *ctx = dev_get_drvdata(&pdev->dev);
+	enum usb_ctrl bam_type = ctx->usb_bam_data->bam_type;
+	struct sps_bam_props props;
+
+	pr_debug("%s: usb_bam_init - %s\n", __func__,
+		bam_enable_strings[bam_type]);
+
+	/*
+	 * CI USB2 BAM is registered before starting controller
+	 * and only if bam2bam function is present in composition
+	 */
+	if (bam_type == CI_CTRL)
+		return 0;
+
+	memset(&props, 0, sizeof(props));
+	msm_usb_bam_update_props(&props, pdev);
 	ret = sps_register_bam_device(&props, &ctx->h_bam);
 	if (ret < 0) {
 		log_event_err("%s: register bam error %d\n", __func__, ret);
@@ -3428,7 +3440,7 @@
 		return 0;
 
 	usb_bam_data = ctx->usb_bam_data;
-	if ((bam != CI_CTRL) || !usb_bam_data->enable_hsusb_bam_on_boot)
+	if (bam != CI_CTRL)
 		return 0;
 
 	if (!ctx->pipes_enabled_per_bam || info[bam].pipes_suspended)
@@ -3532,18 +3544,45 @@
 {
 	struct msm_usb_bam_data *usb_bam_data;
 	struct usb_bam_ctx_type *ctx = &msm_usb_bam[bam];
+	static bool bam_enabled;
+	int ret;
 
 	if (!ctx->usb_bam_pdev)
 		return 0;
 
 	usb_bam_data = ctx->usb_bam_data;
-	if ((bam != CI_CTRL) || !(bam_enable ||
-					usb_bam_data->enable_hsusb_bam_on_boot))
+	if (bam != CI_CTRL)
 		return 0;
 
-	msm_hw_bam_disable(1);
-	sps_device_reset(ctx->h_bam);
-	msm_hw_bam_disable(0);
+	if (bam_enabled == bam_enable) {
+		log_event_dbg("%s: USB BAM is already %s\n", __func__,
+				bam_enable ? "Registered" : "De-registered");
+		return 0;
+	}
+
+	if (bam_enable) {
+		struct sps_bam_props props;
+
+		memset(&props, 0, sizeof(props));
+		msm_usb_bam_update_props(&props, ctx->usb_bam_pdev);
+		msm_hw_bam_disable(1);
+		ret = sps_register_bam_device(&props, &ctx->h_bam);
+		bam_enabled = true;
+		if (ret < 0) {
+			log_event_err("%s: register bam error %d\n",
+					__func__, ret);
+			return -EFAULT;
+		}
+		log_event_dbg("%s: USB BAM Registered\n", __func__);
+		msm_hw_bam_disable(0);
+	} else {
+		msm_hw_soft_reset();
+		msm_hw_bam_disable(1);
+		sps_device_reset(ctx->h_bam);
+		sps_deregister_bam_device(ctx->h_bam);
+		log_event_dbg("%s: USB BAM De-registered\n", __func__);
+		bam_enabled = false;
+	}
 
 	return 0;
 }
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index 03bfd48..3dd1722 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -329,6 +329,8 @@
 	POWER_SUPPLY_ATTR(recharge_soc),
 	POWER_SUPPLY_ATTR(toggle_stat),
 	POWER_SUPPLY_ATTR(allow_hvdcp3),
+	POWER_SUPPLY_ATTR(hvdcp_opti_allowed),
+	POWER_SUPPLY_ATTR(max_pulse_allowed),
 	/* Local extensions of type int64_t */
 	POWER_SUPPLY_ATTR(charge_counter_ext),
 	/* Properties of type `const char *' */
@@ -336,6 +338,7 @@
 	POWER_SUPPLY_ATTR(manufacturer),
 	POWER_SUPPLY_ATTR(serial_number),
 	POWER_SUPPLY_ATTR(battery_type),
+	POWER_SUPPLY_ATTR(cycle_counts),
 };
 
 static struct attribute *
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index 223af14..275b982 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -74,6 +74,7 @@
 	int			total_settled_ua;
 	int			pl_settled_ua;
 	int			pl_fcc_max;
+	u32			wa_flags;
 	struct class		qcom_batt_class;
 	struct wakeup_source	*pl_ws;
 	struct notifier_block	nb;
@@ -85,6 +86,10 @@
 	PR_PARALLEL	= BIT(0),
 };
 
+enum {
+	AICL_RERUN_WA_BIT	= BIT(0),
+};
+
 static int debug_mask;
 module_param_named(debug_mask, debug_mask, int, 0600);
 
@@ -620,7 +625,7 @@
 	if (icl_ua > pval.intval)
 		rerun_aicl = true;
 
-	if (rerun_aicl) {
+	if (rerun_aicl && (chip->wa_flags & AICL_RERUN_WA_BIT)) {
 		/* set a lower ICL */
 		pval.intval = max(pval.intval - ICL_STEP_UA, ICL_STEP_UA);
 		power_supply_set_property(chip->main_psy,
@@ -1190,8 +1195,20 @@
 	return 0;
 }
 
+static void pl_config_init(struct pl_data *chip, int smb_version)
+{
+	switch (smb_version) {
+	case PMI8998_SUBTYPE:
+	case PM660_SUBTYPE:
+		chip->wa_flags = AICL_RERUN_WA_BIT;
+		break;
+	default:
+		break;
+	}
+}
+
 #define DEFAULT_RESTRICTED_CURRENT_UA	1000000
-int qcom_batt_init(void)
+int qcom_batt_init(int smb_version)
 {
 	struct pl_data *chip;
 	int rc = 0;
@@ -1206,6 +1223,7 @@
 	if (!chip)
 		return -ENOMEM;
 	chip->slave_pct = 50;
+	pl_config_init(chip, smb_version);
 	chip->restricted_current = DEFAULT_RESTRICTED_CURRENT_UA;
 
 	chip->pl_ws = wakeup_source_register("qcom-battery");
diff --git a/drivers/power/supply/qcom/battery.h b/drivers/power/supply/qcom/battery.h
index 38626e7..94e8800 100644
--- a/drivers/power/supply/qcom/battery.h
+++ b/drivers/power/supply/qcom/battery.h
@@ -12,6 +12,6 @@
 
 #ifndef __BATTERY_H
 #define __BATTERY_H
-int qcom_batt_init(void);
+int qcom_batt_init(int smb_version);
 void qcom_batt_deinit(void);
 #endif /* __BATTERY_H */
diff --git a/drivers/power/supply/qcom/fg-alg.c b/drivers/power/supply/qcom/fg-alg.c
new file mode 100644
index 0000000..3d74f7e
--- /dev/null
+++ b/drivers/power/supply/qcom/fg-alg.c
@@ -0,0 +1,606 @@
+/* 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.
+ */
+
+#define pr_fmt(fmt)	"ALG: %s: " fmt, __func__
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/power_supply.h>
+#include "fg-alg.h"
+
+#define FULL_SOC_RAW		255
+#define CAPACITY_DELTA_DECIPCT	500
+
+/* Cycle counter APIs */
+
+/**
+ * restore_cycle_count -
+ * @counter: Cycle counter object
+ *
+ * Restores all the counters back from FG/QG during boot
+ *
+ */
+int restore_cycle_count(struct cycle_counter *counter)
+{
+	int rc = 0;
+
+	if (!counter)
+		return -ENODEV;
+
+	mutex_lock(&counter->lock);
+	rc = counter->restore_count(counter->data, counter->count,
+			BUCKET_COUNT);
+	if (rc < 0)
+		pr_err("failed to restore cycle counter rc=%d\n", rc);
+	mutex_unlock(&counter->lock);
+
+	return rc;
+}
+
+/**
+ * clear_cycle_count -
+ * @counter: Cycle counter object
+ *
+ * Clears all the counters stored by FG/QG when a battery is inserted
+ * or the profile is re-loaded.
+ *
+ */
+void clear_cycle_count(struct cycle_counter *counter)
+{
+	int rc = 0, i;
+
+	if (!counter)
+		return;
+
+	mutex_lock(&counter->lock);
+	memset(counter->count, 0, sizeof(counter->count));
+	for (i = 0; i < BUCKET_COUNT; i++) {
+		counter->started[i] = false;
+		counter->last_soc[i] = 0;
+	}
+
+	rc = counter->store_count(counter->data, counter->count, 0,
+			BUCKET_COUNT * 2);
+	if (rc < 0)
+		pr_err("failed to clear cycle counter rc=%d\n", rc);
+
+	mutex_unlock(&counter->lock);
+}
+
+/**
+ * store_cycle_count -
+ * @counter: Cycle counter object
+ * @id: Cycle counter bucket id
+ *
+ * Stores the cycle counter for a bucket in FG/QG.
+ *
+ */
+static int store_cycle_count(struct cycle_counter *counter, int id)
+{
+	int rc = 0;
+	u16 cyc_count;
+
+	if (!counter)
+		return -ENODEV;
+
+	if (id < 0 || (id > BUCKET_COUNT - 1)) {
+		pr_err("Invalid id %d\n", id);
+		return -EINVAL;
+	}
+
+	cyc_count = counter->count[id];
+	cyc_count++;
+
+	rc = counter->store_count(counter->data, &cyc_count, id, 2);
+	if (rc < 0) {
+		pr_err("failed to write cycle_count[%d] rc=%d\n",
+			id, rc);
+		return rc;
+	}
+
+	counter->count[id] = cyc_count;
+	pr_debug("Stored count %d in id %d\n", cyc_count, id);
+
+	return rc;
+}
+
+/**
+ * cycle_count_update -
+ * @counter: Cycle counter object
+ * @batt_soc: Battery State of Charge (SOC)
+ * @charge_status: Charging status from power supply
+ * @charge_done: Indicator for charge termination
+ * @input_present: Indicator for input presence
+ *
+ * Called by FG/QG whenever there is a state change (Charging status, SOC)
+ *
+ */
+void cycle_count_update(struct cycle_counter *counter, int batt_soc,
+			int charge_status, bool charge_done, bool input_present)
+{
+	int rc = 0, id, i, soc_thresh;
+
+	if (!counter)
+		return;
+
+	mutex_lock(&counter->lock);
+
+	/* Find out which id the SOC falls in */
+	id = batt_soc / BUCKET_SOC_PCT;
+
+	if (charge_status == POWER_SUPPLY_STATUS_CHARGING) {
+		if (!counter->started[id] && id != counter->last_bucket) {
+			counter->started[id] = true;
+			counter->last_soc[id] = batt_soc;
+		}
+	} else if (charge_done || !input_present) {
+		for (i = 0; i < BUCKET_COUNT; i++) {
+			soc_thresh = counter->last_soc[i] + BUCKET_SOC_PCT / 2;
+			if (counter->started[i] && batt_soc > soc_thresh) {
+				rc = store_cycle_count(counter, i);
+				if (rc < 0)
+					pr_err("Error in storing cycle_ctr rc: %d\n",
+						rc);
+				counter->last_soc[i] = 0;
+				counter->started[i] = false;
+				counter->last_bucket = i;
+			}
+		}
+	}
+
+	pr_debug("batt_soc: %d id: %d chg_status: %d\n", batt_soc, id,
+		charge_status);
+	mutex_unlock(&counter->lock);
+}
+
+/**
+ * get_cycle_count -
+ * @counter: Cycle counter object
+ *
+ * Returns the cycle counter for a SOC bucket.
+ *
+ */
+int get_cycle_count(struct cycle_counter *counter)
+{
+	int count;
+
+	if (!counter)
+		return 0;
+
+	if ((counter->id <= 0) || (counter->id > BUCKET_COUNT))
+		return -EINVAL;
+
+	mutex_lock(&counter->lock);
+	count = counter->count[counter->id - 1];
+	mutex_unlock(&counter->lock);
+	return count;
+}
+
+/**
+ * cycle_count_init -
+ * @counter: Cycle counter object
+ *
+ * FG/QG have to call this during driver probe to validate the required
+ * parameters after allocating cycle_counter object.
+ *
+ */
+int cycle_count_init(struct cycle_counter *counter)
+{
+	if (!counter)
+		return -ENODEV;
+
+	if (!counter->data || !counter->restore_count ||
+		!counter->store_count) {
+		pr_err("Invalid parameters for using cycle counter\n");
+		return -EINVAL;
+	}
+
+	mutex_init(&counter->lock);
+	counter->last_bucket = -1;
+	return 0;
+}
+
+/* Capacity learning algorithm APIs */
+
+/**
+ * cap_learning_post_process -
+ * @cl: Capacity learning object
+ *
+ * Does post processing on the learnt capacity based on the user specified
+ * or default parameters for the capacity learning algorithm.
+ *
+ */
+static void cap_learning_post_process(struct cap_learning *cl)
+{
+	int64_t max_inc_val, min_dec_val, old_cap;
+	int rc;
+
+	if (cl->dt.skew_decipct) {
+		pr_debug("applying skew %d on current learnt capacity %lld\n",
+			cl->dt.skew_decipct, cl->final_cap_uah);
+		cl->final_cap_uah = cl->final_cap_uah *
+					(1000 + cl->dt.skew_decipct);
+		cl->final_cap_uah = div64_u64(cl->final_cap_uah, 1000);
+	}
+
+	max_inc_val = cl->learned_cap_uah * (1000 + cl->dt.max_cap_inc);
+	max_inc_val = div64_u64(max_inc_val, 1000);
+
+	min_dec_val = cl->learned_cap_uah * (1000 - cl->dt.max_cap_dec);
+	min_dec_val = div64_u64(min_dec_val, 1000);
+
+	old_cap = cl->learned_cap_uah;
+	if (cl->final_cap_uah > max_inc_val)
+		cl->learned_cap_uah = max_inc_val;
+	else if (cl->final_cap_uah < min_dec_val)
+		cl->learned_cap_uah = min_dec_val;
+	else
+		cl->learned_cap_uah = cl->final_cap_uah;
+
+	if (cl->dt.max_cap_limit) {
+		max_inc_val = (int64_t)cl->nom_cap_uah * (1000 +
+				cl->dt.max_cap_limit);
+		max_inc_val = div64_u64(max_inc_val, 1000);
+		if (cl->final_cap_uah > max_inc_val) {
+			pr_debug("learning capacity %lld goes above max limit %lld\n",
+				cl->final_cap_uah, max_inc_val);
+			cl->learned_cap_uah = max_inc_val;
+		}
+	}
+
+	if (cl->dt.min_cap_limit) {
+		min_dec_val = (int64_t)cl->nom_cap_uah * (1000 -
+				cl->dt.min_cap_limit);
+		min_dec_val = div64_u64(min_dec_val, 1000);
+		if (cl->final_cap_uah < min_dec_val) {
+			pr_debug("learning capacity %lld goes below min limit %lld\n",
+				cl->final_cap_uah, min_dec_val);
+			cl->learned_cap_uah = min_dec_val;
+		}
+	}
+
+	if (cl->store_learned_capacity) {
+		rc = cl->store_learned_capacity(cl->data, cl->learned_cap_uah);
+		if (rc < 0)
+			pr_err("Error in storing learned_cap_uah, rc=%d\n", rc);
+	}
+
+	pr_debug("final cap_uah = %lld, learned capacity %lld -> %lld uah\n",
+		cl->final_cap_uah, old_cap, cl->learned_cap_uah);
+}
+
+/**
+ * cap_learning_process_full_data -
+ * @cl: Capacity learning object
+ *
+ * Processes the coulomb counter during charge termination and calculates the
+ * delta w.r.to the coulomb counter obtained earlier when the learning begun.
+ *
+ */
+static int cap_learning_process_full_data(struct cap_learning *cl)
+{
+	int rc, cc_soc_sw, cc_soc_delta_pct;
+	int64_t delta_cap_uah;
+
+	rc = cl->get_cc_soc(cl->data, &cc_soc_sw);
+	if (rc < 0) {
+		pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
+		return rc;
+	}
+
+	cc_soc_delta_pct =
+		div64_s64((int64_t)(cc_soc_sw - cl->init_cc_soc_sw) * 100,
+			cl->cc_soc_max);
+
+	/* If the delta is < 50%, then skip processing full data */
+	if (cc_soc_delta_pct < 50) {
+		pr_err("cc_soc_delta_pct: %d\n", cc_soc_delta_pct);
+		return -ERANGE;
+	}
+
+	delta_cap_uah = div64_s64(cl->learned_cap_uah * cc_soc_delta_pct, 100);
+	cl->final_cap_uah = cl->init_cap_uah + delta_cap_uah;
+	pr_debug("Current cc_soc=%d cc_soc_delta_pct=%d total_cap_uah=%lld\n",
+		cc_soc_sw, cc_soc_delta_pct, cl->final_cap_uah);
+	return 0;
+}
+
+/**
+ * cap_learning_begin -
+ * @cl: Capacity learning object
+ * @batt_soc: Battery State of Charge (SOC)
+ *
+ * Gets the coulomb counter from FG/QG when the conditions are suitable for
+ * beginning capacity learning. Also, primes the coulomb counter based on
+ * battery SOC if required.
+ *
+ */
+static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc)
+{
+	int rc, cc_soc_sw, batt_soc_msb;
+
+	batt_soc_msb = batt_soc >> 24;
+	if (DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW) >
+		cl->dt.start_soc) {
+		pr_debug("Battery SOC %d is high!, not starting\n",
+			batt_soc_msb);
+		return -EINVAL;
+	}
+
+	cl->init_cap_uah = div64_s64(cl->learned_cap_uah * batt_soc_msb,
+					FULL_SOC_RAW);
+
+	if (cl->prime_cc_soc) {
+		/*
+		 * Prime cc_soc_sw with battery SOC when capacity learning
+		 * begins.
+		 */
+		rc = cl->prime_cc_soc(cl->data, batt_soc);
+		if (rc < 0) {
+			pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
+			goto out;
+		}
+	}
+
+	rc = cl->get_cc_soc(cl->data, &cc_soc_sw);
+	if (rc < 0) {
+		pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc);
+		goto out;
+	}
+
+	cl->init_cc_soc_sw = cc_soc_sw;
+	pr_debug("Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n",
+		batt_soc_msb, cl->init_cc_soc_sw);
+out:
+	return rc;
+}
+
+/**
+ * cap_learning_done -
+ * @cl: Capacity learning object
+ *
+ * Top level function for getting coulomb counter and post processing the
+ * data once the capacity learning is complete after charge termination.
+ *
+ */
+static int cap_learning_done(struct cap_learning *cl)
+{
+	int rc;
+
+	rc = cap_learning_process_full_data(cl);
+	if (rc < 0) {
+		pr_err("Error in processing cap learning full data, rc=%d\n",
+			rc);
+		goto out;
+	}
+
+	if (cl->prime_cc_soc) {
+		/* Write a FULL value to cc_soc_sw */
+		rc = cl->prime_cc_soc(cl->data, cl->cc_soc_max);
+		if (rc < 0) {
+			pr_err("Error in writing cc_soc_sw, rc=%d\n", rc);
+			goto out;
+		}
+	}
+
+	cap_learning_post_process(cl);
+out:
+	return rc;
+}
+
+/**
+ * cap_learning_update -
+ * @cl: Capacity learning object
+ * @batt_temp - Battery temperature
+ * @batt_soc: Battery State of Charge (SOC)
+ * @charge_status: Charging status from power supply
+ * @charge_done: Indicator for charge termination
+ * @input_present: Indicator for input presence
+ * @qnovo_en: Indicator for Qnovo enable status
+ *
+ * Called by FG/QG driver when there is a state change (Charging status, SOC)
+ *
+ */
+void cap_learning_update(struct cap_learning *cl, int batt_temp,
+			int batt_soc, int charge_status, bool charge_done,
+			bool input_present, bool qnovo_en)
+{
+	int rc, batt_soc_msb, batt_soc_prime;
+	bool prime_cc = false;
+
+	if (!cl)
+		return;
+
+	mutex_lock(&cl->lock);
+
+	if (batt_temp > cl->dt.max_temp || batt_temp < cl->dt.min_temp ||
+		!cl->learned_cap_uah) {
+		cl->active = false;
+		cl->init_cap_uah = 0;
+		goto out;
+	}
+
+	batt_soc_msb = (u32)batt_soc >> 24;
+	pr_debug("Charge_status: %d active: %d batt_soc: %d\n",
+		charge_status, cl->active, batt_soc_msb);
+
+	/* Initialize the starting point of learning capacity */
+	if (!cl->active) {
+		if (charge_status == POWER_SUPPLY_STATUS_CHARGING) {
+			rc = cap_learning_begin(cl, batt_soc);
+			cl->active = (rc == 0);
+		} else {
+			if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING ||
+				charge_done)
+				prime_cc = true;
+		}
+	} else {
+		if (charge_done) {
+			rc = cap_learning_done(cl);
+			if (rc < 0)
+				pr_err("Error in completing capacity learning, rc=%d\n",
+					rc);
+
+			cl->active = false;
+			cl->init_cap_uah = 0;
+		}
+
+		if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING) {
+			if (!input_present) {
+				pr_debug("Capacity learning aborted @ battery SOC %d\n",
+					 batt_soc_msb);
+				cl->active = false;
+				cl->init_cap_uah = 0;
+				prime_cc = true;
+			}
+		}
+
+		if (charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
+			if (qnovo_en && input_present) {
+				/*
+				 * Don't abort the capacity learning when qnovo
+				 * is enabled and input is present where the
+				 * charging status can go to "not charging"
+				 * intermittently.
+				 */
+			} else {
+				pr_debug("Capacity learning aborted @ battery SOC %d\n",
+					batt_soc_msb);
+				cl->active = false;
+				cl->init_cap_uah = 0;
+				prime_cc = true;
+			}
+		}
+	}
+
+	/*
+	 * Prime CC_SOC_SW when the device is not charging or during charge
+	 * termination when the capacity learning is not active.
+	 */
+
+	if (prime_cc && cl->prime_cc_soc) {
+		if (charge_done)
+			batt_soc_prime = cl->cc_soc_max;
+		else
+			batt_soc_prime = batt_soc;
+
+		rc = cl->prime_cc_soc(cl->data, batt_soc_prime);
+		if (rc < 0)
+			pr_err("Error in writing cc_soc_sw, rc=%d\n",
+				rc);
+	}
+
+out:
+	mutex_unlock(&cl->lock);
+}
+
+/**
+ * cap_learning_abort -
+ * @cl: Capacity learning object
+ *
+ * Aborts the capacity learning and initializes variables
+ *
+ */
+void cap_learning_abort(struct cap_learning *cl)
+{
+	if (!cl)
+		return;
+
+	mutex_lock(&cl->lock);
+	pr_debug("Aborting cap_learning\n");
+	cl->active = false;
+	cl->init_cap_uah = 0;
+	mutex_lock(&cl->lock);
+}
+
+/**
+ * cap_learning_post_profile_init -
+ * @cl: Capacity learning object
+ * @nom_cap_uah: Nominal capacity of battery in uAh
+ *
+ * Called by FG/QG once the profile load is complete and nominal capacity
+ * of battery is known. This also gets the last learned capacity back from
+ * FG/QG to feed back to the algorithm.
+ *
+ */
+int cap_learning_post_profile_init(struct cap_learning *cl, int64_t nom_cap_uah)
+{
+	int64_t delta_cap_uah, pct_nom_cap_uah;
+	int rc;
+
+	if (!cl || !cl->data)
+		return -EINVAL;
+
+	mutex_lock(&cl->lock);
+	cl->nom_cap_uah = nom_cap_uah;
+	rc = cl->get_learned_capacity(cl->data, &cl->learned_cap_uah);
+	if (rc < 0) {
+		pr_err("Couldn't get learned capacity, rc=%d\n", rc);
+		goto out;
+	}
+
+	if (cl->learned_cap_uah != cl->nom_cap_uah) {
+		if (cl->learned_cap_uah == 0)
+			cl->learned_cap_uah = cl->nom_cap_uah;
+
+		delta_cap_uah = abs(cl->learned_cap_uah - cl->nom_cap_uah);
+		pct_nom_cap_uah = div64_s64((int64_t)cl->nom_cap_uah *
+				CAPACITY_DELTA_DECIPCT, 1000);
+		/*
+		 * If the learned capacity is out of range by 50% from the
+		 * nominal capacity, then overwrite the learned capacity with
+		 * the nominal capacity.
+		 */
+		if (cl->nom_cap_uah && delta_cap_uah > pct_nom_cap_uah) {
+			pr_debug("learned_cap_uah: %lld is higher than expected, capping it to nominal: %lld\n",
+				cl->learned_cap_uah, cl->nom_cap_uah);
+			cl->learned_cap_uah = cl->nom_cap_uah;
+		}
+
+		rc = cl->store_learned_capacity(cl->data, cl->learned_cap_uah);
+		if (rc < 0)
+			pr_err("Error in storing learned_cap_uah, rc=%d\n", rc);
+	}
+
+out:
+	mutex_unlock(&cl->lock);
+	return rc;
+}
+
+/**
+ * cap_learning_init -
+ * @cl: Capacity learning object
+ *
+ * FG/QG have to call this during driver probe to validate the required
+ * parameters after allocating cap_learning object.
+ *
+ */
+int cap_learning_init(struct cap_learning *cl)
+{
+	if (!cl)
+		return -ENODEV;
+
+	if (!cl->get_learned_capacity || !cl->store_learned_capacity ||
+		!cl->get_cc_soc) {
+		pr_err("Insufficient functions for supporting capacity learning\n");
+		return -EINVAL;
+	}
+
+	if (!cl->cc_soc_max) {
+		pr_err("Insufficient parameters for supporting capacity learning\n");
+		return -EINVAL;
+	}
+
+	mutex_init(&cl->lock);
+	return 0;
+}
diff --git a/drivers/power/supply/qcom/fg-alg.h b/drivers/power/supply/qcom/fg-alg.h
new file mode 100644
index 0000000..ff5bece
--- /dev/null
+++ b/drivers/power/supply/qcom/fg-alg.h
@@ -0,0 +1,73 @@
+/* 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 __FG_ALG_H__
+#define __FG_ALG_H__
+
+#define BUCKET_COUNT		8
+#define BUCKET_SOC_PCT		(256 / BUCKET_COUNT)
+
+struct cycle_counter {
+	void		*data;
+	bool		started[BUCKET_COUNT];
+	u16		count[BUCKET_COUNT];
+	u8		last_soc[BUCKET_COUNT];
+	int		id;
+	int		last_bucket;
+	struct mutex	lock;
+	int (*restore_count)(void *data, u16 *buf, int num_bytes);
+	int (*store_count)(void *data, u16 *buf, int id, int num_bytes);
+};
+
+struct cl_params {
+	int	start_soc;
+	int	max_temp;
+	int	min_temp;
+	int	max_cap_inc;
+	int	max_cap_dec;
+	int	max_cap_limit;
+	int	min_cap_limit;
+	int	skew_decipct;
+};
+
+struct cap_learning {
+	void			*data;
+	int			init_cc_soc_sw;
+	int			cc_soc_max;
+	int64_t			nom_cap_uah;
+	int64_t			init_cap_uah;
+	int64_t			final_cap_uah;
+	int64_t			learned_cap_uah;
+	bool			active;
+	struct mutex		lock;
+	struct cl_params	dt;
+	int (*get_learned_capacity)(void *data, int64_t *learned_cap_uah);
+	int (*store_learned_capacity)(void *data, int64_t learned_cap_uah);
+	int (*get_cc_soc)(void *data, int *cc_soc_sw);
+	int (*prime_cc_soc)(void *data, u32 cc_soc_sw);
+};
+
+int restore_cycle_count(struct cycle_counter *counter);
+void clear_cycle_count(struct cycle_counter *counter);
+void cycle_count_update(struct cycle_counter *counter, int batt_soc,
+		int charge_status, bool charge_done, bool input_present);
+int get_cycle_count(struct cycle_counter *counter);
+int cycle_count_init(struct cycle_counter *counter);
+void cap_learning_abort(struct cap_learning *cl);
+void cap_learning_update(struct cap_learning *cl, int batt_temp,
+		int batt_soc, int charge_status, bool charge_done,
+		bool input_present, bool qnovo_en);
+int cap_learning_init(struct cap_learning *cl);
+int cap_learning_post_profile_init(struct cap_learning *cl,
+		int64_t nom_cap_uah);
+
+#endif
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index 4bd6c4f..f73e647 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -412,6 +412,7 @@
 };
 
 struct fg_chip {
+	struct thermal_zone_device	*tz_dev;
 	struct device		*dev;
 	struct pmic_revid_data	*pmic_rev_id;
 	struct regmap		*regmap;
diff --git a/drivers/power/supply/qcom/qg-core.h b/drivers/power/supply/qcom/qg-core.h
index 5ea9b78..6e44f33 100644
--- a/drivers/power/supply/qcom/qg-core.h
+++ b/drivers/power/supply/qcom/qg-core.h
@@ -29,7 +29,9 @@
 
 struct qg_dt {
 	int			vbatt_empty_mv;
+	int			vbatt_empty_cold_mv;
 	int			vbatt_low_mv;
+	int			vbatt_low_cold_mv;
 	int			vbatt_cutoff_mv;
 	int			iterm_ma;
 	int			s2_fifo_length;
@@ -44,6 +46,7 @@
 	int			delta_soc;
 	int			rbat_conn_mohm;
 	int			ignore_shutdown_soc_secs;
+	int			cold_temp_threshold;
 	bool			hold_soc_while_full;
 	bool			linearize_soc;
 };
@@ -115,8 +118,10 @@
 };
 
 enum ocv_type {
-	PON_OCV,
-	GOOD_OCV,
+	S7_PON_OCV,
+	S3_GOOD_OCV,
+	S3_LAST_OCV,
+	SDAM_PON_OCV,
 };
 
 enum debug_mask {
@@ -145,6 +150,7 @@
 
 enum qg_wa_flags {
 	QG_VBAT_LOW_WA = BIT(0),
+	QG_RECHARGE_SOC_WA = BIT(1),
 };
 
 
diff --git a/drivers/power/supply/qcom/qg-defs.h b/drivers/power/supply/qcom/qg-defs.h
index bbbc7ee..6ae9aa2 100644
--- a/drivers/power/supply/qcom/qg-defs.h
+++ b/drivers/power/supply/qcom/qg-defs.h
@@ -37,6 +37,8 @@
 
 #define V_RAW_TO_UV(V_RAW)		div_u64(194637ULL * (u64)V_RAW, 1000)
 #define I_RAW_TO_UA(I_RAW)		div_s64(152588LL * (s64)I_RAW, 1000)
+#define FIFO_V_RESET_VAL		0x8000
+#define FIFO_I_RESET_VAL		0x8000
 
 #define DEGC_SCALE			10
 #define UV_TO_DECIUV(a)			(a / 100)
diff --git a/drivers/power/supply/qcom/qg-reg.h b/drivers/power/supply/qcom/qg-reg.h
index 1f42a8c..96533d4 100644
--- a/drivers/power/supply/qcom/qg-reg.h
+++ b/drivers/power/supply/qcom/qg-reg.h
@@ -77,6 +77,8 @@
 #define QG_LAST_ADC_V_DATA0_REG			0xC0
 #define QG_LAST_ADC_I_DATA0_REG			0xC2
 
+#define QG_LAST_S3_SLEEP_V_DATA0_REG		0xCC
+
 /* SDAM offsets */
 #define QG_SDAM_VALID_OFFSET			0x46
 #define QG_SDAM_SOC_OFFSET			0x47
@@ -85,5 +87,6 @@
 #define QG_SDAM_OCV_OFFSET			0x4C
 #define QG_SDAM_IBAT_OFFSET			0x50
 #define QG_SDAM_TIME_OFFSET			0x54
+#define QG_SDAM_PON_OCV_OFFSET			0x7C
 
 #endif
diff --git a/drivers/power/supply/qcom/qg-sdam.c b/drivers/power/supply/qcom/qg-sdam.c
index 65bebab..54eed16 100644
--- a/drivers/power/supply/qcom/qg-sdam.c
+++ b/drivers/power/supply/qcom/qg-sdam.c
@@ -63,6 +63,11 @@
 		.offset = QG_SDAM_TIME_OFFSET,
 		.length = 4,
 	},
+	[SDAM_PON_OCV_UV] = {
+		.name	= "SDAM_PON_OCV",
+		.offset = QG_SDAM_PON_OCV_OFFSET,
+		.length = 2,
+	},
 };
 
 int qg_sdam_write(u8 param, u32 data)
diff --git a/drivers/power/supply/qcom/qg-sdam.h b/drivers/power/supply/qcom/qg-sdam.h
index a75ead9..51af04c 100644
--- a/drivers/power/supply/qcom/qg-sdam.h
+++ b/drivers/power/supply/qcom/qg-sdam.h
@@ -23,6 +23,7 @@
 	SDAM_OCV_UV,
 	SDAM_IBAT_UA,
 	SDAM_TIME_SEC,
+	SDAM_PON_OCV_UV,
 	SDAM_MAX,
 };
 
diff --git a/drivers/power/supply/qcom/qg-soc.c b/drivers/power/supply/qcom/qg-soc.c
index 660f6f1..c4d5043 100644
--- a/drivers/power/supply/qcom/qg-soc.c
+++ b/drivers/power/supply/qcom/qg-soc.c
@@ -24,11 +24,15 @@
 
 #define DEFAULT_UPDATE_TIME_MS			64000
 #define SOC_SCALE_HYST_MS			2000
-#define SOC_SCALE_LOW_TEMP_THRESHOLD		100
 
 static int qg_delta_soc_interval_ms = 20000;
 module_param_named(
-	delta_soc_interval_ms, qg_delta_soc_interval_ms, int, 0600
+	soc_interval_ms, qg_delta_soc_interval_ms, int, 0600
+);
+
+static int qg_delta_soc_cold_interval_ms = 4000;
+module_param_named(
+	soc_cold_interval_ms, qg_delta_soc_cold_interval_ms, int, 0600
 );
 
 static void get_next_update_time(struct qpnp_qg *chip)
@@ -52,9 +56,11 @@
 	rc = qg_get_battery_temp(chip, &batt_temp);
 	if (rc < 0)
 		pr_err("Failed to read battery temperature rc=%d\n", rc);
+	else if (batt_temp < chip->dt.cold_temp_threshold)
+		min_delta_soc_interval_ms = qg_delta_soc_cold_interval_ms;
 
-	if (batt_temp < SOC_SCALE_LOW_TEMP_THRESHOLD)
-		min_delta_soc_interval_ms = min_delta_soc_interval_ms / 2;
+	if (!min_delta_soc_interval_ms)
+		min_delta_soc_interval_ms = 1000;	/* 1 second */
 
 	chip->next_wakeup_ms = (full_time_ms / (soc_points + 1))
 					- SOC_SCALE_HYST_MS;
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 5a9b8f6..440bf74 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -18,6 +18,7 @@
 #include <linux/of_platform.h>
 #include <linux/of_batterydata.h>
 #include <linux/platform_device.h>
+#include <linux/thermal.h>
 #include <linux/iio/consumer.h>
 #include <linux/qpnp/qpnp-revid.h>
 #include "fg-core.h"
@@ -5355,6 +5356,29 @@
 	dev_set_drvdata(chip->dev, NULL);
 }
 
+static int fg_tz_get_temp(void *data, int *temperature)
+{
+	struct fg_chip *chip = (struct fg_chip *)data;
+	int rc, batt_temp = 0;
+
+	if (!temperature)
+		return -EINVAL;
+
+	rc = fg_get_battery_temp(chip, &batt_temp);
+	if (rc < 0) {
+		pr_err("Error in getting batt_temp\n");
+		return rc;
+	}
+
+	/* Convert deciDegC to milliDegC */
+	*temperature = batt_temp * 100;
+	return 0;
+}
+
+static struct thermal_zone_of_device_ops fg_gen3_tz_ops = {
+	.get_temp = fg_tz_get_temp,
+};
+
 static int fg_gen3_probe(struct platform_device *pdev)
 {
 	struct fg_chip *chip;
@@ -5537,6 +5561,15 @@
 			pr_err("Error in configuring ESR filter rc:%d\n", rc);
 	}
 
+	chip->tz_dev = thermal_zone_of_sensor_register(chip->dev, 0, chip,
+							&fg_gen3_tz_ops);
+	if (IS_ERR_OR_NULL(chip->tz_dev)) {
+		rc = PTR_ERR(chip->tz_dev);
+		chip->tz_dev = NULL;
+		dev_err(chip->dev, "thermal_zone_of_sensor_register() failed rc:%d\n",
+			rc);
+	}
+
 	device_init_wakeup(chip->dev, true);
 	schedule_delayed_work(&chip->profile_load_work, 0);
 
@@ -5601,6 +5634,8 @@
 {
 	struct fg_chip *chip = dev_get_drvdata(&pdev->dev);
 
+	if (chip->tz_dev)
+		thermal_zone_of_sensor_unregister(chip->dev, chip->tz_dev);
 	fg_cleanup(chip);
 	return 0;
 }
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index 3f05a53..f7a6b7a 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -64,40 +64,61 @@
 	return false;
 }
 
-static int qg_read_ocv(struct qpnp_qg *chip, u32 *ocv_uv, u8 type)
+static int qg_read_ocv(struct qpnp_qg *chip, u32 *ocv_uv, u32 *ocv_raw, u8 type)
 {
 	int rc, addr;
 	u64 temp = 0;
+	char ocv_name[20];
 
 	switch (type) {
-	case GOOD_OCV:
+	case S3_GOOD_OCV:
 		addr = QG_S3_GOOD_OCV_V_DATA0_REG;
+		strlcpy(ocv_name, "S3_GOOD_OCV", 20);
 		break;
-	case PON_OCV:
+	case S7_PON_OCV:
 		addr = QG_S7_PON_OCV_V_DATA0_REG;
+		strlcpy(ocv_name, "S7_PON_OCV", 20);
+		break;
+	case S3_LAST_OCV:
+		addr = QG_LAST_S3_SLEEP_V_DATA0_REG;
+		strlcpy(ocv_name, "S3_LAST_OCV", 20);
+		break;
+	case SDAM_PON_OCV:
+		addr = QG_SDAM_PON_OCV_OFFSET;
+		strlcpy(ocv_name, "SDAM_PON_OCV", 20);
 		break;
 	default:
 		pr_err("Invalid OCV type %d\n", type);
 		return -EINVAL;
 	}
 
-	rc = qg_read(chip, chip->qg_base + addr, (u8 *)&temp, 2);
-	if (rc < 0) {
-		pr_err("Failed to read ocv, rc=%d\n", rc);
-		return rc;
+	if (type == SDAM_PON_OCV) {
+		rc = qg_sdam_read(SDAM_PON_OCV_UV, ocv_raw);
+		if (rc < 0) {
+			pr_err("Failed to read SDAM PON OCV rc=%d\n", rc);
+			return rc;
+		}
+	} else {
+		rc = qg_read(chip, chip->qg_base + addr, (u8 *)ocv_raw, 2);
+		if (rc < 0) {
+			pr_err("Failed to read ocv, rc=%d\n", rc);
+			return rc;
+		}
 	}
 
+	temp = *ocv_raw;
 	*ocv_uv = V_RAW_TO_UV(temp);
 
-	pr_debug("%s: OCV=%duV\n",
-		type == GOOD_OCV ? "GOOD_OCV" : "PON_OCV", *ocv_uv);
+	pr_debug("%s: OCV_RAW=%x OCV=%duV\n", ocv_name, *ocv_raw, *ocv_uv);
 
 	return rc;
 }
 
+#define DEFAULT_S3_FIFO_LENGTH		3
 static int qg_update_fifo_length(struct qpnp_qg *chip, u8 length)
 {
 	int rc;
+	u8 s3_entry_fifo_length = 0;
 
 	if (!length || length > 8) {
 		pr_err("Invalid FIFO length %d\n", length);
@@ -109,6 +130,21 @@
 	if (rc < 0)
 		pr_err("Failed to write S2 FIFO length, rc=%d\n", rc);
 
+	/* update the S3 FIFO length, when S2 length is updated */
+	if (length > 3)
+		s3_entry_fifo_length = (chip->dt.s3_entry_fifo_length > 0) ?
+			chip->dt.s3_entry_fifo_length : DEFAULT_S3_FIFO_LENGTH;
+	else	/* Use S3 length as 1 for any S2 length <= 3 */
+		s3_entry_fifo_length = 1;
+
+	rc = qg_masked_write(chip,
+			chip->qg_base + QG_S3_SLEEP_OCV_IBAT_CTL1_REG,
+			SLEEP_IBAT_QUALIFIED_LENGTH_MASK,
+			s3_entry_fifo_length - 1);
+	if (rc < 0)
+		pr_err("Failed to write S3-entry fifo-length, rc=%d\n",
+						rc);
+
 	return rc;
 }
 
@@ -276,6 +312,12 @@
 		fifo_v = v_fifo[i] | (v_fifo[i + 1] << 8);
 		fifo_i = i_fifo[i] | (i_fifo[i + 1] << 8);
 
+		if (fifo_v == FIFO_V_RESET_VAL || fifo_i == FIFO_I_RESET_VAL) {
+			pr_err("Invalid FIFO data V_RAW=%x I_RAW=%x - FIFO rejected\n",
+						fifo_v, fifo_i);
+			return -EINVAL;
+		}
+
 		temp = sign_extend32(fifo_i, 15);
 
 		chip->kdata.fifo[j].v = V_RAW_TO_UV(fifo_v);
@@ -387,8 +429,19 @@
 #define VBAT_LOW_HYST_UV		50000 /* 50mV */
 static int qg_vbat_low_wa(struct qpnp_qg *chip)
 {
-	int rc, i;
-	u32 vbat_low_uv = chip->dt.vbatt_low_mv * 1000 + VBAT_LOW_HYST_UV;
+	int rc, i, temp = 0;
+	u32 vbat_low_uv = 0;
+
+	rc = qg_get_battery_temp(chip, &temp);
+	if (rc < 0) {
+		pr_err("Failed to read batt_temp rc=%d\n", rc);
+		temp = 250;
+	}
+
+	vbat_low_uv = 1000 * ((temp < chip->dt.cold_temp_threshold) ?
+				chip->dt.vbatt_low_cold_mv :
+				chip->dt.vbatt_low_mv);
+	vbat_low_uv += VBAT_LOW_HYST_UV;
 
 	if (!(chip->wa_flags & QG_VBAT_LOW_WA) || !chip->vbat_low)
 		return 0;
@@ -434,6 +487,73 @@
 	return rc;
 }
 
+static int qg_vbat_thresholds_config(struct qpnp_qg *chip)
+{
+	int rc, temp = 0, vbat_mv;
+	u8 reg;
+
+	rc = qg_get_battery_temp(chip, &temp);
+	if (rc < 0) {
+		pr_err("Failed to read batt_temp rc=%d\n", rc);
+		return rc;
+	}
+
+	vbat_mv = (temp < chip->dt.cold_temp_threshold) ?
+			chip->dt.vbatt_empty_cold_mv :
+			chip->dt.vbatt_empty_mv;
+
+	rc = qg_read(chip, chip->qg_base + QG_VBAT_EMPTY_THRESHOLD_REG,
+					&reg, 1);
+	if (rc < 0) {
+		pr_err("Failed to read vbat-empty, rc=%d\n", rc);
+		return rc;
+	}
+
+	if (vbat_mv == (reg * 50))	/* No change */
+		goto config_vbat_low;
+
+	reg = vbat_mv / 50;
+	rc = qg_write(chip, chip->qg_base + QG_VBAT_EMPTY_THRESHOLD_REG,
+					&reg, 1);
+	if (rc < 0) {
+		pr_err("Failed to write vbat-empty, rc=%d\n", rc);
+		return rc;
+	}
+
+	qg_dbg(chip, QG_DEBUG_STATUS,
+		"VBAT EMPTY threshold updated to %dmV temp=%d\n",
+						vbat_mv, temp);
+
+config_vbat_low:
+	vbat_mv = (temp < chip->dt.cold_temp_threshold) ?
+			chip->dt.vbatt_low_cold_mv :
+			chip->dt.vbatt_low_mv;
+
+	rc = qg_read(chip, chip->qg_base + QG_VBAT_LOW_THRESHOLD_REG,
+					&reg, 1);
+	if (rc < 0) {
+		pr_err("Failed to read vbat-low, rc=%d\n", rc);
+		return rc;
+	}
+
+	if (vbat_mv == (reg * 50))	/* No change */
+		return 0;
+
+	reg = vbat_mv / 50;
+	rc = qg_write(chip, chip->qg_base + QG_VBAT_LOW_THRESHOLD_REG,
+					&reg, 1);
+	if (rc < 0) {
+		pr_err("Failed to write vbat-low, rc=%d\n", rc);
+		return rc;
+	}
+
+	qg_dbg(chip, QG_DEBUG_STATUS,
+		"VBAT LOW threshold updated to %dmV temp=%d\n",
+						vbat_mv, temp);
+
+	return rc;
+}
+
 #define MIN_FIFO_FULL_TIME_MS			12000
 static int process_rt_fifo_data(struct qpnp_qg *chip,
 				bool vbat_low, bool update_smb)
@@ -584,6 +704,10 @@
 		goto done;
 	}
 
+	rc = qg_vbat_thresholds_config(chip);
+	if (rc < 0)
+		pr_err("Failed to apply VBAT EMPTY config rc=%d\n", rc);
+
 	rc = qg_vbat_low_wa(chip);
 	if (rc < 0) {
 		pr_err("Failed to apply VBAT LOW WA, rc=%d\n", rc);
@@ -669,7 +793,7 @@
 {
 	int rc;
 	u8 status = 0;
-	u32 ocv_uv;
+	u32 ocv_uv = 0, ocv_raw = 0;
 	struct qpnp_qg *chip = data;
 
 	qg_dbg(chip, QG_DEBUG_IRQ, "IRQ triggered\n");
@@ -685,7 +809,7 @@
 	if (!(status & GOOD_OCV_BIT))
 		goto done;
 
-	rc = qg_read_ocv(chip, &ocv_uv, GOOD_OCV);
+	rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, S3_GOOD_OCV);
 	if (rc < 0) {
 		pr_err("Failed to read good_ocv, rc=%d\n", rc);
 		goto done;
@@ -1030,9 +1154,6 @@
 	union power_supply_propval prop = {0, };
 	int rc, recharge_soc, health;
 
-	vote(chip->good_ocv_irq_disable_votable,
-		QG_INIT_STATE_IRQ_DISABLE, !chip->charge_done, 0);
-
 	if (!chip->dt.hold_soc_while_full)
 		goto out;
 
@@ -1059,12 +1180,26 @@
 			chip->charge_full = true;
 			qg_dbg(chip, QG_DEBUG_STATUS, "Setting charge_full (0->1) @ msoc=%d\n",
 					chip->msoc);
-		} else {
+		} else if (health != POWER_SUPPLY_HEALTH_GOOD) {
+			/* terminated in JEITA */
 			qg_dbg(chip, QG_DEBUG_STATUS, "Terminated charging @ msoc=%d\n",
 					chip->msoc);
 		}
 	} else if ((!chip->charge_done || chip->msoc < recharge_soc)
 				&& chip->charge_full) {
+
+		if (chip->wa_flags & QG_RECHARGE_SOC_WA) {
+			/* Force recharge */
+			prop.intval = 0;
+			rc = power_supply_set_property(chip->batt_psy,
+				POWER_SUPPLY_PROP_RECHARGE_SOC, &prop);
+			if (rc < 0)
+				pr_err("Failed to force recharge rc=%d\n", rc);
+			else
+				qg_dbg(chip, QG_DEBUG_STATUS,
+					"Forced recharge\n");
+		}
+
 		/*
 		 * If recharge or discharge has started and
 		 * if linearize soc dtsi property defined
@@ -1528,11 +1663,11 @@
 
 static int qg_determine_pon_soc(struct qpnp_qg *chip)
 {
-	u8 status = 0, ocv_type = 0;
 	int rc = 0, batt_temp = 0;
-	bool use_pon_ocv = true, use_shutdown_ocv = false;
+	bool use_pon_ocv = true;
 	unsigned long rtc_sec = 0;
-	u32 ocv_uv = 0, soc = 0, shutdown[SDAM_MAX] = {0};
+	u32 ocv_uv = 0, ocv_raw = 0, soc = 0, shutdown[SDAM_MAX] = {0};
+	char ocv_type[20] = "NONE";
 
 	if (!chip->profile_loaded) {
 		qg_dbg(chip, QG_DEBUG_PON, "No Profile, skipping PON soc\n");
@@ -1566,9 +1701,9 @@
 			chip->dt.ignore_shutdown_soc_secs,
 			(rtc_sec - shutdown[SDAM_TIME_SEC]))) {
 		use_pon_ocv = false;
-		use_shutdown_ocv = true;
 		ocv_uv = shutdown[SDAM_OCV_UV];
 		soc = shutdown[SDAM_SOC];
+		strlcpy(ocv_type, "SHUTDOWN_SOC", 20);
 		qg_dbg(chip, QG_DEBUG_PON, "Using SHUTDOWN_SOC @ PON\n");
 	}
 
@@ -1580,24 +1715,31 @@
 			goto done;
 		}
 
-		rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status, 1);
-		if (rc < 0) {
-			pr_err("Failed to read status2 register rc=%d\n", rc);
+		/*
+		 * Read S3_LAST_OCV, if S3_LAST_OCV is invalid,
+		 * read the SDAM_PON_OCV
+		 * if SDAM is not-set, use S7_PON_OCV.
+		 */
+		strlcpy(ocv_type, "S3_LAST_SOC", 20);
+		rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, S3_LAST_OCV);
+		if (rc < 0)
 			goto done;
-		}
 
-		if (status & GOOD_OCV_BIT)
-			ocv_type = GOOD_OCV;
-		else
-			ocv_type = PON_OCV;
+		if (ocv_raw == FIFO_V_RESET_VAL) {
+			/* S3_LAST_OCV is invalid */
+			strlcpy(ocv_type, "SDAM_PON_SOC", 20);
+			rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, SDAM_PON_OCV);
+			if (rc < 0)
+				goto done;
 
-		qg_dbg(chip, QG_DEBUG_PON, "Using %s @ PON\n",
-				ocv_type == GOOD_OCV ? "GOOD_OCV" : "PON_OCV");
-
-		rc = qg_read_ocv(chip, &ocv_uv, ocv_type);
-		if (rc < 0) {
-			pr_err("Failed to read ocv rc=%d\n", rc);
-			goto done;
+			if (!ocv_uv) {
+				/* SDAM_PON_OCV is not set */
+				strlcpy(ocv_type, "S7_PON_SOC", 20);
+				rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw,
+							S7_PON_OCV);
+				if (rc < 0)
+					goto done;
+			}
 		}
 
 		rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false);
@@ -1608,7 +1750,7 @@
 	}
 done:
 	if (rc < 0) {
-		pr_err("Failed to get SOC @ PON, rc=%d\n", rc);
+		pr_err("Failed to get %s @ PON, rc=%d\n", ocv_type, rc);
 		return rc;
 	}
 
@@ -1629,9 +1771,9 @@
 	if (rc < 0)
 		pr_err("Failed to update sdam params rc=%d\n", rc);
 
-	pr_info("use_pon_ocv=%d use_good_ocv=%d use_shutdown_ocv=%d ocv_uv=%duV soc=%d\n",
-			use_pon_ocv, !!(status & GOOD_OCV_BIT),
-			use_shutdown_ocv, ocv_uv, chip->msoc);
+	pr_info("using %s @ PON ocv_uv=%duV soc=%d\n",
+			ocv_type, ocv_uv, chip->msoc);
+
 	return 0;
 }
 
@@ -1639,6 +1781,7 @@
 {
 	switch (chip->pmic_rev_id->pmic_subtype) {
 	case PMI632_SUBTYPE:
+		chip->wa_flags |= QG_RECHARGE_SOC_WA;
 		if (chip->pmic_rev_id->rev4 == PMI632_V1P0_REV4)
 			chip->wa_flags |= QG_VBAT_LOW_WA;
 		break;
@@ -1811,31 +1954,25 @@
 		}
 	}
 
-	/* vbat low */
+	/* vbat based configs */
 	if (chip->dt.vbatt_low_mv < 0)
 		chip->dt.vbatt_low_mv = 0;
 	else if (chip->dt.vbatt_low_mv > 12750)
 		chip->dt.vbatt_low_mv = 12750;
 
-	reg = chip->dt.vbatt_low_mv / 50;
-	rc = qg_write(chip, chip->qg_base + QG_VBAT_LOW_THRESHOLD_REG,
-					&reg, 1);
-	if (rc < 0) {
-		pr_err("Failed to write vbat-low, rc=%d\n", rc);
-		return rc;
-	}
-
-	/* vbat empty */
 	if (chip->dt.vbatt_empty_mv < 0)
 		chip->dt.vbatt_empty_mv = 0;
 	else if (chip->dt.vbatt_empty_mv > 12750)
 		chip->dt.vbatt_empty_mv = 12750;
 
-	reg = chip->dt.vbatt_empty_mv / 50;
-	rc = qg_write(chip, chip->qg_base + QG_VBAT_EMPTY_THRESHOLD_REG,
-					&reg, 1);
+	if (chip->dt.vbatt_empty_cold_mv < 0)
+		chip->dt.vbatt_empty_cold_mv = 0;
+	else if (chip->dt.vbatt_empty_cold_mv > 12750)
+		chip->dt.vbatt_empty_cold_mv = 12750;
+
+	rc = qg_vbat_thresholds_config(chip);
 	if (rc < 0) {
-		pr_err("Failed to write vbat-empty, rc=%d\n", rc);
+		pr_err("Failed to configure VBAT empty/low rc=%d\n", rc);
 		return rc;
 	}
 
@@ -1933,8 +2070,10 @@
 }
 
 #define DEFAULT_VBATT_EMPTY_MV		3200
+#define DEFAULT_VBATT_EMPTY_COLD_MV	3000
 #define DEFAULT_VBATT_CUTOFF_MV		3400
 #define DEFAULT_VBATT_LOW_MV		3500
+#define DEFAULT_VBATT_LOW_COLD_MV	3800
 #define DEFAULT_ITERM_MA		100
 #define DEFAULT_S2_FIFO_LENGTH		5
 #define DEFAULT_S2_VBAT_LOW_LENGTH	2
@@ -1942,6 +2081,7 @@
 #define DEFAULT_S2_ACC_INTVL_MS		100
 #define DEFAULT_DELTA_SOC		1
 #define DEFAULT_SHUTDOWN_SOC_SECS	360
+#define DEFAULT_COLD_TEMP_THRESHOLD	0
 static int qg_parse_dt(struct qpnp_qg *chip)
 {
 	int rc = 0;
@@ -2061,7 +2201,7 @@
 	else
 		chip->dt.s3_entry_ibat_ua = temp;
 
-	rc = of_property_read_u32(node, "qcom,s3-entry-ibat-ua", &temp);
+	rc = of_property_read_u32(node, "qcom,s3-exit-ibat-ua", &temp);
 	if (rc < 0)
 		chip->dt.s3_exit_ibat_ua = -EINVAL;
 	else
@@ -2074,12 +2214,30 @@
 	else
 		chip->dt.vbatt_empty_mv = temp;
 
+	rc = of_property_read_u32(node, "qcom,vbatt-empty-cold-mv", &temp);
+	if (rc < 0)
+		chip->dt.vbatt_empty_cold_mv = DEFAULT_VBATT_EMPTY_COLD_MV;
+	else
+		chip->dt.vbatt_empty_cold_mv = temp;
+
+	rc = of_property_read_u32(node, "qcom,cold-temp-threshold", &temp);
+	if (rc < 0)
+		chip->dt.cold_temp_threshold = DEFAULT_COLD_TEMP_THRESHOLD;
+	else
+		chip->dt.cold_temp_threshold = temp;
+
 	rc = of_property_read_u32(node, "qcom,vbatt-low-mv", &temp);
 	if (rc < 0)
 		chip->dt.vbatt_low_mv = DEFAULT_VBATT_LOW_MV;
 	else
 		chip->dt.vbatt_low_mv = temp;
 
+	rc = of_property_read_u32(node, "qcom,vbatt-low-cold-mv", &temp);
+	if (rc < 0)
+		chip->dt.vbatt_low_cold_mv = DEFAULT_VBATT_LOW_COLD_MV;
+	else
+		chip->dt.vbatt_low_cold_mv = temp;
+
 	rc = of_property_read_u32(node, "qcom,vbatt-cutoff-mv", &temp);
 	if (rc < 0)
 		chip->dt.vbatt_cutoff_mv = DEFAULT_VBATT_CUTOFF_MV;
@@ -2134,6 +2292,10 @@
 	if (!chip->profile_loaded)
 		return 0;
 
+	/* disable GOOD_OCV IRQ in sleep */
+	vote(chip->good_ocv_irq_disable_votable,
+			QG_INIT_STATE_IRQ_DISABLE, true, 0);
+
 	chip->suspend_data = false;
 
 	/* ignore any suspend processing if we are charging */
@@ -2198,13 +2360,17 @@
 static int process_resume(struct qpnp_qg *chip)
 {
 	u8 status2 = 0, rt_status = 0;
-	u32 ocv_uv = 0;
+	u32 ocv_uv = 0, ocv_raw = 0;
 	int rc, batt_temp = 0;
 
 	/* skip if profile is not loaded */
 	if (!chip->profile_loaded)
 		return 0;
 
+	/* enable GOOD_OCV IRQ when awake */
+	vote(chip->good_ocv_irq_disable_votable,
+			QG_INIT_STATE_IRQ_DISABLE, false, 0);
+
 	rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status2, 1);
 	if (rc < 0) {
 		pr_err("Failed to read status2 register, rc=%d\n", rc);
@@ -2212,7 +2378,7 @@
 	}
 
 	if (status2 & GOOD_OCV_BIT) {
-		rc = qg_read_ocv(chip, &ocv_uv, GOOD_OCV);
+		rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, S3_GOOD_OCV);
 		if (rc < 0) {
 			pr_err("Failed to read good_ocv, rc=%d\n", rc);
 			return rc;
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index ccc0d5d..5df241f 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -1891,7 +1891,8 @@
 	switch (pmic_rev_id->pmic_subtype) {
 	case PMI8998_SUBTYPE:
 		chip->chg.smb_version = PMI8998_SUBTYPE;
-		chip->chg.wa_flags |= BOOST_BACK_WA | QC_AUTH_INTERRUPT_WA_BIT;
+		chip->chg.wa_flags |= BOOST_BACK_WA | QC_AUTH_INTERRUPT_WA_BIT
+				| TYPEC_PBS_WA_BIT;
 		if (pmic_rev_id->rev4 == PMI8998_V1P1_REV4) /* PMI rev 1.1 */
 			chg->wa_flags |= QC_CHARGER_DETECTION_WA_BIT;
 		if (pmic_rev_id->rev4 == PMI8998_V2P0_REV4) /* PMI rev 2.0 */
@@ -1906,7 +1907,8 @@
 		break;
 	case PM660_SUBTYPE:
 		chip->chg.smb_version = PM660_SUBTYPE;
-		chip->chg.wa_flags |= BOOST_BACK_WA | OTG_WA;
+		chip->chg.wa_flags |= BOOST_BACK_WA | OTG_WA | OV_IRQ_WA_BIT
+				| TYPEC_PBS_WA_BIT;
 		chg->param.freq_buck = pm660_params.freq_buck;
 		chg->param.freq_boost = pm660_params.freq_boost;
 		chg->chg_freq.freq_5V		= 650;
@@ -2119,6 +2121,7 @@
 	[SWITCH_POWER_OK_IRQ] = {
 		.name		= "switcher-power-ok",
 		.handler	= smblib_handle_switcher_power_ok,
+		.wake		= true,
 		.storm_data	= {true, 1000, 8},
 	},
 };
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index 20dd78e..7a3a4dc 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -949,6 +949,7 @@
  *************************/
 static enum power_supply_property smb5_batt_props[] = {
 	POWER_SUPPLY_PROP_INPUT_SUSPEND,
+	POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED,
 	POWER_SUPPLY_PROP_STATUS,
 	POWER_SUPPLY_PROP_HEALTH,
 	POWER_SUPPLY_PROP_PRESENT,
@@ -995,6 +996,10 @@
 	case POWER_SUPPLY_PROP_INPUT_SUSPEND:
 		rc = smblib_get_prop_input_suspend(chg, val);
 		break;
+	case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
+		val->intval = !get_client_vote(chg->chg_disable_votable,
+					      USER_VOTER);
+		break;
 	case POWER_SUPPLY_PROP_CHARGE_TYPE:
 		rc = smblib_get_prop_batt_charge_type(chg, val);
 		break;
@@ -1093,6 +1098,9 @@
 	case POWER_SUPPLY_PROP_INPUT_SUSPEND:
 		rc = smblib_set_prop_input_suspend(chg, val);
 		break;
+	case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
+		vote(chg->chg_disable_votable, USER_VOTER, !val->intval, 0);
+		break;
 	case POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT:
 		rc = smblib_set_prop_system_temp_level(chg, val);
 		break;
@@ -1147,6 +1155,17 @@
 		chg->die_health = val->intval;
 		power_supply_changed(chg->batt_psy);
 		break;
+	case POWER_SUPPLY_PROP_RECHARGE_SOC:
+		if (chg->smb_version == PMI632_SUBTYPE) {
+			/* toggle charging to force recharge */
+			vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER,
+					true, 0);
+			/* charge disable delay */
+			msleep(50);
+			vote(chg->chg_disable_votable, FORCE_RECHARGE_VOTER,
+					false, 0);
+		}
+		break;
 	default:
 		rc = -EINVAL;
 	}
@@ -1169,6 +1188,7 @@
 	case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
 	case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
 	case POWER_SUPPLY_PROP_DIE_HEALTH:
+	case POWER_SUPPLY_PROP_BATTERY_CHARGING_ENABLED:
 		return 1;
 	default:
 		break;
diff --git a/drivers/power/supply/qcom/qpnp-smbcharger.c b/drivers/power/supply/qcom/qpnp-smbcharger.c
index 403b670..c4d10b0 100644
--- a/drivers/power/supply/qcom/qpnp-smbcharger.c
+++ b/drivers/power/supply/qcom/qpnp-smbcharger.c
@@ -176,6 +176,7 @@
 	int				n_vbat_samples;
 
 	/* status variables */
+	int				max_pulse_allowed;
 	int				wake_reasons;
 	int				previous_soc;
 	int				usb_online;
@@ -352,6 +353,7 @@
 #define WEAK_CHARGER_ICL_VOTER	"WEAK_CHARGER_ICL_VOTER"
 #define SW_AICL_ICL_VOTER	"SW_AICL_ICL_VOTER"
 #define CHG_SUSPEND_WORKAROUND_ICL_VOTER "CHG_SUSPEND_WORKAROUND_ICL_VOTER"
+#define SHUTDOWN_WORKAROUND_ICL_VOTER "SHUTDOWN_WORKAROUND_ICL_VOTER"
 
 /* USB SUSPEND VOTERS */
 /* userspace has suspended charging altogether */
@@ -1061,6 +1063,33 @@
 	return ua;
 }
 
+#define DEFAULT_BATT_RESISTANCE_ID	0
+static int get_prop_batt_resistance_id(struct smbchg_chip *chip)
+{
+	int rbatt, rc;
+
+	rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_RESISTANCE_ID,
+			&rbatt);
+	if (rc) {
+		pr_smb(PR_STATUS, "Couldn't get resistance id rc = %d\n", rc);
+		rbatt = DEFAULT_BATT_RESISTANCE_ID;
+	}
+	return rbatt;
+}
+
+#define DEFAULT_BATT_FULL_CHG_CAPACITY	0
+static int get_prop_batt_full_charge(struct smbchg_chip *chip)
+{
+	int bfc, rc;
+
+	rc = get_property_from_fg(chip, POWER_SUPPLY_PROP_CHARGE_FULL, &bfc);
+	if (rc) {
+		pr_smb(PR_STATUS, "Couldn't get charge_full rc = %d\n", rc);
+		bfc = DEFAULT_BATT_FULL_CHG_CAPACITY;
+	}
+	return bfc;
+}
+
 #define DEFAULT_BATT_VOLTAGE_NOW	0
 static int get_prop_batt_voltage_now(struct smbchg_chip *chip)
 {
@@ -1876,6 +1905,7 @@
 		return 0;
 	}
 
+	fg_current_now = abs(fg_current_now) / 1000;
 	icl_ma = max(chip->iterm_ma + ESR_PULSE_CURRENT_DELTA_MA,
 				fg_current_now - ESR_PULSE_CURRENT_DELTA_MA);
 	rc = vote(chip->fcc_votable, ESR_PULSE_FCC_VOTER, en, icl_ma);
@@ -4013,11 +4043,11 @@
 		reg = CHG_LED_OFF << CHG_LED_SHIFT;
 	} else {
 		if (blinking == 1)
-			reg = LED_BLINKING_PATTERN1 << CHG_LED_SHIFT;
-		else if (blinking == 2)
 			reg = LED_BLINKING_PATTERN2 << CHG_LED_SHIFT;
-		else
+		else if (blinking == 2)
 			reg = LED_BLINKING_PATTERN1 << CHG_LED_SHIFT;
+		else
+			reg = LED_BLINKING_PATTERN2 << CHG_LED_SHIFT;
 	}
 
 	rc = smbchg_sec_masked_write(chip,
@@ -4410,6 +4440,20 @@
 	if (type == POWER_SUPPLY_TYPE_UNKNOWN)
 		chip->usb_supply_type = type;
 
+	/*
+	 * Update TYPE property to DCP for HVDCP/HVDCP3 charger types
+	 * so that they can be recongized as AC chargers by healthd.
+	 * Don't report UNKNOWN charger type to prevent healthd missing
+	 * detecting this power_supply status change.
+	 */
+	if (chip->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP_3
+			|| chip->usb_supply_type == POWER_SUPPLY_TYPE_USB_HVDCP)
+		chip->usb_psy_d.type = POWER_SUPPLY_TYPE_USB_DCP;
+	else if (chip->usb_supply_type == POWER_SUPPLY_TYPE_UNKNOWN)
+		chip->usb_psy_d.type = POWER_SUPPLY_TYPE_USB;
+	else
+		chip->usb_psy_d.type = chip->usb_supply_type;
+
 	if (!chip->skip_usb_notification)
 		power_supply_changed(chip->usb_psy);
 
@@ -4602,6 +4646,8 @@
 	/* Clear typec current status */
 	if (chip->typec_psy)
 		chip->typec_current_ma = 0;
+	/* cancel/wait for hvdcp pending work if any */
+	cancel_delayed_work_sync(&chip->hvdcp_det_work);
 	smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN);
 	extcon_set_cable_state_(chip->extcon, EXTCON_USB, chip->usb_present);
 	if (chip->dpdm_reg)
@@ -5226,6 +5272,15 @@
 	 */
 	chip->parallel.enabled_once = false;
 
+	/* Enable AICL */
+	pr_smb(PR_MISC, "Enable AICL\n");
+	rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG,
+			AICL_EN_BIT, AICL_EN_BIT);
+	if (rc < 0) {
+		pr_err("Couldn't enable AICL rc=%d\n", rc);
+		goto out;
+	}
+
 	/* fake an insertion */
 	pr_smb(PR_MISC, "Faking Insertion\n");
 	rc = fake_insertion_removal(chip, true);
@@ -5235,15 +5290,6 @@
 	}
 	chip->hvdcp_3_det_ignore_uv = false;
 
-	/* Enable AICL */
-	pr_smb(PR_MISC, "Enable AICL\n");
-	rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG,
-			AICL_EN_BIT, 0);
-	if (rc < 0) {
-		pr_err("Couldn't enable AICL rc=%d\n", rc);
-		return rc;
-	}
-
 out:
 	/*
 	 * There are many QC 2.0 chargers that collapse before the aicl deglitch
@@ -5276,49 +5322,63 @@
 #define APSD_RERUN		BIT(0)
 static int rerun_apsd(struct smbchg_chip *chip)
 {
-	int rc;
+	int rc = 0;
 
-	reinit_completion(&chip->src_det_raised);
-	reinit_completion(&chip->usbin_uv_lowered);
-	reinit_completion(&chip->src_det_lowered);
-	reinit_completion(&chip->usbin_uv_raised);
+	chip->hvdcp_3_det_ignore_uv = true;
 
-	/* re-run APSD */
-	rc = smbchg_masked_write(chip, chip->usb_chgpth_base + USB_CMD_APSD,
-					APSD_RERUN, APSD_RERUN);
-	if (rc) {
-		pr_err("Couldn't re-run APSD rc=%d\n", rc);
-		return rc;
+	if (chip->schg_version == QPNP_SCHG_LITE) {
+		pr_smb(PR_STATUS, "Re-running APSD\n");
+		reinit_completion(&chip->src_det_raised);
+		reinit_completion(&chip->usbin_uv_lowered);
+		reinit_completion(&chip->src_det_lowered);
+		reinit_completion(&chip->usbin_uv_raised);
+
+		/* re-run APSD */
+		rc = smbchg_masked_write(chip,
+				chip->usb_chgpth_base + USB_CMD_APSD,
+				APSD_RERUN, APSD_RERUN);
+		if (rc) {
+			pr_err("Couldn't re-run APSD rc=%d\n", rc);
+			goto out;
+		}
+
+		pr_smb(PR_MISC, "Waiting on rising usbin uv\n");
+		rc = wait_for_usbin_uv(chip, true);
+		if (rc < 0) {
+			pr_err("wait for usbin uv failed rc = %d\n", rc);
+			goto out;
+		}
+
+		pr_smb(PR_MISC, "Waiting on falling src det\n");
+		rc = wait_for_src_detect(chip, false);
+		if (rc < 0) {
+			pr_err("wait for src detect failed rc = %d\n", rc);
+			goto out;
+		}
+
+		pr_smb(PR_MISC, "Waiting on falling usbin uv\n");
+		rc = wait_for_usbin_uv(chip, false);
+		if (rc < 0) {
+			pr_err("wait for usbin uv failed rc = %d\n", rc);
+			goto out;
+		}
+
+		pr_smb(PR_MISC, "Waiting on rising src det\n");
+		rc = wait_for_src_detect(chip, true);
+		if (rc < 0) {
+			pr_err("wait for src detect failed rc = %d\n", rc);
+			goto out;
+		}
+	} else {
+		pr_smb(PR_STATUS, "Faking Removal\n");
+		rc = fake_insertion_removal(chip, false);
+		msleep(500);
+		pr_smb(PR_STATUS, "Faking Insertion\n");
+		rc = fake_insertion_removal(chip, true);
 	}
 
-	pr_smb(PR_MISC, "Waiting on rising usbin uv\n");
-	rc = wait_for_usbin_uv(chip, true);
-	if (rc < 0) {
-		pr_err("wait for usbin uv failed rc = %d\n", rc);
-		return rc;
-	}
-
-	pr_smb(PR_MISC, "Waiting on falling src det\n");
-	rc = wait_for_src_detect(chip, false);
-	if (rc < 0) {
-		pr_err("wait for src detect failed rc = %d\n", rc);
-		return rc;
-	}
-
-	pr_smb(PR_MISC, "Waiting on falling usbin uv\n");
-	rc = wait_for_usbin_uv(chip, false);
-	if (rc < 0) {
-		pr_err("wait for usbin uv failed rc = %d\n", rc);
-		return rc;
-	}
-
-	pr_smb(PR_MISC, "Waiting on rising src det\n");
-	rc = wait_for_src_detect(chip, true);
-	if (rc < 0) {
-		pr_err("wait for src detect failed rc = %d\n", rc);
-		return rc;
-	}
-
+out:
+	chip->hvdcp_3_det_ignore_uv = false;
 	return rc;
 }
 
@@ -5395,8 +5455,6 @@
 	smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG,
 			AICL_EN_BIT, 0);
 
-	chip->hvdcp_3_det_ignore_uv = true;
-
 	/* re-run APSD */
 	rc = rerun_apsd(chip);
 	if (rc) {
@@ -5404,8 +5462,6 @@
 		goto out;
 	}
 
-	chip->hvdcp_3_det_ignore_uv = false;
-
 	pr_smb(PR_MISC, "Enable AICL\n");
 	smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USB_AICL_CFG,
 			AICL_EN_BIT, AICL_EN_BIT);
@@ -5434,6 +5490,10 @@
 out:
 	chip->hvdcp_3_det_ignore_uv = false;
 	restore_from_hvdcp_detection(chip);
+	if (!is_src_detect_high(chip)) {
+		pr_smb(PR_MISC, "HVDCP removed - force removal\n");
+		update_usb_status(chip, 0, true);
+	}
 	return rc;
 }
 
@@ -5453,6 +5513,10 @@
 	if (rc < 0)
 		pr_err("Couldn't retract HVDCP ICL vote rc=%d\n", rc);
 
+	if (!is_src_detect_high(chip)) {
+		pr_smb(PR_MISC, "HVDCP removed\n");
+		update_usb_status(chip, 0, 0);
+	}
 	smbchg_handle_hvdcp3_disable(chip);
 
 	return rc;
@@ -5631,6 +5695,9 @@
 		val->intval = chip->usb_online;
 		break;
 	case POWER_SUPPLY_PROP_TYPE:
+		val->intval = chip->usb_psy_d.type;
+		break;
+	case POWER_SUPPLY_PROP_REAL_TYPE:
 		val->intval = chip->usb_supply_type;
 		break;
 	case POWER_SUPPLY_PROP_HEALTH:
@@ -5688,6 +5755,7 @@
 	POWER_SUPPLY_PROP_ONLINE,
 	POWER_SUPPLY_PROP_CURRENT_MAX,
 	POWER_SUPPLY_PROP_TYPE,
+	POWER_SUPPLY_PROP_REAL_TYPE,
 	POWER_SUPPLY_PROP_HEALTH,
 };
 
@@ -5733,6 +5801,8 @@
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_TEMP,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_RESISTANCE_ID,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
 	POWER_SUPPLY_PROP_SAFETY_TIMER_ENABLE,
 	POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
 	POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
@@ -5744,6 +5814,7 @@
 	POWER_SUPPLY_PROP_RERUN_AICL,
 	POWER_SUPPLY_PROP_RESTRICTED_CHARGING,
 	POWER_SUPPLY_PROP_ALLOW_HVDCP3,
+	POWER_SUPPLY_PROP_MAX_PULSE_ALLOWED,
 };
 
 static int smbchg_battery_set_property(struct power_supply *psy,
@@ -5924,6 +5995,12 @@
 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 		val->intval = get_prop_batt_voltage_now(chip);
 		break;
+	case POWER_SUPPLY_PROP_RESISTANCE_ID:
+		val->intval = get_prop_batt_resistance_id(chip);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		val->intval = get_prop_batt_full_charge(chip);
+		break;
 	case POWER_SUPPLY_PROP_TEMP:
 		val->intval = get_prop_batt_temp(chip);
 		break;
@@ -5954,6 +6031,9 @@
 	case POWER_SUPPLY_PROP_ALLOW_HVDCP3:
 		val->intval = chip->allow_hvdcp3_detection;
 		break;
+	case POWER_SUPPLY_PROP_MAX_PULSE_ALLOWED:
+		val->intval = chip->max_pulse_allowed;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -6609,7 +6689,6 @@
 	} else {
 		usbid_change_handler(0, chip);
 	}
-	src_detect_handler(0, chip);
 
 	chip->usb_present = is_usb_present(chip);
 	chip->dc_present = is_dc_present(chip);
@@ -7306,6 +7385,7 @@
 
 #define DEFAULT_VLED_MAX_UV		3500000
 #define DEFAULT_FCC_MA			2000
+#define DEFAULT_NUM_OF_PULSE_ALLOWED	20
 static int smb_parse_dt(struct smbchg_chip *chip)
 {
 	int rc = 0, ocp_thresh = -EINVAL;
@@ -7364,6 +7444,11 @@
 	if (chip->parallel.min_current_thr_ma != -EINVAL
 			&& chip->parallel.min_9v_current_thr_ma != -EINVAL)
 		chip->parallel.avail = true;
+
+	OF_PROP_READ(chip, chip->max_pulse_allowed,
+				"max-pulse-allowed", rc, 1);
+	if (chip->max_pulse_allowed == -EINVAL)
+		chip->max_pulse_allowed = DEFAULT_NUM_OF_PULSE_ALLOWED;
 	/*
 	 * use the dt values if they exist, otherwise do not touch the params
 	 */
@@ -7968,20 +8053,18 @@
 			pr_err("Couldn't vote for 300mA for suspend wa, going ahead rc=%d\n",
 					rc);
 
-		pr_smb(PR_STATUS, "Faking Removal\n");
-		fake_insertion_removal(chip, false);
-		msleep(500);
-		pr_smb(PR_STATUS, "Faking Insertion\n");
-		fake_insertion_removal(chip, true);
+		rc = rerun_apsd(chip);
+		if (rc)
+			pr_err("APSD rerun failed rc=%d\n", rc);
 
 		read_usb_type(chip, &usb_type_name, &usb_supply_type);
 		if (usb_supply_type != POWER_SUPPLY_TYPE_USB_DCP) {
 			msleep(500);
-			pr_smb(PR_STATUS, "Fake Removal again as type!=DCP\n");
-			fake_insertion_removal(chip, false);
-			msleep(500);
-			pr_smb(PR_STATUS, "Fake Insert again as type!=DCP\n");
-			fake_insertion_removal(chip, true);
+			pr_smb(PR_STATUS, "Rerun APSD as type !=DCP\n");
+
+			rc = rerun_apsd(chip);
+			if (rc)
+				pr_err("APSD rerun failed rc=%d\n", rc);
 		}
 
 		rc = vote(chip->usb_icl_votable,
@@ -7989,6 +8072,14 @@
 		if (rc < 0)
 			pr_err("Couldn't vote for 0 for suspend wa, going ahead rc=%d\n",
 					rc);
+
+		/* Schedule work for HVDCP detection */
+		if (!chip->hvdcp_not_supported) {
+			cancel_delayed_work_sync(&chip->hvdcp_det_work);
+			smbchg_stay_awake(chip, PM_DETECT_HVDCP);
+			schedule_delayed_work(&chip->hvdcp_det_work,
+					msecs_to_jiffies(HVDCP_NOTIFY_MS));
+		}
 	}
 }
 
@@ -8385,6 +8476,12 @@
 	if (!is_hvdcp_present(chip))
 		return;
 
+	pr_smb(PR_MISC, "Reducing to 500mA\n");
+	rc = vote(chip->usb_icl_votable, SHUTDOWN_WORKAROUND_ICL_VOTER, true,
+			500);
+	if (rc < 0)
+		pr_err("Couldn't vote 500mA ICL\n");
+
 	pr_smb(PR_MISC, "Disable Parallel\n");
 	mutex_lock(&chip->parallel.lock);
 	smbchg_parallel_en = 0;
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 7e1aa5d..39005f6 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -689,6 +689,7 @@
 	vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0);
 	vote(chg->usb_icl_votable, USBIN_USBIN_BOOST_VOTER, false, 0);
 	vote(chg->usb_icl_votable, HVDCP2_ICL_VOTER, false, 0);
+	vote(chg->hvdcp_hw_inov_dis_votable, OV_VOTER, false, 0);
 
 	cancel_delayed_work_sync(&chg->hvdcp_detect_work);
 
@@ -1120,19 +1121,21 @@
 		return -EINVAL;
 	}
 
-	if (power_role == UFP_EN_CMD_BIT) {
-		/* disable PBS workaround when forcing sink mode */
-		rc = smblib_write(chg, TM_IO_DTEST4_SEL, 0x0);
-		if (rc < 0) {
-			smblib_err(chg, "Couldn't write to TM_IO_DTEST4_SEL rc=%d\n",
-				rc);
-		}
-	} else {
-		/* restore it back to 0xA5 */
-		rc = smblib_write(chg, TM_IO_DTEST4_SEL, 0xA5);
-		if (rc < 0) {
-			smblib_err(chg, "Couldn't write to TM_IO_DTEST4_SEL rc=%d\n",
-				rc);
+	if (chg->wa_flags & TYPEC_PBS_WA_BIT) {
+		if (power_role == UFP_EN_CMD_BIT) {
+			/* disable PBS workaround when forcing sink mode */
+			rc = smblib_write(chg, TM_IO_DTEST4_SEL, 0x0);
+			if (rc < 0) {
+				smblib_err(chg, "Couldn't write to TM_IO_DTEST4_SEL rc=%d\n",
+					rc);
+			}
+		} else {
+			/* restore it back to 0xA5 */
+			rc = smblib_write(chg, TM_IO_DTEST4_SEL, 0xA5);
+			if (rc < 0) {
+				smblib_err(chg, "Couldn't write to TM_IO_DTEST4_SEL rc=%d\n",
+					rc);
+			}
 		}
 	}
 
@@ -3638,6 +3641,33 @@
 		   rising ? "rising" : "falling");
 }
 
+#define MICRO_10P3V	10300000
+static void smblib_check_ov_condition(struct smb_charger *chg)
+{
+	union power_supply_propval pval = {0, };
+	int rc;
+
+	if (chg->wa_flags & OV_IRQ_WA_BIT) {
+		rc = power_supply_get_property(chg->usb_psy,
+			POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't get current voltage, rc=%d\n",
+				rc);
+			return;
+		}
+
+		if (pval.intval > MICRO_10P3V) {
+			smblib_err(chg, "USBIN OV detected\n");
+			vote(chg->hvdcp_hw_inov_dis_votable, OV_VOTER, true,
+				0);
+			pval.intval = POWER_SUPPLY_DP_DM_FORCE_5V;
+			rc = power_supply_set_property(chg->batt_psy,
+				POWER_SUPPLY_PROP_DP_DM, &pval);
+			return;
+		}
+	}
+}
+
 #define QC3_PULSES_FOR_6V	5
 #define QC3_PULSES_FOR_9V	20
 #define QC3_PULSES_FOR_12V	35
@@ -3647,6 +3677,7 @@
 	u8 stat;
 	int pulses;
 
+	smblib_check_ov_condition(chg);
 	power_supply_changed(chg->usb_main_psy);
 	if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP) {
 		rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat);
@@ -4198,6 +4229,7 @@
 	/* reset hvdcp voters */
 	vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0);
 	vote(chg->hvdcp_disable_votable_indirect, PD_INACTIVE_VOTER, true, 0);
+	vote(chg->hvdcp_hw_inov_dis_votable, OV_VOTER, false, 0);
 
 	/* reset power delivery voters */
 	vote(chg->pd_allowed_votable, PD_VOTER, false, 0);
@@ -4279,10 +4311,13 @@
 	if (rc < 0)
 		smblib_err(chg, "Couldn't enable HW cc_out rc=%d\n", rc);
 
-	/* restore crude sensor */
-	rc = smblib_write(chg, TM_IO_DTEST4_SEL, 0xA5);
-	if (rc < 0)
-		smblib_err(chg, "Couldn't restore crude sensor rc=%d\n", rc);
+	/* restore crude sensor if PM660/PMI8998 */
+	if (chg->wa_flags & TYPEC_PBS_WA_BIT) {
+		rc = smblib_write(chg, TM_IO_DTEST4_SEL, 0xA5);
+		if (rc < 0)
+			smblib_err(chg, "Couldn't restore crude sensor rc=%d\n",
+				rc);
+	}
 
 	mutex_lock(&chg->vconn_oc_lock);
 	if (!chg->vconn_en)
@@ -5228,7 +5263,7 @@
 
 	switch (chg->mode) {
 	case PARALLEL_MASTER:
-		rc = qcom_batt_init();
+		rc = qcom_batt_init(chg->smb_version);
 		if (rc < 0) {
 			smblib_err(chg, "Couldn't init qcom_batt_init rc=%d\n",
 				rc);
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index b9d1992..dc8cbc7 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -70,6 +70,7 @@
 #define WBC_VOTER			"WBC_VOTER"
 #define MOISTURE_VOTER			"MOISTURE_VOTER"
 #define HVDCP2_ICL_VOTER		"HVDCP2_ICL_VOTER"
+#define OV_VOTER			"OV_VOTER"
 
 #define VCONN_MAX_ATTEMPTS	3
 #define OTG_MAX_ATTEMPTS	3
@@ -88,6 +89,8 @@
 	TYPEC_CC2_REMOVAL_WA_BIT	= BIT(2),
 	QC_AUTH_INTERRUPT_WA_BIT	= BIT(3),
 	OTG_WA				= BIT(4),
+	OV_IRQ_WA_BIT			= BIT(5),
+	TYPEC_PBS_WA_BIT		= BIT(6),
 };
 
 enum smb_irq_index {
diff --git a/drivers/power/supply/qcom/smb1355-charger.c b/drivers/power/supply/qcom/smb1355-charger.c
index ffbced6..327ae63 100644
--- a/drivers/power/supply/qcom/smb1355-charger.c
+++ b/drivers/power/supply/qcom/smb1355-charger.c
@@ -28,6 +28,7 @@
 #include <linux/power_supply.h>
 #include <linux/workqueue.h>
 #include <linux/pmic-voter.h>
+#include <linux/string.h>
 
 /* SMB1355 registers, different than mentioned in smb-reg.h */
 
@@ -120,6 +121,7 @@
 
 #define MISC_CUST_SDCDC_ILIMIT_CFG_REG		(MISC_BASE + 0xA1)
 #define LS_VALLEY_THRESH_PCT_BIT		BIT(3)
+#define PCL_LIMIT_MASK				GENMASK(1, 0)
 
 #define SNARL_BARK_BITE_WD_CFG_REG		(MISC_BASE + 0x53)
 #define BITE_WDOG_DISABLE_CHARGING_CFG_BIT	BIT(7)
@@ -1029,6 +1031,16 @@
 		return rc;
 	}
 
+	/* For SMB1354, set PCL to 8.6 A */
+	if (!strcmp(chip->name, "smb1354")) {
+		rc = smb1355_masked_write(chip, MISC_CUST_SDCDC_ILIMIT_CFG_REG,
+				PCL_LIMIT_MASK, PCL_LIMIT_MASK);
+		if (rc < 0) {
+			pr_err("Couldn't set PCL limit to 8.6A rc=%d\n", rc);
+			return rc;
+		}
+	}
+
 	rc = smb1355_tskin_sensor_config(chip);
 	if (rc < 0) {
 		pr_err("Couldn't configure tskin regs rc=%d\n", rc);
diff --git a/drivers/power/supply/qcom/smb1390-charger.c b/drivers/power/supply/qcom/smb1390-charger.c
index 636265b..55a1f45 100644
--- a/drivers/power/supply/qcom/smb1390-charger.c
+++ b/drivers/power/supply/qcom/smb1390-charger.c
@@ -67,6 +67,15 @@
 #define CORE_FTRIM_ILIM_REG		0x1030
 #define CFG_ILIM_MASK			GENMASK(4, 0)
 
+#define CORE_FTRIM_LVL_REG		0x1033
+#define CFG_WIN_HI_MASK			GENMASK(3, 2)
+#define WIN_OV_LVL_1000MV		0x08
+
+#define CORE_FTRIM_MISC_REG		0x1034
+#define TR_WIN_1P5X_BIT			BIT(0)
+#define WINDOW_DETECTION_DELTA_X1P0	0
+#define WINDOW_DETECTION_DELTA_X1P5	1
+
 #define CP_VOTER	"CP_VOTER"
 #define USER_VOTER	"USER_VOTER"
 #define ILIM_VOTER	"ILIM_VOTER"
@@ -591,11 +600,30 @@
 
 static int smb1390_init_hw(struct smb1390 *chip)
 {
+	int rc;
+
 	/*
 	 * charge pump is initially disabled; this indirectly votes to allow
 	 * traditional parallel charging if present
 	 */
 	vote(chip->disable_votable, USER_VOTER, true, 0);
+
+	/*
+	 * Improve ILIM accuracy:
+	 *  - Configure window (Vin - 2Vout) OV level to 1000mV
+	 *  - Configure VOUT tracking value to 1.0
+	 */
+	rc = smb1390_masked_write(chip, CORE_FTRIM_LVL_REG,
+			CFG_WIN_HI_MASK, WIN_OV_LVL_1000MV);
+	if (rc < 0)
+		return rc;
+
+	rc = smb1390_masked_write(chip, CORE_FTRIM_MISC_REG,
+			TR_WIN_1P5X_BIT, WINDOW_DETECTION_DELTA_X1P0);
+	if (rc < 0)
+		return rc;
+
+
 	return 0;
 }
 
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index 5df7c9e..3152669 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -18,6 +18,7 @@
 #include <linux/qpnp/qpnp-revid.h>
 #include <linux/irq.h>
 #include <linux/pmic-voter.h>
+#include <linux/of_batterydata.h>
 #include "smb5-lib.h"
 #include "smb5-reg.h"
 #include "battery.h"
@@ -592,6 +593,8 @@
 			chg->bms_psy = psy;
 		if (ev == PSY_EVENT_PROP_CHANGED)
 			schedule_work(&chg->bms_update_work);
+		if (!chg->jeita_configured)
+			schedule_work(&chg->jeita_update_work);
 	}
 
 	if (!chg->pl.psy && !strcmp(psy->desc->name, "parallel")) {
@@ -651,6 +654,7 @@
 	return 0;
 }
 
+#define USBIN_100MA	100000
 static void smblib_uusb_removal(struct smb_charger *chg)
 {
 	int rc;
@@ -694,6 +698,15 @@
 	chg->pulse_cnt = 0;
 	chg->uusb_apsd_rerun_done = false;
 
+	/* write back the default FLOAT charger configuration */
+	rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
+				(u8)FLOAT_OPTIONS_MASK, chg->float_cfg);
+	if (rc < 0)
+		smblib_err(chg, "Couldn't write float charger options rc=%d\n",
+			rc);
+
+	/* leave the ICL configured to 100mA for next insertion */
+	vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER, true, USBIN_100MA);
 	/* clear USB ICL vote for USB_PSY_VOTER */
 	rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
 	if (rc < 0)
@@ -759,7 +772,6 @@
 }
 
 #define USBIN_25MA	25000
-#define USBIN_100MA	100000
 #define USBIN_150MA	150000
 #define USBIN_500MA	500000
 #define USBIN_900MA	900000
@@ -881,6 +893,9 @@
 		goto out;
 	}
 
+	/* Re-run AICL */
+	if (chg->real_charger_type != POWER_SUPPLY_TYPE_USB)
+		rc = smblib_rerun_aicl(chg);
 out:
 	return rc;
 }
@@ -2109,12 +2124,20 @@
 			 * Valid FLOAT charger, report the current based
 			 * of Rp
 			 */
-			typec_mode = smblib_get_prop_typec_mode(chg);
-			rp_ua = get_rp_based_dcp_current(chg, typec_mode);
-			rc = vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER,
-								true, rp_ua);
-			if (rc < 0)
-				return rc;
+			if (chg->connector_type ==
+					POWER_SUPPLY_CONNECTOR_TYPEC) {
+				typec_mode = smblib_get_prop_typec_mode(chg);
+				rp_ua = get_rp_based_dcp_current(chg,
+								typec_mode);
+				rc = vote(chg->usb_icl_votable,
+						DYNAMIC_RP_VOTER, true, rp_ua);
+				if (rc < 0) {
+					pr_err("Couldn't vote ICL DYNAMIC_RP_VOTER rc=%d\n",
+							rc);
+					return rc;
+				}
+			}
+			/* No specific handling required for micro-USB */
 		} else {
 			/*
 			 * FLOAT charger detected as SDP by USB driver,
@@ -2123,20 +2146,30 @@
 			 */
 			chg->real_charger_type = POWER_SUPPLY_TYPE_USB;
 			rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
-						true, usb_current);
-			if (rc < 0)
+							true, usb_current);
+			if (rc < 0) {
+				pr_err("Couldn't vote ICL USB_PSY_VOTER rc=%d\n",
+						rc);
 				return rc;
-			rc = vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER,
-							false, 0);
-			if (rc < 0)
-				return rc;
+			}
 		}
 	} else {
 		rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
 					true, usb_current);
+		if (rc < 0) {
+			pr_err("Couldn't vote ICL USB_PSY_VOTER rc=%d\n", rc);
+			return rc;
+		}
+
 	}
 
-	return rc;
+	rc = vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER, false, 0);
+	if (rc < 0) {
+		pr_err("Couldn't unvote ICL DEFAULT_100MA_VOTER rc=%d\n", rc);
+		return rc;
+	}
+
+	return 0;
 }
 
 int smblib_set_prop_sdp_current_max(struct smb_charger *chg,
@@ -2273,9 +2306,6 @@
 			smblib_err(chg, "Couldn't vote for USB ICL rc=%d\n",
 									rc);
 
-		/* since PD was found the cable must be non-legacy */
-		vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0);
-
 		/* clear USB ICL vote for DCP_VOTER */
 		rc = vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
 		if (rc < 0)
@@ -2883,6 +2913,7 @@
 	switch (apsd_result->bit) {
 	case SDP_CHARGER_BIT:
 	case CDP_CHARGER_BIT:
+	case FLOAT_CHARGER_BIT:
 		/* if not DCP then no hvdcp timeout happens. Enable pd here */
 		vote(chg->pd_disallowed_votable_indirect, APSD_VOTER,
 				false, 0);
@@ -2891,12 +2922,13 @@
 			smblib_notify_device_mode(chg, true);
 		break;
 	case OCP_CHARGER_BIT:
-	case FLOAT_CHARGER_BIT:
+		vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER, false, 0);
 		/* if not DCP then no hvdcp timeout happens, Enable pd here. */
 		vote(chg->pd_disallowed_votable_indirect, APSD_VOTER,
 				false, 0);
 		break;
 	case DCP_CHARGER_BIT:
+		vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER, false, 0);
 		break;
 	default:
 		break;
@@ -3008,7 +3040,7 @@
 	cancel_delayed_work_sync(&chg->pl_enable_work);
 
 	/* reset input current limit voters */
-	vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 100000);
+	vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER, true, USBIN_100MA);
 	vote(chg->usb_icl_votable, PD_VOTER, false, 0);
 	vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
 	vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
@@ -3016,6 +3048,7 @@
 	vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0);
 	vote(chg->usb_icl_votable, OTG_VOTER, false, 0);
 	vote(chg->usb_icl_votable, CTM_VOTER, false, 0);
+	vote(chg->usb_icl_votable, DYNAMIC_RP_VOTER, false, 0);
 
 	/* reset power delivery voters */
 	vote(chg->pd_allowed_votable, PD_VOTER, false, 0);
@@ -3146,8 +3179,8 @@
 	 * pre-existing valid vote.
 	 */
 	if (apsd->pst == POWER_SUPPLY_TYPE_USB_FLOAT &&
-		get_client_vote(chg->usb_icl_votable,
-			LEGACY_UNKNOWN_VOTER) <= 100000)
+		(get_client_vote(chg->usb_icl_votable, DEFAULT_100MA_VOTER)
+					<= USBIN_100MA))
 		return;
 
 	/*
@@ -3159,7 +3192,7 @@
 						chg->typec_mode, typec_mode);
 
 	rp_ua = get_rp_based_dcp_current(chg, typec_mode);
-	vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, rp_ua);
+	vote(chg->usb_icl_votable, DYNAMIC_RP_VOTER, true, rp_ua);
 }
 
 static void smblib_handle_typec_cc_state_change(struct smb_charger *chg)
@@ -3497,6 +3530,100 @@
 	vote(chg->awake_votable, PL_DELAY_VOTER, false, 0);
 }
 
+#define JEITA_SOFT			0
+#define JEITA_HARD			1
+static int smblib_update_jeita(struct smb_charger *chg, u32 *thresholds,
+								int type)
+{
+	int rc;
+	u16 temp, base;
+
+	base = CHGR_JEITA_THRESHOLD_BASE_REG(type);
+
+	temp = thresholds[1] & 0xFFFF;
+	temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8);
+	rc = smblib_batch_write(chg, base, (u8 *)&temp, 2);
+	if (rc < 0) {
+		smblib_err(chg,
+			"Couldn't configure Jeita %s hot threshold rc=%d\n",
+			(type == JEITA_SOFT) ? "Soft" : "Hard", rc);
+		return rc;
+	}
+
+	temp = thresholds[0] & 0xFFFF;
+	temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8);
+	rc = smblib_batch_write(chg, base + 2, (u8 *)&temp, 2);
+	if (rc < 0) {
+		smblib_err(chg,
+			"Couldn't configure Jeita %s cold threshold rc=%d\n",
+			(type == JEITA_SOFT) ? "Soft" : "Hard", rc);
+		return rc;
+	}
+
+	smblib_dbg(chg, PR_MISC, "%s Jeita threshold configured\n",
+				(type == JEITA_SOFT) ? "Soft" : "Hard");
+
+	return 0;
+}
+
+static void jeita_update_work(struct work_struct *work)
+{
+	struct smb_charger *chg = container_of(work, struct smb_charger,
+						jeita_update_work);
+	struct device_node *node = chg->dev->of_node;
+	struct device_node *batt_node, *pnode;
+	union power_supply_propval val;
+	int rc;
+	u32 jeita_thresholds[2];
+
+	batt_node = of_find_node_by_name(node, "qcom,battery-data");
+	if (!batt_node) {
+		smblib_err(chg, "Batterydata not available\n");
+		goto out;
+	}
+
+	rc = power_supply_get_property(chg->bms_psy,
+			POWER_SUPPLY_PROP_RESISTANCE_ID, &val);
+	if (rc < 0) {
+		smblib_err(chg, "Failed to get batt-id rc=%d\n", rc);
+		goto out;
+	}
+
+	pnode = of_batterydata_get_best_profile(batt_node,
+					val.intval / 1000, NULL);
+	if (IS_ERR(pnode)) {
+		rc = PTR_ERR(pnode);
+		smblib_err(chg, "Failed to detect valid battery profile %d\n",
+				rc);
+		goto out;
+	}
+
+	rc = of_property_read_u32_array(pnode, "qcom,jeita-hard-thresholds",
+				jeita_thresholds, 2);
+	if (!rc) {
+		rc = smblib_update_jeita(chg, jeita_thresholds, JEITA_HARD);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't configure Hard Jeita rc=%d\n",
+					rc);
+			goto out;
+		}
+	}
+
+	rc = of_property_read_u32_array(pnode, "qcom,jeita-soft-thresholds",
+				jeita_thresholds, 2);
+	if (!rc) {
+		rc = smblib_update_jeita(chg, jeita_thresholds, JEITA_SOFT);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't configure Soft Jeita rc=%d\n",
+					rc);
+			goto out;
+		}
+	}
+
+out:
+	chg->jeita_configured = true;
+}
+
 static int smblib_create_votables(struct smb_charger *chg)
 {
 	int rc = 0;
@@ -3621,6 +3748,7 @@
 	mutex_init(&chg->otg_oc_lock);
 	INIT_WORK(&chg->bms_update_work, bms_update_work);
 	INIT_WORK(&chg->pl_update_work, pl_update_work);
+	INIT_WORK(&chg->jeita_update_work, jeita_update_work);
 	INIT_DELAYED_WORK(&chg->clear_hdc_work, clear_hdc_work);
 	INIT_DELAYED_WORK(&chg->icl_change_work, smblib_icl_change_work);
 	INIT_DELAYED_WORK(&chg->pl_enable_work, smblib_pl_enable_work);
@@ -3629,10 +3757,11 @@
 	chg->fake_capacity = -EINVAL;
 	chg->fake_input_current_limited = -EINVAL;
 	chg->fake_batt_status = -EINVAL;
+	chg->jeita_configured = false;
 
 	switch (chg->mode) {
 	case PARALLEL_MASTER:
-		rc = qcom_batt_init();
+		rc = qcom_batt_init(chg->smb_version);
 		if (rc < 0) {
 			smblib_err(chg, "Couldn't init qcom_batt_init rc=%d\n",
 				rc);
@@ -3686,6 +3815,7 @@
 	switch (chg->mode) {
 	case PARALLEL_MASTER:
 		cancel_work_sync(&chg->bms_update_work);
+		cancel_work_sync(&chg->jeita_update_work);
 		cancel_work_sync(&chg->pl_update_work);
 		cancel_delayed_work_sync(&chg->clear_hdc_work);
 		cancel_delayed_work_sync(&chg->icl_change_work);
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index 39cc921..668ce5f 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -56,7 +56,6 @@
 #define CTM_VOTER			"CTM_VOTER"
 #define SW_QC3_VOTER			"SW_QC3_VOTER"
 #define AICL_RERUN_VOTER		"AICL_RERUN_VOTER"
-#define LEGACY_UNKNOWN_VOTER		"LEGACY_UNKNOWN_VOTER"
 #define QNOVO_VOTER			"QNOVO_VOTER"
 #define BATT_PROFILE_VOTER		"BATT_PROFILE_VOTER"
 #define OTG_DELAY_VOTER			"OTG_DELAY_VOTER"
@@ -66,6 +65,9 @@
 #define PL_FCC_LOW_VOTER		"PL_FCC_LOW_VOTER"
 #define WBC_VOTER			"WBC_VOTER"
 #define HW_LIMIT_VOTER			"HW_LIMIT_VOTER"
+#define DYNAMIC_RP_VOTER		"DYNAMIC_RP_VOTER"
+#define DEFAULT_100MA_VOTER		"DEFAULT_100MA_VOTER"
+#define FORCE_RECHARGE_VOTER		"FORCE_RECHARGE_VOTER"
 
 #define BOOST_BACK_STORM_COUNT	3
 #define WEAK_CHG_STORM_COUNT	8
@@ -304,6 +306,7 @@
 	/* work */
 	struct work_struct	bms_update_work;
 	struct work_struct	pl_update_work;
+	struct work_struct	jeita_update_work;
 	struct delayed_work	ps_change_timeout_work;
 	struct delayed_work	clear_hdc_work;
 	struct delayed_work	icl_change_work;
@@ -347,6 +350,7 @@
 	bool			otg_present;
 	int			hw_max_icl_ua;
 	int			auto_recharge_soc;
+	bool			jeita_configured;
 
 	/* workaround flag */
 	u32			wa_flags;
diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h
index 3334f67..bb28423 100644
--- a/drivers/power/supply/qcom/smb5-reg.h
+++ b/drivers/power/supply/qcom/smb5-reg.h
@@ -101,6 +101,7 @@
 #define JEITA_CCCOMP_CFG_HOT_REG		(CHGR_BASE + 0x92)
 #define JEITA_CCCOMP_CFG_COLD_REG		(CHGR_BASE + 0x93)
 
+#define CHGR_JEITA_THRESHOLD_BASE_REG(i)	(CHGR_BASE + 0x94 + (i * 4))
 /********************************
  *  DCDC Peripheral Registers  *
  ********************************/
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 172ef82..17b808c 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -285,6 +285,7 @@
 		pwm->pwm = chip->base + i;
 		pwm->hwpwm = i;
 		pwm->state.polarity = polarity;
+		pwm->state.output_type = PWM_OUTPUT_FIXED;
 
 		if (chip->ops->get_state)
 			chip->ops->get_state(chip, pwm, &pwm->state);
@@ -498,6 +499,31 @@
 			pwm->state.polarity = state->polarity;
 		}
 
+		if (state->output_type != pwm->state.output_type) {
+			if (!pwm->chip->ops->set_output_type)
+				return -ENOTSUPP;
+
+			err = pwm->chip->ops->set_output_type(pwm->chip, pwm,
+						state->output_type);
+			if (err)
+				return err;
+
+			pwm->state.output_type = state->output_type;
+		}
+
+		if (state->output_pattern != pwm->state.output_pattern &&
+				state->output_pattern != NULL) {
+			if (!pwm->chip->ops->set_output_pattern)
+				return -ENOTSUPP;
+
+			err = pwm->chip->ops->set_output_pattern(pwm->chip,
+					pwm, state->output_pattern);
+			if (err)
+				return err;
+
+			pwm->state.output_pattern = state->output_pattern;
+		}
+
 		if (state->period != pwm->state.period ||
 		    state->duty_cycle != pwm->state.duty_cycle) {
 			err = pwm->chip->ops->config(pwm->chip, pwm,
diff --git a/drivers/pwm/pwm-qti-lpg.c b/drivers/pwm/pwm-qti-lpg.c
index 85a5ea0..31f5204 100644
--- a/drivers/pwm/pwm-qti-lpg.c
+++ b/drivers/pwm/pwm-qti-lpg.c
@@ -24,11 +24,16 @@
 #include <linux/platform_device.h>
 #include <linux/pwm.h>
 #include <linux/regmap.h>
+#include <linux/slab.h>
 #include <linux/types.h>
 
 #define REG_SIZE_PER_LPG	0x100
+#define LPG_BASE		"lpg-base"
+#define LUT_BASE		"lut-base"
 
+/* LPG module registers */
 #define REG_LPG_PERPH_SUBTYPE		0x05
+#define REG_LPG_PATTERN_CONFIG		0x40
 #define REG_LPG_PWM_SIZE_CLK		0x41
 #define REG_LPG_PWM_FREQ_PREDIV_CLK	0x42
 #define REG_LPG_PWM_TYPE_CONFIG		0x43
@@ -36,16 +41,29 @@
 #define REG_LPG_PWM_VALUE_MSB		0x45
 #define REG_LPG_ENABLE_CONTROL		0x46
 #define REG_LPG_PWM_SYNC		0x47
+#define REG_LPG_RAMP_STEP_DURATION_LSB	0x50
+#define REG_LPG_RAMP_STEP_DURATION_MSB	0x51
+#define REG_LPG_PAUSE_HI_MULTIPLIER	0x52
+#define REG_LPG_PAUSE_LO_MULTIPLIER	0x54
+#define REG_LPG_HI_INDEX		0x56
+#define REG_LPG_LO_INDEX		0x57
+
+/* REG_LPG_PATTERN_CONFIG */
+#define LPG_PATTERN_EN_PAUSE_LO		BIT(0)
+#define LPG_PATTERN_EN_PAUSE_HI		BIT(1)
+#define LPG_PATTERN_RAMP_TOGGLE		BIT(2)
+#define LPG_PATTERN_REPEAT		BIT(3)
+#define LPG_PATTERN_RAMP_LO_TO_HI	BIT(4)
 
 /* REG_LPG_PERPH_SUBTYPE */
 #define SUBTYPE_PWM			0x0b
 #define SUBTYPE_LPG_LITE		0x11
 
 /* REG_LPG_PWM_SIZE_CLK */
-#define LPG_PWM_SIZE_MASK_LPG		BIT(4)
-#define LPG_PWM_SIZE_MASK_PWM		BIT(2)
-#define LPG_PWM_SIZE_SHIFT_LPG		4
-#define LPG_PWM_SIZE_SHIFT_PWM		2
+#define LPG_PWM_SIZE_LPG_MASK		BIT(4)
+#define LPG_PWM_SIZE_PWM_MASK		BIT(2)
+#define LPG_PWM_SIZE_LPG_SHIFT		4
+#define LPG_PWM_SIZE_PWM_SHIFT		2
 #define LPG_PWM_CLK_FREQ_SEL_MASK	GENMASK(1, 0)
 
 /* REG_LPG_PWM_FREQ_PREDIV_CLK */
@@ -64,6 +82,7 @@
 
 /* REG_LPG_ENABLE_CONTROL */
 #define LPG_EN_LPG_OUT_BIT		BIT(7)
+#define LPG_EN_LPG_OUT_SHIFT		7
 #define LPG_PWM_SRC_SELECT_MASK		BIT(2)
 #define LPG_PWM_SRC_SELECT_SHIFT	2
 #define LPG_EN_RAMP_GEN_MASK		BIT(1)
@@ -77,9 +96,18 @@
 #define NUM_CLK_PREDIV			4
 #define NUM_PWM_EXP			8
 
-enum {
+#define LPG_HI_LO_IDX_MASK		GENMASK(5, 0)
+
+/* LUT module registers */
+#define REG_LPG_LUT_1_LSB		0x42
+#define REG_LPG_LUT_RAMP_CONTROL	0xc8
+
+#define LPG_LUT_VALUE_MSB_MASK		BIT(0)
+#define LPG_LUT_COUNT_MAX		47
+
+enum lpg_src {
 	LUT_PATTERN = 0,
-	PWM_OUTPUT,
+	PWM_VALUE,
 };
 
 static const int pwm_size[NUM_PWM_SIZE] = {6, 9};
@@ -87,6 +115,19 @@
 static const int clk_prediv[NUM_CLK_PREDIV] = {1, 3, 5, 6};
 static const int pwm_exponent[NUM_PWM_EXP] = {0, 1, 2, 3, 4, 5, 6, 7};
 
+struct lpg_ramp_config {
+	u16			step_ms;
+	u8			pause_hi_count;
+	u8			pause_lo_count;
+	u8			hi_idx;
+	u8			lo_idx;
+	bool			ramp_dir_low_to_hi;
+	bool			pattern_repeat;
+	bool			toggle;
+	u32			*pattern;
+	u32			pattern_length;
+};
+
 struct lpg_pwm_config {
 	u32	pwm_size;
 	u32	pwm_clk;
@@ -96,13 +137,23 @@
 	u32	best_period_ns;
 };
 
+struct qpnp_lpg_lut {
+	struct qpnp_lpg_chip	*chip;
+	struct mutex		lock;
+	u32			reg_base;
+	u32			*pattern; /* patterns in percentage */
+};
+
 struct qpnp_lpg_channel {
 	struct qpnp_lpg_chip		*chip;
 	struct lpg_pwm_config		pwm_config;
+	struct lpg_ramp_config		ramp_config;
 	u32				lpg_idx;
 	u32				reg_base;
+	u32				max_pattern_length;
 	u8				src_sel;
 	u8				subtype;
+	bool				lut_written;
 	int				current_period_ns;
 	int				current_duty_ns;
 };
@@ -112,6 +163,7 @@
 	struct regmap		*regmap;
 	struct device		*dev;
 	struct qpnp_lpg_channel	*lpgs;
+	struct qpnp_lpg_lut	*lut;
 	struct mutex		bus_lock;
 	u32			num_lpgs;
 };
@@ -163,6 +215,36 @@
 	return rc;
 }
 
+static int qpnp_lut_write(struct qpnp_lpg_lut *lut, u16 addr, u8 val)
+{
+	int rc;
+
+	mutex_lock(&lut->chip->bus_lock);
+	rc = regmap_write(lut->chip->regmap, lut->reg_base + addr, val);
+	if (rc < 0)
+		dev_err(lut->chip->dev, "Write addr 0x%x with value %d failed, rc=%d\n",
+				lut->reg_base + addr, val, rc);
+	mutex_unlock(&lut->chip->bus_lock);
+
+	return rc;
+}
+
+static int qpnp_lut_masked_write(struct qpnp_lpg_lut *lut,
+				u16 addr, u8 mask, u8 val)
+{
+	int rc;
+
+	mutex_lock(&lut->chip->bus_lock);
+	rc = regmap_update_bits(lut->chip->regmap, lut->reg_base + addr,
+							mask, val);
+	if (rc < 0)
+		dev_err(lut->chip->dev, "Update addr 0x%x to val 0x%x with mask 0x%x failed, rc=%d\n",
+				lut->reg_base + addr, val, mask, rc);
+	mutex_unlock(&lut->chip->bus_lock);
+
+	return rc;
+}
+
 static struct qpnp_lpg_channel *pwm_dev_to_qpnp_lpg(struct pwm_chip *pwm_chip,
 				struct pwm_device *pwm) {
 
@@ -227,11 +309,11 @@
 	/* pwm_clk_idx is 1 bit lower than the register value */
 	pwm_clk_idx += 1;
 	if (lpg->subtype == SUBTYPE_PWM) {
-		shift = LPG_PWM_SIZE_SHIFT_PWM;
-		mask = LPG_PWM_SIZE_MASK_PWM;
+		shift = LPG_PWM_SIZE_PWM_SHIFT;
+		mask = LPG_PWM_SIZE_PWM_MASK;
 	} else {
-		shift = LPG_PWM_SIZE_SHIFT_LPG;
-		mask = LPG_PWM_SIZE_MASK_LPG;
+		shift = LPG_PWM_SIZE_LPG_SHIFT;
+		mask = LPG_PWM_SIZE_LPG_MASK;
 	}
 
 	val = pwm_size_idx << shift | pwm_clk_idx;
@@ -252,6 +334,9 @@
 		return rc;
 	}
 
+	if (lpg->src_sel == LUT_PATTERN)
+		return 0;
+
 	val = lpg->pwm_config.pwm_value & LPG_PWM_VALUE_LSB_MASK;
 	rc = qpnp_lpg_write(lpg, REG_LPG_PWM_VALUE_LSB, val);
 	if (rc < 0) {
@@ -280,6 +365,145 @@
 	return rc;
 }
 
+static int qpnp_lpg_set_lut_pattern(struct qpnp_lpg_channel *lpg,
+		unsigned int *pattern, unsigned int length)
+{
+	struct qpnp_lpg_lut *lut = lpg->chip->lut;
+	int i, rc = 0;
+	u16 full_duty_value, pwm_values[LPG_LUT_COUNT_MAX + 1] = {0};
+	u8 lsb, msb, addr;
+
+	if (length > lpg->max_pattern_length) {
+		dev_err(lpg->chip->dev, "new pattern length (%d) larger than predefined (%d)\n",
+				length, lpg->max_pattern_length);
+		return -EINVAL;
+	}
+
+	/* Program LUT pattern */
+	mutex_lock(&lut->lock);
+	addr = REG_LPG_LUT_1_LSB + lpg->ramp_config.lo_idx * 2;
+	for (i = 0; i < length; i++) {
+		full_duty_value = 1 << lpg->pwm_config.pwm_size;
+		pwm_values[i] = pattern[i] * full_duty_value / 100;
+
+		if (unlikely(pwm_values[i] > full_duty_value)) {
+			dev_err(lpg->chip->dev, "PWM value %d exceed the max %d\n",
+					pwm_values[i], full_duty_value);
+			rc = -EINVAL;
+			goto unlock;
+		}
+
+		if (pwm_values[i] == full_duty_value)
+			pwm_values[i] = full_duty_value - 1;
+
+		lsb = pwm_values[i] & 0xff;
+		msb = pwm_values[i] >> 8;
+		rc = qpnp_lut_write(lut, addr++, lsb);
+		if (rc < 0) {
+			dev_err(lpg->chip->dev, "Write NO.%d LUT pattern LSB (%d) failed, rc=%d",
+					i, lsb, rc);
+			goto unlock;
+		}
+
+		rc = qpnp_lut_masked_write(lut, addr++,
+				LPG_LUT_VALUE_MSB_MASK, msb);
+		if (rc < 0) {
+			dev_err(lpg->chip->dev, "Write NO.%d LUT pattern MSB (%d) failed, rc=%d",
+					i, msb, rc);
+			goto unlock;
+		}
+	}
+	lpg->ramp_config.pattern_length = length;
+unlock:
+	mutex_unlock(&lut->lock);
+
+	return rc;
+}
+
+static int qpnp_lpg_set_ramp_config(struct qpnp_lpg_channel *lpg)
+{
+	struct lpg_ramp_config *ramp = &lpg->ramp_config;
+	u8 lsb, msb, addr, mask, val;
+	int rc = 0;
+
+	/* Set ramp step duration */
+	lsb = ramp->step_ms & 0xff;
+	msb = ramp->step_ms >> 8;
+	addr = REG_LPG_RAMP_STEP_DURATION_LSB;
+	rc = qpnp_lpg_write(lpg, addr, lsb);
+	if (rc < 0) {
+		dev_err(lpg->chip->dev, "Write RAMP_STEP_DURATION_LSB failed, rc=%d\n",
+					rc);
+		return rc;
+	}
+	rc = qpnp_lpg_write(lpg, addr + 1, msb);
+	if (rc < 0) {
+		dev_err(lpg->chip->dev, "Write RAMP_STEP_DURATION_MSB failed, rc=%d\n",
+					rc);
+		return rc;
+	}
+
+	/* Set hi_idx and lo_idx */
+	rc = qpnp_lpg_masked_write(lpg, REG_LPG_HI_INDEX,
+			LPG_HI_LO_IDX_MASK, ramp->hi_idx);
+	if (rc < 0) {
+		dev_err(lpg->chip->dev, "Write LPG_HI_IDX failed, rc=%d\n",
+					rc);
+		return rc;
+	}
+
+	rc = qpnp_lpg_masked_write(lpg, REG_LPG_LO_INDEX,
+			LPG_HI_LO_IDX_MASK, ramp->lo_idx);
+	if (rc < 0) {
+		dev_err(lpg->chip->dev, "Write LPG_LO_IDX failed, rc=%d\n",
+					rc);
+		return rc;
+	}
+
+	/* Set pause_hi/lo_count */
+	rc = qpnp_lpg_write(lpg, REG_LPG_PAUSE_HI_MULTIPLIER,
+					ramp->pause_hi_count);
+	if (rc < 0) {
+		dev_err(lpg->chip->dev, "Write LPG_PAUSE_HI_MULTIPLIER failed, rc=%d\n",
+					rc);
+		return rc;
+	}
+
+	rc = qpnp_lpg_write(lpg, REG_LPG_PAUSE_LO_MULTIPLIER,
+					ramp->pause_lo_count);
+	if (rc < 0) {
+		dev_err(lpg->chip->dev, "Write LPG_PAUSE_LO_MULTIPLIER failed, rc=%d\n",
+					rc);
+		return rc;
+	}
+
+	/* Set LPG_PATTERN_CONFIG */
+	addr = REG_LPG_PATTERN_CONFIG;
+	mask = LPG_PATTERN_EN_PAUSE_LO | LPG_PATTERN_EN_PAUSE_HI
+		| LPG_PATTERN_RAMP_TOGGLE | LPG_PATTERN_REPEAT
+		| LPG_PATTERN_RAMP_LO_TO_HI;
+	val = 0;
+	if (ramp->pause_lo_count != 0)
+		val |= LPG_PATTERN_EN_PAUSE_LO;
+	if (ramp->pause_hi_count != 0)
+		val |= LPG_PATTERN_EN_PAUSE_HI;
+	if (ramp->ramp_dir_low_to_hi)
+		val |= LPG_PATTERN_RAMP_LO_TO_HI;
+	if (ramp->pattern_repeat)
+		val |= LPG_PATTERN_REPEAT;
+	if (ramp->toggle)
+		val |= LPG_PATTERN_RAMP_TOGGLE;
+
+	rc = qpnp_lpg_masked_write(lpg, addr, mask, val);
+	if (rc < 0) {
+		dev_err(lpg->chip->dev, "Write LPG_PATTERN_CONFIG failed, rc=%d\n",
+					rc);
+		return rc;
+	}
+
+	return rc;
+}
+
 static void __qpnp_lpg_calc_pwm_period(int period_ns,
 			struct lpg_pwm_config *pwm_config)
 {
@@ -396,17 +620,202 @@
 		return -EINVAL;
 	}
 
-	if (period_ns != lpg->current_period_ns)
+	if (period_ns != lpg->current_period_ns) {
 		__qpnp_lpg_calc_pwm_period(period_ns, &lpg->pwm_config);
 
+		/* program LUT if PWM period is changed */
+		if (lpg->src_sel == LUT_PATTERN) {
+			rc = qpnp_lpg_set_lut_pattern(lpg,
+					lpg->ramp_config.pattern,
+					lpg->ramp_config.pattern_length);
+			if (rc < 0) {
+				dev_err(pwm_chip->dev, "set LUT pattern failed for LPG%d, rc=%d\n",
+						lpg->lpg_idx, rc);
+				return rc;
+			}
+			lpg->lut_written = true;
+		}
+	}
+
 	if (period_ns != lpg->current_period_ns ||
 			duty_ns != lpg->current_duty_ns)
 		__qpnp_lpg_calc_pwm_duty(period_ns, duty_ns, &lpg->pwm_config);
 
 	rc = qpnp_lpg_set_pwm_config(lpg);
-	if (rc < 0)
+	if (rc < 0) {
 		dev_err(pwm_chip->dev, "Config PWM failed for channel %d, rc=%d\n",
 						lpg->lpg_idx, rc);
+		return rc;
+	}
+
+	lpg->current_period_ns = period_ns;
+	lpg->current_duty_ns = duty_ns;
+
+	return rc;
+}
+
+static int qpnp_lpg_pwm_src_enable(struct qpnp_lpg_channel *lpg, bool en)
+{
+	struct qpnp_lpg_chip *chip = lpg->chip;
+	struct qpnp_lpg_lut *lut = chip->lut;
+	u8 mask, val;
+	int rc;
+
+	mask = LPG_PWM_SRC_SELECT_MASK | LPG_EN_LPG_OUT_BIT |
+					LPG_EN_RAMP_GEN_MASK;
+	val = lpg->src_sel << LPG_PWM_SRC_SELECT_SHIFT;
+
+	if (lpg->src_sel == LUT_PATTERN)
+		val |= 1 << LPG_EN_RAMP_GEN_SHIFT;
+
+	if (en)
+		val |= 1 << LPG_EN_LPG_OUT_SHIFT;
+
+	rc = qpnp_lpg_masked_write(lpg, REG_LPG_ENABLE_CONTROL, mask, val);
+	if (rc < 0) {
+		dev_err(chip->dev, "Write LPG_ENABLE_CONTROL failed, rc=%d\n",
+				rc);
+		return rc;
+	}
+
+	if (lpg->src_sel == LUT_PATTERN && en) {
+		mutex_lock(&lut->lock);
+		val = 1 << lpg->lpg_idx;
+		rc = qpnp_lut_write(lut, REG_LPG_LUT_RAMP_CONTROL, val);
+		if (rc < 0)
+			dev_err(chip->dev, "Write LPG_LUT_RAMP_CONTROL failed, rc=%d\n",
+					rc);
+		mutex_unlock(&lut->lock);
+	}
+
+	return rc;
+}
+
+static int qpnp_lpg_pwm_set_output_type(struct pwm_chip *pwm_chip,
+		struct pwm_device *pwm, enum pwm_output_type output_type)
+{
+	struct qpnp_lpg_channel *lpg;
+	enum lpg_src src_sel;
+	int rc;
+
+	lpg = pwm_dev_to_qpnp_lpg(pwm_chip, pwm);
+	if (lpg == NULL) {
+		dev_err(pwm_chip->dev, "lpg not found\n");
+		return -ENODEV;
+	}
+
+	if (lpg->chip->lut == NULL) {
+		pr_debug("lpg%d only support PWM mode\n", lpg->lpg_idx);
+		return 0;
+	}
+
+	src_sel = (output_type == PWM_OUTPUT_MODULATED) ?
+				LUT_PATTERN : PWM_VALUE;
+	if (src_sel == lpg->src_sel)
+		return 0;
+
+	if (src_sel == LUT_PATTERN) {
+		/* program LUT if it's never been programmed */
+		if (!lpg->lut_written) {
+			rc = qpnp_lpg_set_lut_pattern(lpg,
+					lpg->ramp_config.pattern,
+					lpg->ramp_config.pattern_length);
+			if (rc < 0) {
+				dev_err(pwm_chip->dev, "set LUT pattern failed for LPG%d, rc=%d\n",
+						lpg->lpg_idx, rc);
+				return rc;
+			}
+			lpg->lut_written = true;
+		}
+
+		rc = qpnp_lpg_set_ramp_config(lpg);
+		if (rc < 0) {
+			dev_err(pwm_chip->dev, "Config LPG%d ramping failed, rc=%d\n",
+					lpg->lpg_idx, rc);
+			return rc;
+		}
+	}
+
+	lpg->src_sel = src_sel;
+
+	if (pwm_is_enabled(pwm)) {
+		rc = qpnp_lpg_pwm_src_enable(lpg, true);
+		if (rc < 0) {
+			dev_err(pwm_chip->dev, "Enable PWM output failed for channel %d, rc=%d\n",
+					lpg->lpg_idx, rc);
+			return rc;
+		}
+	}
+
+	return 0;
+}
+
+static int qpnp_lpg_pwm_set_output_pattern(struct pwm_chip *pwm_chip,
+	struct pwm_device *pwm, struct pwm_output_pattern *output_pattern)
+{
+	struct qpnp_lpg_channel *lpg;
+	int rc = 0, i, period_ns, duty_ns;
+	u32 *percentages;
+
+	lpg = pwm_dev_to_qpnp_lpg(pwm_chip, pwm);
+	if (lpg == NULL) {
+		dev_err(pwm_chip->dev, "lpg not found\n");
+		return -ENODEV;
+	}
+
+	if (output_pattern->num_entries > lpg->max_pattern_length) {
+		dev_err(lpg->chip->dev, "pattern length %d shouldn't exceed %d\n",
+				output_pattern->num_entries,
+				lpg->max_pattern_length);
+		return -EINVAL;
+	}
+
+	percentages = kcalloc(output_pattern->num_entries,
+				sizeof(u32), GFP_KERNEL);
+	if (!percentages)
+		return -ENOMEM;
+
+	period_ns = pwm_get_period(pwm);
+	for (i = 0; i < output_pattern->num_entries; i++) {
+		duty_ns = output_pattern->duty_pattern[i];
+		if (duty_ns > period_ns) {
+			dev_err(lpg->chip->dev, "duty %dns is larger than period %dns\n",
+					duty_ns, period_ns);
+			goto err;
+		}
+		/* Translate the pattern in duty_ns to percentage */
+		if ((INT_MAX / duty_ns) < 100)
+			percentages[i] = duty_ns / (period_ns / 100);
+		else
+			percentages[i] = (duty_ns * 100) / period_ns;
+	}
+
+	rc = qpnp_lpg_set_lut_pattern(lpg, percentages,
+			output_pattern->num_entries);
+	if (rc < 0) {
+		dev_err(lpg->chip->dev, "Set LUT pattern failed for LPG%d, rc=%d\n",
+				lpg->lpg_idx, rc);
+		goto err;
+	}
+
+	lpg->lut_written = true;
+	memcpy(lpg->ramp_config.pattern, percentages,
+			output_pattern->num_entries);
+	lpg->ramp_config.hi_idx = lpg->ramp_config.lo_idx +
+				output_pattern->num_entries - 1;
+	if ((INT_MAX / period_ns) > output_pattern->cycles_per_duty)
+		lpg->ramp_config.step_ms = output_pattern->cycles_per_duty *
+			period_ns / NSEC_PER_MSEC;
+	else
+		lpg->ramp_config.step_ms = (period_ns / NSEC_PER_MSEC) *
+			output_pattern->cycles_per_duty;
+
+	rc = qpnp_lpg_set_ramp_config(lpg);
+	if (rc < 0)
+		dev_err(pwm_chip->dev, "Config LPG%d ramping failed, rc=%d\n",
+				lpg->lpg_idx, rc);
+err:
+	kfree(percentages);
 
 	return rc;
 }
@@ -416,7 +825,6 @@
 {
 	struct qpnp_lpg_channel *lpg;
 	int rc = 0;
-	u8 mask, val;
 
 	lpg = pwm_dev_to_qpnp_lpg(pwm_chip, pwm);
 	if (lpg == NULL) {
@@ -431,10 +839,7 @@
 		return rc;
 	}
 
-	mask = LPG_PWM_SRC_SELECT_MASK | LPG_EN_LPG_OUT_BIT;
-	val = lpg->src_sel << LPG_PWM_SRC_SELECT_SHIFT | LPG_EN_LPG_OUT_BIT;
-
-	rc = qpnp_lpg_masked_write(lpg, REG_LPG_ENABLE_CONTROL, mask, val);
+	rc = qpnp_lpg_pwm_src_enable(lpg, true);
 	if (rc < 0)
 		dev_err(pwm_chip->dev, "Enable PWM output failed for channel %d, rc=%d\n",
 						lpg->lpg_idx, rc);
@@ -447,7 +852,6 @@
 {
 	struct qpnp_lpg_channel *lpg;
 	int rc;
-	u8 mask, val;
 
 	lpg = pwm_dev_to_qpnp_lpg(pwm_chip, pwm);
 	if (lpg == NULL) {
@@ -455,10 +859,7 @@
 		return;
 	}
 
-	mask = LPG_PWM_SRC_SELECT_MASK | LPG_EN_LPG_OUT_BIT;
-	val = lpg->src_sel << LPG_PWM_SRC_SELECT_SHIFT;
-
-	rc = qpnp_lpg_masked_write(lpg, REG_LPG_ENABLE_CONTROL, mask, val);
+	rc = qpnp_lpg_pwm_src_enable(lpg, false);
 	if (rc < 0) {
 		dev_err(pwm_chip->dev, "Disable PWM output failed for channel %d, rc=%d\n",
 						lpg->lpg_idx, rc);
@@ -471,13 +872,32 @@
 							rc);
 }
 
+static int qpnp_lpg_pwm_output_types_supported(struct pwm_chip *pwm_chip,
+				struct pwm_device *pwm)
+{
+	enum pwm_output_type type = PWM_OUTPUT_FIXED;
+	struct qpnp_lpg_channel *lpg;
+
+	lpg = pwm_dev_to_qpnp_lpg(pwm_chip, pwm);
+	if (lpg == NULL) {
+		dev_err(pwm_chip->dev, "lpg not found\n");
+		return type;
+	}
+
+	if (lpg->chip->lut != NULL)
+		type |= PWM_OUTPUT_MODULATED;
+
+	return type;
+}
+
 #ifdef CONFIG_DEBUG_FS
 static void qpnp_lpg_pwm_dbg_show(struct pwm_chip *pwm_chip, struct seq_file *s)
 {
 	struct qpnp_lpg_channel *lpg;
 	struct lpg_pwm_config *cfg;
+	struct lpg_ramp_config *ramp;
 	struct pwm_device *pwm;
-	int i;
+	int i, j;
 
 	for (i = 0; i < pwm_chip->npwm; i++) {
 		pwm = &pwm_chip->pwms[i];
@@ -512,12 +932,39 @@
 		seq_printf(s, "     pwm_value = %d\n", cfg->pwm_value);
 		seq_printf(s, "  Requested period: %dns, best period = %dns\n",
 				pwm_get_period(pwm), cfg->best_period_ns);
+
+		ramp = &lpg->ramp_config;
+		if (pwm_get_output_type(pwm) == PWM_OUTPUT_MODULATED) {
+			seq_puts(s, "  ramping duty percentages:");
+			for (j = 0; j < ramp->pattern_length; j++)
+				seq_printf(s, " %d", ramp->pattern[j]);
+			seq_puts(s, "\n");
+			seq_printf(s, "  ramping time per step: %dms\n",
+					ramp->step_ms);
+			seq_printf(s, "  ramping low index: %d\n",
+					ramp->lo_idx);
+			seq_printf(s, "  ramping high index: %d\n",
+					ramp->hi_idx);
+			seq_printf(s, "  ramping from low to high: %d\n",
+					ramp->ramp_dir_low_to_hi);
+			seq_printf(s, "  ramping pattern repeat: %d\n",
+					ramp->pattern_repeat);
+			seq_printf(s, "  ramping toggle: %d\n",
+					ramp->toggle);
+			seq_printf(s, "  ramping pause count at low index: %d\n",
+					ramp->pause_lo_count);
+			seq_printf(s, "  ramping pause count at high index: %d\n",
+					ramp->pause_hi_count);
+		}
 	}
 }
 #endif
 
 static const struct pwm_ops qpnp_lpg_pwm_ops = {
 	.config = qpnp_lpg_pwm_config,
+	.get_output_type_supported = qpnp_lpg_pwm_output_types_supported,
+	.set_output_type = qpnp_lpg_pwm_set_output_type,
+	.set_output_pattern = qpnp_lpg_pwm_set_output_pattern,
 	.enable = qpnp_lpg_pwm_enable,
 	.disable = qpnp_lpg_pwm_disable,
 #ifdef CONFIG_DEBUG_FS
@@ -528,15 +975,19 @@
 
 static int qpnp_lpg_parse_dt(struct qpnp_lpg_chip *chip)
 {
+	struct device_node *child;
+	struct qpnp_lpg_channel *lpg;
+	struct lpg_ramp_config *ramp;
 	int rc = 0, i;
-	u64 base, length;
+	u32 base, length, lpg_chan_id, tmp;
 	const __be32 *addr;
 
 	addr = of_get_address(chip->dev->of_node, 0, NULL, NULL);
 	if (!addr) {
-		dev_err(chip->dev, "Getting address failed\n");
+		dev_err(chip->dev, "Get %s address failed\n", LPG_BASE);
 		return -EINVAL;
 	}
+
 	base = be32_to_cpu(addr[0]);
 	length = be32_to_cpu(addr[1]);
 
@@ -550,7 +1001,7 @@
 		chip->lpgs[i].chip = chip;
 		chip->lpgs[i].lpg_idx = i;
 		chip->lpgs[i].reg_base = base + i * REG_SIZE_PER_LPG;
-		chip->lpgs[i].src_sel = PWM_OUTPUT;
+		chip->lpgs[i].src_sel = PWM_VALUE;
 		rc = qpnp_lpg_read(&chip->lpgs[i], REG_LPG_PERPH_SUBTYPE,
 				&chip->lpgs[i].subtype);
 		if (rc < 0) {
@@ -559,7 +1010,142 @@
 		}
 	}
 
-	return rc;
+	addr = of_get_address(chip->dev->of_node, 1, NULL, NULL);
+	if (!addr) {
+		pr_debug("NO LUT address assigned\n");
+		return 0;
+	}
+
+	chip->lut = devm_kmalloc(chip->dev, sizeof(*chip->lut), GFP_KERNEL);
+	if (!chip->lut)
+		return -ENOMEM;
+
+	chip->lut->chip = chip;
+	chip->lut->reg_base = be32_to_cpu(*addr);
+	mutex_init(&chip->lut->lock);
+
+	rc = of_property_count_elems_of_size(chip->dev->of_node,
+			"qcom,lut-patterns", sizeof(u32));
+	if (rc < 0) {
+		dev_err(chip->dev, "Read qcom,lut-patterns failed, rc=%d\n",
+							rc);
+		return rc;
+	}
+
+	length = rc;
+	if (length > LPG_LUT_COUNT_MAX) {
+		dev_err(chip->dev, "qcom,lut-patterns length %d exceed max %d\n",
+				length, LPG_LUT_COUNT_MAX);
+		return -EINVAL;
+	}
+
+	chip->lut->pattern = devm_kcalloc(chip->dev, LPG_LUT_COUNT_MAX,
+			sizeof(*chip->lut->pattern), GFP_KERNEL);
+	if (!chip->lut->pattern)
+		return -ENOMEM;
+
+	rc = of_property_read_u32_array(chip->dev->of_node, "qcom,lut-patterns",
+					chip->lut->pattern, length);
+	if (rc < 0) {
+		dev_err(chip->dev, "Get qcom,lut-patterns failed, rc=%d\n",
+				rc);
+		return rc;
+	}
+
+	if (of_get_available_child_count(chip->dev->of_node) == 0) {
+		dev_err(chip->dev, "No ramp configuration for any LPG\n");
+		return -EINVAL;
+	}
+
+	for_each_available_child_of_node(chip->dev->of_node, child) {
+		rc = of_property_read_u32(child, "qcom,lpg-chan-id",
+						&lpg_chan_id);
+		if (rc < 0) {
+			dev_err(chip->dev, "Get qcom,lpg-chan-id failed for node %s, rc=%d\n",
+					child->name, rc);
+			return rc;
+		}
+
+		if (lpg_chan_id > chip->num_lpgs) {
+			dev_err(chip->dev, "lpg-chann-id %d is out of range 1~%d\n",
+					lpg_chan_id, chip->num_lpgs);
+			return -EINVAL;
+		}
+
+		/* lpg channel id is indexed from 1 in hardware */
+		lpg = &chip->lpgs[lpg_chan_id - 1];
+		ramp = &lpg->ramp_config;
+
+		rc = of_property_read_u32(child, "qcom,ramp-step-ms", &tmp);
+		if (rc < 0) {
+			dev_err(chip->dev, "get qcom,ramp-step-ms failed for lpg%d, rc=%d\n",
+					lpg_chan_id, rc);
+			return rc;
+		}
+		ramp->step_ms = (u16)tmp;
+
+		rc = of_property_read_u32(child, "qcom,ramp-low-index", &tmp);
+		if (rc < 0) {
+			dev_err(chip->dev, "get qcom,ramp-low-index failed for lpg%d, rc=%d\n",
+						lpg_chan_id, rc);
+			return rc;
+		}
+		ramp->lo_idx = (u8)tmp;
+		if (ramp->lo_idx >= LPG_LUT_COUNT_MAX) {
+			dev_err(chip->dev, "qcom,ramp-low-index should less than max %d\n",
+					LPG_LUT_COUNT_MAX);
+			return -EINVAL;
+		}
+
+		rc = of_property_read_u32(child, "qcom,ramp-high-index", &tmp);
+		if (rc < 0) {
+			dev_err(chip->dev, "get qcom,ramp-high-index failed for lpg%d, rc=%d\n",
+						lpg_chan_id, rc);
+			return rc;
+		}
+		ramp->hi_idx = (u8)tmp;
+
+		if (ramp->hi_idx > LPG_LUT_COUNT_MAX) {
+			dev_err(chip->dev, "qcom,ramp-high-index shouldn't exceed max %d\n",
+						LPG_LUT_COUNT_MAX);
+			return -EINVAL;
+		}
+
+		if (ramp->hi_idx <= ramp->lo_idx) {
+			dev_err(chip->dev, "high-index(%d) should be larger than low-index(%d)\n",
+						ramp->hi_idx, ramp->lo_idx);
+			return -EINVAL;
+		}
+
+		ramp->pattern_length = ramp->hi_idx - ramp->lo_idx + 1;
+		ramp->pattern = &chip->lut->pattern[ramp->lo_idx];
+		lpg->max_pattern_length = ramp->pattern_length;
+
+		rc = of_property_read_u32(child,
+				"qcom,ramp-pause-hi-count", &tmp);
+		if (rc < 0)
+			ramp->pause_hi_count = 0;
+		else
+			ramp->pause_hi_count = (u8)tmp;
+
+		rc = of_property_read_u32(child,
+				"qcom,ramp-pause-lo-count", &tmp);
+		if (rc < 0)
+			ramp->pause_lo_count = 0;
+		else
+			ramp->pause_lo_count = (u8)tmp;
+
+		ramp->ramp_dir_low_to_hi = of_property_read_bool(child,
+				"qcom,ramp-from-low-to-high");
+
+		ramp->pattern_repeat = of_property_read_bool(child,
+				"qcom,ramp-pattern-repeat");
+
+		ramp->toggle =  of_property_read_bool(child,
+				"qcom,ramp-toggle");
+	}
+
+	return 0;
 }
 
 static int qpnp_lpg_probe(struct platform_device *pdev)
@@ -583,7 +1169,7 @@
 	if (rc < 0) {
 		dev_err(chip->dev, "Devicetree properties parsing failed, rc=%d\n",
 				rc);
-		goto destroy;
+		goto err_out;
 	}
 
 	dev_set_drvdata(chip->dev, chip);
@@ -595,11 +1181,11 @@
 	rc = pwmchip_add(&chip->pwm_chip);
 	if (rc < 0) {
 		dev_err(chip->dev, "Add pwmchip failed, rc=%d\n", rc);
-		goto destroy;
+		goto err_out;
 	}
 
 	return 0;
-destroy:
+err_out:
 	mutex_destroy(&chip->bus_lock);
 	return rc;
 }
diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c
index a813239..ea2b53d 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -223,11 +223,60 @@
 	return sprintf(buf, "%u %u\n", result.period, result.duty_cycle);
 }
 
+static ssize_t output_type_show(struct device *child,
+			     struct device_attribute *attr,
+			     char *buf)
+{
+	const struct pwm_device *pwm = child_to_pwm_device(child);
+	const char *output_type = "unknown";
+	struct pwm_state state;
+
+	pwm_get_state(pwm, &state);
+	switch (state.output_type) {
+	case PWM_OUTPUT_FIXED:
+		output_type = "fixed";
+		break;
+	case PWM_OUTPUT_MODULATED:
+		output_type = "modulated";
+		break;
+	default:
+		break;
+	}
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", output_type);
+}
+
+static ssize_t output_type_store(struct device *child,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	struct pwm_export *export = child_to_pwm_export(child);
+	struct pwm_device *pwm = export->pwm;
+	struct pwm_state state;
+	int ret = -EINVAL;
+
+	mutex_lock(&export->lock);
+	pwm_get_state(pwm, &state);
+	if (sysfs_streq(buf, "fixed"))
+		state.output_type = PWM_OUTPUT_FIXED;
+	else if (sysfs_streq(buf, "modulated"))
+		state.output_type = PWM_OUTPUT_MODULATED;
+	else
+		goto unlock;
+
+	ret = pwm_apply_state(pwm, &state);
+unlock:
+	mutex_unlock(&export->lock);
+
+	return ret ? : size;
+}
+
 static DEVICE_ATTR_RW(period);
 static DEVICE_ATTR_RW(duty_cycle);
 static DEVICE_ATTR_RW(enable);
 static DEVICE_ATTR_RW(polarity);
 static DEVICE_ATTR_RO(capture);
+static DEVICE_ATTR_RW(output_type);
 
 static struct attribute *pwm_attrs[] = {
 	&dev_attr_period.attr,
@@ -235,6 +284,7 @@
 	&dev_attr_enable.attr,
 	&dev_attr_polarity.attr,
 	&dev_attr_capture.attr,
+	&dev_attr_output_type.attr,
 	NULL
 };
 ATTRIBUTE_GROUPS(pwm);
diff --git a/drivers/regulator/cpr4-apss-regulator.c b/drivers/regulator/cpr4-apss-regulator.c
index 1f8f8be..d5a0e33 100644
--- a/drivers/regulator/cpr4-apss-regulator.c
+++ b/drivers/regulator/cpr4-apss-regulator.c
@@ -1840,20 +1840,29 @@
 	return 0;
 }
 
-static int cpr4_apss_regulator_suspend(struct platform_device *pdev,
-				pm_message_t state)
+#if CONFIG_PM
+static int cpr4_apss_regulator_suspend(struct device *dev)
 {
-	struct cpr3_controller *ctrl = platform_get_drvdata(pdev);
+	struct cpr3_controller *ctrl = dev_get_drvdata(dev);
 
 	return cpr3_regulator_suspend(ctrl);
 }
 
-static int cpr4_apss_regulator_resume(struct platform_device *pdev)
+static int cpr4_apss_regulator_resume(struct device *dev)
 {
-	struct cpr3_controller *ctrl = platform_get_drvdata(pdev);
+	struct cpr3_controller *ctrl = dev_get_drvdata(dev);
 
 	return cpr3_regulator_resume(ctrl);
 }
+#else
+#define cpr4_apss_regulator_suspend NULL
+#define cpr4_apss_regulator_resume NULL
+#endif
+
+static const struct dev_pm_ops cpr4_apss_regulator_pm_ops = {
+	.suspend	= cpr4_apss_regulator_suspend,
+	.resume		= cpr4_apss_regulator_resume,
+};
 
 /* Data corresponds to the SoC revision */
 static const struct of_device_id cpr4_regulator_match_table[] = {
@@ -1977,11 +1986,10 @@
 		.name		= "qcom,cpr4-apss-regulator",
 		.of_match_table	= cpr4_regulator_match_table,
 		.owner		= THIS_MODULE,
+		.pm		= &cpr4_apss_regulator_pm_ops,
 	},
 	.probe		= cpr4_apss_regulator_probe,
 	.remove		= cpr4_apss_regulator_remove,
-	.suspend	= cpr4_apss_regulator_suspend,
-	.resume		= cpr4_apss_regulator_resume,
 };
 
 static int cpr4_regulator_init(void)
diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c
index 79d7cba..07a6198 100644
--- a/drivers/regulator/qpnp-lcdb-regulator.c
+++ b/drivers/regulator/qpnp-lcdb-regulator.c
@@ -991,7 +991,8 @@
 }
 
 #define MIN_BST_VOLTAGE_MV			4700
-#define MAX_BST_VOLTAGE_MV			6250
+#define PM660_MAX_BST_VOLTAGE_MV		6250
+#define MAX_BST_VOLTAGE_MV			6275
 #define MIN_VOLTAGE_MV				4000
 #define MAX_VOLTAGE_MV				6000
 #define VOLTAGE_MIN_STEP_100_MV			4000
@@ -1017,8 +1018,14 @@
 
 	if (bst_voltage_mv < MIN_BST_VOLTAGE_MV)
 		bst_voltage_mv = MIN_BST_VOLTAGE_MV;
-	else if (bst_voltage_mv > MAX_BST_VOLTAGE_MV)
-		bst_voltage_mv = MAX_BST_VOLTAGE_MV;
+
+	if (pmic_subtype == PM660L_SUBTYPE) {
+		if (bst_voltage_mv > PM660_MAX_BST_VOLTAGE_MV)
+			bst_voltage_mv = PM660_MAX_BST_VOLTAGE_MV;
+	} else {
+		if (bst_voltage_mv > MAX_BST_VOLTAGE_MV)
+			bst_voltage_mv = MAX_BST_VOLTAGE_MV;
+	}
 
 	if (bst_voltage_mv != bst->voltage_mv) {
 		if (pmic_subtype == PM660L_SUBTYPE) {
@@ -1883,6 +1890,8 @@
 			return rc;
 		}
 		lcdb->bst.soft_start_us = (val & SOFT_START_MASK) * 200 + 200;
+		if (!lcdb->bst.headroom_mv)
+			lcdb->bst.headroom_mv = PM660_BST_HEADROOM_DEFAULT_MV;
 	} else {
 		rc = qpnp_lcdb_read(lcdb, lcdb->base +
 				    LCDB_BST_SS_CTL_REG, &val, 1);
@@ -1891,6 +1900,8 @@
 			return rc;
 		}
 		lcdb->bst.soft_start_us = soft_start_us[val & SOFT_START_MASK];
+		if (!lcdb->bst.headroom_mv)
+			lcdb->bst.headroom_mv = BST_HEADROOM_DEFAULT_MV;
 	}
 
 	return 0;
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 46c8268..39ab28a 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -2499,7 +2499,7 @@
 int ufs_qcom_testbus_config(struct ufs_qcom_host *host)
 {
 	int reg = 0;
-	int offset, ret = 0, testbus_sel_offset = 19;
+	int offset = -1, ret = 0, testbus_sel_offset = 19;
 	u32 mask = TEST_BUS_SUB_SEL_MASK;
 	unsigned long flags;
 	struct ufs_hba *hba;
@@ -2564,6 +2564,12 @@
 	 * is legal
 	 */
 	}
+	if (offset < 0) {
+		dev_err(hba->dev, "%s: Bad offset: %d\n", __func__, offset);
+		ret = -EINVAL;
+		spin_unlock_irqrestore(hba->host->host_lock, flags);
+		goto out;
+	}
 	mask <<= offset;
 
 	spin_unlock_irqrestore(hba->host->host_lock, flags);
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 5fb0c29..26dfd3f 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.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
@@ -425,6 +425,7 @@
 	const u8 *old_wbuf = NULL;
 	bool report_sat = false;
 	bool sync_wr = true;
+	bool txn_async = txn->async;
 
 	memset(wbuf, 0, sizeof(wbuf));
 	if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG)
@@ -769,9 +770,9 @@
 		msm_slim_put_ctrl(dev);
 	}
 ngd_xfer_ret:
-	if (txn->wbuf == wbuf)
+	if (!txn_async && txn->wbuf == wbuf)
 		txn->wbuf = old_wbuf;
-	if (txn->comp == &done)
+	if (!txn_async && txn->comp == &done)
 		txn->comp = NULL;
 	return ret ? ret : dev->err;
 }
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 4e412497..5fafaca 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -386,8 +386,8 @@
 	  configured separately.
 
 config MSM_TZ_SMMU
-	depends on ARCH_MSM8953 || ARCH_MSM8909
 	bool "Helper functions for SMMU configuration through TZ"
+	default n
 	help
 	  Say 'Y' here for targets that need to call into TZ to configure
 	  SMMUs for any reason (for example, for errata workarounds or
@@ -558,6 +558,14 @@
          It also notifies userspace of transitions between these states via
          sysfs.
 
+config MSM_SYSMON_COMM
+	bool "MSM System Monitor communication support"
+	depends on MSM_SMD && MSM_SUBSYSTEM_RESTART
+	help
+	  This option adds support for MSM System Monitor library, which
+	  provides an API that may be used for notifying subsystems within
+	  the SoC about other subsystems' power-up/down state-changes.
+
 config MSM_PIL
        bool "Peripheral image loading"
        select FW_LOADER
@@ -813,4 +821,50 @@
 	  provides a means to support more logical channels
 	  via muxing than BAM could without muxing.
 
+	config MSM_GLINK_BGCOM_XPRT
+	depends on MSM_GLINK
+	depends on MSM_BGCOM
+	tristate "Generic Link (G-Link) BGCOM Transport"
+	help
+		G-Link BGCOM Transport is a Transport plug-in developed over BGCOM.
+		This transport plug-in performs marshaling of G-Link
+		commands & data to the appropriate BGCOM format and
+		allows for G-Link communication with remote subsystems that are
+		external to the System-on-Chip.
+
+	config MSM_BGCOM_INTERFACE
+	bool "Driver support for Blackghost Communication"
+	depends on MSM_BGCOM
+	help
+		Create a bg_com_dev device node for user space communication.
+		Single user space client can open device node for communication
+		from hardware. Hardware will provide access to read
+		registers and read/write AHB memory in the device.
+
+	config MSM_BGRSB
+	bool "Provide support for rsb events on Blackghost chipset"
+	depends on MSM_GLINK
+	help
+		BGRSB communicates to BG over Glink for RSB configuration and
+		enable/disable on device power state change. It enables/disables
+		the regulator specific to RSB. Sends the side band events generated
+		by BG to input framework.
+
+	config MSM_PIL_SSR_BG
+	tristate "MSM Subsystem Blackghost(BG) Support"
+	depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
+	help
+		Support for booting and shutting down Blackghost(BG) SOC which is
+		an external SOC. This driver communicates with Blackghost(BG) SOC
+		via pair of IPC GPIOs for inward and outward signals between MSM
+		and Blackghost(BG) SOC.
+
+	config MSM_BGCOM
+	bool "Provide APIs to communicate with Blackghost chipset"
+	help
+		BGCOM is a thin layer above SPI. It is used whithin a SoC for
+		communication between G-Link/bg_com_dev and BG processor over SPI.
+		This handle the interrupts raised by BG and notify the G-link with
+		interrupt event and event data.
+
 source "drivers/soc/qcom/wcnss/Kconfig"
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index c7c7f62..b83f554 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -2,6 +2,7 @@
 KCOV_INSTRUMENT_scm.o := n
 
 obj-$(CONFIG_QCOM_CPUSS_DUMP) += cpuss_dump.o
+obj-$(CONFIG_CPU_V7) += idle-v7.o
 obj-$(CONFIG_QCOM_GSBI)	+=	qcom_gsbi.o
 obj-$(CONFIG_QCOM_LLCC) += llcc-core.o llcc-slice.o
 obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
@@ -37,6 +38,7 @@
 obj-$(CONFIG_MSM_GLINK) += glink.o glink_debugfs.o glink_ssr.o
 obj-$(CONFIG_MSM_TZ_SMMU) += msm_tz_smmu.o
 obj-$(CONFIG_MSM_GLINK_LOOPBACK_SERVER) += glink_loopback_server.o
+obj-$(CONFIG_MSM_GLINK_BGCOM_XPRT) += glink_bgcom_xprt.o
 obj-$(CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT) += glink_smem_native_xprt.o
 obj-$(CONFIG_MSM_GLINK_SPI_XPRT) += glink_spi_xprt.o
 obj-$(CONFIG_MSM_SPCOM) += spcom.o
@@ -67,7 +69,9 @@
 obj-$(CONFIG_MEM_SHARE_QMI_SERVICE)		+= memshare/
 obj-$(CONFIG_MSM_PIL)   +=      peripheral-loader.o
 obj-$(CONFIG_MSM_PIL_SSR_GENERIC) += subsys-pil-tz.o
+obj-$(CONFIG_MSM_PIL_SSR_BG) += subsys-pil-bg.o
 obj-$(CONFIG_MSM_PIL_MSS_QDSP6V5) += pil-q6v5.o pil-msa.o pil-q6v5-mss.o
+obj-$(CONFIG_MSM_BGCOM) += bgcom_spi.o
 
 obj-$(CONFIG_MSM_PERFORMANCE) += msm_performance.o
 
@@ -77,6 +81,9 @@
        obj-y += ramdump.o
        obj-y += microdump_collector.o
 endif
+obj-$(CONFIG_MSM_SYSMON_COMM) += sysmon.o sysmon-qmi.o
+obj-$(CONFIG_MSM_BGRSB) += bg_rsb.o
+obj-$(CONFIG_MSM_BGCOM_INTERFACE) += bgcom_interface.o
 obj-$(CONFIG_MSM_JTAGV8) += jtagv8.o jtagv8-etm.o
 obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
 obj-$(CONFIG_MSM_QBT1000) += qbt1000.o
diff --git a/drivers/soc/qcom/bg_rsb.c b/drivers/soc/qcom/bg_rsb.c
new file mode 100644
index 0000000..fdfd7b7
--- /dev/null
+++ b/drivers/soc/qcom/bg_rsb.c
@@ -0,0 +1,1037 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(msg) "bgrsb: %s: " msg, __func__
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <soc/qcom/glink.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/regulator/consumer.h>
+#include <soc/qcom/subsystem_restart.h>
+#include <soc/qcom/subsystem_notif.h>
+
+#include "bgrsb.h"
+
+#define BGRSB_GLINK_INTENT_SIZE 0x04
+#define BGRSB_MSG_SIZE 0x08
+#define TIMEOUT_MS 500
+
+#define BGRSB_LDO15_VTG_MIN_UV 3300000
+#define BGRSB_LDO15_VTG_MAX_UV 3300000
+
+#define BGRSB_LDO11_VTG_MIN_UV 1800000
+#define BGRSB_LDO11_VTG_MAX_UV 1800000
+
+#define BGRSB_BGWEAR_SUBSYS "bg-wear"
+
+#define BGRSB_BTTN_CONFIGURE 5
+#define BGRSB_POWER_CALIBRATION 2
+#define BGRSB_POWER_ENABLE 1
+#define BGRSB_POWER_DISABLE 0
+#define BGRSB_GLINK_POWER_ENABLE 6
+#define BGRSB_GLINK_POWER_DISABLE 7
+
+
+struct bgrsb_regulator {
+	struct regulator *regldo11;
+	struct regulator *regldo15;
+};
+
+enum ldo_task {
+	BGRSB_ENABLE_LDO11,
+	BGRSB_ENABLE_LDO15,
+	BGRSB_DISABLE_LDO11,
+	BGRSB_DISABLE_LDO15,
+	BGRSB_NO_ACTION
+};
+
+enum bgrsb_state {
+	BGRSB_STATE_UNKNOWN,
+	BGRSB_STATE_INIT,
+	BGRSB_STATE_LDO11_ENABLED,
+	BGRSB_STATE_RSB_CONFIGURED,
+	BGRSB_STATE_LDO15_ENABLED,
+	BGRSB_STATE_RSB_ENABLED
+};
+
+struct bgrsb_msg {
+	uint32_t cmd_id;
+	uint32_t data;
+};
+
+struct bgrsb_priv {
+	void *handle;
+	struct input_dev *input;
+	struct mutex glink_mutex;
+
+	enum bgrsb_state bgrsb_current_state;
+	enum glink_link_state link_state;
+
+	bool chnl_state;
+	void *lhndl;
+
+	struct work_struct bg_up_work;
+	struct work_struct bg_down_work;
+
+	struct work_struct rsb_up_work;
+	struct work_struct rsb_down_work;
+
+	struct work_struct rsb_glink_up_work;
+	struct work_struct rsb_glink_down_work;
+
+	struct work_struct rsb_calibration_work;
+	struct work_struct bttn_configr_work;
+
+	struct work_struct glink_work;
+
+	struct workqueue_struct *bgrsb_event_wq;
+	struct workqueue_struct *bgrsb_wq;
+
+	struct bg_glink_chnl chnl;
+	char rx_buf[BGRSB_GLINK_INTENT_SIZE];
+
+	struct bgrsb_regulator rgltr;
+
+	enum ldo_task ldo_action;
+
+	void *bgwear_subsys_handle;
+
+	struct completion bg_resp_cmplt;
+	struct completion wrk_cmplt;
+	struct completion bg_lnikup_cmplt;
+	struct completion tx_done;
+
+	struct device *ldev;
+
+	wait_queue_head_t link_state_wait;
+
+	uint32_t calbrtion_intrvl;
+	uint32_t calbrtion_cpi;
+
+	uint8_t bttn_configs;
+
+	bool calibration_needed;
+	bool is_calibrd;
+};
+
+static void *bgrsb_drv;
+static int bgrsb_enable(struct bgrsb_priv *dev, bool enable);
+
+int bgrsb_send_input(struct event *evnt)
+{
+	uint8_t press_code;
+	uint8_t value;
+
+	struct bgrsb_priv *dev =
+			container_of(bgrsb_drv, struct bgrsb_priv, lhndl);
+
+	if (!evnt)
+		return -EINVAL;
+
+	if (evnt->sub_id == 1) {
+		input_report_rel(dev->input, REL_WHEEL, evnt->evnt_data);
+		input_sync(dev->input);
+	} else if (evnt->sub_id == 2) {
+
+		press_code = (uint8_t) evnt->evnt_data;
+		value = (uint8_t) (evnt->evnt_data >> 8);
+
+		switch (press_code) {
+		case 0x1:
+			if (value == 0) {
+				input_report_key(dev->input, KEY_VOLUMEDOWN, 1);
+				input_sync(dev->input);
+			} else {
+				input_report_key(dev->input, KEY_VOLUMEDOWN, 0);
+				input_sync(dev->input);
+			}
+			break;
+		case 0x2:
+			if (value == 0) {
+				input_report_key(dev->input, KEY_VOLUMEUP, 1);
+				input_sync(dev->input);
+			} else {
+				input_report_key(dev->input, KEY_VOLUMEUP, 0);
+				input_sync(dev->input);
+			}
+			break;
+		case 0x3:
+			if (value == 0) {
+				input_report_key(dev->input, KEY_POWER, 1);
+				input_sync(dev->input);
+			} else {
+				input_report_key(dev->input, KEY_POWER, 0);
+				input_sync(dev->input);
+			}
+			break;
+		default:
+			pr_info("event: type[%d] , data: %d\n",
+						evnt->sub_id, evnt->evnt_data);
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(bgrsb_send_input);
+
+static void bgrsb_glink_notify_rx(void *handle, const void *priv,
+	const void *pkt_priv, const void *ptr, size_t size)
+{
+	struct bgrsb_priv *dev = (struct bgrsb_priv *)priv;
+
+	memcpy(dev->rx_buf, ptr, size);
+	glink_rx_done(dev->handle, ptr, false);
+	complete(&dev->bg_resp_cmplt);
+}
+
+static void bgrsb_glink_notify_state(void *handle, const void *priv,
+	unsigned int event)
+{
+	struct bgrsb_priv *dev = (struct bgrsb_priv *)priv;
+
+	switch (event) {
+	case GLINK_CONNECTED:
+		complete(&dev->bg_lnikup_cmplt);
+		break;
+	case GLINK_REMOTE_DISCONNECTED:
+	case GLINK_LOCAL_DISCONNECTED:
+		dev->chnl_state = false;
+		break;
+	}
+}
+
+static void bgrsb_glink_notify_tx_done(void *handle, const void *priv,
+	const void *pkt_priv, const void *ptr)
+{
+	struct bgrsb_priv *dev = (struct bgrsb_priv *)priv;
+
+	complete(&dev->tx_done);
+}
+
+static void bgrsb_glink_close_work(struct work_struct *work)
+{
+	struct bgrsb_priv *dev =
+			container_of(work, struct bgrsb_priv, glink_work);
+
+	if (dev->handle)
+		glink_close(dev->handle);
+	dev->handle = NULL;
+}
+
+static void bgrsb_glink_open_work(struct work_struct *work)
+{
+	struct glink_open_config open_cfg;
+	void *hndl = NULL;
+	int rc = 0;
+	struct bgrsb_priv *dev =
+			container_of(work, struct bgrsb_priv, glink_work);
+
+	if (dev->handle)
+		return;
+
+	memset(&open_cfg, 0, sizeof(struct glink_open_config));
+	open_cfg.priv = (void *)dev;
+	open_cfg.edge = dev->chnl.chnl_edge;
+	open_cfg.transport = dev->chnl.chnl_trnsprt;
+	open_cfg.name = dev->chnl.chnl_name;
+	open_cfg.notify_tx_done = bgrsb_glink_notify_tx_done;
+	open_cfg.notify_state = bgrsb_glink_notify_state;
+	open_cfg.notify_rx = bgrsb_glink_notify_rx;
+
+	init_completion(&dev->bg_lnikup_cmplt);
+	hndl = glink_open(&open_cfg);
+
+	if (IS_ERR_OR_NULL(hndl)) {
+		pr_err("Glink open failed[%s]\n",
+						dev->chnl.chnl_name);
+		dev->handle = NULL;
+		return;
+	}
+
+	rc = wait_for_completion_timeout(&dev->bg_lnikup_cmplt,
+						msecs_to_jiffies(TIMEOUT_MS));
+	if (!rc) {
+		pr_err("Channel open failed. Time out\n");
+		return;
+	}
+	dev->chnl_state = true;
+	dev->handle = hndl;
+}
+
+static void bgrsb_glink_state_cb(struct glink_link_state_cb_info *cb_info,
+	void *data)
+{
+	struct bgrsb_priv *dev = (struct bgrsb_priv *)data;
+
+	dev->link_state = cb_info->link_state;
+	switch (dev->link_state) {
+	case GLINK_LINK_STATE_UP:
+		INIT_WORK(&dev->glink_work, bgrsb_glink_open_work);
+		queue_work(dev->bgrsb_event_wq, &dev->glink_work);
+		break;
+	case GLINK_LINK_STATE_DOWN:
+		INIT_WORK(&dev->glink_work, bgrsb_glink_close_work);
+		queue_work(dev->bgrsb_event_wq, &dev->glink_work);
+		break;
+	}
+}
+
+static int bgrsb_init_link_inf(struct bgrsb_priv *dev)
+{
+	struct glink_link_info link_info;
+	void *hndl;
+
+	link_info.glink_link_state_notif_cb = bgrsb_glink_state_cb;
+	link_info.transport = dev->chnl.chnl_trnsprt;
+	link_info.edge = dev->chnl.chnl_edge;
+
+	hndl = glink_register_link_state_cb(&link_info, (void *)dev);
+	if (IS_ERR_OR_NULL(hndl)) {
+		pr_err("Unable to register link[%s]\n",
+							dev->chnl.chnl_name);
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static int bgrsb_init_regulators(struct device *pdev)
+{
+	struct regulator *reg11;
+	struct regulator *reg15;
+	struct bgrsb_priv *dev = dev_get_drvdata(pdev);
+
+	reg11 = regulator_get(pdev, "vdd-ldo1");
+	if (IS_ERR_OR_NULL(reg11)) {
+		pr_err("Unable to get regulator for LDO-11\n");
+		return PTR_ERR(reg11);
+	}
+
+	reg15 = regulator_get(pdev, "vdd-ldo2");
+	if (IS_ERR_OR_NULL(reg15)) {
+		pr_err("Unable to get regulator for LDO-15\n");
+		return PTR_ERR(reg15);
+	}
+
+	dev->rgltr.regldo11 = reg11;
+	dev->rgltr.regldo15 = reg15;
+
+	return 0;
+}
+
+static int bgrsb_ldo_work(struct bgrsb_priv *dev, enum ldo_task ldo_action)
+{
+	int ret = 0;
+
+	switch (ldo_action) {
+	case BGRSB_ENABLE_LDO11:
+		ret = regulator_set_voltage(dev->rgltr.regldo11,
+				BGRSB_LDO11_VTG_MIN_UV, BGRSB_LDO11_VTG_MAX_UV);
+		if (ret) {
+			pr_err("Failed to request LDO-11 voltage.\n");
+			goto err_ret;
+		}
+		ret = regulator_enable(dev->rgltr.regldo11);
+		if (ret) {
+			pr_err("Failed to enable LDO-11 %d\n", ret);
+			goto err_ret;
+		}
+		break;
+
+	case BGRSB_ENABLE_LDO15:
+		ret = regulator_set_voltage(dev->rgltr.regldo15,
+				BGRSB_LDO15_VTG_MIN_UV, BGRSB_LDO15_VTG_MAX_UV);
+		if (ret) {
+			pr_err("Failed to request LDO-15 voltage.\n");
+			goto err_ret;
+		}
+		ret = regulator_enable(dev->rgltr.regldo15);
+		if (ret) {
+			pr_err("Failed to enable LDO-15 %d\n", ret);
+			goto err_ret;
+		}
+		break;
+	case BGRSB_DISABLE_LDO11:
+		ret = regulator_disable(dev->rgltr.regldo11);
+		if (ret) {
+			pr_err("Failed to disable LDO-11 %d\n", ret);
+			goto err_ret;
+		}
+		break;
+
+	case BGRSB_DISABLE_LDO15:
+		ret = regulator_disable(dev->rgltr.regldo15);
+		if (ret) {
+			pr_err("Failed to disable LDO-15 %d\n", ret);
+			goto err_ret;
+		}
+		regulator_set_load(dev->rgltr.regldo15, 0);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+err_ret:
+	return ret;
+}
+
+static void bgrsb_bgdown_work(struct work_struct *work)
+{
+	struct bgrsb_priv *dev = container_of(work, struct bgrsb_priv,
+								bg_down_work);
+
+	if (dev->bgrsb_current_state == BGRSB_STATE_RSB_ENABLED) {
+		if (bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO15) == 0)
+			dev->bgrsb_current_state = BGRSB_STATE_RSB_CONFIGURED;
+		else
+			pr_err("Failed to unvote LDO-15 on BG down\n");
+	}
+
+	if (dev->bgrsb_current_state == BGRSB_STATE_RSB_CONFIGURED) {
+		if (bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO11) == 0)
+			dev->bgrsb_current_state = BGRSB_STATE_INIT;
+		else
+			pr_err("Failed to unvote LDO-11 on BG down\n");
+	}
+
+	pr_info("RSB current state is : %d\n", dev->bgrsb_current_state);
+
+	if (dev->bgrsb_current_state == BGRSB_STATE_INIT) {
+		if (dev->is_calibrd)
+			dev->calibration_needed = true;
+	}
+}
+
+static void bgrsb_glink_bgdown_work(struct work_struct *work)
+{
+	int rc;
+	struct bgrsb_priv *dev = container_of(work, struct bgrsb_priv,
+							rsb_glink_down_work);
+
+	if (dev->bgrsb_current_state == BGRSB_STATE_RSB_ENABLED) {
+
+		rc = bgrsb_enable(dev, false);
+		if (rc != 0) {
+			pr_err("Failed to send disable command to BG\n");
+			return;
+		}
+
+		if (bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO15) != 0) {
+			pr_err("Failed to un-vote LDO-15\n");
+			return;
+		}
+
+		dev->bgrsb_current_state = BGRSB_STATE_RSB_CONFIGURED;
+		pr_info("RSB Disabled\n");
+	}
+
+	if (dev->bgrsb_current_state == BGRSB_STATE_RSB_CONFIGURED) {
+		if (bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO11) == 0)
+			dev->bgrsb_current_state = BGRSB_STATE_INIT;
+		else
+			pr_err("Failed to unvote LDO-11 on BG Glink down\n");
+	}
+	if (dev->handle)
+		glink_close(dev->handle);
+	dev->handle = NULL;
+	pr_debug("BG Glink Close connection\n");
+}
+
+static int bgrsb_tx_msg(struct bgrsb_priv *dev, void  *msg, size_t len)
+{
+	int rc = 0;
+	uint8_t resp = 0;
+
+	if (!dev->chnl_state)
+		return -ENODEV;
+
+	mutex_lock(&dev->glink_mutex);
+	init_completion(&dev->tx_done);
+	init_completion(&dev->bg_resp_cmplt);
+
+	rc = glink_queue_rx_intent(dev->handle,
+					(void *)dev, BGRSB_GLINK_INTENT_SIZE);
+
+	if (rc) {
+		pr_err("Failed to queue intent\n");
+		goto err_ret;
+	}
+
+	rc = glink_tx(dev->handle, (void *)dev, msg,
+					len, GLINK_TX_REQ_INTENT);
+	if (rc) {
+		pr_err("Failed to send command\n");
+		goto err_ret;
+	}
+
+	rc = wait_for_completion_timeout(&dev->tx_done,
+						msecs_to_jiffies(TIMEOUT_MS));
+	if (!rc) {
+		pr_err("Timed out waiting for Command to send\n");
+		rc = -ETIMEDOUT;
+		goto err_ret;
+	}
+
+	rc = wait_for_completion_timeout(&dev->bg_resp_cmplt,
+						msecs_to_jiffies(TIMEOUT_MS));
+	if (!rc) {
+		pr_err("Timed out waiting for response\n");
+		rc = -ETIMEDOUT;
+		goto err_ret;
+	}
+
+	resp = *(uint8_t *)dev->rx_buf;
+	if (!(resp == 0x01)) {
+		pr_err("Bad RSB response\n");
+		rc = -EINVAL;
+		goto err_ret;
+	}
+	rc = 0;
+
+err_ret:
+	mutex_unlock(&dev->glink_mutex);
+	return rc;
+}
+
+static int bgrsb_enable(struct bgrsb_priv *dev, bool enable)
+{
+	int rc = 0;
+	struct bgrsb_msg req = {0};
+
+	req.cmd_id = 0x02;
+	req.data = enable ? 0x01 : 0x00;
+
+	rc = bgrsb_tx_msg(dev, &req, BGRSB_MSG_SIZE);
+	return rc;
+}
+
+static int bgrsb_configr_rsb(struct bgrsb_priv *dev, bool enable)
+{
+	int rc = 0;
+	struct bgrsb_msg req = {0};
+
+	req.cmd_id = 0x01;
+	req.data = enable ? 0x01 : 0x00;
+
+	rc = bgrsb_tx_msg(dev, &req, BGRSB_MSG_SIZE);
+	return rc;
+}
+
+static void bgrsb_bgup_work(struct work_struct *work)
+{
+	int rc = 0;
+	struct bgrsb_priv *dev = container_of(work, struct bgrsb_priv,
+								bg_up_work);
+
+	if (bgrsb_ldo_work(dev, BGRSB_ENABLE_LDO11) == 0) {
+
+		rc = wait_event_timeout(dev->link_state_wait,
+				(dev->chnl_state == true),
+					msecs_to_jiffies(TIMEOUT_MS*2));
+		if (rc == 0) {
+			pr_err("Glink channel connection time out\n");
+			return;
+		}
+		rc = bgrsb_configr_rsb(dev, true);
+		if (rc != 0) {
+			pr_err("BG failed to configure RSB %d\n", rc);
+			if (bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO11) == 0)
+				dev->bgrsb_current_state = BGRSB_STATE_INIT;
+			return;
+		}
+		dev->bgrsb_current_state = BGRSB_STATE_RSB_CONFIGURED;
+		pr_debug("RSB Cofigured\n");
+	}
+}
+
+static void bgrsb_glink_bgup_work(struct work_struct *work)
+{
+	int rc = 0;
+	struct bgrsb_priv *dev = container_of(work, struct bgrsb_priv,
+							rsb_glink_up_work);
+
+	if (bgrsb_ldo_work(dev, BGRSB_ENABLE_LDO11) == 0) {
+
+		INIT_WORK(&dev->glink_work, bgrsb_glink_open_work);
+		queue_work(dev->bgrsb_event_wq, &dev->glink_work);
+
+		rc = wait_event_timeout(dev->link_state_wait,
+					(dev->chnl_state == true),
+						msecs_to_jiffies(TIMEOUT_MS*2));
+		if (rc == 0) {
+			pr_err("Glink channel connection time out\n");
+			return;
+		}
+		rc = bgrsb_configr_rsb(dev, true);
+		if (rc != 0) {
+			pr_err("BG Glink failed to configure RSB %d\n", rc);
+			if (bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO11) == 0)
+				dev->bgrsb_current_state = BGRSB_STATE_INIT;
+			return;
+		}
+		dev->bgrsb_current_state = BGRSB_STATE_RSB_CONFIGURED;
+		pr_debug("Glink RSB Cofigured\n");
+	}
+}
+
+/**
+ *ssr_bg_cb(): callback function is called
+ *by ssr framework when BG goes down, up and during ramdump
+ *collection. It handles BG shutdown and power up events.
+ */
+static int ssr_bgrsb_cb(struct notifier_block *this,
+		unsigned long opcode, void *data)
+{
+	struct bgrsb_priv *dev = container_of(bgrsb_drv,
+				struct bgrsb_priv, lhndl);
+
+	switch (opcode) {
+	case SUBSYS_BEFORE_SHUTDOWN:
+		queue_work(dev->bgrsb_wq, &dev->bg_down_work);
+		break;
+	case SUBSYS_AFTER_POWERUP:
+		if (dev->bgrsb_current_state == BGRSB_STATE_INIT)
+			queue_work(dev->bgrsb_wq, &dev->bg_up_work);
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ssr_bg_nb = {
+	.notifier_call = ssr_bgrsb_cb,
+	.priority = 0,
+};
+
+/**
+ * ssr_register checks that domain id should be in range and register
+ * SSR framework for value at domain id.
+ */
+static int bgrsb_ssr_register(struct bgrsb_priv *dev)
+{
+	struct notifier_block *nb;
+
+	if (!dev)
+		return -ENODEV;
+
+	nb = &ssr_bg_nb;
+	dev->bgwear_subsys_handle =
+			subsys_notif_register_notifier(BGRSB_BGWEAR_SUBSYS, nb);
+
+	if (!dev->bgwear_subsys_handle) {
+		dev->bgwear_subsys_handle = NULL;
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static void bgrsb_enable_rsb(struct work_struct *work)
+{
+	int rc = 0;
+	struct bgrsb_priv *dev = container_of(work, struct bgrsb_priv,
+								rsb_up_work);
+
+	if (dev->bgrsb_current_state != BGRSB_STATE_RSB_CONFIGURED) {
+		pr_err("BG is not yet configured for RSB\n");
+		return;
+	}
+
+	if (bgrsb_ldo_work(dev, BGRSB_ENABLE_LDO15) == 0) {
+
+		rc = bgrsb_enable(dev, true);
+		if (rc != 0) {
+			pr_err("Failed to send enable command to BG\n");
+			bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO15);
+			dev->bgrsb_current_state = BGRSB_STATE_RSB_CONFIGURED;
+			return;
+		}
+	}
+	dev->bgrsb_current_state = BGRSB_STATE_RSB_ENABLED;
+	pr_debug("RSB Enabled\n");
+
+	if (dev->calibration_needed) {
+		dev->calibration_needed = false;
+		queue_work(dev->bgrsb_wq, &dev->rsb_calibration_work);
+	}
+}
+
+static void bgrsb_disable_rsb(struct work_struct *work)
+{
+	int rc = 0;
+	struct bgrsb_priv *dev = container_of(work, struct bgrsb_priv,
+								rsb_down_work);
+
+	if (dev->bgrsb_current_state == BGRSB_STATE_RSB_ENABLED) {
+
+		rc = bgrsb_enable(dev, false);
+		if (rc != 0) {
+			pr_err("Failed to send disable command to BG\n");
+			return;
+		}
+
+		if (bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO15) != 0)
+			return;
+
+		dev->bgrsb_current_state = BGRSB_STATE_RSB_CONFIGURED;
+		pr_debug("RSB Disabled\n");
+	}
+}
+
+static void bgrsb_calibration(struct work_struct *work)
+{
+	int rc = 0;
+	struct bgrsb_msg req = {0};
+	struct bgrsb_priv *dev =
+			container_of(work, struct bgrsb_priv,
+							rsb_calibration_work);
+
+	req.cmd_id = 0x03;
+	req.data = dev->calbrtion_cpi;
+
+	rc = bgrsb_tx_msg(dev, &req, 5);
+	if (rc != 0) {
+		pr_err("Failed to send resolution value to BG\n");
+		return;
+	}
+
+	req.cmd_id = 0x04;
+	req.data = dev->calbrtion_intrvl;
+
+	rc = bgrsb_tx_msg(dev, &req, 5);
+	if (rc != 0) {
+		pr_err("Failed to send interval value to BG\n");
+		return;
+	}
+	dev->is_calibrd = true;
+	pr_debug("RSB Calibbered\n");
+}
+
+static void bgrsb_buttn_configration(struct work_struct *work)
+{
+	int rc = 0;
+	struct bgrsb_msg req = {0};
+	struct bgrsb_priv *dev =
+			container_of(work, struct bgrsb_priv,
+							bttn_configr_work);
+
+	req.cmd_id = 0x05;
+	req.data = dev->bttn_configs;
+
+	rc = bgrsb_tx_msg(dev, &req, 5);
+	if (rc != 0) {
+		pr_err("Failed to send button configuration cmnd to BG\n");
+		return;
+	}
+
+	dev->bttn_configs = 0;
+	pr_debug("Button configured\n");
+}
+
+static int split_bg_work(struct bgrsb_priv *dev, char *str)
+{
+	long val;
+	int ret;
+	char *tmp;
+
+	tmp = strsep(&str, ":");
+	if (!tmp)
+		return -EINVAL;
+
+	ret = kstrtol(tmp, 10, &val);
+	if (ret < 0)
+		return ret;
+
+	switch (val) {
+	case BGRSB_POWER_DISABLE:
+		if (dev->bgrsb_current_state == BGRSB_STATE_RSB_CONFIGURED)
+			return 0;
+		queue_work(dev->bgrsb_wq, &dev->rsb_down_work);
+		break;
+	case BGRSB_POWER_ENABLE:
+		if (dev->bgrsb_current_state == BGRSB_STATE_RSB_ENABLED)
+			return 0;
+		queue_work(dev->bgrsb_wq, &dev->rsb_up_work);
+		break;
+	case BGRSB_POWER_CALIBRATION:
+		tmp = strsep(&str, ":");
+		if (!tmp)
+			return -EINVAL;
+
+		ret = kstrtol(tmp, 10, &val);
+		if (ret < 0)
+			return ret;
+
+		dev->calbrtion_intrvl = (uint32_t)val;
+
+		tmp = strsep(&str, ":");
+		if (!tmp)
+			return -EINVAL;
+
+		ret = kstrtol(tmp, 10, &val);
+		if (ret < 0)
+			return ret;
+
+		dev->calbrtion_cpi = (uint32_t)val;
+
+		queue_work(dev->bgrsb_wq, &dev->rsb_calibration_work);
+		break;
+	case BGRSB_BTTN_CONFIGURE:
+		tmp = strsep(&str, ":");
+		if (!tmp)
+			return -EINVAL;
+
+		ret = kstrtol(tmp, 10, &val);
+		if (ret < 0)
+			return ret;
+
+		dev->bttn_configs = (uint8_t)val;
+		queue_work(dev->bgrsb_wq, &dev->bttn_configr_work);
+		break;
+	case BGRSB_GLINK_POWER_DISABLE:
+		queue_work(dev->bgrsb_wq, &dev->rsb_glink_down_work);
+		break;
+	case BGRSB_GLINK_POWER_ENABLE:
+		queue_work(dev->bgrsb_wq, &dev->rsb_glink_up_work);
+		break;
+	}
+	return 0;
+}
+
+static int store_enable(struct device *pdev, struct device_attribute *attr,
+		const char *buff, size_t count)
+{
+	int rc;
+	struct bgrsb_priv *dev = dev_get_drvdata(pdev);
+	char *arr = kstrdup(buff, GFP_KERNEL);
+
+	if (!arr)
+		goto err_ret;
+
+	rc = split_bg_work(dev, arr);
+	if (rc != 0)
+		pr_err("Not able to process request\n");
+
+err_ret:
+	return count;
+}
+
+static int show_enable(struct device *dev, struct device_attribute *attr,
+			char *buff)
+{
+	return 0;
+}
+
+static struct device_attribute dev_attr_rsb = {
+	.attr = {
+		.name = "enable",
+		.mode = 00660,
+	},
+	.show = show_enable,
+	.store = store_enable,
+};
+
+static int bgrsb_init(struct bgrsb_priv *dev)
+{
+	bgrsb_drv = &dev->lhndl;
+	dev->chnl.chnl_name = "RSB_CTRL";
+	dev->chnl.chnl_edge = "bg";
+	dev->chnl.chnl_trnsprt = "bgcom";
+	mutex_init(&dev->glink_mutex);
+	dev->link_state = GLINK_LINK_STATE_DOWN;
+
+	dev->ldo_action = BGRSB_NO_ACTION;
+
+	dev->bgrsb_event_wq =
+		create_singlethread_workqueue(dev->chnl.chnl_name);
+	if (!dev->bgrsb_event_wq) {
+		pr_err("Failed to init Glink work-queue\n");
+		goto err_ret;
+	}
+
+	dev->bgrsb_wq =
+		create_singlethread_workqueue("bg-work-queue");
+	if (!dev->bgrsb_wq) {
+		pr_err("Failed to init BG-RSB work-queue\n");
+		goto free_rsb_wq;
+	}
+
+	init_waitqueue_head(&dev->link_state_wait);
+
+	/* set default bgrsb state */
+	dev->bgrsb_current_state = BGRSB_STATE_INIT;
+
+	/* Init all works */
+	INIT_WORK(&dev->bg_up_work, bgrsb_bgup_work);
+	INIT_WORK(&dev->bg_down_work, bgrsb_bgdown_work);
+	INIT_WORK(&dev->rsb_up_work, bgrsb_enable_rsb);
+	INIT_WORK(&dev->rsb_down_work, bgrsb_disable_rsb);
+	INIT_WORK(&dev->rsb_calibration_work, bgrsb_calibration);
+	INIT_WORK(&dev->bttn_configr_work, bgrsb_buttn_configration);
+	INIT_WORK(&dev->rsb_glink_down_work, bgrsb_glink_bgdown_work);
+	INIT_WORK(&dev->rsb_glink_up_work, bgrsb_glink_bgup_work);
+
+	return 0;
+
+free_rsb_wq:
+	destroy_workqueue(dev->bgrsb_event_wq);
+err_ret:
+	return -EFAULT;
+}
+
+static int bg_rsb_probe(struct platform_device *pdev)
+{
+	struct bgrsb_priv *dev;
+	struct input_dev *input;
+	int rc;
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->bgrsb_current_state = BGRSB_STATE_UNKNOWN;
+	rc = bgrsb_init(dev);
+	if (rc)
+		goto err_ret_dev;
+
+	rc = bgrsb_init_link_inf(dev);
+	if (rc)
+		goto err_ret_dev;
+
+	/* Set up input device */
+	input = input_allocate_device();
+	if (!input)
+		goto err_ret_dev;
+
+	input_set_capability(input, EV_REL, REL_WHEEL);
+	input_set_capability(input, EV_KEY, KEY_VOLUMEUP);
+	input_set_capability(input, EV_KEY, KEY_VOLUMEDOWN);
+	input->name = "bg-spi";
+
+	rc = input_register_device(input);
+	if (rc) {
+		pr_err("Input device registration failed\n");
+		goto err_ret_inp;
+	}
+	dev->input = input;
+
+	/* register device for bg-wear ssr */
+	rc = bgrsb_ssr_register(dev);
+	if (rc) {
+		pr_err("Failed to register for bg ssr\n");
+		goto err_ret_inp;
+	}
+	rc = device_create_file(&pdev->dev, &dev_attr_rsb);
+	if (rc) {
+		pr_err("Not able to create the file bg-rsb/enable\n");
+		goto err_ret_inp;
+	}
+	dev_set_drvdata(&pdev->dev, dev);
+	rc = bgrsb_init_regulators(&pdev->dev);
+	if (rc) {
+		pr_err("Failed to set regulators\n");
+		goto err_ret_inp;
+	}
+	return 0;
+
+err_ret_inp:
+	input_free_device(input);
+
+err_ret_dev:
+	devm_kfree(&pdev->dev, dev);
+	return -ENODEV;
+}
+
+static int bg_rsb_remove(struct platform_device *pdev)
+{
+	struct bgrsb_priv *dev = platform_get_drvdata(pdev);
+
+	destroy_workqueue(dev->bgrsb_event_wq);
+	destroy_workqueue(dev->bgrsb_wq);
+	input_free_device(dev->input);
+
+	return 0;
+}
+
+static int bg_rsb_resume(struct platform_device *pdev)
+{
+	int rc;
+	struct bgrsb_priv *dev = platform_get_drvdata(pdev);
+
+	if (dev->bgrsb_current_state == BGRSB_STATE_RSB_CONFIGURED)
+		return 0;
+
+	if (dev->bgrsb_current_state == BGRSB_STATE_INIT) {
+		if (bgrsb_ldo_work(dev, BGRSB_ENABLE_LDO11) == 0) {
+			rc = bgrsb_configr_rsb(dev, true);
+			if (rc != 0) {
+				pr_err("BG failed to configure RSB %d\n", rc);
+				bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO11);
+				return rc;
+			}
+			dev->bgrsb_current_state = BGRSB_STATE_RSB_CONFIGURED;
+			pr_debug("RSB Cofigured\n");
+			return 0;
+		}
+		pr_err("RSB failed to resume\n");
+	}
+	return -EINVAL;
+}
+
+static int bg_rsb_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct bgrsb_priv *dev = platform_get_drvdata(pdev);
+
+	if (dev->bgrsb_current_state == BGRSB_STATE_INIT)
+		return 0;
+
+	if (dev->bgrsb_current_state == BGRSB_STATE_RSB_ENABLED) {
+		if (bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO15) != 0)
+			goto ret_err;
+	}
+
+	if (bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO11) == 0) {
+		dev->bgrsb_current_state = BGRSB_STATE_INIT;
+		pr_debug("RSB Init\n");
+		return 0;
+	}
+
+ret_err:
+	pr_err("RSB failed to suspend\n");
+	return -EINVAL;
+}
+
+static const struct of_device_id bg_rsb_of_match[] = {
+	{ .compatible = "qcom,bg-rsb", },
+	{ }
+};
+
+static struct platform_driver bg_rsb_driver = {
+	.driver = {
+		.name = "bg-rsb",
+		.of_match_table = bg_rsb_of_match,
+	},
+	.probe		= bg_rsb_probe,
+	.remove		= bg_rsb_remove,
+	.resume		= bg_rsb_resume,
+	.suspend	= bg_rsb_suspend,
+};
+
+module_platform_driver(bg_rsb_driver);
+MODULE_DESCRIPTION("SoC BG RSB driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/bgcom.h b/drivers/soc/qcom/bgcom.h
new file mode 100644
index 0000000..b389a91
--- /dev/null
+++ b/drivers/soc/qcom/bgcom.h
@@ -0,0 +1,214 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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 BGCOM_H
+#define BGCOM_H
+
+#define BGCOM_REG_TZ_TO_MASTER_STATUS        0x01
+#define BGCOM_REG_TZ_TO_MASTER_DATA          0x03
+#define BGCOM_REG_SLAVE_STATUS               0x05
+#define BGCOM_REG_TIMESTAMP                  0x07
+#define BGCOM_REG_SLAVE_STATUS_AUTO_CLEAR    0x09
+#define BGCOM_REG_FIFO_FILL                  0x0B
+#define BGCOM_REG_FIFO_SIZE                  0x0D
+#define BGCOM_REG_TZ_TO_SLAVE_COMMAND        0x0E
+#define BGCOM_REG_TZ_TO_SLAVE_DATA           0x10
+#define BGCOM_REG_MASTER_STATUS              0x12
+#define BGCOM_REG_MASTER_COMMAND             0x14
+#define BGCOM_REG_MSG_WR_REG_4               0x16
+#define BGCOM_REG_TO_SLAVE_FIFO              0x40
+#define BGCOM_REG_TO_MASTER_FIFO             0x41
+#define BGCOM_REG_TO_SLAVE_AHB               0x42
+#define BGCOM_REG_TO_MASTER_AHB              0x43
+
+/* Enum to define the bgcom SPI state */
+enum bgcom_spi_state {
+	BGCOM_SPI_FREE = 0,
+	BGCOM_SPI_BUSY,
+};
+
+/* Enums to identify Blackghost events */
+enum bgcom_event_type {
+	BGCOM_EVENT_NONE	= 0,
+	BGCOM_EVENT_APPLICATION_RUNNING,
+	BGCOM_EVENT_TO_SLAVE_FIFO_READY,
+	BGCOM_EVENT_TO_MASTER_FIFO_READY,
+	BGCOM_EVENT_AHB_READY,
+	BGCOM_EVENT_TO_MASTER_FIFO_USED,
+	BGCOM_EVENT_TO_SLAVE_FIFO_FREE,
+	BGCOM_EVENT_TIMESTAMP_UPDATE,
+	BGCOM_EVENT_RESET_OCCURRED,
+
+	BGCOM_EVENT_ERROR_WRITE_FIFO_OVERRUN,
+	BGCOM_EVENT_ERROR_WRITE_FIFO_BUS_ERR,
+	BGCOM_EVENT_ERROR_WRITE_FIFO_ACCESS,
+	BGCOM_EVENT_ERROR_READ_FIFO_UNDERRUN,
+	BGCOM_EVENT_ERROR_READ_FIFO_BUS_ERR,
+	BGCOM_EVENT_ERROR_READ_FIFO_ACCESS,
+	BGCOM_EVENT_ERROR_TRUNCATED_READ,
+	BGCOM_EVENT_ERROR_TRUNCATED_WRITE,
+	BGCOM_EVENT_ERROR_AHB_ILLEGAL_ADDRESS,
+	BGCOM_EVENT_ERROR_AHB_BUS_ERR,
+	BGCOM_EVENT_ERROR_UNKNOWN,
+};
+
+/* Event specific data */
+union bgcom_event_data_type {
+	uint32_t unused;
+	bool application_running;      /* BGCOM_EVENT_APPLICATION_RUNNING */
+	bool to_slave_fifo_ready;      /* BGCOM_EVENT_TO_SLAVE_FIFO_READY */
+	bool to_master_fifo_ready;     /* BGCOM_EVENT_TO_MASTER_FIFO_READY */
+	bool ahb_ready;                /* BGCOM_EVENT_AHB_READY */
+	uint16_t to_slave_fifo_free;	/* BGCOM_EVENT_TO_SLAVE_FIFO_FREE */
+	struct fifo_event_data {
+		uint16_t to_master_fifo_used;
+		void *data;
+	} fifo_data;
+};
+
+/* Client specific data */
+struct bgcom_open_config_type {
+	/** Private data pointer for client to maintain context.
+	 * This data is passed back to client in the notification callbacks.
+	 */
+	void		*priv;
+
+	/* Notification callbacks to notify the BG events */
+	void (*bgcom_notification_cb)(void *handle, void *priv,
+			enum bgcom_event_type event,
+			union bgcom_event_data_type *event_data);
+};
+
+/**
+ * bgcom_open() - opens a channel to interact with Blackghost
+ * @open_config: pointer to the open configuration structure
+ *
+ * Open a new connection to blackghost
+ *
+ * Return a handle on success or NULL on error
+ */
+void *bgcom_open(struct bgcom_open_config_type *open_config);
+
+/**
+ * bgcom_close() - close the exsting with Blackghost
+ * @handle: pointer to the handle, provided by bgcom at
+ *	bgcom_open
+ *
+ * Open a new connection to blackghost
+ *
+ * Return 0 on success or error on invalid handle
+ */
+int bgcom_close(void **handle);
+
+/**
+ * bgcom_reg_read() - Read from the one or more contiguous registers from BG
+ * @handle: BGCOM handle associated with the channel
+ * @reg_start_addr : 8 bit start address of the registers to read from
+ * @num_regs :	Number of contiguous registers to read, starting
+ *				from reg_start_addr.
+ * @read_buf : Buffer to read from the registers.
+ * Return 0 on success or -Ve on error
+ */
+int bgcom_reg_read(void *handle, uint8_t reg_start_addr,
+			uint32_t num_regs, void *read_buf);
+
+/**
+ * Write into the one or more contiguous registers.
+ *
+ * @param[in] handle         BGCOM handle associated with the channel.
+ * @param[in] reg_start_addr 8bit start address of the registers to write into.
+ * @param[in] num_regs       Number of contiguous registers to write, starting
+ *                           from reg_start_addr.
+ * @param[in] write_buf      Buffer to write into the registers.
+ *
+ * @return
+ * 0 if function is successful,
+ * Otherwise returns error code.
+ *
+ * @sideeffects  Causes the Blackghost SPI slave to wakeup. Depending up on
+ * the operation, it may also wakeup the complete Blackghost.
+ */
+
+/**
+ * bgcom_reg_write() - Write to the one or more contiguous registers on BG
+ * @handle: BGCOM handle associated with the channel
+ * @reg_start_addr : 8 bit start address of the registers to read from
+ * @num_regs :	Number of contiguous registers to write, starting
+ *				from reg_start_addr.
+ * @write_buf : Buffer to be written to the registers.
+ * Return 0 on success or -Ve on error
+ */
+int bgcom_reg_write(void *handle, uint8_t reg_start_addr,
+	uint8_t num_regs, void *write_buf);
+
+/**
+ * bgcom_fifo_read() - Read data from the TO_MASTER_FIFO.
+ * @handle: BGCOM handle associated with the channel
+ * @num_words : number of words to read from FIFO
+ * @read_buf : Buffer read from FIFO.
+ * Return 0 on success or -Ve on error
+ */
+int bgcom_fifo_read(void *handle, uint32_t num_words,
+		void *read_buf);
+
+/**
+ * bgcom_fifo_write() - Write data to the TO_SLAVE_FIFO.
+ * @handle: BGCOM handle associated with the channel
+ * @num_words : number of words to write on FIFO
+ * @write_buf : Buffer written to FIFO.
+ * Return 0 on success or -Ve on error
+ */
+int bgcom_fifo_write(void *handle, uint32_t num_words,
+		void *write_buf);
+
+/**
+ * bgcom_ahb_read() - Read data from the AHB memory.
+ * @handle: BGCOM handle associated with the channel
+ * @ahb_start_addr : Memory start address from where to read
+ * @num_words : number of words to read from AHB
+ * @read_buf : Buffer read from FIFO.
+ * Return 0 on success or -Ve on error
+ */
+int bgcom_ahb_read(void *handle, uint32_t ahb_start_addr,
+		uint32_t num_words, void *read_buf);
+
+/**
+ * bgcom_ahb_write() - Write data to the AHB memory.
+ * @handle: BGCOM handle associated with the channel
+ * @ahb_start_addr : Memory start address from where to start write
+ * @num_words : number of words to read from AHB
+ * @write_buf : Buffer to write in AHB.
+ * Return 0 on success or -Ve on error
+ */
+int bgcom_ahb_write(void *handle, uint32_t ahb_start_addr,
+		uint32_t num_words, void *write_buf);
+
+/**
+ * bgcom_suspend() - Suspends the channel.
+ * @handle: BGCOM handle associated with the channel
+ * Return 0 on success or -Ve on error
+ */
+int bgcom_suspend(void *handle);
+
+/**
+ * bgcom_resume() - Resumes the channel.
+ * @handle: BGCOM handle associated with the channel
+ * Return 0 on success or -Ve on error
+ */
+int bgcom_resume(void *handle);
+
+int bgcom_set_spi_state(enum bgcom_spi_state state);
+
+void bgcom_bgdown_handler(void);
+
+#endif /* BGCOM_H */
diff --git a/drivers/soc/qcom/bgcom_interface.c b/drivers/soc/qcom/bgcom_interface.c
new file mode 100644
index 0000000..efef26d
--- /dev/null
+++ b/drivers/soc/qcom/bgcom_interface.c
@@ -0,0 +1,614 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#define pr_fmt(msg) "bgcom_dev:" msg
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <soc/qcom/subsystem_restart.h>
+#include <soc/qcom/subsystem_notif.h>
+#include "bgcom.h"
+#include "linux/bgcom_interface.h"
+#include "bgcom_interface.h"
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
+#define BGCOM "bg_com_dev"
+
+#define BGDAEMON_LDO09_LPM_VTG 0
+#define BGDAEMON_LDO09_NPM_VTG 10000
+
+#define BGDAEMON_LDO03_LPM_VTG 0
+#define BGDAEMON_LDO03_NPM_VTG 10000
+
+#define MPPS_DOWN_EVENT_TO_BG_TIMEOUT 100
+
+enum {
+	SSR_DOMAIN_BG,
+	SSR_DOMAIN_MODEM,
+	SSR_DOMAIN_MAX,
+};
+
+enum ldo_task {
+	ENABLE_LDO03,
+	ENABLE_LDO09,
+	DISABLE_LDO03,
+	DISABLE_LDO09
+};
+
+struct bgdaemon_regulator {
+	struct regulator *regldo03;
+	struct regulator *regldo09;
+};
+
+struct bgdaemon_priv {
+	struct bgdaemon_regulator rgltr;
+	enum ldo_task ldo_action;
+};
+
+struct bg_event {
+	enum bg_event_type e_type;
+};
+
+struct service_info {
+	const char                      name[32];
+	int                             domain_id;
+	void                            *handle;
+	struct notifier_block           *nb;
+};
+
+static char *ssr_domains[] = {
+	"bg-wear",
+	"modem",
+};
+
+static struct bgdaemon_priv *dev;
+static unsigned int bgreset_gpio;
+static  DEFINE_MUTEX(bg_char_mutex);
+static  struct cdev              bg_cdev;
+static  struct class             *bg_class;
+struct  device                   *dev_ret;
+static  dev_t                    bg_dev;
+static  int                      device_open;
+static  void                     *handle;
+static  struct   bgcom_open_config_type   config_type;
+static DECLARE_COMPLETION(bg_modem_down_wait);
+
+/**
+ * send_uevent(): send events to user space
+ * pce : ssr event handle value
+ * Return: 0 on success, standard Linux error code on error
+ *
+ * It adds pce value to event and broadcasts to user space.
+ */
+static int send_uevent(struct bg_event *pce)
+{
+	char event_string[32];
+	char *envp[2] = { event_string, NULL };
+
+	snprintf(event_string, ARRAY_SIZE(event_string),
+			"BG_EVENT=%d", pce->e_type);
+	return kobject_uevent_env(&dev_ret->kobj, KOBJ_CHANGE, envp);
+}
+
+static int bgdaemon_configure_regulators(bool state)
+{
+	int retval;
+
+	if (state == true) {
+		retval = regulator_enable(dev->rgltr.regldo03);
+		if (retval)
+			pr_err("Failed to enable LDO-03 regulator:%d\n",
+					retval);
+		retval = regulator_enable(dev->rgltr.regldo09);
+		if (retval)
+			pr_err("Failed to enable LDO-09 regulator:%d\n",
+					retval);
+	}
+	if (state == false) {
+		retval = regulator_disable(dev->rgltr.regldo03);
+		if (retval)
+			pr_err("Failed to disable LDO-03 regulator:%d\n",
+					retval);
+		retval = regulator_disable(dev->rgltr.regldo09);
+		if (retval)
+			pr_err("Failed to disable LDO-09 regulator:%d\n",
+					retval);
+	}
+	return retval;
+}
+static int bgdaemon_init_regulators(struct device *pdev)
+{
+	int rc;
+	struct regulator *reg03;
+	struct regulator *reg09;
+
+	reg03 = regulator_get(pdev, "ssr-reg1");
+	if (IS_ERR_OR_NULL(reg03)) {
+		rc = PTR_ERR(reg03);
+		pr_err("Unable to get regulator for LDO-03\n");
+		goto err_ret;
+	}
+	reg09 = regulator_get(pdev, "ssr-reg2");
+	if (IS_ERR_OR_NULL(reg09)) {
+		rc = PTR_ERR(reg09);
+		pr_err("Unable to get regulator for LDO-09\n");
+		goto err_ret;
+	}
+	dev->rgltr.regldo03 = reg03;
+	dev->rgltr.regldo09 = reg09;
+	return 0;
+err_ret:
+	return rc;
+}
+
+static int bgdaemon_ldowork(enum ldo_task do_action)
+{
+	int ret;
+
+	switch (do_action) {
+	case ENABLE_LDO03:
+		ret = regulator_set_load(dev->rgltr.regldo03,
+							BGDAEMON_LDO03_NPM_VTG);
+		if (ret < 0) {
+			pr_err("Failed to request LDO-03 voltage:%d\n",
+					ret);
+			goto err_ret;
+		}
+		break;
+	case ENABLE_LDO09:
+		ret = regulator_set_load(dev->rgltr.regldo09,
+							BGDAEMON_LDO09_NPM_VTG);
+		if (ret < 0) {
+			pr_err("Failed to request LDO-09 voltage:%d\n",
+					ret);
+			goto err_ret;
+		}
+		break;
+	case DISABLE_LDO03:
+		ret = regulator_set_load(dev->rgltr.regldo03,
+							BGDAEMON_LDO03_LPM_VTG);
+		if (ret < 0) {
+			pr_err("Failed to disable LDO-03:%d\n", ret);
+			goto err_ret;
+		}
+		break;
+	case DISABLE_LDO09:
+		ret = regulator_set_load(dev->rgltr.regldo09,
+							BGDAEMON_LDO09_LPM_VTG);
+		if (ret < 0) {
+			pr_err("Failed to disable LDO-09:%d\n", ret);
+			goto err_ret;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+err_ret:
+	return ret;
+}
+
+static int bgcom_char_open(struct inode *inode, struct file *file)
+{
+	int ret;
+
+	mutex_lock(&bg_char_mutex);
+	if (device_open == 1) {
+		pr_err("device is already open\n");
+		mutex_unlock(&bg_char_mutex);
+		return -EBUSY;
+	}
+	device_open++;
+	handle = bgcom_open(&config_type);
+	mutex_unlock(&bg_char_mutex);
+	if (IS_ERR(handle)) {
+		device_open = 0;
+		ret = PTR_ERR(handle);
+		handle = NULL;
+		return ret;
+	}
+	return 0;
+}
+
+static int bgchar_read_cmd(struct bg_ui_data *fui_obj_msg,
+		int type)
+{
+	void              *read_buf;
+	int               ret;
+	void __user       *result   = (void *)
+			(uintptr_t)fui_obj_msg->result;
+
+	read_buf = kmalloc_array(fui_obj_msg->num_of_words, sizeof(uint32_t),
+			GFP_KERNEL);
+	if (read_buf == NULL)
+		return -ENOMEM;
+	switch (type) {
+	case REG_READ:
+		ret = bgcom_reg_read(handle, fui_obj_msg->cmd,
+				fui_obj_msg->num_of_words,
+				read_buf);
+		break;
+	case AHB_READ:
+		ret = bgcom_ahb_read(handle,
+				fui_obj_msg->bg_address,
+				fui_obj_msg->num_of_words,
+				read_buf);
+		break;
+	}
+	if (!ret && copy_to_user(result, read_buf,
+			fui_obj_msg->num_of_words * sizeof(uint32_t))) {
+		pr_err("copy to user failed\n");
+		ret = -EFAULT;
+	}
+	kfree(read_buf);
+	return ret;
+}
+
+static int bgchar_write_cmd(struct bg_ui_data *fui_obj_msg, int type)
+{
+	void              *write_buf;
+	int               ret;
+	void __user       *write     = (void *)
+			(uintptr_t)fui_obj_msg->write;
+
+	write_buf = kmalloc_array(fui_obj_msg->num_of_words, sizeof(uint32_t),
+			GFP_KERNEL);
+	if (write_buf == NULL)
+		return -ENOMEM;
+	write_buf = memdup_user(write,
+			fui_obj_msg->num_of_words * sizeof(uint32_t));
+	if (IS_ERR(write_buf)) {
+		ret = PTR_ERR(write_buf);
+		kfree(write_buf);
+		return ret;
+	}
+	switch (type) {
+	case REG_WRITE:
+		ret = bgcom_reg_write(handle, fui_obj_msg->cmd,
+				fui_obj_msg->num_of_words,
+				write_buf);
+		break;
+	case AHB_WRITE:
+		ret = bgcom_ahb_write(handle,
+				fui_obj_msg->bg_address,
+				fui_obj_msg->num_of_words,
+				write_buf);
+		break;
+	}
+	kfree(write_buf);
+	return ret;
+}
+
+int bg_soft_reset(void)
+{
+	/*pull down reset gpio */
+	gpio_direction_output(bgreset_gpio, 0);
+	msleep(50);
+	gpio_set_value(bgreset_gpio, 1);
+	return 0;
+}
+EXPORT_SYMBOL(bg_soft_reset);
+
+static int modem_down2_bg(void)
+{
+	complete(&bg_modem_down_wait);
+	return 0;
+}
+
+static long bg_com_ioctl(struct file *filp,
+		unsigned int ui_bgcom_cmd, unsigned long arg)
+{
+	int ret;
+	struct bg_ui_data ui_obj_msg;
+
+	switch (ui_bgcom_cmd) {
+	case REG_READ:
+	case AHB_READ:
+		if (copy_from_user(&ui_obj_msg, (void __user *) arg,
+				sizeof(ui_obj_msg))) {
+			pr_err("The copy from user failed\n");
+			ret = -EFAULT;
+		}
+		ret = bgchar_read_cmd(&ui_obj_msg,
+				ui_bgcom_cmd);
+		if (ret < 0)
+			pr_err("bgchar_read_cmd failed\n");
+		break;
+	case AHB_WRITE:
+	case REG_WRITE:
+		if (copy_from_user(&ui_obj_msg, (void __user *) arg,
+				sizeof(ui_obj_msg))) {
+			pr_err("The copy from user failed\n");
+			ret = -EFAULT;
+		}
+		ret = bgchar_write_cmd(&ui_obj_msg, ui_bgcom_cmd);
+		if (ret < 0)
+			pr_err("bgchar_write_cmd failed\n");
+		break;
+	case SET_SPI_FREE:
+		ret = bgcom_set_spi_state(BGCOM_SPI_FREE);
+		break;
+	case SET_SPI_BUSY:
+		ret = bgcom_set_spi_state(BGCOM_SPI_BUSY);
+		break;
+	case BG_SOFT_RESET:
+		ret = bg_soft_reset();
+		break;
+	case BG_MODEM_DOWN2_BG_DONE:
+		ret = modem_down2_bg();
+		break;
+	default:
+		ret = -ENOIOCTLCMD;
+	}
+	return ret;
+}
+
+static int bgcom_char_close(struct inode *inode, struct file *file)
+{
+	int ret;
+
+	mutex_lock(&bg_char_mutex);
+	ret = bgcom_close(&handle);
+	device_open = 0;
+	mutex_unlock(&bg_char_mutex);
+	return ret;
+}
+
+static int bg_daemon_probe(struct platform_device *pdev)
+{
+	struct device_node *node;
+	unsigned int reset_gpio;
+	int ret;
+
+	node = pdev->dev.of_node;
+
+	dev = kzalloc(sizeof(struct bgdaemon_priv), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	reset_gpio = of_get_named_gpio(node, "qcom,bg-reset-gpio", 0);
+	if (!gpio_is_valid(reset_gpio)) {
+		pr_err("gpio %d found is not valid\n", reset_gpio);
+		goto err_ret;
+	}
+
+	if (gpio_request(reset_gpio, "bg_reset_gpio")) {
+		pr_err("gpio %d request failed\n", reset_gpio);
+		goto err_ret;
+	}
+
+	if (gpio_direction_output(reset_gpio, 1)) {
+		pr_err("gpio %d direction not set\n", reset_gpio);
+		goto err_ret;
+	}
+
+	pr_info("bg-soft-reset gpio successfully requested\n");
+	bgreset_gpio = reset_gpio;
+
+	ret = bgdaemon_init_regulators(&pdev->dev);
+	if (ret != 0) {
+		pr_err("Failed to init regulators:%d\n", ret);
+		goto err_device;
+	}
+	ret = bgdaemon_configure_regulators(true);
+	if (ret) {
+		pr_err("Failed to confifigure regulators:%d\n", ret);
+		bgdaemon_configure_regulators(false);
+		goto err_ret;
+	}
+
+err_device:
+	return -ENODEV;
+err_ret:
+	return 0;
+}
+
+static const struct of_device_id bg_daemon_of_match[] = {
+	{ .compatible = "qcom,bg-daemon", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, bg_daemon_of_match);
+
+static struct platform_driver bg_daemon_driver = {
+	.probe  = bg_daemon_probe,
+	.driver = {
+		.name = "bg-daemon",
+		.of_match_table = bg_daemon_of_match,
+	},
+};
+
+static const struct file_operations fops = {
+	.owner          = THIS_MODULE,
+	.open           = bgcom_char_open,
+	.release        = bgcom_char_close,
+	.unlocked_ioctl = bg_com_ioctl,
+};
+
+static int __init init_bg_com_dev(void)
+{
+	int ret;
+
+	ret = alloc_chrdev_region(&bg_dev, 0, 1, BGCOM);
+	if (ret  < 0) {
+		pr_err("failed with error %d\n", ret);
+		return ret;
+	}
+	cdev_init(&bg_cdev, &fops);
+	ret = cdev_add(&bg_cdev, bg_dev, 1);
+	if (ret < 0) {
+		unregister_chrdev_region(bg_dev, 1);
+		pr_err("device registration failed\n");
+		return ret;
+	}
+	bg_class = class_create(THIS_MODULE, BGCOM);
+	if (IS_ERR_OR_NULL(bg_class)) {
+		cdev_del(&bg_cdev);
+		unregister_chrdev_region(bg_dev, 1);
+		pr_err("class creation failed\n");
+		return PTR_ERR(bg_class);
+	}
+
+	dev_ret = device_create(bg_class, NULL, bg_dev, NULL, BGCOM);
+	if (IS_ERR_OR_NULL(dev_ret)) {
+		class_destroy(bg_class);
+		cdev_del(&bg_cdev);
+		unregister_chrdev_region(bg_dev, 1);
+		pr_err("device create failed\n");
+		return PTR_ERR(dev_ret);
+	}
+
+	if (platform_driver_register(&bg_daemon_driver))
+		pr_err("%s: failed to register bg-daemon register\n", __func__);
+
+	return 0;
+}
+
+static void __exit exit_bg_com_dev(void)
+{
+	device_destroy(bg_class, bg_dev);
+	class_destroy(bg_class);
+	cdev_del(&bg_cdev);
+	unregister_chrdev_region(bg_dev, 1);
+	bgdaemon_configure_regulators(false);
+	platform_driver_unregister(&bg_daemon_driver);
+}
+
+/**
+ *ssr_bg_cb(): callback function is called
+ *by ssr framework when BG goes down, up and during ramdump
+ *collection. It handles BG shutdown and power up events.
+ */
+static int ssr_bg_cb(struct notifier_block *this,
+		unsigned long opcode, void *data)
+{
+	struct bg_event bge;
+
+	switch (opcode) {
+	case SUBSYS_BEFORE_SHUTDOWN:
+		bge.e_type = BG_BEFORE_POWER_DOWN;
+		bgdaemon_ldowork(ENABLE_LDO03);
+		bgdaemon_ldowork(ENABLE_LDO09);
+		bgcom_bgdown_handler();
+		bgcom_set_spi_state(BGCOM_SPI_BUSY);
+		send_uevent(&bge);
+		break;
+	case SUBSYS_AFTER_POWERUP:
+		bge.e_type = BG_AFTER_POWER_UP;
+		bgdaemon_ldowork(DISABLE_LDO03);
+		bgdaemon_ldowork(DISABLE_LDO09);
+		bgcom_set_spi_state(BGCOM_SPI_FREE);
+		send_uevent(&bge);
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+/**
+ *ssr_modem_cb(): callback function is called
+ *by ssr framework when modem goes down, up and during ramdump
+ *collection. It handles modem shutdown and power up events.
+ */
+static int ssr_modem_cb(struct notifier_block *this,
+		unsigned long opcode, void *data)
+{
+	struct bg_event modeme;
+	int ret;
+
+	switch (opcode) {
+	case SUBSYS_BEFORE_SHUTDOWN:
+		modeme.e_type = MODEM_BEFORE_POWER_DOWN;
+		reinit_completion(&bg_modem_down_wait);
+		send_uevent(&modeme);
+		ret = wait_for_completion_timeout(&bg_modem_down_wait,
+			msecs_to_jiffies(MPPS_DOWN_EVENT_TO_BG_TIMEOUT));
+		if (!ret)
+			pr_err("Time out on modem down event\n");
+		break;
+	case SUBSYS_AFTER_POWERUP:
+		modeme.e_type = MODEM_AFTER_POWER_UP;
+		send_uevent(&modeme);
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block ssr_modem_nb = {
+	.notifier_call = ssr_modem_cb,
+	.priority = 0,
+};
+
+static struct notifier_block ssr_bg_nb = {
+	.notifier_call = ssr_bg_cb,
+	.priority = 0,
+};
+
+static struct service_info service_data[2] = {
+	{
+		.name = "SSR_BG",
+		.domain_id = SSR_DOMAIN_BG,
+		.nb = &ssr_bg_nb,
+		.handle = NULL,
+	},
+	{
+		.name = "SSR_MODEM",
+		.domain_id = SSR_DOMAIN_MODEM,
+		.nb = &ssr_modem_nb,
+		.handle = NULL,
+	},
+};
+
+/**
+ * ssr_register checks that domain id should be in range and register
+ * SSR framework for value at domain id.
+ */
+static int __init ssr_register(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(service_data); i++) {
+		if ((service_data[i].domain_id < 0) ||
+				(service_data[i].domain_id >= SSR_DOMAIN_MAX)) {
+			pr_err("Invalid service ID = %d\n",
+					service_data[i].domain_id);
+		} else {
+			service_data[i].handle =
+					subsys_notif_register_notifier(
+					ssr_domains[service_data[i].domain_id],
+					service_data[i].nb);
+			if (IS_ERR_OR_NULL(service_data[i].handle)) {
+				pr_err("subsys register failed for id = %d",
+						service_data[i].domain_id);
+				service_data[i].handle = NULL;
+			}
+		}
+	}
+	return 0;
+}
+
+module_init(init_bg_com_dev);
+late_initcall(ssr_register);
+module_exit(exit_bg_com_dev);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/bgcom_interface.h b/drivers/soc/qcom/bgcom_interface.h
new file mode 100644
index 0000000..500ca6d
--- /dev/null
+++ b/drivers/soc/qcom/bgcom_interface.h
@@ -0,0 +1,22 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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 BGCOM_INTERFACE_H
+#define BGCOM_INTERFACE_H
+
+/**
+ * bg_soft_reset() - soft reset Blackghost
+ * Return 0 on success or -Ve on error
+ */
+int bg_soft_reset(void);
+
+#endif /* BGCOM_INTERFACE_H */
diff --git a/drivers/soc/qcom/bgcom_spi.c b/drivers/soc/qcom/bgcom_spi.c
new file mode 100644
index 0000000..b8e3b84
--- /dev/null
+++ b/drivers/soc/qcom/bgcom_spi.c
@@ -0,0 +1,1010 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(msg) "bgcom: %s: " msg, __func__
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/ratelimit.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/kthread.h>
+#include "bgcom.h"
+#include "bgrsb.h"
+#include "bgcom_interface.h"
+
+#define BG_SPI_WORD_SIZE (0x04)
+#define BG_SPI_READ_LEN (0x04)
+#define BG_SPI_WRITE_CMND_LEN (0x01)
+#define BG_SPI_FIFO_READ_CMD (0x41)
+#define BG_SPI_FIFO_WRITE_CMD (0x40)
+#define BG_SPI_AHB_READ_CMD (0x43)
+#define BG_SPI_AHB_WRITE_CMD (0x42)
+#define BG_SPI_AHB_CMD_LEN (0x05)
+#define BG_SPI_AHB_READ_CMD_LEN (0x08)
+#define BG_STATUS_REG (0x05)
+#define BG_CMND_REG (0x14)
+
+#define BG_SPI_MAX_WORDS (0x3FFFFFFD)
+#define BG_SPI_MAX_REGS (0x0A)
+#define SLEEP_IN_STATE_CHNG 2000
+#define HED_EVENT_ID_LEN (0x02)
+#define HED_EVENT_SIZE_LEN (0x02)
+#define HED_EVENT_DATA_STRT_LEN (0x05)
+
+#define MAX_RETRY 200
+
+enum bgcom_state {
+	/*BGCOM Staus ready*/
+	BGCOM_PROB_SUCCESS = 0,
+	BGCOM_PROB_WAIT = 1,
+	BGCOM_STATE_SUSPEND = 2,
+	BGCOM_STATE_ACTIVE = 3
+};
+
+enum bgcom_req_type {
+	/*BGCOM local requests*/
+	BGCOM_READ_REG = 0,
+	BGCOM_READ_FIFO = 1,
+	BGCOM_READ_AHB = 2,
+};
+
+struct bg_spi_priv {
+	struct spi_device *spi;
+	/* Transaction related */
+	struct mutex xfer_mutex;
+	void *lhandle;
+	/* Message for single transfer */
+	struct spi_message msg1;
+	struct spi_transfer xfer1;
+	int irq_lock;
+
+	enum bgcom_state bg_state;
+};
+
+struct cb_data {
+	void *priv;
+	void *handle;
+	void (*bgcom_notification_cb)(void *handle, void *priv,
+		enum bgcom_event_type event,
+		union bgcom_event_data_type *event_data);
+	struct list_head list;
+};
+
+struct bg_context {
+	struct bg_spi_priv *bg_spi;
+	enum bgcom_state state;
+	struct cb_data *cb;
+};
+
+struct event_list {
+	struct event *evnt;
+	struct list_head list;
+};
+static void *bg_com_drv;
+static uint32_t g_slav_status_reg;
+
+/* BGCOM client callbacks set-up */
+static void send_input_events(struct work_struct *work);
+static struct list_head cb_head = LIST_HEAD_INIT(cb_head);
+static struct list_head pr_lst_hd = LIST_HEAD_INIT(pr_lst_hd);
+static enum bgcom_spi_state spi_state;
+
+
+static struct workqueue_struct *wq;
+static DECLARE_WORK(input_work, send_input_events);
+
+static struct mutex bg_resume_mutex;
+
+static void augmnt_fifo(uint8_t *data, int pos)
+{
+	data[pos] = '\0';
+}
+
+static void send_input_events(struct work_struct *work)
+{
+	struct list_head *temp;
+	struct list_head *pos;
+	struct event_list *node;
+	struct event *evnt;
+
+	if (list_empty(&pr_lst_hd))
+		return;
+
+	list_for_each_safe(pos, temp, &pr_lst_hd) {
+		node = list_entry(pos, struct event_list, list);
+		evnt = node->evnt;
+		bgrsb_send_input(evnt);
+		kfree(evnt);
+		list_del(&node->list);
+		kfree(node);
+	}
+}
+
+int bgcom_set_spi_state(enum bgcom_spi_state state)
+{
+	struct bg_spi_priv *bg_spi = container_of(bg_com_drv,
+						struct bg_spi_priv, lhandle);
+	if (state < 0 || state > 1)
+		return -EINVAL;
+
+	if (state == spi_state)
+		return 0;
+
+	mutex_lock(&bg_spi->xfer_mutex);
+	spi_state = state;
+	if (spi_state == BGCOM_SPI_BUSY)
+		msleep(SLEEP_IN_STATE_CHNG);
+	mutex_unlock(&bg_spi->xfer_mutex);
+	return 0;
+}
+EXPORT_SYMBOL(bgcom_set_spi_state);
+
+static inline
+void add_to_irq_list(struct  cb_data *data)
+{
+	list_add_tail(&data->list, &cb_head);
+}
+
+static bool is_bgcom_ready(void)
+{
+	return (bg_com_drv != NULL ? true : false);
+}
+
+static void bg_spi_reinit_xfer(struct spi_transfer *xfer)
+{
+	xfer->tx_buf = NULL;
+	xfer->rx_buf = NULL;
+	xfer->delay_usecs = 0;
+	xfer->len = 0;
+}
+
+static int read_bg_locl(enum bgcom_req_type req_type,
+	uint32_t no_of_words, void *buf)
+{
+
+	struct bg_context clnt_handle;
+	struct bg_spi_priv *spi =
+			container_of(bg_com_drv, struct bg_spi_priv, lhandle);
+	int ret = 0;
+
+	if (!buf)
+		return -EINVAL;
+
+	clnt_handle.bg_spi = spi;
+
+	switch (req_type) {
+	case BGCOM_READ_REG:
+		ret = bgcom_reg_read(&clnt_handle,
+			BG_STATUS_REG, no_of_words, buf);
+		break;
+	case BGCOM_READ_FIFO:
+		ret = bgcom_fifo_read(&clnt_handle, no_of_words, buf);
+		break;
+	case BGCOM_READ_AHB:
+		break;
+	}
+	return ret;
+}
+
+static int bgcom_transfer(void *handle, uint8_t *tx_buf,
+	uint8_t *rx_buf, uint32_t txn_len)
+{
+	struct spi_transfer *tx_xfer;
+	struct bg_spi_priv *bg_spi;
+	struct bg_context *cntx;
+	struct spi_device *spi;
+	int ret;
+
+	if (!handle || !tx_buf)
+		return -EINVAL;
+
+	cntx = (struct bg_context *)handle;
+
+	if (cntx->state == BGCOM_PROB_WAIT) {
+		if (!is_bgcom_ready())
+			return -ENODEV;
+		cntx->bg_spi = container_of(bg_com_drv,
+						struct bg_spi_priv, lhandle);
+		cntx->state = BGCOM_PROB_SUCCESS;
+	}
+	bg_spi = cntx->bg_spi;
+
+	if (!bg_spi)
+		return -ENODEV;
+
+	tx_xfer = &bg_spi->xfer1;
+	spi = bg_spi->spi;
+
+	mutex_lock(&bg_spi->xfer_mutex);
+	bg_spi_reinit_xfer(tx_xfer);
+	tx_xfer->tx_buf = tx_buf;
+	if (rx_buf)
+		tx_xfer->rx_buf = rx_buf;
+
+	tx_xfer->len = txn_len;
+	ret = spi_sync(spi, &bg_spi->msg1);
+	mutex_unlock(&bg_spi->xfer_mutex);
+
+	if (ret)
+		pr_err("SPI transaction failed: %d\n", ret);
+	return ret;
+}
+
+/* BG-COM Interrupt handling */
+static inline
+void send_event(enum bgcom_event_type event,
+	void *data)
+{
+	struct list_head *pos;
+	struct cb_data *cb;
+
+	/* send interrupt notification for each
+	 * registered call-back
+	 */
+	list_for_each(pos, &cb_head) {
+		cb = list_entry(pos, struct cb_data, list);
+		cb->bgcom_notification_cb(cb->handle,
+		cb->priv,  event, data);
+	}
+}
+
+void bgcom_bgdown_handler(void)
+{
+	send_event(BGCOM_EVENT_RESET_OCCURRED, NULL);
+	g_slav_status_reg = 0;
+}
+EXPORT_SYMBOL(bgcom_bgdown_handler);
+
+static void parse_fifo(uint8_t *data, union bgcom_event_data_type *event_data)
+{
+	uint16_t p_len;
+	uint8_t sub_id;
+	uint32_t evnt_tm;
+	uint16_t event_id;
+	void *evnt_data;
+	struct event *evnt;
+	struct event_list *data_list;
+
+	while (*data != '\0') {
+
+		event_id = *((uint16_t *) data);
+		data = data + HED_EVENT_ID_LEN;
+		p_len = *((uint16_t *) data);
+		data = data + HED_EVENT_SIZE_LEN;
+
+		if (event_id == 0xFFFE) {
+
+			sub_id = *data;
+			evnt_tm = *((uint32_t *)(data+1));
+
+			evnt = kmalloc(sizeof(*evnt), GFP_KERNEL);
+			evnt->sub_id = sub_id;
+			evnt->evnt_tm = evnt_tm;
+			evnt->evnt_data =
+				*(int16_t *)(data + HED_EVENT_DATA_STRT_LEN);
+
+			data_list = kmalloc(sizeof(*data_list), GFP_KERNEL);
+			data_list->evnt = evnt;
+			list_add_tail(&data_list->list, &pr_lst_hd);
+
+		} else if (event_id == 0x0001) {
+			evnt_data = kmalloc(p_len, GFP_KERNEL);
+			if (evnt_data != NULL) {
+				memcpy(evnt_data, data, p_len);
+				event_data->fifo_data.to_master_fifo_used =
+						p_len/BG_SPI_WORD_SIZE;
+				event_data->fifo_data.data = evnt_data;
+				send_event(BGCOM_EVENT_TO_MASTER_FIFO_USED,
+						event_data);
+			}
+		}
+		data = data + p_len;
+	}
+	if (!list_empty(&pr_lst_hd))
+		queue_work(wq, &input_work);
+}
+
+static void send_back_notification(uint32_t slav_status_reg,
+	uint32_t slav_status_auto_clear_reg,
+	uint32_t fifo_fill_reg, uint32_t fifo_size_reg)
+{
+	uint16_t master_fifo_used;
+	uint16_t slave_fifo_free;
+	uint32_t *ptr;
+	int ret;
+	union bgcom_event_data_type event_data = { .fifo_data = {0} };
+
+	master_fifo_used = (uint16_t)fifo_fill_reg;
+	slave_fifo_free = (uint16_t)(fifo_fill_reg >> 16);
+
+	if (slav_status_auto_clear_reg & BIT(31))
+		send_event(BGCOM_EVENT_RESET_OCCURRED, NULL);
+
+	if (slav_status_auto_clear_reg & BIT(30))
+		send_event(BGCOM_EVENT_ERROR_WRITE_FIFO_OVERRUN, NULL);
+
+	if (slav_status_auto_clear_reg & BIT(29))
+		send_event(BGCOM_EVENT_ERROR_WRITE_FIFO_BUS_ERR, NULL);
+
+	if (slav_status_auto_clear_reg & BIT(28))
+		send_event(BGCOM_EVENT_ERROR_WRITE_FIFO_ACCESS, NULL);
+
+	if (slav_status_auto_clear_reg & BIT(27))
+		send_event(BGCOM_EVENT_ERROR_READ_FIFO_UNDERRUN, NULL);
+
+	if (slav_status_auto_clear_reg & BIT(26))
+		send_event(BGCOM_EVENT_ERROR_READ_FIFO_BUS_ERR, NULL);
+
+	if (slav_status_auto_clear_reg & BIT(25))
+		send_event(BGCOM_EVENT_ERROR_READ_FIFO_ACCESS, NULL);
+
+	if (slav_status_auto_clear_reg & BIT(24))
+		send_event(BGCOM_EVENT_ERROR_TRUNCATED_READ, NULL);
+
+	if (slav_status_auto_clear_reg & BIT(23))
+		send_event(BGCOM_EVENT_ERROR_TRUNCATED_WRITE, NULL);
+
+	if (slav_status_auto_clear_reg & BIT(22))
+		send_event(BGCOM_EVENT_ERROR_AHB_ILLEGAL_ADDRESS, NULL);
+
+	if (slav_status_auto_clear_reg & BIT(21))
+		send_event(BGCOM_EVENT_ERROR_AHB_BUS_ERR, NULL);
+
+	/* check if BG status is changed */
+	if (g_slav_status_reg ^ slav_status_reg) {
+		if (slav_status_reg & BIT(30)) {
+			event_data.application_running = true;
+			send_event(BGCOM_EVENT_APPLICATION_RUNNING,
+				&event_data);
+		}
+
+		if (slav_status_reg & BIT(29)) {
+			event_data.to_slave_fifo_ready = true;
+			send_event(BGCOM_EVENT_TO_SLAVE_FIFO_READY,
+				&event_data);
+		}
+
+		if (slav_status_reg & BIT(28)) {
+			event_data.to_master_fifo_ready = true;
+			send_event(BGCOM_EVENT_TO_MASTER_FIFO_READY,
+				&event_data);
+		}
+
+		if (slav_status_reg & BIT(27)) {
+			event_data.ahb_ready = true;
+			send_event(BGCOM_EVENT_AHB_READY,
+				&event_data);
+		}
+	}
+
+	if (master_fifo_used > 0) {
+		ptr = kzalloc(master_fifo_used*BG_SPI_WORD_SIZE + 1,
+			GFP_KERNEL | GFP_ATOMIC);
+		if (ptr != NULL) {
+			ret = read_bg_locl(BGCOM_READ_FIFO,
+				master_fifo_used,  ptr);
+			if (!ret) {
+				augmnt_fifo((uint8_t *)ptr,
+					master_fifo_used*BG_SPI_WORD_SIZE);
+				parse_fifo((uint8_t *)ptr, &event_data);
+			}
+			kfree(ptr);
+		}
+	}
+
+	event_data.to_slave_fifo_free = slave_fifo_free;
+	send_event(BGCOM_EVENT_TO_SLAVE_FIFO_FREE, &event_data);
+}
+
+static void bg_irq_tasklet_hndlr_l(void)
+{
+	uint32_t slave_status_reg;
+	uint32_t glink_isr_reg;
+	uint32_t slav_status_auto_clear_reg;
+	uint32_t fifo_fill_reg;
+	uint32_t fifo_size_reg;
+	int ret =  0;
+	uint32_t irq_buf[5] = {0};
+
+	ret = read_bg_locl(BGCOM_READ_REG, 5, &irq_buf[0]);
+	if (ret)
+		return;
+
+	/* save current state */
+	slave_status_reg = irq_buf[0];
+	glink_isr_reg = irq_buf[1];
+	slav_status_auto_clear_reg = irq_buf[2];
+	fifo_fill_reg = irq_buf[3];
+	fifo_size_reg = irq_buf[4];
+
+	send_back_notification(slave_status_reg,
+		slav_status_auto_clear_reg, fifo_fill_reg, fifo_size_reg);
+
+	g_slav_status_reg = slave_status_reg;
+}
+
+int bgcom_ahb_read(void *handle, uint32_t ahb_start_addr,
+	uint32_t num_words, void *read_buf)
+{
+	uint32_t txn_len;
+	uint8_t *tx_buf;
+	uint8_t *rx_buf;
+	uint32_t size;
+	int ret;
+	uint8_t cmnd = 0;
+	uint32_t ahb_addr = 0;
+
+	if (!handle || !read_buf || num_words == 0
+		|| num_words > BG_SPI_MAX_WORDS) {
+		pr_err("Invalid param\n");
+		return -EINVAL;
+	}
+	if (!is_bgcom_ready())
+		return -ENODEV;
+
+	if (spi_state == BGCOM_SPI_BUSY) {
+		pr_err("Device busy\n");
+		return -EBUSY;
+	}
+
+	if (bgcom_resume(handle)) {
+		pr_err("Failed to resume\n");
+		return -EBUSY;
+	}
+
+	size = num_words*BG_SPI_WORD_SIZE;
+	txn_len = BG_SPI_AHB_READ_CMD_LEN + size;
+
+	tx_buf = kzalloc(txn_len, GFP_KERNEL);
+
+	if (!tx_buf)
+		return -ENOMEM;
+
+	rx_buf = kzalloc(txn_len, GFP_KERNEL);
+
+	if (!rx_buf) {
+		kfree(tx_buf);
+		return -ENOMEM;
+	}
+
+	cmnd |= BG_SPI_AHB_READ_CMD;
+	ahb_addr |= ahb_start_addr;
+
+	memcpy(tx_buf, &cmnd, sizeof(cmnd));
+	memcpy(tx_buf+sizeof(cmnd), &ahb_addr, sizeof(ahb_addr));
+
+	ret = bgcom_transfer(handle, tx_buf, rx_buf, txn_len);
+
+	if (!ret)
+		memcpy(read_buf, rx_buf+BG_SPI_AHB_READ_CMD_LEN, size);
+
+	kfree(tx_buf);
+	kfree(rx_buf);
+	return ret;
+}
+EXPORT_SYMBOL(bgcom_ahb_read);
+
+int bgcom_ahb_write(void *handle, uint32_t ahb_start_addr,
+	uint32_t num_words, void *write_buf)
+{
+	uint32_t txn_len;
+	uint8_t *tx_buf;
+	uint32_t size;
+	int ret;
+	uint8_t cmnd = 0;
+	uint32_t ahb_addr = 0;
+
+	if (!handle || !write_buf || num_words == 0
+		|| num_words > BG_SPI_MAX_WORDS) {
+		pr_err("Invalid param\n");
+		return -EINVAL;
+	}
+
+	if (!is_bgcom_ready())
+		return -ENODEV;
+
+	if (spi_state == BGCOM_SPI_BUSY) {
+		pr_err("Device busy\n");
+		return -EBUSY;
+	}
+
+	if (bgcom_resume(handle)) {
+		pr_err("Failed to resume\n");
+		return -EBUSY;
+	}
+
+	size = num_words*BG_SPI_WORD_SIZE;
+	txn_len = BG_SPI_AHB_CMD_LEN + size;
+
+	tx_buf = kzalloc(txn_len, GFP_KERNEL);
+
+	if (!tx_buf)
+		return -ENOMEM;
+
+	cmnd |= BG_SPI_AHB_WRITE_CMD;
+	ahb_addr |= ahb_start_addr;
+
+	memcpy(tx_buf, &cmnd, sizeof(cmnd));
+	memcpy(tx_buf+sizeof(cmnd), &ahb_addr, sizeof(ahb_addr));
+	memcpy(tx_buf+BG_SPI_AHB_CMD_LEN, write_buf, size);
+
+	ret = bgcom_transfer(handle, tx_buf, NULL, txn_len);
+	kfree(tx_buf);
+	return ret;
+}
+EXPORT_SYMBOL(bgcom_ahb_write);
+
+int bgcom_fifo_write(void *handle, uint32_t num_words,
+	void  *write_buf)
+{
+	uint32_t txn_len;
+	uint8_t *tx_buf;
+	uint32_t size;
+	int ret;
+	uint8_t cmnd = 0;
+
+	if (!handle || !write_buf || num_words == 0
+		|| num_words > BG_SPI_MAX_WORDS) {
+		pr_err("Invalid param\n");
+		return -EINVAL;
+	}
+
+	if (!is_bgcom_ready())
+		return -ENODEV;
+
+	if (spi_state == BGCOM_SPI_BUSY) {
+		pr_err("Device busy\n");
+		return -EBUSY;
+	}
+
+	if (bgcom_resume(handle)) {
+		pr_err("Failed to resume\n");
+		return -EBUSY;
+	}
+
+	size = num_words*BG_SPI_WORD_SIZE;
+	txn_len = BG_SPI_WRITE_CMND_LEN + size;
+
+	tx_buf = kzalloc(txn_len, GFP_KERNEL | GFP_ATOMIC);
+
+	if (!tx_buf)
+		return -ENOMEM;
+
+	cmnd |= BG_SPI_FIFO_WRITE_CMD;
+	memcpy(tx_buf, &cmnd, sizeof(cmnd));
+	memcpy(tx_buf+sizeof(cmnd), write_buf, size);
+
+	ret = bgcom_transfer(handle, tx_buf, NULL, txn_len);
+	kfree(tx_buf);
+	return ret;
+}
+EXPORT_SYMBOL(bgcom_fifo_write);
+
+int bgcom_fifo_read(void *handle, uint32_t num_words,
+	void *read_buf)
+{
+	uint32_t txn_len;
+	uint8_t *tx_buf;
+	uint8_t *rx_buf;
+	uint32_t size;
+	uint8_t cmnd = 0;
+	int ret =  0;
+
+	if (!handle || !read_buf || num_words == 0
+		|| num_words > BG_SPI_MAX_WORDS) {
+		pr_err("Invalid param\n");
+		return -EINVAL;
+	}
+
+	if (!is_bgcom_ready())
+		return -ENODEV;
+
+	if (spi_state == BGCOM_SPI_BUSY) {
+		pr_err("Device busy\n");
+		return -EBUSY;
+	}
+
+	size = num_words*BG_SPI_WORD_SIZE;
+	txn_len = BG_SPI_READ_LEN + size;
+	tx_buf = kzalloc(txn_len, GFP_KERNEL | GFP_ATOMIC);
+
+	if (!tx_buf)
+		return -ENOMEM;
+
+	rx_buf = kzalloc(txn_len, GFP_KERNEL | GFP_ATOMIC);
+
+	if (!rx_buf) {
+		kfree(tx_buf);
+		return -ENOMEM;
+	}
+
+	cmnd |= BG_SPI_FIFO_READ_CMD;
+	memcpy(tx_buf, &cmnd, sizeof(cmnd));
+
+	ret = bgcom_transfer(handle, tx_buf, rx_buf, txn_len);
+
+	if (!ret)
+		memcpy(read_buf, rx_buf+BG_SPI_READ_LEN, size);
+	kfree(tx_buf);
+	kfree(rx_buf);
+	return ret;
+}
+EXPORT_SYMBOL(bgcom_fifo_read);
+
+int bgcom_reg_write(void *handle, uint8_t reg_start_addr,
+	uint8_t num_regs, void *write_buf)
+{
+	uint32_t txn_len;
+	uint8_t *tx_buf;
+	uint32_t size;
+	uint8_t cmnd = 0;
+	int ret =  0;
+
+	if (!handle || !write_buf || num_regs == 0
+		|| num_regs > BG_SPI_MAX_REGS) {
+		pr_err("Invalid param\n");
+		return -EINVAL;
+	}
+
+	if (!is_bgcom_ready())
+		return -ENODEV;
+
+	if (spi_state == BGCOM_SPI_BUSY) {
+		pr_err("Device busy\n");
+		return -EBUSY;
+	}
+
+	size = num_regs*BG_SPI_WORD_SIZE;
+	txn_len = BG_SPI_WRITE_CMND_LEN + size;
+
+	tx_buf = kzalloc(txn_len, GFP_KERNEL);
+
+	if (!tx_buf)
+		return -ENOMEM;
+
+	cmnd |= reg_start_addr;
+	memcpy(tx_buf, &cmnd, sizeof(cmnd));
+	memcpy(tx_buf+sizeof(cmnd), write_buf, size);
+
+	ret = bgcom_transfer(handle, tx_buf, NULL, txn_len);
+	kfree(tx_buf);
+	return ret;
+}
+EXPORT_SYMBOL(bgcom_reg_write);
+
+int bgcom_reg_read(void *handle, uint8_t reg_start_addr,
+	uint32_t num_regs, void *read_buf)
+{
+	uint32_t txn_len;
+	uint8_t *tx_buf;
+	uint8_t *rx_buf;
+	uint32_t size;
+	int ret;
+	uint8_t cmnd = 0;
+
+	if (!handle || !read_buf || num_regs == 0
+		|| num_regs > BG_SPI_MAX_REGS) {
+		pr_err("Invalid param\n");
+		return -EINVAL;
+	}
+
+	if (!is_bgcom_ready())
+		return -ENODEV;
+
+	if (spi_state == BGCOM_SPI_BUSY) {
+		pr_err("Device busy\n");
+		return -EBUSY;
+	}
+
+	size = num_regs*BG_SPI_WORD_SIZE;
+	txn_len = BG_SPI_READ_LEN + size;
+
+	tx_buf = kzalloc(txn_len, GFP_KERNEL | GFP_ATOMIC);
+
+	if (!tx_buf)
+		return -ENOMEM;
+
+	rx_buf = kzalloc(txn_len, GFP_KERNEL | GFP_ATOMIC);
+
+	if (!rx_buf) {
+		kfree(tx_buf);
+		return -ENOMEM;
+	}
+
+	cmnd |= reg_start_addr;
+	memcpy(tx_buf, &cmnd, sizeof(cmnd));
+
+	ret = bgcom_transfer(handle, tx_buf, rx_buf, txn_len);
+
+	if (!ret)
+		memcpy(read_buf, rx_buf+BG_SPI_READ_LEN, size);
+	kfree(tx_buf);
+	kfree(rx_buf);
+	return ret;
+}
+EXPORT_SYMBOL(bgcom_reg_read);
+
+static int is_bg_resume(void *handle)
+{
+	uint32_t txn_len;
+	int ret;
+	uint8_t tx_buf[8] = {0};
+	uint8_t rx_buf[8] = {0};
+	uint32_t cmnd_reg = 0;
+
+	txn_len = 0x08;
+	tx_buf[0] = 0x05;
+	ret = bgcom_transfer(handle, tx_buf, rx_buf, txn_len);
+	if (!ret)
+		memcpy(&cmnd_reg, rx_buf+BG_SPI_READ_LEN, 0x04);
+	return cmnd_reg & BIT(31);
+}
+
+int bgcom_resume(void *handle)
+{
+	struct bg_spi_priv *bg_spi;
+	struct bg_context *cntx;
+	int retry = 0;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	cntx = (struct bg_context *)handle;
+	bg_spi = cntx->bg_spi;
+
+	mutex_lock(&bg_resume_mutex);
+	if (bg_spi->bg_state == BGCOM_STATE_ACTIVE)
+		goto unlock;
+	do {
+		if (is_bg_resume(handle)) {
+			bg_spi->bg_state = BGCOM_STATE_ACTIVE;
+			break;
+		}
+		udelay(10);
+		++retry;
+	} while (retry < MAX_RETRY);
+
+unlock:
+	mutex_unlock(&bg_resume_mutex);
+	if (retry == MAX_RETRY) {
+		/* BG failed to resume. Trigger BG soft reset. */
+		pr_err("BG failed to resume\n");
+		bg_soft_reset();
+		return -ETIMEDOUT;
+	}
+	pr_info("BG retries for wake up : %d\n", retry);
+	return 0;
+}
+EXPORT_SYMBOL(bgcom_resume);
+
+int bgcom_suspend(void *handle)
+{
+	struct bg_spi_priv *bg_spi;
+	struct bg_context *cntx;
+	uint32_t cmnd_reg = 0;
+	int ret = 0;
+
+	if (handle == NULL)
+		return -EINVAL;
+
+	cntx = (struct bg_context *)handle;
+	bg_spi = cntx->bg_spi;
+	mutex_lock(&bg_resume_mutex);
+	if (bg_spi->bg_state == BGCOM_STATE_SUSPEND)
+		goto unlock;
+
+	cmnd_reg |= BIT(31);
+	ret = bgcom_reg_write(handle, BG_CMND_REG, 1, &cmnd_reg);
+	if (ret == 0)
+		bg_spi->bg_state = BGCOM_STATE_SUSPEND;
+
+unlock:
+	mutex_unlock(&bg_resume_mutex);
+	pr_info("suspended with : %d\n", ret);
+	return ret;
+}
+EXPORT_SYMBOL(bgcom_suspend);
+
+void *bgcom_open(struct bgcom_open_config_type *open_config)
+{
+	struct bg_spi_priv *spi;
+	struct cb_data *irq_notification;
+	struct bg_context  *clnt_handle =
+			kzalloc(sizeof(*clnt_handle), GFP_KERNEL);
+
+	if (!clnt_handle)
+		return NULL;
+
+	/* Client handle Set-up */
+	if (!is_bgcom_ready()) {
+		clnt_handle->bg_spi = NULL;
+		clnt_handle->state = BGCOM_PROB_WAIT;
+	} else {
+		spi = container_of(bg_com_drv, struct bg_spi_priv, lhandle);
+		clnt_handle->bg_spi = spi;
+		clnt_handle->state = BGCOM_PROB_SUCCESS;
+	}
+	clnt_handle->cb = NULL;
+	/* Interrupt callback Set-up */
+	if (open_config && open_config->bgcom_notification_cb) {
+		irq_notification = kzalloc(sizeof(*irq_notification),
+			GFP_KERNEL);
+		if (!irq_notification)
+			goto error_ret;
+
+		/* set irq node */
+		irq_notification->handle = clnt_handle;
+		irq_notification->priv = open_config->priv;
+		irq_notification->bgcom_notification_cb =
+					open_config->bgcom_notification_cb;
+		add_to_irq_list(irq_notification);
+		clnt_handle->cb = irq_notification;
+	}
+	return clnt_handle;
+
+error_ret:
+	kfree(clnt_handle);
+	return NULL;
+}
+EXPORT_SYMBOL(bgcom_open);
+
+int bgcom_close(void **handle)
+{
+	struct bg_context *lhandle;
+	struct cb_data *cb = NULL;
+
+	if (*handle == NULL)
+		return -EINVAL;
+	lhandle = *handle;
+	cb = lhandle->cb;
+	if (cb)
+		list_del(&cb->list);
+
+	kfree(*handle);
+	*handle = NULL;
+	return 0;
+}
+EXPORT_SYMBOL(bgcom_close);
+
+static irqreturn_t bg_irq_tasklet_hndlr(int irq, void *device)
+{
+	struct bg_spi_priv *bg_spi = device;
+	/* check if call-back exists */
+	if (list_empty(&cb_head)) {
+		pr_debug("No callback registered\n");
+		return IRQ_HANDLED;
+	} else if (spi_state == BGCOM_SPI_BUSY) {
+		return IRQ_HANDLED;
+	} else if (!bg_spi->irq_lock) {
+		bg_spi->irq_lock = 1;
+		bg_irq_tasklet_hndlr_l();
+		bg_spi->irq_lock = 0;
+	}
+	return IRQ_HANDLED;
+}
+
+static void bg_spi_init(struct bg_spi_priv *bg_spi)
+{
+	if (!bg_spi) {
+		pr_err("device not found\n");
+		return;
+	}
+
+	/* BGCOM SPI set-up */
+	mutex_init(&bg_spi->xfer_mutex);
+	spi_message_init(&bg_spi->msg1);
+	spi_message_add_tail(&bg_spi->xfer1, &bg_spi->msg1);
+
+	/* BGCOM IRQ set-up */
+	bg_spi->irq_lock = 0;
+
+	spi_state = BGCOM_SPI_FREE;
+
+	wq = create_singlethread_workqueue("input_wq");
+
+	bg_spi->bg_state = BGCOM_STATE_ACTIVE;
+
+	bg_com_drv = &bg_spi->lhandle;
+
+	mutex_init(&bg_resume_mutex);
+}
+
+static int bg_spi_probe(struct spi_device *spi)
+{
+	struct bg_spi_priv *bg_spi;
+	struct device_node *node;
+	int irq_gpio = 0;
+	int bg_irq = 0;
+	int ret;
+
+	bg_spi = devm_kzalloc(&spi->dev, sizeof(*bg_spi),
+				   GFP_KERNEL | GFP_ATOMIC);
+	if (!bg_spi)
+		return -ENOMEM;
+	bg_spi->spi = spi;
+	spi_set_drvdata(spi, bg_spi);
+	bg_spi_init(bg_spi);
+
+	/* BGCOM Interrupt probe */
+	node = spi->dev.of_node;
+	irq_gpio = of_get_named_gpio(node, "qcom,irq-gpio", 0);
+	if (!gpio_is_valid(irq_gpio)) {
+		pr_err("gpio %d found is not valid\n", irq_gpio);
+		goto err_ret;
+	}
+
+	ret = gpio_request(irq_gpio, "bgcom_gpio");
+	if (ret) {
+		pr_err("gpio %d request failed\n", irq_gpio);
+		goto err_ret;
+	}
+
+	ret = gpio_direction_input(irq_gpio);
+	if (ret) {
+		pr_err("gpio_direction_input not set: %d\n", ret);
+		goto err_ret;
+	}
+
+	bg_irq = gpio_to_irq(irq_gpio);
+	ret = request_threaded_irq(bg_irq, NULL, bg_irq_tasklet_hndlr,
+		IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "qcom,bg_spi", bg_spi);
+
+	if (ret)
+		goto err_ret;
+
+	pr_info("Bgcom Probed successfully\n");
+	return ret;
+
+err_ret:
+	bg_com_drv = NULL;
+	mutex_destroy(&bg_spi->xfer_mutex);
+	spi_set_drvdata(spi, NULL);
+	return -ENODEV;
+}
+
+static int bg_spi_remove(struct spi_device *spi)
+{
+	struct bg_spi_priv *bg_spi = spi_get_drvdata(spi);
+
+	mutex_destroy(&bg_spi->xfer_mutex);
+	devm_kfree(&spi->dev, bg_spi);
+	spi_set_drvdata(spi, NULL);
+
+	return 0;
+}
+
+static const struct of_device_id bg_spi_of_match[] = {
+	{ .compatible = "qcom,bg-spi", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, bg_spi_of_match);
+
+static struct spi_driver bg_spi_driver = {
+	.driver = {
+		.name = "bg-spi",
+		.of_match_table = bg_spi_of_match,
+	},
+	.probe = bg_spi_probe,
+	.remove = bg_spi_remove,
+};
+
+module_spi_driver(bg_spi_driver);
+MODULE_DESCRIPTION("bg SPI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/bgrsb.h b/drivers/soc/qcom/bgrsb.h
new file mode 100644
index 0000000..1ad23b7
--- /dev/null
+++ b/drivers/soc/qcom/bgrsb.h
@@ -0,0 +1,36 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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 BGRSB_H
+#define BGRSB_H
+
+struct event {
+	uint8_t sub_id;
+	int16_t evnt_data;
+	uint32_t evnt_tm;
+};
+
+
+struct bg_glink_chnl {
+	char *chnl_name;
+	char *chnl_edge;
+	char *chnl_trnsprt;
+};
+
+/**
+ * bgrsb_send_input() - send the recived input to input framework
+ * @evnt: pointer to the event structure
+ */
+int bgrsb_send_input(struct event *evnt);
+
+#endif /* BGCOM_H */
diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c
index 41a1a79..e641290 100644
--- a/drivers/soc/qcom/dcc_v2.c
+++ b/drivers/soc/qcom/dcc_v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -887,7 +887,8 @@
 		goto err;
 	}
 
-	if (!len) {
+	/* Check the len to avoid allocate huge memory */
+	if (!len || len > (drvdata->ram_size / 8)) {
 		dev_err(drvdata->dev, "DCC: Invalid length\n");
 		ret = -EINVAL;
 		goto err;
@@ -1635,7 +1636,7 @@
 }
 
 static const struct of_device_id msm_dcc_match[] = {
-	{ .compatible = "qcom,dcc_v2"},
+	{ .compatible = "qcom,dcc-v2"},
 	{}
 };
 
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index 4892f50..b8deec1 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -457,6 +457,42 @@
 	rwref_put(&ctx->ch_state_lhb2);
 }
 
+
+/**
+ * glink_subsys_up() - Inform transport about remote subsystem up.
+ * @subsystem:	The name of the subsystem
+ *
+ * Call into the transport using the subsys_up(if_ptr) function to allow it to
+ * initialize any necessary structures.
+ *
+ * Return: Standard error codes.
+ */
+int glink_subsys_up(const char *subsystem)
+{
+	int ret = 0;
+	bool transport_found = false;
+	struct glink_core_xprt_ctx *xprt_ctx = NULL;
+
+	mutex_lock(&transport_list_lock_lha0);
+	list_for_each_entry(xprt_ctx, &transport_list, list_node) {
+		if (!strcmp(subsystem, xprt_ctx->edge) &&
+				!xprt_is_fully_opened(xprt_ctx)) {
+			GLINK_INFO_XPRT(xprt_ctx, "%s: %s Subsystem up\n",
+							__func__, subsystem);
+			if (xprt_ctx->ops->subsys_up)
+				xprt_ctx->ops->subsys_up(xprt_ctx->ops);
+			transport_found = true;
+		}
+	}
+	mutex_unlock(&transport_list_lock_lha0);
+
+	if (!transport_found)
+		ret = -ENODEV;
+
+	return ret;
+}
+EXPORT_SYMBOL(glink_subsys_up);
+
 /**
  * glink_ssr() - Clean up locally for SSR by simulating remote close
  * @subsystem:	The name of the subsystem being restarted
@@ -3792,6 +3828,10 @@
  */
 int glink_xprt_name_to_id(const char *name, uint16_t *id)
 {
+	if (!strcmp(name, "bgcom")) {
+		*id = SPIV2_XPRT_ID;
+		return 0;
+	}
 	if (!strcmp(name, "smem")) {
 		*id = SMEM_XPRT_ID;
 		return 0;
diff --git a/drivers/soc/qcom/glink_bgcom_xprt.c b/drivers/soc/qcom/glink_bgcom_xprt.c
new file mode 100644
index 0000000..3c3923c
--- /dev/null
+++ b/drivers/soc/qcom/glink_bgcom_xprt.c
@@ -0,0 +1,1754 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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/delay.h>
+#include <linux/err.h>
+#include <linux/gfp.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/printk.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/srcu.h>
+#include <linux/wait.h>
+#include <linux/component.h>
+#include <soc/qcom/tracer_pkt.h>
+
+#include "glink_core_if.h"
+#include "glink_private.h"
+#include "glink_xprt_if.h"
+#include "bgcom.h"
+
+#define XPRT_NAME "bgcom"
+#define FIFO_ALIGNMENT 16
+#define TRACER_PKT_FEATURE BIT(2)
+
+#define ACTIVE_TX BIT(0)
+#define ACTIVE_RX BIT(1)
+
+#define ID_MASK 0xFFFFFF
+
+#define BGCOM_RESET 0x00000000
+#define BGCOM_APPLICATION_RUNNING 0x00000001
+#define BGCOM_TO_SLAVE_FIFO_READY 0x00000002
+#define BGCOM_TO_MASTER_FIFO_READY 0x00000004
+#define BGCOM_AHB_READY 0x00000008
+#define WORD_SIZE 4
+#define TX_BLOCKED_CMD_RESERVE 16
+#define FIFO_FULL_RESERVE (TX_BLOCKED_CMD_RESERVE/WORD_SIZE)
+#define BGCOM_LINKUP (BGCOM_APPLICATION_RUNNING \
+			| BGCOM_TO_SLAVE_FIFO_READY \
+			| BGCOM_TO_MASTER_FIFO_READY \
+			| BGCOM_AHB_READY)
+/**
+ * enum command_types - definition of the types of commands sent/received
+ * @VERSION_CMD:		Version and feature set supported
+ * @VERSION_ACK_CMD:		Response for @VERSION_CMD
+ * @OPEN_CMD:			Open a channel
+ * @CLOSE_CMD:			Close a channel
+ * @OPEN_ACK_CMD:		Response to @OPEN_CMD
+ * @CLOSE_ACK_CMD:		Response for @CLOSE_CMD
+ * @RX_INTENT_CMD:		RX intent for a channel is queued
+ * @RX_DONE_CMD:		Use of RX intent for a channel is complete
+ * @RX_DONE_W_REUSE_CMD:	Same as @RX_DONE but also reuse the used intent
+ * @RX_INTENT_REQ_CMD:		Request to have RX intent queued
+ * @RX_INTENT_REQ_ACK_CMD:	Response for @RX_INTENT_REQ_CMD
+ * @TX_DATA_CMD:		Start of a data transfer
+ * @TX_DATA_CONT_CMD:		Continuation or end of a data transfer
+ * @READ_NOTIF_CMD:		Request for a notification when this cmd is read
+ * @SIGNALS_CMD:		Sideband signals
+ * @TRACER_PKT_CMD:		Start of a Tracer Packet Command
+ * @TRACER_PKT_CONT_CMD:	Continuation or end of a Tracer Packet Command
+ */
+enum command_types {
+	VERSION_CMD,
+	VERSION_ACK_CMD,
+	OPEN_CMD,
+	CLOSE_CMD,
+	OPEN_ACK_CMD,
+	CLOSE_ACK_CMD,
+	RX_INTENT_CMD,
+	RX_DONE_CMD,
+	RX_DONE_W_REUSE_CMD,
+	RX_INTENT_REQ_CMD,
+	RX_INTENT_REQ_ACK_CMD,
+	TX_DATA_CMD,
+	TX_DATA_CONT_CMD,
+	READ_NOTIF_CMD,
+	SIGNALS_CMD,
+	TRACER_PKT_CMD,
+	TRACER_PKT_CONT_CMD,
+};
+
+struct bgcom_fifo_size {
+	uint32_t to_master:16;
+	uint32_t to_slave:16;
+};
+
+struct bgcom_fifo_fill {
+	uint32_t rx_avail:16;
+	uint32_t tx_avail:16;
+};
+
+/**
+ * struct edge_info - local information for managing a single complete edge
+ * @list:			List item to traverse in edge_info list
+ * @xprt_if:			The transport interface registered with the
+ *				glink core associated with this edge.
+ * @xprt_cfg:			The transport configuration for the glink core
+ *				assocaited with this edge.
+ * @subsys_name:		Name of the remote subsystem in the edge.
+ * @bgcom_dev:			Pointer to the connectingSPI Device.
+ * @fifo_size:			Size of the FIFO at the remote end.
+ * @fifo_fill:			Current available fifo size.
+ * @tx_avail_lock:		Lock to serialize access to tx_avail.
+ * @kwork:			Work to be executed when receiving data.
+ * @kworker:			Handle to the entity processing @kwork.
+ * @task:			Handle to the task context that runs @kworker.
+ * @use_ref:			Active users of this transport grab a
+ *				reference. Used for SSR synchronization.
+ * @in_ssr:			Signals if this transport is in ssr.
+ * @water_mark_reached		Signals if tx_avail need to read from fifo.
+ * @write_lock:			Lock to serialize write/tx operation.
+ * @tx_blocked_queue:		Queue of entities waiting for the remote side to
+ *				signal the resumption of TX.
+ * @tx_resume_needed:		A tx resume signal needs to be sent to the glink
+ *				core.
+ * @tx_blocked_signal_sent:	Flag to indicate the flush signal has already
+ *				been sent, and a response is pending from the
+ *				remote side.  Protected by @write_lock.
+ * @num_pw_states:		Size of @ramp_time_us.
+ * @ramp_time_us:		Array of ramp times in microseconds where array
+ *				index position represents a power state.
+ * @bgcom_status		Maintains bgcom status based on events.
+ * @wakeup_work	:		Work item for waking up tx_thread
+ * @activity_flag:		Flag indicating active TX and RX.
+ * @activity_lock:		Lock to synchronize access to activity flag.
+ * @bgcom_config:		Config to be given to bgcom driver.
+ * @bgcom_handle:		Handle to use bgcom driver apis.
+ */
+struct edge_info {
+	struct list_head list;
+	struct glink_transport_if xprt_if;
+	struct glink_core_transport_cfg xprt_cfg;
+	char subsys_name[GLINK_NAME_SIZE];
+	struct bgcom_device *bgcom_dev;
+
+	struct bgcom_fifo_size fifo_size;
+	struct bgcom_fifo_fill fifo_fill;
+	struct mutex tx_avail_lock;
+
+	struct kthread_worker kworker;
+	struct task_struct *task;
+	struct srcu_struct use_ref;
+	bool in_ssr;
+	bool water_mark_reached;
+	struct mutex write_lock;
+	wait_queue_head_t tx_blocked_queue;
+	bool tx_resume_needed;
+	bool tx_blocked_signal_sent;
+
+	uint32_t num_pw_states;
+	unsigned long *ramp_time_us;
+	uint32_t bgcom_status;
+	struct work_struct wakeup_work;
+	uint32_t activity_flag;
+	spinlock_t activity_lock;
+	struct bgcom_open_config_type bgcom_config;
+	void *bgcom_handle;
+};
+
+struct rx_pkt {
+	void *rx_buf;
+	uint32_t rx_len;
+	struct edge_info *einfo;
+	struct kthread_work kwork;
+};
+
+
+static uint32_t negotiate_features_v1(struct glink_transport_if *if_ptr,
+				      const struct glink_core_version *version,
+				      uint32_t features);
+static DEFINE_SPINLOCK(edge_infos_lock);
+static LIST_HEAD(edge_infos);
+static struct glink_core_version versions[] = {
+	{1, TRACER_PKT_FEATURE, negotiate_features_v1},
+};
+
+/**
+ * negotiate_features_v1() - determine what features of a version can be used
+ * @if_ptr:	The transport for which features are negotiated for.
+ * @version:	The version negotiated.
+ * @features:	The set of requested features.
+ *
+ * Return: What set of the requested features can be supported.
+ */
+static uint32_t negotiate_features_v1(struct glink_transport_if *if_ptr,
+				      const struct glink_core_version *version,
+				      uint32_t features)
+{
+	return features & version->features;
+}
+
+/**
+ * glink_bgcom_get_tx_avail() - Available Write Space in the remote side
+ * @einfo:	Edge information corresponding to the remote side.
+ *
+ * Return: 0 on error, available write space on success.
+ */
+static int glink_bgcom_get_tx_avail(struct edge_info *einfo)
+{
+	uint32_t tx_avail;
+
+	mutex_lock(&einfo->tx_avail_lock);
+	tx_avail = einfo->fifo_fill.tx_avail;
+	if (tx_avail < FIFO_FULL_RESERVE)
+		tx_avail = 0;
+	else
+		tx_avail -= FIFO_FULL_RESERVE;
+
+	mutex_unlock(&einfo->tx_avail_lock);
+	return tx_avail;
+}
+
+
+/**
+ * glink_bgcom_update_tx_avail() - update available Write Space in fifo
+ * @einfo:	Edge information corresponding to the remote side.
+ * @size:	size to update.
+ *
+ * Return: 0 on error, available write space on success.
+ */
+static void glink_bgcom_update_tx_avail(struct edge_info *einfo, uint32_t size)
+{
+	mutex_lock(&einfo->tx_avail_lock);
+	einfo->fifo_fill.tx_avail -= size;
+	if (einfo->fifo_fill.tx_avail < einfo->fifo_size.to_slave/2)
+		einfo->water_mark_reached = true;
+	mutex_unlock(&einfo->tx_avail_lock);
+}
+
+/**
+ * glink_bgcom_xprt_tx_cmd_safe() - Transmit G-Link commands
+ * @einfo:	Edge information corresponding to the remote subsystem.
+ * @src:	Source buffer containing the G-Link command.
+ * @size:	Size of the command to transmit.
+ *
+ * This function is used to transmit the G-Link commands. This function
+ * must be called with einfo->write_lock locked.
+ *
+ * Return: 0 on success, standard Linux error codes on error.
+ */
+static int glink_bgcom_xprt_tx_cmd_safe(struct edge_info *einfo, void *src,
+				      uint32_t size)
+{
+	uint32_t tx_avail = glink_bgcom_get_tx_avail(einfo);
+	int ret;
+	uint32_t size_in_words = size/WORD_SIZE;
+
+	if (size_in_words > tx_avail) {
+		GLINK_ERR("%s: No Space in Fifo\n", __func__);
+		return -ENOSPC;
+	}
+
+	ret = bgcom_fifo_write(einfo->bgcom_handle, size_in_words, src);
+	if (ret < 0) {
+		GLINK_ERR("%s: Error %d writing data\n", __func__, ret);
+		return ret;
+	}
+	glink_bgcom_update_tx_avail(einfo, size_in_words);
+	return ret;
+}
+
+/**
+ * send_tx_blocked_signal() - Send flow control request message
+ * @einfo:	Edge information corresponding to the remote subsystem.
+ *
+ * This function is used to send a message to the remote subsystem indicating
+ * that the local subsystem is waiting for the write space. The remote
+ * subsystem on receiving this message will send a resume tx message.
+ */
+static void send_tx_blocked_signal(struct edge_info *einfo)
+{
+	struct read_notif_request {
+		uint16_t cmd;
+		uint16_t reserved;
+		uint32_t reserved2;
+		uint64_t reserved3;
+	};
+	struct read_notif_request read_notif_req = {0};
+	int size_in_word = sizeof(read_notif_req)/WORD_SIZE;
+	void *src = &read_notif_req;
+	int ret;
+
+	read_notif_req.cmd = READ_NOTIF_CMD;
+	if (!einfo->tx_blocked_signal_sent) {
+		einfo->tx_blocked_signal_sent = true;
+		ret = bgcom_fifo_write(einfo->bgcom_handle, size_in_word, src);
+		if (ret < 0) {
+			GLINK_ERR("%s: Err %d send blocked\n", __func__, ret);
+			return;
+		}
+		glink_bgcom_update_tx_avail(einfo, size_in_word);
+	}
+}
+
+/**
+ * glink_bgcom_xprt_tx_cmd() - Transmit G-Link commands
+ * @einfo:	Edge information corresponding to the remote subsystem.
+ * @src:	Source buffer containing the G-Link command.
+ * @size:	Size of the command to transmit.
+ *
+ * This function is used to transmit the G-Link commands. This function
+ * might sleep if the space is not available to transmit the command.
+ *
+ * Return: 0 on success, standard Linux error codes on error.
+ */
+static int glink_bgcom_xprt_tx_cmd(struct edge_info *einfo, void *src,
+				 uint32_t size)
+{
+	int ret;
+	DEFINE_WAIT(wait);
+
+	mutex_lock(&einfo->write_lock);
+	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) {
+			mutex_unlock(&einfo->write_lock);
+			return -EFAULT;
+		}
+	}
+	ret = glink_bgcom_xprt_tx_cmd_safe(einfo, src, size);
+	mutex_unlock(&einfo->write_lock);
+	return ret;
+}
+
+/**
+ * process_rx_data() - process received data from an edge
+ * @einfo:		The edge the data is received on.
+ * @cmd_id:		ID to specify the type of data.
+ * @rcid:		The remote channel id associated with the data.
+ * @intend_id:		The intent the data should be put in.
+ * @src:		Address of the source buffer from which the data
+ *			is read.
+ * @frag_size:		Size of the data fragment to read.
+ * @size_remaining:	Size of data left to be read in this packet.
+ */
+static void process_rx_data(struct edge_info *einfo, uint16_t cmd_id,
+			    uint32_t rcid, uint32_t intent_id, void *src,
+			    uint32_t frag_size, uint32_t size_remaining)
+{
+	struct glink_core_rx_intent *intent;
+	int rc = 0;
+
+	intent = einfo->xprt_if.glink_core_if_ptr->rx_get_pkt_ctx(
+				&einfo->xprt_if, rcid, intent_id);
+	if (intent == NULL) {
+		GLINK_ERR("%s: no intent for ch %d liid %d\n", __func__, rcid,
+			  intent_id);
+		return;
+	} else if (intent->data == NULL) {
+		GLINK_ERR("%s: intent for ch %d liid %d has no data buff\n",
+			  __func__, rcid, intent_id);
+		return;
+	} else if (intent->intent_size - intent->write_offset < frag_size ||
+		 intent->write_offset + size_remaining > intent->intent_size) {
+		GLINK_ERR("%s: rx data size:%d and remaining:%d %s %d %s:%d\n",
+			  __func__, frag_size, size_remaining,
+			  "will overflow ch", rcid, "intent", intent_id);
+		return;
+	}
+
+	rc = bgcom_ahb_read(einfo->bgcom_handle, (uint32_t)(size_t)src,
+				ALIGN(frag_size, WORD_SIZE)/WORD_SIZE,
+				intent->data + intent->write_offset);
+
+	if (rc < 0) {
+		GLINK_ERR("%s: Error %d receiving data %d:%d:%d:%d\n",
+			  __func__, rc, rcid, intent_id, frag_size,
+			  size_remaining);
+		size_remaining += frag_size;
+	} else {
+		intent->write_offset += frag_size;
+		intent->pkt_size += frag_size;
+
+		if (unlikely((cmd_id == TRACER_PKT_CMD ||
+			cmd_id == TRACER_PKT_CONT_CMD) && !size_remaining)) {
+			tracer_pkt_log_event(intent->data, GLINK_XPRT_RX);
+			intent->tracer_pkt = true;
+		}
+	}
+	einfo->xprt_if.glink_core_if_ptr->rx_put_pkt_ctx(&einfo->xprt_if,
+				rcid, intent, size_remaining ? false : true);
+}
+
+/**
+ * process_rx_cmd() - Process incoming G-Link commands
+ * @einfo:	Edge information corresponding to the remote subsystem.
+ * @rx_data:	Buffer which contains the G-Link commands to be processed.
+ * @rx_size:	Size of the buffer containing the series of G-Link commands.
+ *
+ * This function is used to parse and process a series of G-Link commands
+ * received in a buffer.
+ */
+static void process_rx_cmd(struct edge_info *einfo,
+			   void *rx_data, int rx_size)
+{
+	struct command {
+		uint16_t id;
+		uint16_t param1;
+		uint32_t param2;
+		uint32_t param3;
+		uint32_t param4;
+	};
+	struct intent_desc {
+		uint32_t size;
+		uint32_t id;
+		uint64_t addr;
+	};
+	struct rx_desc {
+		uint32_t size;
+		uint32_t size_left;
+		uint64_t addr;
+	};
+	struct command *cmd;
+	struct intent_desc *intents;
+	struct rx_desc *rx_descp;
+	int offset = 0;
+	int rcu_id;
+	uint16_t rcid;
+	uint16_t name_len;
+	uint16_t prio;
+	char *name;
+	bool granted;
+	int i;
+
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return;
+	}
+
+	while (offset < rx_size) {
+		cmd = (struct command *)(rx_data + offset);
+		offset += sizeof(*cmd);
+		switch (cmd->id) {
+		case VERSION_CMD:
+			einfo->xprt_if.glink_core_if_ptr->rx_cmd_version(
+				&einfo->xprt_if, cmd->param1, cmd->param2);
+			break;
+
+		case VERSION_ACK_CMD:
+			einfo->xprt_if.glink_core_if_ptr->rx_cmd_version_ack(
+				&einfo->xprt_if, cmd->param1, cmd->param2);
+			break;
+
+		case OPEN_CMD:
+			rcid = cmd->param1;
+			name_len = (uint16_t)(cmd->param2 & 0xFFFF);
+			prio = (uint16_t)((cmd->param2 & 0xFFFF0000) >> 16);
+			name = (char *)(rx_data + offset);
+			offset += ALIGN(name_len, FIFO_ALIGNMENT);
+			einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_remote_open(
+				&einfo->xprt_if, rcid, name, prio);
+			break;
+
+		case CLOSE_CMD:
+			einfo->xprt_if.glink_core_if_ptr->
+					rx_cmd_ch_remote_close(
+						&einfo->xprt_if, cmd->param1);
+			break;
+
+		case OPEN_ACK_CMD:
+			prio = (uint16_t)(cmd->param2 & 0xFFFF);
+			einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_open_ack(
+				&einfo->xprt_if, cmd->param1, prio);
+			break;
+
+		case CLOSE_ACK_CMD:
+			einfo->xprt_if.glink_core_if_ptr->rx_cmd_ch_close_ack(
+					&einfo->xprt_if, cmd->param1);
+			break;
+
+		case RX_INTENT_CMD:
+			for (i = 0; i < cmd->param2; i++) {
+				intents = (struct intent_desc *)
+						(rx_data + offset);
+				offset += sizeof(*intents);
+				einfo->xprt_if.glink_core_if_ptr->
+					rx_cmd_remote_rx_intent_put_cookie(
+					&einfo->xprt_if, cmd->param1,
+					intents->id, intents->size,
+					(void *)(uintptr_t)(intents->addr));
+			}
+			break;
+
+		case RX_DONE_CMD:
+			einfo->xprt_if.glink_core_if_ptr->rx_cmd_tx_done(
+				&einfo->xprt_if, cmd->param1, cmd->param2,
+				false);
+			break;
+
+		case RX_INTENT_REQ_CMD:
+			einfo->xprt_if.glink_core_if_ptr->
+				rx_cmd_remote_rx_intent_req(
+					&einfo->xprt_if, cmd->param1,
+					cmd->param2);
+			break;
+
+		case RX_INTENT_REQ_ACK_CMD:
+			granted = cmd->param2 == 1 ? true : false;
+			einfo->xprt_if.glink_core_if_ptr->
+				rx_cmd_rx_intent_req_ack(&einfo->xprt_if,
+						cmd->param1, granted);
+			break;
+
+		case TX_DATA_CMD:
+		case TX_DATA_CONT_CMD:
+		case TRACER_PKT_CMD:
+		case TRACER_PKT_CONT_CMD:
+			rx_descp = (struct rx_desc *)(rx_data + offset);
+			offset += sizeof(*rx_descp);
+			process_rx_data(einfo, cmd->id, cmd->param1,
+					cmd->param2,
+					(void *)(uintptr_t)(rx_descp->addr),
+					rx_descp->size, rx_descp->size_left);
+			break;
+
+		case READ_NOTIF_CMD:
+			break;
+
+		case SIGNALS_CMD:
+			einfo->xprt_if.glink_core_if_ptr->rx_cmd_remote_sigs(
+				&einfo->xprt_if, cmd->param1, cmd->param2);
+			break;
+
+		case RX_DONE_W_REUSE_CMD:
+			einfo->xprt_if.glink_core_if_ptr->rx_cmd_tx_done(
+				&einfo->xprt_if, cmd->param1,
+				cmd->param2, true);
+			break;
+
+		default:
+			GLINK_ERR("Unrecognized command: %d\n", cmd->id);
+			break;
+		}
+	}
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+
+/**
+ * tx_wakeup_worker() - worker function to wakeup tx blocked thread
+ * @work:	kwork associated with the edge to process commands on.
+ */
+static void tx_wakeup_worker(struct edge_info *einfo)
+{
+	int rcu_id;
+	struct bgcom_fifo_fill fifo_fill;
+
+	mutex_lock(&einfo->tx_avail_lock);
+	bgcom_reg_read(einfo->bgcom_handle, BGCOM_REG_FIFO_FILL, 1,
+						&fifo_fill);
+	einfo->fifo_fill.tx_avail = fifo_fill.tx_avail;
+	if (einfo->fifo_fill.tx_avail > einfo->fifo_size.to_slave/2)
+		einfo->water_mark_reached = false;
+	mutex_unlock(&einfo->tx_avail_lock);
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return;
+	}
+	if (einfo->tx_resume_needed &&
+				glink_bgcom_get_tx_avail(einfo)) {
+		einfo->tx_resume_needed = false;
+		einfo->xprt_if.glink_core_if_ptr->tx_resume(
+						&einfo->xprt_if);
+	}
+	mutex_lock(&einfo->write_lock);
+	if (einfo->tx_blocked_signal_sent) {
+		wake_up_all(&einfo->tx_blocked_queue);
+		einfo->tx_blocked_signal_sent = false;
+	}
+	mutex_unlock(&einfo->write_lock);
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * __rx_worker() - Receive commands on a specific edge
+ * @einfo:      Edge to process commands on.
+ *
+ * This function checks the size of data to be received, allocates the
+ * buffer for that data and reads the data from the remote subsytem
+ * into that buffer. This function then calls the process_rx_cmd() to
+ * parse the received G-Link command sequence. This function will also
+ * poll for the data for a predefined duration for performance reasons.
+ */
+static void __rx_worker(struct rx_pkt *rx_pkt_info)
+{
+	int rcu_id;
+	struct edge_info *einfo = rx_pkt_info->einfo;
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return;
+	}
+	process_rx_cmd(einfo, rx_pkt_info->rx_buf,
+				rx_pkt_info->rx_len*WORD_SIZE);
+	kfree(rx_pkt_info->rx_buf);
+	kfree(rx_pkt_info);
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * rx_worker() - Worker function to process received commands
+ * @work:       kwork associated with the edge to process commands on.
+ */
+static void rx_worker(struct kthread_work *work)
+{
+	struct rx_pkt *rx_pkt_info;
+
+	rx_pkt_info = container_of(work, struct rx_pkt, kwork);
+	__rx_worker(rx_pkt_info);
+};
+
+/**
+ * tx_cmd_version() - Convert a version cmd to wire format and transmit
+ * @if_ptr:     The transport to transmit on.
+ * @version:    The version number to encode.
+ * @features:   The features information to encode.
+ */
+static void tx_cmd_version(struct glink_transport_if *if_ptr, uint32_t version,
+			   uint32_t features)
+{
+	struct command {
+		uint16_t id;
+		uint16_t version;
+		uint32_t features;
+		uint32_t fifo_size;
+		uint32_t reserved;
+	};
+	struct command cmd;
+	struct edge_info *einfo;
+	int rcu_id;
+
+	memset(&cmd, 0, sizeof(cmd));
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return;
+	}
+
+	cmd.id = VERSION_CMD;
+	cmd.version = version;
+	cmd.features = features;
+
+	glink_bgcom_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * tx_cmd_version_ack() - Convert a version ack cmd to wire format and transmit
+ * @if_ptr:	The transport to transmit on.
+ * @version:	The version number to encode.
+ * @features:	The features information to encode.
+ */
+static void tx_cmd_version_ack(struct glink_transport_if *if_ptr,
+			       uint32_t version,
+			       uint32_t features)
+{
+	struct command {
+		uint16_t id;
+		uint16_t version;
+		uint32_t features;
+		uint32_t fifo_size;
+		uint32_t reserved;
+	};
+	struct command cmd;
+	struct edge_info *einfo;
+	int rcu_id;
+
+	memset(&cmd, 0, sizeof(cmd));
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return;
+	}
+
+	cmd.id = VERSION_ACK_CMD;
+	cmd.version = version;
+	cmd.features = features;
+
+	glink_bgcom_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * set_version() - Activate a negotiated version and feature set
+ * @if_ptr:	The transport to configure.
+ * @version:	The version to use.
+ * @features:	The features to use.
+ *
+ * Return: The supported capabilities of the transport.
+ */
+static uint32_t set_version(struct glink_transport_if *if_ptr, uint32_t version,
+			uint32_t features)
+{
+	struct edge_info *einfo;
+	uint32_t ret;
+	int rcu_id;
+
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return 0;
+	}
+
+	ret = GCAP_SIGNALS;
+	if (features & TRACER_PKT_FEATURE)
+		ret |= GCAP_TRACER_PKT;
+
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+	return ret;
+}
+
+/**
+ * tx_cmd_ch_open() - Convert a channel open cmd to wire format and transmit
+ * @if_ptr:	The transport to transmit on.
+ * @lcid:	The local channel id to encode.
+ * @name:	The channel name to encode.
+ * @req_xprt:	The transport the core would like to migrate this channel to.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_ch_open(struct glink_transport_if *if_ptr, uint32_t lcid,
+			  const char *name, uint16_t req_xprt)
+{
+	struct command {
+		uint16_t id;
+		uint16_t lcid;
+		uint16_t length;
+		uint16_t req_xprt;
+		uint64_t reserved;
+	};
+	struct command cmd;
+	struct edge_info *einfo;
+	uint32_t buf_size;
+	void *buf;
+	int rcu_id;
+
+	memset(&cmd, 0, sizeof(cmd));
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return -EFAULT;
+	}
+
+	cmd.id = OPEN_CMD;
+	cmd.lcid = lcid;
+	cmd.length = (uint16_t)(strlen(name) + 1);
+	cmd.req_xprt = req_xprt;
+
+	buf_size = ALIGN(sizeof(cmd) + cmd.length, FIFO_ALIGNMENT);
+
+	buf = kzalloc(buf_size, GFP_KERNEL);
+	if (!buf) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return -ENOMEM;
+	}
+
+	memcpy(buf, &cmd, sizeof(cmd));
+	memcpy(buf + sizeof(cmd), name, cmd.length);
+
+	glink_bgcom_xprt_tx_cmd(einfo, buf, buf_size);
+
+	kfree(buf);
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+	return 0;
+}
+
+/**
+ * tx_cmd_ch_close() - Convert a channel close cmd to wire format and transmit
+ * @if_ptr:	The transport to transmit on.
+ * @lcid:	The local channel id to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_ch_close(struct glink_transport_if *if_ptr, uint32_t lcid)
+{
+	struct command {
+		uint16_t id;
+		uint16_t lcid;
+		uint32_t reserved1;
+		uint64_t reserved2;
+	};
+	struct command cmd;
+	struct edge_info *einfo;
+	int rcu_id;
+
+	memset(&cmd, 0, sizeof(cmd));
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return -EFAULT;
+	}
+
+	cmd.id = CLOSE_CMD;
+	cmd.lcid = lcid;
+
+	glink_bgcom_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+	return 0;
+}
+
+/**
+ * tx_cmd_ch_remote_open_ack() - Convert a channel open ack cmd to wire format
+ *				 and transmit
+ * @if_ptr:	The transport to transmit on.
+ * @rcid:	The remote channel id to encode.
+ * @xprt_resp:	The response to a transport migration request.
+ */
+static void tx_cmd_ch_remote_open_ack(struct glink_transport_if *if_ptr,
+				     uint32_t rcid, uint16_t xprt_resp)
+{
+	struct command {
+		uint16_t id;
+		uint16_t rcid;
+		uint16_t reserved1;
+		uint16_t xprt_resp;
+		uint64_t reserved2;
+	};
+	struct command cmd;
+	struct edge_info *einfo;
+	int rcu_id;
+
+	memset(&cmd, 0, sizeof(cmd));
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return;
+	}
+
+	cmd.id = OPEN_ACK_CMD;
+	cmd.rcid = rcid;
+	cmd.xprt_resp = xprt_resp;
+
+	glink_bgcom_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * tx_cmd_ch_remote_close_ack() - Convert a channel close ack cmd to wire format
+ *				  and transmit
+ * @if_ptr:	The transport to transmit on.
+ * @rcid:	The remote channel id to encode.
+ */
+static void tx_cmd_ch_remote_close_ack(struct glink_transport_if *if_ptr,
+				       uint32_t rcid)
+{
+	struct command {
+		uint16_t id;
+		uint16_t rcid;
+		uint32_t reserved1;
+		uint64_t reserved2;
+	};
+	struct command cmd;
+	struct edge_info *einfo;
+	int rcu_id;
+
+	memset(&cmd, 0, sizeof(cmd));
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return;
+	}
+
+	cmd.id = CLOSE_ACK_CMD;
+	cmd.rcid = rcid;
+
+	glink_bgcom_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * ssr() - Process a subsystem restart notification of a transport
+ * @if_ptr:	The transport to restart
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int ssr(struct glink_transport_if *if_ptr)
+{
+	struct edge_info *einfo;
+
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	einfo->in_ssr = true;
+	wake_up_all(&einfo->tx_blocked_queue);
+
+	synchronize_srcu(&einfo->use_ref);
+	einfo->tx_resume_needed = false;
+	einfo->tx_blocked_signal_sent = false;
+	einfo->xprt_if.glink_core_if_ptr->link_down(&einfo->xprt_if);
+
+	return 0;
+}
+
+/**
+ * allocate_rx_intent() - Allocate/reserve space for RX Intent
+ * @if_ptr:	The transport the intent is associated with.
+ * @size:	size of intent.
+ * @intent:	Pointer to the intent structure.
+ *
+ * Assign "data" with the buffer created, since the transport creates
+ * a linear buffer and "iovec" with the "intent" itself, so that
+ * the data can be passed to a client that receives only vector buffer.
+ * Note that returning NULL for the pointer is valid (it means that space has
+ * been reserved, but the actual pointer will be provided later).
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int allocate_rx_intent(struct glink_transport_if *if_ptr, size_t size,
+			      struct glink_core_rx_intent *intent)
+{
+	void *t;
+
+	t = kzalloc(ALIGN(size, WORD_SIZE), GFP_KERNEL);
+	if (!t)
+		return -ENOMEM;
+
+	intent->data = t;
+	intent->iovec = (void *)intent;
+	intent->vprovider = rx_linear_vbuf_provider;
+	intent->pprovider = NULL;
+	return 0;
+}
+
+/**
+ * deallocate_rx_intent() - Deallocate space created for RX Intent
+ * @if_ptr:	The transport the intent is associated with.
+ * @intent:	Pointer to the intent structure.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int deallocate_rx_intent(struct glink_transport_if *if_ptr,
+				struct glink_core_rx_intent *intent)
+{
+	if (!intent || !intent->data)
+		return -EINVAL;
+
+	kfree(intent->data);
+	intent->data = NULL;
+	intent->iovec = NULL;
+	intent->vprovider = NULL;
+	return 0;
+}
+
+/**
+ * tx_cmd_local_rx_intent() - Convert an rx intent cmd to wire format and
+ *			      transmit
+ * @if_ptr:	The transport to transmit on.
+ * @lcid:	The local channel id to encode.
+ * @size:	The intent size to encode.
+ * @liid:	The local intent id to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_local_rx_intent(struct glink_transport_if *if_ptr,
+				  uint32_t lcid, size_t size, uint32_t liid)
+{
+	struct command {
+		uint16_t id;
+		uint16_t lcid;
+		uint32_t count;
+		uint64_t reserved;
+		uint32_t size;
+		uint32_t liid;
+		uint64_t addr;
+	};
+	struct command cmd;
+	struct edge_info *einfo;
+	int rcu_id;
+
+	if (size > UINT_MAX) {
+		GLINK_ERR("%s: size %zu is too large to encode\n",
+							__func__, size);
+		return -EMSGSIZE;
+	}
+
+	memset(&cmd, 0, sizeof(cmd));
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return -EFAULT;
+	}
+
+	cmd.id = RX_INTENT_CMD;
+	cmd.lcid = lcid;
+	cmd.count = 1;
+	cmd.size = size;
+	cmd.liid = liid;
+
+	glink_bgcom_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+	return 0;
+}
+
+/**
+ * tx_cmd_local_rx_done() - Convert an rx done cmd to wire format and transmit
+ * @if_ptr:	The transport to transmit on.
+ * @lcid:	The local channel id to encode.
+ * @liid:	The local intent id to encode.
+ * @reuse:	Reuse the consumed intent.
+ */
+static void tx_cmd_local_rx_done(struct glink_transport_if *if_ptr,
+				 uint32_t lcid, uint32_t liid, bool reuse)
+{
+	struct command {
+		uint16_t id;
+		uint16_t lcid;
+		uint32_t liid;
+		uint64_t reserved;
+	};
+	struct command cmd;
+	struct edge_info *einfo;
+	int rcu_id;
+
+	memset(&cmd, 0, sizeof(cmd));
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return;
+	}
+
+	cmd.id = reuse ? RX_DONE_W_REUSE_CMD : RX_DONE_CMD;
+	cmd.lcid = lcid;
+	cmd.liid = liid;
+
+	glink_bgcom_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+}
+
+/**
+ * tx_cmd_rx_intent_req() - Convert an rx intent request cmd to wire format and
+ *			    transmit
+ * @if_ptr:	The transport to transmit on.
+ * @lcid:	The local channel id to encode.
+ * @size:	The requested intent size to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_rx_intent_req(struct glink_transport_if *if_ptr,
+				uint32_t lcid, size_t size)
+{
+	struct command {
+		uint16_t id;
+		uint16_t lcid;
+		uint32_t size;
+		uint64_t reserved;
+	};
+	struct command cmd;
+	struct edge_info *einfo;
+	int rcu_id;
+
+	if (size > UINT_MAX) {
+		GLINK_ERR("%s: size %zu is too large to encode\n",
+							__func__, size);
+		return -EMSGSIZE;
+	}
+
+	memset(&cmd, 0, sizeof(cmd));
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return -EFAULT;
+	}
+
+	cmd.id = RX_INTENT_REQ_CMD,
+	cmd.lcid = lcid;
+	cmd.size = ALIGN(size, WORD_SIZE);
+
+	glink_bgcom_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+	return 0;
+}
+
+/**
+ * tx_cmd_rx_intent_req_ack() - Convert an rx intent request ack cmd to wire
+ *				format and transmit
+ * @if_ptr:	The transport to transmit on.
+ * @lcid:	The local channel id to encode.
+ * @granted:	The request response to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_remote_rx_intent_req_ack(struct glink_transport_if *if_ptr,
+					   uint32_t lcid, bool granted)
+{
+	struct command {
+		uint16_t id;
+		uint16_t lcid;
+		uint32_t response;
+		uint64_t reserved;
+	};
+	struct command cmd;
+	struct edge_info *einfo;
+	int rcu_id;
+
+	memset(&cmd, 0, sizeof(cmd));
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return -EFAULT;
+	}
+
+	cmd.id = RX_INTENT_REQ_ACK_CMD,
+	cmd.lcid = lcid;
+	if (granted)
+		cmd.response = 1;
+	else
+		cmd.response = 0;
+
+	glink_bgcom_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+	return 0;
+}
+
+/**
+ * tx_cmd_set_sigs() - Convert a signals ack cmd to wire format and transmit
+ * @if_ptr:	The transport to transmit on.
+ * @lcid:	The local channel id to encode.
+ * @sigs:	The signals to encode.
+ *
+ * Return: 0 on success or standard Linux error code.
+ */
+static int tx_cmd_set_sigs(struct glink_transport_if *if_ptr, uint32_t lcid,
+			   uint32_t sigs)
+{
+	struct command {
+		uint16_t id;
+		uint16_t lcid;
+		uint32_t sigs;
+		uint64_t reserved;
+	};
+	struct command cmd;
+	struct edge_info *einfo;
+	int rcu_id;
+
+	memset(&cmd, 0, sizeof(cmd));
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return -EFAULT;
+	}
+
+	cmd.id = SIGNALS_CMD,
+	cmd.lcid = lcid;
+	cmd.sigs = sigs;
+
+	glink_bgcom_xprt_tx_cmd(einfo, &cmd, sizeof(cmd));
+
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+	return 0;
+}
+
+/**
+ * tx_data() - convert a data/tracer_pkt to wire format and transmit
+ * @if_ptr:     The transport to transmit on.
+ * @cmd_id:     The command ID to transmit.
+ * @lcid:       The local channel id to encode.
+ * @pctx:       The data to encode.
+ *
+ * Return: Number of bytes written or standard Linux error code.
+ */
+static int tx_data(struct glink_transport_if *if_ptr, uint16_t cmd_id,
+		   uint32_t lcid, struct glink_core_tx_pkt *pctx)
+{
+	struct command {
+		uint16_t id;
+		uint16_t lcid;
+		uint32_t riid;
+		uint64_t reserved;
+		uint32_t size;
+		uint32_t size_left;
+		uint64_t addr;
+	};
+	struct command cmd;
+	struct edge_info *einfo;
+	void *data_start, *dst = NULL;
+	size_t tx_size = 0;
+	int rcu_id;
+
+	if (pctx->size < pctx->size_remaining) {
+		GLINK_ERR("%s: size remaining exceeds size.  Resetting.\n",
+			  __func__);
+		pctx->size_remaining = pctx->size;
+	}
+	if (!pctx->size_remaining)
+		return 0;
+
+	memset(&cmd, 0, sizeof(cmd));
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+
+	rcu_id = srcu_read_lock(&einfo->use_ref);
+	if (einfo->in_ssr) {
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return -EFAULT;
+	}
+
+	if (cmd_id == TX_DATA_CMD) {
+		if (pctx->size_remaining == pctx->size)
+			cmd.id = TX_DATA_CMD;
+		else
+			cmd.id = TX_DATA_CONT_CMD;
+	} else {
+		if (pctx->size_remaining == pctx->size)
+			cmd.id = TRACER_PKT_CMD;
+		else
+			cmd.id = TRACER_PKT_CONT_CMD;
+	}
+	cmd.lcid = lcid;
+	cmd.riid = pctx->riid;
+	data_start = get_tx_vaddr(pctx, pctx->size - pctx->size_remaining,
+				  &tx_size);
+	if (unlikely(!data_start)) {
+		GLINK_ERR("%s: invalid data_start\n", __func__);
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		return -EINVAL;
+	}
+	if (likely(pctx->cookie))
+		dst = pctx->cookie + (pctx->size - pctx->size_remaining);
+
+	mutex_lock(&einfo->write_lock);
+	/* Need enough space to write the command */
+	if (glink_bgcom_get_tx_avail(einfo) <= sizeof(cmd)/WORD_SIZE) {
+		einfo->tx_resume_needed = true;
+		send_tx_blocked_signal(einfo);
+		mutex_unlock(&einfo->write_lock);
+		srcu_read_unlock(&einfo->use_ref, rcu_id);
+		GLINK_ERR("%s: No Space in Fifo\n", __func__);
+		return -EAGAIN;
+	}
+	cmd.addr = 0;
+	cmd.size = tx_size;
+	pctx->size_remaining -= tx_size;
+	cmd.size_left = pctx->size_remaining;
+	if (cmd.id == TRACER_PKT_CMD)
+		tracer_pkt_log_event((void *)(pctx->data), GLINK_XPRT_TX);
+
+	bgcom_resume(einfo->bgcom_handle);
+	bgcom_ahb_write(einfo->bgcom_handle, (uint32_t)(size_t)dst,
+				ALIGN(tx_size, WORD_SIZE)/WORD_SIZE,
+				data_start);
+	glink_bgcom_xprt_tx_cmd_safe(einfo, &cmd, sizeof(cmd));
+	GLINK_DBG("%s %s: lcid[%u] riid[%u] cmd %d, size[%d], size_left[%d]\n",
+		  "<BGCOM>", __func__, cmd.lcid, cmd.riid, cmd.id, cmd.size,
+		  cmd.size_left);
+	mutex_unlock(&einfo->write_lock);
+	srcu_read_unlock(&einfo->use_ref, rcu_id);
+	return cmd.size;
+}
+
+/**
+ * tx() - convert a data transmit cmd to wire format and transmit
+ * @if_ptr:     The transport to transmit on.
+ * @lcid:       The local channel id to encode.
+ * @pctx:       The data to encode.
+ *
+ * Return: Number of bytes written or standard Linux error code.
+ */
+static int tx(struct glink_transport_if *if_ptr, uint32_t lcid,
+	      struct glink_core_tx_pkt *pctx)
+{
+	return tx_data(if_ptr, TX_DATA_CMD, lcid, pctx);
+}
+
+/**
+ * tx_cmd_tracer_pkt() - convert a tracer packet cmd to wire format and transmit
+ * @if_ptr:     The transport to transmit on.
+ * @lcid:       The local channel id to encode.
+ * @pctx:       The data to encode.
+ *
+ * Return: Number of bytes written or standard Linux error code.
+ */
+static int tx_cmd_tracer_pkt(struct glink_transport_if *if_ptr, uint32_t lcid,
+			     struct glink_core_tx_pkt *pctx)
+{
+	return tx_data(if_ptr, TRACER_PKT_CMD, lcid, pctx);
+}
+
+/**
+ * int wait_link_down() - Check status of read/write indices
+ * @if_ptr:     The transport to check
+ *
+ * Return: 1 if indices are all zero, 0 otherwise
+ */
+static int wait_link_down(struct glink_transport_if *if_ptr)
+{
+	return 0;
+}
+
+/**
+ * get_power_vote_ramp_time() - Get the ramp time required for the power
+ *                              votes to be applied
+ * @if_ptr:     The transport interface on which power voting is requested.
+ * @state:      The power state for which ramp time is required.
+ *
+ * Return: The ramp time specific to the power state, standard error otherwise.
+ */
+static unsigned long get_power_vote_ramp_time(
+		struct glink_transport_if *if_ptr, uint32_t state)
+{
+	return 0;
+}
+
+/**
+ * power_vote() - Update the power votes to meet qos requirement
+ * @if_ptr:     The transport interface on which power voting is requested.
+ * @state:      The power state for which the voting should be done.
+ *
+ * Return: 0 on Success, standard error otherwise.
+ */
+static int power_vote(struct glink_transport_if *if_ptr, uint32_t state)
+{
+	unsigned long flags;
+	struct edge_info *einfo;
+
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+	spin_lock_irqsave(&einfo->activity_lock, flags);
+	einfo->activity_flag |= ACTIVE_TX;
+	spin_unlock_irqrestore(&einfo->activity_lock, flags);
+	return 0;
+}
+
+/**
+ * power_unvote() - Remove the all the power votes
+ * @if_ptr:     The transport interface on which power voting is requested.
+ *
+ * Return: 0 on Success, standard error otherwise.
+ */
+static int power_unvote(struct glink_transport_if *if_ptr)
+{
+	unsigned long flags;
+	struct edge_info *einfo;
+
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+	spin_lock_irqsave(&einfo->activity_lock, flags);
+	einfo->activity_flag &= ~ACTIVE_TX;
+	spin_unlock_irqrestore(&einfo->activity_lock, flags);
+	return 0;
+}
+
+static void glink_bgcom_linkup(struct edge_info *einfo)
+{
+	if (einfo->bgcom_status != BGCOM_LINKUP)
+		return;
+	einfo->in_ssr = false;
+	synchronize_srcu(&einfo->use_ref);
+	bgcom_reg_read(einfo->bgcom_handle, BGCOM_REG_FIFO_SIZE, 1,
+				&einfo->fifo_size);
+	mutex_lock(&einfo->tx_avail_lock);
+	einfo->fifo_fill.tx_avail = einfo->fifo_size.to_master;
+	mutex_unlock(&einfo->tx_avail_lock);
+	einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if);
+}
+
+static void glink_bgcom_event_handler(void *handle,
+		void *priv_data, enum bgcom_event_type event,
+		union bgcom_event_data_type *data)
+{
+	struct edge_info *einfo = (struct edge_info *)priv_data;
+	struct rx_pkt *rx_pkt_info;
+
+	switch (event) {
+	case BGCOM_EVENT_APPLICATION_RUNNING:
+		if (data->application_running &&
+				einfo->bgcom_status != BGCOM_LINKUP) {
+			einfo->bgcom_status |= BGCOM_APPLICATION_RUNNING;
+			glink_bgcom_linkup(einfo);
+		}
+		break;
+	case BGCOM_EVENT_TO_SLAVE_FIFO_READY:
+		if (data->to_slave_fifo_ready &&
+				einfo->bgcom_status != BGCOM_LINKUP) {
+			einfo->bgcom_status |= BGCOM_TO_SLAVE_FIFO_READY;
+			glink_bgcom_linkup(einfo);
+		}
+		break;
+	case BGCOM_EVENT_TO_MASTER_FIFO_READY:
+		if (data->to_master_fifo_ready &&
+				einfo->bgcom_status != BGCOM_LINKUP) {
+			einfo->bgcom_status |= BGCOM_TO_MASTER_FIFO_READY;
+			glink_bgcom_linkup(einfo);
+		}
+		break;
+	case BGCOM_EVENT_AHB_READY:
+		if (data->ahb_ready &&
+				einfo->bgcom_status != BGCOM_LINKUP) {
+			einfo->bgcom_status |= BGCOM_AHB_READY;
+			glink_bgcom_linkup(einfo);
+		}
+		break;
+	case BGCOM_EVENT_TO_MASTER_FIFO_USED:
+		rx_pkt_info = kzalloc(sizeof(struct rx_pkt), GFP_KERNEL);
+		rx_pkt_info->rx_buf = data->fifo_data.data;
+		rx_pkt_info->rx_len = data->fifo_data.to_master_fifo_used;
+		rx_pkt_info->einfo = einfo;
+		kthread_init_work(&rx_pkt_info->kwork, rx_worker);
+		kthread_queue_work(&einfo->kworker, &rx_pkt_info->kwork);
+		break;
+	case BGCOM_EVENT_TO_SLAVE_FIFO_FREE:
+		if (einfo->water_mark_reached)
+			tx_wakeup_worker(einfo);
+		break;
+	case BGCOM_EVENT_RESET_OCCURRED:
+		einfo->bgcom_status = BGCOM_RESET;
+		ssr(&einfo->xprt_if);
+		break;
+	case BGCOM_EVENT_ERROR_WRITE_FIFO_OVERRUN:
+	case BGCOM_EVENT_ERROR_WRITE_FIFO_BUS_ERR:
+	case BGCOM_EVENT_ERROR_WRITE_FIFO_ACCESS:
+	case BGCOM_EVENT_ERROR_READ_FIFO_UNDERRUN:
+	case BGCOM_EVENT_ERROR_READ_FIFO_BUS_ERR:
+	case BGCOM_EVENT_ERROR_READ_FIFO_ACCESS:
+	case BGCOM_EVENT_ERROR_TRUNCATED_READ:
+	case BGCOM_EVENT_ERROR_TRUNCATED_WRITE:
+	case BGCOM_EVENT_ERROR_AHB_ILLEGAL_ADDRESS:
+	case BGCOM_EVENT_ERROR_AHB_BUS_ERR:
+		GLINK_ERR("%s: ERROR %d", __func__, event);
+		break;
+	default:
+		GLINK_ERR("%s: unhandled event %d", __func__, event);
+		break;
+	}
+}
+
+/**
+ * init_xprt_if() - Initialize the xprt_if for an edge
+ * @einfo:	The edge to initialize.
+ */
+static void init_xprt_if(struct edge_info *einfo)
+{
+	einfo->xprt_if.tx_cmd_version = tx_cmd_version;
+	einfo->xprt_if.tx_cmd_version_ack = tx_cmd_version_ack;
+	einfo->xprt_if.set_version = set_version;
+	einfo->xprt_if.tx_cmd_ch_open = tx_cmd_ch_open;
+	einfo->xprt_if.tx_cmd_ch_close = tx_cmd_ch_close;
+	einfo->xprt_if.tx_cmd_ch_remote_open_ack = tx_cmd_ch_remote_open_ack;
+	einfo->xprt_if.tx_cmd_ch_remote_close_ack = tx_cmd_ch_remote_close_ack;
+	einfo->xprt_if.ssr = ssr;
+	einfo->xprt_if.allocate_rx_intent = allocate_rx_intent;
+	einfo->xprt_if.deallocate_rx_intent = deallocate_rx_intent;
+	einfo->xprt_if.tx_cmd_local_rx_intent = tx_cmd_local_rx_intent;
+	einfo->xprt_if.tx_cmd_local_rx_done = tx_cmd_local_rx_done;
+	einfo->xprt_if.tx = tx;
+	einfo->xprt_if.tx_cmd_rx_intent_req = tx_cmd_rx_intent_req;
+	einfo->xprt_if.tx_cmd_remote_rx_intent_req_ack =
+						tx_cmd_remote_rx_intent_req_ack;
+	einfo->xprt_if.tx_cmd_set_sigs = tx_cmd_set_sigs;
+	einfo->xprt_if.wait_link_down = wait_link_down;
+	einfo->xprt_if.tx_cmd_tracer_pkt = tx_cmd_tracer_pkt;
+	einfo->xprt_if.get_power_vote_ramp_time = get_power_vote_ramp_time;
+	einfo->xprt_if.power_vote = power_vote;
+	einfo->xprt_if.power_unvote = power_unvote;
+}
+
+/**
+ * init_xprt_cfg() - Initialize the xprt_cfg for an edge
+ * @einfo:	The edge to initialize.
+ * @name:	The name of the remote side this edge communicates to.
+ */
+static void init_xprt_cfg(struct edge_info *einfo, const char *name)
+{
+	einfo->xprt_cfg.name = XPRT_NAME;
+	einfo->xprt_cfg.edge = name;
+	einfo->xprt_cfg.versions = versions;
+	einfo->xprt_cfg.versions_entries = ARRAY_SIZE(versions);
+	einfo->xprt_cfg.max_cid = SZ_64K;
+	einfo->xprt_cfg.max_iid = SZ_2G;
+}
+
+/**
+ * parse_qos_dt_params() - Parse the power states from DT
+ * @dev:	Reference to the platform device for a specific edge.
+ * @einfo:	Edge information for the edge probe function is called.
+ *
+ * Return: 0 on success, standard error code otherwise.
+ */
+static int parse_qos_dt_params(struct device_node *node,
+				struct edge_info *einfo)
+{
+	int rc;
+	int i;
+	char *key;
+	uint32_t *arr32;
+	uint32_t num_states;
+
+	key = "qcom,ramp-time";
+	if (!of_find_property(node, key, &num_states))
+		return -ENODEV;
+
+	num_states /= sizeof(uint32_t);
+
+	einfo->num_pw_states = num_states;
+
+	arr32 = kmalloc_array(num_states, sizeof(uint32_t), GFP_KERNEL);
+	if (!arr32)
+		return -ENOMEM;
+
+	einfo->ramp_time_us = kmalloc_array(num_states, sizeof(unsigned long),
+					GFP_KERNEL);
+	if (!einfo->ramp_time_us) {
+		rc = -ENOMEM;
+		goto mem_alloc_fail;
+	}
+
+	rc = of_property_read_u32_array(node, key, arr32, num_states);
+	if (rc) {
+		rc = -ENODEV;
+		goto invalid_key;
+	}
+	for (i = 0; i < num_states; i++)
+		einfo->ramp_time_us[i] = arr32[i];
+
+	kfree(arr32);
+	return 0;
+
+invalid_key:
+	kfree(einfo->ramp_time_us);
+mem_alloc_fail:
+	kfree(arr32);
+	return rc;
+}
+
+static int glink_bgcom_probe(struct platform_device *pdev)
+{
+	struct device_node *node;
+	struct device_node *phandle_node;
+	struct edge_info *einfo;
+	int rc;
+	char *key;
+	const char *subsys_name;
+	unsigned long flags;
+
+	node = pdev->dev.of_node;
+
+	einfo = devm_kzalloc(&pdev->dev, sizeof(*einfo), GFP_KERNEL);
+	if (!einfo) {
+		rc = -ENOMEM;
+		goto edge_info_alloc_fail;
+	}
+
+	key = "label";
+	subsys_name = of_get_property(node, key, NULL);
+	if (!subsys_name) {
+		GLINK_ERR("%s: missing key %s\n", __func__, key);
+		rc = -ENODEV;
+		goto missing_key;
+	}
+	strlcpy(einfo->subsys_name, subsys_name, sizeof(einfo->subsys_name));
+
+	init_xprt_cfg(einfo, subsys_name);
+	init_xprt_if(einfo);
+
+	kthread_init_worker(&einfo->kworker);
+	init_srcu_struct(&einfo->use_ref);
+	mutex_init(&einfo->write_lock);
+	init_waitqueue_head(&einfo->tx_blocked_queue);
+	spin_lock_init(&einfo->activity_lock);
+	mutex_init(&einfo->tx_avail_lock);
+
+	spin_lock_irqsave(&edge_infos_lock, flags);
+	list_add_tail(&einfo->list, &edge_infos);
+	spin_unlock_irqrestore(&edge_infos_lock, flags);
+
+	einfo->task = kthread_run(kthread_worker_fn, &einfo->kworker,
+				  "bgcom_%s", subsys_name);
+	if (IS_ERR(einfo->task)) {
+		rc = PTR_ERR(einfo->task);
+		GLINK_ERR("%s: kthread run failed %d\n", __func__, rc);
+		goto kthread_fail;
+	}
+
+	key = "qcom,qos-config";
+	phandle_node = of_parse_phandle(node, key, 0);
+	if (phandle_node && !(of_get_glink_core_qos_cfg(phandle_node,
+							&einfo->xprt_cfg)))
+		parse_qos_dt_params(node, einfo);
+
+	rc = glink_core_register_transport(&einfo->xprt_if, &einfo->xprt_cfg);
+	if (rc == -EPROBE_DEFER)
+		goto reg_xprt_fail;
+	if (rc) {
+		GLINK_ERR("%s: glink core register transport failed: %d\n",
+			__func__, rc);
+		goto reg_xprt_fail;
+	}
+
+	einfo->bgcom_config.priv = (void *)einfo;
+	einfo->bgcom_config.bgcom_notification_cb = glink_bgcom_event_handler;
+	einfo->bgcom_handle = NULL;
+	dev_set_drvdata(&pdev->dev, einfo);
+	if (!strcmp(einfo->xprt_cfg.edge, "bg")) {
+		einfo->bgcom_handle = bgcom_open(&einfo->bgcom_config);
+		if (!einfo->bgcom_handle) {
+			GLINK_ERR("%s: bgcom open failed\n", __func__);
+			rc = -ENODEV;
+			goto bgcom_open_fail;
+		}
+	}
+	return 0;
+
+bgcom_open_fail:
+	dev_set_drvdata(&pdev->dev, NULL);
+	glink_core_unregister_transport(&einfo->xprt_if);
+reg_xprt_fail:
+	kthread_flush_worker(&einfo->kworker);
+	kthread_stop(einfo->task);
+	einfo->task = NULL;
+kthread_fail:
+	spin_lock_irqsave(&edge_infos_lock, flags);
+	list_del(&einfo->list);
+	spin_unlock_irqrestore(&edge_infos_lock, flags);
+missing_key:
+	kfree(einfo);
+edge_info_alloc_fail:
+	return rc;
+}
+
+static int glink_bgcom_remove(struct platform_device *pdev)
+{
+	struct edge_info *einfo;
+	unsigned long flags;
+
+	einfo = (struct edge_info *)dev_get_drvdata(&pdev->dev);
+	bgcom_close(&einfo->bgcom_handle);
+	glink_core_unregister_transport(&einfo->xprt_if);
+	kthread_flush_worker(&einfo->kworker);
+	kthread_stop(einfo->task);
+	einfo->task = NULL;
+	spin_lock_irqsave(&edge_infos_lock, flags);
+	list_del(&einfo->list);
+	spin_unlock_irqrestore(&edge_infos_lock, flags);
+	return 0;
+}
+
+static int glink_bgcom_resume(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static int glink_bgcom_suspend(struct platform_device *pdev,
+				   pm_message_t state)
+{
+	unsigned long flags;
+	struct edge_info *einfo;
+	bool suspend;
+	int rc = -EBUSY;
+
+	einfo = (struct edge_info *)dev_get_drvdata(&pdev->dev);
+	if (strcmp(einfo->xprt_cfg.edge, "bg"))
+		return 0;
+
+	spin_lock_irqsave(&einfo->activity_lock, flags);
+	suspend = !(einfo->activity_flag);
+	spin_unlock_irqrestore(&einfo->activity_lock, flags);
+	if (suspend)
+		rc = bgcom_suspend(einfo->bgcom_handle);
+	if (rc < 0)
+		GLINK_ERR("%s: Could not suspend activity_flag %d, rc %d\n",
+			__func__, einfo->activity_flag, rc);
+	return rc;
+}
+
+static const struct of_device_id bgcom_match_table[] = {
+	{ .compatible = "qcom,glink-bgcom-xprt" },
+	{},
+};
+
+static struct platform_driver glink_bgcom_driver = {
+	.probe = glink_bgcom_probe,
+	.remove = glink_bgcom_remove,
+	.resume = glink_bgcom_resume,
+	.suspend = glink_bgcom_suspend,
+	.driver = {
+		.name = "msm_glink_bgcom_xprt",
+		.owner = THIS_MODULE,
+		.of_match_table = bgcom_match_table,
+	},
+};
+
+static int __init glink_bgcom_xprt_init(void)
+{
+	int rc;
+
+	rc = platform_driver_register(&glink_bgcom_driver);
+	if (rc)
+		GLINK_ERR("%s: glink_bgcom register failed %d\n", __func__, rc);
+
+	return rc;
+}
+module_init(glink_bgcom_xprt_init);
+
+static void __exit glink_bgcom_xprt_exit(void)
+{
+	platform_driver_unregister(&glink_bgcom_driver);
+}
+module_exit(glink_bgcom_xprt_exit);
+
+MODULE_DESCRIPTION("MSM G-Link bgcom Transport");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/glink_private.h b/drivers/soc/qcom/glink_private.h
index 31c1721..c982cbd 100644
--- a/drivers/soc/qcom/glink_private.h
+++ b/drivers/soc/qcom/glink_private.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
@@ -824,6 +824,14 @@
  */
 int glink_ssr(const char *subsystem);
 
+/*
+ * glink_subsys_up() - SSR sub system up function.
+ * @subsystem:	Constant string for name of remote subsystem.
+ *
+ * Return: Standard error code.
+ */
+int glink_subsys_up(const char *subsystem);
+
 /**
  * notify for subsystem() - Notify other subsystems that a subsystem is being
  *                          restarted
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index baebb25..dda2178 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -947,15 +947,6 @@
 
 	rcu_id = srcu_read_lock(&einfo->use_ref);
 
-	if (unlikely(!einfo->rx_fifo) && atomic_ctx) {
-		if (!get_rx_fifo(einfo)) {
-			srcu_read_unlock(&einfo->use_ref, rcu_id);
-			return;
-		}
-		einfo->in_ssr = false;
-		einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if);
-	}
-
 	if (einfo->in_ssr) {
 		srcu_read_unlock(&einfo->use_ref, rcu_id);
 		return;
@@ -1569,6 +1560,24 @@
 }
 
 /**
+ * subsys_up() - process a subsystem up notification
+ * @if_ptr:	The transport which is up
+ *
+ */
+static void subsys_up(struct glink_transport_if *if_ptr)
+{
+	struct edge_info *einfo;
+
+	einfo = container_of(if_ptr, struct edge_info, xprt_if);
+	if (!einfo->rx_fifo) {
+		if (!get_rx_fifo(einfo))
+			return;
+		einfo->in_ssr = false;
+		einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if);
+	}
+}
+
+/**
  * ssr() - process a subsystem restart notification of a transport
  * @if_ptr:	The transport to restart
  *
@@ -2261,6 +2270,7 @@
 	einfo->xprt_if.tx_cmd_ch_remote_open_ack = tx_cmd_ch_remote_open_ack;
 	einfo->xprt_if.tx_cmd_ch_remote_close_ack = tx_cmd_ch_remote_close_ack;
 	einfo->xprt_if.ssr = ssr;
+	einfo->xprt_if.subsys_up = subsys_up;
 	einfo->xprt_if.allocate_rx_intent = allocate_rx_intent;
 	einfo->xprt_if.deallocate_rx_intent = deallocate_rx_intent;
 	einfo->xprt_if.tx_cmd_local_rx_intent = tx_cmd_local_rx_intent;
@@ -2555,6 +2565,7 @@
 									rc);
 		goto request_irq_fail;
 	}
+	einfo->in_ssr = true;
 	rc = enable_irq_wake(irq_line);
 	if (rc < 0)
 		pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
@@ -3102,6 +3113,7 @@
 	cfg_p_addr = smem_virt_to_phys(mbox_cfg);
 	writel_relaxed(lower_32_bits(cfg_p_addr), mbox_loc);
 	writel_relaxed(upper_32_bits(cfg_p_addr), mbox_loc + 4);
+	einfo->in_ssr = true;
 	send_irq(einfo);
 	iounmap(mbox_size);
 	iounmap(mbox_loc);
diff --git a/drivers/soc/qcom/glink_ssr.c b/drivers/soc/qcom/glink_ssr.c
index 7f97ab0..c16621a 100644
--- a/drivers/soc/qcom/glink_ssr.c
+++ b/drivers/soc/qcom/glink_ssr.c
@@ -266,18 +266,37 @@
 				__func__);
 		return;
 	}
-	if (unlikely(!do_cleanup_data))
-		goto missing_do_cleanup_data;
-	if (unlikely(!cb_data))
-		goto missing_cb_data;
-	if (unlikely(!resp))
-		goto missing_response;
-	if (unlikely(resp->version != do_cleanup_data->version))
-		goto version_mismatch;
-	if (unlikely(resp->seq_num != do_cleanup_data->seq_num))
-		goto invalid_seq_number;
-	if (unlikely(resp->response != GLINK_SSR_CLEANUP_DONE))
-		goto wrong_response;
+	if (unlikely(!do_cleanup_data)) {
+		GLINK_SSR_ERR("<SSR> %s: Missing do_cleanup data!\n", __func__);
+		goto no_clean_done;
+	}
+	if (unlikely(!cb_data)) {
+		GLINK_SSR_ERR("<SSR> %s: Missing cb_data!\n", __func__);
+		goto done;
+	}
+	if (unlikely(!resp)) {
+		GLINK_SSR_ERR("<SSR> %s: Missing response data\n", __func__);
+		goto done;
+	}
+	if (unlikely(resp->version != do_cleanup_data->version)) {
+		GLINK_SSR_ERR("<SSR> %s: Version mismatch. %s[%d], %s[%d]\n",
+			__func__, "do_cleanup version",
+			do_cleanup_data->version, "cleanup_done version",
+			resp->version);
+		goto done;
+	}
+	if (unlikely(resp->seq_num != do_cleanup_data->seq_num)) {
+		GLINK_SSR_ERR("<SSR> %s: Invalid seq. number %s[%d], %s[%d]\n",
+			__func__, "do_cleanup seq num",
+			do_cleanup_data->seq_num,
+			"cleanup_done seq_num", resp->seq_num);
+		goto done;
+	}
+	if (unlikely(resp->response != GLINK_SSR_CLEANUP_DONE)) {
+		GLINK_SSR_ERR("<SSR> %s: Not a cleaup_done message. %s[%d]\n",
+			__func__, "cleanup_done response", resp->response);
+		goto done;
+	}
 
 	cb_data->responded = true;
 	atomic_dec(&responses_remaining);
@@ -287,38 +306,15 @@
 			__func__, cb_data->edge, resp->response,
 			resp->version, resp->seq_num,
 			do_cleanup_data->name);
-
+done:
 	kfree(do_cleanup_data);
+no_clean_done:
 	rx_done_work->ptr = ptr;
 	rx_done_work->handle = handle;
 	INIT_WORK(&rx_done_work->work, rx_done_cb_worker);
 	queue_work(glink_ssr_wq, &rx_done_work->work);
 	wake_up(&waitqueue);
 	return;
-
-missing_cb_data:
-	panic("%s: Missing cb_data!\n", __func__);
-	return;
-missing_do_cleanup_data:
-	panic("%s: Missing do_cleanup data!\n", __func__);
-	return;
-missing_response:
-	GLINK_SSR_ERR("<SSR> %s: Missing response data\n", __func__);
-	return;
-version_mismatch:
-	GLINK_SSR_ERR("<SSR> %s: Version mismatch. %s[%d], %s[%d]\n", __func__,
-			"do_cleanup version", do_cleanup_data->version,
-			"cleanup_done version", resp->version);
-	return;
-invalid_seq_number:
-	GLINK_SSR_ERR("<SSR> %s: Invalid seq. number. %s[%d], %s[%d]\n",
-			__func__, "do_cleanup seq num",
-			do_cleanup_data->seq_num,
-			"cleanup_done seq_num", resp->seq_num);
-	return;
-wrong_response:
-	GLINK_SSR_ERR("<SSR> %s: Not a cleaup_done message. %s[%d]\n", __func__,
-			"cleanup_done response", resp->response);
 }
 
 /**
@@ -492,6 +488,17 @@
 					"Subsystem notification failed", ret);
 			return ret;
 		}
+	} else if (code == SUBSYS_AFTER_POWERUP) {
+		GLINK_SSR_LOG("<SSR> %s: %s: subsystem restart for %s\n",
+				__func__, "SUBSYS_AFTER_POWERUP",
+				notifier->subsystem);
+		ss_info = get_info_for_subsystem(notifier->subsystem);
+		if (ss_info == NULL) {
+			GLINK_SSR_ERR("<SSR> %s: ss_info is NULL\n", __func__);
+			return -EINVAL;
+		}
+
+		glink_subsys_up(ss_info->edge);
 	}
 	return NOTIFY_DONE;
 }
@@ -958,13 +965,6 @@
 	key = "qcom,notify-edges";
 	while (true) {
 		phandle_node = of_parse_phandle(node, key, phandle_index++);
-		if (!phandle_node && phandle_index == 0) {
-			GLINK_SSR_ERR(
-				"<SSR> %s: qcom,notify-edges is not present",
-				__func__);
-			ret = -ENODEV;
-			goto notify_edges_not_present;
-		}
 
 		if (!phandle_node)
 			break;
@@ -976,7 +976,7 @@
 				"<SSR> %s: Could not allocate subsys_info_leaf\n",
 				__func__);
 			ret = -ENOMEM;
-			goto notify_edges_not_present;
+			goto notify_edges_no_memory;
 		}
 
 		subsys_name = of_get_property(phandle_node, "label", NULL);
@@ -1019,7 +1019,7 @@
 	list_del(&ss_info->subsystem_list_node);
 invalid_dt_node:
 	kfree(ss_info_leaf);
-notify_edges_not_present:
+notify_edges_no_memory:
 	subsys_notif_unregister_notifier(handle, &nb->nb);
 	delete_ss_info_notify_list(ss_info);
 nb_registration_fail:
diff --git a/drivers/soc/qcom/glink_xprt_if.h b/drivers/soc/qcom/glink_xprt_if.h
index 47c1580..1902152 100644
--- a/drivers/soc/qcom/glink_xprt_if.h
+++ b/drivers/soc/qcom/glink_xprt_if.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
@@ -105,6 +105,7 @@
 	void (*tx_cmd_ch_remote_close_ack)(struct glink_transport_if *if_ptr,
 			uint32_t rcid);
 	int (*ssr)(struct glink_transport_if *if_ptr);
+	void (*subsys_up)(struct glink_transport_if *if_ptr);
 
 	/* channel data */
 	int (*allocate_rx_intent)(struct glink_transport_if *if_ptr,
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 8e0a61d..683b074 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -471,6 +471,8 @@
 	u16 line_number;
 	char function_name[QMI_WLFW_FUNCTION_NAME_LEN_V01 + 1];
 	struct mutex dev_lock;
+	uint32_t fw_error_fatal_irq;
+	uint32_t fw_early_crash_irq;
 } *penv;
 
 #ifdef CONFIG_ICNSS_DEBUG
@@ -1216,17 +1218,21 @@
 	return IRQ_HANDLED;
 }
 
-static void register_fw_error_notifications(struct icnss_priv *priv)
+static void register_fw_error_notifications(struct device *dev)
 {
-	int gpio, irq, ret;
+	struct icnss_priv *priv = dev_get_drvdata(dev);
+	int gpio = 0, irq = 0, ret = 0;
 
-	if (!of_find_property(priv->pdev->dev.of_node,
-				"qcom,gpio-force-fatal-error", NULL)) {
+	if (!priv)
+		return;
+
+	if (!of_find_property(dev->of_node, "qcom,gpio-force-fatal-error",
+			      NULL)) {
 		icnss_pr_dbg("Error fatal smp2p handler not registered\n");
 		return;
 	}
-	gpio = of_get_named_gpio(priv->pdev->dev.of_node,
-				"qcom,gpio-force-fatal-error", 0);
+	gpio = of_get_named_gpio(dev->of_node, "qcom,gpio-force-fatal-error",
+				 0);
 	if (!gpio_is_valid(gpio)) {
 		icnss_pr_err("Invalid GPIO for error fatal smp2p %d\n", gpio);
 		return;
@@ -1236,22 +1242,31 @@
 		icnss_pr_err("Invalid IRQ for error fatal smp2p %u\n", irq);
 		return;
 	}
-	ret = request_irq(irq, fw_error_fatal_handler,
-			IRQF_TRIGGER_RISING, "wlanfw-err", priv);
+	ret = devm_request_irq(dev, irq, fw_error_fatal_handler,
+			       IRQF_TRIGGER_RISING, "wlanfw-err", priv);
 	if (ret < 0) {
 		icnss_pr_err("Unable to register for error fatal IRQ handler %d",
-				irq);
+			     irq);
 		return;
 	}
-	icnss_pr_dbg("FW force error fatal handler registered\n");
+	icnss_pr_dbg("FW force error fatal handler registered irq = %d\n", irq);
+	priv->fw_error_fatal_irq = irq;
+}
 
-	if (!of_find_property(priv->pdev->dev.of_node,
-				"qcom,gpio-early-crash-ind", NULL)) {
+static void register_early_crash_notifications(struct device *dev)
+{
+	struct icnss_priv *priv = dev_get_drvdata(dev);
+	int gpio = 0, irq = 0, ret = 0;
+
+	if (!priv)
+		return;
+
+	if (!of_find_property(dev->of_node, "qcom,gpio-early-crash-ind",
+			      NULL)) {
 		icnss_pr_dbg("FW early crash indication handler not registered\n");
 		return;
 	}
-	gpio = of_get_named_gpio(priv->pdev->dev.of_node,
-				"qcom,gpio-early-crash-ind", 0);
+	gpio = of_get_named_gpio(dev->of_node, "qcom,gpio-early-crash-ind", 0);
 	if (!gpio_is_valid(gpio)) {
 		icnss_pr_err("Invalid GPIO for early crash indication %d\n",
 				gpio);
@@ -1263,14 +1278,16 @@
 				irq);
 		return;
 	}
-	ret = request_irq(irq, fw_crash_indication_handler,
-			IRQF_TRIGGER_RISING, "wlanfw-early-crash-ind", priv);
+	ret = devm_request_irq(dev, irq, fw_crash_indication_handler,
+			       IRQF_TRIGGER_RISING, "wlanfw-early-crash-ind",
+			       priv);
 	if (ret < 0) {
 		icnss_pr_err("Unable to register for early crash indication IRQ handler %d",
 				irq);
 		return;
 	}
-	icnss_pr_dbg("FW crash indication handler registered\n");
+	icnss_pr_dbg("FW crash indication handler registered irq = %d\n", irq);
+	priv->fw_early_crash_irq = irq;
 }
 
 static int wlfw_msa_mem_info_send_sync_msg(void)
@@ -2162,7 +2179,11 @@
 
 	icnss_init_vph_monitor(penv);
 
-	register_fw_error_notifications(penv);
+	if (!penv->fw_error_fatal_irq)
+		register_fw_error_notifications(&penv->pdev->dev);
+
+	if (!penv->fw_early_crash_irq)
+		register_early_crash_notifications(&penv->pdev->dev);
 
 	return ret;
 
@@ -2571,6 +2592,8 @@
 		break;
 
 	case QMI_SERVER_EXIT:
+		set_bit(ICNSS_FW_DOWN, &penv->state);
+		icnss_ignore_qmi_timeout(true);
 		ret = icnss_driver_event_post(ICNSS_DRIVER_EVENT_SERVER_EXIT,
 					      0, NULL);
 		break;
diff --git a/drivers/soc/qcom/idle-v7.S b/drivers/soc/qcom/idle-v7.S
new file mode 100644
index 0000000..b0ceaf5
--- /dev/null
+++ b/drivers/soc/qcom/idle-v7.S
@@ -0,0 +1,69 @@
+/*
+ * Idle processing for ARMv7-based Qualcomm SoCs.
+ *
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2007-2009, 2011-2014, 2018, The Linux Foundation.
+ * All rights reserved.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <linux/threads.h>
+#include <asm/assembler.h>
+
+	.arm
+ENTRY(msm_pm_boot_entry)
+THUMB(	adr	r9, BSYM(2f)	)	/* Kernel is always entered in ARM. */
+THUMB(	bx	r9		)	/* If this is a Thumb-2 kernel, */
+THUMB(	.thumb			)	/* switch to Thumb now.		*/
+THUMB(2:			)
+	mrc     p15, 0, r0, c0, c0, 5    /* MPIDR                          */
+	bic     r0, #0xff000000         /* what CPU am I */
+	bic     r0, #0x00ff0000         /* clear bits 31-16 */
+
+	adr	r3, 3f
+	ldr	r1, [r3]
+	sub	r3, r1, r3		/* r3 holds the virt to phy offset */
+	ldr	r1, =msm_pc_debug_counters_phys /* phys addr for IMEM reg */
+	sub	r1, r1, r3			/* translate virt to phys */
+	ldr	r1,[r1]
+	cmp	r1, #0
+	beq	skip_pc_debug3
+	mov     r2, r0, lsr #8		/* get cluster num */
+	add 	r1, r1, r2, lsl #6	/* get offset of cluster */
+	and	r2, r0, #0xff
+	add	r1, r1, r2, lsl #4	/* get offset for the cpu */
+	add	r1, #4			/* warmboot entry counter */
+	ldr	r2, [r1]
+	add	r2, #1
+	str	r2, [r1]
+skip_pc_debug3:
+	ldr     r1, =msm_pm_boot_vector
+	sub	r1, r1, r3		/* translate virt to phys */
+	mov     r2, r0, lsr #8		/* get cluster num */
+	add	r1, r1, r2, lsl #4	/* Get offset for the cluster */
+	and	r0, r0, #0xff		/* cpu id */
+	add	r1, r1, r0, lsl #2	/* Get offset for the cpu */
+	ldr     pc, [r1]                 /* jump                    */
+ENDPROC(msm_pm_boot_entry)
+
+3:	.long	.
+
+	.data
+
+	.globl msm_pm_boot_vector
+msm_pm_boot_vector:
+	.space  4 * 4 * 4
+
+	.globl msm_pc_debug_counters_phys
+msm_pc_debug_counters_phys:
+	.long 0x0
diff --git a/drivers/soc/qcom/memshare/msm_memshare.c b/drivers/soc/qcom/memshare/msm_memshare.c
index 77a76d2..696c043 100644
--- a/drivers/soc/qcom/memshare/msm_memshare.c
+++ b/drivers/soc/qcom/memshare/msm_memshare.c
@@ -352,7 +352,7 @@
 static int modem_notifier_cb(struct notifier_block *this, unsigned long code,
 					void *_cmd)
 {
-	int i, ret;
+	int i, ret, size = 0;
 	u32 source_vmlist[1] = {VMID_MSS_MSA};
 	int dest_vmids[1] = {VMID_HLOS};
 	int dest_perms[1] = {PERM_READ|PERM_WRITE|PERM_EXEC};
@@ -393,6 +393,7 @@
 	case SUBSYS_AFTER_POWERUP:
 		pr_debug("memshare: Modem has booted up\n");
 		for (i = 0; i < MAX_CLIENTS; i++) {
+			size = memblock[i].size;
 			if (memblock[i].free_memory > 0 &&
 					bootup_request >= 2) {
 				memblock[i].free_memory -= 1;
@@ -430,9 +431,18 @@
 						memblock[i].hyp_mapping = 0;
 					}
 				}
+				if (memblock[i].client_id == 1) {
+					/*
+					 *	Check if the client id
+					 *	is of diag so that free
+					 *	the memory region of
+					 *	client's size + guard
+					 *	bytes of 4K.
+					 */
+					size += MEMSHARE_GUARD_BYTES;
+				}
 				dma_free_attrs(memsh_drv->dev,
-					memblock[i].size,
-					memblock[i].virtual_addr,
+					size, memblock[i].virtual_addr,
 					memblock[i].phy_addr,
 					attrs);
 				free_client(i);
@@ -635,7 +645,7 @@
 {
 	struct mem_free_generic_req_msg_v01 *free_req;
 	struct mem_free_generic_resp_msg_v01 free_resp;
-	int rc, flag = 0, ret = 0;
+	int rc, flag = 0, ret = 0, size = 0;
 	uint32_t client_id;
 	u32 source_vmlist[1] = {VMID_MSS_MSA};
 	int dest_vmids[1] = {VMID_HLOS};
@@ -669,7 +679,18 @@
 			pr_err("memshare: %s, failed to unmap the region\n",
 				__func__);
 		}
-		dma_free_attrs(memsh_drv->dev, memblock[client_id].size,
+		size = memblock[client_id].size;
+		if (memblock[client_id].client_id == 1) {
+			/*
+			 *	Check if the client id
+			 *	is of diag so that free
+			 *	the memory region of
+			 *	client's size + guard
+			 *	bytes of 4K.
+			 */
+			size += MEMSHARE_GUARD_BYTES;
+		}
+		dma_free_attrs(memsh_drv->dev, size,
 			memblock[client_id].virtual_addr,
 			memblock[client_id].phy_addr,
 			attrs);
diff --git a/drivers/soc/qcom/msm-spm.c b/drivers/soc/qcom/msm-spm.c
index 3033a4a..03b1c56 100644
--- a/drivers/soc/qcom/msm-spm.c
+++ b/drivers/soc/qcom/msm-spm.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
@@ -189,21 +189,12 @@
 }
 
 static inline void msm_spm_drv_set_vctl2(struct msm_spm_driver_data *dev,
-		uint32_t vlevel)
+				uint32_t vlevel, uint32_t vctl_port)
 {
 	unsigned int pmic_data = 0;
 
-	/**
-	 * VCTL_PORT has to be 0, for PMIC_STS register to be updated.
-	 * Ensure that vctl_port is always set to 0.
-	 */
-	if (dev->vctl_port) {
-		__WARN();
-		return;
-	}
-
 	pmic_data |= vlevel;
-	pmic_data |= (dev->vctl_port & 0x7) << 16;
+	pmic_data |= (vctl_port & 0x7) << 16;
 
 	dev->reg_shadow[MSM_SPM_REG_SAW_VCTL] &= ~0x700FF;
 	dev->reg_shadow[MSM_SPM_REG_SAW_VCTL] |= pmic_data;
@@ -510,10 +501,46 @@
 		unsigned int vlevel) { }
 #endif
 
+static inline int msm_spm_drv_validate_data(struct msm_spm_driver_data *dev,
+					unsigned int vlevel, int vctl_port)
+{
+	int timeout_us = dev->vctl_timeout_us;
+	uint32_t new_level;
+
+	/* Confirm the voltage we set was what hardware sent and
+	 * FSM is idle.
+	 */
+	do {
+		udelay(1);
+		new_level = msm_spm_drv_get_sts_curr_pmic_data(dev);
+
+		/**
+		 * VCTL_PORT has to be 0, for vlevel to be updated.
+		 * If port is not 0, check for PMIC_STATE only.
+		 */
+
+		if (((new_level & 0x30000) == MSM_SPM_PMIC_STATE_IDLE) &&
+				(vctl_port || ((new_level & 0xFF) == vlevel)))
+			break;
+	} while (--timeout_us);
+
+	if (!timeout_us) {
+		pr_err("Wrong level %#x\n", new_level);
+		return -EIO;
+	}
+
+	if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL)
+		pr_info("%s: done, remaining timeout %u us\n",
+			__func__, timeout_us);
+
+	return 0;
+}
+
 int msm_spm_drv_set_vdd(struct msm_spm_driver_data *dev, unsigned int vlevel)
 {
-	uint32_t timeout_us, new_level;
+	uint32_t vlevel_set = vlevel;
 	bool avs_enabled;
+	int ret = 0;
 
 	if (!dev)
 		return -EINVAL;
@@ -529,45 +556,63 @@
 	if (avs_enabled)
 		msm_spm_drv_disable_avs(dev);
 
+	if (dev->vctl_port_ub >= 0) {
+		/**
+		 * VCTL can send 8bit voltage level at once.
+		 * Send lower 8bit first, vlevel change happens
+		 * when upper 8bit is sent.
+		 */
+		vlevel = vlevel_set & 0xFF;
+	}
+
 	/* Kick the state machine back to idle */
 	dev->reg_shadow[MSM_SPM_REG_SAW_RST] = 1;
 	msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW_RST);
 
-	msm_spm_drv_set_vctl2(dev, vlevel);
+	msm_spm_drv_set_vctl2(dev, vlevel, dev->vctl_port);
 
-	timeout_us = dev->vctl_timeout_us;
-	/* Confirm the voltage we set was what hardware sent */
-	do {
-		udelay(1);
-		new_level = msm_spm_drv_get_sts_curr_pmic_data(dev);
-		/* FSM is idle */
-		if (((new_level & 0x30000) == 0) &&
-				((new_level & 0xFF) == vlevel))
-			break;
-	} while (--timeout_us);
-	if (!timeout_us) {
-		pr_info("Wrong level %#x\n", new_level);
+	ret = msm_spm_drv_validate_data(dev, vlevel, dev->vctl_port);
+	if (ret)
 		goto set_vdd_bail;
-	}
 
-	if (msm_spm_debug_mask & MSM_SPM_DEBUG_VCTL)
-		pr_info("%s: done, remaining timeout %u us\n",
-			__func__, timeout_us);
+	if (dev->vctl_port_ub >= 0) {
+		/* Send upper 8bit of voltage level */
+		vlevel = (vlevel_set >> 8) & 0xFF;
+
+		/* Kick the state machine back to idle */
+		dev->reg_shadow[MSM_SPM_REG_SAW_RST] = 1;
+		msm_spm_drv_flush_shadow(dev, MSM_SPM_REG_SAW_RST);
+
+		/*
+		 * Steps for sending for vctl port other than '0'
+		 * Write VCTL register with pmic data and address index
+		 * Perform system barrier
+		 * Wait for 1us
+		 * Read PMIC_STS register to make sure operation is complete
+		 */
+		msm_spm_drv_set_vctl2(dev, vlevel, dev->vctl_port_ub);
+
+		mb(); /* To make sure data is sent before checking status */
+
+		ret = msm_spm_drv_validate_data(dev, vlevel, dev->vctl_port_ub);
+		if (ret)
+			goto set_vdd_bail;
+	}
 
 	/* Set AVS min/max */
 	if (avs_enabled) {
-		msm_spm_drv_set_avs_vlevel(dev, vlevel);
+		msm_spm_drv_set_avs_vlevel(dev, vlevel_set);
 		msm_spm_drv_enable_avs(dev);
 	}
 
-	return 0;
+	return ret;
 
 set_vdd_bail:
 	if (avs_enabled)
 		msm_spm_drv_enable_avs(dev);
 
-	pr_err("%s: failed %#x, remaining timeout %uus, vlevel %#x\n",
-		__func__, vlevel, timeout_us, new_level);
+	pr_err("%s: failed %#x vlevel setting in timeout %uus\n",
+			__func__, vlevel_set, dev->vctl_timeout_us);
 	return -EIO;
 }
 
@@ -697,6 +742,7 @@
 		return -ENODEV;
 
 	dev->vctl_port = data->vctl_port;
+	dev->vctl_port_ub = data->vctl_port_ub;
 	dev->phase_port = data->phase_port;
 	dev->pfm_port = data->pfm_port;
 	dev->reg_base_addr = data->reg_base_addr;
diff --git a/drivers/soc/qcom/pil_bg_intf.h b/drivers/soc/qcom/pil_bg_intf.h
new file mode 100644
index 0000000..722024b
--- /dev/null
+++ b/drivers/soc/qcom/pil_bg_intf.h
@@ -0,0 +1,43 @@
+/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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 __BG_INTF_H_
+#define __BG_INTF_H_
+
+#define MAX_APP_NAME_SIZE 100
+#define RESULT_SUCCESS 0
+#define RESULT_FAILURE -1
+
+/* tzapp command list.*/
+enum bg_tz_commands {
+	BGPIL_RAMDUMP,
+	BGPIL_IMAGE_LOAD,
+	BGPIL_AUTH_MDT,
+	BGPIL_DLOAD_CONT,
+};
+
+/* tzapp bg request.*/
+__packed struct tzapp_bg_req {
+	uint8_t tzapp_bg_cmd;
+	phys_addr_t address_fw;
+	size_t size_fw;
+};
+
+/* tzapp bg response.*/
+__packed struct tzapp_bg_rsp {
+	uint32_t tzapp_bg_cmd;
+	uint32_t bg_info_len;
+	uint32_t status;
+	uint32_t bg_info[100];
+};
+
+#endif
diff --git a/drivers/soc/qcom/rpmh_master_stat.c b/drivers/soc/qcom/rpmh_master_stat.c
index e696d4d..3a77ed8 100644
--- a/drivers/soc/qcom/rpmh_master_stat.c
+++ b/drivers/soc/qcom/rpmh_master_stat.c
@@ -103,6 +103,7 @@
 				struct msm_rpmh_master_stats *record,
 				const char *name)
 {
+	uint64_t temp_accumulated_duration = record->accumulated_duration;
 	/*
 	 * If a master is in sleep when reading the sleep stats from SMEM
 	 * adjust the accumulated sleep duration to show actual sleep time.
@@ -110,7 +111,7 @@
 	 * the purpose of computing battery utilization.
 	 */
 	if (record->last_entered > record->last_exited)
-		record->accumulated_duration +=
+		temp_accumulated_duration +=
 				(arch_counter_get_cntvct()
 				- record->last_entered);
 
@@ -121,7 +122,7 @@
 			"\tSleep Accumulated Duration:0x%llx\n\n",
 			name, record->version_id, record->counts,
 			record->last_entered, record->last_exited,
-			record->accumulated_duration);
+			temp_accumulated_duration);
 }
 
 static ssize_t msm_rpmh_master_stats_show(struct kobject *kobj,
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index d8fcf5f..e02bf84 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -605,6 +605,7 @@
 
 	/* SDM450 ID */
 	[338] = {MSM_CPU_SDM450, "SDM450"},
+	[351] = {MSM_CPU_SDM450, "SDA450"},
 
 	/* SDM632 ID */
 	[349] = {MSM_CPU_SDM632, "SDM632"},
@@ -617,6 +618,8 @@
 	/* SDM429 and SDM439 ID*/
 	[353] = {MSM_CPU_SDM439, "SDM439"},
 	[354] = {MSM_CPU_SDM429, "SDM429"},
+	[363] = {MSM_CPU_SDA439, "SDA439"},
+	[364] = {MSM_CPU_SDA429, "SDA429"},
 
 	/* Uninitialized IDs are not known to run Linux.
 	 * MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
@@ -1573,6 +1576,14 @@
 		dummy_socinfo.id = 354;
 		strlcpy(dummy_socinfo.build_id, "sdm429 - ",
 				sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_sda439()) {
+		dummy_socinfo.id = 363;
+		strlcpy(dummy_socinfo.build_id, "sda439 - ",
+				sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_sda429()) {
+		dummy_socinfo.id = 364;
+		strlcpy(dummy_socinfo.build_id, "sda429 - ",
+				sizeof(dummy_socinfo.build_id));
 	} else if (early_machine_is_mdm9607()) {
 		dummy_socinfo.id = 290;
 		strlcpy(dummy_socinfo.build_id, "mdm9607 - ",
diff --git a/drivers/soc/qcom/spm_devices.c b/drivers/soc/qcom/spm_devices.c
index 06c8be4..5f1ac4e 100644
--- a/drivers/soc/qcom/spm_devices.c
+++ b/drivers/soc/qcom/spm_devices.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
@@ -782,12 +782,16 @@
 	}
 
 	spm_data.vctl_port = -1;
+	spm_data.vctl_port_ub = -1;
 	spm_data.phase_port = -1;
 	spm_data.pfm_port = -1;
 
 	key = "qcom,vctl-port";
 	of_property_read_u32(node, key, &spm_data.vctl_port);
 
+	key = "qcom,vctl-port-ub";
+	of_property_read_u32(node, key, &spm_data.vctl_port_ub);
+
 	key = "qcom,phase-port";
 	of_property_read_u32(node, key, &spm_data.phase_port);
 
diff --git a/drivers/soc/qcom/spm_driver.h b/drivers/soc/qcom/spm_driver.h
index a645813..198267a 100644
--- a/drivers/soc/qcom/spm_driver.h
+++ b/drivers/soc/qcom/spm_driver.h
@@ -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
@@ -62,6 +62,7 @@
 
 	uint32_t ver_reg;
 	uint32_t vctl_port;
+	int vctl_port_ub;
 	uint32_t phase_port;
 	uint32_t pfm_port;
 
@@ -84,6 +85,7 @@
 	uint32_t minor;
 	uint32_t ver_reg;
 	uint32_t vctl_port;
+	int vctl_port_ub;
 	uint32_t phase_port;
 	uint32_t pfm_port;
 	void __iomem *reg_base_addr;
diff --git a/drivers/soc/qcom/subsys-pil-bg.c b/drivers/soc/qcom/subsys-pil-bg.c
new file mode 100644
index 0000000..75c3666
--- /dev/null
+++ b/drivers/soc/qcom/subsys-pil-bg.c
@@ -0,0 +1,771 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/interrupt.h>
+#include <linux/of_gpio.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/reboot.h>
+#include <soc/qcom/subsystem_restart.h>
+#include <soc/qcom/ramdump.h>
+#include <soc/qcom/subsystem_notif.h>
+#include <linux/highmem.h>
+
+#include "peripheral-loader.h"
+#include "../../misc/qseecom_kernel.h"
+#include "pil_bg_intf.h"
+
+#define INVALID_GPIO	-1
+#define NUM_GPIOS	4
+#define SECURE_APP	"bgapp"
+#define desc_to_data(d)	container_of(d, struct pil_bg_data, desc)
+#define subsys_to_data(d) container_of(d, struct pil_bg_data, subsys_desc)
+#define BG_RAMDUMP_SZ	0x00102000
+#define BG_CRASH_IN_TWM	2
+/**
+ * struct pil_bg_data
+ * @qseecom_handle: handle of TZ app
+ * @bg_queue: private queue to schedule worker threads for bottom half
+ * @restart_work: work struct for executing ssr
+ * @reboot_blk: notification block for reboot event
+ * @subsys_desc: subsystem descriptor
+ * @subsys: subsystem device pointer
+ * @gpios: array to hold all gpio handle
+ * @desc: PIL descriptor
+ * @address_fw: address where firmware binaries loaded
+ * @ramdump_dev: ramdump device pointer
+ * @size_fw: size of bg firmware binaries
+ * @errfatal_irq: irq number to indicate bg crash or shutdown
+ * @status_irq: irq to indicate bg status
+ * @app_status: status of tz app loading
+ * @is_ready: Is BG chip up
+ * @err_ready: The error ready signal
+ */
+
+struct pil_bg_data {
+	struct qseecom_handle *qseecom_handle;
+	struct workqueue_struct *bg_queue;
+	struct work_struct restart_work;
+	struct notifier_block reboot_blk;
+	struct subsys_desc subsys_desc;
+	struct subsys_device *subsys;
+	unsigned int gpios[NUM_GPIOS];
+	int errfatal_irq;
+	int status_irq;
+	struct pil_desc desc;
+	phys_addr_t address_fw;
+	void *ramdump_dev;
+	u32 cmd_status;
+	size_t size_fw;
+	int app_status;
+	bool is_ready;
+	struct completion err_ready;
+};
+
+static irqreturn_t bg_status_change(int irq, void *dev_id);
+
+/**
+ * bg_app_shutdown_notify() - Toggle AP2BG err fatal gpio when
+ * called by SSR framework.
+ * @subsys: struct containing private BG data.
+ *
+ * Return: none.
+ */
+static void bg_app_shutdown_notify(const struct subsys_desc *subsys)
+{
+	struct pil_bg_data *bg_data = subsys_to_data(subsys);
+	/* Toggle AP2BG err fatal gpio here to inform apps err fatal event */
+	if (gpio_is_valid(bg_data->gpios[2]))
+		gpio_set_value(bg_data->gpios[2], 1);
+}
+
+/**
+ * bg_app_reboot_notify() - Toggle AP2BG err fatal gpio.
+ * @nb: struct containing private BG data.
+ *
+ * Return: NOTIFY_DONE indicating success.
+ */
+static int bg_app_reboot_notify(struct notifier_block *nb,
+		unsigned long code, void *unused)
+{
+	struct pil_bg_data *bg_data = container_of(nb,
+					struct pil_bg_data, reboot_blk);
+	/* Toggle AP2BG err fatal gpio here to inform apps err fatal event */
+	if (gpio_is_valid(bg_data->gpios[2]))
+		gpio_set_value(bg_data->gpios[2], 1);
+	return NOTIFY_DONE;
+}
+
+/**
+ * get_cmd_rsp_buffers() - Function sets cmd & rsp buffer pointers and
+ *                         aligns buffer lengths
+ * @hdl:	index of qseecom_handle
+ * @cmd:	req buffer - set to qseecom_handle.sbuf
+ * @cmd_len:	ptr to req buffer len
+ * @rsp:	rsp buffer - set to qseecom_handle.sbuf + offset
+ * @rsp_len:	ptr to rsp buffer len
+ *
+ * Return: Success always .
+ */
+static int get_cmd_rsp_buffers(struct qseecom_handle *handle, void **cmd,
+			uint32_t *cmd_len, void **rsp, uint32_t *rsp_len)
+{
+	*cmd = handle->sbuf;
+	if (*cmd_len & QSEECOM_ALIGN_MASK)
+		*cmd_len = QSEECOM_ALIGN(*cmd_len);
+
+	*rsp = handle->sbuf + *cmd_len;
+	if (*rsp_len & QSEECOM_ALIGN_MASK)
+		*rsp_len = QSEECOM_ALIGN(*rsp_len);
+
+	return 0;
+}
+
+/**
+ * pil_load_bg_tzapp() - Called to load TZ app.
+ * @pbd: struct containing private BG data.
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int pil_load_bg_tzapp(struct pil_bg_data *pbd)
+{
+	int rc;
+
+	/* return success if already loaded */
+	if (pbd->qseecom_handle && !pbd->app_status)
+		return 0;
+	/* Load the APP */
+	rc = qseecom_start_app(&pbd->qseecom_handle, SECURE_APP, SZ_4K);
+	if (rc < 0) {
+		dev_err(pbd->desc.dev, "BG TZ app load failure\n");
+		pbd->app_status = RESULT_FAILURE;
+		return -EIO;
+	}
+	pbd->app_status = RESULT_SUCCESS;
+	return 0;
+}
+
+/**
+ * bgpil_tzapp_comm() - Function called to communicate with TZ APP.
+ * @req:	struct containing command and parameters.
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static long bgpil_tzapp_comm(struct pil_bg_data *pbd,
+				struct tzapp_bg_req *req)
+{
+	struct tzapp_bg_req *bg_tz_req;
+	struct tzapp_bg_rsp *bg_tz_rsp;
+	int rc, req_len, rsp_len;
+
+	/* Fill command structure */
+	req_len = sizeof(struct tzapp_bg_req);
+	rsp_len = sizeof(struct tzapp_bg_rsp);
+	rc = get_cmd_rsp_buffers(pbd->qseecom_handle,
+		(void **)&bg_tz_req, &req_len,
+		(void **)&bg_tz_rsp, &rsp_len);
+	if (rc)
+		goto end;
+
+	bg_tz_req->tzapp_bg_cmd = req->tzapp_bg_cmd;
+	bg_tz_req->address_fw = req->address_fw;
+	bg_tz_req->size_fw = req->size_fw;
+	rc = qseecom_send_command(pbd->qseecom_handle,
+		(void *)bg_tz_req, req_len, (void *)bg_tz_rsp, rsp_len);
+	pr_debug("BG PIL qseecom returned with value 0x%x and status 0x%x\n",
+		rc, bg_tz_rsp->status);
+	if (rc || bg_tz_rsp->status)
+		pbd->cmd_status = bg_tz_rsp->status;
+	else
+		pbd->cmd_status = 0;
+end:
+	return rc;
+}
+
+/**
+ * wait_for_err_ready() - Called in power_up to wait for error ready.
+ * Signal waiting function.
+ * @bg_data: BG PIL private structure.
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int wait_for_err_ready(struct pil_bg_data *bg_data)
+{
+	int ret;
+
+	if ((!bg_data->status_irq))
+		return 0;
+
+	ret = wait_for_completion_timeout(&bg_data->err_ready,
+			msecs_to_jiffies(10000));
+	if (!ret) {
+		pr_err("[%s]: Error ready timed out\n", bg_data->desc.name);
+		return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+/**
+ * bg_powerup() - Called by SSR framework on userspace invocation.
+ * does load tz app and call peripheral loader.
+ * @subsys: struct containing private BG data.
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int bg_powerup(const struct subsys_desc *subsys)
+{
+	struct pil_bg_data *bg_data = subsys_to_data(subsys);
+	int ret;
+
+	init_completion(&bg_data->err_ready);
+	if (!bg_data->qseecom_handle) {
+		ret = pil_load_bg_tzapp(bg_data);
+		if (ret) {
+			dev_err(bg_data->desc.dev,
+				"%s: BG TZ app load failure\n",
+				__func__);
+			return ret;
+		}
+	}
+	pr_debug("bgapp loaded\n");
+	bg_data->desc.fw_name = subsys->fw_name;
+
+	ret = devm_request_irq(bg_data->desc.dev, bg_data->status_irq,
+		bg_status_change,
+		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+		"bg2ap_status", bg_data);
+	if (ret < 0) {
+		dev_err(bg_data->desc.dev,
+			"%s: BG2AP_STATUS IRQ#%d re registration failed, err=%d",
+			__func__, bg_data->status_irq, ret);
+			return ret;
+	}
+	disable_irq(bg_data->status_irq);
+
+	/* Enable status and err fatal irqs */
+	ret = pil_boot(&bg_data->desc);
+	if (ret) {
+		dev_err(bg_data->desc.dev,
+			"%s: BG PIL Boot failed\n", __func__);
+		return ret;
+	}
+	enable_irq(bg_data->status_irq);
+	enable_irq(bg_data->errfatal_irq);
+	ret = wait_for_err_ready(bg_data);
+	if (ret) {
+		dev_err(bg_data->desc.dev,
+			"[%s:%d]: Timed out waiting for error ready: %s!\n",
+			current->comm, current->pid, bg_data->desc.name);
+		return ret;
+	}
+	return ret;
+}
+
+/**
+ * bg_shutdown() - Called by SSR framework on userspace invocation.
+ * disable status interrupt to avoid spurious signal during PRM exit.
+ * @subsys: struct containing private BG data.
+ * @force_stop: unused
+ *
+ * Return: always success
+ */
+static int bg_shutdown(const struct subsys_desc *subsys, bool force_stop)
+{
+	struct pil_bg_data *bg_data = subsys_to_data(subsys);
+
+	disable_irq(bg_data->status_irq);
+	devm_free_irq(bg_data->desc.dev, bg_data->status_irq, bg_data);
+	disable_irq(bg_data->errfatal_irq);
+	bg_data->is_ready = false;
+	return 0;
+}
+
+/**
+ * bg_auth_metadata() - Called by Peripheral loader framework
+ * send command to tz app for authentication of metadata.
+ * @pil: pil descriptor.
+ * @metadata: metadata load address
+ * @size: size of metadata
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int bg_auth_metadata(struct pil_desc *pil,
+	const u8 *metadata, size_t size,
+	phys_addr_t addr, void *sz)
+{
+	struct pil_bg_data *bg_data = desc_to_data(pil);
+	struct tzapp_bg_req bg_tz_req;
+	void *mdata_buf;
+	dma_addr_t mdata_phys;
+	unsigned long attrs = 0;
+	struct device dev = {0};
+	int ret;
+
+	arch_setup_dma_ops(&dev, 0, 0, NULL, 0);
+
+	dev.coherent_dma_mask = DMA_BIT_MASK(sizeof(dma_addr_t) * 8);
+	attrs |= DMA_ATTR_STRONGLY_ORDERED;
+	mdata_buf = dma_alloc_attrs(&dev, size,
+			&mdata_phys, GFP_KERNEL, attrs);
+
+	if (!mdata_buf) {
+		pr_err("BG_PIL: Allocation for metadata failed.\n");
+		return -ENOMEM;
+	}
+
+	/* Make sure there are no mappings in PKMAP and fixmap */
+	kmap_flush_unused();
+	kmap_atomic_flush_unused();
+
+	memcpy(mdata_buf, metadata, size);
+
+	bg_tz_req.tzapp_bg_cmd = BGPIL_AUTH_MDT;
+	bg_tz_req.address_fw = (phys_addr_t)mdata_phys;
+	bg_tz_req.size_fw = size;
+
+	ret = bgpil_tzapp_comm(bg_data, &bg_tz_req);
+	if (ret || bg_data->cmd_status) {
+		dev_err(pil->dev,
+			"%s: BGPIL_AUTH_MDT qseecom call failed\n",
+				__func__);
+		return bg_data->cmd_status;
+	}
+	dma_free_attrs(&dev, size, mdata_buf, mdata_phys, attrs);
+	pr_debug("BG MDT Authenticated\n");
+	return 0;
+}
+
+/**
+ * bg_get_firmware_addr() - Called by Peripheral loader framework
+ * to get address and size of bg firmware binaries.
+ * @pil: pil descriptor.
+ * @addr: fw load address
+ * @size: size of fw
+ *
+ * Return: 0 on success.
+ */
+static int bg_get_firmware_addr(struct pil_desc *pil,
+					phys_addr_t addr, size_t size)
+{
+	struct pil_bg_data *bg_data = desc_to_data(pil);
+
+	bg_data->address_fw = addr;
+	bg_data->size_fw = size;
+	pr_debug("BG PIL loads firmware blobs at 0x%x with size 0x%x\n",
+		addr, size);
+	return 0;
+}
+
+
+/**
+ * bg_auth_and_xfer() - Called by Peripheral loader framework
+ * to signal tz app to authenticate and boot bg chip.
+ * @pil: pil descriptor.
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int bg_auth_and_xfer(struct pil_desc *pil)
+{
+	struct pil_bg_data *bg_data = desc_to_data(pil);
+	struct tzapp_bg_req bg_tz_req;
+	int ret;
+
+	bg_tz_req.tzapp_bg_cmd = BGPIL_IMAGE_LOAD;
+	bg_tz_req.address_fw = bg_data->address_fw;
+	bg_tz_req.size_fw = bg_data->size_fw;
+
+	ret = bgpil_tzapp_comm(bg_data, &bg_tz_req);
+	if (bg_data->cmd_status == BG_CRASH_IN_TWM) {
+		/* Do ramdump and resend boot cmd */
+		bg_data->subsys_desc.ramdump(true, &bg_data->subsys_desc);
+		bg_tz_req.tzapp_bg_cmd = BGPIL_DLOAD_CONT;
+		ret = bgpil_tzapp_comm(bg_data, &bg_tz_req);
+	}
+	if (ret || bg_data->cmd_status) {
+		dev_err(pil->dev,
+			"%s: BGPIL_IMAGE_LOAD qseecom call failed\n",
+			__func__);
+		pil_free_memory(&bg_data->desc);
+		return bg_data->cmd_status;
+	}
+	/* BG Transfer of image is complete, free up the memory */
+	pr_debug("BG Firmware authentication and transfer done\n");
+	pil_free_memory(&bg_data->desc);
+	return 0;
+}
+
+/**
+ * bg_ramdump() - Called by SSR framework to save dump of BG internal
+ * memory, BG PIL does allocate region from dynamic memory and pass this
+ * region to tz to dump memory content of BG.
+ * @subsys: subsystem descriptor.
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int bg_ramdump(int enable, const struct subsys_desc *subsys)
+{
+	struct pil_bg_data *bg_data = subsys_to_data(subsys);
+	struct pil_desc desc = bg_data->desc;
+	struct ramdump_segment *ramdump_segments;
+	struct tzapp_bg_req bg_tz_req;
+	phys_addr_t start_addr;
+	void *region;
+	int ret;
+	struct device dev = {0};
+
+	arch_setup_dma_ops(&dev, 0, 0, NULL, 0);
+
+	desc.attrs = 0;
+	desc.attrs |= DMA_ATTR_SKIP_ZEROING;
+	desc.attrs |= DMA_ATTR_STRONGLY_ORDERED;
+
+	region = dma_alloc_attrs(desc.dev, BG_RAMDUMP_SZ,
+				&start_addr, GFP_KERNEL, desc.attrs);
+
+	if (region == NULL) {
+		dev_dbg(desc.dev,
+			"BG PIL failure to allocate ramdump region of size %zx\n",
+			BG_RAMDUMP_SZ);
+		return -ENOMEM;
+	}
+
+	ramdump_segments = kcalloc(1, sizeof(*ramdump_segments), GFP_KERNEL);
+	if (!ramdump_segments)
+		return -ENOMEM;
+
+	bg_tz_req.tzapp_bg_cmd = BGPIL_RAMDUMP;
+	bg_tz_req.address_fw = start_addr;
+	bg_tz_req.size_fw = BG_RAMDUMP_SZ;
+
+	ret = bgpil_tzapp_comm(bg_data, &bg_tz_req);
+	if (ret || bg_data->cmd_status) {
+		dev_dbg(desc.dev, "%s: BG PIL ramdump collection failed\n",
+			__func__);
+		return bg_data->cmd_status;
+	}
+
+	ramdump_segments->address = start_addr;
+	ramdump_segments->size = BG_RAMDUMP_SZ;
+
+	do_ramdump(bg_data->ramdump_dev, ramdump_segments, 1);
+	kfree(ramdump_segments);
+	dma_free_attrs(desc.dev, BG_RAMDUMP_SZ, region,
+		       start_addr, desc.attrs);
+	return 0;
+}
+
+static struct pil_reset_ops pil_ops_trusted = {
+	.init_image = bg_auth_metadata,
+	.mem_setup =  bg_get_firmware_addr,
+	.auth_and_reset = bg_auth_and_xfer,
+	.shutdown = NULL,
+	.proxy_vote = NULL,
+	.proxy_unvote = NULL,
+};
+
+/**
+ * bg_restart_work() - scheduled by interrupt handler to carry
+ * out ssr sequence
+ * @work: work struct.
+ *
+ * Return: none.
+ */
+static void bg_restart_work(struct work_struct *work)
+{
+	struct pil_bg_data *drvdata =
+		container_of(work, struct pil_bg_data, restart_work);
+		subsystem_restart_dev(drvdata->subsys);
+}
+
+static irqreturn_t bg_errfatal(int irq, void *dev_id)
+{
+	struct pil_bg_data *drvdata = (struct pil_bg_data *)dev_id;
+
+	if (!drvdata)
+		return IRQ_HANDLED;
+
+	dev_dbg(drvdata->desc.dev, "BG s/w err fatal\n");
+
+	queue_work(drvdata->bg_queue, &drvdata->restart_work);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t bg_status_change(int irq, void *dev_id)
+{
+	bool value;
+	struct pil_bg_data *drvdata = (struct pil_bg_data *)dev_id;
+
+	if (!drvdata)
+		return IRQ_HANDLED;
+
+	value = gpio_get_value(drvdata->gpios[0]);
+	if (value == true && !drvdata->is_ready) {
+		dev_info(drvdata->desc.dev,
+			"BG services are up and running: irq state changed 0->1\n");
+		drvdata->is_ready = true;
+		complete(&drvdata->err_ready);
+	} else if (value == false && drvdata->is_ready) {
+		dev_err(drvdata->desc.dev,
+			"BG got unexpected reset: irq state changed 1->0\n");
+			drvdata->is_ready = false;
+		queue_work(drvdata->bg_queue, &drvdata->restart_work);
+	} else {
+		dev_err(drvdata->desc.dev,
+			"BG status irq: unknown status\n");
+	}
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * setup_bg_gpio_irq() - called in probe to configure input/
+ * output gpio.
+ * @drvdata: private data struct for BG.
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int setup_bg_gpio_irq(struct platform_device *pdev,
+					struct pil_bg_data *drvdata)
+{
+	int ret = -1;
+	int irq, i;
+
+	if (gpio_request(drvdata->gpios[0], "BG2AP_STATUS")) {
+		dev_err(&pdev->dev,
+			"%s Failed to configure BG2AP_STATUS gpio\n",
+				__func__);
+		goto err;
+	}
+	if (gpio_request(drvdata->gpios[1], "BG2AP_ERRFATAL")) {
+		dev_err(&pdev->dev,
+			"%s Failed to configure BG2AP_ERRFATAL gpio\n",
+				__func__);
+		goto err;
+	}
+	gpio_direction_input(drvdata->gpios[0]);
+	gpio_direction_input(drvdata->gpios[1]);
+	/* BG2AP STATUS IRQ */
+	irq = gpio_to_irq(drvdata->gpios[0]);
+	if (irq < 0) {
+		dev_err(&pdev->dev,
+		"%s: bad BG2AP_STATUS IRQ resource, err = %d\n",
+			__func__, irq);
+		goto err;
+	}
+
+	drvdata->status_irq = irq;
+	/* BG2AP ERR_FATAL irq. */
+	irq = gpio_to_irq(drvdata->gpios[1]);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "bad BG2AP_ERRFATAL IRQ resource\n");
+		goto err;
+	}
+	ret = request_irq(irq, bg_errfatal,
+		IRQF_TRIGGER_RISING | IRQF_ONESHOT, "bg2ap_errfatal", drvdata);
+	if (ret < 0) {
+		dev_err(&pdev->dev,
+			"%s: BG2AP_ERRFATAL IRQ#%d request failed,\n",
+				__func__, irq);
+		goto err;
+	}
+	drvdata->errfatal_irq = irq;
+	enable_irq(drvdata->errfatal_irq);
+	/* Configure outgoing GPIO's */
+	if (gpio_request(drvdata->gpios[2], "AP2BG_ERRFATAL")) {
+		dev_err(&pdev->dev,
+			"%s Failed to configure AP2BG_ERRFATAL gpio\n",
+				__func__);
+		goto err;
+	}
+	if (gpio_request(drvdata->gpios[3], "AP2BG_STATUS")) {
+		dev_err(&pdev->dev,
+			"%s Failed to configure AP2BG_STATUS gpio\n",
+				__func__);
+		goto err;
+	}
+	/*
+	 * Put status gpio in default high state which will
+	 * make transition to low on any sudden reset case of msm
+	 */
+	gpio_direction_output(drvdata->gpios[2], 0);
+	gpio_direction_output(drvdata->gpios[3], 1);
+	/* Inform BG that AP is up */
+	gpio_set_value(drvdata->gpios[3], 1);
+	return 0;
+err:
+	for (i = 0; i < NUM_GPIOS; ++i) {
+		if (gpio_is_valid(drvdata->gpios[i]))
+			gpio_free(drvdata->gpios[i]);
+	}
+	return ret;
+}
+
+/**
+ * bg_dt_parse_gpio() - called in probe to parse gpio's
+ * @drvdata: private data struct for BG.
+ *
+ * Return: 0 on success. Error code on failure.
+ */
+static int bg_dt_parse_gpio(struct platform_device *pdev,
+				struct pil_bg_data *drvdata)
+{
+	int i, val;
+
+	for (i = 0; i < NUM_GPIOS; i++)
+		drvdata->gpios[i] = INVALID_GPIO;
+	val = of_get_named_gpio(pdev->dev.of_node,
+					"qcom,bg2ap-status-gpio", 0);
+	if (val >= 0)
+		drvdata->gpios[0] = val;
+	else {
+		pr_err("BG status gpio not found, error=%d\n", val);
+		return -EINVAL;
+	}
+	val = of_get_named_gpio(pdev->dev.of_node,
+					"qcom,bg2ap-errfatal-gpio", 0);
+	if (val >= 0)
+		drvdata->gpios[1] = val;
+	else {
+		pr_err("BG err-fatal gpio not found, error=%d\n", val);
+		return -EINVAL;
+	}
+	val = of_get_named_gpio(pdev->dev.of_node,
+					"qcom,ap2bg-errfatal-gpio", 0);
+	if (val >= 0)
+		drvdata->gpios[2] = val;
+	else {
+		pr_err("ap2bg err-fatal gpio not found, error=%d\n", val);
+		return -EINVAL;
+	}
+	val = of_get_named_gpio(pdev->dev.of_node,
+					"qcom,ap2bg-status-gpio", 0);
+	if (val >= 0)
+		drvdata->gpios[3] = val;
+	else {
+		pr_err("ap2bg status gpio not found, error=%d\n", val);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int pil_bg_driver_probe(struct platform_device *pdev)
+{
+	struct pil_bg_data *bg_data;
+	int rc;
+
+	bg_data = devm_kzalloc(&pdev->dev, sizeof(*bg_data), GFP_KERNEL);
+	if (!bg_data)
+		return -ENOMEM;
+	platform_set_drvdata(pdev, bg_data);
+	rc = of_property_read_string(pdev->dev.of_node,
+			"qcom,firmware-name", &bg_data->desc.name);
+	if (rc)
+		return rc;
+	bg_data->desc.dev = &pdev->dev;
+	bg_data->desc.owner = THIS_MODULE;
+	bg_data->desc.ops = &pil_ops_trusted;
+	rc = pil_desc_init(&bg_data->desc);
+	if (rc)
+		return rc;
+	/* Read gpio configuration */
+	rc = bg_dt_parse_gpio(pdev, bg_data);
+	if (rc)
+		return rc;
+	rc = setup_bg_gpio_irq(pdev, bg_data);
+	if (rc < 0)
+		return rc;
+	bg_data->subsys_desc.name = bg_data->desc.name;
+	bg_data->subsys_desc.owner = THIS_MODULE;
+	bg_data->subsys_desc.dev = &pdev->dev;
+	bg_data->subsys_desc.shutdown = bg_shutdown;
+	bg_data->subsys_desc.powerup = bg_powerup;
+	bg_data->subsys_desc.ramdump = bg_ramdump;
+	bg_data->subsys_desc.free_memory = NULL;
+	bg_data->subsys_desc.crash_shutdown = bg_app_shutdown_notify;
+	bg_data->ramdump_dev =
+		create_ramdump_device(bg_data->subsys_desc.name, &pdev->dev);
+	if (!bg_data->ramdump_dev) {
+		rc = -ENOMEM;
+		goto err_ramdump;
+	}
+	bg_data->subsys = subsys_register(&bg_data->subsys_desc);
+	if (IS_ERR(bg_data->subsys)) {
+		rc = PTR_ERR(bg_data->subsys);
+		goto err_subsys;
+	}
+
+	bg_data->reboot_blk.notifier_call = bg_app_reboot_notify;
+	register_reboot_notifier(&bg_data->reboot_blk);
+
+	bg_data->bg_queue = alloc_workqueue("bg_queue", 0, 0);
+	if (!bg_data->bg_queue) {
+		dev_err(&pdev->dev, "could not create bg_queue\n");
+		subsys_unregister(bg_data->subsys);
+		goto err_subsys;
+	}
+	INIT_WORK(&bg_data->restart_work, bg_restart_work);
+	return 0;
+err_subsys:
+	destroy_ramdump_device(bg_data->ramdump_dev);
+err_ramdump:
+	pil_desc_release(&bg_data->desc);
+	return rc;
+}
+
+static int pil_bg_driver_exit(struct platform_device *pdev)
+{
+	struct pil_bg_data *bg_data = platform_get_drvdata(pdev);
+
+	subsys_unregister(bg_data->subsys);
+	destroy_ramdump_device(bg_data->ramdump_dev);
+	pil_desc_release(&bg_data->desc);
+
+	return 0;
+}
+
+const struct of_device_id pil_bg_match_table[] = {
+	{.compatible = "qcom,pil-blackghost"},
+	{}
+};
+
+static struct platform_driver pil_bg_driver = {
+	.probe = pil_bg_driver_probe,
+	.remove = pil_bg_driver_exit,
+	.driver = {
+		.name = "subsys-pil-bg",
+		.of_match_table = pil_bg_match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init pil_bg_init(void)
+{
+	return platform_driver_register(&pil_bg_driver);
+}
+module_init(pil_bg_init);
+
+static void __exit pil_bg_exit(void)
+{
+	platform_driver_unregister(&pil_bg_driver);
+}
+module_exit(pil_bg_exit);
+
+MODULE_DESCRIPTION("Support for booting QTI Blackghost SoC");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/wcnss/wcnss_wlan.c b/drivers/soc/qcom/wcnss/wcnss_wlan.c
index 4162c53..c3fb30b 100644
--- a/drivers/soc/qcom/wcnss/wcnss_wlan.c
+++ b/drivers/soc/qcom/wcnss/wcnss_wlan.c
@@ -1771,6 +1771,15 @@
 	return 0;
 }
 
+static int wcnss_wlan_suspend_noirq(struct device *dev)
+{
+	if (penv && dev && (dev == &penv->pdev->dev) &&
+	    penv->smd_channel_ready &&
+	    penv->pm_ops && penv->pm_ops->suspend_noirq)
+		return penv->pm_ops->suspend_noirq(dev);
+	return 0;
+}
+
 static int wcnss_wlan_resume(struct device *dev)
 {
 	if (penv && dev && (dev == &penv->pdev->dev) &&
@@ -1780,6 +1789,15 @@
 	return 0;
 }
 
+static int wcnss_wlan_resume_noirq(struct device *dev)
+{
+	if (penv && dev && (dev == &penv->pdev->dev) &&
+	    penv->smd_channel_ready &&
+	    penv->pm_ops && penv->pm_ops->resume_noirq)
+		return penv->pm_ops->resume_noirq(dev);
+	return 0;
+}
+
 void wcnss_prevent_suspend(void)
 {
 	if (penv)
@@ -3535,6 +3553,8 @@
 static const struct dev_pm_ops wcnss_wlan_pm_ops = {
 	.suspend	= wcnss_wlan_suspend,
 	.resume		= wcnss_wlan_resume,
+	.suspend_noirq  = wcnss_wlan_suspend_noirq,
+	.resume_noirq   = wcnss_wlan_resume_noirq,
 };
 
 #ifdef CONFIG_WCNSS_CORE_PRONTO
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index 800c167..3ac71ed 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -2,7 +2,7 @@
  * drivers/staging/android/ion/ion_system_heap.c
  *
  * Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -36,7 +36,11 @@
 static gfp_t low_order_gfp_flags  = (GFP_HIGHUSER | __GFP_NOWARN);
 
 #ifndef CONFIG_ALLOC_BUFFERS_IN_4K_CHUNKS
-static const unsigned int orders[] = {9, 8, 4, 0};
+#if defined(CONFIG_IOMMU_IO_PGTABLE_ARMV7S)
+static const unsigned int orders[] = {8, 4, 0};
+#else
+static const unsigned int orders[] = {9, 4, 0};
+#endif
 #else
 static const unsigned int orders[] = {0};
 #endif
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index f8a9a2f..cc3af57 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1565,7 +1565,7 @@
 	 * based on the MACRO determine the default state to use or the
 	 * offset from the max_state.
 	 */
-	if (upper > (THERMAL_MAX_LIMIT - max_state)) {
+	if (upper >= (THERMAL_MAX_LIMIT - max_state)) {
 		/* upper default max_state */
 		if (upper == THERMAL_NO_LIMIT)
 			upper = max_state;
@@ -1573,7 +1573,7 @@
 			upper = max_state - (THERMAL_MAX_LIMIT - upper);
 	}
 
-	if (lower > (THERMAL_MAX_LIMIT - max_state)) {
+	if (lower >= (THERMAL_MAX_LIMIT - max_state)) {
 		/* lower default 0 */
 		if (lower == THERMAL_NO_LIMIT)
 			lower = 0;
diff --git a/drivers/thermal/tsens-dbg.c b/drivers/thermal/tsens-dbg.c
index e1fc6b9..9f128fe 100644
--- a/drivers/thermal/tsens-dbg.c
+++ b/drivers/thermal/tsens-dbg.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -190,17 +190,34 @@
 	__ATTR(zonehist, 0644, zonehist_show, zonehist_store),
 };
 
+static struct device_attribute tsens_mtc_dev_attr_V14[] = {
+	__ATTR(zonemask, 0644, zonemask_show, zonemask_store),
+	__ATTR(zonelog, 0644, zonelog_show, zonelog_store),
+};
+
 static int tsens_dbg_mtc_data(struct tsens_device *data,
 					u32 id, u32 dbg_type, int *val)
 {
 	int result = 0, i;
 	struct tsens_device *tmdev = NULL;
 	struct device_attribute *attr_ptr = NULL;
+	u32 ver_major;
+	u32 ver_minor;
+	u32 num_elem;
 
-	attr_ptr = tsens_mtc_dev_attr;
 	tmdev = data;
+	ver_major = tmdev->ctrl_data->ver_major;
+	ver_minor = tmdev->ctrl_data->ver_minor;
 
-	for (i = 0; i < ARRAY_SIZE(tsens_mtc_dev_attr); i++) {
+	if (ver_major == 1 && ver_minor == 4) {
+		attr_ptr = tsens_mtc_dev_attr_V14;
+		num_elem = ARRAY_SIZE(tsens_mtc_dev_attr_V14);
+	} else {
+		attr_ptr = tsens_mtc_dev_attr;
+		num_elem = ARRAY_SIZE(tsens_mtc_dev_attr);
+	}
+
+	for (i = 0; i < num_elem; i++) {
 		result = device_create_file(&tmdev->pdev->dev, &attr_ptr[i]);
 		if (result < 0)
 			goto error;
diff --git a/drivers/thermal/tsens-mtc.c b/drivers/thermal/tsens-mtc.c
index 451c6c7..6e43533 100644
--- a/drivers/thermal/tsens-mtc.c
+++ b/drivers/thermal/tsens-mtc.c
@@ -76,6 +76,8 @@
 	unsigned int reg_cntl;
 	void __iomem *sensor_addr;
 	struct tsens_device *tmdev = NULL;
+	u32 ver_major;
+	u32 ver_minor;
 
 	if (zone > TSENS_NUM_MTC_ZONES_SUPPORT)
 		return -EINVAL;
@@ -86,8 +88,16 @@
 		return -EPROBE_DEFER;
 	}
 
-	sensor_addr = TSENS_TM_MTC_ZONE0_SW_MASK_ADDR
-					(tmdev->tsens_tm_addr);
+	ver_major = tmdev->ctrl_data->ver_major;
+	ver_minor = tmdev->ctrl_data->ver_minor;
+
+	if (ver_major == 1 && ver_minor == 4) {
+		sensor_addr = TSENS_TM_MTC_ZONE0_SW_MASK_ADDR_V14
+			(tmdev->tsens_tm_addr);
+	} else {
+		sensor_addr = TSENS_TM_MTC_ZONE0_SW_MASK_ADDR
+			(tmdev->tsens_tm_addr);
+	}
 
 	if (th1_enable && th2_enable)
 		writel_relaxed(TSENS_MTC_IN_EFFECT,
@@ -120,6 +130,8 @@
 	int *zlog = (int *)zone_log;
 	void __iomem *sensor_addr;
 	struct tsens_device *tmdev = NULL;
+	u32 ver_major;
+	u32 ver_minor;
 
 	if (zone > TSENS_NUM_MTC_ZONES_SUPPORT)
 		return -EINVAL;
@@ -130,8 +142,13 @@
 		return -EPROBE_DEFER;
 	}
 
-	sensor_addr = TSENS_TM_MTC_ZONE0_LOG(tmdev->tsens_tm_addr);
+	ver_major = tmdev->ctrl_data->ver_major;
+	ver_minor = tmdev->ctrl_data->ver_minor;
 
+	if (ver_major == 1 && ver_minor == 4)
+		sensor_addr = TSENS_TM_MTC_ZONE0_LOG_V14(tmdev->tsens_tm_addr);
+	else
+		sensor_addr = TSENS_TM_MTC_ZONE0_LOG(tmdev->tsens_tm_addr);
 	reg_cntl = readl_relaxed((sensor_addr +
 				(zone * TSENS_SN_ADDR_OFFSET)));
 	is_valid = (reg_cntl & TSENS_LOGS_VALID_MASK)
diff --git a/drivers/thermal/tsens-mtc.h b/drivers/thermal/tsens-mtc.h
index 8782728..b3a2c8e 100644
--- a/drivers/thermal/tsens-mtc.h
+++ b/drivers/thermal/tsens-mtc.h
@@ -15,6 +15,9 @@
 #define TSENS_TM_MTC_ZONE0_SW_MASK_ADDR(n)      ((n) + 0x140)
 #define TSENS_TM_MTC_ZONE0_LOG(n)               ((n) + 0x150)
 #define TSENS_TM_MTC_ZONE0_HISTORY(n)           ((n) + 0x160)
+#define TSENS_TM_MTC_ZONE0_SW_MASK_ADDR_V14(n)  ((n) + 0xC0)
+#define TSENS_TM_MTC_ZONE0_LOG_V14(n)           ((n) + 0xD0)
+
 #define TSENS_SN_ADDR_OFFSET             0x4
 #define TSENS_RESET_HISTORY_MASK        0x4
 #define TSENS_ZONEMASK_PARAMS           3
diff --git a/drivers/thermal/tsens.h b/drivers/thermal/tsens.h
index 885b15c..730d124 100644
--- a/drivers/thermal/tsens.h
+++ b/drivers/thermal/tsens.h
@@ -127,6 +127,8 @@
 	u32				wd_bark_mask;
 	bool				mtc;
 	bool				valid_status_check;
+	u32				ver_major;
+	u32				ver_minor;
 };
 
 struct tsens_mtc_sysfs {
diff --git a/drivers/thermal/tsens1xxx.c b/drivers/thermal/tsens1xxx.c
index 0ea4a46..d63fcd1 100644
--- a/drivers/thermal/tsens1xxx.c
+++ b/drivers/thermal/tsens1xxx.c
@@ -306,6 +306,10 @@
 	*temp = code_to_degc(last_temp, sensor);
 	*temp = *temp * TSENS_SCALE_MILLIDEG;
 
+	if (tmdev->ops->dbg)
+		tmdev->ops->dbg(tmdev, (u32)sensor->hw_id,
+				TSENS_DBG_LOG_TEMP_READS, temp);
+
 	return 0;
 }
 
@@ -565,6 +569,9 @@
 	/* Disable monitoring sensor trip threshold for triggered sensor */
 	mb();
 
+	if (tm->ops->dbg)
+		tm->ops->dbg(tm, 0, TSENS_DBG_LOG_INTERRUPT_TIMESTAMP, NULL);
+
 	return IRQ_HANDLED;
 }
 
@@ -600,6 +607,11 @@
 
 	spin_lock_init(&tmdev->tsens_upp_low_lock);
 
+	if (tmdev->ctrl_data->mtc) {
+		if (tmdev->ops->dbg)
+			tmdev->ops->dbg(tmdev, 0, TSENS_DBG_MTC_DATA, NULL);
+	}
+
 	return 0;
 }
 
@@ -646,13 +658,16 @@
 	.hw_init		= tsens1xxx_hw_init,
 	.get_temp		= tsens1xxx_get_temp,
 	.set_trips		= tsens1xxx_set_trip_temp,
-	.interrupts_reg		= tsens1xxx_register_interrupts,
+	.interrupts_reg	= tsens1xxx_register_interrupts,
 	.sensor_en		= tsens1xxx_hw_sensor_en,
 	.calibrate		= calibrate_8937,
+	.dbg            = tsens2xxx_dbg,
 };
 
 const struct tsens_data data_tsens14xx = {
-	.ops			= &ops_tsens1xxx,
-	.valid_status_check	= true,
-	.mtc			= true,
+	.ops = &ops_tsens1xxx,
+	.valid_status_check = true,
+	.mtc = true,
+	.ver_major = 1,
+	.ver_minor = 4,
 };
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 148568b..f76b3db 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -96,6 +96,7 @@
 /* UART S_CMD OP codes */
 #define UART_START_READ		(0x1)
 #define UART_PARAM		(0x1)
+#define UART_PARAM_RFR_OPEN		(BIT(7))
 
 /* UART DMA Rx GP_IRQ_BITS */
 #define UART_DMA_RX_PARITY_ERR	BIT(5)
@@ -613,6 +614,27 @@
 	geni_write_reg(FORCE_DEFAULT, uport->membase, GENI_FORCE_DEFAULT_REG);
 }
 
+static void msm_geni_serial_complete_rx_eot(struct uart_port *uport)
+{
+	int poll_done = 0, tries = 0;
+	u32 geni_status = 0;
+	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
+
+	do {
+		poll_done = msm_geni_serial_poll_bit(uport, SE_DMA_RX_IRQ_STAT,
+								RX_EOT, true);
+		tries++;
+	} while (!poll_done && tries < 5);
+
+	geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
+
+	if (!poll_done)
+		IPC_LOG_MSG(port->ipc_log_misc, "%s: RX_EOT, GENI:0x%x\n",
+							__func__, geni_status);
+	else
+		geni_write_reg_nolog(RX_EOT, uport->membase, SE_DMA_RX_IRQ_CLR);
+}
+
 #ifdef CONFIG_CONSOLE_POLL
 static int msm_geni_serial_get_char(struct uart_port *uport)
 {
@@ -999,12 +1021,14 @@
 	unsigned int geni_status;
 	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
 	int ret;
+	u32 geni_se_param = UART_PARAM_RFR_OPEN;
 
 	geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
 	if (geni_status & S_GENI_CMD_ACTIVE)
 		msm_geni_serial_stop_rx(uport);
 
-	geni_setup_s_cmd(uport->membase, UART_START_READ, 0);
+	/* Start RX with the RFR_OPEN to keep RFR in always ready state */
+	geni_setup_s_cmd(uport->membase, UART_START_READ, geni_se_param);
 
 	if (port->xfer_mode == FIFO_MODE) {
 		geni_s_irq_en = geni_read_reg_nolog(uport->membase,
@@ -1078,7 +1102,7 @@
 	unsigned int geni_m_irq_en;
 	unsigned int geni_status;
 	struct msm_geni_serial_port *port = GET_DEV_PORT(uport);
-	u32 irq_clear = S_CMD_DONE_EN;
+	u32 irq_clear = S_CMD_CANCEL_EN;
 	bool done;
 
 	IPC_LOG_MSG(port->ipc_log_misc, "%s\n", __func__);
@@ -1100,22 +1124,31 @@
 	/* Possible stop rx is called multiple times. */
 	if (!(geni_status & S_GENI_CMD_ACTIVE))
 		goto exit_rx_seq;
+
 	geni_cancel_s_cmd(uport->membase);
 	/*
 	 * Ensure that the cancel goes through before polling for the
 	 * cancel control bit.
 	 */
 	mb();
+	msm_geni_serial_complete_rx_eot(uport);
 	done = msm_geni_serial_poll_bit(uport, SE_GENI_S_CMD_CTRL_REG,
 					S_GENI_CMD_CANCEL, false);
-	geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
-	if (!done)
+	if (done) {
+		geni_write_reg_nolog(irq_clear, uport->membase,
+						SE_GENI_S_IRQ_CLEAR);
+		goto exit_rx_seq;
+	} else {
 		IPC_LOG_MSG(port->ipc_log_misc, "%s Cancel fail 0x%x\n",
-							__func__, geni_status);
+						__func__, geni_status);
+	}
 
-	geni_write_reg_nolog(irq_clear, uport->membase, SE_GENI_S_IRQ_CLEAR);
-	if ((geni_status & S_GENI_CMD_ACTIVE))
+	geni_status = geni_read_reg_nolog(uport->membase, SE_GENI_STATUS);
+	if ((geni_status & S_GENI_CMD_ACTIVE)) {
+		IPC_LOG_MSG(port->ipc_log_misc, "%s:Abort Rx, GENI:0x%x\n",
+						__func__, geni_status);
 		msm_geni_serial_abort_rx(uport);
+	}
 exit_rx_seq:
 	if (port->xfer_mode == SE_DMA && port->rx_dma) {
 		msm_geni_serial_rx_fsm_rst(uport);
@@ -1693,6 +1726,9 @@
 		ret = -ENXIO;
 		goto exit_startup;
 	}
+	IPC_LOG_MSG(msm_port->ipc_log_misc, "%s: FW Ver:0x%x%x\n",
+		__func__,
+		get_se_m_fw(uport->membase), get_se_s_fw(uport->membase));
 
 	get_tx_fifo_size(msm_port);
 	if (!msm_port->port_setup) {
@@ -2525,7 +2561,6 @@
 	struct platform_device *pdev = to_platform_device(dev);
 	struct msm_geni_serial_port *port = platform_get_drvdata(pdev);
 	int ret = 0;
-	u32 uart_manual_rfr = 0;
 	u32 geni_status = geni_read_reg_nolog(port->uport.membase,
 							SE_GENI_STATUS);
 
@@ -2537,28 +2572,8 @@
 	 * Resources off
 	 */
 	disable_irq(port->uport.irq);
-	/*
-	 * If the clients haven't done a manual flow on/off then go ahead and
-	 * set this to manual flow on.
-	 */
-	if (!port->manual_flow) {
-		u32 geni_ios;
-
-		uart_manual_rfr |= (UART_MANUAL_RFR_EN | UART_RFR_READY);
-		geni_write_reg_nolog(uart_manual_rfr, port->uport.membase,
-							SE_UART_MANUAL_RFR);
-		/*
-		 * Ensure that the manual flow on writes go through before
-		 * doing a stop_rx else we could end up flowing off the peer.
-		 */
-		mb();
-		geni_ios = geni_read_reg_nolog(port->uport.membase,
-								SE_GENI_IOS);
-		IPC_LOG_MSG(port->ipc_log_pwr, "%s: Manual Flow ON 0x%x 0x%x\n",
-					 __func__, uart_manual_rfr, geni_ios);
-		udelay(10);
-	}
 	stop_rx_sequencer(&port->uport);
+	geni_status = geni_read_reg_nolog(port->uport.membase, SE_GENI_STATUS);
 	if ((geni_status & M_GENI_CMD_ACTIVE))
 		stop_tx_sequencer(&port->uport);
 	ret = se_geni_resources_off(&port->serial_rsc);
@@ -2603,9 +2618,6 @@
 		goto exit_runtime_resume;
 	}
 	start_rx_sequencer(&port->uport);
-	if (!port->manual_flow)
-		geni_write_reg_nolog(0, port->uport.membase,
-						SE_UART_MANUAL_RFR);
 	/* Ensure that the Rx is running before enabling interrupts */
 	mb();
 	if (pm_runtime_enabled(dev))
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 792fb3b..a2522c6 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -3,7 +3,7 @@
  * MSM 7k High speed uart driver
  *
  * Copyright (c) 2008 Google Inc.
- * Copyright (c) 2007-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2007-2018, The Linux Foundation. All rights reserved.
  * Modified: Nick Pelly <npelly@google.com>
  *
  * All source code in this file is licensed under the following license
@@ -2617,6 +2617,33 @@
 	/* turn on uart clk */
 	msm_hs_resource_vote(msm_uport);
 
+	/* Set up Uart Receive */
+	msm_hs_write(uport, UART_DM_RFWR, 32);
+	/* Write to BADR explicitly to set up FIFO sizes */
+	msm_hs_write(uport, UARTDM_BADR_ADDR, 64);
+
+	/* configure the CR Protection to Enable */
+	msm_hs_write(uport, UART_DM_CR, CR_PROTECTION_EN);
+
+	/*
+	 * Enable Command register protection before going ahead as this hw
+	 * configuration makes sure that issued cmd to CR register gets complete
+	 * before next issued cmd start. Hence mb() requires here.
+	 */
+	mb();
+
+	/*
+	 * Set RX_BREAK_ZERO_CHAR_OFF and RX_ERROR_CHAR_OFF
+	 * so any rx_break and character having parity of framing
+	 * error don't enter inside UART RX FIFO.
+	 */
+	data = msm_hs_read(uport, UART_DM_MR2);
+	data |= (UARTDM_MR2_RX_BREAK_ZERO_CHAR_OFF |
+			UARTDM_MR2_RX_ERROR_CHAR_OFF);
+	msm_hs_write(uport, UART_DM_MR2, data);
+	/* Ensure register IO completion */
+	mb();
+
 	if (is_use_low_power_wakeup(msm_uport)) {
 		ret = request_threaded_irq(msm_uport->wakeup.irq, NULL,
 					msm_hs_wakeup_isr,
@@ -2797,10 +2824,6 @@
 		goto exit_lh_init;
 	}
 
-	/* Set up Uart Receive */
-	msm_hs_write(uport, UART_DM_RFWR, 32);
-	/* Write to BADR explicitly to set up FIFO sizes */
-	msm_hs_write(uport, UARTDM_BADR_ADDR, 64);
 
 	INIT_DELAYED_WORK(&rx->flip_insert_work, flip_insert_work);
 
@@ -3331,7 +3354,6 @@
 	struct resource *bam_resource;
 	int core_irqres, bam_irqres, wakeup_irqres;
 	struct msm_serial_hs_platform_data *pdata = pdev->dev.platform_data;
-	unsigned long data;
 	char name[30];
 
 	if (pdev->dev.of_node) {
@@ -3551,27 +3573,6 @@
 	if (unlikely(ret))
 		goto err_clock;
 
-	/* configure the CR Protection to Enable */
-	msm_hs_write(uport, UART_DM_CR, CR_PROTECTION_EN);
-
-	/*
-	 * Enable Command register protection before going ahead as this hw
-	 * configuration makes sure that issued cmd to CR register gets complete
-	 * before next issued cmd start. Hence mb() requires here.
-	 */
-	mb();
-
-	/*
-	 * Set RX_BREAK_ZERO_CHAR_OFF and RX_ERROR_CHAR_OFF
-	 * so any rx_break and character having parity of framing
-	 * error don't enter inside UART RX FIFO.
-	 */
-	data = msm_hs_read(uport, UART_DM_MR2);
-	data |= (UARTDM_MR2_RX_BREAK_ZERO_CHAR_OFF |
-			UARTDM_MR2_RX_ERROR_CHAR_OFF);
-	msm_hs_write(uport, UART_DM_MR2, data);
-	/* Ensure register IO completion */
-	mb();
 
 	ret = sysfs_create_file(&pdev->dev.kobj, &dev_attr_clock.attr);
 	if (unlikely(ret)) {
@@ -3761,8 +3762,8 @@
 	.runtime_suspend = msm_hs_runtime_suspend,
 	.runtime_resume = msm_hs_runtime_resume,
 	.runtime_idle = NULL,
-	.suspend_noirq = msm_hs_pm_sys_suspend_noirq,
-	.resume_noirq = msm_hs_pm_sys_resume_noirq,
+	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(msm_hs_pm_sys_suspend_noirq,
+	   msm_hs_pm_sys_resume_noirq)
 };
 
 static struct platform_driver msm_serial_hs_platform_driver = {
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 04bce36..810546a 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -983,13 +983,17 @@
 
 	gsi_dbl_address_lsb = devm_ioremap_nocache(mdwc->dev,
 				request->db_reg_phs_addr_lsb, sizeof(u32));
-	if (!gsi_dbl_address_lsb)
-		dev_dbg(mdwc->dev, "Failed to get GSI DBL address LSB\n");
+	if (!gsi_dbl_address_lsb) {
+		dev_err(mdwc->dev, "Failed to get GSI DBL address LSB\n");
+		return;
+	}
 
 	gsi_dbl_address_msb = devm_ioremap_nocache(mdwc->dev,
 			request->db_reg_phs_addr_msb, sizeof(u32));
-	if (!gsi_dbl_address_msb)
-		dev_dbg(mdwc->dev, "Failed to get GSI DBL address MSB\n");
+	if (!gsi_dbl_address_msb) {
+		dev_err(mdwc->dev, "Failed to get GSI DBL address MSB\n");
+		return;
+	}
 
 	offset = dwc3_trb_dma_offset(dep, &dep->trb_pool[num_trbs-1]);
 	dev_dbg(mdwc->dev, "Writing link TRB addr: %pa to %pK (%x) for ep:%s\n",
@@ -3589,6 +3593,8 @@
 	mutex_init(&mdwc->suspend_resume_mutex);
 	/* Mark type-C as true by default */
 	mdwc->type_c = true;
+	if (of_property_read_bool(node, "qcom,connector-type-uAB"))
+		mdwc->type_c = false;
 
 	mdwc->usb_psy = power_supply_get_by_name("usb");
 	if (!mdwc->usb_psy) {
@@ -4096,10 +4102,14 @@
 
 	usb_speed = (event == 0 ? USB_SPEED_HIGH : USB_SPEED_SUPER);
 	if (dwc->maximum_speed == usb_speed)
-		goto err;
+		return 0;
 
 	dbg_event(0xFF, "fw_restarthost", 0);
 	flush_delayed_work(&mdwc->sm_work);
+
+	if (!mdwc->in_host_mode)
+		goto err;
+
 	dbg_event(0xFF, "stop_host_mode", dwc->maximum_speed);
 	ret = dwc3_otg_start_host(mdwc, 0);
 	if (ret)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 381ad49..902d36e 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -1143,13 +1143,18 @@
 	__dwc3_ep0_do_control_status(dwc, dep);
 }
 
-static void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep)
+void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep)
 {
 	struct dwc3_gadget_ep_cmd_params params;
 	u32			cmd;
 	int			ret;
 
-	if (!dep->resource_index)
+	/*
+	 * For status/DATA OUT stage, TRB will be queued on ep0 out
+	 * endpoint for which resource index is zero. Hence allow
+	 * queuing ENDXFER command for ep0 out endpoint.
+	 */
+	if (!dep->resource_index && dep->number)
 		return;
 
 	cmd = DWC3_DEPCMD_ENDTRANSFER;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index ab8bd34..73caa97 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -3154,8 +3154,17 @@
 	 * that EP0 is in setup phase by issuing a stall
 	 * and restart if EP0 is not in setup phase.
 	 */
-	if (dwc->ep0state != EP0_SETUP_PHASE)
+	if (dwc->ep0state != EP0_SETUP_PHASE) {
+		unsigned int	dir;
+
+		dbg_event(0xFF, "CONTRPEND", dwc->ep0state);
+		dir = !!dwc->ep0_expect_in;
+		if (dwc->ep0state == EP0_DATA_PHASE)
+			dwc3_ep0_end_control_data(dwc, dwc->eps[dir]);
+		else
+			dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]);
 		dwc3_ep0_stall_and_restart(dwc);
+	}
 
 	dwc3_stop_active_transfers(dwc);
 	dwc3_clear_stall_all_ep(dwc);
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index 8275e56..b3be233 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -98,6 +98,7 @@
 void dwc3_ep0_interrupt(struct dwc3 *dwc,
 		const struct dwc3_event_depevt *event);
 void dwc3_ep0_out_start(struct dwc3 *dwc);
+void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep);
 void dwc3_ep0_stall_and_restart(struct dwc3 *dwc);
 int __dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
 int dwc3_gadget_ep0_set_halt(struct usb_ep *ep, int value);
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 75205bf..939c219 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -3474,6 +3474,7 @@
 		if (udc->udc_driver->notify_event)
 			udc->udc_driver->notify_event(udc,
 				CI13XXX_CONTROLLER_DISCONNECT_EVENT);
+		usb_gadget_set_state(&udc->gadget, USB_STATE_NOTATTACHED);
 	}
 
 	return 0;
@@ -3982,15 +3983,15 @@
 		return;
 	}
 
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+	dbg_remove_files(&udc->gadget.dev);
+#endif
 	usb_del_gadget_udc(&udc->gadget);
 
 	if (udc->transceiver) {
 		otg_set_peripheral(udc->transceiver->otg, &udc->gadget);
 		usb_put_phy(udc->transceiver);
 	}
-#ifdef CONFIG_USB_GADGET_DEBUG_FILES
-	dbg_remove_files(&udc->gadget.dev);
-#endif
 	destroy_eps(udc);
 	dma_pool_destroy(udc->td_pool);
 	dma_pool_destroy(udc->qh_pool);
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile
index a9344a5..b8fa93e 100644
--- a/drivers/usb/gadget/function/Makefile
+++ b/drivers/usb/gadget/function/Makefile
@@ -64,7 +64,7 @@
 obj-$(CONFIG_USB_F_GSI)         += usb_f_gsi.o
 usb_f_qdss-y			:= f_qdss.o u_qdss.o
 obj-$(CONFIG_USB_F_QDSS)        += usb_f_qdss.o
-usb_f_qcrndis-y			:= f_qc_rndis.o u_data_ipa.o
+usb_f_qcrndis-y			:= f_qc_rndis.o
 obj-$(CONFIG_USB_F_QCRNDIS)	+= usb_f_qcrndis.o
-usb_f_rmnet_bam-y		:= f_rmnet.o u_ctrl_qti.o u_bam_dmux.o
+usb_f_rmnet_bam-y		:= f_rmnet.o u_ctrl_qti.o u_bam_dmux.o u_data_ipa.o
 obj-$(CONFIG_USB_F_RMNET_BAM)	+= usb_f_rmnet_bam.o
diff --git a/drivers/usb/gadget/function/f_ccid.c b/drivers/usb/gadget/function/f_ccid.c
index 76b181a..631597e 100644
--- a/drivers/usb/gadget/function/f_ccid.c
+++ b/drivers/usb/gadget/function/f_ccid.c
@@ -1037,9 +1037,6 @@
 	pr_debug("ccid_bind_config\n");
 
 	ccid_dev->function.name = FUNCTION_NAME;
-	ccid_dev->function.fs_descriptors = ccid_fs_descs;
-	ccid_dev->function.hs_descriptors = ccid_hs_descs;
-	ccid_dev->function.ss_descriptors = ccid_ss_descs;
 	ccid_dev->function.bind = ccid_function_bind;
 	ccid_dev->function.unbind = ccid_function_unbind;
 	ccid_dev->function.set_alt = ccid_function_set_alt;
diff --git a/drivers/usb/gadget/function/f_diag.c b/drivers/usb/gadget/function/f_diag.c
index f08e443..b1bccd0 100644
--- a/drivers/usb/gadget/function/f_diag.c
+++ b/drivers/usb/gadget/function/f_diag.c
@@ -2,7 +2,7 @@
  * Diag Function Device - Route ARM9 and ARM11 DIAG messages
  * between HOST and DEVICE.
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -492,6 +492,7 @@
 }
 EXPORT_SYMBOL(usb_diag_alloc_req);
 #define DWC3_MAX_REQUEST_SIZE (16 * 1024 * 1024)
+#define CI_MAX_REQUEST_SIZE   (16 * 1024)
 /**
  * usb_diag_request_size - Max request size for controller
  * @ch: Channel handler
@@ -501,6 +502,12 @@
  */
 int usb_diag_request_size(struct usb_diag_ch *ch)
 {
+	struct diag_context *ctxt = ch->priv_usb;
+	struct usb_composite_dev *cdev = ctxt->cdev;
+
+	if (cdev->gadget->is_chipidea)
+		return CI_MAX_REQUEST_SIZE;
+
 	return DWC3_MAX_REQUEST_SIZE;
 }
 EXPORT_SYMBOL(usb_diag_request_size);
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 80e0e45..8eed1b3 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1404,7 +1404,7 @@
 		*to = p->data;
 	}
 
-	ffs_log("enter");
+	ffs_log("exit");
 
 	return res;
 }
@@ -3633,6 +3633,8 @@
 	if (ffs->func) {
 		ffs_func_eps_disable(ffs->func);
 		ffs->func = NULL;
+		/* matching put to allow LPM on disconnect */
+		usb_gadget_autopm_put_async(ffs->gadget);
 	}
 
 	if (ffs->state == FFS_DEACTIVATED) {
@@ -3665,13 +3667,9 @@
 
 static void ffs_func_disable(struct usb_function *f)
 {
-	struct ffs_function *func = ffs_func_from_usb(f);
-	struct ffs_data *ffs = func->ffs;
-
 	ffs_log("enter");
 	ffs_func_set_alt(f, 0, (unsigned)-1);
-	/* matching put to allow LPM on disconnect */
-	usb_gadget_autopm_put_async(ffs->gadget);
+
 	ffs_log("exit");
 }
 
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 7d509db..5ffbf12 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -19,14 +19,35 @@
 MODULE_PARM_DESC(qti_packet_debug, "Print QTI Packet's Raw Data");
 
 static struct workqueue_struct *ipa_usb_wq;
-static struct gsi_inst_status {
-	struct mutex gsi_lock;
-	bool inst_exist;
-	struct gsi_opts *opts;
-} inst_status[IPA_USB_MAX_TETH_PROT_SIZE];
+static struct f_gsi *__gsi[IPA_USB_MAX_TETH_PROT_SIZE];
+static void *ipc_log_ctxt;
+
+#define NUM_LOG_PAGES 15
+#define log_event_err(x, ...) do { \
+	if (gsi) { \
+		ipc_log_string(ipc_log_ctxt, "id%d:"x, gsi->prot_id, \
+				##__VA_ARGS__); \
+		pr_err("id%d:"x, gsi->prot_id, ##__VA_ARGS__); \
+	} \
+} while (0)
+
+#define log_event_dbg(x, ...) do { \
+	if (gsi) { \
+		ipc_log_string(ipc_log_ctxt, "id%d:"x, gsi->prot_id, \
+				##__VA_ARGS__); \
+		pr_debug("id%d:"x, gsi->prot_id, ##__VA_ARGS__); \
+	} \
+} while (0)
+
+#define log_event_info(x, ...) do { \
+	if (gsi) { \
+		ipc_log_string(ipc_log_ctxt, "id%d:"x, gsi->prot_id, \
+		##__VA_ARGS__); \
+		pr_info("id%d:"x, gsi->prot_id, ##__VA_ARGS__); \
+	} \
+} while (0)
 
 /* Deregister misc device and free instance structures */
-static void gsi_inst_clean(struct gsi_opts *opts);
 static void gsi_rndis_ipa_reset_trigger(struct gsi_data_port *d_port);
 static void ipa_disconnect_handler(struct gsi_data_port *d_port);
 static int gsi_ctrl_send_notification(struct f_gsi *gsi);
@@ -921,68 +942,43 @@
 						struct gsi_ctrl_port,
 						ctrl_device);
 	struct f_gsi *gsi;
-	struct gsi_inst_status *inst_cur;
 
 	if (!c_port) {
 		pr_err_ratelimited("%s: gsi ctrl port %pK", __func__, c_port);
 		return -ENODEV;
 	}
 
-	gsi = container_of(c_port, struct f_gsi, c_port);
-	inst_cur = &inst_status[gsi->prot_id];
+	gsi = c_port_to_gsi(c_port);
+
 	log_event_dbg("%s: open ctrl dev %s", __func__, c_port->name);
 
-	mutex_lock(&inst_cur->gsi_lock);
-
-	fp->private_data = &gsi->prot_id;
-
-	if (!inst_cur->inst_exist) {
-		mutex_unlock(&inst_cur->gsi_lock);
-		log_event_err("%s: [prot_id = %d], GSI instance freed already\n",
-				__func__, gsi->prot_id);
-		return -ENODEV;
-	}
-
 	if (c_port->is_open) {
-		mutex_unlock(&inst_cur->gsi_lock);
 		log_event_err("%s: Already opened\n", __func__);
 		return -EBUSY;
 	}
 
 	c_port->is_open = true;
 
-	mutex_unlock(&inst_cur->gsi_lock);
-
 	return 0;
 }
 
 static int gsi_ctrl_dev_release(struct inode *ip, struct file *fp)
 {
-	enum ipa_usb_teth_prot prot_id =
-		*(enum ipa_usb_teth_prot *)(fp->private_data);
-	struct gsi_inst_status *inst_cur = &inst_status[prot_id];
+	struct gsi_ctrl_port *c_port = container_of(fp->private_data,
+						struct gsi_ctrl_port,
+						ctrl_device);
 	struct f_gsi *gsi;
 
-	mutex_lock(&inst_cur->gsi_lock);
-
-	if (unlikely(inst_cur->inst_exist == false)) {
-		if (inst_cur->opts) {
-			/* GSI instance clean up */
-			gsi_inst_clean(inst_cur->opts);
-			inst_cur->opts = NULL;
-		}
-		mutex_unlock(&inst_cur->gsi_lock);
-		pr_err_ratelimited("%s: prot_id:%d: delayed free memory\n",
-			__func__, prot_id);
+	if (!c_port) {
+		pr_err_ratelimited("%s: gsi ctrl port NULL", __func__);
 		return -ENODEV;
 	}
 
-	inst_cur->opts->gsi->c_port.is_open = false;
-	gsi = inst_cur->opts->gsi;
-	mutex_unlock(&inst_cur->gsi_lock);
+	gsi = c_port_to_gsi(c_port);
 
-	log_event_dbg("close ctrl dev %s\n",
-			inst_cur->opts->gsi->c_port.name);
+	log_event_dbg("close ctrl dev %s\n", c_port->name);
+
+	c_port->is_open = false;
 
 	return 0;
 }
@@ -990,33 +986,23 @@
 static ssize_t
 gsi_ctrl_dev_read(struct file *fp, char __user *buf, size_t count, loff_t *pos)
 {
-	struct gsi_ctrl_port *c_port;
+	struct gsi_ctrl_port *c_port = container_of(fp->private_data,
+						struct gsi_ctrl_port,
+						ctrl_device);
 	struct gsi_ctrl_pkt *cpkt = NULL;
-	enum ipa_usb_teth_prot prot_id =
-		*(enum ipa_usb_teth_prot *)(fp->private_data);
-	struct gsi_inst_status *inst_cur = &inst_status[prot_id];
-	struct f_gsi *gsi;
 	unsigned long flags;
 	int ret = 0;
+	struct f_gsi *gsi;
 
-	pr_debug("%s: Enter %zu", __func__, count);
-
-	mutex_lock(&inst_cur->gsi_lock);
-	if (unlikely(inst_cur->inst_exist == false)) {
-		mutex_unlock(&inst_cur->gsi_lock);
-		pr_err_ratelimited("%s: free_inst is called and being freed\n",
-								__func__);
-		return -ENODEV;
-	}
-	mutex_unlock(&inst_cur->gsi_lock);
-
-	gsi = inst_cur->opts->gsi;
-	c_port = &inst_cur->opts->gsi->c_port;
 	if (!c_port) {
-		log_event_err("%s: gsi ctrl port %pK", __func__, c_port);
+		pr_err_ratelimited("%s: gsi ctrl port NULL", __func__);
 		return -ENODEV;
 	}
 
+	gsi = c_port_to_gsi(c_port);
+
+	log_event_dbg("%s: Enter %zu", __func__, count);
+
 	if (count > GSI_MAX_CTRL_PKT_SIZE) {
 		log_event_err("Large buff size %zu, should be %d",
 			count, GSI_MAX_CTRL_PKT_SIZE);
@@ -1079,34 +1065,32 @@
 	int ret = 0;
 	unsigned long flags;
 	struct gsi_ctrl_pkt *cpkt;
-	struct gsi_ctrl_port *c_port;
-	struct usb_request *req;
-	enum ipa_usb_teth_prot prot_id =
-		*(enum ipa_usb_teth_prot *)(fp->private_data);
-	struct gsi_inst_status *inst_cur = &inst_status[prot_id];
 	struct f_gsi *gsi;
+	struct gsi_ctrl_port *c_port = container_of(fp->private_data,
+						struct gsi_ctrl_port,
+						ctrl_device);
 
-	pr_debug("Enter %zu", count);
-
-	mutex_lock(&inst_cur->gsi_lock);
-	if (unlikely(inst_cur->inst_exist == false)) {
-		mutex_unlock(&inst_cur->gsi_lock);
-		pr_err_ratelimited("%s: free_inst is called and being freed\n",
-								__func__);
+	if (!c_port) {
+		pr_err_ratelimited("%s: gsi ctrl port NULL", __func__);
 		return -ENODEV;
 	}
-	mutex_unlock(&inst_cur->gsi_lock);
 
-	gsi = inst_cur->opts->gsi;
-	c_port = &gsi->c_port;
-	req = c_port->notify_req;
-
-	if (!c_port || !req || !req->buf) {
-		log_event_err("%s: c_port %pK req %p req->buf %p",
-			__func__, c_port, req, req ? req->buf : req);
+	if (!c_port->notify_req) {
+		pr_err_ratelimited("%s: gsi ctrl port notify_req NULL",
+				__func__);
 		return -ENODEV;
 	}
 
+	if (!c_port->notify_req->buf) {
+		pr_err_ratelimited("%s: gsi ctrl port notify_req->buf",
+				__func__);
+		return -ENODEV;
+	}
+
+	gsi = c_port_to_gsi(c_port);
+
+	log_event_dbg("%s: Enter %zu", __func__, count);
+
 	if (!count || count > GSI_MAX_CTRL_PKT_SIZE) {
 		log_event_err("error: ctrl pkt length %zu", count);
 		return -EINVAL;
@@ -1157,33 +1141,22 @@
 static long gsi_ctrl_dev_ioctl(struct file *fp, unsigned int cmd,
 		unsigned long arg)
 {
-	struct gsi_ctrl_port *c_port;
+	struct gsi_ctrl_port *c_port = container_of(fp->private_data,
+						struct gsi_ctrl_port,
+						ctrl_device);
 	struct f_gsi *gsi;
 	struct gsi_ctrl_pkt *cpkt;
 	struct ep_info info;
-	enum ipa_usb_teth_prot prot_id =
-		*(enum ipa_usb_teth_prot *)(fp->private_data);
-	struct gsi_inst_status *inst_cur = &inst_status[prot_id];
 	int val, ret = 0;
 	unsigned long flags;
 
-	mutex_lock(&inst_cur->gsi_lock);
-	if (unlikely(inst_cur->inst_exist == false)) {
-		mutex_unlock(&inst_cur->gsi_lock);
-		pr_err_ratelimited("%s: free_inst is called and being freed\n",
-								__func__);
-		return -ENODEV;
-	}
-	mutex_unlock(&inst_cur->gsi_lock);
-
-	gsi = inst_cur->opts->gsi;
-	c_port = &gsi->c_port;
-
 	if (!c_port) {
-		log_event_err("%s: gsi ctrl port %pK", __func__, c_port);
+		pr_err_ratelimited("%s: gsi ctrl port NULL", __func__);
 		return -ENODEV;
 	}
 
+	gsi = c_port_to_gsi(c_port);
+
 	switch (cmd) {
 	case QTI_CTRL_MODEM_OFFLINE:
 		if (gsi->prot_id == IPA_USB_DIAG) {
@@ -1301,30 +1274,20 @@
 
 static unsigned int gsi_ctrl_dev_poll(struct file *fp, poll_table *wait)
 {
-	struct gsi_ctrl_port *c_port;
-	enum ipa_usb_teth_prot prot_id =
-		*(enum ipa_usb_teth_prot *)(fp->private_data);
-	struct gsi_inst_status *inst_cur = &inst_status[prot_id];
-	struct f_gsi *gsi;
+	struct gsi_ctrl_port *c_port = container_of(fp->private_data,
+						struct gsi_ctrl_port,
+						ctrl_device);
 	unsigned long flags;
 	unsigned int mask = 0;
+	struct f_gsi *gsi;
 
-	mutex_lock(&inst_cur->gsi_lock);
-	if (unlikely(inst_cur->inst_exist == false)) {
-		mutex_unlock(&inst_cur->gsi_lock);
-		pr_err_ratelimited("%s: free_inst is called and being freed\n",
-								__func__);
-		return -ENODEV;
-	}
-	mutex_unlock(&inst_cur->gsi_lock);
-
-	gsi = inst_cur->opts->gsi;
-	c_port = &inst_cur->opts->gsi->c_port;
 	if (!c_port) {
-		log_event_err("%s: gsi ctrl port %pK", __func__, c_port);
+		pr_err_ratelimited("%s: gsi ctrl port NULL", __func__);
 		return -ENODEV;
 	}
 
+	gsi = c_port_to_gsi(c_port);
+
 	poll_wait(fp, &c_port->read_wq, wait);
 
 	spin_lock_irqsave(&c_port->lock, flags);
@@ -1368,11 +1331,6 @@
 	int sz = GSI_CTRL_NAME_LEN;
 	bool ctrl_dev_create = true;
 
-	if (!gsi) {
-		log_event_err("%s: gsi prot ctx is NULL", __func__);
-		return -EINVAL;
-	}
-
 	INIT_LIST_HEAD(&gsi->c_port.cpkt_req_q);
 	INIT_LIST_HEAD(&gsi->c_port.cpkt_resp_q);
 
@@ -2917,7 +2875,9 @@
 
 static void gsi_free_func(struct usb_function *f)
 {
-	pr_debug("%s\n", __func__);
+	struct f_gsi *gsi = func_to_gsi(f);
+
+	log_event_dbg("%s\n", __func__);
 }
 
 static int gsi_bind_config(struct f_gsi *gsi)
@@ -2970,21 +2930,15 @@
 	return status;
 }
 
-static struct f_gsi *gsi_function_init(enum ipa_usb_teth_prot prot_id)
+static struct f_gsi *gsi_function_init(void)
 {
 	struct f_gsi *gsi;
 	int ret = 0;
 
-	if (prot_id >= IPA_USB_MAX_TETH_PROT_SIZE) {
-		pr_err("%s: invalid prot id %d", __func__, prot_id);
-		ret = -EINVAL;
-		goto error;
-	}
-
 	gsi = kzalloc(sizeof(*gsi), GFP_KERNEL);
 	if (!gsi) {
 		ret = -ENOMEM;
-		goto error;
+		return ERR_PTR(ret);
 	}
 
 	spin_lock_init(&gsi->d_port.lock);
@@ -2994,19 +2948,9 @@
 	gsi->d_port.in_channel_handle = -EINVAL;
 	gsi->d_port.out_channel_handle = -EINVAL;
 
-	gsi->prot_id = prot_id;
-
 	gsi->d_port.ipa_usb_wq = ipa_usb_wq;
 
-	ret = gsi_function_ctrl_port_init(gsi);
-	if (ret) {
-		kfree(gsi);
-		goto error;
-	}
-
 	return gsi;
-error:
-	return ERR_PTR(ret);
 }
 
 static void gsi_opts_release(struct config_item *item)
@@ -3217,23 +3161,12 @@
 	.ct_owner	= THIS_MODULE,
 };
 
-static void gsi_inst_clean(struct gsi_opts *opts)
-{
-	if (opts->gsi->c_port.ctrl_device.fops)
-		misc_deregister(&opts->gsi->c_port.ctrl_device);
-
-	kfree(opts->gsi);
-	kfree(opts);
-}
-
 static int gsi_set_inst_name(struct usb_function_instance *fi,
 	const char *name)
 {
-	int prot_id, name_len;
+	int prot_id, name_len, ret = 0;
+	struct gsi_opts *opts;
 	struct f_gsi *gsi;
-	char gsi_inst_name[MAX_INST_NAME_LEN + sizeof("gsi.") + 1];
-	void *ipc_log_ctxt;
-	struct gsi_opts *opts, *opts_prev;
 
 	opts = container_of(fi, struct gsi_opts, func_inst);
 
@@ -3248,73 +3181,27 @@
 		return -EINVAL;
 	}
 
-	mutex_lock(&inst_status[prot_id].gsi_lock);
-	opts_prev = inst_status[prot_id].opts;
-	if (opts_prev) {
-		mutex_unlock(&inst_status[prot_id].gsi_lock);
-		pr_err("%s: prot_id = %d, prev inst do not freed yet\n",
-						__func__, prot_id);
-		return -EBUSY;
-	}
-	mutex_unlock(&inst_status[prot_id].gsi_lock);
-
 	if (prot_id == IPA_USB_RNDIS)
 		config_group_init_type_name(&opts->func_inst.group, "",
 					    &gsi_func_rndis_type);
 
-	gsi = gsi_function_init(prot_id);
-	if (IS_ERR(gsi))
-		return PTR_ERR(gsi);
-
-	opts->gsi = gsi;
-	/*
-	 * create instance name with prefixing "gsi." to differentiate
-	 * ipc log debugfs entry
-	 */
-	snprintf(gsi_inst_name, sizeof(gsi_inst_name), "gsi.%s", name);
-	ipc_log_ctxt = ipc_log_context_create(NUM_LOG_PAGES, gsi_inst_name, 0);
-	if (!ipc_log_ctxt)
-		pr_err("%s: Err allocating ipc_log_ctxt for prot:%s\n",
-						__func__, gsi_inst_name);
-	opts->gsi->ipc_log_ctxt = ipc_log_ctxt;
-
-	/* Set instance status */
-	mutex_lock(&inst_status[prot_id].gsi_lock);
-	inst_status[prot_id].inst_exist = true;
-	inst_status[prot_id].opts = opts;
-	mutex_unlock(&inst_status[prot_id].gsi_lock);
-
-	return 0;
+	gsi = opts->gsi = __gsi[prot_id];
+	opts->gsi->prot_id = prot_id;
+	ret = gsi_function_ctrl_port_init(opts->gsi);
+	if (ret)
+		log_event_err("%s:ctrl port init failed for %s instance\n",
+						__func__, name);
+	return ret;
 }
 
 static void gsi_free_inst(struct usb_function_instance *f)
 {
 	struct gsi_opts *opts = container_of(f, struct gsi_opts, func_inst);
-	enum ipa_usb_teth_prot prot_id;
-	struct f_gsi *gsi;
 
-	if (!opts->gsi)
-		return;
+	if (opts && opts->gsi && opts->gsi->c_port.ctrl_device.fops)
+		misc_deregister(&opts->gsi->c_port.ctrl_device);
 
-	prot_id = opts->gsi->prot_id;
-	gsi = opts->gsi;
-	mutex_lock(&inst_status[prot_id].gsi_lock);
-	if (opts->gsi->c_port.is_open) {
-		/* Mark instance exist as false */
-		inst_status[prot_id].inst_exist = false;
-		mutex_unlock(&inst_status[prot_id].gsi_lock);
-		log_event_err(
-			"%s: [prot_id = %d] Dev is open, free mem when dev close\n",
-			__func__, prot_id);
-		return;
-	}
-
-	ipc_log_context_destroy(opts->gsi->ipc_log_ctxt);
-	/* Clear instance status */
-	gsi_inst_clean(opts);
-	inst_status[prot_id].inst_exist = false;
-	inst_status[prot_id].opts = NULL;
-	mutex_unlock(&inst_status[prot_id].gsi_lock);
+	kfree(opts);
 }
 
 static struct usb_function_instance *gsi_alloc_inst(void)
@@ -3362,8 +3249,15 @@
 		return -ENOMEM;
 	}
 
-	for (i = 0; i < IPA_USB_MAX_TETH_PROT_SIZE; i++)
-		mutex_init(&inst_status[i].gsi_lock);
+	for (i = 0; i < IPA_USB_MAX_TETH_PROT_SIZE; i++) {
+		__gsi[i] = gsi_function_init();
+		if (IS_ERR(__gsi[i]))
+			return PTR_ERR(__gsi[i]);
+	}
+
+	ipc_log_ctxt = ipc_log_context_create(NUM_LOG_PAGES, "usb_gsi", 0);
+	if (!ipc_log_ctxt)
+		pr_err("%s: Err allocating ipc_log_ctxt\n", __func__);
 
 	return usb_function_register(&gsiusb_func);
 }
@@ -3371,8 +3265,16 @@
 
 static void __exit fgsi_exit(void)
 {
+	int i;
+
 	if (ipa_usb_wq)
 		destroy_workqueue(ipa_usb_wq);
+	if (ipc_log_ctxt)
+		ipc_log_context_destroy(ipc_log_ctxt);
+
+	for (i = 0; i < IPA_USB_MAX_TETH_PROT_SIZE; i++)
+		kfree(__gsi[i]);
+
 	usb_function_unregister(&gsiusb_func);
 }
 module_exit(fgsi_exit);
diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h
index 71bea5e..c6e64fd 100644
--- a/drivers/usb/gadget/function/f_gsi.h
+++ b/drivers/usb/gadget/function/f_gsi.h
@@ -82,28 +82,6 @@
 #define	EVT_IPA_SUSPEND			9
 #define	EVT_RESUMED			10
 
-#define NUM_LOG_PAGES 10
-#define log_event_err(x, ...) do { \
-	if (gsi) { \
-		ipc_log_string(gsi->ipc_log_ctxt, x, ##__VA_ARGS__); \
-		pr_err(x, ##__VA_ARGS__); \
-	} \
-} while (0)
-
-#define log_event_dbg(x, ...) do { \
-	if (gsi) { \
-		ipc_log_string(gsi->ipc_log_ctxt, x, ##__VA_ARGS__); \
-		pr_debug(x, ##__VA_ARGS__); \
-	} \
-} while (0)
-
-#define log_event_info(x, ...) do { \
-	if (gsi) { \
-		ipc_log_string(gsi->ipc_log_ctxt, x, ##__VA_ARGS__); \
-		pr_info(x, ##__VA_ARGS__); \
-	} \
-} while (0)
-
 enum connection_state {
 	STATE_UNINITIALIZED,
 	STATE_INITIALIZED,
@@ -275,7 +253,6 @@
 
 	struct gsi_data_port d_port;
 	struct gsi_ctrl_port c_port;
-	void *ipc_log_ctxt;
 	bool rmnet_dtr_status;
 };
 
@@ -313,15 +290,15 @@
 	if (!name)
 		goto error;
 
-	if (!strncasecmp(name, "rndis", strlen("rndis")))
+	if (!strncasecmp(name, "rndis", MAX_INST_NAME_LEN))
 		return IPA_USB_RNDIS;
-	if (!strncasecmp(name, "ecm", strlen("ecm")))
+	if (!strncasecmp(name, "ecm", MAX_INST_NAME_LEN))
 		return IPA_USB_ECM;
-	if (!strncasecmp(name, "rmnet", strlen("rmnet")))
+	if (!strncasecmp(name, "rmnet", MAX_INST_NAME_LEN))
 		return IPA_USB_RMNET;
-	if (!strncasecmp(name, "mbim", strlen("mbim")))
+	if (!strncasecmp(name, "mbim", MAX_INST_NAME_LEN))
 		return IPA_USB_MBIM;
-	if (!strncasecmp(name, "dpl", strlen("dpl")))
+	if (!strncasecmp(name, "dpl", MAX_INST_NAME_LEN))
 		return IPA_USB_DIAG;
 
 error:
@@ -879,6 +856,7 @@
 
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	4*cpu_to_le16(NCM_STATUS_BYTECOUNT),
 };
 
 static struct usb_endpoint_descriptor mbim_gsi_fs_out_desc = {
@@ -887,6 +865,7 @@
 
 	.bEndpointAddress =	USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	4*cpu_to_le16(NCM_STATUS_BYTECOUNT),
 };
 
 static struct usb_descriptor_header *mbim_gsi_fs_function[] = {
@@ -1180,6 +1159,7 @@
 
 	.bEndpointAddress =	USB_DIR_IN,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(ECM_QC_STATUS_BYTECOUNT),
 };
 
 static struct usb_endpoint_descriptor ecm_gsi_fs_out_desc = {
@@ -1188,6 +1168,7 @@
 
 	.bEndpointAddress =	USB_DIR_OUT,
 	.bmAttributes =		USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize =	cpu_to_le16(ECM_QC_STATUS_BYTECOUNT),
 };
 
 static struct usb_descriptor_header *ecm_gsi_fs_function[] = {
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index b24ad72..675741b 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -2282,18 +2282,6 @@
 			}
 		}
 
-		/* Disable the endpoints */
-		if (fsg->bulk_in_enabled) {
-			usb_ep_disable(fsg->bulk_in);
-			fsg->bulk_in_enabled = 0;
-		}
-		if (fsg->bulk_out_enabled) {
-			usb_ep_disable(fsg->bulk_out);
-			fsg->bulk_out_enabled = 0;
-		}
-
-		/* allow usb LPM after eps are disabled */
-		usb_gadget_autopm_put_async(common->gadget);
 		common->fsg = NULL;
 		wake_up(&common->fsg_wait);
 	}
@@ -2305,28 +2293,6 @@
 	common->fsg = new_fsg;
 	fsg = common->fsg;
 
-	/* Enable the endpoints */
-	rc = config_ep_by_speed(common->gadget, &(fsg->function), fsg->bulk_in);
-	if (rc)
-		goto reset;
-	rc = usb_ep_enable(fsg->bulk_in);
-	if (rc)
-		goto reset;
-	fsg->bulk_in->driver_data = common;
-	fsg->bulk_in_enabled = 1;
-
-	rc = config_ep_by_speed(common->gadget, &(fsg->function),
-				fsg->bulk_out);
-	if (rc)
-		goto reset;
-	rc = usb_ep_enable(fsg->bulk_out);
-	if (rc)
-		goto reset;
-	fsg->bulk_out->driver_data = common;
-	fsg->bulk_out_enabled = 1;
-	common->bulk_out_maxpacket = usb_endpoint_maxp(fsg->bulk_out->desc);
-	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
-
 	/* Allocate the requests */
 	for (i = 0; i < common->fsg_num_buffers; ++i) {
 		struct fsg_buffhd	*bh = &common->buffhds[i];
@@ -2357,20 +2323,71 @@
 static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
 {
 	struct fsg_dev *fsg = fsg_from_func(f);
-	fsg->common->new_fsg = fsg;
+	int rc;
 
+	fsg->common->new_fsg = fsg;
 	/* prevents usb LPM until thread runs to completion */
 	usb_gadget_autopm_get_async(fsg->common->gadget);
 
+	/* Enable the endpoints */
+	rc = config_ep_by_speed(fsg->common->gadget, &(fsg->function),
+				fsg->bulk_in);
+	if (rc)
+		goto err_exit;
+	rc = usb_ep_enable(fsg->bulk_in);
+	if (rc)
+		goto err_exit;
+	fsg->bulk_in->driver_data = fsg->common;
+	fsg->bulk_in_enabled = 1;
+
+	rc = config_ep_by_speed(fsg->common->gadget, &(fsg->function),
+				fsg->bulk_out);
+	if (rc)
+		goto reset_bulk_int;
+
+	rc = usb_ep_enable(fsg->bulk_out);
+	if (rc)
+		goto reset_bulk_int;
+
+	fsg->bulk_out->driver_data = fsg->common;
+	fsg->bulk_out_enabled = 1;
+	fsg->common->bulk_out_maxpacket =
+					usb_endpoint_maxp(fsg->bulk_out->desc);
+	clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags);
+
+
 	raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
 	return USB_GADGET_DELAYED_STATUS;
+
+reset_bulk_int:
+	usb_ep_disable(fsg->bulk_in);
+	fsg->bulk_in->driver_data = NULL;
+	fsg->bulk_in_enabled = 0;
+err_exit:
+	return rc;
 }
 
 static void fsg_disable(struct usb_function *f)
 {
 	struct fsg_dev *fsg = fsg_from_func(f);
+
+	/* Disable the endpoints */
+	if (fsg->bulk_in_enabled) {
+		usb_ep_disable(fsg->bulk_in);
+		fsg->bulk_in->driver_data = NULL;
+		fsg->bulk_in_enabled = 0;
+	}
+
+	if (fsg->bulk_out_enabled) {
+		usb_ep_disable(fsg->bulk_out);
+		fsg->bulk_out->driver_data = NULL;
+		fsg->bulk_out_enabled = 0;
+	}
+
 	fsg->common->new_fsg = NULL;
 	raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE);
+	/* allow usb LPM after eps are disabled */
+	usb_gadget_autopm_put_async(fsg->common->gadget);
 }
 
 
diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c
index 4cc7d94..651776d 100644
--- a/drivers/usb/gadget/function/f_mtp.c
+++ b/drivers/usb/gadget/function/f_mtp.c
@@ -1415,6 +1415,12 @@
 	dev->cdev = cdev;
 	DBG(cdev, "mtp_function_bind dev: %pK\n", dev);
 
+	/* ChipIdea controller supports 16K request length for IN endpoint */
+	if (cdev->gadget->is_chipidea && mtp_tx_req_len > 16384) {
+		DBG(cdev, "Truncating Tx Req length to 16K for ChipIdea\n");
+		mtp_tx_req_len = 16384;
+	}
+
 	/* allocate interface ID(s) */
 	id = usb_interface_id(c, f);
 	if (id < 0)
diff --git a/drivers/usb/gadget/function/f_qc_rndis.c b/drivers/usb/gadget/function/f_qc_rndis.c
index 908805a..df26403 100644
--- a/drivers/usb/gadget/function/f_qc_rndis.c
+++ b/drivers/usb/gadget/function/f_qc_rndis.c
@@ -1063,6 +1063,7 @@
 	 * until we're activated via set_alt().
 	 */
 
+	c->cdev->gadget->bam2bam_func_enabled = true;
 	DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n",
 			gadget_is_superspeed(c->cdev->gadget) ? "super" :
 			gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
@@ -1116,6 +1117,7 @@
 		usb_free_descriptors(f->hs_descriptors);
 	usb_free_descriptors(f->fs_descriptors);
 
+	c->cdev->gadget->bam2bam_func_enabled = false;
 	kfree(rndis->notify_req->buf);
 	usb_ep_free_request(rndis->notify, rndis->notify_req);
 
diff --git a/drivers/usb/gadget/function/f_qdss.c b/drivers/usb/gadget/function/f_qdss.c
index 6ae2693..d1c3741 100644
--- a/drivers/usb/gadget/function/f_qdss.c
+++ b/drivers/usb/gadget/function/f_qdss.c
@@ -478,6 +478,7 @@
 		}
 	}
 
+	c->cdev->gadget->bam2bam_func_enabled = true;
 	return 0;
 fail:
 	clear_eps(f);
@@ -494,7 +495,7 @@
 	pr_debug("qdss_unbind\n");
 
 	flush_workqueue(qdss->wq);
-
+	c->cdev->gadget->bam2bam_func_enabled = false;
 	clear_eps(f);
 	clear_desc(gadget, f);
 }
diff --git a/drivers/usb/gadget/function/f_rmnet.c b/drivers/usb/gadget/function/f_rmnet.c
index ffc6897..bdb9762 100644
--- a/drivers/usb/gadget/function/f_rmnet.c
+++ b/drivers/usb/gadget/function/f_rmnet.c
@@ -480,6 +480,8 @@
 
 	if (dev->notify_req)
 		frmnet_free_req(dev->notify, dev->notify_req);
+
+	c->cdev->gadget->bam2bam_func_enabled = false;
 }
 
 static void frmnet_purge_responses(struct f_rmnet *dev)
@@ -1116,6 +1118,9 @@
 		return dev->ifc_id;
 	}
 
+	if (dev->xport_type == BAM2BAM_IPA)
+		c->cdev->gadget->bam2bam_func_enabled = true;
+
 	info.data_str_idx = 0;
 	if (dev->qti_port_type == QTI_PORT_RMNET) {
 		info.string_defs = rmnet_string_defs;
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 56b2a6d..6111d39 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, 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
@@ -1562,6 +1562,18 @@
 
 	/* if this interrupts a previous exchange, abort queued response */
 	if (cmd_type == SVDM_CMD_TYPE_INITIATOR && pd->vdm_tx) {
+		/*
+		 * Drop ATTENTION command unless atleast one SVID handler is
+		 * discovered/connected.
+		 */
+		if (cmd == USBPD_SVDM_ATTENTION && handler &&
+						!handler->discovered) {
+			usbpd_dbg(&pd->dev, "Send vdm command again queued SVDM tx (SVID:0x%04x)\n",
+				VDM_HDR_SVID(pd->vdm_tx->data[0]));
+			kick_sm(pd, 0);
+			return;
+		}
+
 		usbpd_dbg(&pd->dev, "Discarding previously queued SVDM tx (SVID:0x%04x)\n",
 				VDM_HDR_SVID(pd->vdm_tx->data[0]));
 
@@ -1818,6 +1830,7 @@
 	pd->num_svids = 0;
 	kfree(pd->vdm_tx);
 	pd->vdm_tx = NULL;
+	pd->ss_lane_svid = 0x0;
 }
 
 static void dr_swap(struct usbpd *pd)
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index 7706a48..39086bf 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -215,6 +215,8 @@
 	bool vbus_low_as_hostmode;
 };
 
+#define SDP_CHECK_DELAY_MS 10000 /* in ms */
+
 #define MSM_USB_BASE	(motg->regs)
 #define MSM_USB_PHY_CSR_BASE (motg->phy_csr_regs)
 
@@ -1808,23 +1810,41 @@
 }
 #endif
 
-static void msm_otg_notify_chg_current(struct msm_otg *motg, unsigned int mA)
+static int get_psy_type(struct msm_otg *motg)
 {
-	struct usb_gadget *g = motg->phy.otg->gadget;
 	union power_supply_propval pval = {0};
 
-	if (g && g->is_a_peripheral)
-		return;
-
-	dev_dbg(motg->phy.dev, "Requested curr from USB = %u\n", mA);
 	if (!psy) {
-		dev_dbg(motg->phy.dev, "no usb power supply registered\n");
-		return;
+		dev_err(motg->phy.dev, "no usb power supply registered\n");
+		return -ENODEV;
 	}
 
 	power_supply_get_property(psy, POWER_SUPPLY_PROP_REAL_TYPE, &pval);
 
-	if (motg->cur_power == mA || pval.intval != POWER_SUPPLY_TYPE_USB)
+	return pval.intval;
+}
+
+static void msm_otg_notify_chg_current(struct msm_otg *motg, unsigned int mA)
+{
+	struct usb_gadget *g = motg->phy.otg->gadget;
+	union power_supply_propval pval = {0};
+	int psy_type;
+
+	if (g && g->is_a_peripheral)
+		return;
+
+	psy_type = get_psy_type(motg);
+	if (psy_type == POWER_SUPPLY_TYPE_USB_FLOAT) {
+		if (!mA)
+			pval.intval = -ETIMEDOUT;
+		else
+			pval.intval = 1000 * mA;
+		goto set_prop;
+	}
+
+	dev_dbg(motg->phy.dev, "Requested curr from USB = %u\n", mA);
+
+	if (motg->cur_power == mA || psy_type != POWER_SUPPLY_TYPE_USB)
 		return;
 
 	dev_info(motg->phy.dev, "Avail curr from USB = %u\n", mA);
@@ -1833,6 +1853,7 @@
 	/* Set max current limit in uA */
 	pval.intval = 1000 * mA;
 
+set_prop:
 	if (power_supply_set_property(psy, POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
 								&pval)) {
 		dev_dbg(motg->phy.dev, "power supply error when setting property\n");
@@ -2335,6 +2356,21 @@
 							USB_ID_GROUND;
 }
 
+static void check_for_sdp_connection(struct work_struct *w)
+{
+	struct msm_otg *motg = container_of(w, struct msm_otg, sdp_check.work);
+
+	/* Cable disconnected or device enumerated as SDP */
+	if (!motg->vbus_state || motg->phy.otg->gadget->state >=
+							USB_STATE_DEFAULT)
+		return;
+
+	/* floating D+/D- lines detected */
+	motg->vbus_state = 0;
+	msm_otg_dbg_log_event(&motg->phy, "Q RW SDP CHK", motg->vbus_state, 0);
+	msm_otg_set_vbus_state(motg->vbus_state);
+}
+
 static void msm_otg_sm_work(struct work_struct *w)
 {
 	struct msm_otg *motg = container_of(w, struct msm_otg, sm_work);
@@ -2408,6 +2444,11 @@
 				break;
 			}
 
+			if (get_psy_type(motg) == POWER_SUPPLY_TYPE_USB_FLOAT)
+				queue_delayed_work(motg->otg_wq,
+					&motg->sdp_check,
+					msecs_to_jiffies(SDP_CHECK_DELAY_MS));
+
 			pm_runtime_get_sync(otg->usb_phy->dev);
 			msm_otg_start_peripheral(otg, 1);
 			otg->state = OTG_STATE_B_PERIPHERAL;
@@ -2421,6 +2462,7 @@
 		break;
 	case OTG_STATE_B_PERIPHERAL:
 		if (!test_bit(B_SESS_VLD, &motg->inputs)) {
+			cancel_delayed_work_sync(&motg->sdp_check);
 			msm_otg_start_peripheral(otg, 0);
 			msm_otg_dbg_log_event(&motg->phy, "RT PM: B_PERI A PUT",
 				get_pm_runtime_counter(dev), 0);
@@ -2443,6 +2485,7 @@
 		break;
 	case OTG_STATE_B_SUSPEND:
 		if (!test_bit(B_SESS_VLD, &motg->inputs)) {
+			cancel_delayed_work_sync(&motg->sdp_check);
 			msm_otg_start_peripheral(otg, 0);
 			otg->state = OTG_STATE_B_IDLE;
 			/* Schedule work to finish cable disconnect processing*/
@@ -3824,6 +3867,7 @@
 	INIT_WORK(&motg->sm_work, msm_otg_sm_work);
 	INIT_DELAYED_WORK(&motg->id_status_work, msm_id_status_w);
 	INIT_DELAYED_WORK(&motg->perf_vote_work, msm_otg_perf_vote_work);
+	INIT_DELAYED_WORK(&motg->sdp_check, check_for_sdp_connection);
 	INIT_WORK(&motg->notify_chg_current_work,
 			 msm_otg_notify_chg_current_work);
 	motg->otg_wq = alloc_ordered_workqueue("k_otg", 0);
@@ -4176,6 +4220,7 @@
 	if (psy)
 		power_supply_put(psy);
 	msm_otg_debugfs_cleanup();
+	cancel_delayed_work_sync(&motg->sdp_check);
 	cancel_delayed_work_sync(&motg->id_status_work);
 	cancel_delayed_work_sync(&motg->perf_vote_work);
 	msm_otg_perf_vote_update(motg, false);
diff --git a/drivers/video/fbdev/msm/Makefile b/drivers/video/fbdev/msm/Makefile
index 4ee7f4a..81d4953 100644
--- a/drivers/video/fbdev/msm/Makefile
+++ b/drivers/video/fbdev/msm/Makefile
@@ -41,6 +41,7 @@
 mdss-dsi-objs += mdss_dsi_panel.o
 mdss-dsi-objs += msm_mdss_io_8974.o
 mdss-dsi-objs += mdss_dsi_phy.o
+mdss-dsi-objs += mdss_dsi_phy_12nm.o
 mdss-dsi-objs += mdss_dsi_clk.o
 obj-$(CONFIG_FB_MSM_MDSS) += mdss-dsi.o
 obj-$(CONFIG_FB_MSM_MDSS) += mdss_panel.o
diff --git a/drivers/video/fbdev/msm/mdp3.c b/drivers/video/fbdev/msm/mdp3.c
index 00183f8..591c240 100644
--- a/drivers/video/fbdev/msm/mdp3.c
+++ b/drivers/video/fbdev/msm/mdp3.c
@@ -44,6 +44,7 @@
 
 #include <linux/msm-bus.h>
 #include <linux/msm-bus-board.h>
+#include <linux/vmalloc.h>
 
 #include <linux/msm_dma_iommu_mapping.h>
 
@@ -1367,7 +1368,7 @@
 		return -EINVAL;
 	}
 	if (client == MDP3_CLIENT_PPP || client == MDP3_CLIENT_DMA_P) {
-		kfree(data->tab_clone->sgl);
+		vfree(data->tab_clone->sgl);
 		kfree(data->tab_clone);
 	}
 	return 0;
@@ -1496,7 +1497,7 @@
 	dma_buf_put(data->srcp_dma_buf);
 
 	if (client ==  MDP3_CLIENT_PPP || client == MDP3_CLIENT_DMA_P) {
-		kfree(data->tab_clone->sgl);
+		vfree(data->tab_clone->sgl);
 		kfree(data->tab_clone);
 	}
 	return ret;
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c
index 4a844e9..589f2df 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.c
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.c
@@ -1738,12 +1738,15 @@
 		break;
 	case metadata_op_get_ion_fd:
 		if (mfd->fb_ion_handle && mfd->fb_ion_client) {
+			get_dma_buf(mfd->fbmem_buf);
 			metadata->data.fbmem_ionfd =
 				ion_share_dma_buf_fd(mfd->fb_ion_client,
 					mfd->fb_ion_handle);
-			if (metadata->data.fbmem_ionfd < 0)
+			if (metadata->data.fbmem_ionfd < 0) {
+				dma_buf_put(mfd->fbmem_buf);
 				pr_err("fd allocation failed. fd = %d\n",
-						metadata->data.fbmem_ionfd);
+					metadata->data.fbmem_ionfd);
+			}
 		}
 		break;
 	default:
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 6bb0960..cad1387 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -2989,9 +2989,9 @@
 	info.core_clks.mmss_misc_ahb_clk =
 		ctrl_pdata->shared_data->mmss_misc_ahb_clk;
 
-	info.link_clks.esc_clk = ctrl_pdata->esc_clk;
-	info.link_clks.byte_clk = ctrl_pdata->byte_clk;
-	info.link_clks.pixel_clk = ctrl_pdata->pixel_clk;
+	info.link_lp_clks.esc_clk = ctrl_pdata->esc_clk;
+	info.link_hs_clks.byte_clk = ctrl_pdata->byte_clk;
+	info.link_hs_clks.pixel_clk = ctrl_pdata->pixel_clk;
 
 	info.pre_clkoff_cb = mdss_dsi_pre_clkoff_cb;
 	info.post_clkon_cb = mdss_dsi_post_clkon_cb;
@@ -3976,13 +3976,12 @@
 	if (!data) {
 		pr_err("%s:%d, Unable to read Phy Strength ctrl settings\n",
 			__func__, __LINE__);
-		return -EINVAL;
+	} else {
+		pinfo->mipi.dsi_phy_db.strength_len = len;
+		for (i = 0; i < len; i++)
+			pinfo->mipi.dsi_phy_db.strength[i] = data[i];
 	}
 
-	pinfo->mipi.dsi_phy_db.strength_len = len;
-	for (i = 0; i < len; i++)
-		pinfo->mipi.dsi_phy_db.strength[i] = data[i];
-
 	pinfo->mipi.dsi_phy_db.reg_ldo_mode = of_property_read_bool(
 		ctrl_pdev->dev.of_node, "qcom,regulator-ldo-mode");
 
@@ -3991,13 +3990,12 @@
 	if (!data) {
 		pr_err("%s:%d, Unable to read Phy regulator settings\n",
 			__func__, __LINE__);
-		return -EINVAL;
+	} else {
+		pinfo->mipi.dsi_phy_db.regulator_len = len;
+		for (i = 0; i < len; i++)
+			pinfo->mipi.dsi_phy_db.regulator[i] = data[i];
 	}
 
-	pinfo->mipi.dsi_phy_db.regulator_len = len;
-	for (i = 0; i < len; i++)
-		pinfo->mipi.dsi_phy_db.regulator[i] = data[i];
-
 	data = of_get_property(ctrl_pdev->dev.of_node,
 		"qcom,platform-bist-ctrl", &len);
 	if ((!data) || (len != 6))
@@ -4012,13 +4010,12 @@
 	if (!data) {
 		pr_err("%s:%d, Unable to read Phy lane configure settings\n",
 			__func__, __LINE__);
-		return -EINVAL;
+	} else {
+		pinfo->mipi.dsi_phy_db.lanecfg_len = len;
+		for (i = 0; i < len; i++)
+			pinfo->mipi.dsi_phy_db.lanecfg[i] = data[i];
 	}
 
-	pinfo->mipi.dsi_phy_db.lanecfg_len = len;
-	for (i = 0; i < len; i++)
-		pinfo->mipi.dsi_phy_db.lanecfg[i] = data[i];
-
 	ctrl_pdata->timing_db_mode = of_property_read_bool(
 		ctrl_pdev->dev.of_node, "qcom,timing-db-mode");
 
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h
index 60bc455..058c27a 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.h
+++ b/drivers/video/fbdev/msm/mdss_dsi.h
@@ -337,6 +337,7 @@
 	struct mdss_panel_timing timing;
 	uint32_t phy_timing[12];
 	uint32_t phy_timing_8996[40];
+	uint32_t phy_timing_12nm[8];
 	/* DSI_CLKOUT_TIMING_CTRL */
 	char t_clk_post;
 	char t_clk_pre;
@@ -616,15 +617,19 @@
 			struct mdss_dsi_ctrl_pdata *ctrl_pdata);
 int mdss_dsi_pre_clkoff_cb(void *priv,
 			   enum mdss_dsi_clk_type clk_type,
+			   enum mdss_dsi_lclk_type l_type,
 			   enum mdss_dsi_clk_state new_state);
 int mdss_dsi_post_clkoff_cb(void *priv,
 			    enum mdss_dsi_clk_type clk_type,
+			    enum mdss_dsi_lclk_type l_type,
 			    enum mdss_dsi_clk_state curr_state);
 int mdss_dsi_post_clkon_cb(void *priv,
 			   enum mdss_dsi_clk_type clk_type,
+			   enum mdss_dsi_lclk_type l_type,
 			   enum mdss_dsi_clk_state curr_state);
 int mdss_dsi_pre_clkon_cb(void *priv,
 			  enum mdss_dsi_clk_type clk_type,
+			  enum mdss_dsi_lclk_type l_type,
 			  enum mdss_dsi_clk_state new_state);
 int mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable);
 void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl);
diff --git a/drivers/video/fbdev/msm/mdss_dsi_clk.c b/drivers/video/fbdev/msm/mdss_dsi_clk.c
index 372c93e..779e847 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_clk.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_clk.c
@@ -27,11 +27,9 @@
 };
 
 struct dsi_link_clks {
-	struct mdss_dsi_link_clk_info clks;
+	struct mdss_dsi_link_hs_clk_info hs_clks;
+	struct mdss_dsi_link_lp_clk_info lp_clks;
 	u32 current_clk_state;
-	u32 byte_clk_rate;
-	u32 pix_clk_rate;
-	u32 esc_clk_rate;
 };
 
 struct mdss_dsi_clk_mngr {
@@ -73,28 +71,27 @@
 
 	rc = clk_prepare_enable(c_clks->clks.mdp_core_clk);
 	if (rc) {
-		pr_err("%s: failed to enable mdp_core_clock. rc=%d\n",
-							 __func__, rc);
+		pr_err("failed to enable mdp_core_clock. rc=%d\n", rc);
 		goto error;
 	}
 
 	rc = clk_prepare_enable(c_clks->clks.ahb_clk);
 	if (rc) {
-		pr_err("%s: failed to enable ahb clock. rc=%d\n", __func__, rc);
+		pr_err("failed to enable ahb clock. rc=%d\n", rc);
 		goto disable_core_clk;
 	}
 
 	rc = clk_prepare_enable(c_clks->clks.axi_clk);
 	if (rc) {
-		pr_err("%s: failed to enable ahb clock. rc=%d\n", __func__, rc);
+		pr_err("failed to enable ahb clock. rc=%d\n", rc);
 		goto disable_ahb_clk;
 	}
 
 	if (c_clks->clks.mmss_misc_ahb_clk) {
 		rc = clk_prepare_enable(c_clks->clks.mmss_misc_ahb_clk);
 		if (rc) {
-			pr_err("%s: failed to enable mmss misc ahb clk.rc=%d\n",
-				__func__, rc);
+			pr_err("failed to enable mmss misc ahb clk.rc=%d\n",
+				rc);
 			goto disable_axi_clk;
 		}
 	}
@@ -140,12 +137,15 @@
 	return rc;
 }
 
-static int dsi_link_clk_set_rate(struct dsi_link_clks *l_clks)
+static int dsi_link_hs_clk_set_rate(
+	struct mdss_dsi_link_hs_clk_info *link_hs_clks)
 {
 	int rc = 0;
 	struct mdss_dsi_clk_mngr *mngr;
+	struct dsi_link_clks *l_clks;
 	struct mdss_dsi_ctrl_pdata *ctrl;
 
+	l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks);
 	mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks);
 
 	/*
@@ -160,19 +160,13 @@
 	if (ctrl->panel_data.panel_info.cont_splash_enabled)
 		return 0;
 
-	rc = clk_set_rate(l_clks->clks.esc_clk, l_clks->esc_clk_rate);
-	if (rc) {
-		pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc);
-		goto error;
-	}
-
-	rc = clk_set_rate(l_clks->clks.byte_clk, l_clks->byte_clk_rate);
+	rc = clk_set_rate(link_hs_clks->byte_clk, link_hs_clks->byte_clk_rate);
 	if (rc) {
 		pr_err("clk_set_rate failed for byte_clk rc = %d\n", rc);
 		goto error;
 	}
 
-	rc = clk_set_rate(l_clks->clks.pixel_clk, l_clks->pix_clk_rate);
+	rc = clk_set_rate(link_hs_clks->pixel_clk, link_hs_clks->pix_clk_rate);
 	if (rc) {
 		pr_err("clk_set_rate failed for pixel_clk rc = %d\n", rc);
 		goto error;
@@ -182,141 +176,203 @@
 	return rc;
 }
 
-static int dsi_link_clk_prepare(struct dsi_link_clks *l_clks)
+static int dsi_link_hs_clk_prepare(
+	struct mdss_dsi_link_hs_clk_info *link_hs_clks)
 {
 	int rc = 0;
 
-	rc = clk_prepare(l_clks->clks.esc_clk);
+	rc = clk_prepare(link_hs_clks->byte_clk);
 	if (rc) {
-		pr_err("%s: Failed to prepare dsi esc clk\n", __func__);
-		goto esc_clk_err;
-	}
-
-	rc = clk_prepare(l_clks->clks.byte_clk);
-	if (rc) {
-		pr_err("%s: Failed to prepare dsi byte clk\n", __func__);
+		pr_err("Failed to prepare dsi byte clk\n");
 		goto byte_clk_err;
 	}
 
-	rc = clk_prepare(l_clks->clks.pixel_clk);
+	rc = clk_prepare(link_hs_clks->pixel_clk);
 	if (rc) {
-		pr_err("%s: Failed to prepare dsi pixel clk\n", __func__);
+		pr_err("Failed to prepare dsi pixel_clk\n");
 		goto pixel_clk_err;
 	}
 
 	return rc;
 
 pixel_clk_err:
-	clk_unprepare(l_clks->clks.byte_clk);
+	clk_unprepare(link_hs_clks->byte_clk);
 byte_clk_err:
-	clk_unprepare(l_clks->clks.esc_clk);
-esc_clk_err:
 	return rc;
 }
 
-static int dsi_link_clk_unprepare(struct dsi_link_clks *l_clks)
+static int dsi_link_hs_clk_unprepare(
+	struct mdss_dsi_link_hs_clk_info *link_hs_clks)
 {
 	int rc = 0;
 
-	clk_unprepare(l_clks->clks.pixel_clk);
-	clk_unprepare(l_clks->clks.byte_clk);
-	clk_unprepare(l_clks->clks.esc_clk);
+	clk_unprepare(link_hs_clks->pixel_clk);
+	clk_unprepare(link_hs_clks->byte_clk);
 
 	return rc;
 }
 
-static int dsi_link_clk_enable(struct dsi_link_clks *l_clks)
+static int dsi_link_hs_clk_enable(
+	struct mdss_dsi_link_hs_clk_info *link_hs_clks)
 {
 	int rc = 0;
 
-	rc = clk_enable(l_clks->clks.esc_clk);
+	rc = clk_enable(link_hs_clks->byte_clk);
 	if (rc) {
-		pr_err("%s: Failed to enable dsi esc clk\n", __func__);
-		goto esc_clk_err;
-	}
-
-	rc = clk_enable(l_clks->clks.byte_clk);
-	if (rc) {
-		pr_err("%s: Failed to enable dsi byte clk\n", __func__);
+		pr_err("Failed to enable dsi byte clk\n");
 		goto byte_clk_err;
 	}
 
-	rc = clk_enable(l_clks->clks.pixel_clk);
+	rc = clk_enable(link_hs_clks->pixel_clk);
 	if (rc) {
-		pr_err("%s: Failed to enable dsi pixel clk\n", __func__);
+		pr_err("Failed to enable dsi pixel_clk\n");
 		goto pixel_clk_err;
 	}
 
 	return rc;
 
 pixel_clk_err:
-	clk_disable(l_clks->clks.byte_clk);
+	clk_disable(link_hs_clks->byte_clk);
 byte_clk_err:
-	clk_disable(l_clks->clks.esc_clk);
-esc_clk_err:
 	return rc;
 }
 
-static int dsi_link_clk_disable(struct dsi_link_clks *l_clks)
+static int dsi_link_hs_clk_disable(
+	struct mdss_dsi_link_hs_clk_info *link_hs_clks)
 {
 	int rc = 0;
 
-	clk_disable(l_clks->clks.esc_clk);
-	clk_disable(l_clks->clks.pixel_clk);
-	clk_disable(l_clks->clks.byte_clk);
+	clk_disable(link_hs_clks->pixel_clk);
+	clk_disable(link_hs_clks->byte_clk);
 
 	return rc;
 }
 
 
-static int dsi_link_clk_start(struct dsi_link_clks *l_clks)
+static int dsi_link_hs_clk_start(
+	struct mdss_dsi_link_hs_clk_info *link_hs_clks,
+	enum mdss_dsi_link_clk_op_type op_type)
 {
 	int rc = 0;
+	struct dsi_link_clks *l_clks;
 	struct mdss_dsi_clk_mngr *mngr;
 
+	l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks);
 	mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks);
 
-	rc = dsi_link_clk_set_rate(l_clks);
-	if (rc) {
-		pr_err("failed to set clk rates, rc = %d\n", rc);
-		goto error;
+	if (op_type & MDSS_DSI_LINK_CLK_SET_RATE) {
+		rc = dsi_link_hs_clk_set_rate(link_hs_clks);
+		if (rc) {
+			pr_err("failed to set HS clk rates, rc = %d\n", rc);
+			goto error;
+		}
 	}
 
-	rc = dsi_link_clk_prepare(l_clks);
-	if (rc) {
-		pr_err("failed to prepare link clks, rc = %d\n", rc);
-		goto error;
+	if (op_type & MDSS_DSI_LINK_CLK_PREPARE) {
+		rc = dsi_link_hs_clk_prepare(link_hs_clks);
+		if (rc) {
+			pr_err("failed to prepare link HS clks, rc = %d\n", rc);
+			goto error;
+		}
 	}
 
-	rc = dsi_link_clk_enable(l_clks);
-	if (rc) {
-		pr_err("failed to enable link clks, rc = %d\n", rc);
-		goto error_unprepare;
+	if (op_type & MDSS_DSI_LINK_CLK_ENABLE) {
+		rc = dsi_link_hs_clk_enable(link_hs_clks);
+		if (rc) {
+			pr_err("failed to enable link HS clks, rc = %d\n", rc);
+			goto error_unprepare;
+		}
 	}
 
-	pr_debug("%s: LINK CLOCK IS ON\n", mngr->name);
+	pr_debug("%s: LINK HS CLOCK IS ON\n", mngr->name);
 	return rc;
 error_unprepare:
-	dsi_link_clk_unprepare(l_clks);
+	dsi_link_hs_clk_unprepare(link_hs_clks);
 error:
 	return rc;
 }
 
-static int dsi_link_clk_stop(struct dsi_link_clks *l_clks)
+static int dsi_link_lp_clk_start(
+	struct mdss_dsi_link_lp_clk_info *link_lp_clks)
 {
 	int rc = 0;
 	struct mdss_dsi_clk_mngr *mngr;
+	struct dsi_link_clks *l_clks;
+	struct mdss_dsi_ctrl_pdata *ctrl;
 
+	l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks);
+	mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks);
+	/*
+	 * In an ideal world, cont_splash_enabled should not be required inside
+	 * the clock manager. But, in the current driver cont_splash_enabled
+	 * flag is set inside mdp driver and there is no interface event
+	 * associated with this flag setting. Also, set rate for clock need not
+	 * be called for every enable call. It should be done only once when
+	 * coming out of suspend.
+	 */
+	ctrl = mngr->priv_data;
+	if (ctrl->panel_data.panel_info.cont_splash_enabled)
+		goto prepare;
+
+	rc = clk_set_rate(link_lp_clks->esc_clk, link_lp_clks->esc_clk_rate);
+	if (rc) {
+		pr_err("clk_set_rate failed for esc_clk rc = %d\n", rc);
+		goto error;
+	}
+
+prepare:
+	rc = clk_prepare(link_lp_clks->esc_clk);
+	if (rc) {
+		pr_err("Failed to prepare dsi esc clk\n");
+		goto error;
+	}
+
+	rc = clk_enable(link_lp_clks->esc_clk);
+	if (rc) {
+		pr_err("Failed to enable dsi esc clk\n");
+		clk_unprepare(l_clks->lp_clks.esc_clk);
+		goto error;
+	}
+error:
+	pr_debug("%s: LINK LP CLOCK IS ON\n", mngr->name);
+	return rc;
+}
+
+static int dsi_link_hs_clk_stop(
+	struct mdss_dsi_link_hs_clk_info *link_hs_clks)
+{
+	int rc = 0;
+	struct dsi_link_clks *l_clks;
+	struct mdss_dsi_clk_mngr *mngr;
+
+	l_clks = container_of(link_hs_clks, struct dsi_link_clks, hs_clks);
 	mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks);
 
-	(void)dsi_link_clk_disable(l_clks);
+	(void)dsi_link_hs_clk_disable(link_hs_clks);
 
-	(void)dsi_link_clk_unprepare(l_clks);
-	pr_debug("%s: LINK CLOCK IS OFF\n", mngr->name);
+	(void)dsi_link_hs_clk_unprepare(link_hs_clks);
+	pr_debug("%s: LINK HS CLOCK IS OFF\n", mngr->name);
 
 	return rc;
 }
 
+static int dsi_link_lp_clk_stop(
+	struct mdss_dsi_link_lp_clk_info *link_lp_clks)
+{
+	struct dsi_link_clks *l_clks;
+	struct mdss_dsi_clk_mngr *mngr;
+
+	l_clks = container_of(link_lp_clks, struct dsi_link_clks, lp_clks);
+	mngr = container_of(l_clks, struct mdss_dsi_clk_mngr, link_clks);
+
+	clk_disable(l_clks->lp_clks.esc_clk);
+	clk_unprepare(l_clks->lp_clks.esc_clk);
+
+	pr_debug("%s: LINK LP CLOCK IS OFF\n", mngr->name);
+	return 0;
+}
+
+
 static int dsi_update_clk_state(struct dsi_core_clks *c_clks, u32 c_state,
 				struct dsi_link_clks *l_clks, u32 l_state)
 {
@@ -347,8 +403,8 @@
 	if (c_clks && (c_state == MDSS_DSI_CLK_ON)) {
 		if (c_clks->current_clk_state == MDSS_DSI_CLK_OFF) {
 			rc = mngr->pre_clkon_cb(mngr->priv_data,
-						MDSS_DSI_CORE_CLK,
-						MDSS_DSI_CLK_ON);
+				MDSS_DSI_CORE_CLK, MDSS_DSI_LINK_NONE,
+				MDSS_DSI_CLK_ON);
 			if (rc) {
 				pr_err("failed to turn on MDP FS rc= %d\n", rc);
 				goto error;
@@ -362,8 +418,8 @@
 
 		if (mngr->post_clkon_cb) {
 			rc = mngr->post_clkon_cb(mngr->priv_data,
-						 MDSS_DSI_CORE_CLK,
-						 MDSS_DSI_CLK_ON);
+				 MDSS_DSI_CORE_CLK, MDSS_DSI_LINK_NONE,
+				 MDSS_DSI_CLK_ON);
 			if (rc)
 				pr_err("post clk on cb failed, rc = %d\n", rc);
 		}
@@ -375,21 +431,50 @@
 		if (l_state == MDSS_DSI_CLK_ON) {
 			if (mngr->pre_clkon_cb) {
 				rc = mngr->pre_clkon_cb(mngr->priv_data,
-					MDSS_DSI_LINK_CLK, l_state);
+					MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_LP_CLK,
+					l_state);
 				if (rc)
-					pr_err("pre link clk on cb failed\n");
+					pr_err("pre link LP clk on cb failed\n");
 			}
-			rc = dsi_link_clk_start(l_clks);
+			rc = dsi_link_lp_clk_start(&l_clks->lp_clks);
 			if (rc) {
-				pr_err("failed to start link clk rc= %d\n", rc);
+				pr_err("failed to start LP link clk clk\n");
 				goto error;
 			}
 			if (mngr->post_clkon_cb) {
 				rc = mngr->post_clkon_cb(mngr->priv_data,
-							MDSS_DSI_LINK_CLK,
-							l_state);
+					MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_LP_CLK,
+					l_state);
 				if (rc)
-					pr_err("post link clk on cb failed\n");
+					pr_err("post LP clk on cb failed\n");
+			}
+
+			if (mngr->pre_clkon_cb) {
+				rc = mngr->pre_clkon_cb(mngr->priv_data,
+					MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_HS_CLK,
+					l_state);
+				if (rc)
+					pr_err("pre HS clk on cb failed\n");
+			}
+			rc = dsi_link_hs_clk_start(&l_clks->hs_clks,
+				(MDSS_DSI_LINK_CLK_SET_RATE |
+				MDSS_DSI_LINK_CLK_PREPARE));
+			if (rc) {
+				pr_err("failed to prepare HS clk rc= %d\n", rc);
+				goto error;
+			}
+			if (mngr->post_clkon_cb) {
+				rc = mngr->post_clkon_cb(mngr->priv_data,
+					MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_HS_CLK,
+					l_state);
+				if (rc)
+					pr_err("post HS clk on cb failed\n");
+			}
+			rc = dsi_link_hs_clk_start(&l_clks->hs_clks,
+				MDSS_DSI_LINK_CLK_ENABLE);
+			if (rc) {
+				pr_err("failed to enable HS clk rc= %d\n", rc);
+				goto error;
 			}
 		} else {
 			/*
@@ -418,9 +503,16 @@
 					goto error;
 				}
 
-				rc = dsi_link_clk_start(l_clks);
+				rc = dsi_link_lp_clk_start(&l_clks->lp_clks);
 				if (rc) {
-					pr_err("Link clks did not start\n");
+					pr_err("LP Link clks did not start\n");
+					goto error;
+				}
+
+				rc = dsi_link_hs_clk_start(&l_clks->hs_clks,
+						MDSS_DSI_LINK_CLK_START);
+				if (rc) {
+					pr_err("HS Link clks did not start\n");
 					goto error;
 				}
 				l_c_on = true;
@@ -429,24 +521,50 @@
 
 			if (mngr->pre_clkoff_cb) {
 				rc = mngr->pre_clkoff_cb(mngr->priv_data,
-					MDSS_DSI_LINK_CLK, l_state);
+					MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_HS_CLK,
+					l_state);
 				if (rc)
-					pr_err("pre link clk off cb failed\n");
+					pr_err("pre HS clk off cb failed\n");
 			}
 
-			rc = dsi_link_clk_stop(l_clks);
+			rc = dsi_link_hs_clk_stop(&l_clks->hs_clks);
 			if (rc) {
-				pr_err("failed to stop link clk, rc = %d\n",
+				pr_err("failed to stop HS clk, rc = %d\n",
 				       rc);
 				goto error;
 			}
 
 			if (mngr->post_clkoff_cb) {
 				rc = mngr->post_clkoff_cb(mngr->priv_data,
-					MDSS_DSI_LINK_CLK, l_state);
+					MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_HS_CLK,
+					l_state);
 				if (rc)
-					pr_err("post link clk off cb failed\n");
+					pr_err("post HS clk off cb failed\n");
 			}
+
+			if (mngr->pre_clkoff_cb) {
+				rc = mngr->pre_clkoff_cb(mngr->priv_data,
+					MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_LP_CLK,
+					l_state);
+				if (rc)
+					pr_err("pre LP clk off cb failed\n");
+			}
+
+			rc = dsi_link_lp_clk_stop(&l_clks->lp_clks);
+			if (rc) {
+				pr_err("failed to stop LP link clk, rc = %d\n",
+				       rc);
+				goto error;
+			}
+
+			if (mngr->post_clkoff_cb) {
+				rc = mngr->post_clkoff_cb(mngr->priv_data,
+					MDSS_DSI_LINK_CLK, MDSS_DSI_LINK_LP_CLK,
+					l_state);
+				if (rc)
+					pr_err("post LP clk off cb failed\n");
+			}
+
 			/*
 			 * This check is to save unnecessary clock state
 			 * change when going from EARLY_GATE to OFF. In the
@@ -502,8 +620,8 @@
 
 		if (mngr->pre_clkoff_cb) {
 			rc = mngr->pre_clkoff_cb(mngr->priv_data,
-						 MDSS_DSI_CORE_CLK,
-						 c_state);
+				 MDSS_DSI_CORE_CLK, MDSS_DSI_LINK_NONE,
+				 c_state);
 			if (rc)
 				pr_err("pre core clk off cb failed\n");
 		}
@@ -517,7 +635,7 @@
 		if (c_state == MDSS_DSI_CLK_OFF) {
 			if (mngr->post_clkoff_cb) {
 				rc = mngr->post_clkoff_cb(mngr->priv_data,
-						MDSS_DSI_CORE_CLK,
+					MDSS_DSI_CORE_CLK, MDSS_DSI_LINK_NONE,
 						MDSS_DSI_CLK_OFF);
 				if (rc)
 					pr_err("post clkoff cb fail, rc = %d\n",
@@ -610,27 +728,30 @@
 	MDSS_XLOG(clk, rate, flags);
 	switch (clk) {
 	case MDSS_DSI_LINK_ESC_CLK:
-		mngr->link_clks.esc_clk_rate = rate;
+		mngr->link_clks.lp_clks.esc_clk_rate = rate;
 		if (!flags) {
-			rc = clk_set_rate(mngr->link_clks.clks.esc_clk, rate);
+			rc = clk_set_rate(mngr->link_clks.lp_clks.esc_clk,
+				rate);
 			if (rc)
 				pr_err("set rate failed for esc clk rc=%d\n",
 				       rc);
 		}
 		break;
 	case MDSS_DSI_LINK_BYTE_CLK:
-		mngr->link_clks.byte_clk_rate = rate;
+		mngr->link_clks.hs_clks.byte_clk_rate = rate;
 		if (!flags) {
-			rc = clk_set_rate(mngr->link_clks.clks.byte_clk, rate);
+			rc = clk_set_rate(mngr->link_clks.hs_clks.byte_clk,
+				rate);
 			if (rc)
 				pr_err("set rate failed for byte clk rc=%d\n",
 				       rc);
 		}
 		break;
 	case MDSS_DSI_LINK_PIX_CLK:
-		mngr->link_clks.pix_clk_rate = rate;
+		mngr->link_clks.hs_clks.pix_clk_rate = rate;
 		if (!flags) {
-			rc = clk_set_rate(mngr->link_clks.clks.pixel_clk, rate);
+			rc = clk_set_rate(mngr->link_clks.hs_clks.pixel_clk,
+				rate);
 			if (rc)
 				pr_err("failed to set rate for pix clk rc=%d\n",
 				       rc);
@@ -888,8 +1009,10 @@
 	mutex_init(&mngr->clk_mutex);
 	memcpy(&mngr->core_clks.clks, &info->core_clks, sizeof(struct
 						 mdss_dsi_core_clk_info));
-	memcpy(&mngr->link_clks.clks, &info->link_clks, sizeof(struct
-						 mdss_dsi_link_clk_info));
+	memcpy(&mngr->link_clks.hs_clks, &info->link_hs_clks, sizeof(struct
+						 mdss_dsi_link_hs_clk_info));
+	memcpy(&mngr->link_clks.lp_clks, &info->link_lp_clks, sizeof(struct
+						 mdss_dsi_link_lp_clk_info));
 
 	INIT_LIST_HEAD(&mngr->client_list);
 	mngr->pre_clkon_cb = info->pre_clkon_cb;
@@ -981,15 +1104,26 @@
 	if ((clk & MDSS_DSI_LINK_CLK) &&
 	    (mngr->link_clks.current_clk_state == MDSS_DSI_CLK_ON)) {
 
-		rc = dsi_link_clk_stop(&mngr->link_clks);
+		rc = dsi_link_hs_clk_stop(&mngr->link_clks.hs_clks);
 		if (rc) {
-			pr_err("failed to stop link clks\n");
+			pr_err("failed to stop HS link clks\n");
 			goto error;
 		}
 
-		rc = dsi_link_clk_start(&mngr->link_clks);
+		rc = dsi_link_lp_clk_stop(&mngr->link_clks.lp_clks);
+		if (rc) {
+			pr_err("failed to stop LP link clks\n");
+			goto error;
+		}
+
+		rc = dsi_link_lp_clk_start(&mngr->link_clks.lp_clks);
 		if (rc)
-			pr_err("failed to start link clks\n");
+			pr_err("failed to start LP link clks\n");
+
+		rc = dsi_link_hs_clk_start(&mngr->link_clks.hs_clks,
+				MDSS_DSI_LINK_CLK_START);
+		if (rc)
+			pr_err("failed to start HS link clks\n");
 
 	} else if (clk & MDSS_DSI_LINK_CLK) {
 		pr_err("cannot reset, link clock is off\n");
diff --git a/drivers/video/fbdev/msm/mdss_dsi_clk.h b/drivers/video/fbdev/msm/mdss_dsi_clk.h
index 837f2f6..5f000f9 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_clk.h
+++ b/drivers/video/fbdev/msm/mdss_dsi_clk.h
@@ -39,6 +39,13 @@
 	MDSS_DSI_LINK_CLK_MAX,
 };
 
+enum mdss_dsi_link_clk_op_type {
+	MDSS_DSI_LINK_CLK_SET_RATE = BIT(0),
+	MDSS_DSI_LINK_CLK_PREPARE = BIT(1),
+	MDSS_DSI_LINK_CLK_ENABLE = BIT(2),
+	MDSS_DSI_LINK_CLK_START = BIT(0) | BIT(1) | BIT(2),
+};
+
 enum mdss_dsi_clk_type {
 	MDSS_DSI_CORE_CLK = BIT(0),
 	MDSS_DSI_LINK_CLK = BIT(1),
@@ -46,53 +53,67 @@
 	MDSS_DSI_CLKS_MAX = BIT(2),
 };
 
+enum mdss_dsi_lclk_type {
+	MDSS_DSI_LINK_NONE = 0,
+	MDSS_DSI_LINK_LP_CLK = BIT(0),
+	MDSS_DSI_LINK_HS_CLK = BIT(1),
+};
+
 /**
  * typedef *pre_clockoff_cb() - Callback before clock is turned off
  * @priv: private data pointer.
  * @clk_type: clock which is being turned off.
+ * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks.
  * @new_state: next state for the clock.
  *
  * @return: error code.
  */
 typedef int (*pre_clockoff_cb)(void *priv,
-			       enum mdss_dsi_clk_type clk_type,
-			       enum mdss_dsi_clk_state new_state);
+				enum mdss_dsi_clk_type clk_type,
+				enum mdss_dsi_lclk_type l_type,
+				enum mdss_dsi_clk_state new_state);
 
 /**
  * typedef *post_clockoff_cb() - Callback after clock is turned off
  * @priv: private data pointer.
  * @clk_type: clock which was turned off.
+ * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks.
  * @curr_state: current state for the clock.
  *
  * @return: error code.
  */
 typedef int (*post_clockoff_cb)(void *priv,
 				enum mdss_dsi_clk_type clk_type,
+				enum mdss_dsi_lclk_type l_type,
 				enum mdss_dsi_clk_state curr_state);
 
 /**
  * typedef *post_clockon_cb() - Callback after clock is turned on
  * @priv: private data pointer.
  * @clk_type: clock which was turned on.
+ * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks.
  * @curr_state: current state for the clock.
  *
  * @return: error code.
  */
 typedef int (*post_clockon_cb)(void *priv,
-			       enum mdss_dsi_clk_type clk_type,
-			       enum mdss_dsi_clk_state curr_state);
+				enum mdss_dsi_clk_type clk_type,
+				enum mdss_dsi_lclk_type l_type,
+				enum mdss_dsi_clk_state curr_state);
 
 /**
  * typedef *pre_clockon_cb() - Callback before clock is turned on
  * @priv: private data pointer.
  * @clk_type: clock which is being turned on.
+ * @l_type: specifies if the clock is HS or LP type. Valid only for link clocks.
  * @new_state: next state for the clock.
  *
  * @return: error code.
  */
 typedef int (*pre_clockon_cb)(void *priv,
-			      enum mdss_dsi_clk_type clk_type,
-			      enum mdss_dsi_clk_state new_state);
+				enum mdss_dsi_clk_type clk_type,
+				enum mdss_dsi_lclk_type l_type,
+				enum mdss_dsi_clk_state new_state);
 
 struct mdss_dsi_core_clk_info {
 	struct clk *mdp_core_clk;
@@ -101,10 +122,16 @@
 	struct clk *mmss_misc_ahb_clk;
 };
 
-struct mdss_dsi_link_clk_info {
-	struct clk *esc_clk;
+struct mdss_dsi_link_hs_clk_info {
 	struct clk *byte_clk;
 	struct clk *pixel_clk;
+	u32 byte_clk_rate;
+	u32 pix_clk_rate;
+};
+
+struct mdss_dsi_link_lp_clk_info {
+	struct clk *esc_clk;
+	u32 esc_clk_rate;
 };
 
 struct dsi_panel_clk_ctrl {
@@ -126,7 +153,8 @@
 struct mdss_dsi_clk_info {
 	char name[DSI_CLK_NAME_LEN];
 	struct mdss_dsi_core_clk_info core_clks;
-	struct mdss_dsi_link_clk_info link_clks;
+	struct mdss_dsi_link_hs_clk_info link_hs_clks;
+	struct mdss_dsi_link_lp_clk_info link_lp_clks;
 	pre_clockoff_cb pre_clkoff_cb;
 	post_clockoff_cb post_clkoff_cb;
 	post_clockon_cb post_clkon_cb;
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index 988c7a9..d76be70 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -303,6 +303,20 @@
 		 */
 		reg_val = MIPI_INP(ctrl->phy_io.base + 0x20c);
 		reg_val = reg_val >> 4;
+		if (!reg_val) {
+			/*
+			 * DSI_0_PHY_DSIPHY_REVISION_ID3 for 12nm PHY
+			 * reset value = 0x20
+			 * 7:4 Major
+			 * 3:0 Minor
+			 */
+			reg_val = MIPI_INP(ctrl->phy_io.base + 0x3dc);
+			reg_val = reg_val >> 4;
+			if (reg_val == 0x2) {
+				ctrl->shared_data->phy_rev = DSI_PHY_REV_12NM;
+				return;
+			}
+		}
 	}
 
 	if (reg_val == DSI_PHY_REV_20)
@@ -413,6 +427,9 @@
 	/* DSI_LAN_SWAP_CTRL */
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x00b0, ctrl_pdata->dlane_swap);
 
+	if (ctrl_pdata->shared_data->phy_rev == DSI_PHY_REV_12NM)
+		goto next;
+
 	/* clock out ctrl */
 	data = pinfo->t_clk_post & 0x3f;	/* 6 bits */
 	data <<= 8;
@@ -420,6 +437,7 @@
 	/* DSI_CLKOUT_TIMING_CTRL */
 	MIPI_OUTP((ctrl_pdata->ctrl_base) + 0xc4, data);
 
+next:
 	data = 0;
 	if (pinfo->rx_eot_ignore)
 		data |= BIT(4);
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 1cbaa44..2ef1695 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -2309,6 +2309,9 @@
 	for (i = 0; i < ARRAY_SIZE(pt->phy_timing_8996); i++)
 		pinfo->mipi.dsi_phy_db.timing_8996[i] = pt->phy_timing_8996[i];
 
+	for (i = 0; i < ARRAY_SIZE(pt->phy_timing_12nm); i++)
+		pinfo->mipi.dsi_phy_db.timing_12nm[i] = pt->phy_timing_12nm[i];
+
 	ctrl->on_cmds = pt->on_cmds;
 	ctrl->post_panel_on_cmds = pt->post_panel_on_cmds;
 
@@ -2421,6 +2424,18 @@
 			pt->phy_timing_8996[i] = data[i];
 		phy_timings_present = true;
 	}
+
+	data = of_get_property(np,
+		"qcom,mdss-dsi-panel-timings-phy-12nm", &len);
+	if ((!data) || (len != 8)) {
+		pr_debug("%s:%d, Unable to read 12nm Phy lane timing settings",
+		       __func__, __LINE__);
+	} else {
+		for (i = 0; i < len; i++)
+			pt->phy_timing_12nm[i] = data[i];
+		phy_timings_present = true;
+	}
+
 	if (!phy_timings_present) {
 		pr_err("%s: phy timing settings not present\n", __func__);
 		return -EINVAL;
diff --git a/drivers/video/fbdev/msm/mdss_dsi_phy.h b/drivers/video/fbdev/msm/mdss_dsi_phy.h
index aea42e8..108e26e 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_phy.h
+++ b/drivers/video/fbdev/msm/mdss_dsi_phy.h
@@ -16,11 +16,13 @@
 #include <linux/types.h>
 
 #include "mdss_panel.h"
+#include "mdss_dsi.h"
 
 enum phy_rev {
 	DSI_PHY_REV_UNKNOWN = 0x00,
 	DSI_PHY_REV_10 = 0x01,	/* REV 1.0 - 20nm, 28nm */
 	DSI_PHY_REV_20 = 0x02,	/* REV 2.0 - 14nm */
+	DSI_PHY_REV_12NM = 0x03, /* 12nm PHY */
 	DSI_PHY_REV_MAX,
 };
 
@@ -36,4 +38,53 @@
 int mdss_dsi_phy_calc_timing_param(struct mdss_panel_info *pinfo, u32 phy_rev,
 		u32 frate_hz);
 
+/*
+ * mdss_dsi_12nm_phy_regulator_enable() - enable lane reg for DSI 12nm PHY
+ *
+ * @ctrl: pointer to DSI controller structure
+ */
+int mdss_dsi_12nm_phy_regulator_enable(struct mdss_dsi_ctrl_pdata *ctrl);
+
+/*
+ * mdss_dsi_12nm_phy_regulator_disable() - disable lane reg for DSI 12nm PHY
+ *
+ * @ctrl: pointer to DSI controller structure
+ */
+int mdss_dsi_12nm_phy_regulator_disable(struct mdss_dsi_ctrl_pdata *ctrl);
+
+/*
+ * mdss_dsi_12nm_phy_config() - initialization sequence for DSI 12nm PHY
+ *
+ * @ctrl: pointer to DSI controller structure
+ *
+ * This function performs a sequence of register writes to initialize DSI
+ * 12nm phy. This function assumes that the DSI bus clocks are turned on.
+ * This function should only be called prior to enabling the DSI link clocks.
+ */
+int mdss_dsi_12nm_phy_config(struct mdss_dsi_ctrl_pdata *ctrl);
+
+/*
+ * mdss_dsi_12nm_phy_shutdown() - shutdown sequence for DSI 12nm PHY
+ *
+ * @ctrl: pointer to DSI controller structure
+ *
+ * Perform a sequence of register writes to completely shut down DSI 12nm PHY.
+ * This function assumes that the DSI bus clocks are turned on.
+ */
+int mdss_dsi_12nm_phy_shutdown(struct mdss_dsi_ctrl_pdata *ctrl);
+
+/*
+ * mdss_dsi_12nm_phy_hstx_drv_ctrl() - enable/disable HSTX drivers
+ *
+ * @ctrl: pointer to DSI controller structure
+ * @enable: boolean to specify enable/disable the HSTX drivers
+ *
+ * Perform a sequence of register writes to enable/disable HSTX drivers.
+ * This function assumes that the DSI bus clocks are turned on.
+ */
+
+void mdss_dsi_12nm_phy_hstx_drv_ctrl(
+	struct mdss_dsi_ctrl_pdata *ctrl, bool enable);
+
+
 #endif /* MDSS_DSI_PHY_H */
diff --git a/drivers/video/fbdev/msm/mdss_dsi_phy_12nm.c b/drivers/video/fbdev/msm/mdss_dsi_phy_12nm.c
new file mode 100644
index 0000000..9bd2c4d
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdss_dsi_phy_12nm.c
@@ -0,0 +1,127 @@
+/* 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/iopoll.h>
+#include "mdss_dsi_phy.h"
+
+#define T_TA_GO_TIM_COUNT                    0x014
+#define T_TA_SURE_TIM_COUNT                  0x018
+#define HSTX_DRIV_INDATA_CTRL_CLKLANE        0x0c0
+#define HSTX_DATAREV_CTRL_CLKLANE            0x0d4
+#define HSTX_DRIV_INDATA_CTRL_LANE0          0x100
+#define HSTX_READY_DLY_DATA_REV_CTRL_LANE0   0x114
+#define HSTX_DRIV_INDATA_CTRL_LANE1          0x140
+#define HSTX_READY_DLY_DATA_REV_CTRL_LANE1   0x154
+#define HSTX_CLKLANE_REQSTATE_TIM_CTRL       0x180
+#define HSTX_CLKLANE_HS0STATE_TIM_CTRL       0x188
+#define HSTX_CLKLANE_TRALSTATE_TIM_CTRL      0x18c
+#define HSTX_CLKLANE_EXITSTATE_TIM_CTRL      0x190
+#define HSTX_CLKLANE_CLKPOSTSTATE_TIM_CTRL   0x194
+#define HSTX_DATALANE_REQSTATE_TIM_CTRL      0x1c0
+#define HSTX_DATALANE_HS0STATE_TIM_CTRL      0x1c8
+#define HSTX_DATALANE_TRAILSTATE_TIM_CTRL    0x1cc
+#define HSTX_DATALANE_EXITSTATE_TIM_CTRL     0x1d0
+#define HSTX_DRIV_INDATA_CTRL_LANE2          0x200
+#define HSTX_READY_DLY_DATA_REV_CTRL_LANE2   0x214
+#define HSTX_READY_DLY_DATA_REV_CTRL_LANE3   0x254
+#define HSTX_DRIV_INDATA_CTRL_LANE3          0x240
+#define CTRL0                                0x3e8
+#define SYS_CTRL                             0x3f0
+#define REQ_DLY                              0x3fc
+
+#define DSI_PHY_W32(b, off, val) MIPI_OUTP((b) + (off), (val))
+#define DSI_PHY_R32(b, off) MIPI_INP((b) + (off))
+
+int mdss_dsi_12nm_phy_regulator_enable(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	/* Nothing to be done for 12nm PHY */
+	return 0;
+}
+
+int mdss_dsi_12nm_phy_regulator_disable(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	/* Nothing to be done for 12nm PHY */
+	return 0;
+}
+
+int mdss_dsi_12nm_phy_config(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	struct mdss_dsi_phy_ctrl *pd =
+		&(((ctrl->panel_data).panel_info.mipi).dsi_phy_db);
+
+	/* CTRL0: CFG_CLK_EN */
+	DSI_PHY_W32(ctrl->phy_io.base, CTRL0, BIT(0));
+
+	/* DSI PHY clock lane timings */
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_CLKLANE_HS0STATE_TIM_CTRL,
+		(pd->timing_12nm[0] | BIT(7)));
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_CLKLANE_TRALSTATE_TIM_CTRL,
+		(pd->timing_12nm[1] | BIT(6)));
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_CLKLANE_CLKPOSTSTATE_TIM_CTRL,
+		(pd->timing_12nm[2] | BIT(6)));
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_CLKLANE_REQSTATE_TIM_CTRL,
+		pd->timing_12nm[3]);
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_CLKLANE_EXITSTATE_TIM_CTRL,
+		(pd->timing_12nm[7] | BIT(6) | BIT(7)));
+
+	/* DSI PHY data lane timings */
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_DATALANE_HS0STATE_TIM_CTRL,
+		(pd->timing_12nm[4] | BIT(7)));
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_DATALANE_TRAILSTATE_TIM_CTRL,
+		(pd->timing_12nm[5] | BIT(6)));
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_DATALANE_REQSTATE_TIM_CTRL,
+		pd->timing_12nm[6]);
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_DATALANE_EXITSTATE_TIM_CTRL,
+		(pd->timing_12nm[7] | BIT(6) | BIT(7)));
+
+	DSI_PHY_W32(ctrl->phy_io.base, T_TA_GO_TIM_COUNT, 0x03);
+	DSI_PHY_W32(ctrl->phy_io.base, T_TA_SURE_TIM_COUNT, 0x01);
+	DSI_PHY_W32(ctrl->phy_io.base, REQ_DLY, 0x85);
+
+	/* DSI lane control registers */
+	DSI_PHY_W32(ctrl->phy_io.base,
+	HSTX_READY_DLY_DATA_REV_CTRL_LANE0, 0x00);
+	DSI_PHY_W32(ctrl->phy_io.base,
+		HSTX_READY_DLY_DATA_REV_CTRL_LANE1, 0x00);
+	DSI_PHY_W32(ctrl->phy_io.base,
+		HSTX_READY_DLY_DATA_REV_CTRL_LANE2, 0x00);
+	DSI_PHY_W32(ctrl->phy_io.base,
+		HSTX_READY_DLY_DATA_REV_CTRL_LANE3, 0x00);
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_DATAREV_CTRL_CLKLANE, 0x00);
+	wmb(); /* make sure DSI PHY registers are programmed */
+
+	return 0;
+}
+
+int mdss_dsi_12nm_phy_shutdown(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+	DSI_PHY_W32(ctrl->phy_io.base, SYS_CTRL, BIT(0) | BIT(3));
+	wmb(); /* make sure DSI PHY is disabled */
+	return 0;
+}
+
+void mdss_dsi_12nm_phy_hstx_drv_ctrl(
+	struct mdss_dsi_ctrl_pdata *ctrl, bool enable)
+{
+	u32 data = 0;
+
+	if (enable)
+		data = BIT(2) | BIT(3);
+
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_DRIV_INDATA_CTRL_CLKLANE, data);
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_DRIV_INDATA_CTRL_LANE0, data);
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_DRIV_INDATA_CTRL_LANE1, data);
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_DRIV_INDATA_CTRL_LANE2, data);
+	DSI_PHY_W32(ctrl->phy_io.base, HSTX_DRIV_INDATA_CTRL_LANE3, data);
+	wmb(); /* make sure DSI PHY registers are programmed */
+}
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c
index 13a4bb6..d07650b 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -2098,10 +2098,9 @@
 			devm_kzalloc(&mdata->pdev->dev, sizeof(u32) *
 					mdata->scaler_off->ndest_scalers,
 					GFP_KERNEL);
-		if  (!mdata->scaler_off->dest_scaler_off) {
-			kfree(mdata->scaler_off->dest_scaler_off);
+		if  (!mdata->scaler_off->dest_scaler_off)
 			return -ENOMEM;
-		}
+
 		ret = mdss_mdp_parse_dt_handler(mdata->pdev,
 				"qcom,mdss-dest-scaler-off",
 				mdata->scaler_off->dest_scaler_off,
@@ -2112,10 +2111,9 @@
 			devm_kzalloc(&mdata->pdev->dev, sizeof(u32) *
 					mdata->scaler_off->ndest_scalers,
 					GFP_KERNEL);
-		if  (!mdata->scaler_off->dest_scaler_lut_off) {
-			kfree(mdata->scaler_off->dest_scaler_lut_off);
+		if  (!mdata->scaler_off->dest_scaler_lut_off)
 			return -ENOMEM;
-		}
+
 		ret = mdss_mdp_parse_dt_handler(mdata->pdev,
 				"qcom,mdss-dest-scalers-lut-off",
 				mdata->scaler_off->dest_scaler_lut_off,
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index 53db752..a3f9349 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -308,6 +308,7 @@
 	bool reg_ldo_mode;
 
 	char timing_8996[40];/* 8996, 8 * 5 */
+	char timing_12nm[14]; /* 12nm PHY */
 	char regulator_len;
 	char strength_len;
 	char lanecfg_len;
diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c
index fbbdaf2..2d8b5d5 100644
--- a/drivers/video/fbdev/msm/mdss_smmu.c
+++ b/drivers/video/fbdev/msm/mdss_smmu.c
@@ -25,6 +25,7 @@
 #include <linux/dma-buf.h>
 #include <linux/of_platform.h>
 #include <linux/msm_dma_iommu_mapping.h>
+#include <linux/vmalloc.h>
 
 #include <asm/dma-iommu.h>
 #include "soc/qcom/secure_buffer.h"
@@ -522,7 +523,7 @@
  *   either sides of sgl.
  *
  * Returns:
- *   Pointer to new kmalloced sg list, ERR_PTR() on error
+ *   Pointer to new vmalloced sg list, ERR_PTR() on error
  *
  */
 static struct scatterlist *sg_clone(struct scatterlist *orig_sgl, u64 len,
@@ -538,7 +539,7 @@
 	if (padding)
 		nents += 2;
 
-	head = kmalloc_array(nents, sizeof(struct scatterlist), gfp_mask);
+	head = vmalloc(nents * sizeof(struct scatterlist));
 	if (!head)
 		return ERR_PTR(-ENOMEM);
 
diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
index ec1ee60..f0e46f7 100644
--- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c
+++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
@@ -519,7 +519,8 @@
 	 * is only done from the clock master. This will ensure that the PLL is
 	 * off when PHY reset is called.
 	 */
-	if (mdss_dsi_is_ctrl_clk_slave(ctrl))
+	if (mdss_dsi_is_ctrl_clk_slave(ctrl) ||
+		(ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM))
 		return;
 
 	mdss_dsi_phy_sw_reset_sub(ctrl);
@@ -561,6 +562,9 @@
 	if (ctrl->shared_data->phy_rev == DSI_PHY_REV_20)
 		return;
 
+	if (ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM)
+		return;
+
 	MIPI_OUTP(ctrl->phy_regulator_io.base + 0x018, 0x000);
 }
 
@@ -575,6 +579,8 @@
 		MIPI_OUTP(ctrl->phy_io.base + DSIPHY_PLL_CLKBUFLR_EN, 0);
 		MIPI_OUTP(ctrl->phy_io.base + DSIPHY_CMN_GLBL_TEST_CTRL, 0);
 		MIPI_OUTP(ctrl->phy_io.base + DSIPHY_CMN_CTRL_0, 0);
+	} else if (ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM) {
+		mdss_dsi_12nm_phy_shutdown(ctrl);
 	} else {
 		MIPI_OUTP(ctrl->phy_io.base + MDSS_DSI_DSIPHY_CTRL_0, 0x000);
 	}
@@ -596,7 +602,8 @@
 		return;
 	}
 
-	if (ctrl->shared_data->phy_rev == DSI_PHY_REV_20)
+	if ((ctrl->shared_data->phy_rev == DSI_PHY_REV_20) ||
+		(ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM))
 		return;
 
 	pd = &(((ctrl->panel_data).panel_info.mipi).dsi_phy_db);
@@ -1144,6 +1151,8 @@
 	if (enable) {
 		if (ctrl->shared_data->phy_rev == DSI_PHY_REV_20) {
 			mdss_dsi_8996_phy_regulator_enable(ctrl);
+		} else if (ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM) {
+			mdss_dsi_12nm_phy_regulator_enable(ctrl);
 		} else {
 			switch (ctrl->shared_data->hw_rev) {
 			case MDSS_DSI_HW_REV_103:
@@ -1194,6 +1203,8 @@
 
 		if (ctrl->shared_data->phy_rev == DSI_PHY_REV_20) {
 			mdss_dsi_8996_phy_config(ctrl);
+		} else if (ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM) {
+			mdss_dsi_12nm_phy_config(ctrl);
 		} else {
 			switch (ctrl->shared_data->hw_rev) {
 			case MDSS_DSI_HW_REV_103:
@@ -1269,6 +1280,13 @@
 	}
 }
 
+static void mdss_dsi_phy_hstx_drv_ctrl(
+	struct mdss_dsi_ctrl_pdata *ctrl, bool enable)
+{
+	if (ctrl->shared_data->phy_rev == DSI_PHY_REV_12NM)
+		mdss_dsi_12nm_phy_hstx_drv_ctrl(ctrl, enable);
+}
+
 void mdss_dsi_core_clk_deinit(struct device *dev, struct dsi_shared_data *sdata)
 {
 	if (sdata->mmss_misc_ahb_clk)
@@ -1688,7 +1706,7 @@
 }
 
 static bool mdss_dsi_is_ulps_req_valid(struct mdss_dsi_ctrl_pdata *ctrl,
-		int enable)
+		int enable, bool reconfig)
 {
 	struct mdss_dsi_ctrl_pdata *octrl = NULL;
 	struct mdss_panel_data *pdata = &ctrl->panel_data;
@@ -1719,11 +1737,11 @@
 	 * However, this should be allowed in following usecases:
 	 *   1. If ULPS during suspend feature is enabled, where we
 	 *      configure the lanes in ULPS after turning off the panel.
-	 *   2. When coming out of idle PC with clamps enabled, where we
-	 *      transition the controller HW state back to ULPS prior to
+	 *   2. When coming out of idle PC with ULPS enabled, where we need to
+	 *      reconfigure the controller HW state again to ULPS prior to
 	 *      disabling ULPS.
 	 */
-	if (enable && !ctrl->mmss_clamp &&
+	if (enable && !reconfig &&
 		!(ctrl->ctrl_state & CTRL_STATE_PANEL_INIT) &&
 		!pdata->panel_info.ulps_suspend_enabled) {
 		pr_debug("%s: panel not yet initialized\n", __func__);
@@ -1752,13 +1770,14 @@
  * mdss_dsi_ulps_config() - Program DSI lanes to enter/exit ULPS mode
  * @ctrl: pointer to DSI controller structure
  * @enable: 1 to enter ULPS, 0 to exit ULPS
+ * @reconfig: boolean to specify if DSI controller is reconfigured to enter ULPS
  *
  * This function executes the necessary programming sequence to enter/exit
  * DSI Ultra-Low Power State (ULPS). This function assumes that the link and
  * core clocks are already on.
  */
 static int mdss_dsi_ulps_config(struct mdss_dsi_ctrl_pdata *ctrl,
-	int enable)
+	int enable, bool reconfig)
 {
 	int ret = 0;
 	struct mdss_panel_data *pdata = NULL;
@@ -1780,7 +1799,7 @@
 	pinfo = &pdata->panel_info;
 	mipi = &pinfo->mipi;
 
-	if (!mdss_dsi_is_ulps_req_valid(ctrl, enable)) {
+	if (!mdss_dsi_is_ulps_req_valid(ctrl, enable, reconfig)) {
 		pr_debug("%s: skiping ULPS config for ctrl%d, enable=%d\n",
 			__func__, ctrl->ndx, enable);
 		return 0;
@@ -1801,9 +1820,9 @@
 	if (mipi->data_lane3)
 		active_lanes |= BIT(3);
 
-	pr_debug("%s: configuring ulps (%s) for ctrl%d, active lanes=0x%08x,clamps=%s\n",
+	pr_debug("%s: configuring ulps (%s) for ctrl%d, active lanes=0x%08x,reconfig=%s\n",
 		__func__, (enable ? "on" : "off"), ctrl->ndx,
-		active_lanes, ctrl->mmss_clamp ? "enabled" : "disabled");
+		active_lanes, reconfig ? "true" : "false");
 
 	if (enable && !ctrl->ulps) {
 		/*
@@ -1816,7 +1835,7 @@
 		 * power collapse and just restoring the controller state to
 		 * ULPS with the clamps still in place.
 		 */
-		if (!ctrl->mmss_clamp) {
+		if (!reconfig) {
 			ret = mdss_dsi_wait_for_lane_idle(ctrl);
 			if (ret) {
 				pr_warn("%s: lanes not idle, skip ulps\n",
@@ -2165,6 +2184,7 @@
 
 int mdss_dsi_pre_clkoff_cb(void *priv,
 			   enum mdss_dsi_clk_type clk,
+			   enum mdss_dsi_lclk_type l_type,
 			   enum mdss_dsi_clk_state new_state)
 {
 	int rc = 0;
@@ -2173,7 +2193,14 @@
 
 	pdata = &ctrl->panel_data;
 
-	if ((clk & MDSS_DSI_LINK_CLK) && (new_state == MDSS_DSI_CLK_OFF)) {
+	if ((clk & MDSS_DSI_LINK_CLK) && (l_type == MDSS_DSI_LINK_HS_CLK) &&
+		(new_state == MDSS_DSI_CLK_OFF)) {
+		/* Disable HS TX driver in DSI PHY if applicable */
+		mdss_dsi_phy_hstx_drv_ctrl(ctrl, false);
+	}
+
+	if ((clk & MDSS_DSI_LINK_CLK) && (l_type == MDSS_DSI_LINK_LP_CLK) &&
+		(new_state == MDSS_DSI_CLK_OFF)) {
 		/*
 		 * If ULPS feature is enabled, enter ULPS first.
 		 * However, when blanking the panel, we should enter ULPS
@@ -2181,9 +2208,9 @@
 		 */
 		if (!(ctrl->ctrl_state & CTRL_STATE_PANEL_INIT)) {
 			if (pdata->panel_info.ulps_suspend_enabled)
-				mdss_dsi_ulps_config(ctrl, 1);
+				mdss_dsi_ulps_config(ctrl, 1, false);
 		} else if (mdss_dsi_ulps_feature_enabled(pdata)) {
-			rc = mdss_dsi_ulps_config(ctrl, 1);
+			rc = mdss_dsi_ulps_config(ctrl, 1, false);
 		}
 		if (rc) {
 			pr_err("%s: failed enable ulps, rc = %d\n",
@@ -2208,7 +2235,7 @@
 			 * Make sure that controller is not in ULPS state when
 			 * the DSI link is not active.
 			 */
-			rc = mdss_dsi_ulps_config(ctrl, 0);
+			rc = mdss_dsi_ulps_config(ctrl, 0, false);
 			if (rc)
 				pr_err("%s: failed to disable ulps. rc=%d\n",
 					__func__, rc);
@@ -2220,6 +2247,7 @@
 
 int mdss_dsi_post_clkon_cb(void *priv,
 			   enum mdss_dsi_clk_type clk,
+			   enum mdss_dsi_lclk_type l_type,
 			   enum mdss_dsi_clk_state curr_state)
 {
 	int rc = 0;
@@ -2238,6 +2266,21 @@
 		if (mmss_clamp)
 			mdss_dsi_ctrl_setup(ctrl);
 
+		rc = mdss_dsi_clamp_ctrl(ctrl, 0);
+		if (rc) {
+			pr_err("%s: Failed to disable dsi clamps. rc=%d\n",
+				__func__, rc);
+			goto error;
+		}
+
+		/*
+		 * Phy setup is needed if coming out of idle
+		 * power collapse with clamps enabled.
+		 */
+		if (ctrl->phy_power_off || mmss_clamp)
+			mdss_dsi_phy_power_on(ctrl, mmss_clamp);
+	}
+	if ((clk & MDSS_DSI_LINK_CLK) && (l_type == MDSS_DSI_LINK_HS_CLK)) {
 		if (ctrl->ulps) {
 			/*
 			 * ULPS Entry Request. This is needed if the lanes were
@@ -2254,37 +2297,22 @@
 			 * ULPS.
 			 */
 			ctrl->ulps = false;
-			rc = mdss_dsi_ulps_config(ctrl, 1);
+			rc = mdss_dsi_ulps_config(ctrl, 1, true);
 			if (rc) {
 				pr_err("%s: Failed to enter ULPS. rc=%d\n",
 					__func__, rc);
 				goto error;
 			}
-		}
 
-		rc = mdss_dsi_clamp_ctrl(ctrl, 0);
-		if (rc) {
-			pr_err("%s: Failed to disable dsi clamps. rc=%d\n",
-				__func__, rc);
-			goto error;
-		}
-
-		/*
-		 * Phy setup is needed if coming out of idle
-		 * power collapse with clamps enabled.
-		 */
-		if (ctrl->phy_power_off || mmss_clamp)
-			mdss_dsi_phy_power_on(ctrl, mmss_clamp);
-	}
-	if (clk & MDSS_DSI_LINK_CLK) {
-		if (ctrl->ulps) {
-			rc = mdss_dsi_ulps_config(ctrl, 0);
+			rc = mdss_dsi_ulps_config(ctrl, 0, false);
 			if (rc) {
 				pr_err("%s: failed to disable ulps, rc= %d\n",
 				       __func__, rc);
 				goto error;
 			}
 		}
+		/* Enable HS TX driver in DSI PHY if applicable */
+		mdss_dsi_phy_hstx_drv_ctrl(ctrl, true);
 	}
 error:
 	return rc;
@@ -2292,6 +2320,7 @@
 
 int mdss_dsi_post_clkoff_cb(void *priv,
 			    enum mdss_dsi_clk_type clk_type,
+			    enum mdss_dsi_lclk_type l_type,
 			    enum mdss_dsi_clk_state curr_state)
 {
 	int rc = 0;
@@ -2342,6 +2371,7 @@
 
 int mdss_dsi_pre_clkon_cb(void *priv,
 			  enum mdss_dsi_clk_type clk_type,
+			  enum mdss_dsi_lclk_type l_type,
 			  enum mdss_dsi_clk_state new_state)
 {
 	int rc = 0;
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 1692c26..78b763c 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -1456,7 +1456,7 @@
 	while (toread > 0) {
 		tocopy = min_t(unsigned long, sb->s_blocksize - offset, toread);
 repeat:
-		page = read_mapping_page(mapping, blkidx, NULL);
+		page = read_cache_page_gfp(mapping, blkidx, GFP_NOFS);
 		if (IS_ERR(page)) {
 			if (PTR_ERR(page) == -ENOMEM) {
 				congestion_wait(BLK_RW_ASYNC, HZ/50);
diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h
index 610466a..826afb5 100644
--- a/fs/sdcardfs/sdcardfs.h
+++ b/fs/sdcardfs/sdcardfs.h
@@ -669,7 +669,7 @@
 
 static inline bool qstr_case_eq(const struct qstr *q1, const struct qstr *q2)
 {
-	return q1->len == q2->len && str_case_eq(q1->name, q2->name);
+	return q1->len == q2->len && str_n_case_eq(q1->name, q2->name, q2->len);
 }
 
 #define QSTR_LITERAL(string) QSTR_INIT(string, sizeof(string)-1)
diff --git a/include/crypto/ice.h b/include/crypto/ice.h
index 558d136..b02a440 100644
--- a/include/crypto/ice.h
+++ b/include/crypto/ice.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
@@ -53,6 +53,8 @@
 
 struct qcom_ice_variant_ops *qcom_ice_get_variant_ops(struct device_node *node);
 struct platform_device *qcom_ice_get_pdevice(struct device_node *node);
+void qcom_ice_set_fde_flag(int flag);
+int qcom_ice_set_fde_conf(sector_t strt, sector_t size, int idx, int mode);
 
 #ifdef CONFIG_CRYPTO_DEV_QCOM_ICE
 int qcom_ice_setup_ice_hw(const char *storage_type, int enable);
diff --git a/include/dt-bindings/clock/msm-clocks-8952.h b/include/dt-bindings/clock/msm-clocks-8952.h
index 4547751..3190d4f 100644
--- a/include/dt-bindings/clock/msm-clocks-8952.h
+++ b/include/dt-bindings/clock/msm-clocks-8952.h
@@ -235,6 +235,11 @@
 #define clk_ext_pclk0_clk_src			0x087c1612
 #define clk_ext_byte0_clk_src			0xfb32f31e
 
+#define clk_dsi0pll_byte_clk_src		0xbbaa30be
+#define clk_dsi0pll_pixel_clk_src		0x45b3260f
+#define clk_dsi1pll_byte_clk_src		0x63930a8f
+#define clk_dsi1pll_pixel_clk_src		0x0e4c9b56
+
 #define clk_dsi_pll0_byte_clk_src		0x44539836
 #define clk_dsi_pll0_pixel_clk_src		0x5767c287
 #define clk_dsi_pll1_byte_clk_src		0x73e88d02
diff --git a/include/dt-bindings/clock/msm-clocks-hwio-8952.h b/include/dt-bindings/clock/msm-clocks-hwio-8952.h
index 888c2c7..cba5a86 100644
--- a/include/dt-bindings/clock/msm-clocks-hwio-8952.h
+++ b/include/dt-bindings/clock/msm-clocks-hwio-8952.h
@@ -432,6 +432,32 @@
 	VDD_HF_PLL_NUM_8917,
 };
 
+enum vdd_sr2_pll_levels_439 {
+	VDD_SR2_PLL_OFF_439,
+	VDD_SR2_PLL_SVS_439,
+	VDD_SR2_PLL_NOM_439,
+	VDD_SR2_PLL_TUR_439,
+	VDD_SR2_PLL_NUM_439,
+};
+
+enum vdd_dig_levels_439 {
+	VDD_DIG_NONE_439,
+	VDD_DIG_LOWER_439,
+	VDD_DIG_LOW_439,
+	VDD_DIG_NOMINAL_439,
+	VDD_DIG_NOM_PLUS_439,
+	VDD_DIG_HIGH_439,
+	VDD_DIG_NUM_439
+};
+
+enum vdd_hf_pll_levels_439 {
+	VDD_HF_PLL_OFF_439,
+	VDD_HF_PLL_SVS_439,
+	VDD_HF_PLL_NOM_439,
+	VDD_HF_PLL_TUR_439,
+	VDD_HF_PLL_NUM_439,
+};
+
 static int vdd_corner[] = {
 	RPM_REGULATOR_LEVEL_NONE,		/* VDD_DIG_NONE */
 	RPM_REGULATOR_LEVEL_SVS,		/* VDD_DIG_SVS */
diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index 8e849a6..eb84ce6 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -167,6 +167,7 @@
 	struct list_head node;
 
 	struct mutex lock;
+	struct mutex sysfs_lock;
 	struct device dev;
 	struct devfreq_dev_profile *profile;
 	const struct devfreq_governor *governor;
diff --git a/include/linux/dma-mapping-fast.h b/include/linux/dma-mapping-fast.h
index e9dabab..e370b43 100644
--- a/include/linux/dma-mapping-fast.h
+++ b/include/linux/dma-mapping-fast.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,6 +27,7 @@
 
 	u32		min_iova_align;
 	struct page	*guard_page;
+	u32		force_guard_page_len;
 
 	unsigned int	bitmap_size;
 	unsigned long	*bitmap;
diff --git a/include/linux/input/ft5x06_ts.h b/include/linux/input/ft5x06_ts.h
new file mode 100644
index 0000000..2310989
--- /dev/null
+++ b/include/linux/input/ft5x06_ts.h
@@ -0,0 +1,77 @@
+/*
+ *
+ * FocalTech ft5x06 TouchScreen driver header file.
+ *
+ * Copyright (c) 2010  Focal tech Ltd.
+ * Copyright (c) 2012-2015, 2018 The Linux Foundation. All rights reserved.
+ *
+ * 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.
+ *
+ */
+#ifndef __LINUX_FT5X06_TS_H__
+#define __LINUX_FT5X06_TS_H__
+
+#define FT5X06_ID		0x55
+#define FT5X16_ID		0x0A
+#define FT5X36_ID		0x14
+#define FT6X06_ID		0x06
+#define FT6X36_ID       0x36
+
+struct fw_upgrade_info {
+	bool auto_cal;
+	u16 delay_aa;
+	u16 delay_55;
+	u8 upgrade_id_1;
+	u8 upgrade_id_2;
+	u16 delay_readid;
+	u16 delay_erase_flash;
+};
+
+struct ft5x06_gesture_platform_data {
+	int gesture_enable_to_set;	/* enable/disable gesture */
+	int in_pocket;	/* whether in pocket mode or not */
+	struct device *dev;
+	struct class *gesture_class;
+	struct ft5x06_ts_data *data;
+};
+
+struct ft5x06_ts_platform_data {
+	struct fw_upgrade_info info;
+	const char *name;
+	const char *fw_name;
+	u32 irqflags;
+	u32 irq_gpio;
+	u32 irq_gpio_flags;
+	u32 reset_gpio;
+	u32 reset_gpio_flags;
+	u32 family_id;
+	u32 x_max;
+	u32 y_max;
+	u32 x_min;
+	u32 y_min;
+	u32 panel_minx;
+	u32 panel_miny;
+	u32 panel_maxx;
+	u32 panel_maxy;
+	u32 group_id;
+	u32 hard_rst_dly;
+	u32 soft_rst_dly;
+	u32 num_max_touches;
+	bool fw_vkey_support;
+	bool no_force_update;
+	bool i2c_pull_up;
+	bool ignore_id_check;
+	bool gesture_support;
+	bool resume_in_workqueue;
+	int (*power_init)(bool);
+	int (*power_on)(bool);
+};
+
+#endif
diff --git a/include/linux/input/gen_vkeys.h b/include/linux/input/gen_vkeys.h
new file mode 100644
index 0000000..b152147
--- /dev/null
+++ b/include/linux/input/gen_vkeys.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2013, 2018 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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 __GEN_VKEYS_
+struct vkeys_platform_data {
+	const char *name;
+	int disp_maxx;
+	int disp_maxy;
+	int panel_maxx;
+	int panel_maxy;
+	int *keycodes;
+	int num_keys;
+	int y_offset;
+};
+#endif
diff --git a/include/linux/input/synaptics_dsx_v2_6.h b/include/linux/input/synaptics_dsx_v2_6.h
index 52241e5..5cd26bb 100644
--- a/include/linux/input/synaptics_dsx_v2_6.h
+++ b/include/linux/input/synaptics_dsx_v2_6.h
@@ -87,6 +87,7 @@
 	bool y_flip;
 	bool swap_axes;
 	bool resume_in_workqueue;
+	bool wakeup_gesture_en;
 	int irq_gpio;
 	int irq_on_state;
 	int power_gpio;
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index f25acfc..acbc605 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -148,6 +148,7 @@
 	DOMAIN_ATTR_CB_STALL_DISABLE,
 	DOMAIN_ATTR_UPSTREAM_IOVA_ALLOCATOR,
 	DOMAIN_ATTR_MMU500_ERRATA_MIN_ALIGN,
+	DOMAIN_ATTR_FORCE_IOVA_GUARD_PAGE,
 	DOMAIN_ATTR_MAX,
 };
 
diff --git a/include/linux/ipa.h b/include/linux/ipa.h
index 4951e0b..f966e0c 100644
--- a/include/linux/ipa.h
+++ b/include/linux/ipa.h
@@ -1275,11 +1275,13 @@
  */
 int ipa_add_hdr(struct ipa_ioc_add_hdr *hdrs);
 
+int ipa_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs, bool user_only);
+
 int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls);
 
 int ipa_commit_hdr(void);
 
-int ipa_reset_hdr(void);
+int ipa_reset_hdr(bool user_only);
 
 int ipa_get_hdr(struct ipa_ioc_get_hdr *lookup);
 
@@ -1290,7 +1292,8 @@
 /*
  * Header Processing Context
  */
-int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs);
+int ipa_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs,
+							bool user_only);
 
 int ipa_del_hdr_proc_ctx(struct ipa_ioc_del_hdr_proc_ctx *hdls);
 
@@ -1299,11 +1302,13 @@
  */
 int ipa_add_rt_rule(struct ipa_ioc_add_rt_rule *rules);
 
+int ipa_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules, bool user_only);
+
 int ipa_del_rt_rule(struct ipa_ioc_del_rt_rule *hdls);
 
 int ipa_commit_rt(enum ipa_ip_type ip);
 
-int ipa_reset_rt(enum ipa_ip_type ip);
+int ipa_reset_rt(enum ipa_ip_type ip, bool user_only);
 
 int ipa_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup);
 
@@ -1318,13 +1323,15 @@
  */
 int ipa_add_flt_rule(struct ipa_ioc_add_flt_rule *rules);
 
+int ipa_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules, bool user_only);
+
 int ipa_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls);
 
 int ipa_mdfy_flt_rule(struct ipa_ioc_mdfy_flt_rule *rules);
 
 int ipa_commit_flt(enum ipa_ip_type ip);
 
-int ipa_reset_flt(enum ipa_ip_type ip);
+int ipa_reset_flt(enum ipa_ip_type ip, bool user_only);
 
 /*
  * NAT\IPv6CT
@@ -1739,6 +1746,12 @@
 	return -EPERM;
 }
 
+static inline int ipa_add_hdr_usr(struct ipa_ioc_add_hdr *hdrs,
+				bool user_only)
+{
+	return -EPERM;
+}
+
 static inline int ipa_del_hdr(struct ipa_ioc_del_hdr *hdls)
 {
 	return -EPERM;
@@ -1749,7 +1762,7 @@
 	return -EPERM;
 }
 
-static inline int ipa_reset_hdr(void)
+static inline int ipa_reset_hdr(bool user_only)
 {
 	return -EPERM;
 }
@@ -1773,7 +1786,8 @@
  * Header Processing Context
  */
 static inline int ipa_add_hdr_proc_ctx(
-				struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs)
+				struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs,
+				bool user_only)
 {
 	return -EPERM;
 }
@@ -1790,6 +1804,12 @@
 	return -EPERM;
 }
 
+static inline int ipa_add_rt_rule_usr(struct ipa_ioc_add_rt_rule *rules,
+					bool user_only)
+{
+	return -EPERM;
+}
+
 static inline int ipa_del_rt_rule(struct ipa_ioc_del_rt_rule *hdls)
 {
 	return -EPERM;
@@ -1800,7 +1820,7 @@
 	return -EPERM;
 }
 
-static inline int ipa_reset_rt(enum ipa_ip_type ip)
+static inline int ipa_reset_rt(enum ipa_ip_type ip, bool user_only)
 {
 	return -EPERM;
 }
@@ -1833,6 +1853,12 @@
 	return -EPERM;
 }
 
+static inline int ipa_add_flt_rule_usr(struct ipa_ioc_add_flt_rule *rules,
+					bool user_only)
+{
+	return -EPERM;
+}
+
 static inline int ipa_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls)
 {
 	return -EPERM;
@@ -1848,7 +1874,7 @@
 	return -EPERM;
 }
 
-static inline int ipa_reset_flt(enum ipa_ip_type ip)
+static inline int ipa_reset_flt(enum ipa_ip_type ip, bool user_only)
 {
 	return -EPERM;
 }
diff --git a/include/linux/ipa_uc_offload.h b/include/linux/ipa_uc_offload.h
index 85d0ce9..94d8a8a 100644
--- a/include/linux/ipa_uc_offload.h
+++ b/include/linux/ipa_uc_offload.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -70,12 +70,28 @@
 };
 
 /**
+ * struct ntn_buff_smmu_map -  IPA iova->pa SMMU mapping
+ * @iova: virtual address of the data buffer
+ * @pa: physical address of the data buffer
+ */
+struct ntn_buff_smmu_map {
+	dma_addr_t iova;
+	phys_addr_t pa;
+};
+
+/**
  * struct  ipa_ntn_setup_info - NTN TX/Rx configuration
  * @client: type of "client" (IPA_CLIENT_ODU#_PROD/CONS)
+ * @smmu_enabled: SMMU is enabled for uC or not
  * @ring_base_pa: physical address of the base of the Tx/Rx ring
+ * @ring_base_iova: virtual address of the base of the Tx/Rx ring
+ * @ring_base_sgt:Scatter table for ntn_rings,contains valid non NULL
+ *			value when ENAC S1-SMMU enabed, else NULL.
  * @ntn_ring_size: size of the Tx/Rx ring (in terms of elements)
- * @buff_pool_base_pa: physical address of the base of the Tx/Rx
- *						buffer pool
+ * @buff_pool_base_pa: physical address of the base of the Tx/Rx buffer pool
+ * @buff_pool_base_iova: virtual address of the base of the Tx/Rx buffer pool
+ * @buff_pool_base_sgt: Scatter table for buffer pools,contains valid non NULL
+ *			 value when EMAC S1-SMMU enabed, else NULL.
  * @num_buffers: Rx/Tx buffer pool size (in terms of elements)
  * @data_buff_size: size of the each data buffer allocated in DDR
  * @ntn_reg_base_ptr_pa: physical address of the Tx/Rx NTN Ring's
@@ -83,11 +99,21 @@
  */
 struct ipa_ntn_setup_info {
 	enum ipa_client_type client;
+	bool smmu_enabled;
 	phys_addr_t ring_base_pa;
+	dma_addr_t ring_base_iova;
+	struct sg_table *ring_base_sgt;
+
 	u32 ntn_ring_size;
 
 	phys_addr_t buff_pool_base_pa;
+	dma_addr_t buff_pool_base_iova;
+	struct sg_table *buff_pool_base_sgt;
+
+	struct ntn_buff_smmu_map *data_buff_list;
+
 	u32 num_buffers;
+
 	u32 data_buff_size;
 
 	phys_addr_t ntn_reg_base_ptr_pa;
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 7425430..4c53b17 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -396,6 +396,7 @@
 
 /* Make sure CMDQ is empty before queuing DCMD */
 #define MMC_QUIRK_CMDQ_EMPTY_BEFORE_DCMD (1 << 18)
+#define MMC_QUIRK_QCA9379_SETTINGS (1 << 19)    /* QCA9379 card settings*/
 
 
 	unsigned int		erase_size;	/* erase size in sectors */
@@ -708,6 +709,11 @@
 	return c->quirks & MMC_QUIRK_QCA9377_SETTINGS;
 }
 
+static inline bool mmc_enable_qca9379_settings(const struct mmc_card *c)
+{
+	return c->quirks & MMC_QUIRK_QCA9379_SETTINGS;
+}
+
 #define mmc_card_name(c)	((c)->cid.prod_name)
 #define mmc_card_id(c)		(dev_name(&(c)->dev))
 
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 3513226..e1b845a 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2169,13 +2169,10 @@
 	/* Used in GRE, set in fou/gue_gro_receive */
 	u8	is_fou:1;
 
-	/* Used to determine if flush_id can be ignored */
-	u8	is_atomic:1;
-
 	/* Number of gro_receive callbacks this packet already went through */
 	u8 recursion_counter:4;
 
-	/* 1 bit hole */
+	/* 2 bit hole */
 
 	/* used to support CHECKSUM_COMPLETE for tunneling protocols */
 	__wsum	csum;
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 629907a..2fb9f03 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -280,6 +280,8 @@
 	POWER_SUPPLY_PROP_RECHARGE_SOC,
 	POWER_SUPPLY_PROP_TOGGLE_STAT,
 	POWER_SUPPLY_PROP_ALLOW_HVDCP3,
+	POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED,
+	POWER_SUPPLY_PROP_MAX_PULSE_ALLOWED,
 	/* Local extensions of type int64_t */
 	POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
 	/* Properties of type `const char *' */
@@ -287,6 +289,7 @@
 	POWER_SUPPLY_PROP_MANUFACTURER,
 	POWER_SUPPLY_PROP_SERIAL_NUMBER,
 	POWER_SUPPLY_PROP_BATTERY_TYPE,
+	POWER_SUPPLY_PROP_CYCLE_COUNTS,
 };
 
 enum power_supply_type {
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index 2c6c511..6c0168b 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -47,6 +47,29 @@
 	PWMF_EXPORTED = 1 << 1,
 };
 
+/**
+ * enum pwm_output_type - output type of the PWM signal
+ * @PWM_OUTPUT_FIXED: PWM output is fixed until a change request
+ * @PWM_OUTPUT_MODULATED: PWM output is modulated in hardware
+ * autonomously with a predefined pattern
+ */
+enum pwm_output_type {
+	PWM_OUTPUT_FIXED = 1 << 0,
+	PWM_OUTPUT_MODULATED = 1 << 1,
+};
+
+/**
+ * struct pwm_output_pattern - PWM duty pattern for MODULATED duty type
+ * @duty_pattern: PWM duty cycles in the pattern for duty modulation
+ * @num_entries: number of entries in the pattern
+ * @cycles_per_duty: number of PWM period cycles an entry stays at
+ */
+struct pwm_output_pattern {
+	unsigned int *duty_pattern;
+	unsigned int num_entries;
+	unsigned int cycles_per_duty;
+};
+
 /*
  * struct pwm_state - state of a PWM channel
  * @period: PWM period (in nanoseconds)
@@ -58,6 +81,8 @@
 	unsigned int period;
 	unsigned int duty_cycle;
 	enum pwm_polarity polarity;
+	enum pwm_output_type output_type;
+	struct pwm_output_pattern *output_pattern;
 	bool enabled;
 };
 
@@ -143,6 +168,26 @@
 	return state.polarity;
 }
 
+static inline enum pwm_output_type pwm_get_output_type(
+		const struct pwm_device *pwm)
+{
+	struct pwm_state state;
+
+	pwm_get_state(pwm, &state);
+
+	return state.output_type;
+}
+
+static inline struct pwm_output_pattern *pwm_get_output_pattern(
+				struct pwm_device *pwm)
+{
+	struct pwm_state state;
+
+	pwm_get_state(pwm, &state);
+
+	return pwm->state.output_pattern ?: NULL;
+}
+
 static inline void pwm_get_args(const struct pwm_device *pwm,
 				struct pwm_args *args)
 {
@@ -246,6 +291,9 @@
  * @capture: capture and report PWM signal
  * @enable: enable PWM output toggling
  * @disable: disable PWM output toggling
+ * @get_output_type_supported: get the supported output type
+ * @set_output_type: set PWM output type
+ * @set_output_pattern: set the pattern for the modulated output
  * @apply: atomically apply a new PWM config. The state argument
  *	   should be adjusted with the real hardware config (if the
  *	   approximate the period or duty_cycle value, state should
@@ -267,6 +315,13 @@
 		       struct pwm_capture *result, unsigned long timeout);
 	int (*enable)(struct pwm_chip *chip, struct pwm_device *pwm);
 	void (*disable)(struct pwm_chip *chip, struct pwm_device *pwm);
+	int (*get_output_type_supported)(struct pwm_chip *chip,
+			struct pwm_device *pwm);
+	int (*set_output_type)(struct pwm_chip *chip, struct pwm_device *pwm,
+			enum pwm_output_type output_type);
+	int (*set_output_pattern)(struct pwm_chip *chip,
+			struct pwm_device *pwm,
+			struct pwm_output_pattern *output_pattern);
 	int (*apply)(struct pwm_chip *chip, struct pwm_device *pwm,
 		     struct pwm_state *state);
 	void (*get_state)(struct pwm_chip *chip, struct pwm_device *pwm,
@@ -323,6 +378,21 @@
 int pwm_adjust_config(struct pwm_device *pwm);
 
 /**
+ * pwm_output_type_support()
+ * @pwm: PWM device
+ *
+ * Returns:  output types supported by the PWM device
+ */
+static inline int pwm_get_output_type_supported(struct pwm_device *pwm)
+{
+	if (pwm->chip->ops->get_output_type_supported != NULL)
+		return pwm->chip->ops->
+			get_output_type_supported(pwm->chip, pwm);
+	else
+		return PWM_OUTPUT_FIXED;
+}
+
+/**
  * pwm_config() - change a PWM device configuration
  * @pwm: PWM device
  * @duty_ns: "on" time (in nanoseconds)
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index fc02ece..b8dd63a 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -154,6 +154,7 @@
 /* FW_REVISION_RO fields */
 #define FW_REV_PROTOCOL_MSK	(GENMASK(15, 8))
 #define FW_REV_PROTOCOL_SHFT	(8)
+#define FW_REV_VERSION_MSK	(GENMASK(7, 0))
 
 /* GENI_CLK_SEL fields */
 #define CLK_SEL_MSK		(GENMASK(2, 0))
@@ -405,6 +406,22 @@
 int get_se_proto(void __iomem *base);
 
 /**
+ * get_se_m_fw() - Read the Firmware ver for the Main seqeuncer engine
+ * @base:	Base address of the serial engine's register block.
+ *
+ * Return:	Firmware version for the Main seqeuncer engine
+ */
+int get_se_m_fw(void __iomem *base);
+
+/**
+ * get_se_s_fw() - Read the Firmware ver for the Secondry seqeuncer engine
+ * @base:	Base address of the serial engine's register block.
+ *
+ * Return:	Firmware version for the Secondry seqeuncer engine
+ */
+int get_se_s_fw(void __iomem *base);
+
+/**
  * geni_se_init() - Initialize the GENI Serial Engine
  * @base:	Base address of the serial engine's register block.
  * @rx_wm:	Receive watermark to be configured.
diff --git a/include/linux/qcomwlan_secif.h b/include/linux/qcomwlan_secif.h
new file mode 100644
index 0000000..0795cb7
--- /dev/null
+++ b/include/linux/qcomwlan_secif.h
@@ -0,0 +1,41 @@
+/* Copyright (c) 2011-2013, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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 __QCOM_WLAN_SECIF_H__
+#define __QCOM_WLAN_SECIF_H__
+
+#include <crypto/hash.h>
+
+#define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
+
+/*
+ * Prototypes for WLAN Security Interface Functions
+ */
+
+extern struct crypto_ahash *
+wcnss_wlan_crypto_alloc_ahash(const char *alg_name, u32 type, u32 mask);
+
+extern int wcnss_wlan_crypto_ahash_digest(struct ahash_request *req);
+extern void wcnss_wlan_crypto_free_ahash(struct crypto_ahash *tfm);
+extern int wcnss_wlan_crypto_ahash_setkey(struct crypto_ahash *tfm,
+					const u8 *key, unsigned int keylen);
+extern struct crypto_ablkcipher *
+wcnss_wlan_crypto_alloc_ablkcipher(const char *alg_name, u32 type, u32 mask);
+extern void wcnss_wlan_ablkcipher_request_free(struct ablkcipher_request *req);
+extern void wcnss_wlan_crypto_free_cipher(struct crypto_cipher *tfm);
+extern void wcnss_wlan_crypto_free_ablkcipher(struct crypto_ablkcipher *tfm);
+extern struct crypto_cipher *
+wcnss_wlan_crypto_alloc_cipher(const char *alg_name, u32 type, u32 mask);
+extern void wcnss_wlan_cmac_calc_mic(struct crypto_cipher *tfm, u8 *m,
+				u16 length, u8 *mac);
+
+#endif /* __QCOM_WLAN_SECIF_H__ */
diff --git a/include/linux/qpnp/qpnp-misc.h b/include/linux/qpnp/qpnp-misc.h
index 7d95bf2..a7a5616 100644
--- a/include/linux/qpnp/qpnp-misc.h
+++ b/include/linux/qpnp/qpnp-misc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2014, 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2014, 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
@@ -15,6 +15,11 @@
 
 #include <linux/errno.h>
 
+enum twm_state {
+	PMIC_TWM_CLEAR,
+	PMIC_TWM_ENABLE,
+};
+
 #ifdef CONFIG_QPNP_MISC
 /**
  * qpnp_misc_irqs_available - check if IRQs are available
@@ -42,6 +47,25 @@
  */
 
 int qpnp_misc_read_reg(struct device_node *node, u16 addr, u8 *val);
+/**
+ * qpnp_misc_twm_notifier_register - register to the twm mode notifier
+ *
+ * @nb: pointer to the client's notifier handle
+ *
+ * This function returns 0 if the client is successfuly added to the
+ * notifer list.
+ */
+int qpnp_misc_twm_notifier_register(struct notifier_block *nb);
+
+/**
+ * qpnp_misc_twm_notifier_unregister - unregister to the twm mode notifier
+ *
+ * @nb: pointer to the client's notifier handle
+ *
+ * This function returns 0 if the client is successfuly removed from the
+ * notifer list.
+ */
+int qpnp_misc_twm_notifier_unregister(struct notifier_block *nb);
 #else
 static inline int qpnp_misc_irqs_available(struct device *consumer_dev)
 {
@@ -52,5 +76,13 @@
 {
 	return 0;
 }
+static inline int qpnp_misc_twm_notifier_register(struct notifier_block *nb)
+{
+	return 0;
+}
+static inline int qpnp_misc_twm_notifier_unregister(struct notifier_block *nb)
+{
+	return 0;
+}
 #endif
 #endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 8933c9f..4b2a1bc 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1768,6 +1768,7 @@
 	struct sched_entity se;
 	struct sched_rt_entity rt;
 	u64 last_sleep_ts;
+	u64 last_cpu_selected_ts;
 #ifdef CONFIG_SCHED_WALT
 	struct ravg ravg;
 	/*
@@ -3971,6 +3972,7 @@
 #define SCHED_CPUFREQ_WALT (1U << 4)
 #define SCHED_CPUFREQ_PL	(1U << 5)
 #define SCHED_CPUFREQ_EARLY_DET	(1U << 6)
+#define SCHED_CPUFREQ_FORCE_UPDATE (1U << 7)
 
 #define SCHED_CPUFREQ_RT_DL	(SCHED_CPUFREQ_RT | SCHED_CPUFREQ_DL)
 
diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h
index 0f57407..99948cb 100644
--- a/include/linux/sched/sysctl.h
+++ b/include/linux/sched/sysctl.h
@@ -42,6 +42,11 @@
 
 #endif /* CONFIG_SCHED_WALT */
 
+#if defined(CONFIG_PREEMPT_TRACER) || defined(CONFIG_IRQSOFF_TRACER)
+extern unsigned int sysctl_preemptoff_tracing_threshold_ns;
+extern unsigned int sysctl_irqsoff_tracing_threshold_ns;
+#endif
+
 enum sched_tunable_scaling {
 	SCHED_TUNABLESCALING_NONE,
 	SCHED_TUNABLESCALING_LOG,
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index b7ccd4e..c40355f 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -148,6 +148,7 @@
  * @buf: Dynamic Debug Buffer.
  * @max_nominal_system_clk_rate: max freq at which system clock can run in
 		nominal mode.
+ * @sdp_check: SDP detection work in case of USB_FLOAT power supply
  */
 struct msm_otg {
 	struct usb_phy phy;
@@ -276,6 +277,7 @@
 	unsigned int notify_current_mA;
 	struct pm_qos_request pm_qos_req_dma;
 	struct delayed_work perf_vote_work;
+	struct delayed_work sdp_check;
 	struct work_struct notify_chg_current_work;
 };
 
diff --git a/include/linux/usb_bam.h b/include/linux/usb_bam.h
index fc0647a..3811e34 100644
--- a/include/linux/usb_bam.h
+++ b/include/linux/usb_bam.h
@@ -216,7 +216,6 @@
  *		can work at in bam2bam mode when connected to HS host.
  * @max_mbps_superspeed: Maximum Mbits per seconds that the USB core
  *		can work at in bam2bam mode when connected to SS host.
- * @enable_hsusb_bam_on_boot: Enable HSUSB BAM (non-NDP) on bootup itself
  */
 struct msm_usb_bam_data {
 	u8 max_connections;
@@ -229,7 +228,6 @@
 	u32 override_threshold;
 	u32 max_mbps_highspeed;
 	u32 max_mbps_superspeed;
-	bool enable_hsusb_bam_on_boot;
 	enum usb_ctrl bam_type;
 };
 
diff --git a/include/net/cnss2.h b/include/net/cnss2.h
index ca2de60..9dbf449 100644
--- a/include/net/cnss2.h
+++ b/include/net/cnss2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -88,6 +88,7 @@
 	CNSS_INITIALIZED,
 	CNSS_LOAD_UNLOAD,
 	CNSS_RECOVERY,
+	CNSS_FW_DOWN,
 };
 
 struct cnss_ce_tgt_pipe_cfg {
diff --git a/include/soc/qcom/hsic_sysmon.h b/include/soc/qcom/hsic_sysmon.h
new file mode 100644
index 0000000..5cbecab
--- /dev/null
+++ b/include/soc/qcom/hsic_sysmon.h
@@ -0,0 +1,58 @@
+/* Copyright (c) 2012-2013,2016,2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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 __HSIC_SYSMON_H__
+#define __HSIC_SYSMON_H__
+
+/**
+ * enum hsic_sysmon_device_id - Supported HSIC subsystem devices
+ */
+enum hsic_sysmon_device_id {
+	HSIC_SYSMON_DEV_EXT_MODEM,
+	HSIC_SYSMON_DEV_EXT_MODEM_2,
+	NUM_HSIC_SYSMON_DEVS
+};
+
+#if IS_ENABLED(CONFIG_MSM_HSIC_SYSMON) || \
+	IS_ENABLED(CONFIG_MSM_HSIC_SYSMON_MODULE)
+
+extern int hsic_sysmon_open(enum hsic_sysmon_device_id id);
+extern void hsic_sysmon_close(enum hsic_sysmon_device_id id);
+extern int hsic_sysmon_read(enum hsic_sysmon_device_id id, char *data,
+			    size_t len, size_t *actual_len, int timeout);
+extern int hsic_sysmon_write(enum hsic_sysmon_device_id id, const char *data,
+			     size_t len, int timeout);
+
+#else /* CONFIG_MSM_HSIC_SYSMON || CONFIG_MSM_HSIC_SYSMON_MODULE */
+
+static inline int hsic_sysmon_open(enum hsic_sysmon_device_id id)
+{
+	return -ENODEV;
+}
+
+static inline void hsic_sysmon_close(enum hsic_sysmon_device_id id) { }
+
+static inline int hsic_sysmon_read(enum hsic_sysmon_device_id id, char *data,
+				   size_t len, size_t *actual_len, int timeout)
+{
+	return -ENODEV;
+}
+
+static inline int hsic_sysmon_write(enum hsic_sysmon_device_id id,
+				    const char *data, size_t len, int timeout)
+{
+	return -ENODEV;
+}
+
+#endif /* CONFIG_MSM_HSIC_SYSMON || CONFIG_MSM_HSIC_SYSMON_MODULE */
+
+#endif /* __HSIC_SYSMON_H__ */
diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h
index b04052e..5f496a8 100644
--- a/include/soc/qcom/socinfo.h
+++ b/include/soc/qcom/socinfo.h
@@ -122,6 +122,10 @@
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdm439")
 #define early_machine_is_sdm429()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdm429")
+#define early_machine_is_sda439()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sda439")
+#define early_machine_is_sda429()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sda429")
 #define early_machine_is_mdm9650()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mdm9650")
 #else
@@ -174,6 +178,8 @@
 #define early_machine_is_sdm632()	0
 #define early_machine_is_sdm439()	0
 #define early_machine_is_sdm429()	0
+#define early_machine_is_sda439()	0
+#define early_machine_is_sda429()	0
 #define early_machine_is_mdm9650()     0
 #endif
 
@@ -248,6 +254,8 @@
 	MSM_CPU_9607,
 	MSM_CPU_SDM439,
 	MSM_CPU_SDM429,
+	MSM_CPU_SDA439,
+	MSM_CPU_SDA429,
 	MSM_CPU_9650,
 };
 
diff --git a/include/soc/qcom/sysmon.h b/include/soc/qcom/sysmon.h
index 56860db..2ad3a5e 100644
--- a/include/soc/qcom/sysmon.h
+++ b/include/soc/qcom/sysmon.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2016,2018 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,10 +15,27 @@
 #ifndef __MSM_SYSMON_H
 #define __MSM_SYSMON_H
 
+#include <soc/qcom/smd.h>
 #include <soc/qcom/subsystem_notif.h>
 #include <soc/qcom/subsystem_restart.h>
 
 /**
+ * enum subsys_id - Destination subsystems for events.
+ */
+enum subsys_id {
+	/* SMD subsystems */
+	SYSMON_SS_MODEM     = SMD_APPS_MODEM,
+	SYSMON_SS_LPASS     = SMD_APPS_QDSP,
+	SYSMON_SS_WCNSS     = SMD_APPS_WCNSS,
+	SYSMON_SS_DSPS      = SMD_APPS_DSPS,
+	SYSMON_SS_Q6FW      = SMD_APPS_Q6FW,
+
+	/* Non-SMD subsystems */
+	SYSMON_SS_EXT_MODEM = SMD_NUM_TYPE,
+	SYSMON_NUM_SS
+};
+
+/**
  * enum ssctl_ssr_event_enum_type - Subsystem notification type.
  */
 enum ssctl_ssr_event_enum_type {
diff --git a/include/trace/events/mpm.h b/include/trace/events/mpm.h
index 433fdbf..6746377 100644
--- a/include/trace/events/mpm.h
+++ b/include/trace/events/mpm.h
@@ -57,6 +57,28 @@
 	TP_printk("index:%u wakeup_irqs:0x%x", __entry->index, __entry->irqs)
 );
 
+TRACE_EVENT(mpm_wakeup_time,
+
+	TP_PROTO(bool from_idle, u64 wakeup, u64 current_ticks),
+
+	TP_ARGS(from_idle, wakeup, current_ticks),
+
+	TP_STRUCT__entry(
+		__field(bool, from_idle)
+		__field(u64, wakeup)
+		__field(u64, current_ticks)
+	),
+
+	TP_fast_assign(
+		__entry->from_idle = from_idle;
+		__entry->wakeup = wakeup;
+		__entry->current_ticks = current_ticks;
+	),
+
+	TP_printk("idle:%d wakeup:0x%llx current:0x%llx", __entry->from_idle,
+				__entry->wakeup, __entry->current_ticks)
+);
+
 #endif
 #define TRACE_INCLUDE_FILE mpm
 #include <trace/define_trace.h>
diff --git a/include/trace/events/preemptirq.h b/include/trace/events/preemptirq.h
index f5024c5..3c51180 100644
--- a/include/trace/events/preemptirq.h
+++ b/include/trace/events/preemptirq.h
@@ -52,19 +52,50 @@
 	     TP_ARGS(ip, parent_ip));
 #endif
 
+TRACE_EVENT(irqs_disable,
+
+	TP_PROTO(u64 delta, unsigned long caddr0, unsigned long caddr1,
+				unsigned long caddr2, unsigned long caddr3),
+
+	TP_ARGS(delta, caddr0, caddr1, caddr2, caddr3),
+
+	TP_STRUCT__entry(
+		__field(u64, delta)
+		__field(void*, caddr0)
+		__field(void*, caddr1)
+		__field(void*, caddr2)
+		__field(void*, caddr3)
+	),
+
+	TP_fast_assign(
+		__entry->delta = delta;
+		__entry->caddr0 = (void *)caddr0;
+		__entry->caddr1 = (void *)caddr1;
+		__entry->caddr2 = (void *)caddr2;
+		__entry->caddr3 = (void *)caddr3;
+	),
+
+	TP_printk("delta=%llu(ns) Callers:(%pf<-%pf<-%pf<-%pf)", __entry->delta,
+					__entry->caddr0, __entry->caddr1,
+					__entry->caddr2, __entry->caddr3)
+);
+
 #endif /* _TRACE_PREEMPTIRQ_H */
 
 #include <trace/define_trace.h>
 
-#else /* !CONFIG_PREEMPTIRQ_EVENTS */
+#endif /* !CONFIG_PREEMPTIRQ_EVENTS */
 
+#if !defined(CONFIG_PREEMPTIRQ_EVENTS) || defined(CONFIG_PROVE_LOCKING)
 #define trace_irq_enable(...)
 #define trace_irq_disable(...)
-#define trace_preempt_enable(...)
-#define trace_preempt_disable(...)
 #define trace_irq_enable_rcuidle(...)
 #define trace_irq_disable_rcuidle(...)
+#endif
+
+#if !defined(CONFIG_PREEMPTIRQ_EVENTS) || !defined(CONFIG_DEBUG_PREEMPT)
+#define trace_preempt_enable(...)
+#define trace_preempt_disable(...)
 #define trace_preempt_enable_rcuidle(...)
 #define trace_preempt_disable_rcuidle(...)
-
 #endif
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 23a3b9a..e06df4d 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -714,10 +714,10 @@
 
 	TP_PROTO(struct task_struct *p, int next_cpu, int backup_cpu,
 		 int target_cpu, bool sync, bool need_idle,
-		 bool placement_boost, int rtg_cpu),
+		 bool placement_boost, int rtg_cpu, u64 start_t),
 
 	TP_ARGS(p, next_cpu, backup_cpu, target_cpu, sync, need_idle,
-		placement_boost, rtg_cpu),
+		placement_boost, rtg_cpu, start_t),
 
 	TP_STRUCT__entry(
 		__field(int, pid			)
@@ -746,9 +746,7 @@
 		__entry->need_idle		= need_idle;
 		__entry->placement_boost	= placement_boost;
 		__entry->rtg_cpu		= rtg_cpu;
-		__entry->latency		= p->ravg.mark_start ?
-						  ktime_get_ns() -
-						  p->ravg.mark_start : 0;
+		__entry->latency		= (sched_clock() - start_t);
 	),
 
 	TP_printk("pid=%d comm=%s util=%lu prev_cpu=%d next_cpu=%d backup_cpu=%d target_cpu=%d sync=%d need_idle=%d placement_boost=%d rtg_cpu=%d latency=%llu",
@@ -1877,6 +1875,39 @@
 		  __entry->requested_cpu, __entry->isolated_cpus,
 		  __entry->time, __entry->isolate)
 );
+
+TRACE_EVENT(sched_preempt_disable,
+
+	TP_PROTO(u64 delta, bool irqs_disabled,
+			unsigned long caddr0, unsigned long caddr1,
+			unsigned long caddr2, unsigned long caddr3),
+
+	TP_ARGS(delta, irqs_disabled, caddr0, caddr1, caddr2, caddr3),
+
+	TP_STRUCT__entry(
+		__field(u64, delta)
+		__field(bool, irqs_disabled)
+		__field(void*, caddr0)
+		__field(void*, caddr1)
+		__field(void*, caddr2)
+		__field(void*, caddr3)
+	),
+
+	TP_fast_assign(
+		__entry->delta = delta;
+		__entry->irqs_disabled = irqs_disabled;
+		__entry->caddr0 = (void *)caddr0;
+		__entry->caddr1 = (void *)caddr1;
+		__entry->caddr2 = (void *)caddr2;
+		__entry->caddr3 = (void *)caddr3;
+	),
+
+	TP_printk("delta=%llu(ns) irqs_d=%d Callers:(%pf<-%pf<-%pf<-%pf)",
+				__entry->delta, __entry->irqs_disabled,
+				__entry->caddr0, __entry->caddr1,
+				__entry->caddr2, __entry->caddr3)
+);
+
 #endif /* _TRACE_SCHED_H */
 
 /* This part must be outside protection */
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index a17b435..75aa98ff 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -511,4 +511,5 @@
 header-y += msm_dsps.h
 header-y += msm-core-interface.h
 header-y += msm_rotator.h
+header-y += bgcom_interface.h
 header-y += nfc/
diff --git a/include/uapi/linux/bgcom_interface.h b/include/uapi/linux/bgcom_interface.h
new file mode 100644
index 0000000..f18280a
--- /dev/null
+++ b/include/uapi/linux/bgcom_interface.h
@@ -0,0 +1,63 @@
+/* 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 LINUX_BG_CHAR_H
+#define LINUX_BG_CHAR_H
+#define BGCOM_REG_READ  0
+#define BGCOM_AHB_READ  1
+#define BGCOM_AHB_WRITE 2
+#define BGCOM_SET_SPI_FREE  3
+#define BGCOM_SET_SPI_BUSY  4
+#define BGCOM_REG_WRITE  5
+#define BGCOM_SOFT_RESET  6
+#define BGCOM_MODEM_DOWN2_BG  7
+#define EXCHANGE_CODE  'V'
+
+struct bg_ui_data {
+	uint64_t  __user write;
+	uint64_t  __user result;
+	uint32_t  bg_address;
+	uint32_t  cmd;
+	uint32_t  num_of_words;
+};
+
+enum bg_event_type {
+	BG_BEFORE_POWER_DOWN = 1,
+	BG_AFTER_POWER_UP,
+	MODEM_BEFORE_POWER_DOWN,
+	MODEM_AFTER_POWER_UP,
+};
+
+#define REG_READ \
+	_IOWR(EXCHANGE_CODE, BGCOM_REG_READ, \
+	struct bg_ui_data)
+#define AHB_READ \
+	_IOWR(EXCHANGE_CODE, BGCOM_AHB_READ, \
+	struct bg_ui_data)
+#define AHB_WRITE \
+	_IOW(EXCHANGE_CODE, BGCOM_AHB_WRITE, \
+	struct bg_ui_data)
+#define SET_SPI_FREE \
+	_IOR(EXCHANGE_CODE, BGCOM_SET_SPI_FREE, \
+	struct bg_ui_data)
+#define SET_SPI_BUSY \
+	_IOR(EXCHANGE_CODE, BGCOM_SET_SPI_BUSY, \
+	struct bg_ui_data)
+#define REG_WRITE \
+	_IOWR(EXCHANGE_CODE, BGCOM_REG_WRITE, \
+	struct bg_ui_data)
+#define BG_SOFT_RESET \
+	_IOWR(EXCHANGE_CODE, BGCOM_SOFT_RESET, \
+	struct bg_ui_data)
+#define BG_MODEM_DOWN2_BG_DONE \
+	_IOWR(EXCHANGE_CODE, BGCOM_MODEM_DOWN2_BG, \
+	struct bg_ui_data)
+#endif
diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h
index de3f890..062a1b9 100644
--- a/include/uapi/linux/msm_ipa.h
+++ b/include/uapi/linux/msm_ipa.h
@@ -95,6 +95,8 @@
 #define IPA_IOCTL_ALLOC_IPV6CT_TABLE            53
 #define IPA_IOCTL_DEL_NAT_TABLE                 54
 #define IPA_IOCTL_DEL_IPV6CT_TABLE              55
+#define IPA_IOCTL_CLEANUP                       56
+#define IPA_IOCTL_QUERY_WLAN_CLIENT             57
 
 /**
  * max size of the header to be inserted
@@ -2023,6 +2025,10 @@
 #define IPA_IOC_DEL_L2TP_VLAN_MAPPING _IOWR(IPA_IOC_MAGIC, \
 				IPA_IOCTL_DEL_L2TP_VLAN_MAPPING, \
 				struct ipa_ioc_l2tp_vlan_mapping_info *)
+#define IPA_IOC_CLEANUP _IO(IPA_IOC_MAGIC,\
+					IPA_IOCTL_CLEANUP)
+#define IPA_IOC_QUERY_WLAN_CLIENT _IO(IPA_IOC_MAGIC,\
+					IPA_IOCTL_QUERY_WLAN_CLIENT)
 /*
  * unique magic number of the Tethering bridge ioctls
  */
diff --git a/include/uapi/linux/qcedev.h b/include/uapi/linux/qcedev.h
index fb51c23..108af3c 100644
--- a/include/uapi/linux/qcedev.h
+++ b/include/uapi/linux/qcedev.h
@@ -228,6 +228,33 @@
 	void *kernel;
 };
 
+/**
+ * struct qcedev_map_buf_req - Holds the mapping request information
+ * fd (IN):            Array of fds.
+ * num_fds (IN):       Number of fds in fd[].
+ * fd_size (IN):       Array of sizes corresponding to each fd in fd[].
+ * fd_offset (IN):     Array of offset corresponding to each fd in fd[].
+ * vaddr (OUT):        Array of mapped virtual address corresponding to
+ *			each fd in fd[].
+ */
+struct qcedev_map_buf_req {
+	int32_t         fd[QCEDEV_MAX_BUFFERS];
+	uint32_t        num_fds;
+	uint32_t        fd_size[QCEDEV_MAX_BUFFERS];
+	uint32_t        fd_offset[QCEDEV_MAX_BUFFERS];
+	uint64_t        buf_vaddr[QCEDEV_MAX_BUFFERS];
+};
+
+/**
+ * struct qcedev_unmap_buf_req - Holds the hashing request information
+ * fd (IN):            Array of fds to unmap
+ * num_fds (IN):       Number of fds in fd[].
+ */
+struct  qcedev_unmap_buf_req {
+	int32_t         fd[QCEDEV_MAX_BUFFERS];
+	uint32_t        num_fds;
+};
+
 struct file;
 
 #define QCEDEV_IOC_MAGIC	0x87
@@ -250,8 +277,8 @@
 	_IO(QCEDEV_IOC_MAGIC, 8)
 #define QCEDEV_IOCTL_GET_CMAC_REQ	\
 	_IOWR(QCEDEV_IOC_MAGIC, 9, struct qcedev_sha_op_req)
-#define QCEDEV_IOCTL_UPDATE_FIPS_STATUS		\
-	_IOWR(QCEDEV_IOC_MAGIC, 10, enum fips_status)
-#define QCEDEV_IOCTL_QUERY_FIPS_STATUS	\
-	_IOR(QCEDEV_IOC_MAGIC, 11, enum fips_status)
+#define QCEDEV_IOCTL_MAP_BUF_REQ	\
+	_IOWR(QCEDEV_IOC_MAGIC, 10, struct qcedev_map_buf_req)
+#define QCEDEV_IOCTL_UNMAP_BUF_REQ	\
+	_IOWR(QCEDEV_IOC_MAGIC, 11, struct qcedev_unmap_buf_req)
 #endif /* _UAPI_QCEDEV__H */
diff --git a/include/uapi/linux/qseecom.h b/include/uapi/linux/qseecom.h
index 55c71dd..f0a26b2 100644
--- a/include/uapi/linux/qseecom.h
+++ b/include/uapi/linux/qseecom.h
@@ -277,6 +277,17 @@
 	struct qseecom_ce_pipe_entry ce_pipe_entry[MAX_CE_PIPE_PAIR_PER_UNIT];
 };
 
+struct qseecom_ice_data_t {
+	int flag;
+};
+
+struct qseecom_encdec_conf_t {
+	__le64 start_sector;
+	size_t fs_size;
+	int index;
+	int mode;
+};
+
 #define SG_ENTRY_SZ		sizeof(struct qseecom_sg_entry)
 #define SG_ENTRY_SZ_64BIT	sizeof(struct qseecom_sg_entry_64bit)
 
@@ -385,5 +396,10 @@
 #define QSEECOM_IOCTL_QUERY_CE_PIPE_INFO \
 	_IOWR(QSEECOM_IOC_MAGIC, 42, struct qseecom_ce_info_req)
 
+#define QSEECOM_IOCTL_SET_ICE_INFO \
+	_IOWR(QSEECOM_IOC_MAGIC, 43, struct qseecom_ice_data_t)
+
+#define QSEECOM_IOCTL_SET_ENCDEC_INFO \
+	_IOWR(QSEECOM_IOC_MAGIC, 44, struct qseecom_encdec_conf_t)
 
 #endif /* _UAPI_QSEECOM_H_ */
diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h
index 3f1facd..841c40a 100644
--- a/include/uapi/media/cam_req_mgr.h
+++ b/include/uapi/media/cam_req_mgr.h
@@ -41,9 +41,9 @@
 #define V4L_EVENT_CAM_REQ_MGR_EVENT       (V4L2_EVENT_PRIVATE_START + 0)
 
 /* Specific event ids to get notified in user space */
-#define V4L_EVENT_CAM_REQ_MGR_SOF         0
-#define V4L_EVENT_CAM_REQ_MGR_ERROR       1
-#define V4L_EVENT_CAM_REQ_MGR_MAX         2
+#define V4L_EVENT_CAM_REQ_MGR_SOF            0
+#define V4L_EVENT_CAM_REQ_MGR_ERROR          1
+#define V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS    2
 
 /* SOF Event status */
 #define CAM_REQ_MGR_SOF_EVENT_SUCCESS           0
diff --git a/include/uapi/media/msm_camera.h b/include/uapi/media/msm_camera.h
index 693fd21..c58a273 100644
--- a/include/uapi/media/msm_camera.h
+++ b/include/uapi/media/msm_camera.h
@@ -1392,6 +1392,7 @@
 	uint16_t lane_mask;
 	uint8_t combo_mode;
 	uint8_t csid_core;
+	unsigned long data_rate;
 };
 
 struct msm_camera_csi2_params {
diff --git a/include/uapi/media/msm_camsensor_sdk.h b/include/uapi/media/msm_camsensor_sdk.h
index 5266c02..2283933f 100644
--- a/include/uapi/media/msm_camsensor_sdk.h
+++ b/include/uapi/media/msm_camsensor_sdk.h
@@ -367,6 +367,7 @@
 	unsigned char csid_core;
 	unsigned int csiphy_clk;
 	unsigned char csi_3phase;
+	unsigned long data_rate;
 };
 
 struct msm_camera_i2c_seq_reg_array {
diff --git a/kernel/events/core.c b/kernel/events/core.c
index e144ded..cd941f8 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -4286,7 +4286,7 @@
 	 *  back online.
 	 */
 #if defined CONFIG_HOTPLUG_CPU || defined CONFIG_KEXEC_CORE
-	if (!cpu_online(event->cpu)) {
+	if (event->cpu != -1 && !cpu_online(event->cpu)) {
 		if (event->state == PERF_EVENT_STATE_ZOMBIE)
 			return 0;
 
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index f4330a2..a29eaee 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -77,6 +77,23 @@
 
 	  For more information take a look at <file:Documentation/power/swsusp.txt>.
 
+config HIBERNATION_IMAGE_REUSE
+	bool "Reuse hibernation image"
+	depends on HIBERNATION
+	---help---
+	  By default this hibernation image is erased after either a
+	  successful or unsuccessful hibernation restore sequeunce. Since
+	  filesystem contents on disk are not part of the hibernation
+	  image, failure to create a new hibernation image every boot can
+	  lead to filesystem corruption.
+
+	  Conversely, if the usecase can guarantee that the filesystem is
+	  not ever modified, the same hibernation image can be reused. This
+	  prevents creating additional hibernation images unncesarily.
+
+	  For more details, refer to the description of CONFIG_HIBERNATION
+	  for booting without resuming.
+
 config ARCH_SAVE_PAGE_KEYS
 	bool
 
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index a3b1e61..95db6b79 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -1542,10 +1542,12 @@
 
 		if (!memcmp(HIBERNATE_SIG, swsusp_header->sig, 10)) {
 			memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10);
+#ifndef CONFIG_HIBERNATION_IMAGE_REUSE
 			/* Reset swap signature now */
 			error = hib_submit_io(REQ_OP_WRITE, WRITE_SYNC,
 						swsusp_resume_block,
 						swsusp_header, NULL);
+#endif
 		} else {
 			error = -EINVAL;
 		}
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 484578e..467801c 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2331,6 +2331,7 @@
 	p->se.nr_migrations		= 0;
 	p->se.vruntime			= 0;
 	p->last_sleep_ts		= 0;
+	p->last_cpu_selected_ts		= 0;
 
 	INIT_LIST_HEAD(&p->se.group_node);
 
@@ -3323,16 +3324,38 @@
 #if defined(CONFIG_PREEMPT) && (defined(CONFIG_DEBUG_PREEMPT) || \
 				defined(CONFIG_PREEMPT_TRACER))
 /*
+ * preemptoff stack tracing threshold in ns.
+ * default: 1ms
+ */
+unsigned int sysctl_preemptoff_tracing_threshold_ns = 1000000UL;
+
+struct preempt_store {
+	u64 ts;
+	unsigned long caddr[4];
+	bool irqs_disabled;
+};
+
+static DEFINE_PER_CPU(struct preempt_store, the_ps);
+/*
  * If the value passed in is equal to the current preempt count
  * then we just disabled preemption. Start timing the latency.
  */
 static inline void preempt_latency_start(int val)
 {
+	struct preempt_store *ps = &per_cpu(the_ps, raw_smp_processor_id());
+
 	if (preempt_count() == val) {
 		unsigned long ip = get_lock_parent_ip();
 #ifdef CONFIG_DEBUG_PREEMPT
 		current->preempt_disable_ip = ip;
 #endif
+		ps->ts = sched_clock();
+		ps->caddr[0] = CALLER_ADDR0;
+		ps->caddr[1] = CALLER_ADDR1;
+		ps->caddr[2] = CALLER_ADDR2;
+		ps->caddr[3] = CALLER_ADDR3;
+		ps->irqs_disabled = irqs_disabled();
+
 		trace_preempt_off(CALLER_ADDR0, ip);
 	}
 }
@@ -3365,8 +3388,21 @@
  */
 static inline void preempt_latency_stop(int val)
 {
-	if (preempt_count() == val)
+	if (preempt_count() == val) {
+		struct preempt_store *ps = &per_cpu(the_ps,
+				raw_smp_processor_id());
+		u64 delta = sched_clock() - ps->ts;
+
+		/*
+		 * Trace preempt disable stack if preemption
+		 * is disabled for more than the threshold.
+		 */
+		if (delta > sysctl_preemptoff_tracing_threshold_ns)
+			trace_sched_preempt_disable(delta, ps->irqs_disabled,
+						ps->caddr[0], ps->caddr[1],
+						ps->caddr[2], ps->caddr[3]);
 		trace_preempt_on(CALLER_ADDR0, get_lock_parent_ip());
+	}
 }
 
 void preempt_count_sub(int val)
@@ -4294,7 +4330,8 @@
 	struct rq *rq;
 
 	/* may grab non-irq protected spin_locks */
-	BUG_ON(in_interrupt());
+	if (pi)
+		BUG_ON(in_interrupt());
 recheck:
 	/* double check policy once rq lock held */
 	if (policy < 0) {
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 744b535..04ba6d0 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6814,12 +6814,33 @@
 	bool avoid_prev_cpu;
 };
 
+#ifdef CONFIG_SCHED_WALT
+static unsigned long cpu_estimated_capacity(int cpu, struct task_struct *p)
+{
+	unsigned long tutil, estimated_capacity;
+
+	if (task_in_cum_window_demand(cpu_rq(cpu), p))
+		tutil = 0;
+	else
+		tutil = task_util(p);
+
+	estimated_capacity = cpu_util_cum(cpu, tutil);
+
+	return estimated_capacity;
+}
+#else
+static unsigned long cpu_estimated_capacity(int cpu, struct task_struct *p)
+{
+	return cpu_util_wake(cpu, p);
+}
+#endif
+
 static bool is_packing_eligible(struct task_struct *p, int target_cpu,
 				struct find_best_target_env *fbt_env,
 				unsigned int target_cpus_count,
 				int best_idle_cstate)
 {
-	unsigned long tutil, estimated_capacity;
+	unsigned long estimated_capacity;
 
 	if (fbt_env->placement_boost || fbt_env->need_idle)
 		return false;
@@ -6830,12 +6851,7 @@
 	if (target_cpus_count != 1)
 		return true;
 
-	if (task_in_cum_window_demand(cpu_rq(target_cpu), p))
-		tutil = 0;
-	else
-		tutil = task_util(p);
-
-	estimated_capacity = cpu_util_cum(target_cpu, tutil);
+	estimated_capacity = cpu_estimated_capacity(target_cpu, p);
 	estimated_capacity = add_capacity_margin(estimated_capacity,
 						 target_cpu);
 
@@ -6874,6 +6890,7 @@
 	return walt_start_cpu(start_cpu);
 }
 
+unsigned int sched_smp_overlap_capacity;
 static inline int find_best_target(struct task_struct *p, int *backup_cpu,
 				   bool boosted, bool prefer_idle,
 				   struct find_best_target_env *fbt_env)
@@ -7113,6 +7130,12 @@
 			}
 
 			/*
+			 * Consider only idle CPUs for active migration.
+			 */
+			if (p->state == TASK_RUNNING)
+				continue;
+
+			/*
 			 * Case C) Non latency sensitive tasks on ACTIVE CPUs.
 			 *
 			 * Pack tasks in the most energy efficient capacities.
@@ -7273,6 +7296,40 @@
 	       task_fits_max(p, cpu);
 }
 
+#define SCHED_SELECT_PREV_CPU_NSEC	2000000
+#define SCHED_FORCE_CPU_SELECTION_NSEC	20000000
+
+static inline bool
+bias_to_prev_cpu(struct task_struct *p, struct cpumask *rtg_target)
+{
+	int prev_cpu = task_cpu(p);
+#ifdef CONFIG_SCHED_WALT
+	u64 ms = p->ravg.mark_start;
+#else
+	u64 ms = sched_clock();
+#endif
+
+	if (cpu_isolated(prev_cpu) || !idle_cpu(prev_cpu))
+		return false;
+
+	if (!ms)
+		return false;
+
+	if (ms - p->last_cpu_selected_ts >= SCHED_SELECT_PREV_CPU_NSEC) {
+		p->last_cpu_selected_ts = ms;
+		return false;
+	}
+
+	if (ms - p->last_sleep_ts >= SCHED_SELECT_PREV_CPU_NSEC)
+		return false;
+
+	if (rtg_target && !cpumask_test_cpu(prev_cpu, rtg_target))
+		return false;
+
+	return true;
+}
+
+#ifdef CONFIG_SCHED_WALT
 static inline struct cpumask *find_rtg_target(struct task_struct *p)
 {
 	struct related_thread_group *grp;
@@ -7293,6 +7350,12 @@
 
 	return rtg_target;
 }
+#else
+static inline struct cpumask *find_rtg_target(struct task_struct *p)
+{
+	return NULL;
+}
+#endif
 
 static int select_energy_cpu_brute(struct task_struct *p, int prev_cpu, int sync)
 {
@@ -7303,6 +7366,10 @@
 	int next_cpu = -1;
 	struct cpumask *rtg_target = find_rtg_target(p);
 	struct find_best_target_env fbt_env;
+	u64 start_t = 0;
+
+	if (trace_sched_task_util_enabled())
+		start_t = sched_clock();
 
 	schedstat_inc(p->se.statistics.nr_wakeups_secb_attempts);
 	schedstat_inc(this_rq()->eas_stats.secb_attempts);
@@ -7340,6 +7407,9 @@
 		}
 	}
 
+	if (bias_to_prev_cpu(p, rtg_target))
+		return prev_cpu;
+
 	rcu_read_lock();
 
 	sd = rcu_dereference(per_cpu(sd_ea, prev_cpu));
@@ -7427,7 +7497,8 @@
 unlock:
 	trace_sched_task_util(p, next_cpu, backup_cpu, target_cpu, sync,
 			      fbt_env.need_idle, fbt_env.placement_boost,
-			      rtg_target ? cpumask_first(rtg_target) : -1);
+			      rtg_target ? cpumask_first(rtg_target) : -1,
+			      start_t);
 	rcu_read_unlock();
 	return target_cpu;
 }
@@ -8754,9 +8825,11 @@
 		capacity = 1;
 
 	cpu_rq(cpu)->cpu_capacity = capacity;
-	sdg->sgc->capacity = capacity;
-	sdg->sgc->max_capacity = capacity;
-	sdg->sgc->min_capacity = capacity;
+	if (!sd->child) {
+		sdg->sgc->capacity = capacity;
+		sdg->sgc->max_capacity = capacity;
+		sdg->sgc->min_capacity = capacity;
+	}
 }
 
 void update_group_capacity(struct sched_domain *sd, int cpu)
@@ -8770,9 +8843,16 @@
 	interval = clamp(interval, 1UL, max_load_balance_interval);
 	sdg->sgc->next_update = jiffies + interval;
 
-	if (!child) {
+	/*
+	 * When there is only 1 CPU in the sched group of a higher
+	 * level sched domain (sd->child != NULL), the load balance
+	 * does not happen for the last level sched domain. Check
+	 * this condition and update the CPU capacity accordingly.
+	 */
+	if (cpumask_weight(sched_group_cpus(sdg)) == 1) {
 		update_cpu_capacity(sd, cpu);
-		return;
+		if (!child)
+			return;
 	}
 
 	capacity = 0;
@@ -10871,6 +10951,24 @@
 
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_SCHED_WALT
+static inline void
+walt_update_misfit_task(struct rq *rq, struct task_struct *curr)
+{
+	bool misfit = rq->misfit_task;
+
+	if (curr->misfit != misfit) {
+		walt_fixup_nr_big_tasks(rq, curr, 1, misfit);
+		curr->misfit = misfit;
+	}
+}
+#else
+static inline void
+walt_update_misfit_task(struct rq *rq, struct task_struct *curr)
+{
+}
+#endif
+
 /*
  * scheduler tick hitting a task of our scheduling class:
  */
@@ -10878,10 +10976,6 @@
 {
 	struct cfs_rq *cfs_rq;
 	struct sched_entity *se = &curr->se;
-#ifdef CONFIG_SMP
-	bool old_misfit = curr->misfit;
-	bool misfit;
-#endif
 
 	for_each_sched_entity(se) {
 		cfs_rq = cfs_rq_of(se);
@@ -10897,15 +10991,9 @@
 		trace_sched_overutilized(true);
 	}
 
-	misfit = !task_fits_max(curr, rq->cpu);
-	rq->misfit_task = misfit;
-
-	if (old_misfit != misfit) {
-		walt_fixup_nr_big_tasks(rq, curr, 1, misfit);
-		curr->misfit = misfit;
-	}
+	rq->misfit_task = !task_fits_max(curr, rq->cpu);
 #endif
-
+	walt_update_misfit_task(rq, curr);
 }
 
 /*
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 8329e9c..f27ab13 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -822,6 +822,9 @@
 	u8 curr_table;
 	int prev_top;
 	int curr_top;
+	bool notif_pending;
+	u64 last_cc_update;
+	u64 cycles;
 #endif
 
 #ifdef CONFIG_IRQ_TIME_ACCOUNTING
@@ -1112,6 +1115,11 @@
 	SCHED_BOOST_ON_ALL,
 };
 
+#define NO_BOOST 0
+#define FULL_THROTTLE_BOOST 1
+#define CONSERVATIVE_BOOST 2
+#define RESTRAINED_BOOST 3
+
 /*
  * Returns the rq capacity of any rq in a group. This does not play
  * well with groups where rq capacity can change independently.
@@ -1910,6 +1918,9 @@
 	return cpu_util_freq_pelt(cpu);
 }
 
+#define sched_ravg_window TICK_NSEC
+#define sysctl_sched_use_walt_cpu_util 0
+
 #endif /* CONFIG_SCHED_WALT */
 
 extern unsigned long
@@ -2258,7 +2269,8 @@
 
 #ifdef CONFIG_SCHED_WALT
 	unsigned int exception_flags = SCHED_CPUFREQ_INTERCLUSTER_MIG |
-				SCHED_CPUFREQ_PL | SCHED_CPUFREQ_EARLY_DET;
+				SCHED_CPUFREQ_PL | SCHED_CPUFREQ_EARLY_DET |
+				SCHED_CPUFREQ_FORCE_UPDATE;
 
 	/*
 	 * Skip if we've already reported, but not if this is an inter-cluster
@@ -2367,11 +2379,6 @@
 extern void add_new_task_to_grp(struct task_struct *new);
 extern unsigned int update_freq_aggregate_threshold(unsigned int threshold);
 
-#define NO_BOOST 0
-#define FULL_THROTTLE_BOOST 1
-#define CONSERVATIVE_BOOST 2
-#define RESTRAINED_BOOST 3
-
 static inline int cpu_capacity(int cpu)
 {
 	return cpu_rq(cpu)->cluster->capacity;
@@ -2789,6 +2796,11 @@
 
 static inline void clear_walt_request(int cpu) { }
 
+static inline int is_reserved(int cpu)
+{
+	return 0;
+}
+
 static inline int got_boost_kick(void)
 {
 	return 0;
diff --git a/kernel/sched/tune.c b/kernel/sched/tune.c
index bdcd174..192e8c7 100644
--- a/kernel/sched/tune.c
+++ b/kernel/sched/tune.c
@@ -753,6 +753,10 @@
 		sync_cgroup_colocation(task, colocate);
 
 }
+#else
+static void schedtune_attach(struct cgroup_taskset *tset)
+{
+}
 #endif
 
 static int
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
index b4d815c..a9fb367 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -301,10 +301,27 @@
 	return 0;
 }
 
-static void update_task_cpu_cycles(struct task_struct *p, int cpu)
+/*
+ * Assumes rq_lock is held and wallclock was recorded in the same critical
+ * section as this function's invocation.
+ */
+static inline u64 read_cycle_counter(int cpu, u64 wallclock)
+{
+	struct rq *rq = cpu_rq(cpu);
+
+	if (rq->last_cc_update != wallclock) {
+		rq->cycles = cpu_cycle_counter_cb.get_cpu_cycle_counter(cpu);
+		rq->last_cc_update = wallclock;
+	}
+
+	return rq->cycles;
+}
+
+static void update_task_cpu_cycles(struct task_struct *p, int cpu,
+				   u64 wallclock)
 {
 	if (use_cycle_counter)
-		p->cpu_cycles = cpu_cycle_counter_cb.get_cpu_cycle_counter(cpu);
+		p->cpu_cycles = read_cycle_counter(cpu, wallclock);
 }
 
 void clear_ed_task(struct task_struct *p, struct rq *rq)
@@ -348,7 +365,7 @@
 	if (is_idle_task(curr)) {
 		/* We're here without rq->lock held, IRQ disabled */
 		raw_spin_lock(&rq->lock);
-		update_task_cpu_cycles(curr, cpu);
+		update_task_cpu_cycles(curr, cpu, ktime_get_ns());
 		raw_spin_unlock(&rq->lock);
 	}
 }
@@ -757,7 +774,7 @@
 	update_task_ravg(p, task_rq(p), TASK_MIGRATE,
 			 wallclock, 0);
 
-	update_task_cpu_cycles(p, new_cpu);
+	update_task_cpu_cycles(p, new_cpu, wallclock);
 
 	/*
 	 * When a task is migrating during the wakeup, adjust
@@ -822,8 +839,11 @@
 
 	migrate_top_tasks(p, src_rq, dest_rq);
 
-	if (!same_freq_domain(new_cpu, task_cpu(p)))
+	if (!same_freq_domain(new_cpu, task_cpu(p))) {
+		src_rq->notif_pending = true;
+		dest_rq->notif_pending = true;
 		irq_work_queue(&walt_migration_irq_work);
+	}
 
 	if (p == src_rq->ed_task) {
 		src_rq->ed_task = NULL;
@@ -1836,7 +1856,7 @@
 		return;
 	}
 
-	cur_cycles = cpu_cycle_counter_cb.get_cpu_cycle_counter(cpu);
+	cur_cycles = read_cycle_counter(cpu, wallclock);
 
 	/*
 	 * If current task is idle task and irqtime == 0 CPU was
@@ -1901,7 +1921,7 @@
 	old_window_start = update_window_start(rq, wallclock, event);
 
 	if (!p->ravg.mark_start) {
-		update_task_cpu_cycles(p, cpu_of(rq));
+		update_task_cpu_cycles(p, cpu_of(rq), wallclock);
 		goto done;
 	}
 
@@ -2032,7 +2052,7 @@
 	p->ravg.mark_start = p->last_wake_ts = wallclock;
 	p->last_enqueued_ts = wallclock;
 	p->last_switch_out_ts = 0;
-	update_task_cpu_cycles(p, cpu_of(rq));
+	update_task_cpu_cycles(p, cpu_of(rq), wallclock);
 }
 
 static cpumask_t all_cluster_cpus = CPU_MASK_NONE;
@@ -2193,7 +2213,6 @@
 
 int __read_mostly min_power_cpu;
 
-unsigned int sched_smp_overlap_capacity;
 void walt_sched_energy_populated_callback(void)
 {
 	struct sched_cluster *cluster;
@@ -3114,10 +3133,11 @@
 	int cpu;
 	u64 wc;
 	int flag = SCHED_CPUFREQ_WALT;
+	bool is_migration = false;
 
 	/* Am I the window rollover work or the migration work? */
 	if (irq_work == &walt_migration_irq_work)
-		flag |= SCHED_CPUFREQ_INTERCLUSTER_MIG;
+		is_migration = true;
 
 	for_each_cpu(cpu, cpu_possible_mask)
 		raw_spin_lock(&cpu_rq(cpu)->lock);
@@ -3144,14 +3164,29 @@
 		raw_spin_unlock(&cluster->load_lock);
 	}
 
-	for_each_sched_cluster(cluster)
-		for_each_cpu(cpu, &cluster->cpus)
-			cpufreq_update_util(cpu_rq(cpu), flag);
+	for_each_sched_cluster(cluster) {
+		for_each_cpu(cpu, &cluster->cpus) {
+			int nflag = flag;
+
+			rq = cpu_rq(cpu);
+
+			if (is_migration) {
+				if (rq->notif_pending) {
+					nflag |= SCHED_CPUFREQ_INTERCLUSTER_MIG;
+					rq->notif_pending = false;
+				} else {
+					nflag |= SCHED_CPUFREQ_FORCE_UPDATE;
+				}
+			}
+
+			cpufreq_update_util(rq, nflag);
+		}
+	}
 
 	for_each_cpu(cpu, cpu_possible_mask)
 		raw_spin_unlock(&cpu_rq(cpu)->lock);
 
-	if (irq_work != &walt_migration_irq_work)
+	if (!is_migration)
 		core_ctl_check(this_rq()->window_start);
 }
 
@@ -3237,6 +3272,8 @@
 	rq->curr_table = 0;
 	rq->prev_top = 0;
 	rq->curr_top = 0;
+	rq->last_cc_update = 0;
+	rq->cycles = 0;
 	for (j = 0; j < NUM_TRACKED_WINDOWS; j++) {
 		memset(&rq->load_subs[j], 0,
 				sizeof(struct load_subtractions));
@@ -3247,6 +3284,7 @@
 		clear_top_tasks_bitmap(rq->top_tasks_bitmap[j]);
 	}
 	rq->cum_window_demand = 0;
+	rq->notif_pending = false;
 
 	walt_cpu_util_freq_divisor =
 	    (sched_ravg_window >> SCHED_CAPACITY_SHIFT) * 100;
diff --git a/kernel/sched/walt.h b/kernel/sched/walt.h
index 414c4ae..be06e7d4 100644
--- a/kernel/sched/walt.h
+++ b/kernel/sched/walt.h
@@ -181,7 +181,6 @@
 {
 	return sched_irqload(cpu) >= sysctl_sched_cpu_high_irqload;
 }
-#define walt_cpu_high_irqload(cpu) sched_cpu_high_irqload(cpu)
 
 static inline int exiting_task(struct task_struct *p)
 {
@@ -378,6 +377,12 @@
 	return prev_cpu;
 }
 
+static inline u64 sched_irqload(int cpu)
+{
+	return 0;
+}
 #endif /* CONFIG_SCHED_WALT */
 
+#define walt_cpu_high_irqload(cpu) sched_cpu_high_irqload(cpu)
+
 #endif
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 6340010..f41c0e9 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -291,6 +291,22 @@
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec,
 	},
+#if defined(CONFIG_PREEMPT_TRACER) || defined(CONFIG_IRQSOFF_TRACER)
+	{
+		.procname       = "preemptoff_tracing_threshold_ns",
+		.data           = &sysctl_preemptoff_tracing_threshold_ns,
+		.maxlen         = sizeof(unsigned int),
+		.mode           = 0644,
+		.proc_handler   = proc_dointvec,
+	},
+	{
+		.procname       = "irqsoff_tracing_threshold_ns",
+		.data           = &sysctl_irqsoff_tracing_threshold_ns,
+		.maxlen         = sizeof(unsigned int),
+		.mode           = 0644,
+		.proc_handler   = proc_dointvec,
+	},
+#endif
 #ifdef CONFIG_SCHED_WALT
 	{
 		.procname       = "sched_cpu_high_irqload",
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index c180fe5..79bbaf0 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -13,6 +13,7 @@
 #include <linux/uaccess.h>
 #include <linux/module.h>
 #include <linux/ftrace.h>
+#include <linux/sched/sysctl.h>
 
 #include "trace.h"
 
@@ -39,6 +40,12 @@
 static void stop_irqsoff_tracer(struct trace_array *tr, int graph);
 static int start_irqsoff_tracer(struct trace_array *tr, int graph);
 
+/*
+ * irqsoff stack tracing threshold in ns.
+ * default: 1ms
+ */
+unsigned int sysctl_irqsoff_tracing_threshold_ns = 1000000UL;
+
 #ifdef CONFIG_PREEMPT_TRACER
 static inline int
 preempt_trace(void)
@@ -454,17 +461,53 @@
 
 #else /* !CONFIG_PROVE_LOCKING */
 
+#ifdef CONFIG_PREEMPTIRQ_EVENTS
+struct irqsoff_store {
+	u64 ts;
+	unsigned long caddr[4];
+};
+
+static DEFINE_PER_CPU(struct irqsoff_store, the_irqsoff);
+#endif /* CONFIG_PREEMPTIRQ_EVENTS */
+
 /*
  * We are only interested in hardirq on/off events:
  */
 static inline void tracer_hardirqs_on(void)
 {
+#ifdef CONFIG_PREEMPTIRQ_EVENTS
+	struct irqsoff_store *is = &per_cpu(the_irqsoff,
+						raw_smp_processor_id());
+
+	if (!is->ts) {
+		is->ts = sched_clock();
+		is->caddr[0] = CALLER_ADDR0;
+		is->caddr[1] = CALLER_ADDR1;
+		is->caddr[2] = CALLER_ADDR2;
+		is->caddr[3] = CALLER_ADDR3;
+	}
+#endif /* CONFIG_PREEMPTIRQ_EVENTS */
+
 	if (!preempt_trace() && irq_trace())
 		stop_critical_timing(CALLER_ADDR0, CALLER_ADDR1);
 }
 
 static inline void tracer_hardirqs_off(void)
 {
+#ifdef CONFIG_PREEMPTIRQ_EVENTS
+	struct irqsoff_store *is = &per_cpu(the_irqsoff,
+						raw_smp_processor_id());
+	u64 delta = 0;
+
+	if (is->ts) {
+		delta = sched_clock() - is->ts;
+		is->ts = 0;
+	}
+	if (delta > sysctl_irqsoff_tracing_threshold_ns)
+		trace_irqs_disable(delta, is->caddr[0], is->caddr[1],
+						is->caddr[2], is->caddr[3]);
+#endif /* CONFIG_PREEMPTIRQ_EVENTS */
+
 	if (!preempt_trace() && irq_trace())
 		start_critical_timing(CALLER_ADDR0, CALLER_ADDR1);
 }
diff --git a/net/core/dev.c b/net/core/dev.c
index 5c66140..fe1dc21 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4583,6 +4583,7 @@
 		unsigned long diffs;
 
 		NAPI_GRO_CB(p)->flush = 0;
+		NAPI_GRO_CB(p)->flush_id = 0;
 
 		if (hash != skb_get_hash_raw(p)) {
 			NAPI_GRO_CB(p)->same_flow = 0;
@@ -4674,7 +4675,6 @@
 		NAPI_GRO_CB(skb)->encap_mark = 0;
 		NAPI_GRO_CB(skb)->recursion_counter = 0;
 		NAPI_GRO_CB(skb)->is_fou = 0;
-		NAPI_GRO_CB(skb)->is_atomic = 1;
 		NAPI_GRO_CB(skb)->gro_remcsum_start = 0;
 
 		/* Setup for GRO checksum validation */
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 7d07d6b..eecad95 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -945,11 +945,15 @@
 	if (neigh_probe_enable) {
 		if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE | NUD_STALE))
 			neigh_probe(neigh);
-	} else if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
-		neigh_probe(neigh);
+		else
+			write_unlock(&neigh->lock);
 	} else {
+		if (neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) {
+			neigh_probe(neigh);
+		} else {
 out:
-		write_unlock(&neigh->lock);
+			write_unlock(&neigh->lock);
+		}
 	}
 
 	if (notify)
diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c
index d38157d..3403108 100644
--- a/net/ipc_router/ipc_router_core.c
+++ b/net/ipc_router/ipc_router_core.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
@@ -223,6 +223,25 @@
 	is_wakeup_source_allowed = flag;
 }
 
+/**
+ * is_sensor_port() - Check if the remote port is sensor service or not
+ * @rport: Pointer to the remote port.
+ *
+ * Return: true if the remote port is sensor service else false.
+ */
+static int is_sensor_port(struct msm_ipc_router_remote_port *rport)
+{
+	u32 svcid = 0;
+
+	if (rport && rport->server) {
+		svcid = rport->server->name.service;
+		if (svcid == 400 || (svcid >= 256 && svcid <= 320))
+			return true;
+	}
+
+	return false;
+}
+
 static void init_routing_table(void)
 {
 	int i;
@@ -277,7 +296,7 @@
  */
 static void skb_copy_to_log_buf(struct sk_buff_head *skb_head,
 				unsigned int pl_len, unsigned int hdr_offset,
-				u64 *log_buf)
+				unsigned char *log_buf)
 {
 	struct sk_buff *temp_skb;
 	unsigned int copied_len = 0, copy_len = 0;
@@ -356,7 +375,8 @@
 			else if (hdr->version == IPC_ROUTER_V2)
 				hdr_offset = sizeof(struct rr_header_v2);
 		}
-		skb_copy_to_log_buf(skb_head, buf_len, hdr_offset, &pl_buf);
+		skb_copy_to_log_buf(skb_head, buf_len, hdr_offset,
+				    (unsigned char *)&pl_buf);
 
 		if (port_ptr && rport_ptr && (port_ptr->type == CLIENT_PORT) &&
 		    rport_ptr->server) {
@@ -2728,7 +2748,6 @@
 	struct rr_packet *pkt = NULL;
 	struct msm_ipc_port *port_ptr;
 	struct msm_ipc_router_remote_port *rport_ptr;
-	int ret;
 
 	struct msm_ipc_router_xprt_info *xprt_info =
 		container_of(work,
@@ -2736,16 +2755,7 @@
 			     read_data);
 
 	while ((pkt = rr_read(xprt_info)) != NULL) {
-		if (pkt->length < calc_rx_header_size(xprt_info) ||
-		    pkt->length > MAX_IPC_PKT_SIZE) {
-			IPC_RTR_ERR("%s: Invalid pkt length %d\n", __func__,
-				    pkt->length);
-			goto read_next_pkt1;
-		}
 
-		ret = extract_header(pkt);
-		if (ret < 0)
-			goto read_next_pkt1;
 		hdr = &pkt->hdr;
 
 		if ((hdr->dst_node_id != IPC_ROUTER_NID_LOCAL) &&
@@ -4172,6 +4182,7 @@
 {
 	struct msm_ipc_router_xprt_info *xprt_info = xprt->priv;
 	struct msm_ipc_router_xprt_work *xprt_work;
+	struct msm_ipc_router_remote_port *rport_ptr = NULL;
 	struct rr_packet *pkt;
 	int ret;
 
@@ -4222,16 +4233,40 @@
 	if (!pkt)
 		return;
 
+	if (pkt->length < calc_rx_header_size(xprt_info) ||
+	    pkt->length > MAX_IPC_PKT_SIZE) {
+		IPC_RTR_ERR("%s: Invalid pkt length %d\n",
+			    __func__, pkt->length);
+		release_pkt(pkt);
+		return;
+	}
+
+	ret = extract_header(pkt);
+	if (ret < 0) {
+		release_pkt(pkt);
+		return;
+	}
+
 	pkt->ws_need = false;
+
+	if (pkt->hdr.type == IPC_ROUTER_CTRL_CMD_DATA)
+		rport_ptr = ipc_router_get_rport_ref(pkt->hdr.src_node_id,
+						     pkt->hdr.src_port_id);
+
 	mutex_lock(&xprt_info->rx_lock_lhb2);
 	list_add_tail(&pkt->list, &xprt_info->pkt_list);
-	if (!xprt_info->dynamic_ws) {
-		__pm_stay_awake(&xprt_info->ws);
-		pkt->ws_need = true;
-	} else {
-		if (is_wakeup_source_allowed) {
+	/* check every pkt is from SENSOR services or not and
+	 * avoid holding both edge and port specific wake-up sources
+	 */
+	if (!is_sensor_port(rport_ptr)) {
+		if (!xprt_info->dynamic_ws) {
 			__pm_stay_awake(&xprt_info->ws);
 			pkt->ws_need = true;
+		} else {
+			if (is_wakeup_source_allowed) {
+				__pm_stay_awake(&xprt_info->ws);
+				pkt->ws_need = true;
+			}
 		}
 	}
 	mutex_unlock(&xprt_info->rx_lock_lhb2);
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index f3bf1ba..90c91a7 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1362,7 +1362,6 @@
 
 	for (p = *head; p; p = p->next) {
 		struct iphdr *iph2;
-		u16 flush_id;
 
 		if (!NAPI_GRO_CB(p)->same_flow)
 			continue;
@@ -1388,34 +1387,23 @@
 
 		NAPI_GRO_CB(p)->flush |= flush;
 
-		/* We need to store of the IP ID check to be included later
-		 * when we can verify that this packet does in fact belong
-		 * to a given flow.
+		/* For non-atomic datagrams we need to save the IP ID offset
+		 * to be included later.  If the frame has the DF bit set
+		 * we must ignore the IP ID value as per RFC 6864.
 		 */
-		flush_id = (u16)(id - ntohs(iph2->id));
+		if (iph2->frag_off & htons(IP_DF))
+			continue;
 
-		/* This bit of code makes it much easier for us to identify
-		 * the cases where we are doing atomic vs non-atomic IP ID
-		 * checks.  Specifically an atomic check can return IP ID
-		 * values 0 - 0xFFFF, while a non-atomic check can only
-		 * return 0 or 0xFFFF.
+		/* We must save the offset as it is possible to have multiple
+		 * flows using the same protocol and address pairs so we
+		 * need to wait until we can validate this is part of the
+		 * same flow with a 5-tuple or better to avoid unnecessary
+		 * collisions between flows.
 		 */
-		if (!NAPI_GRO_CB(p)->is_atomic ||
-		    !(iph->frag_off & htons(IP_DF))) {
-			flush_id ^= NAPI_GRO_CB(p)->count;
-			flush_id = flush_id ? 0xFFFF : 0;
-		}
-
-		/* If the previous IP ID value was based on an atomic
-		 * datagram we can overwrite the value and ignore it.
-		 */
-		if (NAPI_GRO_CB(skb)->is_atomic)
-			NAPI_GRO_CB(p)->flush_id = flush_id;
-		else
-			NAPI_GRO_CB(p)->flush_id |= flush_id;
+		NAPI_GRO_CB(p)->flush_id |= ntohs(iph2->id) ^
+					    (u16)(id - NAPI_GRO_CB(p)->count);
 	}
 
-	NAPI_GRO_CB(skb)->is_atomic = !!(iph->frag_off & htons(IP_DF));
 	NAPI_GRO_CB(skb)->flush |= flush;
 	skb_set_network_header(skb, off);
 	/* The above will be needed by the transport layer if there is one
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c
index 366b1be..35637f1 100644
--- a/net/ipv4/tcp_offload.c
+++ b/net/ipv4/tcp_offload.c
@@ -230,7 +230,7 @@
 
 found:
 	/* Include the IP ID check below from the inner most IP hdr */
-	flush = NAPI_GRO_CB(p)->flush;
+	flush = NAPI_GRO_CB(p)->flush | NAPI_GRO_CB(p)->flush_id;
 	flush |= (__force int)(flags & TCP_FLAG_CWR);
 	flush |= (__force int)((flags ^ tcp_flag_word(th2)) &
 		  ~(TCP_FLAG_CWR | TCP_FLAG_FIN | TCP_FLAG_PSH));
@@ -239,17 +239,6 @@
 		flush |= *(u32 *)((u8 *)th + i) ^
 			 *(u32 *)((u8 *)th2 + i);
 
-	/* When we receive our second frame we can made a decision on if we
-	 * continue this flow as an atomic flow with a fixed ID or if we use
-	 * an incrementing ID.
-	 */
-	if (NAPI_GRO_CB(p)->flush_id != 1 ||
-	    NAPI_GRO_CB(p)->count != 1 ||
-	    !NAPI_GRO_CB(p)->is_atomic)
-		flush |= NAPI_GRO_CB(p)->flush_id;
-	else
-		NAPI_GRO_CB(p)->is_atomic = false;
-
 	mss = skb_shinfo(p)->gso_size;
 
 	flush |= (len - 1) >= mss;
@@ -318,9 +307,6 @@
 				  iph->daddr, 0);
 	skb_shinfo(skb)->gso_type |= SKB_GSO_TCPV4;
 
-	if (NAPI_GRO_CB(skb)->is_atomic)
-		skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_FIXEDID;
-
 	return tcp_gro_complete(skb);
 }
 
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 649f4d8..3cdf4dc 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -237,15 +237,8 @@
 		/* flush if Traffic Class fields are different */
 		NAPI_GRO_CB(p)->flush |= !!(first_word & htonl(0x0FF00000));
 		NAPI_GRO_CB(p)->flush |= flush;
-
-		/* If the previous IP ID value was based on an atomic
-		 * datagram we can overwrite the value and ignore it.
-		 */
-		if (NAPI_GRO_CB(skb)->is_atomic)
-			NAPI_GRO_CB(p)->flush_id = 0;
 	}
 
-	NAPI_GRO_CB(skb)->is_atomic = true;
 	NAPI_GRO_CB(skb)->flush |= flush;
 
 	skb_gro_postpull_rcsum(skb, iph, nlen);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 2d64e0f..0dc41fd 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -1012,6 +1012,8 @@
 	wdev->current_bss = NULL;
 	wdev->ssid_len = 0;
 	wdev->conn_owner_nlportid = 0;
+	kzfree(wdev->connect_keys);
+	wdev->connect_keys = NULL;
 
 	nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
 
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 4f6c777..b761761 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -34,6 +34,7 @@
 #include <linux/ctype.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/dma-mapping.h>
 #include <sound/core.h>
 #include <sound/jack.h>
 #include <sound/pcm.h>
@@ -2665,6 +2666,8 @@
 	if (ret != 0)
 		return ret;
 
+	arch_setup_dma_ops(card->dev, 0, 0, NULL, 0);
+
 	/* deactivate pins to sleep state */
 	list_for_each_entry(rtd, &card->rtd_list, list)  {
 		struct snd_soc_dai *cpu_dai = rtd->cpu_dai;