Merge "Merge android-4.9.112 (9e79039) into msm-4.9"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_fifo_xprt.txt b/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_fifo_xprt.txt
new file mode 100644
index 0000000..a6fd56c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_fifo_xprt.txt
@@ -0,0 +1,25 @@
+Qualcomm Technologies, Inc. IPC Router FIFO Transport
+
+Required properties:
+- compatible:	should be "qcom,ipcr_fifo_xprt"
+- reg:		the irq register to raise an interrupt
+- interrupts:	the receiving interrupt line
+- qcom,ipc-shm:	Reference to shared memory phandle
+
+Example:
+
+	fifo_vipc_irq@176 {
+		compatible = "qcom,ipcr-fifo-xprt";
+		reg = <0x176>;
+		interrupts = <0x0 0x142 0x1>;
+		qcom,ipc-shm = <&ipc-shm>;
+	};
+
+	ipc-shm: shared-buffer@85af7000 {
+		compatible = "qcom,hypervisor-shared-memory";
+		phandle = <0x1e4>;
+		reg = <0x0 0x85af7000 0x0 0x9000>;
+		label = "ipc_shm";
+		qcom,tx-is-first;
+	};
+
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt b/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt
index c5d052c..07f971e 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_ipc_router_glink_xprt.txt
@@ -19,6 +19,8 @@
 			that subsystem.
 -qcom,dynamic-wakeup-source:	Boolean property to indicate that G-Link
 				transport supports dynamic wakeup source
+-qcom,low-latency-xprt:		Boolean property to indicate that G-Link
+				transport is low latency trasport.
 
 Example:
 	qcom,ipc_router_modem_xprt {
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
index 90bc368..c4ada7c 100644
--- a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
@@ -86,7 +86,8 @@
 
 compatible devices:
 		qcom,sdm845-llcc,
-		qcom,sdm670-llcc
+		qcom,sdm670-llcc,
+		qcom,qcs605-llcc
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt b/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt
index 02dab4c..7fe9e5d 100644
--- a/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt
+++ b/Documentation/devicetree/bindings/arm/msm/rpm_stats.txt
@@ -24,10 +24,16 @@
 	Value type: <prop-encoded-array>
 	Definition: Provides labels for the reg property.
 
+- qcom,num-records:
+	Usage: optional
+	Value type: <u32>
+	Definition: Specifies number of records to read from RPM RAM.
+
 EXAMPLE:
 
 	qcom,rpm-stats@c000000 {
 		compatible = "qcom,rpm-stats";
 		reg = <0xC000000 0x1000>, <0x3F0000 0x4>;
 		reg-names = "phys_addr_base", "offset_addr";
+		qcom,num-records = <3>;
 	};
diff --git a/Documentation/devicetree/bindings/cnss/cnss-wlan.txt b/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
index ea3afc7..06a60e2 100644
--- a/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
+++ b/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
@@ -13,6 +13,7 @@
 Required properties:
   - compatible: "qcom,cnss" for QCA6174 device
                 "qcom,cnss-qca6290" for QCA6290 device
+                "qcom,cnss-qca6390" for QCA6390 device
   - wlan-en-gpio: WLAN_EN GPIO signal specified by the chip specifications
   - vdd-wlan-supply: phandle to the regulator device tree node
   - pinctrl-names: Names corresponding to the numbered pinctrl states
diff --git a/Documentation/devicetree/bindings/input/touchscreen/elants_i2c.txt b/Documentation/devicetree/bindings/input/touchscreen/elants_i2c.txt
new file mode 100644
index 0000000..3fcaaad
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/elants_i2c.txt
@@ -0,0 +1,34 @@
+Elan Ektf3xx series touch controller
+
+   Required properties:
+
+		- compatible				: Should be "elan,ekth3500"
+		- reg				        : I2C slave address of the device.
+		- interrupt-parent			: Parent of interrupt.
+		- interrupts				: Configuration of touch panel controller interrupt GPIO.
+		- elan,irq-gpio				: Interrupt gpio which is to provide interrupts to
+										host, same as "interrupts" node.It will also contain
+										active low or active high information
+
+  Optional properties:
+
+		- vdd-supply				: Power supply needed to power up the device, when use
+										external regulator, do not add this property.
+		- vccio-supply				: Power source required to power up i2c bus.
+										Ekth3500 series can provide 1.8V from internal
+										LDO, add this properties base on hardware design.
+		- reset-gpio			    : Reset gpio to control the reset of chip.
+
+  Example:
+		i2c@f9923000{
+			elan_ktf@10 {
+				compatible = "elan,ekth3500";
+				reg = <0x10>;
+				vdd-supply = <&pm8110_l19>;
+				vccio-supply = <&pm8110_l14>;
+				reset-gpio = <&msmgpio 0 GPIO_ACTIVE_LOW>;
+				interrupt-parent = <&msmgpio>;
+				interrupts = <1 0x2>;
+				elan,irq-gpio = <&tlmm 65 0x2008>;>
+			};
+		};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/git9xx/gt9xx.txt b/Documentation/devicetree/bindings/input/touchscreen/git9xx/gt9xx.txt
new file mode 100644
index 0000000..ba61a2f
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/git9xx/gt9xx.txt
@@ -0,0 +1,99 @@
+Goodix GT9xx series touch controller
+
+Required properties:
+
+ - compatible		: Should be "goodix,gt9xx"
+ - reg			: I2C slave address of the device.
+ - interrupt-parent	: Parent of interrupt.
+ - interrupts		: Configuration of touch panel controller interrupt
+				GPIO.
+ - goodix,product-id	: Product identification of the controller.
+ - interrupt-gpios	: Interrupt gpio which is to provide interrupts to
+				host, same as "interrupts" node.
+ - reset-gpios		: Reset gpio to control the reset of chip.
+ - goodix,display-coords	: Display coordinates in pixels. It is a four
+				tuple consisting of min x, min y, max x and
+				max y values.
+
+Optional properties:
+
+ - avdd-supply		: Power supply needed to power up the device, this is
+				for fixed voltage external regulator.
+ - vdd-supply		: Power supply needed to power up the device, when use
+				external regulator, do not add this property.
+ - vcc-i2c-supply	: Power source required to power up i2c bus.
+				GT9xx series can provide 1.8V from internal
+				LDO, add this properties base on hardware
+				design.
+ - goodix,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.
+ - goodix,i2c-pull-up	: To specify pull up is required.
+ - goodix,force-update	: To specify force update is allowed.
+ - goodix,enable-power-off	: Power off touchscreen during suspend.
+ - goodix,button-map	: Button map of key codes. The number of key codes
+				depend on panel.
+ - goodix,cfg-data0	: Touch screen controller config data group 0. Ask vendor
+				to provide that.
+				Driver supports maximum six config groups. If more than one
+				groups are defined, driver will select config group depending
+				on hardware configuration. If only config group 0 is defined,
+				it will be used for all hardware configurations.
+				Touch screen controller will use its onchip default config data
+				if this property is not present.
+ - goodix,cfg-data1	: Touch screen controller config data group 1. Ask vendor
+				to provide that.
+ - goodix,cfg-data2	: Touch screen controller config data group 2. Ask vendor
+				to provide that.
+ - goodix,cfg-data3	: Touch screen controller config data group 3. Ask vendor
+				to provide that.
+ - goodix,cfg-data4	: Touch screen controller config data group 4. Ask vendor
+				to provide that.
+ - goodix,cfg-data5	: Touch screen controller config data group 5. Ask vendor
+				to provide that.
+ - goodix,fw-name	: Touch screen controller firmware file name.
+ - goodix,slide-wakeup	: To specify slide-wakeup property is enabled or not.
+ - goodix,dbl-clk-wakeup	: To specify dbl-clk-wakeup property is enabled or not.
+ - goodix,change-x2y	: To specify change-x2y property is enabled or not.
+ - goodix,driver-send-cfg	: To specify driver-send-cfg property is enabled or not.
+ - goodix,have-touch-key	: To specify have-touch-key property is enabled or not.
+ - goodix,with-pen	: To specify with-pen property is enabled or not.
+Example:
+i2c@f9927000 {
+		goodix@5d {
+			compatible = "goodix,gt9xx";
+			reg = <0x5d>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <17 0x2008>;
+			reset-gpios = <&msmgpio 16 0x00>;
+			interrupt-gpios = <&msmgpio 17 0x00>;
+			avdd-supply = <&tp_power>;
+			goodix,panel-coords = <0 0 720 1200>;
+			goodix,display-coords = <0 0 720 1080>;
+			goodix,button-map= <158 102 139>;
+			goodix,product-id = "915";
+			goodix,cfg-data0 = [
+				41 D0 02 00 05 0A 05 01 01 08
+				12 58 50 41 03 05 00 00 00 00
+				00 00 00 00 00 00 00 8C 2E 0E
+				28 24 73 13 00 00 00 83 03 1D
+				40 02 00 00 00 03 64 32 00 00
+				00 1A 38 94 C0 02 00 00 00 04
+				9E 1C 00 8D 20 00 7A 26 00 6D
+				2C 00 60 34 00 60 10 38 68 00
+				F0 50 35 FF FF 27 00 00 00 00
+				00 01 1B 14 0C 14 00 00 01 00
+				00 00 00 00 00 00 00 00 00 00
+				00 00 02 04 06 08 0A 0C 0E 10
+				12 14 16 18 1A 1C FF FF FF FF
+				FF FF FF FF FF FF FF FF FF FF
+				FF FF 00 02 04 06 08 0A 0C 0F
+				10 12 13 14 16 18 1C 1D 1E 1F
+				20 21 22 24 26 28 29 2A FF FF
+				FF FF FF FF FF FF FF 22 22 22
+				22 22 22 FF 07 01];
+			goodix,fw_name = "gtp_fw.bin";
+			goodix,have-touch-key;
+			goodix,driver-send-cfg;
+		};
+};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/himax.txt b/Documentation/devicetree/bindings/input/touchscreen/himax.txt
deleted file mode 100644
index b54c859..0000000
--- a/Documentation/devicetree/bindings/input/touchscreen/himax.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-Himax touch controller
-
-Required properties:
-
- - compatible			: Should be "himax,hxcommon"
- - reg					: i2c slave address of the device.
- - interrupt-parent		: parent of interrupt.
- - himax,irq-gpio       : irq gpio.
- - himax,reset-gpio		: reset gpio.
- - vdd-supply			: Power supply needed to power up the device.
- - avdd-supply			: Power source required to power up i2c bus.
- - himax,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.
- - himax,display-coords : display coordinates in pixels. It is a four
-						  tuple consisting of min x, min y, max x and
-						  max y values
-
-Optional properties:
- - himax,3v3-gpio		: gpio acting as 3.3 v supply.
- - report_type			: Multi-touch protocol type. Default 0.
-						  0 for protocol A, 1 for protocol B.
diff --git a/Documentation/devicetree/bindings/input/touchscreen/himax_i2c_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/himax_i2c_ts.txt
new file mode 100644
index 0000000..9889f55
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/himax_i2c_ts.txt
@@ -0,0 +1,57 @@
+Himax touch controller
+
+Required properties:
+
+ - compatible	: should be "himax,hxcommon"
+ - 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.
+ - himax,irq-gpio	: irq gpio
+ - himax,reset-gpio	: reset gpio
+
+Optional property:
+ - vdd-supply		: Analog power supply needed to power device
+ - vcc_i2c-supply		: Power source required to pull up i2c bus
+ - himax,i2c-pull-up	: specify to indicate pull up is needed
+ - himax,disable-gpios	: specify to disable gpios in suspend (power saving)
+ - himax,button-map		: virtual key code mappings to be used
+ - himax,x-flip		: modify orientation of the x axis
+ - himax,y-flip		: modify orientation of the y axis
+ - himax,panel-coords	: touch panel min x, min y, max x and
+					max y resolution
+ - himax,display-coords	: display min x, min y, max x and
+					max y resolution
+ - himax,reset-delay	: reset delay for controller (ms), default 100
+ - himax,fw-image-name	: name of firmware .img file in /etc/firmware
+ - himax,power-down		: fully power down regulators in suspend
+ - himax,do-lockdown	: perform one time lockdown procedure
+
+Example:
+	i2c@f9927000 { /* BLSP1 QUP5 */
+		cell-index = <5>;
+		compatible = "himax,hxcommon";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0xf9927000 0x1000>;
+		interrupt-names = "qup_err_intr";
+		interrupts = <0 99 0>;
+		gpios = <&msmgpio 19 0>, /* SCL */
+			<&msmgpio 18 0>; /* SDA */
+		qcom,i2c-bus-freq = <100000>;
+		qcom,i2c-src-freq = <19200000>;
+
+		himax_ts@20 {
+			compatible = "himax,hxcommon"
+			reg = <0x20>;
+			interrupt-parent = <&tlmm>;
+			interrupts	= <255 0x2008>;
+			vdd-supply 	= <&pm8994_l15>;
+			avdd-supply = <&pm8994_l22>;
+			himax,panel-coords = <0 720 0 1440>;
+			himax,display-coords = <0 720 0 1440>;
+			himax,irq-gpio = <&tlmm 255 0x2008>;
+			himax,rst-gpio = <&tlmm 8 0x00>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cam-cci.txt
index cd4d222..59651a3 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-cci.txt
@@ -1,355 +1,752 @@
 * Qualcomm Technologies, Inc. MSM CCI
 
-[First level nodes]
-Required properties:
+CCI (Camera Control Interface) is module that is use for camera sensor module
+I2C communication.
+
+=======================
+Required Node Structure
+=======================
+The camera CCI node must be described in two levels of device nodes. The
+first level describe the overall CCI node structure. Second level nodes
+describe camera sensor submodule nodes which is using CCI for
+i2c communication.
+
+======================================
+First Level Node - CCI device
+======================================
+
+- compatible
+  Usage: required
+  Value type: <string>
+  Definition: Should be "qcom,cci".
+
 - cell-index: cci hardware core index
-- compatible :
-  - "qcom,cci"
-- reg : offset and length of the register set for the device
-  for the cci operating in compatible mode.
-- reg-names : should specify relevant names to each reg property defined.
-- interrupts : should contain the cci interrupt.
-- interrupt-names : should specify relevant names to each interrupts
-  property defined.
-- gpios : should contain phandle to gpio controller node and array of
-  #gpio-cells specifying specific gpio (controller specific)
-- gpio-req-tbl-num : should contain index to gpios specific to this sensor
-- gpio-req-tbl-flags : should contain direction of gpios present in
-  gpio-req-tbl-num property (in the same order)
-- gpio-req-tbl-label : should contain name of gpios present in
-  gpio-req-tbl-num property (in the same order)
-- clock-names: name of the clocks required for the device
-- clock-rates: clock rate in Hz
+  Usage: required
+  Value type: <u32>
+  Definition: Should specify the Hardware index id.
 
-Optional properties:
-- regulator-names : name of the voltage regulators required for the device.
-- gdscr-supply : should contain gdsr regulator used for cci clocks.
-- mmagic-supply : should contain mmagic regulator used for mmagic clocks.
+- reg
+  Usage: required
+  Value type: <u32>
+  Definition: offset and length of the register set
+	for the device for the cci operating in
+	compatible mode.
 
+- reg-names
+  Usage: required
+  Value type: <string>
+  Definition: Should specify relevant names to each
+	reg property defined.
+
+- interrupts
+  Usage: required
+  Value type: <u32>
+  Definition: Interrupt associated with CCI HW.
+
+- interrupt-names
+  Usage: required
+  Value type: <string>
+  Definition: Name of the interrupt.
+
+- gpios
+  Usage: required
+  Value type: <phandle>
+  Definition: should specify the gpios to be used for the CCI.
+
+- gpio-req-tbl-num
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the gpio table index.
+
+- gpio-req-tbl-flags
+  Usage: required
+  Value type: <u32>
+  Definition: should specify the gpio functions.
+
+- gpio-req-tbl-label
+  Usage: required
+  Value type: <string>
+  Definition: should specify the gpio labels in
+	gpio-req-tbl-num property (in the same order)
+
+- clock-names
+  Usage: required
+  Value type: <string>
+  Definition: List of clock names required for CCI HW.
+
+- clock-rates
+  Usage: required
+  Value type: <u32>
+  Definition: List of clock rates in Hz for CCI HW.
+
+- clock-cntl-level
+  Usage: required
+  Value type: <string>
+  Definition: All different clock level node can support.
+
+- clocks
+  Usage: required
+  Value type: <phandle>
+  Definition: all clock phandle and source clocks.
+
+- src-clock-name
+  Usage: required
+  Value type: <string>
+  Definition: name for the source clock.
+
+- regulator-names
+  Usage: required
+  Value type: <string>
+  Definition: name of the voltage regulators required for the device.
+
+- gdscr-supply
+  Usage: required
+  Value type: <phandle>
+  Definition: should contain gdsr regulator used for cci clocks.
+
+- mmagic-supply
+  Usage: optional
+  Value type: <phandle>
+  Definition: should contain mmagic regulator used for mmagic clocks.
+
+=========================
+CCI clock settings
+=========================
 - I2c speed settings (*)
-  - i2c_freq_100Khz: qcom,i2c_standard_mode - node should contain clock settings for
-    100Khz
-  - i2c_freq_400Khz: qcom,i2c_fast_mode - node should contain clock settings for
-    400Khz
-  - i2c_freq_custom: qcom,i2c_custom_mode - node can contain clock settings for
-    frequencies other than 100Khz and 400Khz which is specific to usecase.
-    Currently it has settings for 375Khz.
-  - i2c_freq_1Mhz: qcom,i2c_fast_plus_mode - node should contain clock
-    settings for 1Mhz
+  Usage: required
+  Definition: List of i2c rates for CCI HW.
+  - i2c_freq_100Khz
+    Definition: qcom,i2c_standard_mode - node should contain clock settings for
+		100Khz
+  - i2c_freq_400Khz
+    Definition: qcom,i2c_fast_mode - node should contain clock settings for
+		400Khz
+  - i2c_freq_custom
+    Definition: qcom,i2c_custom_mode - node can contain clock settings for
+		frequencies other than 100Khz and 400Khz which is specific to usecase.
+		Currently it has settings for 375Khz.
+  - i2c_freq_1Mhz
+    Definition: qcom,i2c_fast_plus_mode - node should contain clock
+		settings for 1Mhz
 * if speed settings is not defined the low level driver can use "i2c_freq_custom"
 like default
 
-[Second level nodes]
-* Qualcomm Technologies, Inc. CCI clock settings
-
-Optional properties:
-- hw-thigh : should contain high period of the SCL clock in terms of CCI clock cycle
-- hw-tlow : should contain high period of the SCL clock in terms of CCI clock cycle
-- hw-tsu-sto : should contain setup time for STOP condition
-- hw-tsu-sta : should contain setup time for Repeated START condition
-- hw-thd-dat : should contain hold time for the data
-- hw-thd-sta : should contain hold time for START condition
-- hw-tbuf : should contain free time between a STOP and a START condition
-- hw-scl-stretch-en : should contain enable or disable clock stretching
-- hw-trdhld : should contain internal hold time for SDA
-- hw-tsp : should contain filtering of glitches
-
-* Qualcomm Technologies, Inc. MSM Camera Sensor Resource Manager
-
-MSM camera sensor resource manager node contains properties of shared camera
-sensor resource.
-
-Required properties:
-- compatible : should be manufacturer name followed by sensor name
-  - "qcom,cam-res-mgr"
-Optional properties:
-- shared-gpios : should contain the gpios which are used by two or more
-  cameras, and these cameras may be opened together.
-- pinctrl-names: List of names to assign the shared pin state defined in pinctrl device node
-- pinctrl-<0..n>: Lists phandles each pointing to the pin configuration node within a pin
-  controller. These pin configurations are installed in the pinctrl device node.
-
-* Qualcomm Technologies, Inc. MSM Sensor
-
-MSM sensor node contains properties of camera sensor
-
-Required properties:
-- compatible : should be manufacturer name followed by sensor name
-  - "qcom,camera"
-- reg : should contain i2c slave address of the device
-- csiphy-sd-index : should contain csiphy instance that will used to
-  receive sensor data
-  - 0, 1, 2
-- cam_vdig-supply : should contain regulator from which digital voltage is
-  supplied
-- cam_vana-supply : should contain regulator from which analog voltage is
-  supplied
-- cam_vio-supply : should contain regulator from which IO voltage is supplied
-- regulator-names : should contain names of all regulators needed by this
-  sensor
-  - "cam_vdig", "cam_vana", "cam_vio", "cam_vaf"
-- rgltr-cntrl-support : It is booloean property. This property is required
-  if the code and regulator control parameters e.g. rgltr-min-voltage
-- rgltr-min-voltage : should contain minimum voltage level for
-  regulators mentioned in regulator-names property (in the same order)
-- rgltr-max-voltage : should contain maximum voltage level for
-  regulators mentioned in regulator-names property (in the same order)
-- rgltr-load-current : should contain optimum voltage level for regulators
-  mentioned in regulator-names property (in the same order)
-- sensor-position-roll : should contain sensor rotational angle with respect
-  to axis of reference
-  - 0, 90, 180, 360
-- sensor-position-pitch : should contain sensor rotational angle with respect
-  to axis of reference
-  - 0, 90, 180, 360
-- sensor-position-yaw : should contain sensor rotational angle  with respect
-  to axis of reference
-  - 0, 90, 180, 360
-Optional properties:
-- slave-id : should contain i2c slave address, device id address, expected
-  id read value and device id mask
-- sensor-name : should contain unique sensor name to differentiate from
-  other sensor
-  - "s5k3l1yx"
-- sensor-mode : should contain sensor mode supported
-  - 0 -> back camera 2D
-  - 1 -> front camera 2D
-  - 2 -> back camera 3D
-  - 3 -> back camera int 3D
-- sensor-type : should contain format of data that sensor streams
-  - 0 -> bayer format
-  - 1 -> yuv format
-- qcom,secure : should be enabled to operate the camera in secure mode
-  - 0, 1
-- gpio-no-mux : should contain field to indicate whether gpio mux table is
-  available
-  - 1 if gpio mux is not available, 0 otherwise
-- cam_vaf-supply : should contain regulator from which AF voltage is supplied
-- gpios : should contain phandle to gpio controller node and array of
-    #gpio-cells specifying specific gpio (controller specific)
-- gpio-reset : should contain index to gpio used by sensors reset_n
-- gpio-standby : should contain index to gpio used by sensors standby_n
-- gpio-vio : should contain index to gpio used by sensors io vreg enable
-- gpio-vana : should contain index to gpio used by sensors analog vreg enable
-- gpio-vdig : should contain index to gpio used by sensors digital vreg enable
-- gpio-vaf : should contain index to gpio used by sensors af vreg enable
-- gpio-af-pwdm : should contain index to gpio used by sensors af pwdm_n
-- gpio-req-tbl-num : should contain index to gpios specific to this sensor
-- gpio-req-tbl-flags : should contain direction of gpios present in
-  gpio-req-tbl-num property (in the same order)
-- gpio-req-tbl-label : should contain name of gpios present in
-  gpio-req-tbl-num property (in the same order)
-- gpio-set-tbl-num : should contain index of gpios that need to be
-  configured by msm
-- gpio-set-tbl-flags : should contain value to be configured for the gpios
-  present in gpio-set-tbl-num property (in the same order)
-- gpio-set-tbl-delay : should contain amount of delay after configuring
-  gpios as specified in gpio_set_tbl_flags property (in the same order)
-- csi-phy-sel : should contain CSIPHY core instance from which CSID should
-  receive data
-- actuator-cam-name : should contain actuator cam name associated with
-  this sensor
-  - If actuator does not exist, this property should not be initialized
-  - If actuator exist, this field should indicate the index of actuator to
-    be used
-- qcom,actuator-vcm-pwd : should contain the gpio pin of vcm power to be enabled
-  for actuator
-- qcom,actuator-vcm-enable : should contain value to be set for actuator vcm
-  gpio
-- sensor-position : should contain the mount angle of the camera sensor
-  - 0 -> back camera
-  - 1 -> front camera
-- cci-master : should contain i2c master id to be used for this camera
-  sensor
-  - 0 -> MASTER 0
-  - 1 -> MASTER 1
-- actuator-src : if auto focus is supported by this sensor, this
-  property should contain phandle of respective actuator node
-- led-flash-src : if LED flash is supported by this sensor, this
-  property should contain phandle of respective LED flash node
-- qcom,vdd-cx-supply : should contain regulator from which cx voltage is
-  supplied
-- qcom,vdd-cx-name : should contain names of cx regulator
-- eeprom-src : if eeprom memory is supported by this sensor, this
-  property should contain phandle of respective eeprom nodes
-- ois-src : if optical image stabilization is supported by this sensor,
-  this property should contain phandle of respective ois node
-- ir-led-src : if ir led is supported by this sensor, this property
-  should contain phandle of respective ir-led node
-- qcom,ir-cut-src : if ir cut is supported by this sensor, this property
-  should contain phandle of respective ir-cut node
-- qcom,special-support-sensors: if only some special sensors are supported
-  on this board, add sensor name in this property.
-- use-shared-clk : It is booloean property. This property is required
-  if the clk is shared clk between different sensor and ois, if this
-  device need to be opened together.
-- clock-rates: clock rate in Hz.
-- clock-cntl-level: says what all different cloc level node has.
-- clock-cntl-support: Says whether clock control support is present or not
-- clock-control: The valid fields are "NO_SET_RATE", "INIT_RATE" and
-  "SET_RATE". "NO_SET_RATE" the corresponding clock is enabled without setting
-  the rate assuming some other driver has already set it to appropriate rate.
-  "INIT_RATE" clock rate is not queried assuming some other driver has set
-  the clock rate and ispif will set the the clock to this rate.
-  "SET_RATE" clock is enabled and the rate is set to the value specified
-  in the property clock-rates.
-
-* Qualcomm Technologies, Inc. MSM ACTUATOR
-
-Required properties:
-- cell-index : should contain unique identifier to differentiate
-  between multiple actuators
-- reg : should contain i2c slave address of the actuator and length of
-  data field which is 0x0
-- compatible :
-  - "qcom,actuator"
-- cci-master : should contain i2c master id to be used for this camera
-  sensor
-  - 0 -> MASTER 0
-  - 1 -> MASTER 1
-Optional properties:
-- regulator-names : should contain names of all regulators needed by this
-  actuator
-  - "cam_vaf"
-- rgltr-cntrl-support : It is booloean property. This property is required
-  if the code and regulator control parameters e.g. rgltr-min-voltage
-- rgltr-min-voltage : should contain minimum voltage level in mcrovolts
-  for regulators mentioned in regulator-names property (in the same order)
-- rgltr-max-voltage : should contain maximum voltage level in mcrovolts
-  for regulators mentioned in regulator-names property (in the same order)
-- rgltr-load-current : should contain the maximum current in microamps
-  required from the regulators mentioned in the regulator-names property
-  (in the same order).
-- cam_vaf-supply : should contain regulator from which AF voltage is supplied
-
-* Qualcomm Technologies, Inc. MSM OIS
-
-Required properties:
-- cell-index : should contain unique identifier to differentiate
-  between multiple ois drivers
-- reg : should contain i2c slave address of the ois and length of
-  data field which is 0x0
-- compatible :
-  - "qcom,ois"
-- cci-master : should contain i2c master id to be used for this camera
-  sensor
-  - 0 -> MASTER 0
-  - 1 -> MASTER 1
-- clock-rates: clock rate in Hz.
-
-Optional properties:
-- regulator-names : should contain names of all regulators needed by this
-  ois
-  - "cam_vaf"
-- rgltr-cntrl-support : It is booloean property. This property is required
-  if the code and regulator control parameters e.g. rgltr-min-voltage
-- rgltr-min-voltage : should contain minimum voltage level in mcrovolts
-  for regulators mentioned in regulator-names property (in the same order)
-- rgltr-max-voltage : should contain maximum voltage level in mcrovolts
-  for regulators mentioned in regulator-names property (in the same order)
-- rgltr-load-current : should contain the maximum current in microamps
-  required from the regulators mentioned in the regulator-names property
-  (in the same order).
-- cam_vaf-supply : should contain regulator from which ois voltage is supplied
-- use-shared-clk : It is booloean property. This property is required
-  if the clk is shared clk between different sensor and ois, if this
-  device need to be opened together.
+  - hw-thigh
+    Definition: should contain high period of the SCL clock in terms of CCI clock cycle
+  - hw-tlow
+    Definition: should contain high period of the SCL clock in terms of CCI clock cycle
+  - hw-tsu-sto
+    Definition: should contain setup time for STOP condition
+  - hw-tsu-sta
+    Definition: should contain setup time for Repeated START condition
+  - hw-thd-dat
+    Definition: should contain hold time for the data
+  - hw-thd-sta
+    Definition: should contain hold time for START condition
+  - hw-tbuf
+    Definition: should contain free time between a STOP and a START condition
+  - hw-scl-stretch-en
+    Definition: should contain enable or disable clock stretching
+  - hw-trdhld
+    Definition: should contain internal hold time for SDA
+  - hw-tsp
+    Definition: should contain filtering of glitches
 
 Example:
 
-led_flash0: qcom,camera-flash@0 {
-    cell-index = <0>;
-    compatible = "qcom,camera-flash";
-    flash-source = <&pmi8994_flash0 &pmi8994_flash1>;
-    torch-source = <&pmi8998_torch0 &pmi8998_torch1>;
-    switch-source = <&pmi8998_switch>;
-    status = "ok";
-}
+	qcom,cci@0xfda0c000 {
+		cell-index = <0>;
+		compatible = "qcom,cci";
+		reg = <0xfda0c000 0x300>;
+		reg-names = "cci";
+		interrupts = <0 50 0>;
+		interrupt-names = "cci";
+		clock-names = "camnoc_axi_clk", "soc_ahb_clk",
+		"slow_ahb_src_clk", "cpas_ahb_clk",
+		"cci_clk", "cci_clk_src";
+		clock-rates = <0 0 80000000 0 0 37500000>;
+		clock-cntl-level = "turbo";
+		gpios = <&tlmm 17 0>,
+			   <&tlmm 18 0>,
+			   <&tlmm 19 0>,
+			   <&tlmm 20 0>;
+		gpio-tbl-num = <0 1 2 3>;
+		gpio-tbl-flags = <1 1 1 1>;
+		gpio-tbl-label = "CCI_I2C_DATA0",
+				"CCI_I2C_CLK0",
+				"CCI_I2C_DATA1",
+				"CCI_I2C_CLK1";
+		i2c_freq_100Khz: qcom,i2c_standard_mode {
+			 hw-thigh = <78>;
+			 hw-tlow = <114>;
+			 hw-tsu-sto = <28>;
+			 hw-tsu-sta = <28>;
+			 hw-thd-dat = <10>;
+			 hw-thd-sta = <77>;
+			 hw-tbuf = <118>;
+			 hw-scl-stretch-en = <0>;
+			 hw-trdhld = <6>;
+			 hw-tsp = <1>;
+			 status = "ok";
+		};
+		i2c_freq_400Khz: qcom,i2c_fast_mode {
+			 hw-thigh = <20>;
+			 hw-tlow = <28>;
+			 hw-tsu-sto = <21>;
+			 hw-tsu-sta = <21>;
+			 hw-thd-dat = <13>;
+			 hw-thd-sta = <18>;
+			 hw-tbuf = <25>;
+			 hw-scl-stretch-en = <0>;
+			 hw-trdhld = <6>;
+			 hw-tsp = <3>;
+			 status = "ok";
+		};
+		i2c_freq_custom: qcom,i2c_custom_mode {
+			 hw-thigh = <15>;
+			 hw-tlow = <28>;
+			 hw-tsu-sto = <21>;
+			 hw-tsu-sta = <21>;
+			 hw-thd-dat = <13>;
+			 hw-thd-sta = <18>;
+			 hw-tbuf = <25>;
+			 hw-scl-stretch-en = <1>;
+			 hw-trdhld = <6>;
+			 hw-tsp = <3>;
+			 status = "ok";
+		};
+		i2c_freq_1Mhz: qcom,i2c_fast_plus_mode {
+			 hw-thigh = <16>;
+			 hw-tlow = <22>;
+			 hw-tsu-sto = <17>;
+			 hw-tsu-sta = <18>;
+			 hw-thd-dat = <16>;
+			 hw-thd-sta = <15>;
+			 hw-tbuf = <19>;
+			 hw-scl-stretch-en = <1>;
+			 hw-trdhld = <3>;
+			 hw-tsp = <3>;
+			 cci-clk-src = <37500000>;
+			 status = "ok";
+		};
+	};
 
-qcom,cci@0xfda0c000 {
-    cell-index = <0>;
-    compatible = "qcom,cci";
-    reg = <0xfda0c000 0x300>;
-    reg-names = "cci";
-    interrupts = <0 50 0>;
-    interrupt-names = "cci";
-    clock-names = "camnoc_axi_clk", "soc_ahb_clk",
-	"slow_ahb_src_clk", "cpas_ahb_clk",
-	"cci_clk", "cci_clk_src";
-    clock-rates = <0 0 80000000 0 0 37500000>;
-	clock-cntl-level = "turbo";
-    gpios = <&tlmm 17 0>,
-           <&tlmm 18 0>,
-           <&tlmm 19 0>,
-           <&tlmm 20 0>;
-    gpio-tbl-num = <0 1 2 3>;
-    gpio-tbl-flags = <1 1 1 1>;
-    gpio-tbl-label = "CCI_I2C_DATA0",
-                    "CCI_I2C_CLK0",
-                    "CCI_I2C_DATA1",
-                    "CCI_I2C_CLK1";
-    i2c_freq_100Khz: qcom,i2c_standard_mode {
-         hw-thigh = <78>;
-         hw-tlow = <114>;
-         hw-tsu-sto = <28>;
-         hw-tsu-sta = <28>;
-         hw-thd-dat = <10>;
-         hw-thd-sta = <77>;
-         hw-tbuf = <118>;
-         hw-scl-stretch-en = <0>;
-         hw-trdhld = <6>;
-         hw-tsp = <1>;
-         status = "ok";
-    };
-    i2c_freq_400Khz: qcom,i2c_fast_mode {
-         hw-thigh = <20>;
-         hw-tlow = <28>;
-         hw-tsu-sto = <21>;
-         hw-tsu-sta = <21>;
-         hw-thd-dat = <13>;
-         hw-thd-sta = <18>;
-         hw-tbuf = <25>;
-         hw-scl-stretch-en = <0>;
-         hw-trdhld = <6>;
-         hw-tsp = <3>;
-         status = "ok";
-    };
-    i2c_freq_custom: qcom,i2c_custom_mode {
-         hw-thigh = <15>;
-         hw-tlow = <28>;
-         hw-tsu-sto = <21>;
-         hw-tsu-sta = <21>;
-         hw-thd-dat = <13>;
-         hw-thd-sta = <18>;
-         hw-tbuf = <25>;
-         hw-scl-stretch-en = <1>;
-         hw-trdhld = <6>;
-         hw-tsp = <3>;
-         status = "ok";
-    };
-    i2c_freq_1Mhz: qcom,i2c_fast_plus_mode {
-         hw-thigh = <16>;
-         hw-tlow = <22>;
-         hw-tsu-sto = <17>;
-         hw-tsu-sta = <18>;
-         hw-thd-dat = <16>;
-         hw-thd-sta = <15>;
-         hw-tbuf = <19>;
-         hw-scl-stretch-en = <1>;
-         hw-trdhld = <3>;
-         hw-tsp = <3>;
-         cci-clk-src = <37500000>;
-         status = "ok";
-    };
+=======================================
+Second Level Node - CAM SENSOR MODULES
+=======================================
 
+=======================================
+CAM SENSOR RESOURCE MANAGER
+=======================================
+Camera Sensor Resource manager node contains properties of shared camera
+sensor resource.
+
+- compatible
+  Usage: required
+  Value type: <string>
+  Definition: Should be "qcom,cam-res-mgr".
+
+- shared-gpios
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain the gpios which are used by two or more
+	cameras, and these cameras may be opened together.
+
+- pinctrl-names
+  Usage: optional
+  Value type: <string>
+  Definition: List of names to assign the shared pin state defined in pinctrl device node
+
+- pinctrl-<0..n>
+  Usage: optional
+  Value type: <phandle>
+  Definition: Lists phandles each pointing to the pin configuration node within a pin
+	controller. These pin configurations are installed in the pinctrl device node.
+
+
+=============================
+CAMERA IMAGE SENSOR MODULE
+=============================
+Image sensor node contains properties of camera image sensor
+
+- compatible
+  Usage: required
+  Value type: <string>
+  Definition: Should be "qcom,cam-sensor".
+
+- cell-index: cci hardware core index
+  Usage: required
+  Value type: <u32>
+  Definition: Should specify the Hardware index id.
+
+- reg
+  Usage: required
+  Value type: <u32>
+  Definition: offset and length of the register set
+	for the device for the cci operating in
+	compatible mode.
+
+- cci-device
+  Usage: required
+  Value type: <u32>
+  Definition: should contain i2c device id to be used for this camera
+	sensor
+
+- cci-master
+  Usage: required
+  Value type: <u32>
+  Definition: should contain i2c master id to be used for this camera
+	sensor
+	- 0 -> MASTER 0
+	- 1 -> MASTER 1
+
+- csiphy-sd-index
+  Usage: required
+  Value type: <u32>
+  Definition: should contain csiphy instance that will used to
+	receive sensor data (0, 1, 2, 3).
+
+- cam_vdig-supply
+  Usage: required
+  Value type: <phandle>
+  Definition: should contain regulator from which digital voltage is
+	supplied
+
+- cam_vana-supply
+  Usage: required
+  Value type: <phandle>
+  Definition: should contain regulator from which analog voltage is
+	supplied
+
+- cam_vio-supply
+  Usage: required
+  Value type: <phandle>
+  Definition: should contain regulator from which IO voltage is supplied
+
+- cam_bob-supply
+  Usage: optional
+  Value type: <phandle>
+  Definition: should contain regulator from which BoB voltage is supplied
+
+- regulator-names
+  Usage: required
+  Value type: <string>
+  Definition: should contain names of all regulators needed by this
+	sensor
+
+- rgltr-cntrl-support
+  Usage: required
+  Value type: <boolean>
+  Definition: This property is required if the sw control regulator parameters
+	e.g. rgltr-min-voltage
+
+- rgltr-min-voltage
+  Usage: required
+  Value type: <u32>
+  Definition: should contain minimum voltage level for regulators mentioned
+	in regulator-names property (in the same order)
+
+- rgltr-max-voltage
+  Usage: required
+  Value type: <u32>
+  Definition: should contain maximum voltage level for regulators mentioned
+	in regulator-names property (in the same order)
+
+- rgltr-load-current
+  Usage: required
+  Value type: <u32>
+  Definition: should contain optimum voltage level for regulators mentioned
+	in regulator-names property (in the same order)
+
+- sensor-position-roll
+  Usage: required
+  Value type: <u32>
+  Definition: should contain sensor rotational angle with respect to axis of
+	reference. i.e. 0, 90, 180, 360
+
+- sensor-position-pitch
+  Usage: required
+  Value type: <u32>
+  Definition: should contain sensor rotational angle with respect to axis of
+	reference. i.e. 0, 90, 180, 360
+
+- sensor-position-yaw
+  Usage: required
+  Value type: <u32>
+  Definition: should contain sensor rotational angle  with respect to axis of
+	reference. i.e. 0, 90, 180, 360
+
+- qcom,secure
+  Usage: optional
+  Value type: <u32>
+  Definition: should be enabled to operate the camera in secure mode
+
+- gpio-no-mux
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain field to indicate whether gpio mux table is
+	available. i.e. 1 if gpio mux is not available, 0 otherwise
+
+- cam_vaf-supply
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain regulator from which AF voltage is supplied
+
+- pwm-switch
+  Usage: optional
+  Value type: <boolean>
+  Definition: This property is required for regulator to switch into PWM mode.
+
+- gpios
+  Usage: required
+  Value type: <phandle>
+  Definition: should contain phandle to gpio controller node and array of
+	#gpio-cells specifying specific gpio (controller specific)
+
+- gpio-reset
+  Usage: required
+  Value type: <u32>
+  Definition: should contain index to gpio used by sensors reset_n
+
+- gpio-standby
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain index to gpio used by sensors standby_n
+
+- gpio-vio
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain index to gpio used by sensors io vreg enable
+
+- gpio-vana
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain index to gpio used by sensors analog vreg enable
+
+- gpio-vdig
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain index to gpio used by sensors digital vreg enable
+
+- gpio-vaf
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain index to gpio used by sensors af vreg enable
+
+- gpio-af-pwdm
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain index to gpio used by sensors af pwdm_n
+
+- gpio-req-tbl-num
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain index to gpios specific to this sensor
+
+- gpio-req-tbl-flags
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain direction of gpios present in
+	gpio-req-tbl-num property (in the same order)
+
+- gpio-req-tbl-label
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain name of gpios present in
+	gpio-req-tbl-num property (in the same order)
+
+- gpio-set-tbl-num
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain index of gpios that need to be
+	configured by msm
+
+- gpio-set-tbl-flags
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain value to be configured for the gpios
+	present in gpio-set-tbl-num property (in the same order)
+
+- gpio-set-tbl-delay
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain amount of delay after configuring
+	gpios as specified in gpio_set_tbl_flags property (in the same order)
+
+- actuator-src
+  Usage: optional
+  Value type: <phandle>
+  Definition: if auto focus is supported by this sensor, this
+	property should contain phandle of respective actuator node
+
+- led-flash-src
+  Usage: optional
+  Value type: <phandle>
+  Definition: if LED flash is supported by this sensor, this
+	property should contain phandle of respective LED flash node
+
+- qcom,vdd-cx-supply
+  Usage: optional
+  Value type: <phandle>
+  Definition: should contain regulator from which cx voltage is supplied
+
+- qcom,vdd-cx-name
+  Usage: optional
+  Value type: <string>
+  Definition: should contain names of cx regulator
+
+- eeprom-src
+  Usage: optional
+  Value type: <phandle>
+  Definition: if eeprom memory is supported by this sensor, this
+	property should contain phandle of respective eeprom nodes
+
+- ois-src
+  Usage: optional
+  Value type: <phandle>
+  Definition: if optical image stabilization is supported by this sensor,
+	this property should contain phandle of respective ois node
+
+- ir-led-src
+  Usage: optional
+  Value type: <phandle>
+  Definition: if ir led is supported by this sensor, this property
+	should contain phandle of respective ir-led node
+
+- qcom,ir-cut-src
+  Usage: optional
+  Value type: <phandle>
+  Definition: if ir cut is supported by this sensor, this property
+	should contain phandle of respective ir-cut node
+
+- qcom,special-support-sensors
+  Usage: required
+  Value type: <string>
+  Definition: if only some special sensors are supported
+	on this board, add sensor name in this property.
+
+- use-shared-clk
+  Usage: optional
+  Value type: <boolean>
+  Definition: It is booloean property. This property is required
+	if the clk is shared clk between different sensor and ois, if this
+	device need to be opened together.
+
+- clock-rates
+  Usage: required
+  Value type: <u32>
+  Definition: clock rate in Hz.
+
+- clock-cntl-level
+  Usage: required
+  Value type: <string>
+  Definition: All different clock level node can support.
+
+- clock-cntl-support
+  Usage: optional
+  Value type: <boolean>
+  Definition: Says whether clock control support is present or not
+
+- clocks
+  Usage: required
+  Value type: <phandle>
+  Definition: all clock phandle and source clocks.
+
+- clock-control
+  Usage: optional
+  Value type: <string>
+  Definition: The valid fields are "NO_SET_RATE", "INIT_RATE" and
+	"SET_RATE". "NO_SET_RATE" the corresponding clock is enabled without setting
+	the rate assuming some other driver has already set it to appropriate rate.
+	"INIT_RATE" clock rate is not queried assuming some other driver has set
+	the clock rate and ispif will set the the clock to this rate.
+	"SET_RATE" clock is enabled and the rate is set to the value specified
+	in the property clock-rates.
+
+=============================
+ACTUATOR MODULE
+=============================
+
+- compatible
+  Usage: required
+  Value type: <string>
+  Definition: Should be "qcom,actuator".
+
+- cell-index: cci hardware core index
+  Usage: required
+  Value type: <u32>
+  Definition: Should specify the Hardware index id.
+
+- reg
+  Usage: required
+  Value type: <u32>
+  Definition: offset and length of the register set
+	for the device for the cci operating in
+	compatible mode.
+
+- cci-device
+  Usage: required
+  Value type: <u32>
+  Definition: should contain i2c device id to be used for this camera
+	sensor
+
+- cci-master
+  Usage: required
+  Value type: <u32>
+  Definition: should contain i2c master id to be used for this camera
+	sensor
+	- 0 -> MASTER 0
+	- 1 -> MASTER 1
+
+- cam_vaf-supply
+  Usage: required
+  Value type: <phandle>
+  Definition: should contain regulator from which AF voltage is supplied
+
+- regulator-names
+  Usage: required
+  Value type: <string>
+  Definition: should contain names of all regulators needed by this
+	actuator. i.e. "cam_vaf"
+
+- rgltr-cntrl-support
+  Usage: optional
+  Value type: <boolean>
+  Definition: It is booloean property. This property is required
+	if the code and regulator control parameters e.g. rgltr-min-voltage
+
+- rgltr-min-voltage
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain minimum voltage level in mcrovolts
+	for regulators mentioned in regulator-names property (in the same order)
+
+- rgltr-max-voltage
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain maximum voltage level in mcrovolts
+	for regulators mentioned in regulator-names property (in the same order)
+
+- rgltr-load-current
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain the maximum current in microamps
+	required from the regulators mentioned in the regulator-names property
+	(in the same order).
+
+=============================
+OIS MODULE
+=============================
+
+- compatible
+  Usage: required
+  Value type: <string>
+  Definition: Should be "qcom,ois".
+
+- cell-index: cci hardware core index
+  Usage: required
+  Value type: <u32>
+  Definition: Should specify the Hardware index id.
+
+- reg
+  Usage: required
+  Value type: <u32>
+  Definition: offset and length of the register set
+	for the device for the cci operating in
+	compatible mode.
+
+- cci-device
+  Usage: required
+  Value type: <u32>
+  Definition: should contain i2c device id to be used for this camera
+	sensor
+
+- cci-master
+  Usage: required
+  Value type: <u32>
+  Definition: should contain i2c master id to be used for this camera
+	sensor
+	- 0 -> MASTER 0
+	- 1 -> MASTER 1
+
+- cam_vaf-supply
+  Usage: required
+  Value type: <phandle>
+  Definition: should contain regulator from which AF voltage is supplied
+
+- regulator-names
+  Usage: required
+  Value type: <string>
+  Definition: should contain names of all regulators needed by this
+	actuator. i.e. "cam_vaf"
+
+- rgltr-cntrl-support
+  Usage: optional
+  Value type: <boolean>
+  Definition: It is booloean property. This property is required
+	if the code and regulator control parameters e.g. rgltr-min-voltage
+
+- rgltr-min-voltage
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain minimum voltage level in mcrovolts
+	for regulators mentioned in regulator-names property (in the same order)
+
+- rgltr-max-voltage
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain maximum voltage level in mcrovolts
+	for regulators mentioned in regulator-names property (in the same order)
+
+- rgltr-load-current
+  Usage: optional
+  Value type: <u32>
+  Definition: should contain the maximum current in microamps
+	required from the regulators mentioned in the regulator-names property
+	(in the same order).
+
+- use-shared-clk
+  Usage: optional
+  Value type: <boolean>
+  Definition: This property is required if the clk is shared clk between different
+	sensor and ois, if this device need to be opened together.
+
+Example:
+&soc {
+    led_flash0: qcom,camera-flash@0 {
+         cell-index = <0>;
+         compatible = "qcom,camera-flash";
+         flash-source = <&pmi8994_flash0 &pmi8994_flash1>;
+         torch-source = <&pmi8998_torch0 &pmi8998_torch1>;
+         switch-source = <&pmi8998_switch>;
+         status = "ok";
+    };
+};
+
+&cam_cci0 {
     actuator0: qcom,actuator@0 {
          cell-index = <0>;
          reg = <0x0>;
          compatible = "qcom,actuator";
+         cci-device = <0>;
          cci-master = <0>;
          cam_vaf-supply = <&pmi8998_bob>;
          regulator-names = "cam_vaf";
-	 rgltr-cntrl-support;
+         rgltr-cntrl-support;
+         rgltr-min-voltage = <2800000>;
+         rgltr-max-voltage = <2800000>;
+         rgltr-load-current = <100000>;
+    };
+
+	ois0: qcom,ois@0 {
+         cell-index = <0>;
+         reg = <0x0>;
+         compatible = "qcom,ois";
+         cci-device = <0>;
+         cci-master = <0>;
+         cam_vaf-supply = <&pmi8998_bob>;
+         regulator-names = "cam_vaf";
+         rgltr-cntrl-support;
          rgltr-min-voltage = <2800000>;
          rgltr-max-voltage = <2800000>;
          rgltr-load-current = <100000>;
@@ -375,15 +772,20 @@
          secure = <1>;
          led-flash-src = <&led_flash0>;
          actuator-src = <&actuator0>;
+         ois-src = <&ois0>;
          eeprom-src = <&eeprom0>;
-         cam_vdig-supply = <&pm845_s3>;
-         cam_vio-supply = <&pm845_lvs1>;
-         cam_vana-supply = <&pmi8998_bob>;
-         regulator-names = "cam_vdig", "cam_vio", "cam_vana";
+         cam_vdig-supply = <&pm8009_l2>;
+         cam_vio-supply = <&pm8009l_l1>;
+         cam_vana-supply = <&pm8009l_l5>;
+         cam_bob-supply = <&pm8150l_bob>;
+         cam_clk-supply = <&tital_top_gdsc>;
+         regulator-names = "cam_vio", "cam_vana", "cam_vdig",
+                "cam_clk", "cam_bob";
          rgltr-cntrl-support;
-         rgltr-min-voltage = <0 3312000 1352000>;
-         rgltr-max-voltage = <0 3312000 1352000>;
-         rgltr-load-current = <0 80000 105000>;
+         pwm-switch;
+         rgltr-min-voltage = <0 2800000 1200000 0 3008000>;
+         rgltr-max-voltage = <0 2800000 1200000 0 4000000>;
+         rgltr-load-current = <0 80000 1200000 0 2000000>;
          gpio-no-mux = <0>;
          pinctrl-names = "cam_default", "cam_suspend";
          pinctrl-0 = <&cam_sensor_mclk0_active
@@ -402,12 +804,14 @@
                          "CAM_VANA";
          sensor-position = <0>;
          sensor-mode = <0>;
+         cci-device = <0>;
          cci-master = <0>;
          status = "ok";
          use-shared-clk;
          clocks = <&clock_mmss clk_mclk0_clk_src>,
                <&clock_mmss clk_camss_mclk0_clk>;
          clock-names = "cam_src_clk", "cam_clk";
-		 clock-cntl-level;
+         clock-cntl-leveli = "turbo";
+         clock-rates = <24000000>;
     };
 };
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-fd.txt b/Documentation/devicetree/bindings/media/video/msm-cam-fd.txt
index c47cb34..b968530 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-fd.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-fd.txt
@@ -108,6 +108,11 @@
   Value type: <string>
   Definition: Source clock name.
 
+- clock-control-debugfs
+  Usage: optional
+  Value type: <string>
+  Definition: Enable/Disable clk rate control.
+
 - clock-cntl-level
   Usage: required
   Value type: <string>
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-icp.txt b/Documentation/devicetree/bindings/media/video/msm-cam-icp.txt
index ffc0e96..1495881 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-icp.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-icp.txt
@@ -110,6 +110,11 @@
   Value type: <string>
   Definition: Source clock name.
 
+- clock-control-debugfs
+  Usage: optional
+  Value type: <string>
+  Definition: Enable/Disable clk rate control.
+
 - clocks
   Usage: required
   Value type: <phandle>
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt b/Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt
index f9a5e0f..29ea987 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-ife-csid.txt
@@ -73,7 +73,10 @@
   Value type: <string>
   Definition: Source clock name.
 
-
+- clock-control-debugfs
+  Usage: optional
+  Value type: <string>
+  Definition: Enable/Disable clk rate control.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt b/Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt
index 99f2c7a..f156cc6 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-vfe.txt
@@ -91,6 +91,11 @@
   Value type: <u32>
   Definition: List of clocks rates for optional clocks.
 
+- clock-control-debugfs
+  Usage: optional
+  Value type: <string>
+  Definition: Enable/Disable clk rate control.
+
 Example:
 	qcom,vfe0@acaf000 {
 		cell-index = <0>;
diff --git a/Documentation/devicetree/bindings/net/qcom-ssdk.txt b/Documentation/devicetree/bindings/net/qcom-ssdk.txt
index b72215d..9624edb 100644
--- a/Documentation/devicetree/bindings/net/qcom-ssdk.txt
+++ b/Documentation/devicetree/bindings/net/qcom-ssdk.txt
@@ -21,15 +21,15 @@
 	compatible = "qcom,ess-switch-qca83xx";
 	qcom,switch-access-mode = "mdio";
 	qcom,ar8327-initvals = <
-		0x0000c 0x7600000   /* PAD6_MODE */
+		0x00004 0x7600000   /* PAD0_MODE */
 		0x00008 0x0         /* PAD5_MODE */
 		0x000e4 0xaa545     /* MAC_POWER_SEL */
 		0x000e0 0xc74164de  /* SGMII_CTRL */
 		0x0007c 0x4e        /* PORT0_STATUS */
 		0x00094 0x4e        /* PORT6_STATUS */
 	>;
-	qcom,link-intr-gpio = <2>;
-	qcom,switch-cpu-bmp = <0x40>;    /* cpu port bitmap */
+	qcom,link-intr-gpio = <84>;
+	qcom,switch-cpu-bmp = <0x01>;    /* cpu port bitmap */
 	qcom,switch-lan-bmp = <0x3e>;    /* lan port bitmap */
 	qcom,switch-wan-bmp = <0x0>;     /* wan port bitmap */
 };
diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt
index 917c2d0..7652aa4 100644
--- a/Documentation/devicetree/bindings/platform/msm/ipa.txt
+++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt
@@ -87,6 +87,8 @@
                                 need to be unlocked by TZ.
 - qcom,ipa-uc-monitor-holb:   	Boolean context flag to indicate whether
                                 monitoring of holb via IPA uc is required.
+- qcom,wlan-ce-db-over-pcie: Boolean context flag to represent WLAN CE DB
+				over pcie bus or not.
 
 IPA pipe sub nodes (A2 static pipes configurations):
 
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 3d054f3..cc4a38a 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
@@ -296,6 +296,17 @@
 		    This should be defined in the ascending order and in the
 		    range of 0-100. Array limit is set to 3.
 
+- qcom,ki-coeff-low-dischg
+	Usage:      optional
+	Value type: <prop-encoded-array>
+	Definition: Array of ki coefficient values for low discharge current
+		    during discharge. These values will be applied when the
+		    monotonic SOC goes below the SOC threshold specified under
+		    qcom,ki-coeff-soc-dischg. Array limit is set to 3. This
+		    property should be specified if qcom,ki-coeff-soc-dischg
+		    is specified to make it fully functional. Value has no
+		    unit. Allowed range is 0 to 62200 in micro units.
+
 - qcom,ki-coeff-med-dischg
 	Usage:      optional
 	Value type: <prop-encoded-array>
@@ -325,13 +336,6 @@
 		    discharging. If not specified, a value of 0 will be set.
 		    Allowed range is from 245 to 62256.
 
-- qcom,ki-coeff-low-dischg
-	Usage:      optional
-	Value type: <u32>
-	Definition: Ki coefficient value for low discharge current during
-		    discharging. Value has no unit. Allowed range is 0-62200
-		    in micro units.
-
 - qcom,ki-coeff-hi-chg
 	Usage:      optional
 	Value type: <u32>
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
index 0da71a3..83f964d 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
@@ -295,6 +295,13 @@
 		    attempted by QG. If not defined the value defaults
 		    to 10%.
 
+- qcom,esr-chg-min-ibat-ua
+	Usage:      optional
+	Value type: <int>
+	Definition: Minimun charge current (IBAT) in uA at which ESR will
+		    be attempted. If not specified the default value is
+		    in -450mA.
+
 - qcom,qg-ext-sns
 	Usage:      optional
 	Value type: <bool>
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
index 8ee2749..2c26743 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
@@ -107,6 +107,27 @@
 		then charge inhibit will be disabled by default.
 		Allowed values are: 50, 100, 200, 300.
 
+- qcom,chg-term-src
+  Usage:      optional
+  Value type: <u32>
+  Definition: Specify either the ADC or analog comparators to be used in order
+		to set threshold values for charge termination current.
+		0 - Unspecified
+		1 - Select ADC comparator
+		2 - Select ANALOG comparator
+
+- qcom,chg-term-current-ma
+  Usage:      optional
+  Value type: <u32>
+  Definition: When ADC comparator is selected as qcom,chg-term-src, this
+		parameter should be set to the desired upper threshold.
+
+- qcom,chg-term-base-current-ma
+  Usage:      optional
+  Value type: <u32>
+  Definition: When ADC comparator is selected as qcom,chg-term-src, this
+		parameter should be set to the desired lower threshold.
+
 - qcom,auto-recharge-soc
   Usage:      optional
   Value type: <u32>
@@ -201,6 +222,31 @@
 	Definition: Phandle for the VADC node, it is used to obtain USBIN_V
 		    and USBIN_I readings on PMIC632 based platform.
 
+- qcom,hw-die-temp-mitigation
+	Usage:      optional
+	Value type: bool
+	Definition: Boolean flag which when present enables h/w based thermal
+		    mitigation.
+
+- qcom,hw-connector-mitigation
+	Usage:      optional
+	Value type: bool
+	Definition: Boolean flag which when present enables h/w based
+		    connector temperature mitigation.
+
+- qcom,connector-internal-pull-kohm
+	Usage:      optional
+	Value type: <u32>
+	Definition: Specifies internal pull-up configuration to be applied to
+		    connector THERM, only valid values are (0/30/100/400).
+		    If not specified 100K is used as default pull-up.
+
+- qcom,moisture-protection-enable
+	Usage:      optional
+	Value type: bool
+	Definition: Boolean flag which when present enables mositure protection
+		    feature.
+
 =============================================
 Second Level Nodes - SMB5 Charger Peripherals
 =============================================
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt
index 4f12ec0..528c285 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt
@@ -51,6 +51,18 @@
 	      stacked one after the other and thus all the charge current
 	      (FCC) flows through main. In a non-stacked configuration each
 	      charger controls the charge current (FCC) separately.
+
+- qcom,die-temp-threshold-degc
+  Usage:      optional
+  Value type: <u32>
+  Definition: Specifies DIE temp threshold beyond which h/w starts mitigation.
+	      If not sepcified, 90 degrees centigrade is used.
+
+- qcom,hw-die-temp-mitigation
+  Usage:      optional
+  Value type: bool
+  Definition: Boolean property to enable h/w controlled die temp mitigation.
+
 ================================================
 Second Level Nodes - SMB1355 Charger Peripherals
 ================================================
diff --git a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
index 803df6f..6fae8b0 100644
--- a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
@@ -61,6 +61,12 @@
 			in conjunction with "hw-ctrl-addr".
  - qcom,toggle-sw-collapse-in-disable: If set, SW_COLLAPSE bit is toggled
 			in disable call.
+ - qcom,en-few-wait-val: Input value for EN_FEW_WAIT controls state transition
+			 delay after receiving ack signal (gds_enf_ack) from the
+			 longest en_few power switch chain.
+ - qcom,en-rest-wait-val: Input value for EN_REST_WAIT controls state transition
+			  delay after receiving ack signal (gds_enr_ack) from the
+			  longest en_rest power switch chain.
 
 Example:
 	gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 20cb25b..6c9d8253 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -3290,3 +3290,97 @@
 		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
 					"SpkrLeft", "SpkrRight";
 	}
+
+* QCS605 IPcamera  ASoC Machine driver
+
+Required properties:
+- compatible : "qcom,qcs605-asoc-snd-tavil"
+- 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-asoc-snd-tavil";
+		qcom,model = "qcs605-tavil-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,msm-gpios =
+			"slim",
+			"us_eu_gpio";
+		qcom,pinctrl-names =
+			"all_off",
+			"slim_act",
+			"us_eu_gpio_act",
+			"slim_us_eu_gpio_act";
+		pinctrl-names =
+			"all_off",
+			"slim_act",
+			"us_eu_gpio_act",
+			"slim_us_eu_gpio_act";
+		pinctrl-0 = <&cdc_slim_lines_sus &cross_conn_det_sus>;
+		pinctrl-1 = <&cdc_slim_lines_act &cross_conn_det_sus>;
+		pinctrl-2 = <&cdc_slim_lines_sus &cross_conn_det_act>;
+		pinctrl-3 = <&cdc_slim_lines_act &cross_conn_det_act>;
+		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/spi/qcom,spi-geni-qcom.txt b/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt
index 866d004..8b6d5a2 100644
--- a/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt
+++ b/Documentation/devicetree/bindings/spi/qcom,spi-geni-qcom.txt
@@ -28,6 +28,7 @@
 Optional properties:
 - qcom,rt:	Specifies if the framework worker thread for this
 		controller device should have "real-time" priority.
+- qcom,disable-autosuspend: Specifies to disable runtime PM auto suspend.
 
 SPI slave nodes must be children of the SPI master node and can contain
 properties described in Documentation/devicetree/bindings/spi/spi-bus.txt
diff --git a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
index 5c09077..70b6fb5 100644
--- a/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
+++ b/Documentation/devicetree/bindings/spi/qcom,spi-qup.txt
@@ -40,7 +40,24 @@
                 receive.
 
 SPI slave nodes must be children of the SPI master node and can contain
-properties described in Documentation/devicetree/bindings/spi/spi-bus.txt
+the following properties.
+
+Required properties:
+- compatible:     Should contain:
+                  "qcom,spi-msm-slave" for external slave control
+
+- reg:            Chip select address of device.
+
+- spi-max-frequency: Maximum SPI clocking speed of device in Hz.
+
+Optional properties:
+- spi-cpol:       Empty property indicating device requires
+                  inverse clock polarity (CPOL) mode.
+- spi-cpha:       Empty property indicating device requires
+                  shifted clock phase (CPHA) mode.
+
+Other optional properties described in
+Documentation/devicetree/bindings/spi/spi-bus.txt
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index a22edb5..ed51a77 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -123,13 +123,13 @@
 hannstar	HannStar Display Corporation
 haoyu	Haoyu Microelectronic Co. Ltd.
 hardkernel	Hardkernel Co., Ltd
-himax	Himax Technologies, Inc.
 hisilicon	Hisilicon Limited.
 hit	Hitachi Ltd.
 hitex	Hitex Development Tools
 holt	Holt Integrated Circuits, Inc.
 honeywell	Honeywell
 hp	Hewlett Packard
+himax   Himax Coroporation
 i2se	I2SE GmbH
 ibm	International Business Machines (IBM)
 idt	Integrated Device Technologies, Inc.
diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
index 206c9b0..3cab335 100644
--- a/Documentation/sysctl/vm.txt
+++ b/Documentation/sysctl/vm.txt
@@ -64,6 +64,7 @@
 - vfs_cache_pressure
 - watermark_scale_factor
 - zone_reclaim_mode
+- want_old_faultaround_pte
 
 ==============================================================
 
@@ -891,4 +892,25 @@
 node unless explicitly overridden by memory policies or cpuset
 configurations.
 
+=============================================================
+
+want_old_faultaround_pte:
+
+By default faultaround code produces young pte. When want_old_faultaround_pte is
+set to 1, faultaround produces old ptes.
+
+During sparse file access faultaround gets more pages mapped and when all of
+them are young (default), under memory pressure, this makes vmscan swap out anon
+pages instead, or to drop other page cache pages which otherwise stay resident.
+Setting want_old_faultaround_pte to 1 avoids this.
+
+Making the faultaround ptes old can result in performance regression on some
+architectures. This is due to cycles spent in micro-faults which would take page
+walk to set young bit in the pte. One such known test that shows a regression on
+x86 is unixbench shell8. Set want_old_faultaround_pte to 1 on architectures
+which does not show this regression or if the workload shows overall performance
+benefit with old faultaround ptes.
+
+The default value is 0.
+
 ============ End of Document =================================
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 54e93a0..04b90d3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1412,6 +1412,16 @@
 	help
 	  This options enables support for the ARM timer and watchdog unit
 
+config ARCH_MSM8953_SOC_SETTINGS
+	bool "Enable MSM8953 SOC settings"
+	depends on ARCH_MSM8953
+	help
+	  Enable MSM8953 SOC related settings, these generic MSM8953
+	  related settings are required for some of CPUSS sub-system
+	  functionality.
+
+	  If you are not sure what to do, select 'N' here.
+
 config MCPM
 	bool "Multi-Cluster Power Management"
 	depends on CPU_V7 && SMP
diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-sdxpoorwills.dtsi
index 580df55..a9b17a0 100644
--- a/arch/arm/boot/dts/qcom/msm-arm-smmu-sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-sdxpoorwills.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,8 @@
 		reg-names = "base", "tcu-base";
 		#iommu-cells = <2>;
 		qcom,use-3-lvl-tables;
+		qcom,no-asid-retention;
+		qcom,disable-atos;
 		#global-interrupts = <1>;
 		#size-cells = <1>;
 		#address-cells = <1>;
@@ -100,5 +102,6 @@
 		 * the apps_smmu device.
 		 */
 		iommus = <&apps_smmu 0x1a0 0x0>;
+		status = "disabled";
 	};
 };
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dts
index 04f11ce..fa858c3 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dts
@@ -20,3 +20,7 @@
 		"qcom,sdxpoorwills", "qcom,cdp";
 	qcom,board-id = <1 0x0>;
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dtsi
index 0f9c8bc..fc56a50 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp-256.dtsi
@@ -11,6 +11,7 @@
  */
 
 #include "sdxpoorwills-cdp.dtsi"
+#include "sdxpoorwills-memory-256.dtsi"
 
 &soc {
 	vreg_sd_mmc: vreg_sd_mmc {
@@ -21,3 +22,11 @@
 &sdhc_1 {
 	cd-gpios = <&tlmm 21 0x1>;
 };
+
+&soc {
+	bluetooth: bt_qca6174 {
+		compatible = "qca,qca6174";
+		qca,bt-reset-gpio = <&pmxpoorwills_gpios 4 0>; /* BT_EN */
+		qca,bt-vdd-pa-supply = <&vreg_wlan>;
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dts
index 99e3faa..eb28282 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dts
@@ -22,3 +22,7 @@
 		"qcom,sdxpoorwills", "qcom,cdp";
 	qcom,board-id = <1 0x102>;
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dtsi
index 8c506b9..c836f94 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dtsi
@@ -141,3 +141,11 @@
 	extcon = <&smb1381_charger>;
 	vbus_dwc3-supply = <&smb138x_vbus>;
 };
+
+&soc {
+	bluetooth: bt_qca6174 {
+		compatible = "qca,qca6174";
+		qca,bt-reset-gpio = <&pmxpoorwills_gpios 4 0>; /* BT_EN */
+		qca,bt-vdd-pa-supply = <&vreg_wlan>;
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dtsi
index 16f933f..d447724 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dtsi
@@ -36,11 +36,3 @@
 	/delete-property/ qcom,devfreq,freq-table;
 	/delete-property/ cd-gpios;
 };
-
-&soc {
-	bluetooth: bt_qca6174 {
-		compatible = "qca,qca6174";
-		qca,bt-reset-gpio = <&pmxpoorwills_gpios 4 0>; /* BT_EN */
-		qca,bt-vdd-pa-supply = <&vreg_wlan>;
-	};
-};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts
index 5fd7042..243fdaf 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts
@@ -28,3 +28,7 @@
 &cnss_sdio {
 	status = "okay";
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-ion.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-ion.dtsi
index a09b149..6957063 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-ion.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-ion.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -26,5 +26,17 @@
 			memory-region = <&audio_mem>;
 			qcom,ion-heap-type = "DMA";
 		};
+
+		qcom,ion-heap@27 { /* QSEECOM HEAP */
+			reg = <27>;
+			memory-region = <&qseecom_mem>;
+			qcom,ion-heap-type = "DMA";
+		};
+
+		qcom,ion-heap@19 { /* QSEECOM TA HEAP */
+			reg = <19>;
+			memory-region = <&qseecom_ta_mem>;
+			qcom,ion-heap-type = "DMA";
+		};
 	};
 };
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-memory-256.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-memory-256.dtsi
new file mode 100644
index 0000000..0c21814
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-memory-256.dtsi
@@ -0,0 +1,19 @@
+/* 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.
+ */
+
+&peripheral2_mem {
+	reg = <0x8fe00000 0x200000>;
+};
+
+&mss_mem {
+	reg = <0x87000000 0x8300000>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dts
index 2377d79c..a774c8b 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dts
@@ -20,3 +20,7 @@
 		"qcom,sdxpoorwills", "qcom,mtp";
 	qcom,board-id = <8 0x0>;
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dtsi
index 7412031..297af52 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp-256.dtsi
@@ -11,6 +11,7 @@
  */
 
 #include "sdxpoorwills-mtp.dtsi"
+#include "sdxpoorwills-memory-256.dtsi"
 
 &soc {
 	vreg_sd_mmc: vreg_sd_mmc {
@@ -21,3 +22,11 @@
 &sdhc_1 {
 	cd-gpios = <&tlmm 21 0x1>;
 };
+
+&soc {
+	bluetooth: bt_qca6174 {
+		compatible = "qca,qca6174";
+		qca,bt-reset-gpio = <&pmxpoorwills_gpios 4 0>; /* BT_EN */
+		qca,bt-vdd-pa-supply = <&vreg_wlan>;
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
index ae3de38..a383f3e 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dts
@@ -20,3 +20,11 @@
 		"qcom,sdxpoorwills", "qcom,mtp";
 	qcom,board-id = <8 0x102>;
 };
+
+&qcom_seecom {
+	status = "okay";
+};
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dtsi
index ef1150a..a6d2463 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dtsi
@@ -141,3 +141,11 @@
 	extcon = <&smb1381_charger>;
 	vbus_dwc3-supply = <&smb138x_vbus>;
 };
+
+&soc {
+	bluetooth: bt_qca6174 {
+		compatible = "qca,qca6174";
+		qca,bt-reset-gpio = <&pmxpoorwills_gpios 4 0>; /* BT_EN */
+		qca,bt-vdd-pa-supply = <&vreg_wlan>;
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp-256.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp-256.dts
index cbbf585..d23275e 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp-256.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp-256.dts
@@ -20,3 +20,7 @@
 		"qcom,sdxpoorwills", "qcom,cdp";
 	qcom,board-id = <1 0x1>;
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dts
index 2a2e496..521d948 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dts
@@ -21,3 +21,6 @@
 	qcom,board-id = <1 0x106>;
 };
 
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp-256.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp-256.dts
index 6b6aab5..236ce73 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp-256.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp-256.dts
@@ -20,3 +20,7 @@
 		"qcom,sdxpoorwills", "qcom,mtp";
 	qcom,board-id = <8 0x1>;
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dts
index 8c22348..11c4e62 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dts
@@ -20,3 +20,7 @@
 		"qcom,sdxpoorwills", "qcom,mtp";
 	qcom,board-id = <8 0x105>;
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie.dtsi
index e939bd2..1907209 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie.dtsi
@@ -143,6 +143,26 @@
 
 		qcom,cpl-timeout = <0x2>;
 
+		qcom,smmu-sid-base = <0x00A0>;
+
+		iommu-map = <0x0 &apps_smmu 0x00A0 0x1>,
+			<0x100 &apps_smmu 0x00A1 0x1>,
+			<0x200 &apps_smmu 0x00A2 0x1>,
+			<0x300 &apps_smmu 0x00A3 0x1>,
+			<0x400 &apps_smmu 0x00A4 0x1>,
+			<0x500 &apps_smmu 0x00A5 0x1>,
+			<0x600 &apps_smmu 0x00A6 0x1>,
+			<0x700 &apps_smmu 0x00A7 0x1>,
+			<0x800 &apps_smmu 0x00A8 0x1>,
+			<0x900 &apps_smmu 0x00A9 0x1>,
+			<0xa00 &apps_smmu 0x00AA 0x1>,
+			<0xb00 &apps_smmu 0x00AB 0x1>,
+			<0xc00 &apps_smmu 0x00AC 0x1>,
+			<0xd00 &apps_smmu 0x00AD 0x1>,
+			<0xe00 &apps_smmu 0x00AE 0x1>,
+			<0xf00 &apps_smmu 0x00AF 0x1>;
+
+
 		qcom,boot-option = <0x1>;
 
 		linux,pci-domain = <0>;
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
index 505f242..2c227b3 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
@@ -97,6 +97,7 @@
 		compatible = "qcom,rpm-stats";
 		reg = <0xC300000 0x1000>, <0xC370004 0x4>;
 		reg-names = "phys_addr_base", "offset_addr";
+		qcom,num-records = <3>;
 	};
 
 	qcom,rpmh-master-stats@b211200 {
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dts
index 775be96..f0363c0 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dts
@@ -20,3 +20,7 @@
 		"qcom,sdxpoorwills", "qcom,ttp";
 	qcom,board-id = <30 0x100>;
 };
+
+&blsp1_uart2b_hs {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi
index 7f49b6d..fa8f3a4 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi
@@ -12,3 +12,12 @@
 
 #include "sdxpoorwills-mtp.dtsi"
 
+&vbus_detect {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+	qcom,connector-type-uAB;
+	extcon = <0>, <0>, <0>, <&vbus_detect>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
index 9f74227..642a541 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
@@ -44,8 +44,8 @@
 		clock-names = "core_clk", "iface_clk", "utmi_clk", "sleep_clk",
 				"cfg_ahb_clk", "xo";
 
-		qcom,core-clk-rate = <133333333>;
-		qcom,core-clk-rate-hs = <66666667>;
+		qcom,core-clk-rate = <120000000>; /* MAX SVS */
+		qcom,core-clk-rate-hs = <75000000>; /* MAX LOW SVS */
 
 		resets = <&clock_gcc GCC_USB30_BCR>;
 		reset-names = "core_reset";
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index d1b2050..61363fe 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -18,6 +18,7 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/regulator/qcom,rpmh-regulator.h>
 #include <dt-bindings/clock/qcom,aop-qmp.h>
+#include <dt-bindings/msm/msm-bus-ids.h>
 
 #define MHZ_TO_MBPS(mhz, w) ((mhz * 1000000 * w) / (1024 * 1024))
 
@@ -35,7 +36,7 @@
 		peripheral2_mem: peripheral2_region@8fe00000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0x8fe00000 0x200000>;
+			reg = <0x8fe00000 0xe00000>;
 			label = "peripheral2_mem";
 		};
 
@@ -64,7 +65,7 @@
 		mss_mem: mss_region@87400000 {
 			compatible = "removed-dma-pool";
 			no-map;
-			reg = <0x87400000 0x8300000>;
+			reg = <0x87000000 0x8700000>;
 			label = "mss_mem";
 		};
 
@@ -79,6 +80,20 @@
 			reusable;
 			size = <0x400000>;
 		};
+
+		qseecom_mem: qseecom_region@0 {
+			compatible = "shared-dma-pool";
+			reusable;
+			alignment = <0x400000>;
+			size = <0x1400000>;
+		};
+
+		qseecom_ta_mem: qseecom_ta_region@0 {
+			compatible = "shared-dma-pool";
+			reusable;
+			alignment = <0x400000>;
+			size = <0x1000000>;
+		};
 	};
 
 	cpus {
@@ -920,38 +935,49 @@
 		qcom,mhi-event-ring-id-limits = <9 10>; /* start and end */
 		qcom,modem-cfg-emb-pipe-flt;
 		qcom,use-ipa-pm;
+		qcom,wlan-ce-db-over-pcie;
 		qcom,arm-smmu;
 		qcom,smmu-fast-map;
 		qcom,bandwidth-vote-for-ipa;
 		qcom,msm-bus,name = "ipa";
 		qcom,msm-bus,num-cases = <5>;
-		qcom,msm-bus,num-paths = <4>;
+		qcom,msm-bus,num-paths = <5>;
 		qcom,msm-bus,vectors-KBps =
 		/* No vote */
-			<90 512 0 0>,
-			<90 585 0 0>,
-			<1 676 0 0>,
-			<143 777 0 0>,
+		<MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_SNOC_MEM_NOC_GC 0 0>,
+		<MSM_BUS_MASTER_SNOC_GC_MEM_NOC MSM_BUS_SLAVE_EBI_CH0 0 0>,
+		<MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_OCIMEM 0 0>,
+		<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_IPA_CFG 0 0>,
+		<MSM_BUS_MASTER_IPA_CORE MSM_BUS_SLAVE_IPA_CORE 0 0>,
+
 		/* SVS2 */
-			<90 512 900000 1800000>,
-			<90 585 300000 600000>,
-			<1 676 90000 179000>, /*gcc_config_noc_clk_src */
-			<143 777 0 120>, /* IB defined for IPA2X_clk in MHz*/
+		<MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_SNOC_MEM_NOC_GC 116000 480000>,
+		<MSM_BUS_MASTER_SNOC_GC_MEM_NOC MSM_BUS_SLAVE_EBI_CH0 116000 1800000>,
+		<MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_OCIMEM 60000 600000>,
+		<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_IPA_CFG 17900 179000>,
+		<MSM_BUS_MASTER_IPA_CORE MSM_BUS_SLAVE_IPA_CORE 0 120>,
+
 		/* SVS */
-			<90 512 1530000 3060000>,
-			<90 585 400000 800000>,
-			<1 676 100000 199000>,
-			<143 777 0 250>, /* IB defined for IPA2X_clk in MHz*/
+		<MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_SNOC_MEM_NOC_GC 225000 720000>,
+		<MSM_BUS_MASTER_SNOC_GC_MEM_NOC MSM_BUS_SLAVE_EBI_CH0 225000 3060000>,
+		<MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_OCIMEM 80000 800000>,
+		<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_IPA_CFG 19900 199000>,
+		<MSM_BUS_MASTER_IPA_CORE MSM_BUS_SLAVE_IPA_CORE 0 250>,
+
 		/* NOMINAL */
-			<90 512 2592000 5184000>,
-			<90 585 800000 1600000>,
-			<1 676 200000 399000>,
-			<143 777 0 440>, /* IB defined for IPA2X_clk in MHz*/
+		<MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_SNOC_MEM_NOC_GC 375000 1560000>,
+		<MSM_BUS_MASTER_SNOC_GC_MEM_NOC MSM_BUS_SLAVE_EBI_CH0 375000 5184000>,
+		<MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_OCIMEM 160000 1600000>,
+		<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_IPA_CFG 39900 399000>,
+		<MSM_BUS_MASTER_IPA_CORE MSM_BUS_SLAVE_IPA_CORE 0 440>,
+
 		/* TURBO */
-			<90 512 2592000 5184000>,
-			<90 585 960000 1920000>,
-			<1 676 266000 531000>,
-			<143 777 0 500>; /* IB defined for IPA clk in MHz*/
+		<MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_SNOC_MEM_NOC_GC 960000 1920000>,
+		<MSM_BUS_MASTER_SNOC_GC_MEM_NOC MSM_BUS_SLAVE_EBI_CH0 2592000 5184000>,
+		<MSM_BUS_MASTER_IPA MSM_BUS_SLAVE_OCIMEM 960000 1920000>,
+		<MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_IPA_CFG 266000 531000>,
+		<MSM_BUS_MASTER_IPA_CORE MSM_BUS_SLAVE_IPA_CORE 0 500>;
+
 		qcom,bus-vector-names = "MIN", "SVS2", "SVS", "NOMINAL",
 		"TURBO";
 		qcom,throughput-threshold = <310 600 1000>;
@@ -1140,6 +1166,33 @@
 		clock-names = "iface_clk";
 	};
 
+	qcom_seecom: qseecom@90000000{
+		compatible = "qcom,qseecom";
+		reg = <0x90000000 0x600000>;
+		reg-names = "secapp-region";
+		qcom,hlos-num-ce-hw-instances = <1>;
+		qcom,hlos-ce-hw-instance = <0>;
+		qcom,qsee-ce-hw-instance = <0>;
+		qcom,no-clock-support;
+		qcom,msm-bus,name = "qseecom-noc";
+		qcom,msm-bus,num-cases = <4>;
+		qcom,msm-bus,num-paths = <1>;
+		clocks = <&clock_gcc GCC_CE1_CLK>,
+			<&clock_gcc GCC_CE1_CLK>,
+			<&clock_gcc GCC_CE1_AHB_CLK>,
+			<&clock_gcc GCC_CE1_AXI_CLK>;
+		qcom,msm-bus,vectors-KBps =
+			<125 512 0 0>,
+			<125 512 20000 40000>,
+			<125 512 30000 80000>,
+			<125 512 40000 100000>;
+		clock-names = "core_clk_src", "core_clk",
+			"iface_clk", "bus_clk";
+		qcom,ce-opp-freq = <171430000>;
+		qcom,qsee-reentrancy-support = <2>;
+		status = "disabled";
+	};
+
 	qcom_cedev: qcedev@1de0000 {
 		compatible = "qcom,qcedev";
 		reg = <0x1de0000 0x20000>,
@@ -1235,6 +1288,9 @@
 				<45 512 98572 655360>, <1 512 98572 1600000>,
 				/* Upto 800 Mbps */
 				<45 512 207108 1146880>, <1 512 207108 3124992>;
+
+		qcom,wlan-smmu-iova-address = <0x10000000 0x10000000>;
+		qcom,wlan-smmu-iova-ipa = <0x20000000 0x10000>;
 	};
 
 	cnss_sdio: qcom,cnss_sdio {
@@ -1268,6 +1324,7 @@
 	emac_hw: qcom,emac@00020000 {
 		compatible = "qcom,emac-dwc-eqos";
 		qcom,arm-smmu;
+		emac-core-version = <1>;
 		reg = <0x20000 0x10000>,
 			<0x36000 0x100>,
 			<0x3900000 0x300000>;
@@ -1289,9 +1346,9 @@
 		qcom,msm-bus,num-paths = <2>;
 		qcom,msm-bus,vectors-KBps =
 			<98 512 0 0>, <1 781 0 0>,  /* No vote */
-			<98 512 1250 0>, <1 781 0 40000>,  /* 10Mbps vote */
-			<98 512 12500 0>, <1 781 0 40000>,  /* 100Mbps vote */
-			<98 512 125000 0>, <1 781 0 40000>; /* 1000Mbps vote */
+			<98 512 2500 0>, <1 781 0 40000>,  /* 10Mbps vote */
+			<98 512 25000 0>, <1 781 0 40000>,  /* 100Mbps vote */
+			<98 512 250000 0>, <1 781 0 40000>; /* 1000Mbps vote */
 		qcom,bus-vector-names = "0", "10", "100", "1000";
 		clocks = <&clock_gcc GCC_ETH_AXI_CLK>,
 			<&clock_gcc GCC_ETH_PTP_CLK>,
@@ -1305,6 +1362,8 @@
 		vreg_emac_phy-supply =  <&vreg_emac_phy>;
 		vreg_rgmii_io_pads-supply = <&vreg_rgmii_io_pads>;
 		gdsc_emac-supply = <&gdsc_emac>;
+		mboxes = <&qmp_aop 0>;
+		mbox-names = "emac_aop";
 		io-macro-info {
 			io-macro-bypass-mode = <0>;
 			io-interface = "rgmii";
@@ -1323,15 +1382,15 @@
 			compatible = "qcom,ess-switch-qca83xx";
 			qcom,switch-access-mode = "mdio";
 			qcom,ar8327-initvals = <
-				0x0000c 0x7600000   /* PAD6_MODE */
+				0x00004 0x7600000   /* PAD0_MODE */
 				0x00008 0x0         /* PAD5_MODE */
 				0x000e4 0xaa545     /* MAC_POWER_SEL */
 				0x000e0 0xc74164de  /* SGMII_CTRL */
 				0x0007c 0x4e        /* PORT0_STATUS */
 				0x00094 0x4e        /* PORT6_STATUS */
 			>;
-			qcom,link-intr-gpio = <2>;
-			qcom,switch-cpu-bmp = <0x40>;    /* cpu port bitmap */
+			qcom,link-intr-gpio = <84>;
+			qcom,switch-cpu-bmp = <0x01>;    /* cpu port bitmap */
 			qcom,switch-lan-bmp = <0x3e>;    /* lan port bitmap */
 			qcom,switch-wan-bmp = <0x0>;     /* wan port bitmap */
 		};
diff --git a/arch/arm/configs/msm8909-perf_defconfig b/arch/arm/configs/msm8909-perf_defconfig
index e21e912..3f8ba5f 100644
--- a/arch/arm/configs/msm8909-perf_defconfig
+++ b/arch/arm/configs/msm8909-perf_defconfig
@@ -1,4 +1,5 @@
 CONFIG_LOCALVERSION="-perf"
+CONFIG_POSIX_MQUEUE=y
 # CONFIG_AUDITSYSCALL is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -9,8 +10,6 @@
 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
@@ -26,8 +25,6 @@
 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
@@ -38,7 +35,7 @@
 CONFIG_EMBEDDED=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
+CONFIG_OPROFILE=m
 CONFIG_CC_STACKPROTECTOR_REGULAR=y
 CONFIG_ARCH_MMAP_RND_BITS=16
 CONFIG_MODULES=y
@@ -55,7 +52,6 @@
 CONFIG_SCHED_MC=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
-CONFIG_HIGHMEM=y
 CONFIG_ARM_MODULE_PLTS=y
 CONFIG_CMA=y
 CONFIG_ZSMALLOC=y
@@ -88,7 +84,6 @@
 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
@@ -118,14 +113,12 @@
 CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
 CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
 CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_CT=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
@@ -157,6 +150,8 @@
 CONFIG_NETFILTER_XT_MATCH_TIME=y
 CONFIG_NETFILTER_XT_MATCH_U32=y
 CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_DUP_IPV4=y
+CONFIG_NF_LOG_IPV4=y
 CONFIG_IP_NF_IPTABLES=y
 CONFIG_IP_NF_MATCH_AH=y
 CONFIG_IP_NF_MATCH_ECN=y
@@ -175,6 +170,8 @@
 CONFIG_IP_NF_ARPFILTER=y
 CONFIG_IP_NF_ARP_MANGLE=y
 CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_DUP_IPV6=y
+CONFIG_NF_LOG_IPV6=y
 CONFIG_IP6_NF_IPTABLES=y
 CONFIG_IP6_NF_MATCH_RPFILTER=y
 CONFIG_IP6_NF_FILTER=y
@@ -191,11 +188,8 @@
 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
@@ -216,7 +210,6 @@
 CONFIG_CFG80211=y
 CONFIG_CFG80211_INTERNAL_REGDB=y
 CONFIG_RFKILL=y
-CONFIG_NFC_NQ=y
 CONFIG_IPC_ROUTER=y
 CONFIG_IPC_ROUTER_SECURITY=y
 CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
@@ -227,23 +220,14 @@
 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_UEVENT=y
 CONFIG_DM_VERITY=y
@@ -268,23 +252,20 @@
 CONFIG_CNSS_SDIO=y
 CONFIG_CLD_HL_SDIO_CORE=y
 CONFIG_INPUT_EVDEV=y
-CONFIG_INPUT_EVBUG=y
+CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
 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
 CONFIG_MSM_ADSPRPC=y
-CONFIG_MSM_RDBG=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MSM_V2=y
 CONFIG_SPI=y
@@ -346,10 +327,8 @@
 CONFIG_MSM_ISPIF=y
 CONFIG_QCOM_KGSL=y
 CONFIG_FB=y
-CONFIG_FB_VIRTUAL=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_LOGO=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_DYNAMIC_MINORS=y
@@ -375,10 +354,6 @@
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MSM=y
 CONFIG_USB_STORAGE=y
-CONFIG_USB_DWC3=y
-CONFIG_USB_DWC3_GADGET=y
-CONFIG_NOP_USB_XCEIV=y
-CONFIG_DUAL_ROLE_USB_INTF=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_GADGET_DEBUG_FS=y
@@ -386,8 +361,6 @@
 CONFIG_USB_CI13XXX_MSM=y
 CONFIG_USB_CONFIGFS=y
 CONFIG_USB_CONFIGFS_SERIAL=y
-CONFIG_USB_CONFIGFS_NCM=y
-CONFIG_USB_CONFIGFS_RMNET_BAM=y
 CONFIG_USB_CONFIGFS_MASS_STORAGE=y
 CONFIG_USB_CONFIGFS_F_FS=y
 CONFIG_USB_CONFIGFS_UEVENT=y
@@ -400,7 +373,6 @@
 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
@@ -420,8 +392,6 @@
 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
@@ -443,83 +413,51 @@
 CONFIG_MSM_SMEM=y
 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
 CONFIG_TRACER_PKT=y
 CONFIG_MSM_SMP2P=y
 CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
-CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
 CONFIG_MSM_QMI_INTERFACE=y
-CONFIG_MSM_GLINK_PKT=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_PIL=y
 CONFIG_MSM_PIL_SSR_GENERIC=y
 CONFIG_MSM_PIL_MSS_QDSP6V5=y
 CONFIG_MSM_EVENT_TIMER=y
-CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_MSM_BAM_DMUX=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_CNSS_CRYPTO=y
 CONFIG_PWM=y
 CONFIG_PWM_QPNP=y
 CONFIG_QTI_MPM=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_STM=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_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_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
 CONFIG_FRAME_WARN=2048
-CONFIG_PAGE_OWNER=y
-CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOCKUP_DETECTOR=y
-# CONFIG_DETECT_HUNG_TASK is not set
 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_FTRACE is not set
-CONFIG_LKDTM=y
-CONFIG_PANIC_ON_DATA_CORRUPTION=y
-# CONFIG_ARM_UNWIND is not set
-CONFIG_PID_IN_CONTEXTIDR=y
+CONFIG_FUNCTION_TRACER=y
 CONFIG_DEBUG_SET_MODULE_RONX=y
-CONFIG_CORESIGHT=y
-CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
-CONFIG_CORESIGHT_SINK_TPIU=y
-CONFIG_CORESIGHT_SOURCE_ETM3X=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_LSM_MMAP_MIN_ADDR=4096
@@ -543,5 +481,4 @@
 CONFIG_CRYPTO_SHA2_ARM_CE=y
 CONFIG_CRYPTO_AES_ARM_BS=y
 CONFIG_CRYPTO_AES_ARM_CE=y
-CONFIG_XZ_DEC=y
 CONFIG_QMI_ENCDEC=y
diff --git a/arch/arm/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig
index 8c3b56b..009ead2 100644
--- a/arch/arm/configs/msm8909_defconfig
+++ b/arch/arm/configs/msm8909_defconfig
@@ -1,3 +1,4 @@
+CONFIG_POSIX_MQUEUE=y
 # CONFIG_AUDITSYSCALL is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -372,12 +373,8 @@
 CONFIG_USB_EHCI_MSM=y
 CONFIG_USB_ACM=y
 CONFIG_USB_STORAGE=y
-CONFIG_USB_DWC3=y
-CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_SERIAL=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
-CONFIG_NOP_USB_XCEIV=y
-CONFIG_DUAL_ROLE_USB_INTF=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_GADGET_DEBUG_FS=y
@@ -463,6 +460,9 @@
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_MSM_BAM_DMUX=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_CNSS_CRYPTO=y
 CONFIG_QCOM_DEVFREQ_DEVBW=y
 CONFIG_IIO=y
@@ -507,7 +507,6 @@
 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
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index 7994ad8..3094af9 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -1,6 +1,5 @@
 # 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
@@ -28,12 +27,17 @@
 CONFIG_DEFAULT_USE_ENERGY_AWARE=y
 CONFIG_RELAY=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_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_BPF_SYSCALL=y
 CONFIG_EMBEDDED=y
 CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
+CONFIG_OPROFILE=m
 CONFIG_CC_STACKPROTECTOR_REGULAR=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
@@ -182,11 +186,8 @@
 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
@@ -225,19 +226,15 @@
 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_UFSHCD_CMD_LOGGING=y
 CONFIG_MD=y
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=y
 CONFIG_DM_UEVENT=y
 CONFIG_DM_VERITY=y
-CONFIG_DM_VERITY_FEC=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
@@ -336,27 +333,11 @@
 CONFIG_FB_MSM_MDSS_MDP3=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_LOGO=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_DYNAMIC_MINORS=y
 CONFIG_SND_SOC=y
 CONFIG_UHID=y
-CONFIG_HID_A4TECH=y
-CONFIG_HID_APPLE=y
-CONFIG_HID_BELKIN=y
-CONFIG_HID_CHERRY=y
-CONFIG_HID_CHICONY=y
-CONFIG_HID_CYPRESS=y
-CONFIG_HID_ELECOM=y
-CONFIG_HID_EZKEY=y
-CONFIG_HID_KENSINGTON=y
-CONFIG_HID_LOGITECH=y
-CONFIG_HID_MAGICMOUSE=y
-CONFIG_HID_MICROSOFT=y
-CONFIG_HID_MONTEREY=y
-CONFIG_HID_MULTITOUCH=y
-CONFIG_DUAL_ROLE_USB_INTF=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_DEBUG_FILES=y
 CONFIG_USB_GADGET_DEBUG_FS=y
@@ -364,9 +345,6 @@
 CONFIG_USB_CI13XXX_MSM=y
 CONFIG_USB_CONFIGFS=y
 CONFIG_USB_CONFIGFS_SERIAL=y
-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
@@ -451,6 +429,7 @@
 CONFIG_MSM_EVENT_TIMER=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_MSM_GLINK_BGCOM_XPRT=y
 CONFIG_MSM_BGCOM_INTERFACE=y
@@ -488,23 +467,15 @@
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
 CONFIG_FRAME_WARN=2048
-CONFIG_PAGE_OWNER=y
-CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOCKUP_DETECTOR=y
-# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_PAGE_EXTENSION=y
+CONFIG_PANIC_ON_RECURSIVE_FAULT=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_IPC_LOGGING=y
-CONFIG_LKDTM=y
-CONFIG_PANIC_ON_DATA_CORRUPTION=y
-# CONFIG_ARM_UNWIND is not set
-CONFIG_PID_IN_CONTEXTIDR=y
+CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_SET_MODULE_RONX=y
 CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY=y
diff --git a/arch/arm/configs/msm8909w_defconfig b/arch/arm/configs/msm8909w_defconfig
index c99d05f..2e545d8 100644
--- a/arch/arm/configs/msm8909w_defconfig
+++ b/arch/arm/configs/msm8909w_defconfig
@@ -26,6 +26,7 @@
 CONFIG_SCHED_AUTOGROUP=y
 CONFIG_SCHED_TUNE=y
 CONFIG_DEFAULT_USE_ENERGY_AWARE=y
+CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
@@ -36,7 +37,6 @@
 CONFIG_KALLSYMS_ALL=y
 CONFIG_BPF_SYSCALL=y
 CONFIG_EMBEDDED=y
-# CONFIG_SLUB_DEBUG is not set
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=m
 CONFIG_CC_STACKPROTECTOR_REGULAR=y
@@ -323,8 +323,9 @@
 CONFIG_FB_MSM_MDSS_SPI_PANEL=y
 CONFIG_FB_MSM_MDSS_MDP3=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_LOGO=y
+# CONFIG_BACKLIGHT_GENERIC is not set
 CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_DYNAMIC_MINORS=y
@@ -357,7 +358,6 @@
 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
@@ -421,6 +421,7 @@
 CONFIG_MSM_EVENT_TIMER=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_MSM_GLINK_BGCOM_XPRT=y
 CONFIG_MSM_BGCOM_INTERFACE=y
@@ -455,27 +456,25 @@
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=6
 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_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
-CONFIG_PANIC_TIMEOUT=5
+CONFIG_PANIC_ON_OOPS=y
+CONFIG_PANIC_TIMEOUT=-1
 CONFIG_PANIC_ON_SCHED_BUG=y
 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
@@ -488,12 +487,9 @@
 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_TRACER_SNAPSHOT=y
+CONFIG_TRACER_SNAPSHOT_PER_CPU_SWAP=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
@@ -507,8 +503,6 @@
 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
diff --git a/arch/arm/configs/msm8937-perf_defconfig b/arch/arm/configs/msm8937-perf_defconfig
index ec018d8..e9a5237 100644
--- a/arch/arm/configs/msm8937-perf_defconfig
+++ b/arch/arm/configs/msm8937-perf_defconfig
@@ -104,6 +104,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPVTI=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
@@ -115,6 +116,7 @@
 CONFIG_INET6_ESP=y
 CONFIG_INET6_IPCOMP=y
 CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_VTI=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_NETFILTER=y
@@ -341,7 +343,6 @@
 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
@@ -382,10 +383,7 @@
 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
@@ -400,9 +398,7 @@
 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
@@ -568,7 +564,6 @@
 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
@@ -592,6 +587,7 @@
 CONFIG_PWM=y
 CONFIG_PWM_QPNP=y
 CONFIG_PWM_QTI_LPG=y
+CONFIG_QCOM_SHOW_RESUME_IRQ=y
 CONFIG_QTI_MPM=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
@@ -599,8 +595,12 @@
 CONFIG_MSM_TZ_LOG=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
 CONFIG_F2FS_FS=y
 CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_FS_ENCRYPTION=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V2=y
@@ -634,13 +634,14 @@
 CONFIG_CORESIGHT_CTI=y
 CONFIG_CORESIGHT_EVENT=y
 CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=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_GCM=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm/configs/msm8937_defconfig b/arch/arm/configs/msm8937_defconfig
index 2fb806d..4a85408 100644
--- a/arch/arm/configs/msm8937_defconfig
+++ b/arch/arm/configs/msm8937_defconfig
@@ -108,6 +108,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPVTI=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
@@ -119,6 +120,7 @@
 CONFIG_INET6_ESP=y
 CONFIG_INET6_IPCOMP=y
 CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_VTI=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_NETFILTER=y
@@ -348,7 +350,6 @@
 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
@@ -389,10 +390,7 @@
 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
@@ -565,7 +563,6 @@
 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_DEBUG_LAR_UNLOCK=y
@@ -586,7 +583,6 @@
 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
@@ -619,8 +615,12 @@
 CONFIG_MSM_TZ_LOG=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
 CONFIG_F2FS_FS=y
 CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_FS_ENCRYPTION=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V2=y
@@ -650,7 +650,6 @@
 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
@@ -701,13 +700,14 @@
 CONFIG_CORESIGHT_CTI=y
 CONFIG_CORESIGHT_EVENT=y
 CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=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_GCM=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm/configs/msm8953-perf_defconfig b/arch/arm/configs/msm8953-perf_defconfig
index 1f94d63..e4bae9f 100644
--- a/arch/arm/configs/msm8953-perf_defconfig
+++ b/arch/arm/configs/msm8953-perf_defconfig
@@ -64,6 +64,7 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
 CONFIG_CMA=y
 CONFIG_CMA_DEBUGFS=y
 CONFIG_ZSMALLOC=y
@@ -101,6 +102,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPVTI=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
@@ -112,6 +114,7 @@
 CONFIG_INET6_ESP=y
 CONFIG_INET6_IPCOMP=y
 CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_VTI=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_NETFILTER=y
@@ -302,6 +305,7 @@
 # CONFIG_WLAN_VENDOR_ZYDAS is not set
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_CLD_LL_CORE=y
+CONFIG_QCA402X=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
@@ -309,6 +313,9 @@
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_FT5X06=y
 CONFIG_TOUCHSCREEN_GEN_VKEYS=y
+CONFIG_TOUCHSCREEN_GT9XX_v28=y
+CONFIG_TOUCHSCREEN_GT9XX_UPDATE=y
+CONFIG_TOUCHSCREEN_GT9XX_TOOL=y
 CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y
 CONFIG_TOUCHSCREEN_HIMAX_I2C=y
 CONFIG_TOUCHSCREEN_HIMAX_DEBUG=y
@@ -503,6 +510,7 @@
 CONFIG_MMC_PERF_PROFILING=y
 # CONFIG_PWRSEQ_EMMC is not set
 # CONFIG_PWRSEQ_SIMPLE is not set
+CONFIG_MMC_EMBEDDED_SDIO=y
 CONFIG_MMC_PARANOID_SD_INIT=y
 CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_BLOCK_MINORS=32
@@ -604,6 +612,8 @@
 CONFIG_EXT4_ENCRYPTION=y
 CONFIG_EXT4_FS_ENCRYPTION=y
 CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V2=y
@@ -644,6 +654,7 @@
 CONFIG_HARDENED_USERCOPY=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_GCM=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm/configs/msm8953_defconfig b/arch/arm/configs/msm8953_defconfig
index b1f5cb9..1dea4b9 100644
--- a/arch/arm/configs/msm8953_defconfig
+++ b/arch/arm/configs/msm8953_defconfig
@@ -67,6 +67,7 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
 CONFIG_CMA=y
 CONFIG_CMA_DEBUGFS=y
 CONFIG_ZSMALLOC=y
@@ -105,6 +106,7 @@
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPVTI=y
 CONFIG_INET_AH=y
 CONFIG_INET_ESP=y
 CONFIG_INET_IPCOMP=y
@@ -116,6 +118,7 @@
 CONFIG_INET6_ESP=y
 CONFIG_INET6_IPCOMP=y
 CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_VTI=y
 CONFIG_IPV6_MULTIPLE_TABLES=y
 CONFIG_IPV6_SUBTREES=y
 CONFIG_NETFILTER=y
@@ -307,6 +310,7 @@
 # CONFIG_WLAN_VENDOR_ZYDAS is not set
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_CLD_LL_CORE=y
+CONFIG_QCA402X=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
@@ -314,6 +318,9 @@
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_FT5X06=y
 CONFIG_TOUCHSCREEN_GEN_VKEYS=y
+CONFIG_TOUCHSCREEN_GT9XX_v28=y
+CONFIG_TOUCHSCREEN_GT9XX_UPDATE=y
+CONFIG_TOUCHSCREEN_GT9XX_TOOL=y
 CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y
 CONFIG_TOUCHSCREEN_HIMAX_I2C=y
 CONFIG_TOUCHSCREEN_HIMAX_DEBUG=y
@@ -512,6 +519,7 @@
 # CONFIG_PWRSEQ_EMMC is not set
 # CONFIG_PWRSEQ_SIMPLE is not set
 CONFIG_MMC_RING_BUFFER=y
+CONFIG_MMC_EMBEDDED_SDIO=y
 CONFIG_MMC_PARANOID_SD_INIT=y
 CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_BLOCK_MINORS=32
@@ -567,7 +575,6 @@
 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_DEBUG_LAR_UNLOCK=y
@@ -622,6 +629,8 @@
 CONFIG_EXT4_ENCRYPTION=y
 CONFIG_EXT4_FS_ENCRYPTION=y
 CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V2=y
@@ -709,6 +718,7 @@
 CONFIG_HARDENED_USERCOPY=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_GCM=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm/configs/sdm670_defconfig b/arch/arm/configs/sdm670_defconfig
new file mode 100644
index 0000000..082a53a
--- /dev/null
+++ b/arch/arm/configs/sdm670_defconfig
@@ -0,0 +1,622 @@
+# 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_BLK_CGROUP=y
+CONFIG_DEBUG_BLK_CGROUP=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_BPF=y
+CONFIG_SCHED_CORE_CTL=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_KALLSYMS_ALL=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_AIO is not set
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_IOSCHED_DEADLINE is not set
+CONFIG_CFQ_GROUP_IOSCHED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_SDM670=y
+CONFIG_PCI_MSM=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=8
+CONFIG_ARM_PSCI=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
+CONFIG_CLEANCACHE=y
+CONFIG_CMA=y
+CONFIG_CMA_DEBUGFS=y
+CONFIG_ZSMALLOC=y
+CONFIG_BALANCE_ANON_FILE_RECLAIM=y
+CONFIG_SECCOMP=y
+CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_KERNEL_MODE_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_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_QUOTA2_LOG=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_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_AQT_REGMAP=y
+CONFIG_REGMAP_ALLOW_WRITE_DEBUGFS=y
+CONFIG_DMA_CMA=y
+CONFIG_ZRAM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_QSEECOM=y
+CONFIG_UID_SYS_STATS=y
+CONFIG_MEMORY_STATE_TIME=y
+CONFIG_QPNP_MISC=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_GENL=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_QPNP_POWER_ON=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM_GENI=y
+CONFIG_SERIAL_MSM_GENI_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QCOM_GENI=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_QCOM_GENI=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SPMI=y
+CONFIG_SPMI_MSM_PMIC_ARB_DEBUG=y
+CONFIG_PINCTRL_SDM670=y
+CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_QPNP_FG_GEN3=y
+CONFIG_SMB1355_SLAVE_CHARGER=y
+CONFIG_QPNP_SMB2=y
+CONFIG_QPNP_QNOVO=y
+CONFIG_SMB1390_CHARGE_PUMP=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_THERMAL=y
+CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
+CONFIG_QCOM_SPMI_TEMP_ALARM=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_THERMAL_TSENS=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
+CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_MFD_I2C_PMIC=y
+CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_PROXY_CONSUMER=y
+CONFIG_REGULATOR_QPNP_LABIBB=y
+CONFIG_REGULATOR_QPNP_LCDB=y
+CONFIG_REGULATOR_QPNP_OLEDB=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_REFGEN=y
+CONFIG_REGULATOR_RPMH=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_FIXED_MINOR_RANGES=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_QCOM_KGSL=y
+CONFIG_DRM=y
+CONFIG_DRM_SDE_EVTLOG_DEBUG=y
+CONFIG_DRM_SDE_RSC=y
+CONFIG_DRM_LT_LT9611=y
+CONFIG_FB_VIRTUAL=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_AUDIO_QMI=y
+CONFIG_SND_SOC=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_USB=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_ISP1760=y
+CONFIG_USB_ISP1760_HOST_ROLE=y
+CONFIG_USB_PD_POLICY=y
+CONFIG_QPNP_USB_PDPHY=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_DUAL_ROLE_USB_INTF=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_QUSB_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_DIAG=y
+CONFIG_USB_CONFIGFS_F_CDEV=y
+CONFIG_USB_CONFIGFS_F_CCID=y
+CONFIG_USB_CONFIGFS_F_GSI=y
+CONFIG_USB_CONFIGFS_F_QDSS=y
+CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SDHCI_MSM_ICE=y
+CONFIG_MMC_CQ_HCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_QPNP_FLASH_V2=y
+CONFIG_LEDS_QPNP_WLED=y
+CONFIG_LEDS_QPNP_HAPTICS=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_DMADEVICES=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_GSI=y
+CONFIG_IPA3=y
+CONFIG_RMNET_IPA3=y
+CONFIG_RNDIS_IPA=y
+CONFIG_IPA_UT=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_QPNP_COINCELL=y
+CONFIG_QPNP_REVID=y
+CONFIG_USB_BAM=y
+CONFIG_QCOM_GENI_SE=y
+CONFIG_MSM_GCC_SDM845=y
+CONFIG_MSM_VIDEOCC_SDM845=y
+CONFIG_MSM_CAMCC_SDM845=y
+CONFIG_MSM_DISPCC_SDM845=y
+CONFIG_CLOCK_QPNP_DIV=y
+CONFIG_MSM_CLK_RPMH=y
+CONFIG_CLOCK_CPU_OSM=y
+CONFIG_MSM_GPUCC_SDM845=y
+CONFIG_MSM_CLK_AOP_QMP=y
+CONFIG_QCOM_MDSS_PLL=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MSM_QMP=y
+CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_IOMMU_DEBUG=y
+CONFIG_IOMMU_DEBUG_TRACKING=y
+CONFIG_IOMMU_TESTS=y
+CONFIG_QCOM_CPUSS_DUMP=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
+CONFIG_QCOM_LLCC=y
+CONFIG_QCOM_SDM670_LLCC=y
+CONFIG_QCOM_LLCC_PERFMON=m
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_CORE_HANG_DETECT=y
+CONFIG_MSM_GLADIATOR_HANG_DETECT=y
+CONFIG_MSM_GLADIATOR_ERP=y
+CONFIG_QCOM_EUD=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QPNP_PBS=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_QCOM_BUS_SCALING=y
+CONFIG_QCOM_BUS_CONFIG_RPMH=y
+CONFIG_QCOM_SECURE_BUFFER=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_MSM_SMEM=y
+CONFIG_MSM_GLINK=y
+CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
+CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
+CONFIG_MSM_GLINK_SPI_XPRT=y
+CONFIG_MSM_SPCOM=y
+CONFIG_MSM_SPSS_UTILS=y
+CONFIG_TRACER_PKT=y
+CONFIG_QTI_RPMH_API=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_GLINK_PKT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_SYSMON_GLINK_COMM=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_ICNSS=y
+CONFIG_ICNSS_DEBUG=y
+CONFIG_QCOM_COMMAND_DB=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_MSM_CDSP_LOADER=y
+CONFIG_QCOM_SMCINVOKE=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_QBT1000=y
+CONFIG_QCOM_DCC_V2=y
+CONFIG_QTI_RPM_STATS_LOG=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_QMP_DEBUGFS_CLIENT=y
+CONFIG_MSM_REMOTEQDSS=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_CACHE_HWMON=y
+CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_QCOM_RRADC=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
+CONFIG_ARM_GIC_V3_ACL=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_SENSORS_SSC=y
+CONFIG_MSM_TZ_LOG=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_QUOTA=y
+CONFIG_QUOTA_NETLINK_INTERFACE=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_PAGE_OWNER=y
+CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_SLUB_DEBUG_PANIC_ON=y
+CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
+CONFIG_DEBUG_OBJECTS=y
+CONFIG_DEBUG_OBJECTS_FREE=y
+CONFIG_DEBUG_OBJECTS_TIMERS=y
+CONFIG_DEBUG_OBJECTS_WORK=y
+CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
+CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
+CONFIG_SLUB_DEBUG_ON=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_LOCKUP_DETECTOR=y
+CONFIG_WQ_WATCHDOG=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_PANIC_ON_SCHED_BUG=y
+CONFIG_PANIC_ON_RT_THROTTLING=y
+CONFIG_SCHEDSTATS=y
+CONFIG_SCHED_STACK_END_CHECK=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_LIST=y
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_IPC_LOGGING=y
+CONFIG_QCOM_RTB=y
+CONFIG_QCOM_RTB_SEPARATE_CPUS=y
+CONFIG_FUNCTION_TRACER=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_LKDTM=y
+CONFIG_MEMTEST=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
+CONFIG_PID_IN_CONTEXTIDR=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_REMOTE_ETM=y
+CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
+CONFIG_CORESIGHT_QCOM_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
+CONFIG_CORESIGHT_CTI=y
+CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_CORESIGHT_DUMMY=y
+CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
+CONFIG_SECURITY=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_XZ_DEC=y
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index cab3796..54214d5 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -41,6 +41,9 @@
 CONFIG_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
@@ -182,6 +185,7 @@
 CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
+CONFIG_QSEECOM=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
@@ -298,6 +302,8 @@
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_LINK_LAYER_TEST=y
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_USB_MSM_SSPHY_QMP=y
 CONFIG_MSM_HSUSB_PHY=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index bd429ee..b4862b9 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -43,6 +43,9 @@
 CONFIG_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
@@ -176,6 +179,7 @@
 CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
+CONFIG_QSEECOM=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
@@ -299,6 +303,7 @@
 CONFIG_USB_DWC3=y
 CONFIG_USB_DWC3_MSM=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_LINK_LAYER_TEST=y
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_USB_MSM_SSPHY_QMP=y
 CONFIG_MSM_HSUSB_PHY=y
diff --git a/arch/arm/include/asm/arch_gicv3.h b/arch/arm/include/asm/arch_gicv3.h
index 4d1065c..e65712e 100644
--- a/arch/arm/include/asm/arch_gicv3.h
+++ b/arch/arm/include/asm/arch_gicv3.h
@@ -25,6 +25,7 @@
 #include <asm/cp15.h>
 
 #define ICC_EOIR1			__ACCESS_CP15(c12, 0, c12, 1)
+#define ICC_HPPIR1			__ACCESS_CP15(c12, 0, c12, 2)
 #define ICC_DIR				__ACCESS_CP15(c12, 0, c11, 1)
 #define ICC_IAR1			__ACCESS_CP15(c12, 0, c12, 0)
 #define ICC_SGI1R			__ACCESS_CP15_64(0, c12)
@@ -140,6 +141,7 @@
 CPUIF_MAP(ICH_AP1R0, ICH_AP1R0_EL2)
 CPUIF_MAP(ICC_HSRE, ICC_SRE_EL2)
 CPUIF_MAP(ICC_SRE, ICC_SRE_EL1)
+CPUIF_MAP(ICC_HPPIR1, ICC_HPPIR1_EL1)
 
 CPUIF_MAP_LO_HI(ICH_LR15, ICH_LRC15, ICH_LR15_EL2)
 CPUIF_MAP_LO_HI(ICH_LR14, ICH_LRC14, ICH_LR14_EL2)
@@ -184,6 +186,15 @@
 	return irqstat;
 }
 
+static inline u32 gic_read_hppir(void)
+{
+	u32 irqstat = read_sysreg(ICC_HPPIR1);
+
+	dsb(sy);
+
+	return irqstat;
+}
+
 static inline void gic_write_pmr(u32 val)
 {
 	write_sysreg(val, ICC_PMR);
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index b62eaeb..174346b 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -76,6 +76,8 @@
 #define ARM_CPU_PART_CORTEX_A12		0x4100c0d0
 #define ARM_CPU_PART_CORTEX_A17		0x4100c0e0
 #define ARM_CPU_PART_CORTEX_A15		0x4100c0f0
+#define ARM_CPU_PART_CORTEX_A73		0x4100d090
+#define ARM_CPU_PART_KRYO2XX_GOLD		0x51008000
 #define ARM_CPU_PART_MASK		0xff00fff0
 
 /* DEC implemented cores */
diff --git a/arch/arm/include/asm/mmu_context.h b/arch/arm/include/asm/mmu_context.h
index 3cc14dd..0c835ee 100644
--- a/arch/arm/include/asm/mmu_context.h
+++ b/arch/arm/include/asm/mmu_context.h
@@ -24,6 +24,18 @@
 
 void __check_vmalloc_seq(struct mm_struct *mm);
 
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+void arm_init_bp_hardening(void);
+void arm_apply_bp_hardening(void);
+#else
+static inline void arm_init_bp_hardening(void)
+{
+}
+static inline void arm_apply_bp_hardening(void)
+{
+}
+#endif
+
 #ifdef CONFIG_CPU_HAS_ASID
 
 void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk);
@@ -63,8 +75,10 @@
 		 * finish_arch_post_lock_switch() call.
 		 */
 		mm->context.switch_pending = 1;
-	else
+	else {
+		arm_apply_bp_hardening();
 		cpu_switch_mm(mm->pgd, mm);
+	}
 }
 
 #ifndef MODULE
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index 4f14b5c..c2b440b 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -40,8 +40,15 @@
 #ifdef CONFIG_MMU
 void *module_alloc(unsigned long size)
 {
-	void *p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
-				GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
+	gfp_t gfp_mask = GFP_KERNEL;
+	void *p;
+
+	/* Silence the initial allocation */
+	if (IS_ENABLED(CONFIG_ARM_MODULE_PLTS))
+		gfp_mask |= __GFP_NOWARN;
+
+	p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+				gfp_mask, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
 				__builtin_return_address(0));
 	if (!IS_ENABLED(CONFIG_ARM_MODULE_PLTS) || p)
 		return p;
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 38ad8b9..b876193 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -150,17 +150,6 @@
 	show_data(regs->ARM_sp - nbytes, nbytes * 2, "SP");
 	show_data(regs->ARM_ip - nbytes, nbytes * 2, "IP");
 	show_data(regs->ARM_fp - nbytes, nbytes * 2, "FP");
-	show_data(regs->ARM_r0 - nbytes, nbytes * 2, "R0");
-	show_data(regs->ARM_r1 - nbytes, nbytes * 2, "R1");
-	show_data(regs->ARM_r2 - nbytes, nbytes * 2, "R2");
-	show_data(regs->ARM_r3 - nbytes, nbytes * 2, "R3");
-	show_data(regs->ARM_r4 - nbytes, nbytes * 2, "R4");
-	show_data(regs->ARM_r5 - nbytes, nbytes * 2, "R5");
-	show_data(regs->ARM_r6 - nbytes, nbytes * 2, "R6");
-	show_data(regs->ARM_r7 - nbytes, nbytes * 2, "R7");
-	show_data(regs->ARM_r8 - nbytes, nbytes * 2, "R8");
-	show_data(regs->ARM_r9 - nbytes, nbytes * 2, "R9");
-	show_data(regs->ARM_r10 - nbytes, nbytes * 2, "R10");
 	set_fs(fs);
 }
 
@@ -256,7 +245,8 @@
 	}
 #endif
 
-	show_extra_register_data(regs, 128);
+	if (!user_mode(regs))
+		show_extra_register_data(regs, 128);
 }
 
 void show_regs(struct pt_regs * regs)
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 09dd8ff..4f451ce 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -243,6 +243,40 @@
 	"?(17)",
 };
 
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+struct arm_btbinv {
+	void (*apply_bp_hardening)(void);
+};
+static DEFINE_PER_CPU_READ_MOSTLY(struct arm_btbinv, arm_btbinv);
+
+static void arm_a73_apply_bp_hardening(void)
+{
+	asm("mov        r2, #0");
+	asm("mcr        p15, 0, r2, c7, c5, 6");
+}
+
+void arm_apply_bp_hardening(void)
+{
+	if (this_cpu_ptr(&arm_btbinv)->apply_bp_hardening)
+		this_cpu_ptr(&arm_btbinv)->apply_bp_hardening();
+}
+
+void arm_init_bp_hardening(void)
+{
+	switch (read_cpuid_part()) {
+	case ARM_CPU_PART_CORTEX_A73:
+	case ARM_CPU_PART_KRYO2XX_GOLD:
+		per_cpu(arm_btbinv.apply_bp_hardening, raw_smp_processor_id())
+			  = arm_a73_apply_bp_hardening;
+		break;
+	default:
+		per_cpu(arm_btbinv.apply_bp_hardening, raw_smp_processor_id())
+			  = NULL;
+		break;
+	}
+}
+#endif
+
 #ifdef CONFIG_CPU_V7M
 static int __get_cpu_architecture(void)
 {
@@ -685,6 +719,7 @@
 	 * types.  The linker builds this table for us from the
 	 * entries in arch/arm/mm/proc-*.S
 	 */
+	arm_init_bp_hardening();
 	list = lookup_processor_type(read_cpuid_id());
 	if (!list) {
 		pr_err("CPU configuration botched (ID %08x), unable to continue.\n",
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index a03a99a..0169acb 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -47,6 +47,7 @@
 #include <asm/virt.h>
 #include <asm/mach/arch.h>
 #include <asm/mpu.h>
+#include <asm/cputype.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/ipi.h>
@@ -239,15 +240,13 @@
 	return 0;
 }
 
-static DECLARE_COMPLETION(cpu_died);
-
 /*
  * called on the thread which is asking for a CPU to be shutdown -
  * waits until shutdown has completed, or it is timed out.
  */
 void __cpu_die(unsigned int cpu)
 {
-	if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) {
+	if (!cpu_wait_death(cpu, 5)) {
 		pr_err("CPU%u: cpu didn't die\n", cpu);
 		return;
 	}
@@ -293,7 +292,7 @@
 	 * this returns, power and/or clocks can be removed at any point
 	 * from this CPU and its cache by platform_cpu_kill().
 	 */
-	complete(&cpu_died);
+	(void)cpu_report_death();
 
 	/*
 	 * Ensure that the cache lines associated with that completion are
@@ -361,6 +360,7 @@
 	 * The identity mapping is uncached (strongly ordered), so
 	 * switch away from it before attempting any exclusive accesses.
 	 */
+	arm_init_bp_hardening();
 	cpu_switch_mm(mm->pgd, mm);
 	local_flush_bp_all();
 	enter_lazy_tlb(mm, current);
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index da48623..7ca9180 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -64,6 +64,7 @@
 	select HAVE_CLK
 	select HAVE_CLK_PREPARE
 	select COMMON_CLK_MSM
+	select ARCH_MSM8953_SOC_SETTINGS
 
 config ARCH_MSM8953_BOOT_ORDERING
 	bool "Enable support for MSM8953 device boot ordering"
@@ -160,6 +161,7 @@
 	select HAVE_CLK
 	select HAVE_CLK_PREPARE
 	select COMMON_CLK_MSM
+	select ARCH_MSM8953_SOC_SETTINGS
 
 config ARCH_SDM632
 	bool "Enable Support for Qualcomm Technologies Inc. SDM632"
@@ -176,6 +178,41 @@
 	select SND_HWDEP
 	select CPU_FREQ_QCOM
 	select COMMON_CLK_MSM
+	select ARCH_MSM8953_SOC_SETTINGS
+
+config ARCH_SDM670
+        bool "Enable Support for SDM670"
+	select CPU_V7
+	select CLKDEV_LOOKUP
+	select HAVE_CLK
+	select HAVE_CLK_PREPARE
+	select PM_OPP
+	select SOC_BUS
+	select MSM_IRQ
+	select THERMAL_WRITABLE_TRIPS
+	select ARM_GIC_V3
+	select ARM_AMBA
+	select SPARSE_IRQ
+	select MULTI_IRQ_HANDLER
+	select HAVE_ARM_ARCH_TIMER
+	select MAY_HAVE_SPARSE_IRQ
+	select COMMON_CLK
+	select COMMON_CLK_QCOM
+	select QCOM_GDSC
+	select PINCTRL_MSM_TLMM
+	select PCI
+	select USE_PINCTRL_IRQ
+	select MSM_PM if PM
+	select QMI_ENCDEC
+	select CPU_FREQ
+	select PM_DEVFREQ
+	select MSM_DEVFREQ_DEVBW
+	select DEVFREQ_SIMPLE_DEV
+	select DEVFREQ_GOV_MSM_BW_HWMON
+	select MSM_BIMC_BWMON
+	select MSM_QDSP6V2_CODECS
+	select MSM_AUDIO_QDSP6V2 if SND_SOC
+	select GENERIC_IRQ_MIGRATION
 
 config ARCH_MDM9650
 	bool "MDM9650"
diff --git a/arch/arm/mach-qcom/Makefile b/arch/arm/mach-qcom/Makefile
index 2f26f39..3ef169f 100644
--- a/arch/arm/mach-qcom/Makefile
+++ b/arch/arm/mach-qcom/Makefile
@@ -12,3 +12,4 @@
 obj-$(CONFIG_ARCH_MDM9650) += board-9650.o
 obj-$(CONFIG_ARCH_MDM9607) += board-9607.o
 obj-$(CONFIG_ARCH_SDM632) += board-sdm632.o
+obj-$(CONFIG_ARCH_SDM670) += board-sdm670.o
diff --git a/arch/arm/mach-qcom/board-sdm670.c b/arch/arm/mach-qcom/board-sdm670.c
new file mode 100644
index 0000000..c77a3ff
--- /dev/null
+++ b/arch/arm/mach-qcom/board-sdm670.c
@@ -0,0 +1,33 @@
+/* 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 *sdm670_dt_match[] __initconst = {
+	"qcom,sdm670",
+	"qcom,qcs605",
+	NULL
+};
+
+static void __init sdm670_init(void)
+{
+	board_dt_populate(NULL);
+}
+
+DT_MACHINE_START(SDM670_DT,
+	"Qualcomm Technologies, Inc. SDM670 (Flattened Device Tree)")
+	.init_machine		= sdm670_init,
+	.dt_compat		= sdm670_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-qcom/platsmp.c b/arch/arm/mach-qcom/platsmp.c
index 803804d..3be4cae 100644
--- a/arch/arm/mach-qcom/platsmp.c
+++ b/arch/arm/mach-qcom/platsmp.c
@@ -25,7 +25,7 @@
 #ifdef CONFIG_MSM_PM_LEGACY
 #include <soc/qcom/pm-legacy.h>
 #endif
-
+#include <soc/qcom/scm-boot.h>
 #define MSM_APCS_IDR 0x0B011030
 
 /* Base Address of APC IPC block */
@@ -434,10 +434,19 @@
 
 static void __init qcom_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int cpu;
+	int cpu, map;
+	u32 aff0_mask = 0;
+	u32 aff1_mask = 0;
+	u32 aff2_mask = 0;
 
-	if (qcom_scm_set_cold_boot_addr(secondary_startup_arm,
-					cpu_present_mask)) {
+	for_each_present_cpu(cpu) {
+		map = cpu_logical_map(cpu);
+		aff0_mask |= BIT(MPIDR_AFFINITY_LEVEL(map, 0));
+		aff1_mask |= BIT(MPIDR_AFFINITY_LEVEL(map, 1));
+		aff2_mask |= BIT(MPIDR_AFFINITY_LEVEL(map, 2));
+	}
+	if (scm_set_boot_addr_mc(virt_to_phys(secondary_startup_arm),
+		aff0_mask, aff1_mask, aff2_mask, SCM_FLAG_COLDBOOT_MC)) {
 		for_each_present_cpu(cpu) {
 			if (cpu == smp_processor_id())
 				continue;
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index c1799dd..1a5acee 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -1068,3 +1068,20 @@
 	  additional section-aligned split of rodata from kernel text so it
 	  can be made explicitly non-executable. This padding may waste memory
 	  space to gain the additional protection.
+
+config HARDEN_BRANCH_PREDICTOR
+	bool "Harden the branch predictor against aliasing attacks" if EXPERT
+	default y
+	help
+	  Speculation attacks against some high-performance processors rely on
+	  being able to manipulate the branch predictor for a victim context by
+	  executing aliasing branches in the attacker context.  Such attacks
+	  can be partially mitigated against by clearing internal branch
+	  predictor state and limiting the prediction logic in some situations.
+
+	  This config option will take CPU-specific actions to harden the
+	  branch predictor against aliasing attacks and may rely on specific
+	  instruction sequences or control bits being set by the system
+	  firmware.
+
+	  If unsure, say Y.
diff --git a/arch/arm/mm/context.c b/arch/arm/mm/context.c
index c8c8b9e..f187439 100644
--- a/arch/arm/mm/context.c
+++ b/arch/arm/mm/context.c
@@ -276,5 +276,6 @@
 	raw_spin_unlock_irqrestore(&cpu_asid_lock, flags);
 
 switch_mm_fastpath:
+	arm_apply_bp_hardening();
 	cpu_switch_mm(mm->pgd, mm);
 }
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index f216025..a8f8d46 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2483,7 +2483,10 @@
 {
 	int err;
 
-	err = iommu_attach_device(mapping->domain, dev);
+	if (!dev->iommu_group)
+		return -EINVAL;
+
+	err = iommu_attach_group(mapping->domain, dev->iommu_group);
 	if (err)
 		return err;
 
@@ -2610,7 +2613,7 @@
 	}
 
 	if (__arm_iommu_attach_device(dev, mapping)) {
-		pr_warn("Failed to attached device %s to IOMMU_mapping\n",
+		pr_debug("Failed to attached device %s to IOMMU_mapping\n",
 				dev_name(dev));
 		arm_iommu_release_mapping(mapping);
 		return false;
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 203728d..7fa65aa 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -265,6 +265,7 @@
 	unsigned long addr;
 	struct vm_struct *area;
 	phys_addr_t paddr = __pfn_to_phys(pfn);
+	pgprot_t prot;
 
 #ifndef CONFIG_ARM_LPAE
 	/*
@@ -310,6 +311,12 @@
  	addr = (unsigned long)area->addr;
 	area->phys_addr = paddr;
 
+	prot = __pgprot(type->prot_pte);
+#ifdef CONFIG_ARCH_MSM8953_SOC_SETTINGS
+	if (paddr >= MSM8953_TLMM_START_ADDR &&
+	    paddr <= MSM8953_TLMM_END_ADDR)
+		prot = pgprot_stronglyordered(type->prot_pte);
+#endif
 #if !defined(CONFIG_SMP) && !defined(CONFIG_ARM_LPAE)
 	if (DOMAIN_IO == 0 &&
 	    (((cpu_architecture() >= CPU_ARCH_ARMv6) && (get_cr() & CR_XP)) ||
@@ -322,8 +329,7 @@
 		err = remap_area_sections(addr, pfn, size, type);
 	} else
 #endif
-		err = ioremap_page_range(addr, addr + size, paddr,
-					 __pgprot(type->prot_pte));
+		err = ioremap_page_range(addr, addr + size, paddr, prot);
 
 	if (err) {
  		vunmap((void *)addr);
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 9c01a31..ac71d39 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -15,7 +15,24 @@
 	select ARCH_HAS_KCOV
 	select ARCH_HAS_SG_CHAIN
 	select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
+	select ARCH_INLINE_READ_LOCK if !PREEMPT
+	select ARCH_INLINE_READ_LOCK_BH if !PREEMPT
+	select ARCH_INLINE_READ_LOCK_IRQ if !PREEMPT
+	select ARCH_INLINE_READ_LOCK_IRQSAVE if !PREEMPT
+	select ARCH_INLINE_READ_UNLOCK if !PREEMPT
+	select ARCH_INLINE_READ_UNLOCK_BH if !PREEMPT
+	select ARCH_INLINE_READ_UNLOCK_IRQ if !PREEMPT
+	select ARCH_INLINE_READ_UNLOCK_IRQRESTORE if !PREEMPT
+	select ARCH_INLINE_WRITE_LOCK if !PREEMPT
+	select ARCH_INLINE_WRITE_LOCK_BH if !PREEMPT
+	select ARCH_INLINE_WRITE_LOCK_IRQ if !PREEMPT
+	select ARCH_INLINE_WRITE_LOCK_IRQSAVE if !PREEMPT
+	select ARCH_INLINE_WRITE_UNLOCK if !PREEMPT
+	select ARCH_INLINE_WRITE_UNLOCK_BH if !PREEMPT
+	select ARCH_INLINE_WRITE_UNLOCK_IRQ if !PREEMPT
+	select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE if !PREEMPT
 	select ARCH_USE_CMPXCHG_LOCKREF
+	select ARCH_USE_QUEUED_RWLOCKS
 	select ARCH_SUPPORTS_LTO_CLANG
 	select ARCH_SUPPORTS_ATOMIC_RMW
 	select ARCH_SUPPORTS_NUMA_BALANCING
@@ -112,6 +129,7 @@
 	select SPARSE_IRQ
 	select SYSCTL_EXCEPTION_TRACE
 	select THREAD_INFO_IN_TASK
+	select ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT
 	help
 	  ARM 64-bit (AArch64) Linux support.
 
@@ -536,6 +554,16 @@
 
 endchoice
 
+config ARCH_MSM8953_SOC_SETTINGS
+	bool "Enable MSM8953 SOC settings"
+	depends on ARCH_MSM8953
+	help
+	  Enable MSM8953 SOC related settings, these generic MSM8953
+	  related settings are required for some of CPUSS sub-system
+	  functionality.
+
+	  If you are not sure what to do, select 'N' here.
+
 choice
 	prompt "Virtual address space size"
 	default ARM64_VA_BITS_39 if ARM64_4K_PAGES
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index a92f511..4c013ad 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -152,6 +152,7 @@
 	depends on ARCH_QCOM
 	select CPU_FREQ_QCOM
 	select COMMON_CLK_MSM
+	select ARCH_MSM8953_SOC_SETTINGS
 	help
 	  This enables support for the MSM8953 chipset. If you do not
 	  wish to build a kernel that runs on this chipset, say 'N' here.
@@ -179,6 +180,7 @@
 	depends on ARCH_QCOM
 	select CPU_FREQ_QCOM
 	select COMMON_CLK_MSM
+	select ARCH_MSM8953_SOC_SETTINGS
 	help
 	  This enables support for the sdm450 chipset. If you do not
 	  wish to build a kernel that runs on this chipset, say 'N' here.
@@ -188,6 +190,7 @@
 	depends on ARCH_QCOM
 	select CPU_FREQ_QCOM
 	select COMMON_CLK_MSM
+	select ARCH_MSM8953_SOC_SETTINGS
 	help
 	  This enables support for the sdm632 chipset. If you do not
 	  wish to build a kernel that runs on this chipset, say 'N' here.
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 3ad1c0e..dbaf7cd 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -150,6 +150,7 @@
 		qcs605-mtp-overlay.dtbo \
 		qcs605-360camera-overlay.dtbo \
 		qcs605-external-codec-mtp-overlay.dtbo \
+		qcs605-lc-ipcamera-overlay.dtbo \
 		qcs605-lc-mtp-overlay.dtbo \
 		qcs605-lc-cdp-overlay.dtbo \
 		sdm710-cdp-overlay.dtbo \
@@ -211,6 +212,7 @@
 qcs605-mtp-overlay.dtbo-base := qcs605.dtb
 qcs605-external-codec-mtp-overlay.dtbo-base := qcs605.dtb
 qcs605-lc-mtp-overlay.dtbo-base := qcs605-lc.dtb
+qcs605-lc-ipcamera-overlay.dtbo-base := qcs605-lc.dtb
 qcs605-360camera-overlay.dtbo-base := qcs605.dtb
 qcs605-lc-cdp-overlay.dtbo-base := qcs605-lc-cdp-base.dtb
 sdm710-cdp-overlay.dtbo-base := sdm710.dtb
@@ -271,6 +273,7 @@
 	qcs605-mtp.dtb \
 	qcs605-cdp.dtb \
 	qcs605-external-codec-mtp.dtb \
+	qcs605-lc-ipcamera.dtb \
 	qcs605-lc-mtp.dtb \
 	qcs605-lc-cdp.dtb \
 	sdm710-mtp.dtb \
@@ -296,6 +299,16 @@
 endif
 
 ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y)
+dtbo-$(CONFIG_ARCH_MSM8917) += msm8917-mtp-overlay.dtbo \
+	msm8917-qrd-overlay.dtbo \
+	msm8917-cdp-overlay.dtbo \
+	msm8917-cdp-ext-codec-overlay.dtbo \
+	msm8917-cdp-ml-touch-overlay.dtbo \
+	msm8917-rcm-overlay.dtbo \
+	apq8017-mtp-overlay.dtbo \
+	apq8017-cdp-overlay.dtbo \
+	apq8017-cdp-wcd-rome-overlay.dtbo
+
 dtbo-$(CONFIG_ARCH_MSM8953) += msm8953-mtp-overlay.dtbo \
 	msm8953-cdp-overlay.dtbo \
 	msm8953-rcm-overlay.dtbo \
@@ -334,6 +347,33 @@
 	sdm429-cdp-overlay.dtbo \
 	sdm429-qrd-overlay.dtbo
 
+msm8917-mtp-overlay.dtbo-base := msm8917-pmi8950.dtb \
+	msm8917-pmi8937.dtb \
+	msm8917-pmi8940.dtb
+
+msm8917-qrd-overlay.dtbo-base := msm8917-pmi8937.dtb
+
+msm8917-cdp-ext-codec-overlay.dtbo-base := msm8917-pmi8950.dtb
+
+msm8917-cdp-ml-touch-overlay.dtbo-base := msm8917-pmi8950.dtb
+
+msm8917-cdp-overlay.dtbo-base := msm8917-pmi8950.dtb \
+	msm8917-pmi8937.dtb \
+	msm8917-pmi8940.dtb
+
+msm8917-rcm-overlay.dtbo-base := msm8917-pmi8950.dtb \
+	msm8917-pmi8937.dtb \
+	msm8917-pmi8940.dtb
+
+apq8017-mtp-overlay.dtbo-base := apq8017-pmi8950.dtb \
+	apq8017-pmi8937.dtb
+
+apq8017-cdp-overlay.dtbo-base := apq8017-pmi8950.dtb \
+	apq8017-pmi8937.dtb
+
+apq8017-cdp-wcd-rome-overlay.dtbo-base := apq8017-pmi8950.dtb \
+	apq8017-pmi8937.dtb
+
 msm8953-mtp-overlay.dtbo-base := sdm450.dtb \
 	msm8953.dtb \
 	apq8053.dtb \
@@ -462,13 +502,16 @@
 	msm8917-pmi8940-cdp.dtb \
 	msm8917-pmi8940-rcm.dtb
 
-dtb-$(CONFIG_ARCH_MSM8909) += msm8909w-bg-wtp-v2.dtb \
-	apq8009w-bg-wtp-v2.dtb \
-	apq8009w-bg-alpha.dtb \
+dtb-$(CONFIG_ARCH_MSM8909) += sdw3100-msm8909w-wtp.dtb \
+	sdw3100-apq8009w-wtp.dtb \
+	sdw3100-apq8009w-alpha.dtb \
 	apq8009-mtp-wcd9326-refboard.dtb \
 	apq8009-robot-som-refboard.dtb \
+	apq8009-robot-rome-refboard.dtb \
+	apq8009-robot-pronto-refboard.dtb \
 	apq8009-dragon.dtb \
-	apq8009-lat-v1.0.dtb
+	apq8009-lat-v1.0.dtb \
+	sdw3100-msm8909w-1gb-wtp.dtb
 
 dtb-$(CONFIG_ARCH_SDM450) += sdm450-rcm.dtb \
 	sdm450-cdp.dtb \
diff --git a/arch/arm64/boot/dts/qcom/apq8009-dragon.dts b/arch/arm64/boot/dts/qcom/apq8009-dragon.dts
index ba12854..041563b 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-dragon.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-dragon.dts
@@ -211,6 +211,7 @@
 
 &pm8916_chg {
 	status = "ok";
+	qcom,use-default-batt-values;
 };
 
 &pm8916_bms {
diff --git a/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
index 2afd5ac..71082c8 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
@@ -195,14 +195,6 @@
 				<79 512 2048000 4096000>; /* MAX */
 	};
 
-	vbus_otg_supply: vbus_otg_supply {
-		compatible = "regulator-fixed";
-		regulator-name = "vbus_otg";
-		status = "ok";
-		enable-active-high;
-		gpio = <&pm8916_gpios 3 0>;
-	};
-
 	usb_detect: qcom,gpio-usbdetect {
 		compatible = "qcom,gpio-usbdetect";
 		interrupt-parent = <&msm_gpio>;
@@ -325,12 +317,18 @@
 		qcom,iterm-ma = <200>;
 		qcom,recharge-thresh-mv = <100>;
 		qcom,thermal-mitigation = <1500 700 600 0>;
-		regulator-name = "smb1360_otg_vreg";
 		status= "okay";
+		smb1360_vbus: qcom,smb1360-vbus {
+			regulator-name = "qcom,smb1360-vbus";
+		};
 	};
 };
 
 &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>;
+	vbus_otg-supply = <&smb1360_vbus>;
 	extcon = <&smb1360_otg_supply>;
 };
 
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts
new file mode 100644
index 0000000..0ac8a31
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-pronto-refboard.dts
@@ -0,0 +1,380 @@
+/* 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 "msm8909-mtp.dtsi"
+#include "8909-pm8916.dtsi"
+#include "msm8909-pm8916-mtp.dtsi"
+#include "apq8009-audio-external_codec.dtsi"
+#include "apq8009-memory.dtsi"
+#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
+#include "msm8909-pm8916-camera.dtsi"
+#include "msm8909-pm8916-camera-sensor-robot.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8009 Robot-pronto RefBoard";
+	compatible = "qcom,apq8009-mtp", "qcom,apq8009", "qcom,mtp";
+	qcom,msm-id = <265 2>;
+	qcom,board-id= <8 0xE>;
+};
+
+&audio_codec_mtp {
+	status = "disabled";
+};
+
+&pm8916_gpios {
+	nfc_clk {
+		nfc_clk_default: nfc_clk_default {
+			status = "okay";
+		};
+	};
+};
+
+&msm_gpio {
+	hsuart_active: default {
+		mux {
+			pins = "gpio20", "gpio21", "gpio111", "gpio112";
+			function = "blsp_uart2";
+		};
+
+		config {
+			pins = "gpio20", "gpio21", "gpio111", "gpio112";
+			drive-strength = <16>;
+			bias-disable;
+		};
+	};
+
+	hsuart_sleep: sleep {
+		mux {
+			pins = "gpio20", "gpio21", "gpio111", "gpio112";
+			function = "blsp_uart2";
+		};
+
+		config {
+			pins = "gpio20", "gpio21", "gpio111", "gpio112";
+			drive-strength = <2>;
+			bias-disable;
+		};
+	};
+
+	usb_vbus_detect: usb_vbus_detect {
+		mux {
+			pins = "gpio97";
+			function = "gpio";
+		};
+
+		config {
+			pins = "gpio97";
+			drive-strength = <2>;
+			bias-disable;
+		};
+	};
+
+	usb_id_detect: usb_id_detect {
+		mux {
+			pins = "gpio110";
+			function = "gpio";
+		};
+
+		config {
+			pins = "gpio110";
+			drive-strength = <2>;
+			bias-pull-up;
+		};
+	};
+};
+
+&soc {
+	ext_codec: sound-9335 {
+		qcom,audio-routing =
+			"AIF4 VI", "MCLK",
+			"RX_BIAS", "MCLK",
+			"MADINPUT", "MCLK",
+			"AMIC2", "MIC BIAS2",
+			"MIC BIAS2", "Headset Mic",
+			"DMIC0", "MIC BIAS1",
+			"MIC BIAS1", "Digital Mic0",
+			"DMIC1", "MIC BIAS1",
+			"MIC BIAS1", "Digital Mic1",
+			"DMIC2", "MIC BIAS3",
+			"MIC BIAS3", "Digital Mic2",
+			"DMIC3", "MIC BIAS3",
+			"MIC BIAS3", "Digital Mic3",
+			"SpkrLeft IN", "SPK1 OUT",
+			"SpkrRight IN", "SPK2 OUT";
+
+		qcom,msm-gpios =
+			"us_eu_gpio";
+		qcom,pinctrl-names =
+			"all_off",
+			"us_eu_gpio_act";
+		pinctrl-names =
+			"all_off",
+			"us_eu_gpio_act";
+		pinctrl-0 = <&cross_conn_det_sus>;
+		pinctrl-1 = <&cross_conn_det_act>;
+		qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+		qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
+
+		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+					"SpkrLeft", "SpkrRight";
+	};
+
+	i2c@78b9000 {
+		synaptics@20 {
+			status = "disabled";
+		};
+	};
+
+	blsp1_uart2_hs: uart@78b0000 {
+		compatible = "qcom,msm-hsuart-v14";
+		reg = <0x78b0000 0x200>,
+			<0x7884000 0x1f000>;
+		reg-names = "core_mem", "bam_mem";
+		interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+		#address-cells = <0>;
+		interrupt-parent = <&blsp1_uart2_hs>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 108 0
+				1 &intc 0 238 0
+				2 &msm_gpio 21 0>;
+		qcom,inject-rx-on-wakeup;
+		qcom,rx-char-to-inject = <0xfd>;
+		qcom,master-id = <86>;
+		clock-names = "core_clk", "iface_clk";
+		clocks = <&clock_gcc clk_gcc_blsp1_uart2_apps_clk>,
+				<&clock_gcc clk_gcc_blsp1_ahb_clk>;
+		pinctrl-names = "sleep", "default";
+		pinctrl-0 = <&hsuart_sleep>;
+		pinctrl-1 = <&hsuart_active>;
+		qcom,bam-tx-ep-pipe-index = <2>;
+		qcom,bam-rx-ep-pipe-index = <3>;
+		qcom,msm-bus,name = "blsp1_uart2_hs";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<86 512 0 0>,
+				<86 512 500 800>;
+		status = "ok";
+	};
+
+	bluetooth: bt_qca9379 {
+		compatible = "qca,qca9379";
+		qca,bt-reset-gpio = <&msm_gpio 47 0>; /* BT_EN */
+	};
+
+	cnss_sdio: qcom,cnss_sdio {
+		compatible = "qcom,cnss_sdio";
+		subsys-name = "AR6320";
+		/**
+		 * There is no vdd-wlan on board and this is not for DSRC.
+		 * IO and XTAL share the same vreg.
+		 **/
+		vdd-wlan-io-supply = <&pm8916_l5>;
+		qcom,cap-tsf-gpio = <&msm_gpio 42 1>;
+		qcom,wlan-ramdump-dynamic = <0x200000>;
+		qcom,msm-bus,name = "msm-cnss";
+		qcom,msm-bus,num-cases = <4>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<79 512 0 0>,             /* No vote */
+				<79 512 6250 200000>,     /* 50 Mbps */
+				<79 512 25000 200000>,    /* 200 Mbps */
+				<79 512 2048000 4096000>; /* MAX */
+	};
+
+	usb_detect: qcom,gpio-usbdetect {
+		compatible = "qcom,gpio-usbdetect";
+		interrupt-parent = <&msm_gpio>;
+		interrupts = <97 0>;
+		interrupt-names = "vbus_det_irq";
+		pinctrl-names = "usb_vbus_detect", "usb_id_detect";
+		pinctrl-0 = <&usb_vbus_detect>;
+		pinctrl-1 = <&usb_id_detect>;
+		qcom,gpio-mode-sel = <&msm_gpio 97 0>;
+		qcom,id-det-gpio = <&msm_gpio 110 0>;
+		qcom,dpdm_switch_gpio = <&pm8916_gpios 3 0>;
+	};
+
+	i2c@78b8000 {
+		wcd9xxx_codec@d {
+			status = "okay";
+			qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+		};
+	};
+
+	cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&pri_mi2s_active &pri_mi2s_ws_active
+		     &pri_mi2s_dout_active &pri_mi2s_din_active>;
+		pinctrl-1 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
+		     &pri_mi2s_dout_sleep &pri_mi2s_din_sleep>;
+	};
+
+	cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
+		pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+	};
+
+	wcd_rst_gpio: wcd_gpio_ctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_reset_active>;
+		pinctrl-1 = <&cdc_reset_sleep>;
+	};
+};
+
+&wcnss {
+	status = "disabled";
+};
+
+&msm_gpio {
+	sdc2_wlan_gpio_on: sdc2_wlan_gpio_on {
+		mux {
+			pins = "gpio43";
+			function = "gpio";
+		};
+		config {
+			pins = "gpio43";
+			drive-strength = <10>;
+			bias-pull-up;
+			output-high;
+		};
+	};
+
+	sdc2_wlan_gpio_off: sdc2_wlan_gpio_off {
+		mux {
+			pins = "gpio43";
+			function = "gpio";
+		};
+		config {
+			pins = "gpio43";
+			drive-strength = <2>;
+			bias-disable;
+			output-low;
+		};
+	};
+};
+
+&sdhc_2 {
+	/delete-property/cd-gpios;
+	#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 &msm_gpio 38 0>;
+	interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+	qcom,vdd-voltage-level = <1800000 2950000>;
+	qcom,vdd-current-level = <15000 400000>;
+
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 50000>;
+	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on
+	&sdc2_wlan_gpio_on>;
+	pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off
+	&sdc2_wlan_gpio_off>;
+	qcom,nonremovable;
+	qcom,core_3_0v_support;
+	status = "ok";
+};
+
+&i2c_4 {
+	status= "okay";
+	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>;
+		status= "okay";
+		smb1360_vbus: qcom,smb1360-vbus {
+			regulator-name = "qcom,smb1360-vbus";
+		};
+	};
+};
+
+&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>;
+	vbus_otg-supply = <&smb1360_vbus>;
+	extcon = <&smb1360_otg_supply>;
+};
+
+&mdss_fb0 {
+	status = "disabled";
+	/delete-node/ qcom,cont-splash-memory;
+};
+
+&mdss_mdp {
+	status = "disabled";
+};
+
+&mdss_dsi0_pll {
+	status = "disabled";
+};
+
+&mdss_dsi0 {
+	status = "disabled";
+};
+
+&i2c_1 {
+	status = "disabled";
+};
+
+&i2c_2 {
+	status = "disabled";
+};
+
+&i2c_5 {
+	status = "disabled";
+};
+
+&spi_0 {
+	status = "disabled";
+};
+
+&wcd_rst_gpio {
+	status = "okay";
+};
+
+&ext_codec {
+	status = "okay";
+};
+
+&blsp1_uart2_hs {
+	status = "disabled";
+};
+
+/delete-node/ &cont_splash_mem;
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-rome-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-rome-refboard.dts
new file mode 100644
index 0000000..66070b7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-rome-refboard.dts
@@ -0,0 +1,380 @@
+/* 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 "msm8909-mtp.dtsi"
+#include "8909-pm8916.dtsi"
+#include "msm8909-pm8916-mtp.dtsi"
+#include "apq8009-audio-external_codec.dtsi"
+#include "apq8009-memory.dtsi"
+#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
+#include "msm8909-pm8916-camera.dtsi"
+#include "msm8909-pm8916-camera-sensor-robot.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8009 Robot-rome RefBoard";
+	compatible = "qcom,apq8009-mtp", "qcom,apq8009", "qcom,mtp";
+	qcom,msm-id = <265 2>;
+	qcom,board-id= <8 0x10>;
+};
+
+&audio_codec_mtp {
+	status = "disabled";
+};
+
+&pm8916_gpios {
+	nfc_clk {
+		nfc_clk_default: nfc_clk_default {
+			status = "okay";
+		};
+	};
+};
+
+&msm_gpio {
+	hsuart_active: default {
+		mux {
+			pins = "gpio20", "gpio21", "gpio111", "gpio112";
+			function = "blsp_uart2";
+		};
+
+		config {
+			pins = "gpio20", "gpio21", "gpio111", "gpio112";
+			drive-strength = <16>;
+			bias-disable;
+		};
+	};
+
+	hsuart_sleep: sleep {
+		mux {
+			pins = "gpio20", "gpio21", "gpio111", "gpio112";
+			function = "blsp_uart2";
+		};
+
+		config {
+			pins = "gpio20", "gpio21", "gpio111", "gpio112";
+			drive-strength = <2>;
+			bias-disable;
+		};
+	};
+
+	usb_vbus_detect: usb_vbus_detect {
+		mux {
+			pins = "gpio97";
+			function = "gpio";
+		};
+
+		config {
+			pins = "gpio97";
+			drive-strength = <2>;
+			bias-disable;
+		};
+	};
+
+	usb_id_detect: usb_id_detect {
+		mux {
+			pins = "gpio110";
+			function = "gpio";
+		};
+
+		config {
+			pins = "gpio110";
+			drive-strength = <2>;
+			bias-pull-up;
+		};
+	};
+};
+
+&soc {
+	ext_codec: sound-9335 {
+		qcom,audio-routing =
+			"AIF4 VI", "MCLK",
+			"RX_BIAS", "MCLK",
+			"MADINPUT", "MCLK",
+			"AMIC2", "MIC BIAS2",
+			"MIC BIAS2", "Headset Mic",
+			"DMIC0", "MIC BIAS1",
+			"MIC BIAS1", "Digital Mic0",
+			"DMIC1", "MIC BIAS1",
+			"MIC BIAS1", "Digital Mic1",
+			"DMIC2", "MIC BIAS3",
+			"MIC BIAS3", "Digital Mic2",
+			"DMIC3", "MIC BIAS3",
+			"MIC BIAS3", "Digital Mic3",
+			"SpkrLeft IN", "SPK1 OUT",
+			"SpkrRight IN", "SPK2 OUT";
+
+		qcom,msm-gpios =
+			"us_eu_gpio";
+		qcom,pinctrl-names =
+			"all_off",
+			"us_eu_gpio_act";
+		pinctrl-names =
+			"all_off",
+			"us_eu_gpio_act";
+		pinctrl-0 = <&cross_conn_det_sus>;
+		pinctrl-1 = <&cross_conn_det_act>;
+		qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+		qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
+
+		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+					"SpkrLeft", "SpkrRight";
+	};
+
+	i2c@78b9000 {
+		synaptics@20 {
+			status = "disabled";
+		};
+	};
+
+	blsp1_uart2_hs: uart@78b0000 {
+		compatible = "qcom,msm-hsuart-v14";
+		reg = <0x78b0000 0x200>,
+			<0x7884000 0x1f000>;
+		reg-names = "core_mem", "bam_mem";
+		interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+		#address-cells = <0>;
+		interrupt-parent = <&blsp1_uart2_hs>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 108 0
+				1 &intc 0 238 0
+				2 &msm_gpio 21 0>;
+		qcom,inject-rx-on-wakeup;
+		qcom,rx-char-to-inject = <0xfd>;
+		qcom,master-id = <86>;
+		clock-names = "core_clk", "iface_clk";
+		clocks = <&clock_gcc clk_gcc_blsp1_uart2_apps_clk>,
+				<&clock_gcc clk_gcc_blsp1_ahb_clk>;
+		pinctrl-names = "sleep", "default";
+		pinctrl-0 = <&hsuart_sleep>;
+		pinctrl-1 = <&hsuart_active>;
+		qcom,bam-tx-ep-pipe-index = <2>;
+		qcom,bam-rx-ep-pipe-index = <3>;
+		qcom,msm-bus,name = "blsp1_uart2_hs";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<86 512 0 0>,
+				<86 512 500 800>;
+		status = "ok";
+	};
+
+	bluetooth: bt_qca9379 {
+		compatible = "qca,qca9379";
+		qca,bt-reset-gpio = <&msm_gpio 47 0>; /* BT_EN */
+	};
+
+	cnss_sdio: qcom,cnss_sdio {
+		compatible = "qcom,cnss_sdio";
+		subsys-name = "AR6320";
+		/**
+		 * There is no vdd-wlan on board and this is not for DSRC.
+		 * IO and XTAL share the same vreg.
+		 **/
+		vdd-wlan-io-supply = <&pm8916_l5>;
+		qcom,cap-tsf-gpio = <&msm_gpio 42 1>;
+		qcom,wlan-ramdump-dynamic = <0x200000>;
+		qcom,msm-bus,name = "msm-cnss";
+		qcom,msm-bus,num-cases = <4>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<79 512 0 0>,             /* No vote */
+				<79 512 6250 200000>,     /* 50 Mbps */
+				<79 512 25000 200000>,    /* 200 Mbps */
+				<79 512 2048000 4096000>; /* MAX */
+	};
+
+	usb_detect: qcom,gpio-usbdetect {
+		compatible = "qcom,gpio-usbdetect";
+		interrupt-parent = <&msm_gpio>;
+		interrupts = <97 0>;
+		interrupt-names = "vbus_det_irq";
+		pinctrl-names = "usb_vbus_detect", "usb_id_detect";
+		pinctrl-0 = <&usb_vbus_detect>;
+		pinctrl-1 = <&usb_id_detect>;
+		qcom,gpio-mode-sel = <&msm_gpio 97 0>;
+		qcom,id-det-gpio = <&msm_gpio 110 0>;
+		qcom,dpdm_switch_gpio = <&pm8916_gpios 3 0>;
+	};
+
+	i2c@78b8000 {
+		wcd9xxx_codec@d {
+			status = "okay";
+			qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+		};
+	};
+
+	cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&pri_mi2s_active &pri_mi2s_ws_active
+		     &pri_mi2s_dout_active &pri_mi2s_din_active>;
+		pinctrl-1 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
+		     &pri_mi2s_dout_sleep &pri_mi2s_din_sleep>;
+	};
+
+	cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
+		pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+	};
+
+	wcd_rst_gpio: wcd_gpio_ctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_reset_active>;
+		pinctrl-1 = <&cdc_reset_sleep>;
+	};
+};
+
+&wcnss {
+	status = "disabled";
+};
+
+&msm_gpio {
+	sdc2_wlan_gpio_on: sdc2_wlan_gpio_on {
+		mux {
+			pins = "gpio43";
+			function = "gpio";
+		};
+		config {
+			pins = "gpio43";
+			drive-strength = <10>;
+			bias-pull-up;
+			output-high;
+		};
+	};
+
+	sdc2_wlan_gpio_off: sdc2_wlan_gpio_off {
+		mux {
+			pins = "gpio43";
+			function = "gpio";
+		};
+		config {
+			pins = "gpio43";
+			drive-strength = <2>;
+			bias-disable;
+			output-low;
+		};
+	};
+};
+
+&sdhc_2 {
+	/delete-property/cd-gpios;
+	#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 &msm_gpio 38 0>;
+	interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+	qcom,vdd-voltage-level = <1800000 2950000>;
+	qcom,vdd-current-level = <15000 400000>;
+
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 50000>;
+	qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on
+	&sdc2_wlan_gpio_on>;
+	pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off
+	&sdc2_wlan_gpio_off>;
+	qcom,nonremovable;
+	qcom,core_3_0v_support;
+	status = "ok";
+};
+
+&i2c_4 {
+	status= "okay";
+	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>;
+		status= "okay";
+		smb1360_vbus: qcom,smb1360-vbus {
+			regulator-name = "qcom,smb1360-vbus";
+		};
+	};
+};
+
+&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>;
+	vbus_otg-supply = <&smb1360_vbus>;
+	extcon = <&smb1360_otg_supply>;
+};
+
+&mdss_fb0 {
+	status = "disabled";
+	/delete-node/ qcom,cont-splash-memory;
+};
+
+&mdss_mdp {
+	status = "disabled";
+};
+
+&mdss_dsi0_pll {
+	status = "disabled";
+};
+
+&mdss_dsi0 {
+	status = "disabled";
+};
+
+&i2c_1 {
+	status = "disabled";
+};
+
+&i2c_2 {
+	status = "disabled";
+};
+
+&i2c_5 {
+	status = "disabled";
+};
+
+&spi_0 {
+	status = "disabled";
+};
+
+&wcd_rst_gpio {
+	status = "okay";
+};
+
+&ext_codec {
+	status = "okay";
+};
+
+&blsp1_uart2_hs {
+	status = "disabled";
+};
+
+/delete-node/ &cont_splash_mem;
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
index 1314129..ab711dd 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
@@ -17,6 +17,8 @@
 #include "8909-pm8916.dtsi"
 #include "msm8909-pm8916-mtp.dtsi"
 #include "apq8009-audio-external_codec.dtsi"
+#include "msm8909-pm8916-camera.dtsi"
+#include "msm8909-pm8916-camera-sensor-robot-som.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. APQ8009 Robot SOM refboard";
@@ -25,37 +27,147 @@
 	qcom,board-id = <8 0x15>;
 };
 
+&audio_codec_mtp {
+	status = "disabled";
+};
+
+&i2c_4 {
+	status= "okay";
+};
+
+&pm8916_gpios {
+	wcd_vdd_en { /* GPIO 4 */
+		wcd_vdd_en_active: wcd_vdd_en_active {
+			status = "ok";
+			pins = "gpio4";
+			function = "normal";
+			output-high;
+			qcom,drive-strength = <2>;
+		};
+		wcd_vdd_en_sleep: wcd_vdd_en_sleep {
+			status = "ok";
+			pins = "gpio4";
+			function = "normal";
+			output-low;
+			qcom,drive-strength = <2>;
+		};
+
+	};
+};
+
 &soc {
-	ext-codec {
-		qcom,msm-mbhc-hphl-swh = <0>;
+	ext_codec: sound-9335 {
+		compatible = "qcom,apq8009-audio-i2s-codec";
+		qcom,model = "apq8009-tashalite-snd-card-tdm";
+
 		qcom,audio-routing =
 			"AIF4 VI", "MCLK",
 			"RX_BIAS", "MCLK",
 			"MADINPUT", "MCLK",
-			"AMIC2", "MIC BIAS2",
-			"MIC BIAS2", "Headset Mic",
-			"DMIC0", "MIC BIAS1",
-			"MIC BIAS1", "Digital Mic0",
-			"DMIC1", "MIC BIAS1",
-			"MIC BIAS1", "Digital Mic1",
-			"DMIC2", "MIC BIAS3",
-			"MIC BIAS3", "Digital Mic2",
-			"DMIC3", "MIC BIAS3",
-			"MIC BIAS3", "Digital Mic3",
 			"SpkrLeft IN", "SPK1 OUT",
 			"SpkrRight IN", "SPK2 OUT";
+
+		qcom,tdm-i2s-switch-enable = <&msm_gpio 88 0>;
+		qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+		qcom,quat-mi2s-gpios = <&cdc_quat_tdm_gpios>;
 	};
 
-	sound-9335 {
-		status = "disabled";
+	clock_audio: audio_ext_clk {
+		compatible = "qcom,audio-ref-clk";
+		qcom,codec-mclk-clk-freq = <9600000>;
+		qcom,lpass-clock = <1>;
+		reg = <0x07702004 0x4>;
+		pinctrl-names = "sleep", "active";
+		pinctrl-0 = <&i2s_mclk_sleep>;
+		pinctrl-1 = <&i2s_mclk_active>;
+		#clock-cells = <1>;
 	};
 
 	i2c@78b8000 {
 		wcd9xxx_codec@d {
-		  status = "disabled";
+			status = "okay";
+			compatible = "qcom,tasha-i2c-pgd";
+			reg = <0x0d>;
+
+			interrupt-parent = <&wcd9xxx_intc>;
+			interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+				17 18 19 20 21 22 23 24 25 26 27 28 29
+				30>;
+
+			qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+
+			qcom,has-buck-vsel-gpio;
+			qcom,buck-vsel-gpio-node = <&wcd_vdd_gpio>;
+			swr_master {
+				compatible = "qcom,swr-wcd";
+				qcom,swr-num-dev = <2>;
+				#address-cells = <2>;
+				#size-cells = <0>;
+
+				wsa881x_211:wsa881x@21170211 {
+					compatible = "qcom,wsa881x";
+					reg = <0x00 0x21170211>;
+					qcom,spkr-sd-n-node = <&wsa_spkr>;
+				};
+
+				wsa881x_212:wsa881x@21170212 {
+					compatible = "qcom,wsa881x";
+					reg = <0x00 0x21170212>;
+					qcom,spkr-sd-n-node = <&wsa_spkr>;
+				};
+
+				wsa881x_213:wsa881x@21170213 {
+					compatible = "qcom,wsa881x";
+					reg = <0x00 0x21170213>;
+					qcom,spkr-sd-n-node = <&wsa_spkr>;
+				};
+
+				wsa881x_214:wsa881x@21170214 {
+					compatible = "qcom,wsa881x";
+					reg = <0x00 0x21170214>;
+					qcom,spkr-sd-n-node = <&wsa_spkr>;
+				};
+			};
 		};
 	};
 
+	cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&pri_mi2s_active &pri_mi2s_ws_active
+		     &pri_mi2s_dout_active &pri_mi2s_din_active>;
+		pinctrl-1 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
+		     &pri_mi2s_dout_sleep &pri_mi2s_din_sleep>;
+	};
+
+	cdc_quat_tdm_gpios: msm_cdc_pinctrl_quat {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
+		pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+	};
+
+	wcd_rst_gpio: wcd_gpio_ctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_reset1_active>;
+		pinctrl-1 = <&cdc_reset1_sleep>;
+	};
+
+	wcd_vdd_gpio: wcd_vdd_gpio_ctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&wcd_vdd_en_active>;
+		pinctrl-1 = <&wcd_vdd_en_sleep>;
+	};
+
+	wsa_spkr: msm_cdc_pinctrll {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&spkr_en_active>;
+		pinctrl-1 = <&spkr_en_sleep>;
+	};
+
 	vph_pwr_vreg: vph_pwr_vreg {
 		compatible = "regulator-fixed";
 		status = "ok";
@@ -63,6 +175,23 @@
 		regulator-always-on;
 	};
 
+	otg_vreg_5p0: otg_vreg_5p0 {
+		compatible = "regulator-fixed";
+		regulator-name = "sbc_vreg_5p0";
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+		status = "ok";
+		enable-active-low;
+		vin-supply = <&vph_pwr_vreg>;
+	};
+
+	vbus_otg_vreg: vbus_otg_vreg {
+		compatible = "regulator-fixed";
+		regulator-name = "vbus_otg_vreg";
+		gpio = <&msm_gpio 74 0>;
+		vin-supply = <&otg_vreg_5p0>;
+	};
+
 	mdss_mdp: qcom,mdss_mdp@1a00000 {
 		status = "disabled";
 	};
@@ -90,6 +219,44 @@
 			<79 512 25000 200000>,    /* 200 Mbps */
 			<79 512 2048000 4096000>; /* MAX */
 	};
+
+	gpio_keys {
+		status = "disable";
+	};
+
+	spi@78ba000 {
+		reg = <0x78ba000 0x600>;
+		spi-max-frequency = <50000000>;
+		status = "okay";
+
+		spi@0 {
+			compatible = "qcom,spi-msm-slave";
+			reg = <0>;
+			spi-max-frequency = <50000000>;
+		};
+	};
+};
+
+&i2c_1 {
+	status = "okay";
+	icm20602@68 {
+		compatible = "invensense,icm20602";
+		reg = <0x68>;
+		interrupt-parent = <&msm_gpio>;
+		interrupts = <12 0>;
+		invensense,icm20602-gpio = <&msm_gpio 12 0x0>;
+		vdd-ldo-supply = <&pm8916_l6>;
+		interrupt-names = "icm20602_irq";
+		pinctrl-names = "imu_active","imu_suspend";
+		pinctrl-0 = <&imu_int_active>;
+		pinctrl-1 = <&imu_int_suspend>;
+		status = "ok";
+	};
+	vl53l0x@29 {
+		compatible = "st,stmvl53l0";
+		reg = <0x29>;
+		status = "ok";
+	};
 };
 
 &wcnss {
@@ -133,7 +300,7 @@
 	interrupt-map-mask = <0xffffffff>;
 	interrupt-map = <0 &intc 0 125 0
 		1 &intc 0 221 0
-		2 &msm_gpio 38 0>;
+		2 &msm_gpio 40 0x1>;
 	interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
 
 	qcom,vdd-voltage-level = <1800000 2950000>;
@@ -159,8 +326,8 @@
 	interrupt-names = "core_irq", "async_irq", "phy_irq";
 	qcom,hsusb-otg-mode = <3>;
 	qcom,switch-vbus-w-id;
-	vbus_otg-supply = <&vph_pwr_vreg>;
-	extcon = <&pm8916_chg>;
+	qcom,phy-id-high-as-peripheral;
+	vbus_otg-supply = <&vbus_otg_vreg>;
 };
 
 &external_image_mem {
@@ -195,3 +362,12 @@
 		status = "ok";
 	};
 };
+
+
+&wcd_rst_gpio {
+	status = "okay";
+};
+
+&ext_codec {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8009w-bg-memory.dtsi b/arch/arm64/boot/dts/qcom/apq8009w-bg-memory.dtsi
index d83ae5c..fef9f45 100644
--- a/arch/arm64/boot/dts/qcom/apq8009w-bg-memory.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8009w-bg-memory.dtsi
@@ -22,3 +22,14 @@
 &peripheral_mem {
 	reg = <0x0 0x8a300000 0x0 0x0600000>;
 };
+
+&reserved_mem {
+	linux,cma {
+		compatible = "shared-dma-pool";
+		alloc-ranges = <0 0x00000000 0 0xa0000000>;
+		reusable;
+		alignment = <0 0x400000>;
+		size = <0 0x1000000>;
+		linux,cma-default;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8017-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/apq8017-cdp-overlay.dts
new file mode 100644
index 0000000..21e47bf
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8017-cdp-overlay.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/;
+/plugin/;
+
+#include "msm8917-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8017-CDP";
+	qcom,board-id = <1 0>;
+	qcom,msm-id = <307 0x0>;
+};
+
+&mdss_fb0 {
+	/delete-node/ qcom,cont-splash-memory;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8017-cdp-wcd-rome-overlay.dts b/arch/arm64/boot/dts/qcom/apq8017-cdp-wcd-rome-overlay.dts
new file mode 100644
index 0000000..4f07399
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8017-cdp-wcd-rome-overlay.dts
@@ -0,0 +1,83 @@
+/*
+ * 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 "msm8917-cdp.dtsi"
+#include "apq8017-rome.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8017-CDP \
+					with WCD codec/Rome card";
+	qcom,board-id = <1 2>;
+	qcom,msm-id = <307 0x0>;
+};
+
+&blsp1_uart1 {
+	status = "ok";
+};
+
+&sdhc_2 {
+	/* device core power supply */
+	/delete-property/vdd-supply;
+	/delete-property/qcom,vdd-voltage-level;
+	/delete-property/qcom,vdd-current-level;
+
+	/* device communication power supply */
+	vdd-io-supply = <&pm8937_l5>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 325000>;
+
+	qcom,core_3_0v_support;
+	qcom,nonremovable;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on
+			&sdc2_wlan_gpio_active>;
+	pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off
+			&sdc2_wlan_gpio_sleep>;
+
+	#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 124 0x4>;
+	interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+	/delete-property/cd-gpios;
+	/delete-property/qcom,devfreq,freq-table;
+
+	status = "ok";
+
+};
+
+&modem_mem {
+	reg = <0x0 0x86800000 0x0 0x1500000>;
+};
+
+&adsp_fw_mem {
+	reg = <0x0 0x87d00000 0x0 0x1100000>;
+};
+
+&wcnss_fw_mem {
+	reg = <0x0 0x88e00000 0x0 0x700000>;
+};
+
+&secure_mem {
+	status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8017-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/apq8017-mtp-overlay.dts
new file mode 100644
index 0000000..0b958ee
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8017-mtp-overlay.dts
@@ -0,0 +1,79 @@
+/*
+ * 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 "msm8917-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8017-MTP";
+	qcom,board-id = <8 0>;
+	qcom,msm-id = <307 0x0>;
+};
+
+&blsp1_uart1 {
+	status = "ok";
+};
+
+&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>;
+};
+
+&i2c_2 {
+	/* DSI_TO_HDMI I2C configuration */
+	adv7533@39 {
+		compatible = "adv7533";
+		reg = <0x39>;
+		instance_id = <0>;
+		adi,video-mode = <3>; /* 3 = 1080p */
+		adi,main-addr = <0x39>;
+		adi,cec-dsi-addr = <0x3C>;
+		adi,enable-audio;
+		adi,irq-gpio = <&tlmm 0x29 0x2002>;
+		adi,power-down-gpio = <&tlmm 0x7D 0x0>;
+		adi,switch-gpio = <&pm8937_gpios 0x8 0x1>;
+		pinctrl-names = "pmx_adv7533_active",
+					"pmx_adv7533_suspend";
+		pinctrl-0 = <&adv7533_int_active>;
+		pinctrl-1 = <&adv7533_int_suspend>;
+	};
+};
+
+&mdss_dsi {
+	hw-config = "single_dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_adv7533_1080p>;
+	qcom,platform-intf-mux-gpio = <&tlmm 115 0>;
+	status = "ok";
+	qcom,bridge-index = <0>;
+	qcom,pluggable;
+};
+
+&dsi_adv7533_1080p {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8017-pmi8937.dts b/arch/arm64/boot/dts/qcom/apq8017-pmi8937.dts
new file mode 100644
index 0000000..c060461
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8017-pmi8937.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 "apq8017.dtsi"
+#include "msm8917-pmi8937.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917 + PMI8937 SOC";
+	compatible = "qcom,msm8917";
+	qcom,pmic-id = <0x10019 0x020037 0x0 0x0>;
+	qcom,pmic-name = "PMI8937";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8017-pmi8950.dts b/arch/arm64/boot/dts/qcom/apq8017-pmi8950.dts
new file mode 100644
index 0000000..5fc2b60
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8017-pmi8950.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 "apq8017.dtsi"
+#include "msm8917-pmi8950.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917 + PMI8950 SOC ";
+	compatible = "qcom,msm8917";
+	qcom,pmic-id = <0x10019 0x010011 0x0 0x0>;
+	qcom,pmic-name = "PMI8950";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-dragon-memory.dtsi b/arch/arm64/boot/dts/qcom/apq8053-dragon-memory.dtsi
new file mode 100644
index 0000000..a26926a
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-dragon-memory.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.
+ */
+
+&modem_mem {
+	reg = <0x0 0x86c00000 0x0 0x1800000>;
+};
+
+&adsp_fw_mem {
+	reg = <0x0 0x88400000 0x0 0x1100000>;
+};
+
+&wcnss_fw_mem {
+	reg = <0x0 0x89500000 0x0 0x700000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-ipc.dts b/arch/arm64/boot/dts/qcom/apq8053-ipc.dts
index 3381b2a..5004d71 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-ipc.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053-ipc.dts
@@ -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
@@ -15,7 +15,8 @@
 
 #include "apq8053.dtsi"
 #include "msm8953-ipc.dtsi"
-
+#include "pmi8950.dtsi"
+#include "msm8953-pmi8950.dtsi"
 / {
 	model = "Qualcomm Technologies, Inc. APQ8053 + PMI8950 IPC";
 	compatible = "qcom,apq8053-ipc", "qcom,apq8053", "qcom,ipc";
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.0.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.0.dts
index 55d8b7b..9961a97 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.0.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.0.dts
@@ -25,3 +25,8 @@
 &blsp2_uart0 {
 	status = "okay";
 };
+
+&blsp2_uart1 { /* UART6 */
+	status = "okay";
+};
+
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts
index ecc4fea..8b5dd2b 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dts
@@ -25,3 +25,81 @@
 &blsp2_uart0 {
 	status = "okay";
 };
+
+&i2c_3 {
+	status = "okay";
+	/delete-node/ himax_ts@48;
+	gt9xx-i2c@14 {
+		compatible = "goodix,gt9xx";
+		status = "okay";
+		reg = <0x14>;
+		vdd_ana-supply = <&pm8953_l10>;
+		vcc_i2c-supply = <&pm8953_l6>;
+		interrupt-parent = <&tlmm>;
+		interrupts = <65 0x2008>;
+		pinctrl-names = "gdix_ts_int_default", "gdix_ts_int_output_low",
+			"gdix_ts_int_output_high", "gdix_ts_int_input",
+			"gdix_ts_rst_default", "gdix_ts_rst_output_low",
+			"gdix_ts_rst_output_high", "gdix_ts_rst_input";
+		pinctrl-0 = <&ts_int_default>;
+		pinctrl-1 = <&ts_int_output_low>;
+		pinctrl-2 = <&ts_int_output_high>;
+		pinctrl-3 = <&ts_int_input>;
+		pinctrl-4 = <&ts_rst_default>;
+		pinctrl-5 = <&ts_rst_output_low>;
+		pinctrl-6 = <&ts_rst_output_high>;
+		pinctrl-7 = <&ts_rst_input>;
+
+		reset-gpios = <&tlmm 64 0x00>;
+		irq-gpios = <&tlmm 65 0x2008>;
+		irq-flags = <2>;
+
+		touchscreen-max-id = <11>;
+		touchscreen-size-x = <1200>;
+		touchscreen-size-y = <1920>;
+		touchscreen-max-w = <1024>;
+		touchscreen-max-p = <1024>;
+
+		goodix,type-a-report = <0>;
+		goodix,driver-send-cfg = <1>;
+		goodix,wakeup-with-reset = <0>;
+		goodix,resume-in-workqueue = <0>;
+		goodix,int-sync = <1>;
+		goodix,swap-x2y = <0>;
+		goodix,esd-protect = <1>;
+		goodix,pen-suppress-finger = <0>;
+		goodix,auto-update = <1>;
+		goodix,auto-update-cfg = <0>;
+		goodix,power-off-sleep = <0>;
+
+		goodix,cfg-group0 = [
+			5A B0 04 80 07 0A 35 10 22 08 32 0D 50 3C 0A 04
+			01 01 00 B4 11 11 44 15 19 1B 14 95 35 FF 3A 3C
+			39 13 00 00 00 98 03 1C 00 00 00 00 03 00 00 00
+			00 80 0A 37 46 40 E5 52 23 28 00 04 81 38 00 7F
+			3B 00 7D 3E 00 7C 41 00 7A 44 0C 7A 00 50 33 50
+			0B 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+			00 00 00 00 00 00 00 55 00 01 00 00 02 00 00 00
+			1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E
+			0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00 2A 29
+			28 27 26 25 24 23 22 21 20 1F 1E 1D 1C 1B 19 18
+			17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08
+			07 06 05 04 03 02 01 00 08 01
+		];
+
+		goodix,cfg-group2 = [
+			5B B0 04 80 07 0A 35 10 22 08 32 0D 50 32 0A 04
+			01 01 00 B4 11 11 44 2B 31 36 28 95 35 FF 3E 40
+			39 13 00 00 00 DA 03 1C 00 00 00 00 03 00 00 00
+			00 80 0A 32 42 40 E5 52 23 28 00 04 7D 33 00 7D
+			36 00 7E 39 00 7F 3C 00 80 40 0C 80 00 50 33 50
+			0B 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+			00 00 00 00 00 00 00 55 00 01 00 00 02 00 00 00
+			1D 1C 1B 1A 19 18 17 16 15 14 13 12 11 10 0F 0E
+			0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 00 2A 29
+			28 27 26 25 24 23 22 21 20 1F 1E 1D 1C 1B 19 18
+			17 16 15 14 13 12 11 10 0F 0E 0D 0C 0B 0A 09 08
+			07 06 05 04 03 02 01 00 81 01
+		];
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.3.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.3.dtsi
index 5cf8ac0..c682f58 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.3.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.3.dtsi
@@ -42,6 +42,7 @@
 
 &i2c_3 {
 	status = "okay";
+	/delete-node/ focaltech@38;
 	/delete-node/ himax_ts@48;
 	focaltech_ts@38 {
 		compatible = "focaltech,fts";
@@ -64,6 +65,7 @@
 };
 
 &wled {
+	qcom,cons-sync-write-delay-us = <1000>;
 	qcom,led-strings-list = [00 01 02];
 };
 
@@ -78,3 +80,19 @@
 &camera2{
 	qcom,mount-angle = <90>;
 };
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_hx8394d_kingdisplay_vid>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+	pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+
+	vdd-supply = <&pm8953_l17>;
+	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>;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
index bd48f09..90b1d4f 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
@@ -16,6 +16,7 @@
 #include "apq8053-camera-sensor-dragon.dtsi"
 #include "pmi8950.dtsi"
 #include "msm8953-pmi8950.dtsi"
+#include "apq8053-dragon-memory.dtsi"
 
 &soc {
 	vreg_5p0: vreg_5p0 {
@@ -103,6 +104,25 @@
 		pinctrl-1 = <&sec_tlmm_lines_sus>;
 	};
 
+	gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpio_key_active>;
+		vol_up {
+			label = "volume_up";
+			gpios = <&tlmm 85 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
+		};
+	};
+
+	qcom,rmnet-ipa {
+		status = "disabled";
+	};
 };
 
 &firmware {
@@ -319,7 +339,7 @@
 			pins = "gpio75";
 			drive-strength = <10>;
 			bias-pull-up;
-			output-low;
+			output-high;
 		};
 	};
 	sdc2_wlan_gpio_off: sdc2_wlan_gpio_off {
@@ -358,14 +378,6 @@
 };
 
 &spmi_bus {
-	qcom,pm8953@0 {
-		qcom,power-on@800 {
-			qcom,resin-gpiobase = <1019>;
-			qcom,pon_2 {
-				/delete-property/ linux,code;
-			};
-		};
-	};
 	qcom,pmi8950@2 {
 		qcom,leds@a100 {
 			compatible = "qcom,leds-qpnp";
@@ -495,3 +507,11 @@
 		status = "okay";
 	};
 };
+
+&ipa_hw {
+	status = "disabled";
+};
+
+&msm_gpu {
+	/delete-node/ qcom,gpu-mempools;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite.dtsi
index 5be35e7..c9d7160 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite.dtsi
@@ -18,7 +18,7 @@
 	model = "Qualcomm Technologies, Inc. APQ 8953 Lite";
 	compatible = "qcom,apq8053";
 	qcom,msm-id = <304 0x0>;
-	interrupt-parent = <&intc>;
+	interrupt-parent = <&wakegic>;
 
 	soc: soc { };
 };
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-hx83112a-truly-singlemipi-fhd-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-hx83112a-truly-singlemipi-fhd-video.dtsi
new file mode 100644
index 0000000..e065f00
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx83112a-truly-singlemipi-fhd-video.dtsi
@@ -0,0 +1,157 @@
+/* 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_hx83112a_truly_video: qcom,mdss_dsi_hx83112a_truly_video {
+		qcom,mdss-dsi-panel-name =
+			"hx83112a video mode dsi truly panel";
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		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-h-sync-pulse = <0>;
+		qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
+		qcom,mdss-dsi-lane-map = "lane_map_0123";
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-tx-eot-append;
+		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-dma-trigger = "trigger_sw";
+		qcom,mdss-dsi-mdp-trigger = "none";
+		qcom,mdss-dsi-lp11-init;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+
+		qcom,mdss-dsi-display-timings {
+			timing@0 {
+				qcom,mdss-dsi-panel-width = <1080>;
+				qcom,mdss-dsi-panel-height = <2160>;
+				qcom,mdss-dsi-h-front-porch = <42>;
+				qcom,mdss-dsi-h-back-porch = <42>;
+				qcom,mdss-dsi-h-pulse-width = <10>;
+				qcom,mdss-dsi-h-sync-skew = <0>;
+				qcom,mdss-dsi-v-back-porch = <15>;
+				qcom,mdss-dsi-v-front-porch = <10>;
+				qcom,mdss-dsi-v-pulse-width = <3>;
+				qcom,mdss-dsi-panel-framerate = <60>;
+				qcom,mdss-dsi-on-command = [
+				  39 01 00 00 00 00 04 B9 83 11 2A
+				  39 01 00 00 00 00 09 B1 08 29 29 00 00 4F 54
+				     33
+				  39 01 00 00 00 00 11 B2 00 02 00 80 70 00 08
+				     26 FC 01 00 03 15 A3 87 09
+				  39 01 00 00 00 00 02 BD 02
+				  39 01 00 00 00 00 02 BD 00
+				  39 01 00 00 00 00 03 D2 2C 2C
+				  39 01 00 00 00 00 1C B4 01 CE 01 CE 01 CE 0A
+				     CE 0A CE 0A CE 00 FF 00 FF 00 00 22 23 00
+				     28 0A 13 14 00 8A
+				  39 01 00 00 00 00 02 BD 02
+				  39 01 00 00 00 00 0A B4 00 92 12 22 88 12 12
+				     00 53
+				  39 01 00 00 00 00 02 BD 00
+				  39 01 00 00 00 00 04 B6 82 82 E3
+				  39 01 00 00 00 00 02 CC 08
+				  39 01 00 00 00 00 2B D3 40 00 00 00 00 01 01
+				     0A 0A 07 07 00 08 09 09 09 09 32 10 09 00
+				     09 32 21 0A 00 0A 32 10 08 00 00 00 00 00
+				     00 00 00 00 0B 08 82
+				  39 01 00 00 00 00 02 BD 01
+				  39 01 00 00 00 00 09 D3 00 00 19 00 00 0A 00
+				     81
+				  39 01 00 00 00 00 02 BD 00
+				  39 01 00 00 00 00 31 D5 18 18 18 18 18 18 18
+				     18 31 31 30 30 2F 2F 31 31 30 30 2F 2F C0
+				     18 40 40 01 00 07 06 05 04 03 02 21 20 18
+				     18 19 19 18 18 03 03 18 18 18 18 18 18
+				  39 01 00 00 00 00 31 D6 18 18 18 18 18 18 18
+				     18 31 31 30 30 2F 2F 31 31 30 30 2F 2F C0
+				     18 40 40 02 03 04 05 06 07 00 01 20 21 18
+				     18 18 18 19 19 20 20 18 18 18 18 18 18
+				  39 01 00 00 00 00 19 D8 00 00 00 00 00 00 00
+				     00 00 00 00 00 00 00 00 00 00 00 00 00 00
+				     00 00 00
+				  39 01 00 00 00 00 02 BD 01
+				  39 01 00 00 00 00 19 D8 AA AA AA AA AA AA AA
+				     AA AA AA AA AA AA AA AA AA AA AA AA AA AA
+				     AA AA AA
+				  39 01 00 00 00 00 02 BD 02
+				  39 01 00 00 00 00 0D D8 AF FF FA AA BA AA AA
+				     FF FA AA BA AA
+				  39 01 00 00 00 00 02 BD 03
+				  39 01 00 00 00 00 19 D8 AA AA AA AA AA AA AA
+				     AA AA AA AA AA AA AA AA AA AA AA AA AA AA
+				     AA AA AA
+				  39 01 00 00 00 00 02 BD 00
+				  39 01 00 00 00 00 18 E7 0E 0E 1E 6A 1D 6A 00
+				     32 02 02 00 00 02 02 02 05 14 14 32 B9 23
+				     B9 08
+				  39 01 00 00 00 00 02 BD 01
+				  39 01 00 00 00 00 0A E7 02 00 98 01 9A 0D A8
+				     0E 01
+				  39 01 00 00 00 00 02 BD 02
+				  39 01 00 00 00 00 1E E7 00 00 08 00 01 00 00
+				     00 00 00 00 00 00 00 00 00 00 00 00 00 00
+				     00 04 00 00 00 00 02 00
+				  39 01 00 00 00 00 02 BD 00
+				  39 01 00 00 00 00 02 C1 01
+				  39 01 00 00 00 00 02 BD 01
+				  39 01 00 00 00 00 3A C1 FF F7 F0 E9 E2 DB D4
+				     C6 BF B8 B1 AB A5 9F 99 94 8E 8A 85 7C 74
+				     6C 65 5F 58 52 4B 47 42 3C 37 31 2C 27 22
+				     1C 18 12 0D 08 05 04 02 01 00 27 B9 BE 54
+				     C6 B8 9C 37 43 3D E5 00
+				  39 01 00 00 00 00 02 BD 02
+				  39 01 00 00 00 00 3A C1 FF F7 F0 E9 E2 DB D4
+				     C6 BF B8 B1 AB A5 9F 99 94 8E 8A 85 7C 74
+				     6C 65 5F 58 52 4B 47 42 3C 37 31 2C 27 22
+				     1C 18 12 0D 08 05 04 02 01 00 27 B9 BE 54
+				     C6 B8 9C 37 43 3D E5 00
+				  39 01 00 00 00 00 02 BD 03
+				  39 01 00 00 00 00 3A C1 FF F7 F0 E9 E2 DB D4
+				     C6 BF B8 B1 AB A5 9F 99 94 8E 8A 85 7C 74
+				     6C 65 5F 58 52 4B 47 42 3C 37 31 2C 27 22
+				     1C 18 12 0D 08 05 04 02 01 00 27 B9 BE 54
+				     C6 B8 9C 37 43 3D E5 00
+				  39 01 00 00 00 00 02 BD 00
+				  39 01 00 00 00 00 02 E9 C3
+				  39 01 00 00 00 00 03 CB 92 01
+				  39 01 00 00 00 00 02 E9 3F
+				  39 01 00 00 00 00 07 C7 70 00 04 E0 33 00
+				  39 01 00 00 00 00 03 51 0F FF
+				  39 01 00 00 00 00 02 53 24
+				  39 01 00 00 00 00 02 55 00
+				  15 01 00 00 00 00 02 35 00
+				  05 01 00 00 96 00 02 11 00
+				  05 01 00 00 32 00 02 29 00];
+				qcom,mdss-dsi-off-command = [
+				  05 01 00 00 32 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";
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-hx8394d-wxga-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-hx8394d-wxga-video.dtsi
new file mode 100644
index 0000000..69f168b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx8394d-wxga-video.dtsi
@@ -0,0 +1,86 @@
+/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ * This 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_hx8394d_kingdisplay_vid: qcom,mdss_dsi_hx8394d_kingdisplay_vid {
+		qcom,mdss-dsi-panel-name = "hx8394d wxga video mode dsi panel";
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <800>;
+		qcom,mdss-dsi-panel-height = <1280>;
+		qcom,mdss-dsi-h-front-porch = <24>;
+		qcom,mdss-dsi-h-back-porch = <132>;
+		qcom,mdss-dsi-h-pulse-width = <4>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <16>;
+		qcom,mdss-dsi-v-front-porch = <9>;
+		qcom,mdss-dsi-v-pulse-width = <2>;
+		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 = [
+			39 01 00 00 00 00 04 B9 FF 83 94
+			39 01 00 00 32 00 05 D9 00 8B 02 07
+			39 01 00 00 00 00 03 BA 73 83
+			39 01 00 00 00 00 10 B1 6C 10 10 24 E4 11 F1 80 E4 D7 23 80 C0 D2 58
+			39 01 00 00 00 00 0C B2 00 64 10 07 70 1C 08 08 1C 4D 00
+			39 01 00 00 00 00 0D B4 00 FF 03 5A 03 5A 03 5A 01 6A 01 6A
+			39 01 00 00 00 00 1F D3 00 06 00 40 1A 08 00 32 10 07 00 07 54 15 0F 05 04 02 12 10 05 07 33 33 0B 0B 37 10 07 07
+			39 01 00 00 00 00 2D D5 19 19 18 18 1A 1A 1B 1B 04 05 06 07 00 01 02 03 20 21 18 18 18 18 18 18 18 18 18 18 18 18 22 23 18 18 18 18 18 18 18 18 18 18 18 18
+			39 01 00 00 00 00 2D D6 18 18 19 19 1A 1A 1B 1B 03 02 01 00 07 06 05 04 23 22 18 18 18 18 18 18 18 18 18 18 18 18 21 20 18 18 18 18 18 18 18 18 19 18 18 18
+			39 01 00 00 00 00 2B E0 00 00 02 3C 3E 3F 12 3D 06 09 0A 19 0F 11 14 12 13 07 12 15 16 00 00 01 3C 3E 3F 12 3D 07 09 0B 12 0D 11 13 11 13 08 13 14 19
+			15 01 00 00 00 00 02 CC 09
+			15 01 00 00 00 00 02 D2 55
+			39 01 00 00 00 00 03 C0 30 14
+			39 01 00 00 00 00 04 BF 41 0E 01
+			39 01 00 00 00 00 05 C7 00 C0 40 C0
+			15 01 00 00 00 00 02 DF 8E
+			05 01 00 00 C8 00 01 11
+			05 01 00 00 C8 00 01 29
+		];
+		qcom,mdss-dsi-off-command = [
+			05 01 00 00 32 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-h-sync-pulse = <0>;
+		qcom,mdss-dsi-traffic-mode = "non_burst_sync_event";
+		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 =
+					[8B 1f 14 00 45 4A 19 23 23 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x04>;
+		qcom,mdss-dsi-t-clk-pre = <0x1D>;
+		qcom,mdss-dsi-dma-trigger = "trigger_sw";
+		qcom,mdss-dsi-mdp-trigger = "none";
+		qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
+		qcom,mdss-dsi-init-delay-us = <50000>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+		qcom,mdss-pan-physical-width-dimension = <107>;
+		qcom,mdss-pan-physical-height-dimension = <172>;
+	};
+};
+
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 91bf722..89c5178 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
@@ -20,13 +20,13 @@
 		qcom,mdss-dsi-stream = <0>;
 		qcom,mdss-dsi-panel-width = <720>;
 		qcom,mdss-dsi-panel-height = <1440>;
-		qcom,mdss-dsi-h-front-porch = <24>;
-		qcom,mdss-dsi-h-back-porch = <24>;
+		qcom,mdss-dsi-h-front-porch = <48>;
+		qcom,mdss-dsi-h-back-porch = <48>;
 		qcom,mdss-dsi-h-pulse-width = <16>;
 		qcom,mdss-dsi-h-sync-skew = <0>;
 		qcom,mdss-dsi-v-back-porch = <40>;
-		qcom,mdss-dsi-v-front-porch = <36>;
-		qcom,mdss-dsi-v-pulse-width = <2>;
+		qcom,mdss-dsi-v-front-porch = <60>;
+		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>;
diff --git a/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-mlp466076-3250mah.dtsi b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-mlp466076-3250mah.dtsi
new file mode 100644
index 0000000..09c21ed
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-mlp466076-3250mah.dtsi
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+qcom,mlp466076_3250mah_averaged_masterslave_jun15th2018 {
+	/* #mlp466076_3250mAh_averaged_MasterSlave_Jun15th2018 */
+	qcom,max-voltage-uv = <4400000>;
+	qcom,nom-batt-capacity-mah = <3250>;
+	qcom,fastchg-current-ma = <6000>;
+	qcom,jeita-fcc-ranges = <0  150  650000
+				151 450  4875000
+				451 550  1625000>;
+	qcom,jeita-fv-ranges =  <0   150 4150000
+				151 450 4400000
+				451 550 4150000>;
+	qcom,batt-id-kohm = <133>;
+	qcom,battery-beta = <4250>;
+	qcom,fg-cc-cv-threshold-mv = <4390>;
+	qcom,battery-type = "mlp466076_3250mah_jun15th2018";
+	qcom,checksum = <0x8905>;
+	qcom,gui-version = "PM660GUI - 0.0.0.45";
+	qcom,fg-profile-data = [
+		5E 21 D2 0D
+		E3 0B 04 05
+		EC 1C 8B 01
+		4F 05 31 03
+		80 18 D2 22
+		C2 45 73 52
+		90 00 00 00
+		13 00 00 00
+		00 00 82 C3
+		A3 CC 92 BC
+		2F 00 08 00
+		14 DA CE E5
+		B0 04 41 02
+		C5 F4 C4 12
+		0C 07 3F 32
+		2B 06 09 20
+		27 00 14 00
+		4C 20 E0 04
+		1A 0B A1 05
+		C4 1C E7 02
+		3E 0C 02 12
+		9D 18 4C 23
+		DC 44 15 5A
+		70 00 00 00
+		10 00 00 00
+		00 00 F6 07
+		1D CB 02 B4
+		20 00 00 00
+		5B E3 CE E5
+		C8 05 54 01
+		A6 06 BD FB
+		35 F4 47 23
+		C5 33 CC FF
+		07 10 00 00
+		38 0D 66 46
+		20 00 40 00
+		61 01 0A FA
+		FF 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+		00 00 00 00
+	];
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
index eda92c5..c69e699 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
@@ -545,6 +545,33 @@
 			};
 		};
 
+		imu {
+			imu_int_active: imu_int_active{
+				mux {
+					pins = "gpio12";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio12";
+					drive-strength = <6>;
+					bias-pull-up;
+				};
+			};
+
+			imu_int_suspend: imu_int_suspend{
+				mux {
+					pins = "gpio12";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio12";
+					drive-strength = <6>;
+					bias-pull-up;
+				};
+			};
+
+		};
+
 		nfc {
 			nfcw_int_active: nfcw_int_active {
 				mux {
@@ -1917,6 +1944,32 @@
 			};
 		};
 
+		cdc_reset1_ctrl {
+			cdc_reset1_sleep: cdc_reset1_sleep {
+				mux {
+					pins = "gpio23";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio23";
+					drive-strength = <16>;
+					bias-disable;
+					output-low;
+				};
+			};
+			cdc_reset1_active:cdc_reset1_active {
+				mux {
+					pins = "gpio23";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio23";
+					drive-strength = <16>;
+					bias-pull-down;
+					output-high;
+				};
+			};
+		};
 
 		cdc-dmic-lines {
 			cdc_dmic0_clk_act: dmic0_clk_on {
@@ -2219,5 +2272,32 @@
 			};
 		};
 
+		spkr_en {
+			label = "spkr_en";
+			spkr_en_active: spkr_en_active {
+				mux {
+					pins = "gpio72";
+					function = "gpio";
+				};
+				configs {
+					pins = "gpio72";
+					drive-strength = <8>;   /* 8 MA */
+					output-high;
+				};
+			};
+			spkr_en_sleep: spkr_en_sleep {
+				mux {
+					pins = "gpio72";
+					function = "gpio";
+				};
+				configs {
+					pins = "gpio72";
+					drive-strength = <2>;   /* 2 MA */
+					input-enable;           /* PULL DOWN */
+				};
+			};
+		};
+
+
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot-som.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot-som.dtsi
new file mode 100644
index 0000000..9c0e539
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot-som.dtsi
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+&i2c_3 {
+	status = "ok";
+};
+
+&i2c_3 {
+	qcom,camera@0 {
+		cell-index = <0>;
+		compatible = "qcom,camera";
+		reg = <0x2>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,mount-angle = <90>;
+		cam_vdig-supply = <&pm8916_l2>;
+		cam_vana-supply = <&pm8916_l17>;
+		cam_vio-supply = <&pm8916_l6>;
+		qcom,cam-vreg-type = <0 0 0>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
+		qcom,cam-vreg-op-mode = <200000 0 80000>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_default
+				&cam_sensor_rear_default>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>;
+		gpios = <&msm_gpio 26 0>,
+			<&msm_gpio 35 0>,
+			<&msm_gpio 34 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_MCLK",
+			"CAM_RESET",
+			"CAM_STANDBY";
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <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 = <0>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <90>;
+		cam_vana-supply = <&pm8916_l17>;
+		cam_vio-supply = <&pm8916_l6>;
+		qcom,cam-vreg-name = "cam_vio","cam_vana";
+		qcom,cam-vreg-min-voltage = <1800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1800000 2850000>;
+		qcom,cam-vreg-op-mode = <0 80000>;
+		qcom,cam-vreg-type = <0 0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_default
+				&cam_sensor_rear_default>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>;
+		gpios = <&msm_gpio 26 0>,
+			<&msm_gpio 91 0>;
+		qcom,gpio-reset = <1>;
+
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+			"CAM_RESET";
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <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>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot.dtsi
index 6f6655a..ce12d33 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-pm8916-camera-sensor-robot.dtsi
@@ -16,6 +16,95 @@
 };
 
 &i2c_3 {
+	otp_eeprom: qcom,msm_eeprom@6e{
+		status = "ok";
+		cell-index = <0>;
+		reg = <0x6e>;
+		compatible = "msm_eeprom";
+		qcom,eeprom-name = "sunny_imx241_otp";
+		qcom,slave-addr = <0x6e>;
+		qcom,i2c-freq-mode = <1>;
+
+		cam_vdig-supply = <&pm8916_l2>;
+		cam_vio-supply = <&pm8916_l6>;
+		cam_vana-supply = <&pm8916_l17>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
+		qcom,cam-vreg-op-mode = <200000 0 80000>;
+		qcom,cam-vreg-type = <0 0 0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_default
+					&cam_sensor_rear_default>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep
+					&cam_sensor_rear_sleep>;
+		gpios = <&msm_gpio 26 0>,
+				<&msm_gpio 35 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <1 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET";
+
+		qcom,cam-power-seq-type = "sensor_vreg",
+						"sensor_vreg",
+						"sensor_vreg",
+						"sensor_gpio",
+						"sensor_clk",
+						"sensor_i2c_mux";
+		qcom,cam-power-seq-val =  "cam_vana",
+						"cam_vdig",
+						"cam_vio",
+						"sensor_gpio_reset",
+						"sensor_cam_mclk",
+						"none";
+		qcom,cam-power-seq-cfg-val = <2850000 1200000
+						1800000 1 24000000 0>;
+		qcom,cam-power-seq-delay =   <1 1 1 1 1 0>;
+
+		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,num-blocks = <12>;
+		qcom,page0 = <1 0x34C5 2 0x02 1 1>;
+		qcom,poll0 = <0 0x0 2 0 1 1>;
+		qcom,mem0 = <0 0x0 2 0 1 0>;
+		qcom,page1 = <1 0x34C9 2 0x02 1 10>;
+		qcom,poll1 = <0 0x0 2 0 1 1>;
+		qcom,mem1 = <8 0x3510 2 0 1 0>;
+		qcom,page2 = <1 0x34C5 2 0x03 1 1>;
+		qcom,poll2 = <0 0x0 2 0 1 1>;
+		qcom,mem2 = <0 0x0 2 0 1 0>;
+		qcom,page3 = <1 0x34C9 2 0x03 1 10>;
+		qcom,poll3 = <0 0x0 2 0 1 1>;
+		qcom,mem3 = <8 0x3518 2 0 1 0>;
+		qcom,page4 = <1 0x34C5 2 0x06 1 1>;
+		qcom,poll4 = <0 0x0 2 0 1 1>;
+		qcom,mem4 = <0 0x0 2 0 1 0>;
+		qcom,page5 = <1 0x34C9 2 0x06 1 10>;
+		qcom,poll5 = <0 0x0 2 0 1 1>;
+		qcom,mem5 = <8 0x3530 2 0 1 0>;
+		qcom,page6 = <1 0x34C5 2 0x07 1 1>;
+		qcom,poll6 = <0 0x0 2 0 1 1>;
+		qcom,mem6 = <0 0x0 2 0 1 0>;
+		qcom,page7 = <1 0x34C9 2 0x07 1 10>;
+		qcom,poll7 = <0 0x0 2 0 1 1>;
+		qcom,mem7 = <8 0x3538 2 0 1 0>;
+		qcom,page8 = <1 0x34C5 2 0x0A 1 1>;
+		qcom,poll8 = <0 0x0 2 0 1 1>;
+		qcom,mem8 = <0 0x0 2 0 1 0>;
+		qcom,page9 = <1 0x34C9 2 0x0A 1 10>;
+		qcom,poll9 = <0 0x0 2 0 1 1>;
+		qcom,mem9 = <8 0x3550 2 0 1 0>;
+		qcom,page10 = <1 0x34C5 2 0x0B 1 1>;
+		qcom,poll10 = <0 0x0 2 0 1 1>;
+		qcom,mem10 = <0 0x0 2 0 1 0>;
+		qcom,page11 = <1 0x34C9 2 0x0B 1 10>;
+		qcom,poll11 = <0 0x0 2 0 1 1>;
+		qcom,mem11 = <8 0x3558 2 0 1 0>;
+	};
+
 	qcom,camera@0 {
 		cell-index = <0>;
 		compatible = "qcom,camera";
@@ -26,6 +115,7 @@
 		cam_vdig-supply = <&pm8916_l2>;
 		cam_vana-supply = <&pm8916_l17>;
 		cam_vio-supply = <&pm8916_l6>;
+		qcom,cam-vreg-type = <0 0 0>;
 		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
 		qcom,cam-vreg-min-voltage = <1200000 1800000 2850000>;
 		qcom,cam-vreg-max-voltage = <1200000 1800000 2850000>;
@@ -46,6 +136,7 @@
 			"CAM_STANDBY";
 		qcom,sensor-position = <0>;
 		qcom,sensor-mode = <0>;
+		qcom,eeprom-src = <&otp_eeprom>;
 		status = "ok";
 		clocks = <&clock_gcc clk_mclk0_clk_src>,
 				<&clock_gcc clk_gcc_camss_mclk0_clk>;
@@ -66,6 +157,7 @@
 		qcom,cam-vreg-min-voltage = <1800000 2850000>;
 		qcom,cam-vreg-max-voltage = <1800000 2850000>;
 		qcom,cam-vreg-op-mode = <0 80000>;
+		qcom,cam-vreg-type = <0 0>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_default
 				&cam_sensor_rear_default>;
diff --git a/arch/arm64/boot/dts/qcom/msm8909.dtsi b/arch/arm64/boot/dts/qcom/msm8909.dtsi
index 8984360..8c06c93 100644
--- a/arch/arm64/boot/dts/qcom/msm8909.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909.dtsi
@@ -163,7 +163,7 @@
 		};
 	};
 
-	reserved-memory {
+	reserved_mem: reserved-memory {
 		#address-cells = <2>;
 		#size-cells = <2>;
 		ranges;
@@ -839,6 +839,7 @@
 		qcom,hsusb-otg-otg-control = <2>; /* PMIC */
 		qcom,dp-manual-pullup;
 		qcom,phy-dvdd-always-on;
+		qcom,hsusb-otg-delay-lpm;
 		qcom,hsusb-otg-mpm-dpsehv-int = <49>;
 		qcom,hsusb-otg-mpm-dmsehv-int = <58>;
 
@@ -1352,7 +1353,7 @@
 		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
 			 <&clock_gcc clk_gcc_blsp1_qup1_i2c_apps_clk>;
 		clock-names = "iface_clk", "core_clk";
-		qcom,clk-freq-out = <100000>;
+		qcom,clk-freq-out = <400000>;
 		qcom,clk-freq-in  = <19200000>;
 		pinctrl-names = "i2c_active", "i2c_sleep";
 		pinctrl-0 = <&i2c_1_active>;
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-bg-memory.dtsi b/arch/arm64/boot/dts/qcom/msm8909w-bg-memory.dtsi
index f841097..3389d29 100644
--- a/arch/arm64/boot/dts/qcom/msm8909w-bg-memory.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909w-bg-memory.dtsi
@@ -22,3 +22,14 @@
 &peripheral_mem {
 	reg = <0x0 0x8d200000 0x0 0x0600000>;
 };
+
+&reserved_mem {
+	linux,cma {
+		compatible = "shared-dma-pool";
+		alloc-ranges = <0 0x00000000 0 0xa0000000>;
+		reusable;
+		alignment = <0 0x400000>;
+		size = <0 0x1000000>;
+		linux,cma-default;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-regulator.dtsi b/arch/arm64/boot/dts/qcom/msm8916-regulator.dtsi
index 36a67af..7c3e932 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-regulator.dtsi
@@ -214,7 +214,7 @@
 			regulator-min-microvolt = <1>;
 			regulator-max-microvolt = <7>;
 			qcom,use-voltage-corner;
-			qcom,init-voltage = <1>;
+			qcom,init-voltage-corner = <1>;
 		};
 	};
 
diff --git a/arch/arm64/boot/dts/qcom/msm8917-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-camera-sensor-mtp.dtsi
new file mode 100644
index 0000000..23c0987
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-camera-sensor-mtp.dtsi
@@ -0,0 +1,282 @@
+/*
+ * 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 = <&pm8937_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 = <&pm8937_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_vdig-supply = <&pm8937_l23>;
+		cam_vana-supply = <&pm8937_l22>;
+		cam_vio-supply = <&pm8937_l6>;
+		cam_vaf-supply = <&pm8937_l17>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vana", "cam_vio",
+							"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_mclk0_default
+				&cam_sensor_rear_default>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>;
+		gpios = <&tlmm 26 0>,
+			<&tlmm 36 0>,
+			<&tlmm 35 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";
+		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 = <&pm8937_l23>;
+		cam_vana-supply = <&pm8937_l22>;
+		cam_vio-supply = <&pm8937_l6>;
+		cam_vaf-supply = <&pm8937_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,camera@0 {
+		cell-index = <0>;
+		compatible = "qcom,camera";
+		reg = <0x0>;
+		qcom,csiphy-sd-index = <0>;
+		qcom,csid-sd-index = <0>;
+		qcom,mount-angle = <270>;
+		qcom,led-flash-src = <&led_flash0>;
+		qcom,eeprom-src = <&eeprom0>;
+		qcom,actuator-src = <&actuator0>;
+		cam_vana-supply = <&pm8937_l22>;
+		cam_vio-supply = <&pm8937_l6>;
+		cam_vaf-supply = <&pm8937_l17>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vaf";
+		qcom,cam-vreg-min-voltage = <0 2800000 2850000>;
+		qcom,cam-vreg-max-voltage = <0 2800000 2850000>;
+		qcom,cam-vreg-op-mode = <0 80000 100000>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_default
+				&cam_sensor_rear_default
+				&cam_sensor_rear_vdig>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
+				&cam_sensor_rear_vdig_sleep>;
+		gpios = <&tlmm 26 0>,
+			<&tlmm 36 0>,
+			<&tlmm 35 0>,
+			<&tlmm 62 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-vdig = <3>;
+		qcom,gpio-req-tbl-num = <0 1 2 3>;
+		qcom,gpio-req-tbl-flags = <1 0 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+			"CAM_RESET0",
+			"CAM_STANDBY0",
+			"CAM_VDIG";
+		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 = <90>;
+		cam_vdig-supply = <&pm8937_l23>;
+		cam_vana-supply = <&pm8937_l22>;
+		cam_vio-supply = <&pm8937_l6>;
+		cam_vaf-supply = <&pm8937_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 = <90>;
+		qcom,eeprom-src = <&eeprom1>;
+		qcom,actuator-src = <&actuator1>;
+		cam_vdig-supply = <&pm8937_l23>;
+		cam_vana-supply = <&pm8937_l22>;
+		cam_vio-supply = <&pm8937_l6>;
+		cam_vaf-supply = <&pm8937_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,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/msm8917-cdp-ext-codec-overlay.dts b/arch/arm64/boot/dts/qcom/msm8917-cdp-ext-codec-overlay.dts
new file mode 100644
index 0000000..7dba042
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-cdp-ext-codec-overlay.dts
@@ -0,0 +1,80 @@
+/*
+ * 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 "msm8917-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917 External Audio Codec CDP";
+	qcom,board-id = <1 1>;
+};
+
+&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>;
+	};
+
+	gpio@c600 {
+		status = "ok";
+		qcom,mode = <1>;
+		qcom,pull = <5>;
+		qcom,vin-sel = <0>;
+		qcom,src-sel = <0>;
+		qcom,master-en = <1>;
+		qcom,out-strength = <2>;
+	};
+};
+
+&slim_msm {
+	status = "okay";
+};
+
+&wcd9xxx_intc {
+	status = "okay";
+};
+
+&clock_audio {
+	status = "okay";
+};
+
+&wcd9335 {
+	status = "okay";
+};
+
+&wcd_rst_gpio {
+	status = "okay";
+};
+
+&ext_codec {
+	status = "okay";
+};
+
+&int_codec {
+	status = "disabled";
+};
+
+&wsa881x_i2c_f {
+	status = "disabled";
+};
+
+&wsa881x_i2c_45 {
+	status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-cdp-mirror-lake-touch.dtsi b/arch/arm64/boot/dts/qcom/msm8917-cdp-mirror-lake-touch.dtsi
index 1f19e20..178af9d 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-cdp-mirror-lake-touch.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-cdp-mirror-lake-touch.dtsi
@@ -11,16 +11,14 @@
  * GNU General Public License for more details.
  */
 
-#include "msm8917-pinctrl.dtsi"
 /* #include "msm8917-camera-sensor-cdp.dtsi"*/
 
 &soc {
 	gpio_keys {
 		compatible = "gpio-keys";
 		input-name = "gpio-keys";
-		pinctrl-names = "tlmm_gpio_key_active", "tlmm_gpio_key_suspend";
+		pinctrl-names = "default";
 		pinctrl-0 = <&gpio_key_active>;
-		pinctrl-1 = <&gpio_key_suspend>;
 
 		camera_focus {
 			label = "camera_focus";
@@ -28,6 +26,8 @@
 			linux,input-type = <1>;
 			linux,code = <0x210>;
 			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
 		};
 
 		camera_snapshot {
@@ -36,6 +36,8 @@
 			linux,input-type = <1>;
 			linux,code = <0x2fe>;
 			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
 		};
 
 		vol_up {
@@ -44,6 +46,8 @@
 			linux,input-type = <1>;
 			linux,code = <115>;
 			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
 		};
 
 		home {
@@ -52,6 +56,8 @@
 			linux,input-type = <1>;
 			linux,code = <102>;
 			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
 		};
 	};
 
@@ -106,151 +112,25 @@
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart_console_active>;
 };
-
-#include "msm8937-mdss-panels.dtsi"
-
-&mdss_mdp {
-	qcom,mdss-pref-prim-intf = "dsi";
-};
-
-&mdss_dsi {
-	hw-config = "single_dsi";
-};
-
-&mdss_dsi0 {
-	qcom,dsi-pref-prim-pan = <&dsi_truly_720_vid>;
-	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>;
-	qcom,platform-bklight-en-gpio = <&tlmm 98 0>;
-};
-
-&dsi_truly_720_vid {
-	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_truly_720_cmd {
-	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
-	qcom,ulps-enabled;
-	qcom,partial-update-enabled;
-	qcom,panel-roi-alignment = <2 2 2 2 2 2>;
-};
-
-&dsi_icn9706_720_1440_vid {
-	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";
-};
-
-&tlmm {
-	tlmm_gpio_key {
-		gpio_key_active: gpio_key_active {
-			mux {
-				pins = "gpio86", "gpio91", "gpio127", "gpio128";
-				function = "gpio";
-			};
-
-			config {
-				pins = "gpio86", "gpio91", "gpio127", "gpio128";
-			};
-		};
-
-		gpio_key_suspend: gpio_key_suspend {
-			mux {
-				pins = "gpio86", "gpio91", "gpio127", "gpio128";
-				function = "gpio";
-			};
-
-			config {
-				pins = "gpio86", "gpio91", "gpio127", "gpio128";
-			};
-		};
-	};
-};
-
-&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";
-};
-
 &i2c_3 {
 	status = "okay";
 	synaptics@22 {
-		compatible = "synaptics,dsx";
+		compatible = "synaptics,dsx-i2c";
 		reg = <0x22>;
 		interrupt-parent = <&tlmm>;
 		interrupts = <65 0x2008>;
-		avdd-supply = <&pm8937_l10>;
-		vdd-supply = <&pm8937_l5>;
-		synaptics,vdd-voltage = <1880000 1880000>;
-		synaptics,avdd-voltage = <3008000 3008000>;
-		synaptics,vdd-current = <40000>;
-		synaptics,avdd-current = <20000>;
+		vdd_ana-supply = <&pm8937_l10>;
+		vcc_i2c-supply = <&pm8937_l5>;
+		synaptics,pwr-reg-name = "vdd_ana";
+		synaptics,bus-reg-name = "vcc_i2c";
 		pinctrl-names = "pmx_ts_active","pmx_ts_suspend";
 		pinctrl-0 = <&ts_int_active &ts_reset_active>;
 		pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
-		synaptics,display-coords = <0 0 719 1439>;
-		synaptics,panel-coords  = <0 0 719 1439>;
-		synaptics,reset-gpio = <&tlmm 64 0x00>;
 		synaptics,irq-gpio = <&tlmm 65 0x2008>;
-		synaptics,disable-gpios;
+		synaptics,irq-on-state = <0>;
+		synaptics,irq-flags = <0x2008>;
+		synaptics,power-delay-ms = <200>;
+		synaptics,reset-delay-ms = <200>;
+		synaptics,resume-in-workqueue;
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8917-cdp-ml-touch-overlay.dts b/arch/arm64/boot/dts/qcom/msm8917-cdp-ml-touch-overlay.dts
new file mode 100644
index 0000000..73ea29b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-cdp-ml-touch-overlay.dts
@@ -0,0 +1,112 @@
+/*
+ * 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 "msm8917-cdp.dtsi"
+#include "msm8917-cdp-mirror-lake-touch.dtsi"
+#include "msm8917-audio-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917-CDP ML Touch";
+	qcom,board-id = <1 4>;
+};
+
+&soc {
+	led_flash0: qcom,camera-flash {
+		cell-index = <0>;
+		compatible = "qcom,camera-flash";
+		qcom,flash-type = <1>;
+		qcom,flash-source = <&pmi8950_flash0 &pmi8950_flash1>;
+		qcom,torch-source = <&pmi8950_torch0 &pmi8950_torch1>;
+		qcom,switch-source = <&pmi8950_switch>;
+	};
+
+	bluetooth: bt_qca6174 {
+		compatible = "qca,qca6174";
+		qca,bt-reset-gpio = <&tlmm 129 0>; /* BT_EN */
+	};
+};
+
+&qpnp_smbcharger {
+	/delete-property/ dpdm-supply;
+};
+
+&pm8937_gpios {
+	gpio@c400 {
+		qcom,mode = <0>;
+		qcom,output-type = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,out-strength = <3>;
+		qcom,src-sel = <0>;
+		qcom,master-en = <1>;
+		status = "okay";
+	};
+};
+
+&i2c_5 { /* BLSP2 QUP1 */
+	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 = <&pm8937_gpios 5 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>;
+		pinctrl-1 = <&nfc_int_suspend &nfc_disable_suspend>;
+		clocks = <&clock_gcc clk_bb_clk2_pin>;
+		clock-names = "ref_clk";
+	};
+};
+
+&mdss_dsi0 {
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+};
+
+&labibb {
+	status = "ok";
+	qpnp,qpnp-labibb-mode = "lcd";
+};
+
+&ibb_regulator {
+	qcom,qpnp-ibb-discharge-resistor = <32>;
+};
+
+&dsi_panel_pwr_supply {
+	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 = <20>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8917-cdp-overlay.dts
new file mode 100644
index 0000000..c695324
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-cdp-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 "msm8917-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917-CDP";
+	qcom,board-id = <1 0>,
+			<1 4>,
+			<1 1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-cdp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-cdp.dtsi
index fde4847..a804edd 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-cdp.dtsi
@@ -10,16 +10,15 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-#include "msm8917-pinctrl.dtsi"
-/* #include "msm8917-camera-sensor-cdp.dtsi"*/
+
+#include <dt-bindings/clock/msm-clocks-8952.h>
 
 &soc {
 	gpio_keys {
 		compatible = "gpio-keys";
 		input-name = "gpio-keys";
-		pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
+		pinctrl-names = "default";
 		pinctrl-0 = <&gpio_key_active>;
-		pinctrl-1 = <&gpio_key_suspend>;
 
 		camera_focus {
 			label = "camera_focus";
@@ -27,6 +26,8 @@
 			linux,input-type = <1>;
 			linux,code = <0x210>;
 			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
 		};
 
 		camera_snapshot {
@@ -35,6 +36,8 @@
 			linux,input-type = <1>;
 			linux,code = <0x2fe>;
 			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
 		};
 
 		vol_up {
@@ -43,6 +46,8 @@
 			linux,input-type = <1>;
 			linux,code = <115>;
 			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
 		};
 
 		home {
@@ -51,6 +56,8 @@
 			linux,input-type = <1>;
 			linux,code = <102>;
 			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
 		};
 	};
 
@@ -119,6 +126,12 @@
 	qcom,panel-roi-alignment = <2 2 2 2 2 2>;
 };
 
+&dsi_icn9706_720_1440_vid {
+	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";
+};
+
 &tlmm {
 	tlmm_gpio_key {
 		gpio_key_active: gpio_key_active {
@@ -145,6 +158,39 @@
 	};
 };
 
+&pm8937_gpios {
+	nfc_clk {
+		nfc_clk_default: nfc_clk_default {
+			pins = "gpio5";
+			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 = <&pm8937_gpios 5 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 = <&pm8937_l8>;
diff --git a/arch/arm64/boot/dts/qcom/msm8917-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8917-mtp-overlay.dts
new file mode 100644
index 0000000..0540e09
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-mtp-overlay.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/;
+/plugin/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "msm8917-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917-MTP";
+	qcom,board-id = <8 0>;
+};
+
+&blsp1_uart1 {
+	status = "ok";
+};
+
+&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-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
index 164b781..9a3b6dae 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
@@ -11,7 +11,8 @@
  * GNU General Public License for more details.
  */
 
-#include "msm8917-pinctrl.dtsi"
+#include <dt-bindings/clock/msm-clocks-8952.h>
+#include "msm8917-camera-sensor-mtp.dtsi"
 
 &blsp1_uart2 {
 	status = "ok";
@@ -19,6 +20,39 @@
 	pinctrl-0 = <&uart_console_active>;
 };
 
+&pm8937_gpios {
+	nfc_clk {
+		nfc_clk_default: nfc_clk_default {
+			pins = "gpio5";
+			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 = <&pm8937_gpios 5 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 = <&pm8937_l8>;
@@ -80,6 +114,43 @@
 		qcom,dig-vtg-min = <1800000>;
 		qcom,dig-vtg-max = <1800000>;
 	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpio_key_active>;
+
+		camera_focus {
+			label = "camera_focus";
+			gpios = <&tlmm 128 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x210>;
+			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
+		};
+
+		camera_snapshot {
+			label = "camera_snapshot";
+			gpios = <&tlmm 127 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x2fe>;
+			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
+		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&tlmm 91 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
+		};
+	};
 };
 
 #include "msm8937-mdss-panels.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi
index 858936d..0e613b6 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi
@@ -1345,39 +1345,65 @@
 			};
 		};
 
-		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 */
+					pins = "gpio16", "gpio130";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio16", "gpio130";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-up;
+				};
+			};
+
+			nfc_disable_suspend: nfc_disable_suspend {
+				/* sleep state */
+				mux {
+					/* 16: NFC ENABLE 130: FW DNLD */
+					pins = "gpio16", "gpio130";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio16", "gpio130";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable;
+				};
 			};
 		};
 
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dts
new file mode 100644
index 0000000..635705b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8937.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 "msm8917.dtsi"
+#include "msm8917-pmi8937.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917 + PMI8937 SOC";
+	compatible = "qcom,msm8917";
+	qcom,pmic-id = <0x10019 0x020037 0x0 0x0>;
+	qcom,pmic-name = "PMI8937";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi
index 91a290f..55e8e21 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi
@@ -22,3 +22,14 @@
 &usb_otg {
 	extcon = <&qpnp_smbcharger>;
 };
+
+&soc {
+	led_flash0: qcom,camera-flash {
+		cell-index = <0>;
+		compatible = "qcom,camera-flash";
+		qcom,flash-type = <1>;
+		qcom,flash-source = <&pmi8937_flash0 &pmi8937_flash1>;
+		qcom,torch-source = <&pmi8937_torch0 &pmi8937_torch1>;
+		qcom,switch-source = <&pmi8937_switch>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dts
new file mode 100644
index 0000000..e4017c7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.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 "msm8917.dtsi"
+#include "msm8917-pmi8940.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917 + PMI8940 SOC";
+	compatible = "qcom,msm8917";
+	qcom,pmic-id = <0x10019 0x020040 0x0 0x0>;
+	qcom,pmic-name = "PMI8940";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
index 90226da..9b9cd47 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
@@ -22,3 +22,14 @@
 &usb_otg {
 	extcon = <&qpnp_smbcharger>;
 };
+
+&soc {
+	led_flash0: qcom,camera-flash {
+		cell-index = <0>;
+		compatible = "qcom,camera-flash";
+		qcom,flash-type = <1>;
+		qcom,flash-source = <&pmi8940_flash0 &pmi8940_flash1>;
+		qcom,torch-source = <&pmi8940_torch0 &pmi8940_torch1>;
+		qcom,switch-source = <&pmi8940_switch>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dts
index ea6b24a..ae35baf 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dts
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dts
@@ -14,6 +14,8 @@
 /dts-v1/;
 
 #include "msm8917.dtsi"
+#include "msm8917-pmi8950.dtsi"
+#include "msm8917-cdp.dtsi"
 #include "msm8917-pmi8950-cdp-mirror-lake-touch.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dtsi
index 4701101..6415241 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dtsi
@@ -11,7 +11,6 @@
  * GNU General Public License for more details.
  */
 
-#include "pmi8950.dtsi"
 #include "msm8917-cdp-mirror-lake-touch.dtsi"
 #include "msm8917-audio-cdp.dtsi"
 
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dts
new file mode 100644
index 0000000..4a904c6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950.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 "msm8917.dtsi"
+#include "msm8917-pmi8950.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917 + PMI8950 SOC ";
+	compatible = "qcom,msm8917";
+	qcom,pmic-id = <0x10019 0x010011 0x0 0x0>;
+	qcom,pmic-name = "PMI8950";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/msm8917-qrd-overlay.dts
new file mode 100644
index 0000000..9b4d8f4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-qrd-overlay.dts
@@ -0,0 +1,122 @@
+/*
+ * 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 "msm8917-qrd.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917-QRD SKU5";
+	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>;
+	};
+
+	led_flash0: qcom,camera-flash {
+		cell-index = <0>;
+		compatible = "qcom,camera-flash";
+		qcom,flash-type = <1>;
+		qcom,flash-source = <&pmi8937_flash0>;
+		qcom,torch-source = <&pmi8937_torch0>;
+		qcom,switch-source = <&pmi8937_switch>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi b/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
index 431a5e5..5c63ed3 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
@@ -10,9 +10,9 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-
-#include "msm8917-pinctrl.dtsi"
+#include <dt-bindings/clock/msm-clocks-8952.h>
 #include "msm8917-camera-sensor-qrd.dtsi"
+#include "msm8937-mdss-panels.dtsi"
 
 &blsp1_uart2 {
 	status = "ok";
@@ -20,6 +20,39 @@
 	pinctrl-0 = <&uart_console_active>;
 };
 
+&pm8937_gpios {
+	nfc_clk {
+		nfc_clk_default: nfc_clk_default {
+			pins = "gpio5";
+			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 = <&pm8937_gpios 5 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 = <&pm8937_l8>;
@@ -88,9 +121,8 @@
 	gpio_keys {
 		compatible = "gpio-keys";
 		input-name = "gpio-keys";
-		pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
+		pinctrl-names = "default";
 		pinctrl-0 = <&gpio_key_active>;
-		pinctrl-1 = <&gpio_key_suspend>;
 
 		vol_up {
 			label = "volume_up";
@@ -98,6 +130,8 @@
 			linux,input-type = <1>;
 			linux,code = <115>;
 			debounce-interval = <15>;
+			linux,can-disable;
+			gpio-key,wakeup;
 		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8917-rcm-overlay.dts b/arch/arm64/boot/dts/qcom/msm8917-rcm-overlay.dts
new file mode 100644
index 0000000..fdf98db
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-rcm-overlay.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/;
+/plugin/;
+
+#include "msm8917-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917-RCM";
+	qcom,board-id = <21 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917.dtsi b/arch/arm64/boot/dts/qcom/msm8917.dtsi
index c4b1ec3..d5f5243 100644
--- a/arch/arm64/boot/dts/qcom/msm8917.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917.dtsi
@@ -53,6 +53,11 @@
 	firmware: firmware {
 		android {
 			compatible = "android,firmware";
+			vbmeta {
+				compatible = "android,vbmeta";
+				parts = "vbmeta,boot,system,vendor,dtbo,recovery";
+			};
+
 			fstab {
 				compatible = "android,fstab";
 				vendor {
@@ -60,15 +65,7 @@
 					dev = "/dev/block/platform/soc/7824900.sdhci/by-name/vendor";
 					type = "ext4";
 					mnt_flags = "ro,barrier=1,discard";
-					fsmgr_flags = "wait";
-					status = "ok";
-				};
-				system {
-					compatible = "android,system";
-					dev = "/dev/block/platform/soc/7824900.sdhci/by-name/system";
-					type = "ext4";
-					mnt_flags = "ro,barrier=1,discard";
-					fsmgr_flags = "wait";
+					fsmgr_flags = "wait,avb";
 					status = "ok";
 				};
 			};
@@ -1640,6 +1637,10 @@
 		qcom,has-vsys-adc-channel;
 		qcom,wcnss-adc_tm = <&pm8937_adc_tm>;
 	};
+
+	ssc_sensors: qcom,msm-ssc-sensors {
+		compatible = "qcom,msm-ssc-sensors";
+	};
 };
 
 #include "pm8937-rpm-regulator.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8937.dtsi b/arch/arm64/boot/dts/qcom/msm8937.dtsi
index 85e3043..5180d1a 100644
--- a/arch/arm64/boot/dts/qcom/msm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937.dtsi
@@ -45,15 +45,6 @@
 					fsmgr_flags = "wait,avb";
 					status = "ok";
 				};
-				system {
-					compatible = "android,system";
-					dev = "/dev/block/platform/soc/7824900.sdhci/by-name/system";
-					type = "ext4";
-					mnt_flags = "ro,barrier=1,discard";
-					fsmgr_flags = "wait,avb";
-					status = "ok";
-				};
-
 			};
 		};
 	};
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 67ed197..1b09b3c 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
@@ -35,6 +35,13 @@
 	qcom,battery-data = <&mtp_batterydata>;
 };
 
+&pmi_haptic{
+	qcom,lra-auto-res-mode="qwd";
+	qcom,lra-high-z="opt1";
+	qcom,lra-res-cal-period = <0>;
+	qcom,wave-play-rate-us = <4165>;
+};
+
 &qpnp_smbcharger {
 	qcom,battery-data = <&mtp_batterydata>;
 	qcom,chg-led-sw-controls;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-ipc.dts b/arch/arm64/boot/dts/qcom/msm8953-ipc.dts
index 89a54af..43c6441 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-ipc.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-ipc.dts
@@ -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
@@ -15,11 +15,11 @@
 
 #include "msm8953.dtsi"
 #include "msm8953-ipc.dtsi"
-
+#include "pmi8950.dtsi"
+#include "msm8953-pmi8950.dtsi"
 / {
 	model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 IPC";
 	compatible = "qcom,msm8953-ipc", "qcom,msm8953", "qcom,ipc";
 	qcom,board-id= <12 0>;
 	qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
 };
-
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
index a80b4fe..be6ab79 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
@@ -26,6 +26,7 @@
 #include "dsi-panel-hx8399c-fhd-plus-video.dtsi"
 #include "dsi-panel-hx83100a-800p-video.dtsi"
 #include "dsi-panel-boent51021-1200p-video.dtsi"
+#include "dsi-panel-hx8394d-wxga-video.dtsi"
 
 &soc {
 	dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -124,6 +125,12 @@
 		24 1f 08 09 05 03 04 a0
 		24 1f 08 09 05 03 04 a0
 		24 1c 08 09 05 03 04 a0];
+	qcom,mdss-dsi-h-front-porch = <52>;
+	qcom,mdss-dsi-h-back-porch = <48>;
+	qcom,mdss-dsi-h-pulse-width = <8>;
+	qcom,mdss-dsi-v-back-porch = <8>;
+	qcom,mdss-dsi-v-front-porch = <8>;
+	qcom,mdss-dsi-v-pulse-width = <4>;
 	qcom,esd-check-enabled;
 	qcom,mdss-dsi-panel-status-check-mode = "reg_read";
 	qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
@@ -178,3 +185,11 @@
 		25 20 08 0a 06 03 04 a0
 		25 1d 08 0a 06 03 04 a0];
 };
+
+&dsi_hx8394d_kingdisplay_vid {
+    qcom,mdss-dsi-panel-timings-phy-v2 = [1c 19 02 03 01 03 04 a0
+        1c 19 02 03 01 03 04 a0
+        1c 19 02 03 01 03 04 a0
+        1c 19 02 03 01 03 04 a0
+        1c 07 02 03 01 03 04 a0];
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
index e4897bc..00614b2 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
@@ -33,6 +33,13 @@
 	qcom,battery-data = <&mtp_batterydata>;
 };
 
+&pmi_haptic{
+	qcom,lra-auto-res-mode="qwd";
+	qcom,lra-high-z="opt1";
+	qcom,lra-res-cal-period = <0>;
+	qcom,wave-play-rate-us = <4165>;
+};
+
 &qpnp_smbcharger {
 	qcom,battery-data = <&mtp_batterydata>;
 	qcom,chg-led-sw-controls;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
index e8de4ef..c58d82e 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
@@ -599,6 +599,32 @@
 			};
 		};
 
+		blsp2_uart1_active: blsp2_uart1_active {
+			mux {
+				pins = "gpio20", "gpio21", "gpio22", "gpio23";
+				function = "blsp_uart6";
+			};
+
+			config {
+				pins = "gpio20", "gpio21", "gpio22", "gpio23";
+				drive-strength = <16>;
+				bias-disable;
+			};
+		};
+
+		blsp2_uart1_sleep: blsp2_uart1_sleep {
+			mux {
+				pins = "gpio20", "gpio21", "gpio22", "gpio23";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio20", "gpio21", "gpio22", "gpio23";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
 		/* SDC pin type */
 		sdc1_clk_on: sdc1_clk_on {
 			config {
@@ -1374,6 +1400,163 @@
 			};
 		};
 
+		spi6 {
+			spi6_default: spi6_default {
+				/* active state */
+				mux {
+					/* MOSI, MISO, CLK */
+					pins = "gpio20", "gpio21", "gpio23";
+					function = "blsp_spi6";
+				};
+
+				config {
+					pins = "gpio20", "gpio21", "gpio23";
+					drive-strength = <12>; /* 12 MA */
+					bias-disable = <0>; /* No PULL */
+				};
+			};
+
+			spi6_sleep: spi6_sleep {
+				/* suspended state */
+				mux {
+					/* MOSI, MISO, CLK */
+					pins = "gpio20", "gpio21", "gpio23";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio20", "gpio21", "gpio23";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-down; /* PULL Down */
+				};
+			};
+
+			spi6_cs0_active: cs0_active {
+				/* CS */
+				mux {
+					pins = "gpio22";
+					function = "blsp_spi6";
+				};
+
+				config {
+					pins = "gpio22";
+					drive-strength = <2>;
+					bias-disable = <0>;
+				};
+			};
+
+			spi6_cs0_sleep: cs0_sleep {
+				/* CS */
+				mux {
+					pins = "gpio22";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio22";
+					drive-strength = <2>;
+					bias-disable = <0>;
+				};
+			};
+		};
+
+		/* add pingrp for touchscreen */
+		ts_int_default: ts_int_default {
+			mux {
+				pins = "gpio65";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio65";
+				drive-strength = <16>;
+				/*bias-pull-up;*/
+				input-enable;
+				bias-disable;
+			};
+		};
+
+		ts_int_output_high: ts_int_output_high {
+			mux {
+				pins = "gpio65";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio65";
+				output-high;
+			};
+		};
+
+		ts_int_output_low: ts_int_output_low {
+			mux {
+				pins = "gpio65";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio65";
+				output-low;
+			};
+		};
+
+		ts_int_input: ts_int_input {
+			mux {
+				pins = "gpio65";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio65";
+				input-enable;
+				bias-disable;
+			};
+		};
+
+		ts_rst_default: ts_rst_default {
+			mux {
+				pins = "gpio64";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio64";
+				drive-strength = <16>;
+				/*bias-pull-up;*/
+				input-enable;
+				bias-disable;
+			};
+		};
+
+		ts_rst_output_high: ts_rst_output_high {
+			mux {
+				pins = "gpio64";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio64";
+				output-high;
+			};
+		};
+
+		ts_rst_output_low: ts_rst_output_low {
+			mux {
+				pins = "gpio64";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio64";
+				output-low;
+			};
+		};
+
+		ts_rst_input: ts_rst_input {
+			mux {
+				pins = "gpio64";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio64";
+				input-enable;
+				bias-disable;
+			};
+		};
+
 		/* add pingrp for touchscreen */
 		pmx_ts_int_active {
 			ts_int_active: ts_int_active {
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index c3178e0..efe01f7 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -55,14 +55,6 @@
 					fsmgr_flags = "wait,avb";
 					status = "ok";
 				};
-				system {
-					compatible = "android,system";
-					dev = "/dev/block/platform/soc/7824900.sdhci/by-name/system";
-					type = "ext4";
-					mnt_flags = "ro,barrier=1,discard";
-					fsmgr_flags = "wait,avb";
-					status = "ok";
-				};
 
 			};
 		};
@@ -179,6 +171,7 @@
 		i2c3 = &i2c_3;
 		i2c5 = &i2c_5;
 		spi3 = &spi_3;
+		spi6 = &spi_6;
 	};
 
 	soc: soc {
@@ -613,6 +606,42 @@
 		status = "disabled";
 	};
 
+	blsp2_uart1: uart@7af0000 {
+		compatible = "qcom,msm-hsuart-v14";
+		reg = <0x7af0000 0x200>,
+			<0x7ac4000 0x1f000>;
+		reg-names = "core_mem", "bam_mem";
+
+		interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+		#address-cells = <0>;
+		interrupt-parent = <&blsp2_uart1>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 307 0
+				1 &intc 0 239 0
+				2 &tlmm 21 0>;
+
+		qcom,inject-rx-on-wakeup;
+		qcom,rx-char-to-inject = <0xFD>;
+		qcom,master-id = <84>;
+		clock-names = "core_clk", "iface_clk";
+		clocks = <&clock_gcc clk_gcc_blsp2_uart2_apps_clk>,
+			<&clock_gcc clk_gcc_blsp2_ahb_clk>;
+		pinctrl-names = "sleep", "default";
+		pinctrl-0 = <&blsp2_uart1_sleep>;
+		pinctrl-1 = <&blsp2_uart1_active>;
+		qcom,bam-tx-ep-pipe-index = <2>;
+		qcom,bam-rx-ep-pipe-index = <3>;
+		qcom,msm-bus,name = "blsp2_uart1";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<84 512 0 0>,
+				<84 512 500 800>;
+		status = "disabled";
+	};
+
 	blsp1_serial1: serial@78b0000 {
 		compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
 		reg = <0x78b0000 0x200>;
@@ -664,6 +693,33 @@
 		qcom,master-id = <86>;
 		status = "disabled";
 	};
+
+	spi_6: spi@7af6000 { /* BLSP2 QUP2 */
+		compatible = "qcom,spi-qup-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "spi_physical", "spi_bam_physical";
+		reg = <0x7af6000 0x600>,
+			<0x7ac4000 0x1f000>;
+		interrupt-names = "spi_irq", "spi_bam_irq";
+		interrupts = <0 300 0>, <0 239 0>;
+		spi-max-frequency = <19200000>;
+		pinctrl-names = "spi_default", "spi_sleep";
+		pinctrl-0 = <&spi6_default &spi6_cs0_active>;
+		pinctrl-1 = <&spi6_sleep &spi6_cs0_sleep>;
+		clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>,
+			<&clock_gcc clk_gcc_blsp2_qup2_spi_apps_clk>;
+		clock-names = "iface_clk", "core_clk";
+		qcom,infinite-mode = <0>;
+		qcom,use-bam;
+		qcom,use-pinctrl;
+		qcom,ver-reg-exists;
+		qcom,bam-consumer-pipe-index = <6>;
+		qcom,bam-producer-pipe-index = <7>;
+		qcom,master-id = <84>;
+		status = "disabled";
+	};
+
 	i2c_1: i2c@78b5000 { /* BLSP1 QUP1 */
 		compatible = "qcom,i2c-msm-v2";
 		#address-cells = <1>;
@@ -1464,8 +1520,10 @@
 
 	sdhc_1: sdhci@7824900 {
 		compatible = "qcom,sdhci-msm";
-		reg = <0x7824900 0x500>, <0x7824000 0x800>, <0x7824e00 0x200>;
-		reg-names = "hc_mem", "core_mem", "cmdq_mem";
+		reg = <0x7824900 0x500>, <0x7824000 0x800>, <0x7824e00 0x200>,
+			<0x0119d000 0x4>;
+		reg-names = "hc_mem", "core_mem", "cmdq_mem",
+				"tlmm_mem";
 
 		interrupts = <0 123 0>, <0 138 0>;
 		interrupt-names = "hc_irq", "pwr_irq";
diff --git a/arch/arm64/boot/dts/qcom/pmi632.dtsi b/arch/arm64/boot/dts/qcom/pmi632.dtsi
index fb26ab6..d175b80 100644
--- a/arch/arm64/boot/dts/qcom/pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi632.dtsi
@@ -289,20 +289,20 @@
 		pmi632_gpios: pinctrl@c000 {
 			compatible = "qcom,spmi-gpio";
 			reg = <0xc000 0x800>;
-			interrupts = <0x2 0xc1 0 IRQ_TYPE_NONE>,
+			interrupts = <0x2 0xc0 0 IRQ_TYPE_NONE>,
+					<0x2 0xc1 0 IRQ_TYPE_NONE>,
 					<0x2 0xc2 0 IRQ_TYPE_NONE>,
 					<0x2 0xc3 0 IRQ_TYPE_NONE>,
 					<0x2 0xc4 0 IRQ_TYPE_NONE>,
 					<0x2 0xc5 0 IRQ_TYPE_NONE>,
 					<0x2 0xc6 0 IRQ_TYPE_NONE>,
 					<0x2 0xc7 0 IRQ_TYPE_NONE>;
-			interrupt-names = "pmi632_gpio2", "pmi632_gpio3",
-					"pmi632_gpio4", "pmi632_gpio5",
-					"pmi632_gpio6", "pmi632_gpio7",
-					"pmi632_gpio8";
+			interrupt-names = "pmi632_gpio1", "pmi632_gpio2",
+					"pmi632_gpio3", "pmi632_gpio4",
+					"pmi632_gpio5", "pmi632_gpio6",
+					"pmi632_gpio7", "pmi632_gpio8";
 			gpio-controller;
 			#gpio-cells = <2>;
-			qcom,gpios-disallowed = <1>;
 		};
 
 		pmi632_charger: qcom,qpnp-smb5 {
@@ -318,6 +318,9 @@
 			qcom,flash-disable-soc = <10>;
 			qcom,sw-jeita-enable;
 			qcom,step-charging-enable;
+			qcom,hw-die-temp-mitigation;
+			qcom,hw-connector-mitigation;
+			qcom,connector-internal-pull-kohm = <100>;
 
 			qcom,thermal-mitigation
 				= <3000000 2500000 2000000 1500000
@@ -394,7 +397,7 @@
 				interrupts =
 					<0x2 0x13 0x0 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x13 0x1 IRQ_TYPE_EDGE_BOTH>,
-					<0x2 0x13 0x2 IRQ_TYPE_EDGE_BOTH>,
+					<0x2 0x13 0x2 IRQ_TYPE_EDGE_RISING>,
 					<0x2 0x13 0x3 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x13 0x4 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x13 0x5 IRQ_TYPE_EDGE_BOTH>,
diff --git a/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp-overlay.dts
index 44fae6a..76088af 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp-overlay.dts
@@ -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
@@ -32,3 +32,47 @@
 		       <0x0001001b 0x0102001a 0x0 0x0>,
 		       <0x0001001b 0x0201011a 0x0 0x0>;
 };
+
+&cam_cci {
+	/delete-node/ qcom,cam-sensor@1;
+	qcom,cam-sensor@1 {
+		cell-index = <1>;
+		compatible = "qcom,cam-sensor";
+		reg = <0x1>;
+		csiphy-sd-index = <1>;
+		sensor-position-roll = <90>;
+		sensor-position-pitch = <0>;
+		sensor-position-yaw = <180>;
+		eeprom-src = <&eeprom_rear_aux>;
+		cam_vio-supply = <&camera_vio_ldo>;
+		cam_vana-supply = <&camera_vana_ldo>;
+		cam_vdig-supply = <&camera_ldo>;
+		cam_clk-supply = <&titan_top_gdsc>;
+		regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+			"cam_clk";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <1352000 1800000 2850000 0>;
+		rgltr-max-voltage = <1352000 1800000 2850000 0>;
+		rgltr-load-current = <105000 0 80000 0>;
+		gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_active
+				&cam_sensor_rear2_active>;
+		pinctrl-1 = <&cam_sensor_mclk0_suspend
+				&cam_sensor_rear2_suspend>;
+		gpios = <&tlmm 13 0>,
+			<&tlmm 28 0>;
+		gpio-reset = <1>;
+		gpio-req-tbl-num = <0 1>;
+		gpio-req-tbl-flags = <1 0>;
+		gpio-req-tbl-label = "CAMIF_MCLK0",
+					"CAM_RESET1";
+		sensor-mode = <0>;
+		cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
+		clock-rates = <24000000>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp.dts b/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp.dts
index abc3f2d..47ea8f3 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-external-codec-mtp.dts
@@ -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
@@ -26,3 +26,47 @@
 		       <0x0001001b 0x0102001a 0x0 0x0>,
 		       <0x0001001b 0x0201011a 0x0 0x0>;
 };
+
+&cam_cci {
+	/delete-node/ qcom,cam-sensor@1;
+	qcom,cam-sensor@1 {
+		cell-index = <1>;
+		compatible = "qcom,cam-sensor";
+		reg = <0x1>;
+		csiphy-sd-index = <1>;
+		sensor-position-roll = <90>;
+		sensor-position-pitch = <0>;
+		sensor-position-yaw = <180>;
+		eeprom-src = <&eeprom_rear_aux>;
+		cam_vio-supply = <&camera_vio_ldo>;
+		cam_vana-supply = <&camera_vana_ldo>;
+		cam_vdig-supply = <&camera_ldo>;
+		cam_clk-supply = <&titan_top_gdsc>;
+		regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+			"cam_clk";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <1352000 1800000 2850000 0>;
+		rgltr-max-voltage = <1352000 1800000 2850000 0>;
+		rgltr-load-current = <105000 0 80000 0>;
+		gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_active
+				&cam_sensor_rear2_active>;
+		pinctrl-1 = <&cam_sensor_mclk0_suspend
+				&cam_sensor_rear2_suspend>;
+		gpios = <&tlmm 13 0>,
+			<&tlmm 28 0>;
+		gpio-reset = <1>;
+		gpio-req-tbl-num = <0 1>;
+		gpio-req-tbl-flags = <1 0>;
+		gpio-req-tbl-label = "CAMIF_MCLK0",
+					"CAM_RESET1";
+		sensor-mode = <0>;
+		cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
+		clock-rates = <24000000>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-audio.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-audio.dtsi
new file mode 100644
index 0000000..ab82fe6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-audio.dtsi
@@ -0,0 +1,360 @@
+/*
+ * 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 "sdm670-wcd.dtsi"
+#include "sdm670-wsa881x.dtsi"
+#include "sdm670-lpi.dtsi"
+#include <dt-bindings/clock/qcom,audio-ext-clk.h>
+
+&tavil_snd {
+	qcom,msm-mi2s-master = <1>, <1>, <1>, <1>, <1>;
+	qcom,audio-routing =
+		"AIF4 VI", "MCLK",
+		"RX_BIAS", "MCLK",
+		"MADINPUT", "MCLK",
+		"hifi amp", "LINEOUT1",
+		"hifi amp", "LINEOUT2",
+		"AMIC2", "MIC BIAS2",
+		"MIC BIAS2", "Headset Mic",
+		"AMIC3", "MIC BIAS2",
+		"MIC BIAS2", "ANCRight Headset Mic",
+		"AMIC4", "MIC BIAS2",
+		"MIC BIAS2", "ANCLeft Headset Mic",
+		"AMIC5", "MIC BIAS3",
+		"MIC BIAS3", "Handset Mic",
+		"DMIC0", "MIC BIAS1",
+		"MIC BIAS1", "Digital Mic0",
+		"DMIC1", "MIC BIAS1",
+		"MIC BIAS1", "Digital Mic1",
+		"DMIC2", "MIC BIAS3",
+		"MIC BIAS3", "Digital Mic2",
+		"DMIC3", "MIC BIAS3",
+		"MIC BIAS3", "Digital Mic3",
+		"DMIC4", "MIC BIAS4",
+		"MIC BIAS4", "Digital Mic4",
+		"DMIC5", "MIC BIAS4",
+		"MIC BIAS4", "Digital Mic5",
+		"SpkrLeft IN", "SPK1 OUT",
+		"SpkrRight IN", "SPK2 OUT";
+
+	qcom,msm-mbhc-hphl-swh = <1>;
+	qcom,msm-mbhc-gnd-swh = <1>;
+	qcom,hph-en0-gpio = <&tavil_hph_en0>;
+	qcom,hph-en1-gpio = <&tavil_hph_en1>;
+	qcom,msm-mclk-freq = <9600000>;
+	asoc-codec = <&stub_codec>, <&ext_disp_audio_codec>;
+	asoc-codec-names = "msm-stub-codec.1", "msm-ext-disp-audio-codec-rx";
+	qcom,wsa-max-devs = <2>;
+	qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0212>,
+		<&wsa881x_0213>, <&wsa881x_0214>;
+	qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+		"SpkrLeft", "SpkrRight";
+};
+
+&tasha_snd {
+	qcom,msm-mi2s-master = <1>, <1>, <1>, <1>, <1>;
+	qcom,audio-routing =
+		"AIF4 VI", "MCLK",
+		"RX_BIAS", "MCLK",
+		"MADINPUT", "MCLK",
+		"hifi amp", "LINEOUT1",
+		"hifi amp", "LINEOUT2",
+		"AMIC2", "MIC BIAS2",
+		"MIC BIAS2", "Headset Mic",
+		"AMIC3", "MIC BIAS2",
+		"MIC BIAS2", "ANCRight Headset Mic",
+		"AMIC4", "MIC BIAS2",
+		"MIC BIAS2", "ANCLeft Headset Mic",
+		"AMIC5", "MIC BIAS3",
+		"MIC BIAS3", "Handset Mic",
+		"DMIC0", "MIC BIAS1",
+		"MIC BIAS1", "Digital Mic0",
+		"DMIC1", "MIC BIAS1",
+		"MIC BIAS1", "Digital Mic1",
+		"DMIC2", "MIC BIAS3",
+		"MIC BIAS3", "Digital Mic2",
+		"DMIC3", "MIC BIAS3",
+		"MIC BIAS3", "Digital Mic3",
+		"DMIC4", "MIC BIAS4",
+		"MIC BIAS4", "Digital Mic4",
+		"DMIC5", "MIC BIAS4",
+		"MIC BIAS4", "Digital Mic5",
+		"SpkrLeft IN", "SPK1 OUT",
+		"SpkrRight IN", "SPK2 OUT";
+
+	qcom,msm-mbhc-hphl-swh = <0>;
+	qcom,msm-mbhc-gnd-swh = <0>;
+	qcom,msm-mclk-freq = <9600000>;
+	asoc-codec = <&stub_codec>;
+	asoc-codec-names = "msm-stub-codec.1";
+	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";
+};
+
+&soc {
+	wcd_usbc_analog_en1_gpio: msm_cdc_pinctrl_usbc_audio_en1 {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&wcd_usbc_analog_en1_active>;
+		pinctrl-1 = <&wcd_usbc_analog_en1_idle>;
+	};
+
+	cdc_pdm_gpios: cdc_pdm_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_pdm_clk_active &cdc_pdm_sync_active
+			     &cdc_pdm_rx0_active &cdc_pdm_rx1_2_active
+			     &cdc_pdm_2_gpios_active>;
+		pinctrl-1 = <&cdc_pdm_clk_sleep &cdc_pdm_sync_sleep
+			     &cdc_pdm_rx0_sleep &cdc_pdm_rx1_2_sleep
+			     &cdc_pdm_2_gpios_sleep>;
+		qcom,lpi-gpios;
+	};
+
+	cdc_comp_gpios: cdc_comp_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_rx0_comp_active &cdc_rx1_comp_active>;
+		pinctrl-1 = <&cdc_rx0_comp_sleep &cdc_rx1_comp_sleep>;
+		qcom,lpi-gpios;
+	};
+
+	cdc_dmic_gpios: cdc_dmic_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_dmic12_gpios_active
+			     &cdc_dmic34_gpios_active>;
+		pinctrl-1 = <&cdc_dmic12_gpios_sleep
+			     &cdc_dmic34_gpios_sleep>;
+		qcom,lpi-gpios;
+	};
+
+	cdc_sdw_gpios: sdw_clk_data_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&sdw_clk_active &sdw_data_active>;
+		pinctrl-1 = <&sdw_clk_sleep &sdw_data_sleep>;
+	};
+
+	wsa_spkr_en1: wsa_spkr_en1_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&spkr_1_sd_n_active>;
+		pinctrl-1 = <&spkr_1_sd_n_sleep>;
+	};
+
+	wsa_spkr_en2: wsa_spkr_en2_pinctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&spkr_2_sd_n_active>;
+		pinctrl-1 = <&spkr_2_sd_n_sleep>;
+	};
+
+	msm_sdw_codec: msm-sdw-codec@62ec1000 {
+		status = "okay";
+		compatible = "qcom,msm-sdw-codec";
+		reg = <0x62ec1000 0x0>;
+		interrupts = <0 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>;
+			};
+		};
+	};
+
+	wcd9xxx_intc: wcd9xxx-irq {
+		status = "disabled";
+		compatible = "qcom,wcd9xxx-irq";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&tlmm>;
+		qcom,gpio-connect = <&tlmm 80 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&wcd_intr_default>;
+	};
+
+	clock_audio_native: audio_ext_clk_native {
+		status = "disabled";
+		compatible = "qcom,audio-ref-clk";
+		#clock-cells = <1>;
+		qcom,lpass-mclk-id = <0x116>;
+		qcom,codec-mclk-clk-freq = <11289600>;
+		qcom,audio-ref-clk-gpio = <&lpi_tlmm 19 0>;
+		pinctrl-names = "sleep", "active";
+		pinctrl-0 = <&lpi_mclk0_sleep>;
+		pinctrl-1 = <&lpi_mclk0_active>;
+	};
+
+	clock_audio: audio_ext_clk {
+		status = "disabled";
+		compatible = "qcom,audio-ref-clk";
+		pinctrl-names = "active", "sleep";
+		pinctrl-0 = <&tasha_mclk_default>;
+		pinctrl-1 = <&tasha_mclk_default>;
+		qcom,audio-ref-clk-gpio = <&pm660_gpios 3 0>;
+		clock-names = "osr_clk";
+		clocks = <&pm660_div_clk>;
+		qcom,node_has_rpm_clock;
+		#clock-cells = <1>;
+	};
+
+	clock_audio_lnbb: audio_ext_clk_lnbb {
+		status = "disabled";
+		compatible = "qcom,audio-ref-clk";
+		clock-names = "osr_clk";
+		clocks = <&clock_rpmh RPMH_LN_BB_CLK2>;
+		qcom,node_has_rpm_clock;
+		#clock-cells = <1>;
+	};
+
+	wcd_rst_gpio: msm_cdc_pinctrl@64 {
+		status = "disabled";
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&lpi_cdc_reset_active>;
+		pinctrl-1 = <&lpi_cdc_reset_sleep>;
+		qcom,lpi-gpios;
+	};
+
+	wdsp_mgr: qcom,wcd-dsp-mgr {
+		compatible = "qcom,wcd-dsp-mgr";
+		qcom,wdsp-components = <&wcd934x_cdc 0>,
+				       <&wcd_spi_0 1>,
+				       <&glink_spi_xprt_wdsp 2>;
+					qcom,img-filename = "cpe_9340";
+	};
+
+	wdsp_glink: qcom,wcd-dsp-glink {
+		compatible = "qcom,wcd-dsp-glink";
+	};
+
+	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>;
+	};
+};
+
+&slim_aud {
+	wcd9335: tasha_codec {
+		status = "disabled";
+		compatible = "qcom,tasha-slim-pgd";
+		elemental-addr = [00 01 a0 01 17 02];
+
+		interrupt-parent = <&wcd9xxx_intc>;
+		interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+		      17 18 19 20 21 22 23 24 25 26 27 28 29
+		      30>;
+
+		qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+
+		clock-names = "wcd_clk", "wcd_native_clk";
+		clocks = <&clock_audio AUDIO_PMI_CLK>,
+			 <&clock_audio_native AUDIO_LPASS_MCLK>;
+
+		cdc-vdd-mic-bias-supply = <&pm660l_bob>;
+		qcom,cdc-vdd-mic-bias-voltage = <3312000 3312000>;
+		qcom,cdc-vdd-mic-bias-current = <30400>;
+
+		qcom,cdc-static-supplies = "cdc-vdd-mic-bias";
+
+		qcom,cdc-micbias1-mv = <1800>;
+		qcom,cdc-micbias2-mv = <1800>;
+		qcom,cdc-micbias3-mv = <1800>;
+		qcom,cdc-micbias4-mv = <1800>;
+
+		qcom,cdc-mclk-clk-rate = <9600000>;
+		qcom,cdc-slim-ifd = "tasha-slim-ifd";
+		qcom,cdc-slim-ifd-elemental-addr = [00 00 a0 01 17 02];
+		qcom,cdc-dmic-sample-rate = <4800000>;
+		qcom,cdc-mad-dmic-rate = <600000>;
+	};
+
+	wcd934x_cdc: tavil_codec {
+		status = "disabled";
+		compatible = "qcom,tavil-slim-pgd";
+		elemental-addr = [00 01 50 02 17 02];
+
+		interrupt-parent = <&wcd9xxx_intc>;
+		interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+			      17 18 19 20 21 22 23 24 25 26 27 28 29
+			      30 31>;
+
+		qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+
+		clock-names = "wcd_clk";
+		clocks = <&clock_audio_lnbb AUDIO_PMIC_LNBB_CLK>;
+
+		cdc-vdd-mic-bias-supply = <&pm660l_bob>;
+		qcom,cdc-vdd-mic-bias-voltage = <3312000 3312000>;
+		qcom,cdc-vdd-mic-bias-current = <30400>;
+
+		qcom,cdc-static-supplies = "cdc-vdd-mic-bias";
+
+		qcom,cdc-micbias1-mv = <1800>;
+		qcom,cdc-micbias2-mv = <1800>;
+		qcom,cdc-micbias3-mv = <1800>;
+		qcom,cdc-micbias4-mv = <1800>;
+
+		qcom,cdc-mclk-clk-rate = <9600000>;
+		qcom,cdc-slim-ifd = "tavil-slim-ifd";
+		qcom,cdc-slim-ifd-elemental-addr = [00 00 50 02 17 02];
+		qcom,cdc-dmic-sample-rate = <4800000>;
+		qcom,cdc-mad-dmic-rate = <600000>;
+
+		qcom,wdsp-cmpnt-dev-name = "tavil_codec";
+
+		wcd_spi_0: wcd_spi {
+			compatible = "qcom,wcd-spi-v2";
+			qcom,master-bus-num = <0>;
+			qcom,chip-select = <0>;
+			qcom,max-frequency = <24000000>;
+			qcom,mem-base-addr = <0x100000>;
+		};
+	};
+};
+
+
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts
new file mode 100644
index 0000000..c7912d6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera-overlay.dts
@@ -0,0 +1,30 @@
+/*
+ * 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 "qcs605-lc-ipcamera.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 IPC";
+	compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
+	qcom,msm-id = <347 0x0>;
+	qcom,board-id = <8 6>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dts
new file mode 100644
index 0000000..90dcd7b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.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 "qcs605-lc.dtsi"
+#include "qcs605-lc-ipcamera.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 IPC";
+	compatible = "qcom,qcs605-mtp", "qcom,qcs605", "qcom,mtp";
+	qcom,board-id = <8 6>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi
new file mode 100644
index 0000000..d6d9a17
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-ipcamera.dtsi
@@ -0,0 +1,196 @@
+/* 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 "qcs605-lc-pmic-overlay.dtsi"
+#include "qcs605-lc-camera-sensor-mtp.dtsi"
+#include "qcs605-lc-ipcamera-audio.dtsi"
+
+&qupv3_se9_2uart {
+	status = "disabled";
+};
+
+&qupv3_se12_2uart {
+	status = "ok";
+};
+
+&sdhc_1 {
+	vdd-supply = <&pm660_l19>;
+	qcom,vdd-voltage-level = <2960000 2960000>;
+	qcom,vdd-current-level = <0 570000>;
+
+	vdd-io-supply = <&pm660_l8>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-lpm-sup;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <0 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>;
+
+	status = "ok";
+};
+
+&tlmm {
+	sdc2_cd_on: cd_on {
+		mux {
+			pins = "gpio116";
+			function = "gpio";
+		};
+
+		config {
+			pins = "gpio116";
+			drive-strength = <2>;
+			bias-pull-up;
+			};
+		};
+
+	sdc2_cd_off: cd_off {
+		mux {
+			pins = "gpio116";
+			function = "gpio";
+		};
+
+		config {
+			pins = "gpio116";
+			drive-strength = <2>;
+			bias-disable;
+			};
+	};
+};
+
+&sdhc_2 {
+	/* VDD external regulator is enabled/disabled by pm660_l18 regulator */
+	vdd-io-supply = <&pm660_l18>;
+	qcom,vdd-io-voltage-level = <1800000 2960000>;
+	qcom,vdd-io-current-level = <0 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 &sdc2_cd_off>;
+
+	cd-gpios = <&tlmm 116 0x1>;
+
+	status = "ok";
+};
+
+&usb0 {
+	dwc3@a600000 {
+		dr_mode = "host";
+	};
+};
+
+&icnss {
+	status = "disabled";
+};
+
+&msm_sdw_codec {
+	status = "disabled";
+};
+
+&cdc_pdm_gpios {
+	status = "disabled";
+};
+
+&cdc_comp_gpios {
+	status = "disabled";
+};
+
+&cdc_dmic_gpios {
+	status = "disabled";
+};
+
+&cdc_sdw_gpios {
+	status = "disabled";
+};
+
+&wsa_spkr_en1 {
+	status = "disabled";
+};
+
+&wsa_spkr_en2 {
+	status = "disabled";
+};
+
+&qupv3_se8_spi {
+	status = "okay";
+};
+
+&wcd9xxx_intc {
+	status = "okay";
+};
+
+&wdsp_mgr {
+	status = "okay";
+};
+
+&wdsp_glink {
+	status = "okay";
+};
+
+&slim_aud {
+	status = "okay";
+};
+
+&dai_slim {
+	status = "okay";
+};
+
+&wcd934x_cdc {
+	status = "okay";
+};
+
+&clock_audio_lnbb {
+	status = "okay";
+};
+
+&tavil_snd {
+	status = "okay";
+	compatible = "qcom,qcs605-asoc-snd-tavil";
+	qcom,model = "qcs605-tavil-snd-card";
+	qcom,audio-routing =
+		"AIF4 VI", "MCLK",
+		"RX_BIAS", "MCLK",
+		"MADINPUT", "MCLK",
+		"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";
+	qcom,wsa-max-devs = <1>;
+	qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0213>;
+	qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrLeft";
+};
+
+&soc {
+	wcd_rst_gpio1: msm_cdc_pinctrl@11 {
+		compatible = "qcom,msm-cdc-pinctrl";
+		qcom,cdc-rst-n-gpio = <&tlmm 11 0>;
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_reset_active>;
+		pinctrl-1 = <&cdc_reset_sleep>;
+	};
+};
+
+&wcd934x_cdc {
+	/delete-property/ cdc-vdd-mic-bias-supply;
+	/delete-property/ qcom,cdc-static-supplies;
+	qcom,wcd-rst-gpio-node = <&wcd_rst_gpio1>;
+};
+
+&wcd9335 {
+	/delete-property/ cdc-vdd-mic-bias-supply;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
index f8dde39..7e15752 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
@@ -212,6 +212,11 @@
 	vdd_gfx-supply = <&pm8005_s3_level>;
 };
 
+&gpu_cx_gdsc {
+	/delete-property/ parent-supply;
+	parent-supply = <&pm8005_s1_level>;
+};
+
 &gpu_gx_gdsc {
 	/delete-property/ parent-supply;
 	parent-supply = <&pm8005_s3_level>;
diff --git a/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi b/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi
index 382ba65..8efb7c1 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-pm660-pm8005-regulator.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -102,7 +102,8 @@
 		pm8005_s1_level: regulator-pm8005-s1-level {
 			regulator-name = "pm8005_s1_level";
 			qcom,set = <RPMH_REGULATOR_SET_ALL>;
-			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-min-microvolt
+				= <RPMH_REGULATOR_LEVEL_RETENTION>;
 			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
 			qcom,min-dropout-voltage-level = <(-1)>;
 		};
@@ -110,7 +111,8 @@
 		pm8005_s1_level_ao: regulator-pm8005-s1-level-ao {
 			regulator-name = "pm8005_s1_level_ao";
 			qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
-			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-min-microvolt
+				= <RPMH_REGULATOR_LEVEL_RETENTION>;
 			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
 			qcom,min-dropout-voltage-level = <(-1)>;
 		};
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi
index 16ae8de..7801775 100644
--- a/arch/arm64/boot/dts/qcom/qcs605.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi
@@ -76,6 +76,10 @@
 	};
 };
 
+&llcc {
+	compatible = "qcom,qcs605-llcc";
+};
+
 &ipa_hw {
 	status = "disabled";
 };
@@ -90,8 +94,8 @@
 	lmh-dcvs-00 {
 		trips {
 			active-config {
-				temperature = <105000>;
-				hysteresis = <40000>;
+				temperature = <100000>;
+				hysteresis = <35000>;
 			};
 		};
 	};
@@ -99,8 +103,16 @@
 	lmh-dcvs-01 {
 		trips {
 			active-config {
-				temperature = <105000>;
-				hysteresis = <40000>;
+				temperature = <100000>;
+				hysteresis = <35000>;
+			};
+		};
+	};
+
+	gpu-virt-max-step {
+		trips {
+			gpu-trip0 {
+				temperature = <100000>;
 			};
 		};
 	};
diff --git a/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi b/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi
index 5b1ed9c..ea385bd 100644
--- a/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi
@@ -17,6 +17,10 @@
 	/delete-property/ qcom,dsi-display-active;
 };
 
+&qrd_batterydata {
+	#include "fg-gen3-batterydata-mlp466076-3250mah.dtsi"
+};
+
 &dsi_hx8399_truly_cmd {
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
@@ -32,6 +36,29 @@
 	qcom,dsi-display-active;
 };
 
+&tavil_snd {
+	qcom,model = "sdm670-tavil-hdk-snd-card";
+	com,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",
+		"DMIC3", "MIC BIAS3",
+		"MIC BIAS3", "Digital Mic3",
+		"DMIC4", "MIC BIAS4",
+		"MIC BIAS4", "Digital Mic4",
+		"SpkrLeft IN", "SPK1 OUT";
+
+	qcom,wsa-max-devs = <1>;
+	qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0213>;
+	qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrLeft";
+};
+
 &ufsphy_mem {
 	compatible = "qcom,ufs-phy-qmp-v3";
 
@@ -57,3 +84,46 @@
 
 	status = "ok";
 };
+
+&qusb_phy0 {
+	qcom,qusb-phy-host-init-seq =
+			/* <value reg_offset> */
+			   <0x23 0x210 /* PWR_CTRL1 */
+			    0x03 0x04  /* PLL_ANALOG_CONTROLS_TWO */
+			    0x7c 0x18c /* PLL_CLOCK_INVERTERS */
+			    0x80 0x2c  /* PLL_CMODE */
+			    0x0a 0x184 /* PLL_LOCK_DELAY */
+			    0x19 0xb4  /* PLL_DIGITAL_TIMERS_TWO */
+			    0x40 0x194 /* PLL_BIAS_CONTROL_1 */
+			    0x20 0x198 /* PLL_BIAS_CONTROL_2 */
+			    0x21 0x214 /* PWR_CTRL2 */
+			    0x0f 0x220 /* IMP_CTRL1 */
+			    0x58 0x224 /* IMP_CTRL2 */
+			    0xc5 0x240 /* TUNE1 */
+			    0x29 0x244 /* TUNE2 */
+			    0xca 0x248 /* TUNE3 */
+			    0x04 0x24c /* TUNE4 */
+			    0x03 0x250 /* TUNE5 */
+			    0x00 0x23c /* CHG_CTRL2 */
+			    0x22 0x210>; /* PWR_CTRL1 */
+	qcom,qusb-phy-init-seq =
+			/* <value reg_offset> */
+			   <0x23 0x210 /* PWR_CTRL1 */
+			    0x03 0x04  /* PLL_ANALOG_CONTROLS_TWO */
+			    0x7c 0x18c /* PLL_CLOCK_INVERTERS */
+			    0x80 0x2c  /* PLL_CMODE */
+			    0x0a 0x184 /* PLL_LOCK_DELAY */
+			    0x19 0xb4  /* PLL_DIGITAL_TIMERS_TWO */
+			    0x40 0x194 /* PLL_BIAS_CONTROL_1 */
+			    0x20 0x198 /* PLL_BIAS_CONTROL_2 */
+			    0x21 0x214 /* PWR_CTRL2 */
+			    0x00 0x220 /* IMP_CTRL1 */
+			    0x58 0x224 /* IMP_CTRL2 */
+			    0x67 0x240 /* TUNE1 */
+			    0x29 0x244 /* TUNE2 */
+			    0xca 0x248 /* TUNE3 */
+			    0x04 0x24c /* TUNE4 */
+			    0x03 0x250 /* TUNE5 */
+			    0x00 0x23c /* CHG_CTRL2 */
+			    0x22 0x210>; /* PWR_CTRL1 */
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670.dtsi b/arch/arm64/boot/dts/qcom/sda670.dtsi
index d19aac3..0861718 100644
--- a/arch/arm64/boot/dts/qcom/sda670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda670.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,3 +17,13 @@
 	model = "Qualcomm Technologies, Inc. SDA670";
 	qcom,msm-id = <337 0x0>;
 };
+
+&soc {
+	qcom,rmnet-ipa {
+		status="disabled";
+	};
+};
+
+&ipa_hw {
+	status="disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/sda845-svr.dtsi b/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
index 1062ca6..f6bf107d 100644
--- a/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
@@ -270,6 +270,13 @@
 	qcom,init-voltage = <3312000>;
 };
 
+&pm8998_l19 {
+	regulator-min-microvolt = <3104000>;
+	regulator-max-microvolt = <3104000>;
+	qcom,init-voltage = <3104000>;
+};
+
+
 &ufsphy_mem {
 	compatible = "qcom,ufs-phy-qmp-v3";
 
diff --git a/arch/arm64/boot/dts/qcom/sdm429.dtsi b/arch/arm64/boot/dts/qcom/sdm429.dtsi
index b52ee2d..65f7b5e 100644
--- a/arch/arm64/boot/dts/qcom/sdm429.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429.dtsi
@@ -69,8 +69,8 @@
 		target-dev = <&cpubw>;
 		cpu-to-dev-map =
 			<  960000  2929 >,
-			< 1305600  5126 >,
-			< 1497600  5859 >,
+			< 1305600  5053 >,
+			< 1497600  5712 >,
 			< 1708800  6445 >,
 			< 1804800  7104 >,
 			< 1958400  7104 >;
@@ -91,7 +91,7 @@
 			target-dev = <&mincpubw>;
 			cpu-to-dev-map =
 				< 1305600 2929 >,
-				< 1804800 5859 >;
+				< 1804800 5712 >;
 		};
 	};
 };
@@ -222,4 +222,7 @@
 &msm_gpu {
 	/* Update GPU chip ID*/
 	qcom,chipid = <0x05000400>;
+
+	/* disable mem pools */
+	/delete-node/qcom,gpu-mempools;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi
index eae8c56..2987d67 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi
@@ -30,7 +30,7 @@
 		cell-index = <1>;
 		reg = <0x1>;
 		compatible = "qcom,actuator";
-		qcom,cci-master = <0>;
+		qcom,cci-master = <1>;
 		cam_vaf-supply = <&pm8953_l17>;
 		qcom,cam-vreg-name = "cam_vaf";
 		qcom,cam-vreg-min-voltage = <2850000>;
@@ -156,6 +156,43 @@
 		qcom,clock-rates = <19200000 0>;
 	};
 
+	eeprom2: qcom,eeprom@2 {
+		cell-index = <2>;
+		compatible = "qcom,eeprom";
+		qcom,cci-master = <1>;
+		reg = <0x2>;
+		cam_vdig-supply = <&pm8953_l3>;
+		cam_vana-supply = <&pm8953_l22>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vaf-supply = <&pm8953_l17>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+					"cam_vaf";
+		qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk2_default
+				&cam_sensor_front1_default>;
+		pinctrl-1 = <&cam_sensor_mclk2_sleep
+				&cam_sensor_front1_sleep>;
+		gpios = <&tlmm 28 0>,
+			<&tlmm 40 0>,
+			<&tlmm 39 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+					  "CAM_RESET2",
+					  "CAM_STANDBY2";
+		status = "ok";
+		clocks = <&clock_gcc clk_mclk2_clk_src>,
+				<&clock_gcc clk_gcc_camss_mclk2_clk>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <19200000 0>;
+	};
+
 	qcom,camera@0 {
 		cell-index = <0>;
 		compatible = "qcom,camera";
@@ -249,9 +286,9 @@
 		qcom,csiphy-sd-index = <1>;
 		qcom,csid-sd-index = <1>;
 		qcom,mount-angle = <90>;
-		qcom,eeprom-src = <&eeprom1>;
+		qcom,eeprom-src = <&eeprom2>;
 		qcom,actuator-src = <&actuator1>;
-		cam_vdig-supply = <&pm8953_l23>;
+		cam_vdig-supply = <&pm8953_l3>;
 		cam_vana-supply = <&pm8953_l22>;
 		cam_vio-supply = <&pm8953_l6>;
 		cam_vaf-supply = <&pm8953_l17>;
@@ -278,7 +315,7 @@
 					  "CAM_STANDBY2";
 		qcom,sensor-position = <1>;
 		qcom,sensor-mode = <0>;
-		qcom,cci-master = <0>;
+		qcom,cci-master = <1>;
 		status = "ok";
 		clocks = <&clock_gcc clk_mclk2_clk_src>,
 			<&clock_gcc clk_gcc_camss_mclk2_clk>;
diff --git a/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
index 6ecd0dd..cef5534 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
@@ -233,7 +233,7 @@
 
 &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,mdss-dsi-panel-timings-phy-12nm = [09 06 0a 02 00 05 02 08];
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
 	qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
@@ -568,3 +568,27 @@
 	qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
 	/delete-node/ qcom,mdss-dsi-display-timings;
 };
+
+&dsi_truly_1080_vid {
+	/delete-property/ qcom,mdss-dsi-panel-timings;
+	qcom,mdss-dsi-panel-timings-phy-12nm = [17 0a 0f 06 02 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";
+	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>;
+};
+
+&dsi_truly_1080_cmd {
+	/delete-property/ qcom,mdss-dsi-panel-timings;
+	qcom,mdss-dsi-panel-timings-phy-12nm = [17 0a 0f 06 02 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";
+	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>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
index a940515..913d079 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
@@ -208,7 +208,7 @@
 
 &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,mdss-dsi-panel-timings-phy-12nm = [09 06 0a 02 00 05 02 08];
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
 	qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
@@ -544,6 +544,30 @@
 	/delete-node/ qcom,mdss-dsi-display-timings;
 };
 
+&dsi_truly_1080_vid {
+	/delete-property/ qcom,mdss-dsi-panel-timings;
+	qcom,mdss-dsi-panel-timings-phy-12nm = [17 0a 0f 06 02 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";
+	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>;
+};
+
+&dsi_truly_1080_cmd {
+	/delete-property/ qcom,mdss-dsi-panel-timings;
+	qcom,mdss-dsi-panel-timings-phy-12nm = [17 0a 0f 06 02 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";
+	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>;
+};
+
 &i2c_2 {
 #include "smb1355.dtsi"
 };
@@ -565,6 +589,15 @@
 			bias-disable;		/* no-pull */
 		};
 	};
+
+	pmi632_ctm {
+		/* Disable GPIO1 for h/w base mitigation */
+		pmi632_ctm_default: pmi632_ctm_default {
+			pins = "gpio1";
+			bias-high-impedance;	/* disable the GPIO */
+			bias-disable;		/* no-pull */
+		};
+	};
 };
 
 &tlmm {
@@ -585,7 +618,7 @@
 &smb1355_0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&smb_int_default
-		&smb_en_default &pmi632_sense_default>;
+		&smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
 	interrupt-parent = <&tlmm>;
 	interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
 	smb1355_charger_0: qcom,smb1355-charger@1000 {
@@ -593,13 +626,15 @@
 		/delete-property/ io-channels;
 		/delete-property/ io-channels-names;
 		qcom,parallel-mode = <1>;
+		qcom,disable-ctm;
+		qcom,hw-die-temp-mitigation;
 	};
 };
 
 &smb1355_1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&smb_int_default
-		&smb_en_default &pmi632_sense_default>;
+		&smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
 	interrupt-parent = <&tlmm>;
 	interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
 	smb1355_charger_1: qcom,smb1355-charger@1000 {
@@ -607,5 +642,7 @@
 		/delete-property/ io-channels;
 		/delete-property/ io-channels-names;
 		qcom,parallel-mode = <1>;
+		qcom,disable-ctm;
+		qcom,hw-die-temp-mitigation;
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
index ac31fc8..20562d1 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
@@ -115,7 +115,7 @@
 	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>;
 
-	cd-gpios = <&tlmm 67 0x1>;
+	cd-gpios = <&tlmm 67 0x0>;
 
 	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
 								200000000>;
@@ -323,7 +323,7 @@
 
 &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,mdss-dsi-panel-timings-phy-12nm = [09 06 0a 02 00 05 02 08];
 	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
 	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
 	qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
@@ -371,6 +371,15 @@
 			bias-disable;		/* no-pull */
 		};
 	};
+
+	pmi632_ctm {
+		/* Disable GPIO1 for h/w base mitigation */
+		pmi632_ctm_default: pmi632_ctm_default {
+			pins = "gpio1";
+			bias-high-impedance;	/* disable the GPIO */
+			bias-disable;		/* no-pull */
+		};
+	};
 };
 
 &tlmm {
@@ -391,7 +400,7 @@
 &smb1355_0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&smb_int_default
-		&smb_en_default &pmi632_sense_default>;
+		&smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
 	interrupt-parent = <&tlmm>;
 	interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
 	smb1355_charger_0: qcom,smb1355-charger@1000 {
@@ -399,13 +408,15 @@
 		/delete-property/ io-channels;
 		/delete-property/ io-channels-names;
 		qcom,parallel-mode = <1>;
+		qcom,disable-ctm;
+		qcom,hw-die-temp-mitigation;
 	};
 };
 
 &smb1355_1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&smb_int_default
-		&smb_en_default &pmi632_sense_default>;
+		&smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
 	interrupt-parent = <&tlmm>;
 	interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
 	smb1355_charger_1: qcom,smb1355-charger@1000 {
@@ -413,5 +424,12 @@
 		/delete-property/ io-channels;
 		/delete-property/ io-channels-names;
 		qcom,parallel-mode = <1>;
+		qcom,disable-ctm;
+		qcom,hw-die-temp-mitigation;
 	};
 };
+
+&pmi632_charger {
+	qcom,thermal-mitigation = <4200000 3500000 3000000 2500000
+				2000000 1500000 1000000 500000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
index 414e8fe..42c3e83 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
@@ -477,17 +477,22 @@
 
 		qcom,cpr-quotient-adjustment =
 			<66      77      66>, /* SVSP/NOM/TUR:30/35/30 mV */
-			<(-74) (-57)  (-30)>, /* SVSP/NOM/TUR:-34/-26/-14 mV */
+			<(-74)    0   (-30)>, /* SVSP/NOM/TUR:-34/0/-14 mV */
 			<0        0       0>;
 
 		qcom,cpr-floor-to-ceiling-max-range =
-			<50000 50000 50000 65000 65000>,
-			<50000 50000 50000 65000 65000>,
-			<50000 50000 50000 65000 65000>;
+			<50000 50000 65000 65000 65000>,
+			<50000 50000 65000 65000 65000>,
+			<50000 50000 65000 65000 65000>;
 
 		qcom,cpr-voltage-ceiling-override =
 			<(-1) (-1) 810000 845000 885000 960000 960000>;
 
+		qcom,cpr-virtual-corner-quotient-adjustment =
+			<0  0    0   0   0>,
+			<0  0  (-22) 0   0>, /* NOMP: -10 mV */
+			<0  0    0   0   0>;
+
 		qcom,cpr-enable;
 	};
 
diff --git a/arch/arm64/boot/dts/qcom/sdm439.dtsi b/arch/arm64/boot/dts/qcom/sdm439.dtsi
index be05b6e..9067bc9 100644
--- a/arch/arm64/boot/dts/qcom/sdm439.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439.dtsi
@@ -78,9 +78,9 @@
 			<  2929 /*  384   MHz */ >,     /* SVS */
 			<  3221 /*  422.4 MHz */ >,
 			<  4248 /*  556.8 MHz */ >,
-			<  5126 /*  662.4 MHz */ >,     /* SVS+  */
-			<  5859 /*  748.8 MHz */ >,     /* NOM   */
-			<  6152 /*  806.4 MHz */ >,     /* NOM+  */
+			<  5053 /*  662.4 MHz */ >,     /* SVS+  */
+			<  5712 /*  748.8 MHz */ >,     /* NOM   */
+			<  6079 /*  796.8 MHz */ >,     /* NOM+  */
 			<  6445 /*  844.8 MHz */ >,
 			<  7104 /*  931.2 MHz */ >;     /* TURBO */
 	};
@@ -98,9 +98,9 @@
 			<  2929 /*  384   MHz */ >,     /* SVS */
 			<  3221 /*  422.4 MHz */ >,
 			<  4248 /*  556.8 MHz */ >,
-			<  5126 /*  662.4 MHz */ >,     /* SVS+  */
-			<  5859 /*  748.8 MHz */ >,     /* NOM   */
-			<  6152 /*  806.4 MHz */ >,     /* NOM+  */
+			<  5053 /*  662.4 MHz */ >,     /* SVS+  */
+			<  5712 /*  748.8 MHz */ >,     /* NOM   */
+			<  6079 /*  796.8 MHz */ >,     /* NOM+  */
 			<  6445 /*  844.8 MHz */ >,
 			<  7104 /*  931.2 MHz */ >;     /* TURBO */
 	};
@@ -124,16 +124,16 @@
 		cpubw-cpufreq {
 		target-dev = <&cpubw>;
 		cpu-to-dev-map-0 =
-			< 1305600  5126 >,
-			< 1497600  5859 >,
+			< 1305600  5053 >,
+			< 1497600  5712 >,
 			< 1708800  6445 >,
 			< 1804800  7104 >,
 			< 1958400  7104 >;
 		cpu-to-dev-map-4 =
 			<  768000  2929 >,
-			<  998400  5126 >,
-			< 1171200  5859 >,
-			< 1305600  6152 >,
+			<  998400  5053 >,
+			< 1171200  5712 >,
+			< 1305600  6079 >,
 			< 1459200  7104 >;
 
 		};
@@ -158,10 +158,10 @@
 			target-dev = <&mincpubw>;
 			cpu-to-dev-map-0 =
 				< 1305600 2929 >,
-				< 1804800 5859 >;
+				< 1804800 5712 >;
 			cpu-to-dev-map-4 =
 				< 1171200 2929 >,
-				< 1459200 5859 >;
+				< 1459200 5712 >;
 		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
index 07d2e08..5db626b 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
@@ -68,6 +68,15 @@
 			bias-disable;		/* no-pull */
 		};
 	};
+
+	pmi632_ctm {
+		/* Disable GPIO1 for h/w base mitigation */
+		pmi632_ctm_default: pmi632_ctm_default {
+			pins = "gpio1";
+			bias-high-impedance;	/* disable the GPIO */
+			bias-disable;		/* no-pull */
+		};
+	};
 };
 
 &tlmm {
@@ -88,7 +97,7 @@
 &smb1355_0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&smb_int_default
-		&smb_en_default &pmi632_sense_default>;
+		&smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
 	interrupt-parent = <&tlmm>;
 	interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
 	smb1355_charger_0: qcom,smb1355-charger@1000 {
@@ -96,13 +105,15 @@
 		/delete-property/ io-channels;
 		/delete-property/ io-channels-names;
 		qcom,parallel-mode = <1>;
+		qcom,disable-ctm;
+		qcom,hw-die-temp-mitigation;
 	};
 };
 
 &smb1355_1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&smb_int_default
-		&smb_en_default &pmi632_sense_default>;
+		&smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
 	interrupt-parent = <&tlmm>;
 	interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
 	smb1355_charger_1: qcom,smb1355-charger@1000 {
@@ -110,5 +121,7 @@
 		/delete-property/ io-channels;
 		/delete-property/ io-channels-names;
 		qcom,parallel-mode = <1>;
+		qcom,disable-ctm;
+		qcom,hw-die-temp-mitigation;
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
index a2bd5cd..8671877 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
@@ -198,6 +198,15 @@
 			bias-disable;		/* no-pull */
 		};
 	};
+
+	pmi632_ctm {
+		/* Disable GPIO1 for h/w base mitigation */
+		pmi632_ctm_default: pmi632_ctm_default {
+			pins = "gpio1";
+			bias-high-impedance;	/* disable the GPIO */
+			bias-disable;		/* no-pull */
+		};
+	};
 };
 
 &tlmm {
@@ -218,7 +227,7 @@
 &smb1355_0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&smb_int_default
-		&smb_en_default &pmi632_sense_default>;
+		&smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
 	interrupt-parent = <&tlmm>;
 	interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
 	smb1355_charger_0: qcom,smb1355-charger@1000 {
@@ -226,13 +235,15 @@
 		/delete-property/ io-channels;
 		/delete-property/ io-channels-names;
 		qcom,parallel-mode = <1>;
+		qcom,disable-ctm;
+		qcom,hw-die-temp-mitigation;
 	};
 };
 
 &smb1355_1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&smb_int_default
-		&smb_en_default &pmi632_sense_default>;
+		&smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
 	interrupt-parent = <&tlmm>;
 	interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
 	smb1355_charger_1: qcom,smb1355-charger@1000 {
@@ -240,5 +251,12 @@
 		/delete-property/ io-channels;
 		/delete-property/ io-channels-names;
 		qcom,parallel-mode = <1>;
+		qcom,disable-ctm;
+		qcom,hw-die-temp-mitigation;
 	};
 };
+
+&pmi632_charger {
+	qcom,thermal-mitigation = <4200000 3500000 3000000 2500000
+				2000000 1500000 1000000 500000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm632-qrd.dtsi
index cefc078..6a07bfe 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632-qrd.dtsi
@@ -18,3 +18,8 @@
 	qcom,redrive-voltage-level = <0 1800000 1900000>;
 	qcom,redrive-load = <105000>;
 };
+
+&pmi632_charger {
+	qcom,thermal-mitigation = <4200000 3500000 3000000 2500000
+				2000000 1500000 1000000 500000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-360camera.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-360camera.dtsi
index c40fff6..1cfa3ae 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-360camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-camera-sensor-360camera.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
@@ -189,7 +189,7 @@
 	rgltr-cntrl-support;
 	rgltr-min-voltage = <1352000 1800000 2850000 0 2800000>;
 	rgltr-max-voltage = <1352000 1800000 2850000 0 2800000>;
-	rgltr-load-current = <105000 0 80000 0>;
+	rgltr-load-current = <105000 0 80000 0 0>;
 	gpio-no-mux = <0>;
 	pinctrl-names = "cam_default", "cam_suspend";
 	pinctrl-0 = <&cam_sensor_mclk1_active
@@ -226,7 +226,7 @@
 	rgltr-cntrl-support;
 	rgltr-min-voltage = <1800000 2850000 1352000 0 2800000>;
 	rgltr-max-voltage = <1800000 2850000 1352000 0 2800000>;
-	rgltr-load-current = <0 80000 105000 0>;
+	rgltr-load-current = <0 80000 105000 0 0>;
 	gpio-no-mux = <0>;
 	pinctrl-names = "cam_default", "cam_suspend";
 	pinctrl-0 = <&cam_sensor_mclk2_active
diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi
index 348ba6f..76b7b05 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi
@@ -46,6 +46,7 @@
 			"csiphy0_clk",
 			"csi0phytimer_clk_src",
 			"csi0phytimer_clk";
+		src-clock-name = "csi0phytimer_clk_src";
 		clock-cntl-level = "turbo";
 		clock-rates =
 			<0 0 0 0 384000000 0 269333333 0>;
@@ -81,6 +82,7 @@
 			"csiphy1_clk",
 			"csi1phytimer_clk_src",
 			"csi1phytimer_clk";
+		src-clock-name = "csi1phytimer_clk_src";
 		clock-cntl-level = "turbo";
 		clock-rates =
 			<0 0 0 0 384000000 0 269333333 0>;
@@ -117,6 +119,7 @@
 			"csiphy2_clk",
 			"csi2phytimer_clk_src",
 			"csi2phytimer_clk";
+		src-clock-name = "csi2phytimer_clk_src";
 		clock-cntl-level = "turbo";
 		clock-rates =
 			<0 0 0 0 384000000 0 269333333 0>;
@@ -338,17 +341,17 @@
 				iova-mem-region-io {
 					/* IO region is approximately 3 GB */
 					iova-region-name = "io";
-					iova-region-start = <0xd911000>;
-					iova-region-len = <0xd26ef000>;
+					iova-region-start = <0xda00000>;
+					iova-region-len = <0xd2500000>;
 					iova-region-id = <0x3>;
 					status = "ok";
 				};
 
 				iova-mem-qdss-region {
-					/* qdss region is approximately 64K */
+					/* qdss region is approximately 1MB */
 					iova-region-name = "qdss";
 					iova-region-start = <0xd900000>;
-					iova-region-len = <0x10000>;
+					iova-region-len = <0x100000>;
 					iova-region-id = <0x5>;
 					qdss-phy-addr = <0x16790000>;
 					status = "ok";
@@ -911,6 +914,9 @@
 	cam_ipe0: qcom,ipe0 {
 		cell-index = <0>;
 		compatible = "qcom,cam-ipe";
+		reg = <0xac87000 0x3000>;
+		reg-names = "ipe0_top";
+		reg-cam-base = <0x87000>;
 		regulator-names = "ipe0-vdd";
 		ipe0-vdd-supply = <&ipe_0_gdsc>;
 		clock-names = "ipe_0_ahb_clk",
@@ -938,6 +944,9 @@
 	cam_ipe1: qcom,ipe1 {
 		cell-index = <1>;
 		compatible = "qcom,cam-ipe";
+		reg = <0xac91000 0x3000>;
+		reg-names = "ipe1_top";
+		reg-cam-base = <0x91000>;
 		regulator-names = "ipe1-vdd";
 		ipe1-vdd-supply = <&ipe_1_gdsc>;
 		clock-names = "ipe_1_ahb_clk",
@@ -965,6 +974,9 @@
 	cam_bps: qcom,bps {
 		cell-index = <0>;
 		compatible = "qcom,cam-bps";
+		reg = <0xac6f000 0x3000>;
+		reg-names = "bps_top";
+		reg-cam-base = <0x6f000>;
 		regulator-names = "bps-vdd";
 		bps-vdd-supply = <&bps_gdsc>;
 		clock-names = "bps_ahb_clk",
diff --git a/arch/arm64/boot/dts/qcom/sdm670-ion.dtsi b/arch/arm64/boot/dts/qcom/sdm670-ion.dtsi
index 3fd1229..0968a52 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-ion.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-ion.dtsi
@@ -49,5 +49,12 @@
 			reg = <9>;
 			qcom,ion-heap-type = "SYSTEM_SECURE";
 		};
+
+		qcom,ion-heap@22 { /* ADSP HEAP */
+			reg = <22>;
+			memory-region = <&sdsp_mem>;
+			qcom,ion-heap-type = "DMA";
+		};
+
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
index 0461429..0453cee 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
@@ -1490,6 +1490,34 @@
 			};
 		};
 
+		cdc_reset_ctrl {
+			cdc_reset_sleep: cdc_reset_sleep {
+				mux {
+					pins = "gpio11";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio11";
+					drive-strength = <2>;
+					bias-disable;
+					output-low;
+				};
+			};
+
+			cdc_reset_active:cdc_reset_active {
+				mux {
+					pins = "gpio11";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio11";
+					drive-strength = <8>;
+					bias-pull-down;
+					output-high;
+				};
+			};
+		};
+
 		/* WSA speaker reset pins */
 		spkr_1_sd_n {
 			spkr_1_sd_n_sleep: spkr_1_sd_n_sleep {
diff --git a/arch/arm64/boot/dts/qcom/sdm670-qrd-sku1.dtsi b/arch/arm64/boot/dts/qcom/sdm670-qrd-sku1.dtsi
index 2c1cde6..ecd389b 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-qrd-sku1.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-qrd-sku1.dtsi
@@ -10,5 +10,5 @@
  * GNU General Public License for more details.
  */
 
-#include "sdm670-qrd.dtsi"
 #include "sdm670-audio-overlay.dtsi"
+#include "sdm670-qrd.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2-overlay.dts b/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2-overlay.dts
index d5edb36..2968ecc 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2-overlay.dts
@@ -13,6 +13,11 @@
 /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-qrd-sku2.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2.dtsi b/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2.dtsi
index cdb652e..0f23216 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-qrd-sku2.dtsi
@@ -9,8 +9,8 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  */
-#include "sdm670-qrd.dtsi"
 #include "sdm670-audio-overlay.dtsi"
+#include "sdm670-qrd.dtsi"
 
 &dsi_dual_nt36850_truly_cmd_display {
 	/delete-property/ qcom,dsi-display-active;
diff --git a/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
index 9d3f37d..3efadcb 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-regulator.dtsi
@@ -133,7 +133,8 @@
 		pm660l_s3_level: regulator-pm660l-s3-level {
 			regulator-name = "pm660l_s3_level";
 			qcom,set = <RPMH_REGULATOR_SET_ALL>;
-			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-min-microvolt
+				= <RPMH_REGULATOR_LEVEL_RETENTION>;
 			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
 			qcom,min-dropout-voltage-level = <(-1)>;
 		};
@@ -141,7 +142,8 @@
 		pm660l_s3_level_ao: regulator-pm660l-s3-level-ao {
 			regulator-name = "pm660l_s3_level_ao";
 			qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
-			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-min-microvolt
+				= <RPMH_REGULATOR_LEVEL_RETENTION>;
 			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
 			qcom,min-dropout-voltage-level = <(-1)>;
 		};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
index 395e88c..5d62c5a 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-sde-display.dtsi
@@ -27,6 +27,7 @@
 #include "dsi-panel-rm67195-amoled-fhd-cmd.dtsi"
 #include "dsi-panel-nt36850-truly-dualmipi-wqhd-cmd.dtsi"
 #include "dsi-panel-hx8399-truly-singlemipi-fhd-video.dtsi"
+#include "dsi-panel-hx83112a-truly-singlemipi-fhd-video.dtsi"
 #include <dt-bindings/clock/mdss-10nm-pll-clk.h>
 
 &soc {
@@ -489,7 +490,30 @@
 		ibb-supply = <&lcdb_ncp_vreg>;
 	};
 
-	ext_dsi_bridge_display: qcom,dsi-display@17 {
+	dsi_hx83112a_truly_video_display: qcom,dsi-display@17 {
+		compatible = "qcom,dsi-display";
+		label = "dsi_hx83112a_truly_video_display";
+		qcom,display-type = "primary";
+
+		qcom,dsi-ctrl = <&mdss_dsi0>;
+		qcom,dsi-phy = <&mdss_dsi_phy0>;
+		clocks = <&mdss_dsi0_pll BYTECLK_MUX_0_CLK>,
+			<&mdss_dsi0_pll PCLK_MUX_0_CLK>;
+		clock-names = "src_byte_clk", "src_pixel_clk";
+
+		pinctrl-names = "panel_active", "panel_suspend";
+		pinctrl-0 = <&sde_dsi_active &sde_te_active>;
+		pinctrl-1 = <&sde_dsi_suspend &sde_te_suspend>;
+		qcom,platform-te-gpio = <&tlmm 10 0>;
+		qcom,platform-reset-gpio = <&tlmm 75 0>;
+
+		qcom,dsi-panel = <&dsi_hx83112a_truly_video>;
+		vddio-supply = <&pm660_l11>;
+		lab-supply = <&lcdb_ldo_vreg>;
+		ibb-supply = <&lcdb_ncp_vreg>;
+	};
+
+	ext_dsi_bridge_display: qcom,dsi-display@18 {
 		compatible = "qcom,dsi-display";
 		label = "ext_dsi_bridge_display";
 		qcom,display-type = "primary";
@@ -561,7 +585,7 @@
 	qcom,mdss-dsi-display-timings {
 		timing@0{
 			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
-				07 05 03 04 00];
+				07 05 02 04 00];
 			qcom,display-topology = <2 0 2>,
 						<1 0 2>;
 			qcom,default-topology-index = <0>;
@@ -583,7 +607,7 @@
 	qcom,mdss-dsi-display-timings {
 		timing@0{
 			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
-				07 05 03 04 00];
+				07 05 02 04 00];
 			qcom,display-topology = <2 0 2>,
 						<1 0 2>;
 			qcom,default-topology-index = <0>;
@@ -607,7 +631,7 @@
 	qcom,mdss-dsi-display-timings {
 		timing@0{
 			qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05
-				05 03 03 04 00];
+				05 03 02 04 00];
 			qcom,display-topology = <1 1 1>,
 						<2 2 1>, /* dsc merge */
 						<2 1 1>; /* 3d mux */
@@ -634,7 +658,7 @@
 	qcom,mdss-dsi-display-timings {
 		timing@0{
 			qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05
-				04 03 03 04 00];
+				04 03 02 04 00];
 			qcom,display-topology = <1 1 1>,
 						<2 2 1>, /* dsc merge */
 						<2 1 1>; /* 3d mux */
@@ -649,7 +673,7 @@
 	qcom,mdss-dsi-display-timings {
 		timing@0{
 			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
-				07 05 03 04 00];
+				07 05 02 04 00];
 			qcom,display-topology = <1 0 1>,
 						<2 0 1>;
 			qcom,default-topology-index = <0>;
@@ -663,7 +687,7 @@
 	qcom,mdss-dsi-display-timings {
 		timing@0{
 			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
-				07 05 03 04 00];
+				07 05 02 04 00];
 			qcom,display-topology = <2 0 2>,
 						<1 0 2>;
 			qcom,default-topology-index = <0>;
@@ -682,7 +706,7 @@
 			qcom,panel-roi-alignment = <720 40 720 40 720 40>;
 			qcom,partial-update-enabled = "single_roi";
 			qcom,mdss-dsi-panel-phy-timings = [00 1a 06 06 22 20 07
-				07 04 03 04 00];
+				07 04 02 04 00];
 		};
 		timing@1{
 			qcom,display-topology = <1 0 1>,
@@ -691,7 +715,7 @@
 			qcom,panel-roi-alignment = <540 40 540 40 540 40>;
 			qcom,partial-update-enabled = "single_roi";
 			qcom,mdss-dsi-panel-phy-timings = [00 1a 06 06 22 20 07
-				07 04 03 04 00];
+				07 04 02 04 00];
 		};
 		timing@2{
 			qcom,display-topology = <1 0 1>,
@@ -700,7 +724,7 @@
 			qcom,panel-roi-alignment = <360 40 360 40 360 40>;
 			qcom,partial-update-enabled = "single_roi";
 			qcom,mdss-dsi-panel-phy-timings = [00 1a 06 06 22 20 07
-				07 04 03 04 00];
+				07 04 02 04 00];
 		};
 	};
 };
@@ -711,20 +735,20 @@
 	qcom,mdss-dsi-display-timings {
 		timing@0{
 			qcom,mdss-dsi-panel-phy-timings = [00 24 09 09 26 24 09
-				09 06 03 04 00];
+				09 06 02 04 00];
 			qcom,display-topology = <2 0 2>;
 			qcom,default-topology-index = <0>;
 		};
 		timing@1{
 			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
-				07 05 03 04 00];
+				07 05 02 04 00];
 			qcom,display-topology = <2 0 2>,
 						<1 0 2>;
 			qcom,default-topology-index = <0>;
 		};
 		timing@2{
 			qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06
-				06 04 03 04 00];
+				06 04 02 04 00];
 			qcom,display-topology = <2 0 2>;
 			qcom,default-topology-index = <0>;
 		};
@@ -737,13 +761,13 @@
 	qcom,mdss-dsi-display-timings {
 		timing@0 { /* 1080p */
 			qcom,mdss-dsi-panel-phy-timings = [00 1A 06 06 22 20 07
-				07 04 03 04 00];
+				07 04 02 04 00];
 			qcom,display-topology = <1 1 1>;
 			qcom,default-topology-index = <0>;
 		};
 		timing@1 { /* qhd */
 			qcom,mdss-dsi-panel-phy-timings = [00 15 05 05 20 1f 05
-				05 03 03 04 00];
+				05 03 02 04 00];
 			qcom,display-topology = <1 1 1>,
 						<2 2 1>, /* dsc merge */
 						<2 1 1>; /* 3d mux */
@@ -758,13 +782,13 @@
 	qcom,mdss-dsi-display-timings {
 		timing@0 { /* qhd */
 			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
-				07 05 03 04 00];
+				07 05 02 04 00];
 			qcom,display-topology = <2 2 2>;
 			qcom,default-topology-index = <0>;
 		};
 		timing@1 { /* 4k */
 			qcom,mdss-dsi-panel-phy-timings = [00 18 06 06 21 20 06
-				06 04 03 04 00];
+				06 04 02 04 00];
 			qcom,display-topology = <2 2 2>;
 			qcom,default-topology-index = <0>;
 		};
@@ -777,7 +801,7 @@
 	qcom,mdss-dsi-display-timings {
 		 timing@0 {
 			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
-				07 05 03 04 00];
+				07 05 02 04 00];
 			qcom,display-topology = <2 0 2>,
 						<1 0 2>;
 			qcom,default-topology-index = <0>;
@@ -792,7 +816,7 @@
 	qcom,mdss-dsi-display-timings {
 		 timing@0 {
 			qcom,mdss-dsi-panel-phy-timings = [00 1c 07 07 23 21 07
-				07 05 03 04 00];
+				07 05 02 04 00];
 			qcom,display-topology = <2 0 2>,
 						<1 0 2>;
 			qcom,default-topology-index = <0>;
@@ -808,7 +832,7 @@
 	qcom,mdss-dsi-display-timings {
 		timing@0 {
 			qcom,mdss-dsi-panel-phy-timings = [00 1c 05 06 0b 0c
-				05 07 05 03 04 00];
+				05 07 05 02 04 00];
 			qcom,display-topology = <1 0 1>;
 			qcom,default-topology-index = <0>;
 		};
@@ -826,7 +850,7 @@
 	qcom,mdss-dsi-display-timings {
 		timing@0 {
 			qcom,mdss-dsi-panel-phy-timings = [00 1c 05 06 0b 0c
-				05 07 05 03 04 00];
+				05 07 05 02 04 00];
 			qcom,display-topology = <1 0 1>;
 			qcom,default-topology-index = <0>;
 		};
@@ -841,7 +865,7 @@
 	qcom,mdss-dsi-display-timings {
 		timing@0 {
 			qcom,mdss-dsi-panel-phy-timings = [00 1c 08 07 23 22
-				07 07 05 03 04 00];
+				07 07 05 02 04 00];
 			qcom,display-topology = <1 0 1>;
 			qcom,default-topology-index = <0>;
 		};
@@ -862,7 +886,7 @@
 	qcom,mdss-dsi-display-timings {
 		timing@0{
 			qcom,mdss-dsi-panel-phy-timings = [00 1f 08 08 24 23 08
-				08 05 03 04 00];
+				08 05 02 04 00];
 			qcom,display-topology = <2 0 2>,
 				<1 0 2>;
 			qcom,default-topology-index = <0>;
@@ -881,14 +905,39 @@
 	qcom,esd-check-enabled;
 	qcom,mdss-dsi-panel-status-check-mode = "reg_read";
 	qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
-	qcom,mdss-dsi-panel-status-command-state = "dsi_lp_mode";
+	qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
 	qcom,mdss-dsi-panel-status-value = <0x9d 0x9d 0x9d 0x9d>;
 	qcom,mdss-dsi-panel-on-check-value = <0x9d 0x9d 0x9d 0x9d>;
 	qcom,mdss-dsi-panel-status-read-length = <4>;
 	qcom,mdss-dsi-display-timings {
 		timing@0 {
 			qcom,mdss-dsi-panel-phy-timings = [00 1f 08 08 24 22 08
-				08 05 03 04 00];
+				08 05 02 04 00];
+			qcom,display-topology = <1 0 1>;
+			qcom,default-topology-index = <0>;
+		};
+	};
+};
+
+&dsi_hx83112a_truly_video {
+	qcom,mdss-dsi-t-clk-post = <0x0E>;
+	qcom,mdss-dsi-t-clk-pre = <0x30>;
+
+	qcom,mdss-dsi-min-refresh-rate = <55>;
+	qcom,mdss-dsi-max-refresh-rate = <60>;
+	qcom,mdss-dsi-pan-enable-dynamic-fps;
+	qcom,esd-check-enabled;
+	qcom,mdss-dsi-panel-status-check-mode = "reg_read";
+	qcom,mdss-dsi-panel-status-command = [06 01 00 01 00 00 01 0a];
+	qcom,mdss-dsi-panel-status-command-state = "dsi_hs_mode";
+	qcom,mdss-dsi-panel-status-value = <0x9d 0x9d 0x9d 0x9d>;
+	qcom,mdss-dsi-panel-on-check-value = <0x9d 0x9d 0x9d 0x9d>;
+	qcom,mdss-dsi-panel-status-read-length = <4>;
+
+	qcom,mdss-dsi-display-timings {
+		timing@0 {
+			qcom,mdss-dsi-panel-phy-timings = [00 1f 08 08 24 22 08
+				08 05 02 04 00];
 			qcom,display-topology = <1 0 1>;
 			qcom,default-topology-index = <0>;
 		};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi
index 4ca4001..fb717f3 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-sde.dtsi
@@ -249,33 +249,13 @@
 
 		/* data and reg bus scale settings */
 		qcom,sde-data-bus {
-			qcom,msm-bus,name = "mdss_sde_mnoc";
+			qcom,msm-bus,name = "mdss_sde";
 			qcom,msm-bus,num-cases = <3>;
 			qcom,msm-bus,num-paths = <2>;
 			qcom,msm-bus,vectors-KBps =
-			    <22 773 0 0>, <23 773 0 0>,
-			    <22 773 0 6400000>, <23 773 0 6400000>,
-			    <22 773 0 6400000>, <23 773 0 6400000>;
-		};
-
-		qcom,sde-llcc-bus {
-			qcom,msm-bus,name = "mdss_sde_llcc";
-			qcom,msm-bus,num-cases = <3>;
-			qcom,msm-bus,num-paths = <1>;
-			qcom,msm-bus,vectors-KBps =
-			    <132 770 0 0>,
-			    <132 770 0 6400000>,
-			    <132 770 0 6400000>;
-		};
-
-		qcom,sde-ebi-bus {
-			qcom,msm-bus,name = "mdss_sde_ebi";
-			qcom,msm-bus,num-cases = <3>;
-			qcom,msm-bus,num-paths = <1>;
-			qcom,msm-bus,vectors-KBps =
-			    <129 512 0 0>,
-			    <129 512 0 6400000>,
-			    <129 512 0 6400000>;
+			    <22 512 0 0>, <23 512 0 0>,
+			    <22 512 0 6400000>, <23 512 0 6400000>,
+			    <22 512 0 6400000>, <23 512 0 6400000>;
 		};
 
 		qcom,sde-reg-bus {
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index c962b42..bb07c04 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -560,7 +560,15 @@
 			alloc-ranges = <0 0x00000000 0 0xffffffff>;
 			reusable;
 			alignment = <0 0x400000>;
-			size = <0 0xc00000>;
+			size = <0 0x800000>;
+		};
+
+		sdsp_mem: sdsp_region {
+			compatible = "shared-dma-pool";
+			alloc-ranges = <0 0x00000000 0 0xffffffff>;
+			reusable;
+			alignment = <0 0x400000>;
+			size = <0 0x400000>;
 		};
 
 		qseecom_ta_mem: qseecom_ta_region {
@@ -2969,6 +2977,7 @@
 };
 
 &gpu_cx_gdsc {
+	parent-supply = <&pm660l_s3_level>;
 	status = "ok";
 };
 
diff --git a/arch/arm64/boot/dts/qcom/sdm710-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-qrd-overlay.dts
index 08c3433..91139ba 100644
--- a/arch/arm64/boot/dts/qcom/sdm710-qrd-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm710-qrd-overlay.dts
@@ -13,6 +13,11 @@
 /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-qrd-sku1.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2-overlay.dts
index 91891ba..526fe6b 100644
--- a/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2-overlay.dts
@@ -13,6 +13,11 @@
 /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-qrd-sku2.dtsi"
 
 / {
diff --git a/arch/arm64/boot/dts/qcom/sdm710-qrd.dts b/arch/arm64/boot/dts/qcom/sdm710-qrd.dts
index 4eb414f..af0c717 100644
--- a/arch/arm64/boot/dts/qcom/sdm710-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sdm710-qrd.dts
@@ -14,8 +14,8 @@
 /dts-v1/;
 
 #include "sdm710.dtsi"
-#include "sdm670-qrd.dtsi"
 #include "sdm670-audio-overlay.dtsi"
+#include "sdm670-qrd.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L QRD";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-670-usb-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-670-usb-common.dtsi
index bf09b67..9b88356 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-670-usb-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-670-usb-common.dtsi
@@ -404,6 +404,7 @@
 			snps,hird-threshold = /bits/ 8 <0x10>;
 			snps,usb3_lpm_capable;
 			usb-core-id = <1>;
+			dr_mode = "host";
 		};
 	};
 
@@ -429,7 +430,8 @@
 			 0x254 /* QUSB2PHY_TEST1 */
 			 0x198 /* PLL_BIAS_CONTROL_2 */
 			 0x228 /* QUSB2PHY_SQ_CTRL1 */
-			 0x22c>; /* QUSB2PHY_SQ_CTRL2 */
+			 0x22c /* QUSB2PHY_SQ_CTRL2 */
+			 0x27c>; /* QUSB2PHY_DEBUG_CTRL1 */
 
 		qcom,qusb-phy-init-seq =
 			/* <value reg_offset> */
diff --git a/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi b/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
index 944c1dd..b5c1ded 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-audio.dtsi
@@ -27,7 +27,9 @@
 		qcom,clk-div = <192>;
 		qcom,clk-mult = <10>;
 	};
+};
 
+&audio_apr {
 	snd_934x: sound-tavil {
 		compatible = "qcom,sdm845-asoc-snd-tavil";
 		qcom,model = "sdm845-tavil-snd-card";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
index 2e2de74..86b1704 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-camera.dtsi
@@ -45,6 +45,7 @@
 			"csiphy0_clk",
 			"csi0phytimer_clk_src",
 			"csi0phytimer_clk";
+		src-clock-name = "csi0phytimer_clk_src";
 		clock-cntl-level = "svs", "turbo";
 		clock-rates =
 			<0 0 0 0 320000000 0 269333333 0>,
@@ -80,6 +81,7 @@
 			"csiphy1_clk",
 			"csi1phytimer_clk_src",
 			"csi1phytimer_clk";
+		src-clock-name = "csi1phytimer_clk_src";
 		clock-cntl-level = "svs", "turbo";
 		clock-rates =
 			<0 0 0 0 320000000 0 269333333 0>,
@@ -116,6 +118,7 @@
 			"csiphy2_clk",
 			"csi2phytimer_clk_src",
 			"csi2phytimer_clk";
+		src-clock-name = "csi2phytimer_clk_src";
 		clock-cntl-level = "svs", "turbo";
 		clock-rates =
 			<0 0 0 0 320000000 0 269333333 0>,
@@ -311,17 +314,17 @@
 				iova-mem-region-io {
 					/* IO region is approximately 3 GB */
 					iova-region-name = "io";
-					iova-region-start = <0xd911000>;
-					iova-region-len = <0xd26ef000>;
+					iova-region-start = <0xda00000>;
+					iova-region-len = <0xd2500000>;
 					iova-region-id = <0x3>;
 					status = "ok";
 				};
 
 				iova-mem-qdss-region {
-					/* qdss region is approximately 64K */
+					/* qdss region is approximately 1MB */
 					iova-region-name = "qdss";
 					iova-region-start = <0xd900000>;
-					iova-region-len = <0x10000>;
+					iova-region-len = <0x100000>;
 					iova-region-id = <0x5>;
 					qdss-phy-addr = <0x16790000>;
 					status = "ok";
@@ -621,6 +624,7 @@
 			<0 0 0 0 0 0 538000000 0 0 0 600000000 0 0>;
 		clock-cntl-level = "svs", "turbo";
 		src-clock-name = "ife_csid_clk_src";
+		clock-control-debugfs = "true";
 		status = "ok";
 	};
 
@@ -659,6 +663,7 @@
 			<0 0 0 0 0 0 600000000 0 0>;
 		clock-cntl-level = "svs", "svs_l1", "turbo";
 		src-clock-name = "ife_clk_src";
+		clock-control-debugfs = "true";
 		clock-names-option =  "ife_dsp_clk";
 		clocks-option = <&clock_camcc CAM_CC_IFE_0_DSP_CLK>;
 		clock-rates-option = <600000000>;
@@ -707,6 +712,7 @@
 			<0 0 0 0 0 0 538000000 0 0 0 600000000 0 0>;
 		clock-cntl-level = "svs", "turbo";
 		src-clock-name = "ife_csid_clk_src";
+		clock-control-debugfs = "true";
 		status = "ok";
 	};
 
@@ -745,6 +751,7 @@
 			<0 0 0 0 0 0 600000000 0 0>;
 		clock-cntl-level = "svs", "svs_l1", "turbo";
 		src-clock-name = "ife_clk_src";
+		clock-control-debugfs = "true";
 		clock-names-option =  "ife_dsp_clk";
 		clocks-option = <&clock_camcc CAM_CC_IFE_1_DSP_CLK>;
 		clock-rates-option = <600000000>;
@@ -790,6 +797,7 @@
 			<0 0 0 0 0 0 538000000 0 0 0 600000000 0>;
 		clock-cntl-level = "svs", "turbo";
 		src-clock-name = "ife_csid_clk_src";
+		clock-control-debugfs = "true";
 		status = "ok";
 	};
 
@@ -825,6 +833,7 @@
 			<0 0 0 0 0 0 600000000 0>;
 		clock-cntl-level = "svs", "svs_l1", "turbo";
 		src-clock-name = "ife_clk_src";
+		clock-control-debugfs = "true";
 		status = "ok";
 	};
 
@@ -881,6 +890,9 @@
 	cam_ipe0: qcom,ipe0 {
 		cell-index = <0>;
 		compatible = "qcom,cam-ipe";
+		reg = <0xac87000 0x3000>;
+		reg-names = "ipe0_top";
+		reg-cam-base = <0x87000>;
 		regulator-names = "ipe0-vdd";
 		ipe0-vdd-supply = <&ipe_0_gdsc>;
 		clock-names = "ipe_0_ahb_clk",
@@ -889,6 +901,7 @@
 			"ipe_0_clk",
 			"ipe_0_clk_src";
 		src-clock-name = "ipe_0_clk_src";
+		clock-control-debugfs = "true";
 		clocks = <&clock_camcc CAM_CC_IPE_0_AHB_CLK>,
 				<&clock_camcc CAM_CC_IPE_0_AREG_CLK>,
 				<&clock_camcc CAM_CC_IPE_0_AXI_CLK>,
@@ -908,6 +921,9 @@
 	cam_ipe1: qcom,ipe1 {
 		cell-index = <1>;
 		compatible = "qcom,cam-ipe";
+		reg = <0xac91000 0x3000>;
+		reg-names = "ipe1_top";
+		reg-cam-base = <0x91000>;
 		regulator-names = "ipe1-vdd";
 		ipe1-vdd-supply = <&ipe_1_gdsc>;
 		clock-names = "ipe_1_ahb_clk",
@@ -916,6 +932,7 @@
 			"ipe_1_clk",
 			"ipe_1_clk_src";
 		src-clock-name = "ipe_1_clk_src";
+		clock-control-debugfs = "true";
 		clocks = <&clock_camcc CAM_CC_IPE_1_AHB_CLK>,
 				<&clock_camcc CAM_CC_IPE_1_AREG_CLK>,
 				<&clock_camcc CAM_CC_IPE_1_AXI_CLK>,
@@ -935,6 +952,9 @@
 	cam_bps: qcom,bps {
 		cell-index = <0>;
 		compatible = "qcom,cam-bps";
+		reg = <0xac6f000 0x3000>;
+		reg-names = "bps_top";
+		reg-cam-base = <0x6f000>;
 		regulator-names = "bps-vdd";
 		bps-vdd-supply = <&bps_gdsc>;
 		clock-names = "bps_ahb_clk",
@@ -943,6 +963,7 @@
 			"bps_clk",
 			"bps_clk_src";
 		src-clock-name = "bps_clk_src";
+		clock-control-debugfs = "true";
 		clocks = <&clock_camcc CAM_CC_BPS_AHB_CLK>,
 				<&clock_camcc CAM_CC_BPS_AREG_CLK>,
 				<&clock_camcc CAM_CC_BPS_AXI_CLK>,
@@ -1065,6 +1086,7 @@
 			<&clock_camcc CAM_CC_FD_CORE_CLK>,
 			<&clock_camcc CAM_CC_FD_CORE_UAR_CLK>;
 		src-clock-name = "fd_core_clk_src";
+		clock-control-debugfs = "true";
 		clock-cntl-level = "svs", "svs_l1", "turbo";
 		clock-rates =
 			<0 0 0 0 0 400000000 0 0>,
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp-audio-overlay.dtsi
index 68f2e51..99798ff 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp-audio-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp-audio-overlay.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,9 +13,7 @@
 
 #include "sdm845-audio-overlay.dtsi"
 
-&soc {
-	sound-tavil {
-		qcom,us-euro-gpios = <&tavil_us_euro_sw>;
-	};
+&snd_934x {
+	qcom,us-euro-gpios = <&tavil_us_euro_sw>;
 };
 
diff --git a/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
index d6be6d4..0a02bfb 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-interposer-pm660.dtsi
@@ -265,6 +265,10 @@
 	/delete-property/ vdd_mx-supply;
 };
 
+&gpu_cx_gdsc {
+	/delete-property/ parent-supply;
+};
+
 &gpu_gx_gdsc {
 	/delete-property/ parent-supply;
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index 812a313..274a862 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -341,22 +341,13 @@
 };
 
 &usb1 {
-	status = "okay";
 	extcon = <&extcon_usb1>;
 };
 
-&qusb_phy1 {
-	status = "okay";
-};
-
 &ext_5v_boost {
 	status = "ok";
 };
 
-&usb_qmp_phy {
-	status = "okay";
-};
-
 &pm8998_vadc {
 	chan@83 {
 		label = "vph_pwr";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi
index 361fa2f..ed75507 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd-audio-overlay.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -13,21 +13,19 @@
 
 #include "sdm845-audio-overlay.dtsi"
 
-&soc {
-	sound-tavil {
-		qcom,model = "sdm845-tavil-qrd-snd-card";
+&snd_934x {
+	qcom,model = "sdm845-tavil-qrd-snd-card";
 
-		qcom,wsa-max-devs = <1>;
-		qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0213>;
-		qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrRight";
+	qcom,wsa-max-devs = <1>;
+	qcom,wsa-devs = <&wsa881x_0211>, <&wsa881x_0213>;
+	qcom,wsa-aux-dev-prefix = "SpkrRight", "SpkrRight";
 
-		qcom,msm-mbhc-usbc-audio-supported = <1>;
+	qcom,msm-mbhc-usbc-audio-supported = <1>;
 
-		qcom,usbc-analog-en2-gpio = <&tlmm 51 0>;
-		pinctrl-names = "aud_active", "aud_sleep";
-		pinctrl-0 = <&wcd_usbc_analog_en2_active>;
-		pinctrl-1 = <&wcd_usbc_analog_en2_idle>;
-	};
+	qcom,usbc-analog-en2-gpio = <&tlmm 51 0>;
+	pinctrl-names = "aud_active", "aud_sleep";
+	pinctrl-0 = <&wcd_usbc_analog_en2_active>;
+	pinctrl-1 = <&wcd_usbc_analog_en2_idle>;
 };
 
 &us_euro_sw_wcd_active {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
index ec8665b..34beda4 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-regulator.dtsi
@@ -142,7 +142,8 @@
 		pm8998_s9_level: regulator-s9-level {
 			regulator-name = "pm8998_s9_level";
 			qcom,set = <RPMH_REGULATOR_SET_ALL>;
-			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-min-microvolt
+				= <RPMH_REGULATOR_LEVEL_RETENTION>;
 			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
 			qcom,min-dropout-voltage-level = <(-1)>;
 		};
@@ -150,7 +151,8 @@
 		pm8998_s9_level_ao: regulator-s9-level-ao {
 			regulator-name = "pm8998_s9_level_ao";
 			qcom,set = <RPMH_REGULATOR_SET_ACTIVE>;
-			regulator-min-microvolt = <RPMH_REGULATOR_LEVEL_OFF>;
+			regulator-min-microvolt
+				= <RPMH_REGULATOR_LEVEL_RETENTION>;
 			regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
 			qcom,min-dropout-voltage-level = <(-1)>;
 		};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi
index 97cb981..c9669d9 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2-camera.dtsi
@@ -248,17 +248,17 @@
 				iova-mem-region-io {
 					/* IO region is approximately 3 GB */
 					iova-region-name = "io";
-					iova-region-start = <0xd911000>;
-					iova-region-len = <0xd26ef000>;
+					iova-region-start = <0xda00000>;
+					iova-region-len = <0xd2500000>;
 					iova-region-id = <0x3>;
 					status = "ok";
 				};
 
 				iova-mem-qdss-region {
-					/* qdss region is approximately 64K */
+					/* qdss region is approximately 1MB */
 					iova-region-name = "qdss";
 					iova-region-start = <0xd900000>;
-					iova-region-len = <0x10000>;
+					iova-region-len = <0x100000>;
 					iova-region-id = <0x5>;
 					qdss-phy-addr = <0x16790000>;
 					status = "ok";
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 26b0385..4efab0b 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -1550,6 +1550,7 @@
 		qcom,firmware-name = "modem";
 		qcom,pil-self-auth;
 		qcom,sysmon-id = <0>;
+		qcom,minidump-id = <3>;
 		qcom,ssctl-instance-id = <0x12>;
 		qcom,override-acc;
 		qcom,signal-aop;
@@ -2375,6 +2376,7 @@
 		qcom,xprt-version = <1>;
 		qcom,fragmented-data;
 		qcom,dynamic-wakeup-source;
+		qcom,low-latency-xprt;
 	};
 
 	qcom,ipc_router_cdsp_xprt {
@@ -4057,9 +4059,12 @@
 
 &mdss_core_gdsc {
 	status = "ok";
+	qcom,en-few-wait-val = <6>;
+	qcom,en-rest-wait-val = <5>;
 };
 
 &gpu_cx_gdsc {
+	parent-supply = <&pm8998_s9_level>;
 	status = "ok";
 };
 
diff --git a/arch/arm64/boot/dts/qcom/apq8009w-bg-alpha.dts b/arch/arm64/boot/dts/qcom/sdw3100-apq8009w-alpha.dts
similarity index 98%
rename from arch/arm64/boot/dts/qcom/apq8009w-bg-alpha.dts
rename to arch/arm64/boot/dts/qcom/sdw3100-apq8009w-alpha.dts
index 20878c0..be8416f 100644
--- a/arch/arm64/boot/dts/qcom/apq8009w-bg-alpha.dts
+++ b/arch/arm64/boot/dts/qcom/sdw3100-apq8009w-alpha.dts
@@ -20,7 +20,7 @@
 #include "msm8909-audio-bg_codec.dtsi"
 
 / {
-	model = "Qualcomm Technologies, Inc. APQ8009W-PM660 BG Alpha";
+	model = "Qualcomm Technologies, Inc. APQ8009W-PM660 BG Alpha SDW3100";
 	compatible = "qcom,apq8009-mtp", "qcom,apq8009", "qcom,mtp";
 	qcom,msm-id =   <265 0>,
 			<301 0>;
diff --git a/arch/arm64/boot/dts/qcom/apq8009w-bg-wtp-v2.dts b/arch/arm64/boot/dts/qcom/sdw3100-apq8009w-wtp.dts
similarity index 98%
rename from arch/arm64/boot/dts/qcom/apq8009w-bg-wtp-v2.dts
rename to arch/arm64/boot/dts/qcom/sdw3100-apq8009w-wtp.dts
index e7af39f..2b3fd84 100644
--- a/arch/arm64/boot/dts/qcom/apq8009w-bg-wtp-v2.dts
+++ b/arch/arm64/boot/dts/qcom/sdw3100-apq8009w-wtp.dts
@@ -20,7 +20,7 @@
 #include "msm8909-audio-bg_codec.dtsi"
 
 / {
-	model = "Qualcomm Technologies, Inc. APQ8009W-PM660 BLACKGHOST WTP";
+	model = "Qualcomm Technologies, Inc. APQ8009W-PM660 BG WTP SDW3100";
 	compatible = "qcom,apq8009-mtp", "qcom,apq8009", "qcom,mtp";
 	qcom,msm-id =   <265 0>,
 			<301 0>;
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts b/arch/arm64/boot/dts/qcom/sdw3100-msm8909w-1gb-wtp.dts
similarity index 96%
copy from arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
copy to arch/arm64/boot/dts/qcom/sdw3100-msm8909w-1gb-wtp.dts
index 255c146..e3bdfd9 100644
--- a/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
+++ b/arch/arm64/boot/dts/qcom/sdw3100-msm8909w-1gb-wtp.dts
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 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,13 +21,13 @@
 #include "msm8909-audio-bg_codec.dtsi"
 
 / {
-	model = "Qualcomm Technologies, Inc. MSM8909W-PM660 BLACKGHOST WTP";
+	model = "Qualcomm Technologies, Inc. MSM8909W BG 1GB WTP SDW3100";
 	compatible = "qcom,msm8909-mtp", "qcom,msm8909", "qcom,mtp";
 	qcom,msm-id =   <245 0>,
 			<258 0>,
 			<275 0>,
 			<300 0>;
-	qcom,board-id = <8 0x10f>;
+	qcom,board-id = <8 0xf>;
 	qcom,pmic-id =  <0x0001001b 0x0 0x0 0x0>,
 			<0x0001011b 0x0 0x0 0x0>;
 };
@@ -73,6 +73,7 @@
 
 	qcom,blackghost {
 		compatible = "qcom,pil-blackghost";
+
 		qcom,pil-force-shutdown;
 		qcom,firmware-name = "bg-wear";
 		/* GPIO inputs from blackghost */
@@ -220,9 +221,8 @@
 		interrupts = <50 0>;
 		interrupt-names = "nfc_irq";
 		pinctrl-names = "nfc_active","nfc_suspend";
-		pinctrl-0 = <&nfcw_int_active
-			     &nfcw_disable_active
-			     &nfc_clk_default>;
+		pinctrl-0 = <&nfcw_int_active &nfcw_disable_active
+						&nfc_clk_default>;
 		pinctrl-1 = <&nfcw_int_suspend &nfcw_disable_suspend>;
 		clocks = <&clock_rpm clk_bb_clk3_pin>;
 		clock-names = "ref_clk";
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts b/arch/arm64/boot/dts/qcom/sdw3100-msm8909w-wtp.dts
similarity index 98%
rename from arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
rename to arch/arm64/boot/dts/qcom/sdw3100-msm8909w-wtp.dts
index 255c146..89f0bb8 100644
--- a/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
+++ b/arch/arm64/boot/dts/qcom/sdw3100-msm8909w-wtp.dts
@@ -21,7 +21,7 @@
 #include "msm8909-audio-bg_codec.dtsi"
 
 / {
-	model = "Qualcomm Technologies, Inc. MSM8909W-PM660 BLACKGHOST WTP";
+	model = "Qualcomm Technologies, Inc. MSM8909W-PM660 BG WTP SDW3100";
 	compatible = "qcom,msm8909-mtp", "qcom,msm8909", "qcom,mtp";
 	qcom,msm-id =   <245 0>,
 			<258 0>,
diff --git a/arch/arm64/configs/msm8937-perf_defconfig b/arch/arm64/configs/msm8937-perf_defconfig
index 3f161f4..6420837 100644
--- a/arch/arm64/configs/msm8937-perf_defconfig
+++ b/arch/arm64/configs/msm8937-perf_defconfig
@@ -340,7 +340,6 @@
 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
@@ -379,10 +378,7 @@
 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
@@ -395,9 +391,7 @@
 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
@@ -549,6 +543,7 @@
 CONFIG_QCOM_SCM=y
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QPNP_PBS=y
 CONFIG_QCOM_MEMORY_DUMP_V2=y
 CONFIG_MSM_RPM_SMD=y
 CONFIG_QCOM_BUS_SCALING=y
@@ -566,7 +561,6 @@
 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
@@ -594,10 +588,15 @@
 CONFIG_QTI_MPM=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_NVMEM=y
+CONFIG_NVMEM_SPMI_SDAM=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
 CONFIG_F2FS_FS=y
 CONFIG_F2FS_FS_SECURITY=y
 CONFIG_QUOTA=y
@@ -629,12 +628,13 @@
 CONFIG_CORESIGHT_CTI=y
 CONFIG_CORESIGHT_EVENT=y
 CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=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_GCM=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/msm8937_defconfig b/arch/arm64/configs/msm8937_defconfig
index 25ad0bc..4040863 100644
--- a/arch/arm64/configs/msm8937_defconfig
+++ b/arch/arm64/configs/msm8937_defconfig
@@ -348,7 +348,6 @@
 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
@@ -387,10 +386,7 @@
 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
@@ -563,8 +559,8 @@
 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_QPNP_PBS=y
 CONFIG_QCOM_MEMORY_DUMP_V2=y
 CONFIG_MSM_DEBUG_LAR_UNLOCK=y
 CONFIG_MSM_RPM_SMD=y
@@ -584,7 +580,6 @@
 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
@@ -612,10 +607,15 @@
 CONFIG_QTI_MPM=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_NVMEM=y
+CONFIG_NVMEM_SPMI_SDAM=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
 CONFIG_F2FS_FS=y
 CONFIG_F2FS_FS_SECURITY=y
 CONFIG_QUOTA=y
@@ -646,7 +646,6 @@
 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
@@ -695,12 +694,13 @@
 CONFIG_CORESIGHT_CTI=y
 CONFIG_CORESIGHT_EVENT=y
 CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=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_GCM=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index 9ac93aa..8004333 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -556,6 +556,7 @@
 CONFIG_QCOM_SCM=y
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QPNP_PBS=y
 CONFIG_QCOM_MEMORY_DUMP_V2=y
 CONFIG_MSM_RPM_SMD=y
 CONFIG_QCOM_BUS_SCALING=y
@@ -600,10 +601,17 @@
 CONFIG_QTI_MPM=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_NVMEM=y
+CONFIG_NVMEM_SPMI_SDAM=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V2=y
@@ -633,12 +641,13 @@
 CONFIG_CORESIGHT_CTI=y
 CONFIG_CORESIGHT_EVENT=y
 CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=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_GCM=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index 63dce91..c869190 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -571,8 +571,8 @@
 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_QPNP_PBS=y
 CONFIG_QCOM_MEMORY_DUMP_V2=y
 CONFIG_MSM_DEBUG_LAR_UNLOCK=y
 CONFIG_MSM_RPM_SMD=y
@@ -620,10 +620,17 @@
 CONFIG_QTI_MPM=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_NVMEM=y
+CONFIG_NVMEM_SPMI_SDAM=y
 CONFIG_SENSORS_SSC=y
 CONFIG_MSM_TZ_LOG=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V2=y
@@ -701,12 +708,13 @@
 CONFIG_CORESIGHT_CTI=y
 CONFIG_CORESIGHT_EVENT=y
 CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=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_GCM=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index 956bcc5..ac21b63 100644
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -513,6 +513,7 @@
 CONFIG_QCOM_RUN_QUEUE_STATS=y
 CONFIG_QCOM_LLCC=y
 CONFIG_QCOM_SDM670_LLCC=y
+CONFIG_QCOM_QCS605_LLCC=y
 CONFIG_QCOM_LLCC_PERFMON=m
 CONFIG_MSM_SERVICE_LOCATOR=y
 CONFIG_MSM_SERVICE_NOTIFIER=y
@@ -579,11 +580,14 @@
 CONFIG_QCOM_QFPROM=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_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_FS_ENCRYPTION=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V2=y
@@ -615,12 +619,14 @@
 CONFIG_CORESIGHT_EVENT=y
 CONFIG_CORESIGHT_HWEVENT=y
 CONFIG_CORESIGHT_DUMMY=y
+CONFIG_PFK=y
 CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY=y
 CONFIG_HARDENED_USERCOPY=y
 CONFIG_FORTIFY_SOURCE=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_GCM=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index f6895a5..9a6da1f 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -313,6 +313,8 @@
 CONFIG_INPUT_UINPUT=y
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_MSM_GENI=y
 CONFIG_SERIAL_MSM_GENI_CONSOLE=y
 CONFIG_DIAG_CHAR=y
@@ -525,6 +527,7 @@
 CONFIG_QCOM_RUN_QUEUE_STATS=y
 CONFIG_QCOM_LLCC=y
 CONFIG_QCOM_SDM670_LLCC=y
+CONFIG_QCOM_QCS605_LLCC=y
 CONFIG_QCOM_LLCC_PERFMON=m
 CONFIG_MSM_SERVICE_LOCATOR=y
 CONFIG_MSM_SERVICE_NOTIFIER=y
@@ -597,11 +600,14 @@
 CONFIG_QCOM_QFPROM=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_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_F2FS_FS=y
+CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_FS_ENCRYPTION=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V2=y
@@ -675,12 +681,14 @@
 CONFIG_CORESIGHT_TGU=y
 CONFIG_CORESIGHT_HWEVENT=y
 CONFIG_CORESIGHT_DUMMY=y
+CONFIG_PFK=y
 CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
 CONFIG_SECURITY=y
 CONFIG_HARDENED_USERCOPY=y
 CONFIG_FORTIFY_SOURCE=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_GCM=y
 CONFIG_CRYPTO_XCBC=y
 CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index e35e571..0c54182 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -520,6 +520,7 @@
 CONFIG_QCOM_EUD=y
 CONFIG_QCOM_WATCHDOG_V2=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
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 28196b1..fd38814 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -27,6 +27,7 @@
 generic-y += poll.h
 generic-y += preempt.h
 generic-y += resource.h
+generic-y += qrwlock.h
 generic-y += rwsem.h
 generic-y += segment.h
 generic-y += sembuf.h
diff --git a/arch/arm64/include/asm/spinlock.h b/arch/arm64/include/asm/spinlock.h
index b15a5ab..53c0f54 100644
--- a/arch/arm64/include/asm/spinlock.h
+++ b/arch/arm64/include/asm/spinlock.h
@@ -186,169 +186,7 @@
 }
 #define arch_spin_is_contended	arch_spin_is_contended
 
-/*
- * Write lock implementation.
- *
- * Write locks set bit 31. Unlocking, is done by writing 0 since the lock is
- * exclusively held.
- *
- * The memory barriers are implicit with the load-acquire and store-release
- * instructions.
- */
-
-static inline void arch_write_lock(arch_rwlock_t *rw)
-{
-	unsigned int tmp;
-
-	asm volatile(ARM64_LSE_ATOMIC_INSN(
-	/* LL/SC */
-	"	sevl\n"
-	"1:	wfe\n"
-	"2:	ldaxr	%w0, %1\n"
-	"	cbnz	%w0, 1b\n"
-	"	stxr	%w0, %w2, %1\n"
-	"	cbnz	%w0, 2b\n"
-	__nops(1),
-	/* LSE atomics */
-	"1:	mov	%w0, wzr\n"
-	"2:	casa	%w0, %w2, %1\n"
-	"	cbz	%w0, 3f\n"
-	"	ldxr	%w0, %1\n"
-	"	cbz	%w0, 2b\n"
-	"	wfe\n"
-	"	b	1b\n"
-	"3:")
-	: "=&r" (tmp), "+Q" (rw->lock)
-	: "r" (0x80000000)
-	: "memory");
-}
-
-static inline int arch_write_trylock(arch_rwlock_t *rw)
-{
-	unsigned int tmp;
-
-	asm volatile(ARM64_LSE_ATOMIC_INSN(
-	/* LL/SC */
-	"1:	ldaxr	%w0, %1\n"
-	"	cbnz	%w0, 2f\n"
-	"	stxr	%w0, %w2, %1\n"
-	"	cbnz	%w0, 1b\n"
-	"2:",
-	/* LSE atomics */
-	"	mov	%w0, wzr\n"
-	"	casa	%w0, %w2, %1\n"
-	__nops(2))
-	: "=&r" (tmp), "+Q" (rw->lock)
-	: "r" (0x80000000)
-	: "memory");
-
-	return !tmp;
-}
-
-static inline void arch_write_unlock(arch_rwlock_t *rw)
-{
-	asm volatile(ARM64_LSE_ATOMIC_INSN(
-	"	stlr	wzr, %0",
-	"	swpl	wzr, wzr, %0")
-	: "=Q" (rw->lock) :: "memory");
-}
-
-/* write_can_lock - would write_trylock() succeed? */
-#define arch_write_can_lock(x)		((x)->lock == 0)
-
-/*
- * Read lock implementation.
- *
- * It exclusively loads the lock value, increments it and stores the new value
- * back if positive and the CPU still exclusively owns the location. If the
- * value is negative, the lock is already held.
- *
- * During unlocking there may be multiple active read locks but no write lock.
- *
- * The memory barriers are implicit with the load-acquire and store-release
- * instructions.
- *
- * Note that in UNDEFINED cases, such as unlocking a lock twice, the LL/SC
- * and LSE implementations may exhibit different behaviour (although this
- * will have no effect on lockdep).
- */
-static inline void arch_read_lock(arch_rwlock_t *rw)
-{
-	unsigned int tmp, tmp2;
-
-	asm volatile(
-	"	sevl\n"
-	ARM64_LSE_ATOMIC_INSN(
-	/* LL/SC */
-	"1:	wfe\n"
-	"2:	ldaxr	%w0, %2\n"
-	"	add	%w0, %w0, #1\n"
-	"	tbnz	%w0, #31, 1b\n"
-	"	stxr	%w1, %w0, %2\n"
-	"	cbnz	%w1, 2b\n"
-	__nops(1),
-	/* LSE atomics */
-	"1:	wfe\n"
-	"2:	ldxr	%w0, %2\n"
-	"	adds	%w1, %w0, #1\n"
-	"	tbnz	%w1, #31, 1b\n"
-	"	casa	%w0, %w1, %2\n"
-	"	sbc	%w0, %w1, %w0\n"
-	"	cbnz	%w0, 2b")
-	: "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
-	:
-	: "cc", "memory");
-}
-
-static inline void arch_read_unlock(arch_rwlock_t *rw)
-{
-	unsigned int tmp, tmp2;
-
-	asm volatile(ARM64_LSE_ATOMIC_INSN(
-	/* LL/SC */
-	"1:	ldxr	%w0, %2\n"
-	"	sub	%w0, %w0, #1\n"
-	"	stlxr	%w1, %w0, %2\n"
-	"	cbnz	%w1, 1b",
-	/* LSE atomics */
-	"	movn	%w0, #0\n"
-	"	staddl	%w0, %2\n"
-	__nops(2))
-	: "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
-	:
-	: "memory");
-}
-
-static inline int arch_read_trylock(arch_rwlock_t *rw)
-{
-	unsigned int tmp, tmp2;
-
-	asm volatile(ARM64_LSE_ATOMIC_INSN(
-	/* LL/SC */
-	"	mov	%w1, #1\n"
-	"1:	ldaxr	%w0, %2\n"
-	"	add	%w0, %w0, #1\n"
-	"	tbnz	%w0, #31, 2f\n"
-	"	stxr	%w1, %w0, %2\n"
-	"	cbnz	%w1, 1b\n"
-	"2:",
-	/* LSE atomics */
-	"	ldr	%w0, %2\n"
-	"	adds	%w1, %w0, #1\n"
-	"	tbnz	%w1, #31, 1f\n"
-	"	casa	%w0, %w1, %2\n"
-	"	sbc	%w1, %w1, %w0\n"
-	__nops(1)
-	"1:")
-	: "=&r" (tmp), "=&r" (tmp2), "+Q" (rw->lock)
-	:
-	: "cc", "memory");
-
-	return !tmp2;
-}
-
-/* read_can_lock - would read_trylock() succeed? */
-#define arch_read_can_lock(x)		((x)->lock < 0x80000000)
+#include <asm/qrwlock.h>
 
 #define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
 #define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
diff --git a/arch/arm64/include/asm/spinlock_types.h b/arch/arm64/include/asm/spinlock_types.h
index 55be59a..6b85601 100644
--- a/arch/arm64/include/asm/spinlock_types.h
+++ b/arch/arm64/include/asm/spinlock_types.h
@@ -36,10 +36,6 @@
 
 #define __ARCH_SPIN_LOCK_UNLOCKED	{ 0 , 0 }
 
-typedef struct {
-	volatile unsigned int lock;
-} arch_rwlock_t;
-
-#define __ARCH_RW_LOCK_UNLOCKED		{ 0 }
+#include <asm-generic/qrwlock_types.h>
 
 #endif
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 6befc9c..c1d02d1 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -253,14 +253,12 @@
 #define VM_FAULT_BADMAP		0x010000
 #define VM_FAULT_BADACCESS	0x020000
 
-static int __do_page_fault(struct mm_struct *mm, unsigned long addr,
+static int __do_page_fault(struct vm_area_struct *vma, unsigned long addr,
 			   unsigned int mm_flags, unsigned long vm_flags,
 			   struct task_struct *tsk)
 {
-	struct vm_area_struct *vma;
 	int fault;
 
-	vma = find_vma(mm, addr);
 	fault = VM_FAULT_BADMAP;
 	if (unlikely(!vma))
 		goto out;
@@ -318,6 +316,7 @@
 	int fault, sig, code;
 	unsigned long vm_flags = VM_READ | VM_WRITE;
 	unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
+	struct vm_area_struct *vma = NULL;
 
 	if (notify_page_fault(regs, esr))
 		return 0;
@@ -356,6 +355,14 @@
 	}
 
 	/*
+	 * let's try a speculative page fault without grabbing the
+	 * mmap_sem.
+	 */
+	fault = handle_speculative_fault(mm, addr, mm_flags, &vma);
+	if (fault != VM_FAULT_RETRY)
+		goto done;
+
+	/*
 	 * As per x86, we may deadlock here. However, since the kernel only
 	 * validly references user space from well defined areas of the code,
 	 * we can bug out early if this is from code which shouldn't.
@@ -377,19 +384,44 @@
 #endif
 	}
 
-	fault = __do_page_fault(mm, addr, mm_flags, vm_flags, tsk);
+	if (!vma || !can_reuse_spf_vma(vma, addr))
+		vma = find_vma(mm, addr);
 
-	/*
-	 * If we need to retry but a fatal signal is pending, handle the
-	 * signal first. We do not need to release the mmap_sem because it
-	 * would already be released in __lock_page_or_retry in mm/filemap.c.
-	 */
-	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) {
-		if (!user_mode(regs))
-			goto no_context;
-		return 0;
+	fault = __do_page_fault(vma, addr, mm_flags, vm_flags, tsk);
+	if (fault & VM_FAULT_RETRY) {
+		/*
+		 * If we need to retry but a fatal signal is pending, handle the
+		 * signal first. We do not need to release the mmap_sem because
+		 * it would already be released in __lock_page_or_retry in
+		 * mm/filemap.c.
+		 */
+
+		if (fatal_signal_pending(current)) {
+			if (!user_mode(regs))
+				goto no_context;
+			return 0;
+		}
+
+		/*
+		 * Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk of
+		 * starvation.
+		 */
+		if (mm_flags & FAULT_FLAG_ALLOW_RETRY) {
+			mm_flags &= ~FAULT_FLAG_ALLOW_RETRY;
+			mm_flags |= FAULT_FLAG_TRIED;
+
+			/*
+			 * Do not try to reuse this vma and fetch it
+			 * again since we will release the mmap_sem.
+			 */
+			vma = NULL;
+			goto retry;
+		}
 	}
 
+	up_read(&mm->mmap_sem);
+done:
+
 	/*
 	 * Major/minor page fault accounting is only done on the initial
 	 * attempt. If we go through a retry, it is extremely likely that the
@@ -407,19 +439,8 @@
 			perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs,
 				      addr);
 		}
-		if (fault & VM_FAULT_RETRY) {
-			/*
-			 * Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk of
-			 * starvation.
-			 */
-			mm_flags &= ~FAULT_FLAG_ALLOW_RETRY;
-			mm_flags |= FAULT_FLAG_TRIED;
-			goto retry;
-		}
 	}
 
-	up_read(&mm->mmap_sem);
-
 	/*
 	 * Handle the "normal" case first - VM_FAULT_MAJOR
 	 */
diff --git a/arch/arm64/mm/ioremap.c b/arch/arm64/mm/ioremap.c
index 01e88c8..8e2c1d6 100644
--- a/arch/arm64/mm/ioremap.c
+++ b/arch/arm64/mm/ioremap.c
@@ -64,6 +64,11 @@
 	addr = (unsigned long)area->addr;
 	area->phys_addr = phys_addr;
 
+#ifdef CONFIG_ARCH_MSM8953_SOC_SETTINGS
+	if (phys_addr >= MSM8953_TLMM_START_ADDR &&
+	    phys_addr <= MSM8953_TLMM_END_ADDR)
+		prot = __pgprot(PROT_DEVICE_nGnRnE);
+#endif
 	err = ioremap_page_range(addr, addr + size, phys_addr, prot);
 	if (err) {
 		vunmap((void *)addr);
diff --git a/drivers/bluetooth/bluetooth-power.c b/drivers/bluetooth/bluetooth-power.c
index 7f7c942..0574e44 100644
--- a/drivers/bluetooth/bluetooth-power.c
+++ b/drivers/bluetooth/bluetooth-power.c
@@ -666,7 +666,7 @@
 
 	bluetooth_power_rfkill_remove(pdev);
 
-	if (bt_power_pdata->bt_chip_pwd->reg)
+	if (bt_power_pdata->bt_chip_pwd)
 		regulator_put(bt_power_pdata->bt_chip_pwd->reg);
 
 	kfree(bt_power_pdata);
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index d52c80c..c3d7c68 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1179,8 +1179,6 @@
 	hlist_del_init(&ctx->hn);
 	hlist_add_head(&ctx->hn, &clst->interrupted);
 	spin_unlock(&ctx->fl->hlock);
-	/* free the cache on power collapse */
-	fastrpc_buf_list_free(ctx->fl);
 }
 
 static void context_free(struct smq_invoke_ctx *ctx)
@@ -2489,6 +2487,31 @@
 
 static void fastrpc_mmap_add(struct fastrpc_mmap *map);
 
+static inline void get_fastrpc_ioctl_mmap_64(
+			struct fastrpc_ioctl_mmap_64 *mmap64,
+			struct fastrpc_ioctl_mmap *immap)
+{
+	immap->fd = mmap64->fd;
+	immap->flags = mmap64->flags;
+	immap->vaddrin = (uintptr_t)mmap64->vaddrin;
+	immap->size = mmap64->size;
+}
+
+static inline void put_fastrpc_ioctl_mmap_64(
+			struct fastrpc_ioctl_mmap_64 *mmap64,
+			struct fastrpc_ioctl_mmap *immap)
+{
+	mmap64->vaddrout = (uint64_t)immap->vaddrout;
+}
+
+static inline void get_fastrpc_ioctl_munmap_64(
+			struct fastrpc_ioctl_munmap_64 *munmap64,
+			struct fastrpc_ioctl_munmap *imunmap)
+{
+	imunmap->vaddrout = (uintptr_t)munmap64->vaddrout;
+	imunmap->size = munmap64->size;
+}
+
 static int fastrpc_internal_munmap(struct fastrpc_file *fl,
 				   struct fastrpc_ioctl_munmap *ud)
 {
@@ -3211,12 +3234,18 @@
 	union {
 		struct fastrpc_ioctl_invoke_crc inv;
 		struct fastrpc_ioctl_mmap mmap;
+		struct fastrpc_ioctl_mmap_64 mmap64;
 		struct fastrpc_ioctl_munmap munmap;
+		struct fastrpc_ioctl_munmap_64 munmap64;
 		struct fastrpc_ioctl_munmap_fd munmap_fd;
 		struct fastrpc_ioctl_init_attrs init;
 		struct fastrpc_ioctl_perf perf;
 		struct fastrpc_ioctl_control cp;
 	} p;
+	union {
+		struct fastrpc_ioctl_mmap mmap;
+		struct fastrpc_ioctl_munmap munmap;
+	} i;
 	void *param = (char *)ioctl_param;
 	struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data;
 	int size = 0, err = 0;
@@ -3280,24 +3309,27 @@
 			goto bail;
 		break;
 	case FASTRPC_IOCTL_MMAP_64:
-		K_COPY_FROM_USER(err, 0, &p.mmap, param,
-						sizeof(p.mmap));
+		K_COPY_FROM_USER(err, 0, &p.mmap64, param,
+						sizeof(p.mmap64));
 		if (err)
 			goto bail;
-		VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &p.mmap)));
+		get_fastrpc_ioctl_mmap_64(&p.mmap64, &i.mmap);
+		VERIFY(err, 0 == (err = fastrpc_internal_mmap(fl, &i.mmap)));
 		if (err)
 			goto bail;
-		K_COPY_TO_USER(err, 0, param, &p.mmap, sizeof(p.mmap));
+		put_fastrpc_ioctl_mmap_64(&p.mmap64, &i.mmap);
+		K_COPY_TO_USER(err, 0, param, &p.mmap64, sizeof(p.mmap64));
 		if (err)
 			goto bail;
 		break;
 	case FASTRPC_IOCTL_MUNMAP_64:
-		K_COPY_FROM_USER(err, 0, &p.munmap, param,
-						sizeof(p.munmap));
+		K_COPY_FROM_USER(err, 0, &p.munmap64, param,
+						sizeof(p.munmap64));
 		if (err)
 			goto bail;
+		get_fastrpc_ioctl_munmap_64(&p.munmap64, &i.munmap);
 		VERIFY(err, 0 == (err = fastrpc_internal_munmap(fl,
-							&p.munmap)));
+							&i.munmap)));
 		if (err)
 			goto bail;
 		break;
@@ -3514,8 +3546,16 @@
 				pdr->domain_list[i].name,
 				pdr->domain_list[i].instance_id,
 				&spd->pdrnb, &curr_state);
-			if (IS_ERR(spd->pdrhandle))
+			if (IS_ERR(spd->pdrhandle)) {
 				pr_err("ADSPRPC: Unable to register notifier\n");
+			} else if (curr_state ==
+				SERVREG_NOTIF_SERVICE_STATE_UP_V01) {
+				pr_info("ADSPRPC: STATE_UP_V01 received\n");
+				spd->ispdup = 1;
+			} else if (curr_state ==
+				SERVREG_NOTIF_SERVICE_STATE_UNINIT_V01) {
+				pr_info("ADSPRPC: STATE_UNINIT_V01 received\n");
+			}
 			break;
 		}
 	}
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index a7f29e6..acee74a 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.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
@@ -797,6 +797,7 @@
 	return ret;
 }
 
+#ifdef CONFIG_IPC_LOGGING
 static ssize_t diag_dbgfs_write_debug(struct file *fp, const char __user *buf,
 				      size_t count, loff_t *ppos)
 {
@@ -827,6 +828,7 @@
 	diag_debug_mask = (uint16_t)value;
 	return count;
 }
+#endif
 
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
 #ifdef CONFIG_USB_QCOM_DIAG_BRIDGE
@@ -1086,9 +1088,11 @@
 	.read = diag_dbgfs_read_power,
 };
 
+#ifdef CONFIG_IPC_LOGGING
 const struct file_operations diag_dbgfs_debug_ops = {
 	.write = diag_dbgfs_write_debug
 };
+#endif
 
 int diag_debugfs_init(void)
 {
@@ -1145,11 +1149,12 @@
 	if (!entry)
 		goto err;
 
+#ifdef CONFIG_IPC_LOGGING
 	entry = debugfs_create_file("debug", 0444, diag_dbgfs_dent, 0,
 				    &diag_dbgfs_debug_ops);
 	if (!entry)
 		goto err;
-
+#endif
 #ifdef CONFIG_DIAGFWD_BRIDGE_CODE
 	entry = debugfs_create_file("bridge", 0444, diag_dbgfs_dent, 0,
 				    &diag_dbgfs_bridge_ops);
diff --git a/drivers/char/diag/diag_ipc_logging.h b/drivers/char/diag/diag_ipc_logging.h
index 4b8dd1b..839c8ca 100644
--- a/drivers/char/diag/diag_ipc_logging.h
+++ b/drivers/char/diag/diag_ipc_logging.h
@@ -26,9 +26,7 @@
 #define DIAG_DEBUG_BRIDGE	0x0040
 #define DIAG_DEBUG_CONTROL	0x0080
 
-#define DIAG_DEBUG
-
-#ifdef DIAG_DEBUG
+#ifdef CONFIG_IPC_LOGGING
 extern uint16_t diag_debug_mask;
 extern void *diag_ipc_log;
 
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index c20dd2e..44cf56c 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -195,10 +195,11 @@
 			}
 			mask_info->update_buf = temp;
 			mask_info->update_buf_len = header_len + mask_size;
+			buf = temp;
 		}
 
 		memcpy(buf, &ctrl_pkt, header_len);
-		if (mask_size > 0)
+		if (mask_size > 0 && mask_size <= LOG_MASK_SIZE)
 			memcpy(buf + header_len, mask->ptr, mask_size);
 		mutex_unlock(&mask->lock);
 
@@ -297,9 +298,16 @@
 			} else {
 				mask_info->update_buf = temp;
 				mask_info->update_buf_len = temp_len;
+				buf = temp;
 			}
 		}
-		memcpy(buf + sizeof(header), mask_info->ptr, num_bytes);
+		if (num_bytes > 0 && num_bytes < mask_info->mask_len)
+			memcpy(buf + sizeof(header), mask_info->ptr, num_bytes);
+		else {
+			pr_err("diag: num_bytes(%d) is not satisfying length condition\n",
+				num_bytes);
+			goto err;
+		}
 		write_len += num_bytes;
 		break;
 	default:
@@ -415,6 +423,7 @@
 			} else {
 				mask_info->update_buf = temp;
 				mask_info->update_buf_len = temp_len;
+				buf = temp;
 				pr_debug("diag: In %s, successfully reallocated msg_mask update buffer to len: %d\n",
 					 __func__, mask_info->update_buf_len);
 			}
@@ -922,10 +931,12 @@
 	mask_info->status = (req->rt_mask) ? DIAG_CTRL_MASK_ALL_ENABLED :
 					   DIAG_CTRL_MASK_ALL_DISABLED;
 	for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
-		mutex_lock(&mask->lock);
-		memset(mask->ptr, req->rt_mask,
-		       mask->range * sizeof(uint32_t));
-		mutex_unlock(&mask->lock);
+		if (mask && mask->ptr) {
+			mutex_lock(&mask->lock);
+			memset(mask->ptr, req->rt_mask,
+			       mask->range * sizeof(uint32_t));
+			mutex_unlock(&mask->lock);
+		}
 	}
 	mutex_unlock(&driver->msg_mask_lock);
 	mutex_unlock(&mask_info->lock);
@@ -1337,6 +1348,8 @@
 
 	mutex_lock(&mask_info->lock);
 	for (i = 0; i < MAX_EQUIP_ID && !status; i++, mask++) {
+		if (!mask || !mask->ptr)
+			continue;
 		if (mask->equip_id != req->equip_id)
 			continue;
 		mutex_lock(&mask->lock);
@@ -1464,9 +1477,11 @@
 		return -EINVAL;
 	}
 	for (i = 0; i < MAX_EQUIP_ID; i++, mask++) {
-		mutex_lock(&mask->lock);
-		memset(mask->ptr, 0, mask->range);
-		mutex_unlock(&mask->lock);
+		if (mask && mask->ptr) {
+			mutex_lock(&mask->lock);
+			memset(mask->ptr, 0, mask->range);
+			mutex_unlock(&mask->lock);
+		}
 	}
 	mask_info->status = DIAG_CTRL_MASK_ALL_DISABLED;
 	mutex_unlock(&driver->md_session_lock);
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index a169230..8b089eb 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -162,7 +162,7 @@
 
 #define DIAGPKT_MAX_DELAYED_RSP 0xFFFF
 
-#ifdef DIAG_DEBUG
+#ifdef CONFIG_IPC_LOGGING
 uint16_t diag_debug_mask;
 void *diag_ipc_log;
 #endif
@@ -3804,7 +3804,7 @@
 		pm_relax(driver->diag_dev);
 }
 
-#ifdef DIAG_DEBUG
+#ifdef CONFIG_IPC_LOGGING
 static void diag_debug_init(void)
 {
 	diag_ipc_log = ipc_log_context_create(DIAG_IPC_LOG_PAGES, "diag", 0);
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 6f81bfd..ac4394b 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -528,9 +528,8 @@
 	header = (struct diag_ctrl_last_event_report *)ptr;
 	event_size = ((header->event_last_id / 8) + 1);
 	if (event_size >= driver->event_mask_size) {
-		DIAG_LOG(DIAG_DEBUG_CONTROL,
-			"diag: In %s, receiving event mask size more that Apps can handle\n",
-			 __func__);
+		DIAG_LOG(DIAG_DEBUG_MASKS,
+		"diag: receiving event mask size more that Apps can handle\n");
 		temp = krealloc(driver->event_mask->ptr, event_size,
 				GFP_KERNEL);
 		if (!temp) {
@@ -669,6 +668,10 @@
 		mask_ptr = (struct diag_msg_mask_t *)msg_mask.ptr;
 		found = 0;
 		for (j = 0; j < driver->msg_mask_tbl_count; j++, mask_ptr++) {
+			if (!mask_ptr || !ssid_range) {
+				found = 1;
+				break;
+			}
 			if (mask_ptr->ssid_first != ssid_range->ssid_first)
 				continue;
 			mutex_lock(&mask_ptr->lock);
@@ -687,6 +690,8 @@
 
 		new_size = (driver->msg_mask_tbl_count + 1) *
 			   sizeof(struct diag_msg_mask_t);
+		DIAG_LOG(DIAG_DEBUG_MASKS,
+			"diag: receiving msg mask size more that Apps can handle\n");
 		temp = krealloc(msg_mask.ptr, new_size, GFP_KERNEL);
 		if (!temp) {
 			pr_err("diag: In %s, Unable to add new ssid table to msg mask, ssid first: %d, last: %d\n",
@@ -695,6 +700,7 @@
 			continue;
 		}
 		msg_mask.ptr = temp;
+		mask_ptr = (struct diag_msg_mask_t *)msg_mask.ptr;
 		err = diag_create_msg_mask_table_entry(mask_ptr, ssid_range);
 		if (err) {
 			pr_err("diag: In %s, Unable to create a new msg mask table entry, first: %d last: %d err: %d\n",
@@ -741,6 +747,10 @@
 	num_items = range->ssid_last - range->ssid_first + 1;
 
 	for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) {
+		if (!build_mask) {
+			found = 1;
+			break;
+		}
 		if (build_mask->ssid_first != range->ssid_first)
 			continue;
 		found = 1;
@@ -751,7 +761,8 @@
 			       __func__);
 		}
 		dest_ptr = build_mask->ptr;
-		for (j = 0; j < build_mask->range; j++, mask_ptr++, dest_ptr++)
+		for (j = 0; (j < build_mask->range) && mask_ptr && dest_ptr;
+			j++, mask_ptr++, dest_ptr++)
 			*(uint32_t *)dest_ptr |= *mask_ptr;
 		mutex_unlock(&build_mask->lock);
 		break;
@@ -759,8 +770,12 @@
 
 	if (found)
 		goto end;
+
 	new_size = (driver->bt_msg_mask_tbl_count + 1) *
 		   sizeof(struct diag_msg_mask_t);
+	DIAG_LOG(DIAG_DEBUG_MASKS,
+		"diag: receiving build time mask size more that Apps can handle\n");
+
 	temp = krealloc(driver->build_time_mask->ptr, new_size, GFP_KERNEL);
 	if (!temp) {
 		pr_err("diag: In %s, unable to create a new entry for build time mask\n",
@@ -768,6 +783,7 @@
 		goto end;
 	}
 	driver->build_time_mask->ptr = temp;
+	build_mask = (struct diag_msg_mask_t *)driver->build_time_mask->ptr;
 	err = diag_create_msg_mask_table_entry(build_mask, range);
 	if (err) {
 		pr_err("diag: In %s, Unable to create a new msg mask table entry, err: %d\n",
diff --git a/drivers/clk/msm/clock-gcc-8952.c b/drivers/clk/msm/clock-gcc-8952.c
index d471138..47619f5 100644
--- a/drivers/clk/msm/clock-gcc-8952.c
+++ b/drivers/clk/msm/clock-gcc-8952.c
@@ -4505,6 +4505,7 @@
 			vdd_hf_pll.num_levels = VDD_HF_PLL_NUM_439;
 			vdd_hf_pll.cur_level = VDD_HF_PLL_NUM_439;
 
+			gpll3_clk_src.test_ctl_hi_val = 0x400000;
 			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;
diff --git a/drivers/clk/qcom/gcc-sdxpoorwills.c b/drivers/clk/qcom/gcc-sdxpoorwills.c
index b52002f..a27bd19 100644
--- a/drivers/clk/qcom/gcc-sdxpoorwills.c
+++ b/drivers/clk/qcom/gcc-sdxpoorwills.c
@@ -143,11 +143,6 @@
 			.parent_names = (const char *[]){ "bi_tcxo" },
 			.num_parents = 1,
 			.ops = &clk_trion_fixed_pll_ops,
-			VDD_CX_FMAX_MAP4(
-				MIN, 615000000,
-				LOW, 1066000000,
-				LOW_L1, 1600000000,
-				NOMINAL, 2000000000),
 		},
 	},
 };
@@ -757,7 +752,7 @@
 static const struct freq_tbl ftbl_gcc_usb30_master_clk_src[] = {
 	F(50000000, P_GPLL0_OUT_EVEN, 6, 0, 0),
 	F(75000000, P_GPLL0_OUT_EVEN, 4, 0, 0),
-	F(100000000, P_GPLL0_OUT_MAIN, 6, 0, 0),
+	F(120000000, P_GPLL0_OUT_MAIN, 5, 0, 0),
 	F(200000000, P_GPLL0_OUT_MAIN, 3, 0, 0),
 	F(240000000, P_GPLL0_OUT_MAIN, 2.5, 0, 0),
 	{ }
@@ -777,7 +772,7 @@
 		VDD_CX_FMAX_MAP5(
 			MIN, 50000000,
 			LOWER, 75000000,
-			LOW, 100000000,
+			LOW, 120000000,
 			NOMINAL, 200000000,
 			HIGH, 240000000),
 	},
diff --git a/drivers/clk/qcom/gdsc-regulator.c b/drivers/clk/qcom/gdsc-regulator.c
index 0899138..0d7ed80 100644
--- a/drivers/clk/qcom/gdsc-regulator.c
+++ b/drivers/clk/qcom/gdsc-regulator.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -34,6 +34,10 @@
 #define PWR_ON_MASK		BIT(31)
 #define CLK_DIS_WAIT_MASK	(0xF << 12)
 #define CLK_DIS_WAIT_SHIFT	(12)
+#define EN_FEW_WAIT_MASK	(0xF << 16)
+#define EN_FEW_WAIT_SHIFT	(16)
+#define EN_REST_WAIT_MASK	(0xF << 20)
+#define EN_REST_WAIT_SHIFT	(20)
 #define SW_OVERRIDE_MASK	BIT(2)
 #define HW_CONTROL_MASK		BIT(1)
 #define SW_COLLAPSE_MASK	BIT(0)
@@ -535,6 +539,7 @@
 	struct resource *res;
 	struct gdsc *sc;
 	uint32_t regval, clk_dis_wait_val = 0;
+	uint32_t en_few_wait_val, en_rest_wait_val;
 	bool retain_mem, retain_periph, support_hw_trigger, prop_val;
 	int i, ret;
 	u32 timeout;
@@ -681,6 +686,22 @@
 		regval |= clk_dis_wait_val;
 	}
 
+	if (!of_property_read_u32(pdev->dev.of_node, "qcom,en-few-wait-val",
+				  &en_few_wait_val)) {
+		en_few_wait_val <<= EN_FEW_WAIT_SHIFT;
+
+		regval &= ~(EN_FEW_WAIT_MASK);
+		regval |= en_few_wait_val;
+	}
+
+	if (!of_property_read_u32(pdev->dev.of_node, "qcom,en-rest-wait-val",
+				  &en_rest_wait_val)) {
+		en_rest_wait_val <<= EN_REST_WAIT_SHIFT;
+
+		regval &= ~(EN_REST_WAIT_MASK);
+		regval |= en_rest_wait_val;
+	}
+
 	regmap_write(sc->regmap, REG_OFFSET, regval);
 
 	sc->no_status_check_on_disable =
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 731ea9b..6e16d9f 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1508,6 +1508,9 @@
 		policy->freq_table = NULL;
 	}
 
+	blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+			CPUFREQ_STOP, policy);
+
 unlock:
 	up_write(&policy->rwsem);
 	return 0;
diff --git a/drivers/cpuidle/lpm-levels-legacy.c b/drivers/cpuidle/lpm-levels-legacy.c
index 006a5ef..26cb52a 100644
--- a/drivers/cpuidle/lpm-levels-legacy.c
+++ b/drivers/cpuidle/lpm-levels-legacy.c
@@ -643,9 +643,11 @@
 		cpumask_copy(&cpumask, cpumask_of(cpu));
 		nextcpu = level->disable_dynamic_routing ? NULL : &cpumask;
 
-		if (sys_pm_ops && sys_pm_ops->enter)
-			if ((sys_pm_ops->enter(nextcpu)))
-				return -EBUSY;
+		if (sys_pm_ops && sys_pm_ops->enter) {
+			ret = sys_pm_ops->enter(nextcpu);
+			if (ret)
+				goto failed_set_mode;
+		}
 
 		if (cluster->no_saw_devices && !use_psci)
 			msm_spm_set_rpm_hs(true);
diff --git a/drivers/cpuidle/lpm-levels-of-legacy.c b/drivers/cpuidle/lpm-levels-of-legacy.c
index bf74124..8782850 100644
--- a/drivers/cpuidle/lpm-levels-of-legacy.c
+++ b/drivers/cpuidle/lpm-levels-of-legacy.c
@@ -863,8 +863,11 @@
 			continue;
 		key = "qcom,pm-cluster-level";
 		if (!of_node_cmp(n->name, key)) {
-			if (parse_cluster_level(n, c))
+			if (parse_cluster_level(n, c)) {
+				of_node_put(n);
 				goto failed_parse_cluster;
+			}
+			of_node_put(n);
 			continue;
 		}
 
@@ -877,14 +880,16 @@
 					__func__);
 
 			child = parse_cluster(n, c);
-			if (!child)
+			if (!child) {
+				of_node_put(n);
 				goto failed_parse_cluster;
+			}
 
-			of_node_put(n);
 			list_add(&child->list, &c->child);
 			cpumask_or(&c->child_cpus, &c->child_cpus,
 					&child->child_cpus);
 			c->aff_level = child->aff_level + 1;
+			of_node_put(n);
 			continue;
 		}
 
@@ -898,10 +903,13 @@
 			if (get_cpumask_for_node(node, &c->child_cpus))
 				goto failed_parse_cluster;
 
-			if (parse_cpu_levels(n, c))
+			if (parse_cpu_levels(n, c)) {
+				of_node_put(n);
 				goto failed_parse_cluster;
+			}
 
 			c->aff_level = 1;
+			of_node_put(n);
 
 			for_each_cpu(i, &c->child_cpus) {
 				per_cpu(max_residency, i) = devm_kzalloc(
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index c7ec868..e692f660 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -1777,6 +1777,7 @@
 	.driver = {
 		.name = "lpm-levels",
 		.owner = THIS_MODULE,
+		.suppress_bind_attrs = true,
 		.of_match_table = lpm_mtch_tbl,
 	},
 };
diff --git a/drivers/devfreq/devfreq_devbw.c b/drivers/devfreq/devfreq_devbw.c
index 5c7959c..5bc4db4 100644
--- a/drivers/devfreq/devfreq_devbw.c
+++ b/drivers/devfreq/devfreq_devbw.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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
@@ -258,6 +258,7 @@
 	.driver = {
 		.name = "devbw",
 		.of_match_table = devbw_match_table,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/devfreq/devfreq_simple_dev.c b/drivers/devfreq/devfreq_simple_dev.c
index b0757b6..8566e98 100644
--- a/drivers/devfreq/devfreq_simple_dev.c
+++ b/drivers/devfreq/devfreq_simple_dev.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-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
@@ -212,6 +213,7 @@
 	.driver = {
 		.name = "devfreq-simple-dev",
 		.of_match_table = devfreq_simple_match_table,
+		.suppress_bind_attrs = true,
 	},
 };
 module_platform_driver(devfreq_clock_driver);
diff --git a/drivers/devfreq/governor_cpufreq.c b/drivers/devfreq/governor_cpufreq.c
index 03ec792..3c7fc8b 100644
--- a/drivers/devfreq/governor_cpufreq.c
+++ b/drivers/devfreq/governor_cpufreq.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-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
@@ -182,14 +182,14 @@
 	struct cpufreq_policy *policy = data;
 
 	switch (event) {
-	case CPUFREQ_CREATE_POLICY:
+	case CPUFREQ_START:
 		mutex_lock(&state_lock);
 		add_policy(policy);
 		update_all_devfreqs();
 		mutex_unlock(&state_lock);
 		break;
 
-	case CPUFREQ_REMOVE_POLICY:
+	case CPUFREQ_STOP:
 		mutex_lock(&state_lock);
 		if (state[policy->cpu]) {
 			state[policy->cpu]->on = false;
diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c
index 065b765..fff2ae9 100644
--- a/drivers/dma/qcom/gpi.c
+++ b/drivers/dma/qcom/gpi.c
@@ -2564,22 +2564,6 @@
 	return arm_iommu_create_mapping(&platform_bus_type, base, size);
 }
 
-static int gpi_dma_mask(struct gpi_dev *gpi_dev)
-{
-	int mask = 64;
-
-	if (gpi_dev->smmu_cfg && !(gpi_dev->smmu_cfg & GPI_SMMU_S1_BYPASS)) {
-		unsigned long addr;
-
-		addr = gpi_dev->iova_base + gpi_dev->iova_size + 1;
-		mask = find_last_bit(&addr, 64);
-	}
-
-	GPI_LOG(gpi_dev, "Setting dma mask to %d\n", mask);
-
-	return dma_set_mask(gpi_dev->dev, DMA_BIT_MASK(mask));
-}
-
 static int gpi_smmu_init(struct gpi_dev *gpi_dev)
 {
 	struct dma_iommu_mapping *mapping = NULL;
@@ -2643,9 +2627,10 @@
 		}
 	}
 
-	ret = gpi_dma_mask(gpi_dev);
+	GPI_LOG(gpi_dev, "Setting dma mask to 64\n");
+	ret = dma_set_mask(gpi_dev->dev, DMA_BIT_MASK(64));
 	if (ret) {
-		GPI_ERR(gpi_dev, "Error setting dma_mask, ret:%d\n", ret);
+		GPI_ERR(gpi_dev, "Error setting dma_mask to 64, ret:%d\n", ret);
 		goto error_set_mask;
 	}
 
diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c
index 78bea02..6e6efa5 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -104,7 +104,7 @@
 	size = min_t(size_t, count, SZ_1K);
 
 	buf = kzalloc(size, GFP_KERNEL);
-	if (!buf) {
+	if (ZERO_OR_NULL_PTR(buf)) {
 		rc = -ENOMEM;
 		goto bail;
 	}
@@ -172,7 +172,7 @@
 	size = min_t(size_t, count, SZ_2K);
 
 	buf = kzalloc(size, GFP_KERNEL);
-	if (!buf) {
+	if (ZERO_OR_NULL_PTR(buf)) {
 		rc = -ENOMEM;
 		goto bail;
 	}
@@ -493,7 +493,7 @@
 		goto error;
 
 	buf = kzalloc(SZ_4K, GFP_KERNEL);
-	if (!buf) {
+	if (ZERO_OR_NULL_PTR(buf)) {
 		rc = -ENOMEM;
 		goto error;
 	}
@@ -538,7 +538,7 @@
 		return 0;
 
 	buf = kzalloc(SZ_4K, GFP_KERNEL);
-	if (!buf)
+	if (ZERO_OR_NULL_PTR(buf))
 		return -ENOMEM;
 
 	rc = snprintf(buf + len, max_size, "\tstate=0x%x\n", debug->aux->state);
@@ -624,7 +624,7 @@
 		return 0;
 
 	buf = kzalloc(SZ_4K, GFP_KERNEL);
-	if (!buf)
+	if (ZERO_OR_NULL_PTR(buf))
 		return -ENOMEM;
 
 	len += snprintf(buf + len, (SZ_4K - len),
@@ -669,7 +669,7 @@
 	struct sde_connector *c_conn;
 	struct sde_connector_state *c_state;
 	struct dp_debug_private *debug = file->private_data;
-	char buf[SZ_1K];
+	char buf[SZ_512];
 	size_t len = 0;
 
 	if (!debug)
@@ -683,7 +683,7 @@
 	c_state = to_sde_connector_state(connector->state);
 
 	/* Leave room for termination char */
-	len = min_t(size_t, count, SZ_1K - 1);
+	len = min_t(size_t, count, SZ_512 - 1);
 	if (copy_from_user(buf, user_buff, len))
 		goto end;
 
@@ -745,7 +745,7 @@
 		goto error;
 
 	buf = kzalloc(SZ_4K, GFP_KERNEL);
-	if (!buf) {
+	if (ZERO_OR_NULL_PTR(buf)) {
 		rc = -ENOMEM;
 		goto error;
 	}
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 1b92261..d9839e7 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1488,6 +1488,7 @@
 	.driver = {
 		.name = "msm-dp-display",
 		.of_match_table = dp_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/gpu/drm/msm/dp/dp_hdcp2p2.c b/drivers/gpu/drm/msm/dp/dp_hdcp2p2.c
index 2b7b217..f277ac0 100644
--- a/drivers/gpu/drm/msm/dp/dp_hdcp2p2.c
+++ b/drivers/gpu/drm/msm/dp/dp_hdcp2p2.c
@@ -26,6 +26,9 @@
 
 #define DP_INTR_STATUS2				(0x00000024)
 #define DP_INTR_STATUS3				(0x00000028)
+
+#define DP_DPCD_CP_IRQ                          (0x201)
+
 #define dp_read(offset) readl_relaxed((offset))
 #define dp_write(offset, data) writel_relaxed((data), (offset))
 #define DP_HDCP_RXCAPS_LENGTH 3
@@ -393,6 +396,7 @@
 		if (bytes_written != write_size) {
 			pr_err("fail: offset(0x%x), size(0x%x), rc(0x%x)\n",
 					offset, write_size, bytes_written);
+			rc = bytes_written;
 			break;
 		}
 
@@ -675,6 +679,18 @@
 	return rc;
 }
 
+static void dp_hdcp2p2_clear_cp_irq(struct dp_hdcp2p2_ctrl *ctrl)
+{
+	int rc = 0;
+	u8 buf = BIT(2);
+	u32 const default_timeout_us = 500;
+
+	rc = dp_hdcp2p2_aux_write_message(ctrl, &buf, 1,
+			DP_DPCD_CP_IRQ, default_timeout_us);
+	if (rc)
+		pr_err("error clearing irq_vector\n");
+}
+
 static int dp_hdcp2p2_cp_irq(void *input)
 {
 	int rc = 0;
@@ -709,6 +725,7 @@
 
 	kthread_queue_work(&ctrl->worker, &ctrl->link);
 
+	dp_hdcp2p2_clear_cp_irq(ctrl);
 	return 0;
 error:
 	return rc;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
index a457070..011e3b8 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
@@ -69,6 +69,7 @@
 	ctrl->ops.get_hw_version = dsi_ctrl_hw_cmn_get_hw_version;
 	ctrl->ops.wait_for_cmd_mode_mdp_idle =
 		dsi_ctrl_hw_cmn_wait_for_cmd_mode_mdp_idle;
+	ctrl->ops.set_continuous_clk = dsi_ctrl_hw_cmn_set_continuous_clk;
 
 	switch (version) {
 	case DSI_CTRL_VERSION_1_4:
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
index 9a923aa..c55bbe0 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
@@ -224,4 +224,6 @@
 /* Definitions specific to 2.2 DSI controller hardware */
 bool dsi_ctrl_hw_22_get_cont_splash_status(struct dsi_ctrl_hw *ctrl);
 
+void dsi_ctrl_hw_cmn_set_continuous_clk(struct dsi_ctrl_hw *ctrl, bool enable);
+
 #endif /* _DSI_CATALOG_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 92e08e0..31c3b1a 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -1239,9 +1239,10 @@
 			}
 		}
 
-		if (dsi_ctrl->hw.ops.mask_error_intr)
+		if (dsi_ctrl->hw.ops.mask_error_intr &&
+		    !dsi_ctrl->esd_check_underway)
 			dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
-					BIT(DSI_FIFO_OVERFLOW), false);
+						BIT(DSI_FIFO_OVERFLOW), false);
 		dsi_ctrl->hw.ops.reset_cmd_fifo(&dsi_ctrl->hw);
 
 		/*
@@ -1272,6 +1273,7 @@
 		.type = MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE,
 		.tx_len = 2,
 		.tx_buf = tx,
+		.flags = rx_msg->flags,
 	};
 
 	rc = dsi_message_tx(dsi_ctrl, &msg, flags);
@@ -1797,6 +1799,7 @@
 	.driver = {
 		.name = "drm_dsi_ctrl",
 		.of_match_table = msm_dsi_of_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
@@ -2601,6 +2604,16 @@
 	mutex_unlock(&dsi_ctrl->ctrl_lock);
 }
 
+void dsi_ctrl_set_continuous_clk(struct dsi_ctrl *dsi_ctrl, bool enable)
+{
+	if (!dsi_ctrl)
+		return;
+
+	mutex_lock(&dsi_ctrl->ctrl_lock);
+	dsi_ctrl->hw.ops.set_continuous_clk(&dsi_ctrl->hw, enable);
+	mutex_unlock(&dsi_ctrl->ctrl_lock);
+}
+
 int dsi_ctrl_soft_reset(struct dsi_ctrl *dsi_ctrl)
 {
 	if (!dsi_ctrl)
@@ -2886,7 +2899,8 @@
 						dsi_ctrl->cell_index);
 			}
 		}
-		if (dsi_ctrl->hw.ops.mask_error_intr)
+		if (dsi_ctrl->hw.ops.mask_error_intr &&
+				!dsi_ctrl->esd_check_underway)
 			dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw,
 					BIT(DSI_FIFO_OVERFLOW), false);
 
@@ -3384,7 +3398,8 @@
 	return misr;
 }
 
-void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl)
+void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl, u32 idx,
+		bool mask_enable)
 {
 	if (!dsi_ctrl || !dsi_ctrl->hw.ops.error_intr_ctrl
 			|| !dsi_ctrl->hw.ops.clear_error_status) {
@@ -3397,9 +3412,23 @@
 	 * register
 	 */
 	mutex_lock(&dsi_ctrl->ctrl_lock);
-	dsi_ctrl->hw.ops.error_intr_ctrl(&dsi_ctrl->hw, false);
-	dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
+	if (idx & BIT(DSI_ERR_INTR_ALL)) {
+		/*
+		 * The behavior of mask_enable is different in ctrl register
+		 * and mask register and hence mask_enable is manipulated for
+		 * selective error interrupt masking vs total error interrupt
+		 * masking.
+		 */
+
+		dsi_ctrl->hw.ops.error_intr_ctrl(&dsi_ctrl->hw, !mask_enable);
+		dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
 					DSI_ERROR_INTERRUPT_COUNT);
+	} else {
+		dsi_ctrl->hw.ops.mask_error_intr(&dsi_ctrl->hw, idx,
+								mask_enable);
+		dsi_ctrl->hw.ops.clear_error_status(&dsi_ctrl->hw,
+					DSI_ERROR_INTERRUPT_COUNT);
+	}
 	mutex_unlock(&dsi_ctrl->ctrl_lock);
 }
 
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
index 6ac7dd7..61c6116 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
@@ -221,6 +221,7 @@
  * @cmd_buffer_size:     Size of command buffer.
  * @vaddr:               CPU virtual address of cmd buffer.
  * @secure_mode:         Indicates if secure-session is in progress
+ * @esd_check_underway:  Indicates if esd status check is in progress
  * @debugfs_root:        Root for debugfs entries.
  * @misr_enable:         Frame MISR enable/disable
  * @misr_cache:          Cached Frame MISR value
@@ -266,6 +267,7 @@
 	u32 cmd_len;
 	void *vaddr;
 	bool secure_mode;
+	bool esd_check_underway;
 
 	/* Debug Information */
 	struct dentry *debugfs_root;
@@ -743,8 +745,11 @@
  * dsi_ctrl_mask_error_status_interrupts() - API to mask dsi ctrl error status
  *                                           interrupts
  * @dsi_ctrl:              DSI controller handle.
+ * @idx:                   id indicating which interrupts to enable/disable.
+ * @mask_enable:           boolean to enable/disable masking.
  */
-void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl);
+void dsi_ctrl_mask_error_status_interrupts(struct dsi_ctrl *dsi_ctrl, u32 idx,
+						bool mask_enable);
 
 /**
  * dsi_ctrl_irq_update() - Put a irq vote to process DSI error
@@ -772,4 +777,10 @@
  */
 int dsi_ctrl_wait_for_cmd_mode_mdp_idle(struct dsi_ctrl *dsi_ctrl);
 
+/**
+ * dsi_ctrl_set_continuous_clk() - API to set/unset force clock lane HS request.
+ * @dsi_ctrl:                      DSI controller handle.
+ * @enable:			   variable to control continuous clock.
+ */
+void dsi_ctrl_set_continuous_clk(struct dsi_ctrl *dsi_ctrl, bool enable);
 #endif /* _DSI_CTRL_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
index 73aab3f..348ef36 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
@@ -158,7 +158,7 @@
  * @DSI_EINT_DLN0_ESC_ENTRY_ERR:         Incorrect LP Rx escape entry.
  * @DSI_EINT_DLN0_ESC_SYNC_ERR:          LP Rx data is not byte aligned.
  * @DSI_EINT_DLN0_LP_CONTROL_ERR:        Incorrect LP Rx state sequence.
- * @DSI_EINT_PENDING_HS_TX_TIMEOUT:      Pending High-speed transfer timeout.
+ * @DSI_EINT_PANEL_SPECIFIC_ERR:         DSI Protocol violation error.
  * @DSI_EINT_INTERLEAVE_OP_CONTENTION:   Interleave operation contention.
  * @DSI_EINT_CMD_DMA_FIFO_UNDERFLOW:     Command mode DMA FIFO underflow.
  * @DSI_EINT_CMD_MDP_FIFO_UNDERFLOW:     Command MDP FIFO underflow (failed to
@@ -179,7 +179,6 @@
  * @DSI_EINT_DLN1_LP1_CONTENTION:        PHY level contention while lane 1 high.
  * @DSI_EINT_DLN2_LP1_CONTENTION:        PHY level contention while lane 2 high.
  * @DSI_EINT_DLN3_LP1_CONTENTION:        PHY level contention while lane 3 high.
- * @DSI_EINT_PANEL_SPECIFIC_ERR:         DSI Protocol violation error.
  */
 enum dsi_error_int_index {
 	DSI_EINT_RDBK_SINGLE_ECC_ERR = 0,
@@ -194,7 +193,7 @@
 	DSI_EINT_DLN0_ESC_ENTRY_ERR = 9,
 	DSI_EINT_DLN0_ESC_SYNC_ERR = 10,
 	DSI_EINT_DLN0_LP_CONTROL_ERR = 11,
-	DSI_EINT_PENDING_HS_TX_TIMEOUT = 12,
+	DSI_EINT_PANEL_SPECIFIC_ERR = 12,
 	DSI_EINT_INTERLEAVE_OP_CONTENTION = 13,
 	DSI_EINT_CMD_DMA_FIFO_UNDERFLOW = 14,
 	DSI_EINT_CMD_MDP_FIFO_UNDERFLOW = 15,
@@ -214,7 +213,6 @@
 	DSI_EINT_DLN1_LP1_CONTENTION = 29,
 	DSI_EINT_DLN2_LP1_CONTENTION = 30,
 	DSI_EINT_DLN3_LP1_CONTENTION = 31,
-	DSI_EINT_PANEL_SPECIFIC_ERR = 32,
 
 	DSI_ERROR_INTERRUPT_COUNT
 };
@@ -233,7 +231,7 @@
  * @DSI_DLN0_ESC_ENTRY_ERR:         Incorrect LP Rx escape entry.
  * @DSI_DLN0_ESC_SYNC_ERR:          LP Rx data is not byte aligned.
  * @DSI_DLN0_LP_CONTROL_ERR:        Incorrect LP Rx state sequence.
- * @DSI_PENDING_HS_TX_TIMEOUT:      Pending High-speed transfer timeout.
+ * @DSI_PANEL_SPECIFIC_ERR:         DSI Protocol violation.
  * @DSI_INTERLEAVE_OP_CONTENTION:   Interleave operation contention.
  * @DSI_CMD_DMA_FIFO_UNDERFLOW:     Command mode DMA FIFO underflow.
  * @DSI_CMD_MDP_FIFO_UNDERFLOW:     Command MDP FIFO underflow (failed to
@@ -254,7 +252,6 @@
  * @DSI_DLN1_LP1_CONTENTION:        PHY level contention while lane 1 is high.
  * @DSI_DLN2_LP1_CONTENTION:        PHY level contention while lane 2 is high.
  * @DSI_DLN3_LP1_CONTENTION:        PHY level contention while lane 3 is high.
- * @DSI_PANEL_SPECIFIC_ERR:         DSI Protocol violation.
  */
 enum dsi_error_int_type {
 	DSI_RDBK_SINGLE_ECC_ERR = BIT(DSI_EINT_RDBK_SINGLE_ECC_ERR),
@@ -269,7 +266,7 @@
 	DSI_DLN0_ESC_ENTRY_ERR = BIT(DSI_EINT_DLN0_ESC_ENTRY_ERR),
 	DSI_DLN0_ESC_SYNC_ERR = BIT(DSI_EINT_DLN0_ESC_SYNC_ERR),
 	DSI_DLN0_LP_CONTROL_ERR = BIT(DSI_EINT_DLN0_LP_CONTROL_ERR),
-	DSI_PENDING_HS_TX_TIMEOUT = BIT(DSI_EINT_PENDING_HS_TX_TIMEOUT),
+	DSI_PANEL_SPECIFIC_ERR = BIT(DSI_EINT_PANEL_SPECIFIC_ERR),
 	DSI_INTERLEAVE_OP_CONTENTION = BIT(DSI_EINT_INTERLEAVE_OP_CONTENTION),
 	DSI_CMD_DMA_FIFO_UNDERFLOW = BIT(DSI_EINT_CMD_DMA_FIFO_UNDERFLOW),
 	DSI_CMD_MDP_FIFO_UNDERFLOW = BIT(DSI_EINT_CMD_MDP_FIFO_UNDERFLOW),
@@ -289,7 +286,6 @@
 	DSI_DLN1_LP1_CONTENTION = BIT(DSI_EINT_DLN1_LP1_CONTENTION),
 	DSI_DLN2_LP1_CONTENTION = BIT(DSI_EINT_DLN2_LP1_CONTENTION),
 	DSI_DLN3_LP1_CONTENTION = BIT(DSI_EINT_DLN3_LP1_CONTENTION),
-	DSI_PANEL_SPECIFIC_ERR = BIT(DSI_EINT_PANEL_SPECIFIC_ERR),
 };
 
 /**
@@ -807,6 +803,13 @@
 	 * @ctrl:         Pointer to the controller host hardware.
 	 */
 	int (*wait_for_cmd_mode_mdp_idle)(struct dsi_ctrl_hw *ctrl);
+
+	/**
+	 * hw.ops.set_continuous_clk() - Set continuous clock
+	 * @ctrl:         Pointer to the controller host hardware.
+	 * @enable:	  Bool to control continuous clock request.
+	 */
+	void (*set_continuous_clk)(struct dsi_ctrl_hw *ctrl, bool enable);
 };
 
 /*
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
index 6dde454..7c58c43 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
@@ -1420,17 +1420,20 @@
 	reg = DSI_R32(ctrl, 0x10c);
 
 	if (idx & BIT(DSI_FIFO_OVERFLOW)) {
-		if (en)
-			reg |= (0xf << 16);
-		else
-			reg &= ~(0xf << 16);
+		if (en) {
+			reg |= (0x1f << 16);
+			reg |= BIT(9);
+		} else {
+			reg &= ~(0x1f << 16);
+			reg &= ~BIT(9);
+		}
 	}
 
 	if (idx & BIT(DSI_FIFO_UNDERFLOW)) {
 		if (en)
-			reg |= (0xf << 26);
+			reg |= (0x1b << 26);
 		else
-			reg &= ~(0xf << 26);
+			reg &= ~(0x1b << 26);
 	}
 
 	if (idx & BIT(DSI_LP_Rx_TIMEOUT)) {
@@ -1493,3 +1496,16 @@
 
 	return rc;
 }
+
+void dsi_ctrl_hw_cmn_set_continuous_clk(struct dsi_ctrl_hw *ctrl, bool enable)
+{
+	u32 reg = 0;
+
+	reg = DSI_R32(ctrl, DSI_LANE_CTRL);
+	if (enable)
+		reg |= BIT(28);
+	else
+		reg &= ~BIT(28);
+	DSI_W32(ctrl, DSI_LANE_CTRL, reg);
+	wmb(); /* make sure request is set */
+}
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
index 6540182..3b2ef70 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_defs.h
@@ -404,6 +404,7 @@
  * @ignore_rx_eot:       Ignore Rx EOT packets if set to true.
  * @append_tx_eot:       Append EOT packets for forward transmissions if set to
  *                       true.
+ * @force_hs_clk_lane:   Send continuous clock to the panel.
  */
 struct dsi_host_common_cfg {
 	enum dsi_pixel_format dst_format;
@@ -422,6 +423,7 @@
 	u32 t_clk_pre;
 	bool ignore_rx_eot;
 	bool append_tx_eot;
+	bool force_hs_clk_lane;
 };
 
 /**
@@ -598,6 +600,7 @@
 	DSI_FIFO_OVERFLOW = 1,
 	DSI_FIFO_UNDERFLOW,
 	DSI_LP_Rx_TIMEOUT,
+	DSI_ERR_INTR_ALL,
 };
 
 #endif /* _DSI_DEFS_H_ */
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index f0311fd..c5a1a9f 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -48,15 +48,19 @@
 static char dsi_display_primary[MAX_CMDLINE_PARAM_LEN];
 static char dsi_display_secondary[MAX_CMDLINE_PARAM_LEN];
 static struct dsi_display_boot_param boot_displays[MAX_DSI_ACTIVE_DISPLAY];
-static struct device_node *default_active_node;
+static struct device_node *primary_active_node;
+static struct device_node *secondary_active_node;
+
 static const struct of_device_id dsi_display_dt_match[] = {
 	{.compatible = "qcom,dsi-display"},
 	{}
 };
 
-static struct dsi_display *main_display;
+static struct dsi_display *primary_display;
+static struct dsi_display *secondary_display;
 
-static void dsi_display_mask_ctrl_error_interrupts(struct dsi_display *display)
+static void dsi_display_mask_ctrl_error_interrupts(struct dsi_display *display,
+			u32 mask, bool enable)
 {
 	int i;
 	struct dsi_display_ctrl *ctrl;
@@ -69,7 +73,25 @@
 		ctrl = &display->ctrl[i];
 		if (!ctrl)
 			continue;
-		dsi_ctrl_mask_error_status_interrupts(ctrl->ctrl);
+		dsi_ctrl_mask_error_status_interrupts(ctrl->ctrl, mask, enable);
+	}
+}
+
+static void dsi_display_set_ctrl_esd_check_flag(struct dsi_display *display,
+			bool enable)
+{
+	int i;
+	struct dsi_display_ctrl *ctrl;
+
+	if (!display)
+		return;
+
+	for (i = 0; (i < display->ctrl_count) &&
+			(i < MAX_DSI_CTRLS_PER_DISPLAY); i++) {
+		ctrl = &display->ctrl[i];
+		if (!ctrl)
+			continue;
+		ctrl->ctrl->esd_check_underway = enable;
 	}
 }
 
@@ -668,10 +690,6 @@
 		}
 	}
 exit:
-	/* mask only error interrupts */
-	if (rc <= 0)
-		dsi_display_mask_ctrl_error_interrupts(display);
-
 	dsi_display_cmd_engine_disable(display);
 done:
 	return rc;
@@ -712,6 +730,7 @@
 	struct dsi_panel *panel;
 	u32 status_mode;
 	int rc = 0x1;
+	u32 mask;
 
 	if (!dsi_display || !dsi_display->panel)
 		return -EINVAL;
@@ -727,6 +746,12 @@
 	}
 	SDE_EVT32(SDE_EVTLOG_FUNC_ENTRY);
 
+	/* Prevent another ESD check,when ESD recovery is underway */
+	if (atomic_read(&panel->esd_recovery_pending)) {
+		dsi_panel_release_panel_lock(panel);
+		return rc;
+	}
+
 	if (te_check_override && gpio_is_valid(dsi_display->disp_te_gpio))
 		status_mode = ESD_MODE_PANEL_TE;
 	else
@@ -735,6 +760,11 @@
 	dsi_display_clk_ctrl(dsi_display->dsi_clk_handle,
 		DSI_ALL_CLKS, DSI_CLK_ON);
 
+	/* Mask error interrupts before attempting ESD read */
+	mask = BIT(DSI_FIFO_OVERFLOW) | BIT(DSI_FIFO_UNDERFLOW);
+	dsi_display_set_ctrl_esd_check_flag(dsi_display, true);
+	dsi_display_mask_ctrl_error_interrupts(dsi_display, mask, true);
+
 	if (status_mode == ESD_MODE_REG_READ) {
 		rc = dsi_display_status_reg_read(dsi_display);
 	} else if (status_mode == ESD_MODE_SW_BTA) {
@@ -746,6 +776,16 @@
 		panel->esd_config.esd_enabled = false;
 	}
 
+	/* Unmask error interrupts */
+	if (rc > 0) {
+		dsi_display_set_ctrl_esd_check_flag(dsi_display, false);
+		dsi_display_mask_ctrl_error_interrupts(dsi_display, mask,
+							false);
+	} else {
+		/* Handle Panel failures during display disable sequence */
+		atomic_set(&panel->esd_recovery_pending, 1);
+	}
+
 	dsi_display_clk_ctrl(dsi_display->dsi_clk_handle,
 		DSI_ALL_CLKS, DSI_CLK_OFF);
 	dsi_panel_release_panel_lock(panel);
@@ -769,8 +809,8 @@
 	cmd->msg.tx_len = ((cmd_buf[5] << 8) | (cmd_buf[6]));
 
 	if (cmd->msg.tx_len > payload_len) {
-		pr_err("Incorrect payload length tx_len %ld, payload_len %d\n",
-				cmd->msg.tx_len, payload_len);
+		pr_err("Incorrect payload length tx_len %zu, payload_len %d\n",
+		       cmd->msg.tx_len, payload_len);
 		return -EINVAL;
 	}
 
@@ -835,6 +875,21 @@
 	return rc;
 }
 
+static void _dsi_display_continuous_clk_ctrl(struct dsi_display *display,
+					     bool enable)
+{
+	int i;
+	struct dsi_display_ctrl *ctrl;
+
+	if (!display || !display->panel->host_config.force_hs_clk_lane)
+		return;
+
+	for (i = 0; i < display->ctrl_count; i++) {
+		ctrl = &display->ctrl[i];
+		dsi_ctrl_set_continuous_clk(ctrl->ctrl, enable);
+	}
+}
+
 int dsi_display_soft_reset(void *display)
 {
 	struct dsi_display *dsi_display;
@@ -1075,7 +1130,7 @@
 		return 0;
 
 	buf = kzalloc(max_len, GFP_KERNEL);
-	if (!buf)
+	if (ZERO_OR_NULL_PTR(buf))
 		return -ENOMEM;
 
 	mutex_lock(&display->display_lock);
@@ -1193,7 +1248,7 @@
 		return 0;
 
 	buf = kzalloc(len, GFP_KERNEL);
-	if (!buf)
+	if (ZERO_OR_NULL_PTR(buf))
 		return -ENOMEM;
 
 	if (copy_from_user(buf, user_buf, user_len)) {
@@ -1265,7 +1320,7 @@
 	}
 
 	buf = kzalloc(len, GFP_KERNEL);
-	if (!buf)
+	if (ZERO_OR_NULL_PTR(buf))
 		return -ENOMEM;
 
 	esd_config = &display->panel->esd_config;
@@ -2019,11 +2074,9 @@
 			boot_displays[i].name[j] = *(disp_buf + j);
 		boot_displays[i].name[j] = '\0';
 
-		if (i == DSI_PRIMARY) {
+		if (i == DSI_PRIMARY)
 			boot_displays[i].is_primary = true;
-			/* Currently, secondary DSI display is not supported */
-			boot_displays[i].boot_disp_en = true;
-		}
+		boot_displays[i].boot_disp_en = true;
 	}
 	return 0;
 }
@@ -2046,6 +2099,8 @@
 
 	for (i = 0; i < MAX_DSI_ACTIVE_DISPLAY; i++) {
 		node = boot_displays[i].node;
+		if (!node)
+			continue;
 		ctrl_count = of_count_phandle_with_args(node, "qcom,dsi-ctrl",
 								NULL);
 
@@ -2087,11 +2142,12 @@
 
 	pr_err("index = %d\n", index);
 
-	if (boot_displays[index].node)
-		return boot_displays[index].node;
-	else if ((index == (MAX_DSI_ACTIVE_DISPLAY - 1))
-			&& (default_active_node))
-		return default_active_node;
+	if ((index == DSI_PRIMARY)
+			&& (primary_active_node))
+		return primary_active_node;
+	else if ((index == DSI_SECONDARY)
+			&& (secondary_active_node))
+		return secondary_active_node;
 	else
 		return NULL;
 }
@@ -2734,7 +2790,7 @@
 static ssize_t dsi_host_transfer(struct mipi_dsi_host *host,
 				 const struct mipi_dsi_msg *msg)
 {
-	struct dsi_display *display = to_dsi_display(host);
+	struct dsi_display *display;
 	int rc = 0, ret = 0;
 
 	if (!host || !msg) {
@@ -2742,6 +2798,14 @@
 		return 0;
 	}
 
+	display = to_dsi_display(host);
+
+	/* Avoid sending DCS commands when ESD recovery is pending */
+	if (atomic_read(&display->panel->esd_recovery_pending)) {
+		pr_debug("ESD recovery pending\n");
+		return 0;
+	}
+
 	rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
 			DSI_ALL_CLKS, DSI_CLK_ON);
 	if (rc) {
@@ -3040,6 +3104,12 @@
 	if ((clk & DSI_LINK_CLK) && (new_state == DSI_CLK_OFF) &&
 		(l_type && DSI_LINK_LP_CLK)) {
 		/*
+		 * If continuous clock is enabled then disable it
+		 * before entering into ULPS Mode.
+		 */
+		if (display->panel->host_config.force_hs_clk_lane)
+			_dsi_display_continuous_clk_ctrl(display, false);
+		/*
 		 * If ULPS feature is enabled, enter ULPS first.
 		 * However, when blanking the panel, we should enter ULPS
 		 * only if ULPS during suspend feature is enabled.
@@ -3170,6 +3240,9 @@
 				goto error;
 			}
 		}
+
+		if (display->panel->host_config.force_hs_clk_lane)
+			_dsi_display_continuous_clk_ctrl(display, true);
 	}
 
 	/* enable dsi to serve irqs */
@@ -4641,6 +4714,7 @@
 	.driver = {
 		.name = "msm-dsi-display",
 		.of_match_table = dsi_display_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
@@ -4648,8 +4722,7 @@
 {
 	int rc = 0;
 	struct dsi_display *display;
-	static bool display_from_cmdline, boot_displays_parsed;
-	static bool comp_add_success;
+	static bool boot_displays_parsed;
 	static struct device_node *primary_np, *secondary_np;
 
 	if (!pdev || !pdev->dev.of_node) {
@@ -4678,55 +4751,53 @@
 	display->cmdline_topology = NO_OVERRIDE;
 	display->cmdline_timing = 0;
 
-	if ((!display_from_cmdline) &&
-			(boot_displays[DSI_PRIMARY].boot_disp_en)) {
-		display->is_active = dsi_display_name_compare(pdev->dev.of_node,
-						display->name, DSI_PRIMARY);
-		if (display->is_active) {
-			if (comp_add_success) {
-				(void)_dsi_display_dev_deinit(main_display);
-				component_del(&main_display->pdev->dev,
-					      &dsi_display_comp_ops);
-				mutex_lock(&dsi_display_list_lock);
-				list_del(&main_display->list);
-				mutex_unlock(&dsi_display_list_lock);
-				comp_add_success = false;
-				default_active_node = NULL;
-				pr_debug("removed the existing comp ops\n");
-			}
-			/*
-			 * Need to add component for
-			 * the secondary DSI display
-			 * when more than one DSI display
-			 * is supported.
-			 */
-			pr_debug("cmdline primary dsi: %s\n",
-						display->name);
-			display_from_cmdline = true;
-			dsi_display_parse_cmdline_topology(display,
-					DSI_PRIMARY);
-			primary_np = pdev->dev.of_node;
+	if (boot_displays[DSI_PRIMARY].boot_disp_en && !primary_np &&
+		dsi_display_name_compare(pdev->dev.of_node,
+			display->name, DSI_PRIMARY)) {
+		if (primary_display) {
+			(void)_dsi_display_dev_deinit(primary_display);
+			component_del(&primary_display->pdev->dev,
+					&dsi_display_comp_ops);
+			mutex_lock(&dsi_display_list_lock);
+			list_del(&primary_display->list);
+			mutex_unlock(&dsi_display_list_lock);
+			primary_active_node = NULL;
+			pr_debug("removed the existing comp ops\n");
 		}
+		/*
+		 * Need to add component for
+		 * the secondary DSI display
+		 * when more than one DSI display
+		 * is supported.
+		 */
+		pr_debug("cmdline primary dsi: %s\n", display->name);
+		display->is_active = true;
+		dsi_display_parse_cmdline_topology(display, DSI_PRIMARY);
+		primary_np = pdev->dev.of_node;
 	}
 
-	if (boot_displays[DSI_SECONDARY].boot_disp_en) {
-		if (!secondary_np) {
-			if (dsi_display_name_compare(pdev->dev.of_node,
-				display->name, DSI_SECONDARY)) {
-				pr_debug("cmdline secondary dsi: %s\n",
-							display->name);
-				secondary_np = pdev->dev.of_node;
-				if (primary_np) {
-					if (validate_dsi_display_selection()) {
-					display->is_active = true;
-					dsi_display_parse_cmdline_topology
-						(display, DSI_SECONDARY);
-					} else {
-						boot_displays[DSI_SECONDARY]
-							.boot_disp_en = false;
-					}
-				}
+	if (boot_displays[DSI_SECONDARY].boot_disp_en && !secondary_np &&
+		dsi_display_name_compare(pdev->dev.of_node,
+			display->name, DSI_SECONDARY)) {
+		pr_debug("cmdline secondary dsi: %s\n", display->name);
+		if (validate_dsi_display_selection()) {
+			if (secondary_display) {
+				(void)_dsi_display_dev_deinit(
+						secondary_display);
+				component_del(&secondary_display->pdev->dev,
+						&dsi_display_comp_ops);
+				mutex_lock(&dsi_display_list_lock);
+				list_del(&secondary_display->list);
+				mutex_unlock(&dsi_display_list_lock);
+				secondary_active_node = NULL;
+				pr_debug("removed the existing comp ops\n");
 			}
+			display->is_active = true;
+			dsi_display_parse_cmdline_topology(display,
+					DSI_SECONDARY);
+			secondary_np = pdev->dev.of_node;
+		} else {
+			boot_displays[DSI_SECONDARY].boot_disp_en = false;
 		}
 	}
 	display->display_type = of_get_property(pdev->dev.of_node,
@@ -4741,12 +4812,18 @@
 	list_add(&display->list, &dsi_display_list);
 	mutex_unlock(&dsi_display_list_lock);
 
-	if (!display_from_cmdline)
+	if (!strcmp(display->display_type, "primary") && !primary_np)
+		display->is_active = of_property_read_bool(pdev->dev.of_node,
+						"qcom,dsi-display-active");
+	else if (strcmp(display->display_type, "primary") && !secondary_np)
 		display->is_active = of_property_read_bool(pdev->dev.of_node,
 						"qcom,dsi-display-active");
 
 	if (display->is_active) {
-		main_display = display;
+		if (!strcmp(display->display_type, "primary"))
+			primary_display = display;
+		else
+			secondary_display = display;
 		rc = _dsi_display_dev_init(display);
 		if (rc) {
 			pr_err("device init failed, rc=%d\n", rc);
@@ -4757,10 +4834,11 @@
 		if (rc)
 			pr_err("component add failed, rc=%d\n", rc);
 
-		comp_add_success = true;
 		pr_debug("Component_add success: %s\n", display->name);
-		if (!display_from_cmdline)
-			default_active_node = pdev->dev.of_node;
+		if (!strcmp(display->display_type, "primary"))
+			primary_active_node = pdev->dev.of_node;
+		else
+			secondary_active_node = pdev->dev.of_node;
 	}
 	return rc;
 }
@@ -5844,6 +5922,8 @@
 
 	mode = display->panel->cur_mode;
 
+	dsi_display_set_ctrl_esd_check_flag(display, false);
+
 	if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) {
 		if (display->is_cont_splash_enabled) {
 			pr_err("DMS is not supposed to be set on first frame\n");
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index 6b5bfb4..250314b 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -139,8 +139,12 @@
 		return;
 	}
 
-	if (!c_bridge || !c_bridge->display)
+	if (!c_bridge || !c_bridge->display || !c_bridge->display->panel) {
 		pr_err("Incorrect bridge details\n");
+		return;
+	}
+
+	atomic_set(&c_bridge->display->panel->esd_recovery_pending, 0);
 
 	/* By this point mode should have been validated through mode_fixup */
 	rc = dsi_display_set_mode(c_bridge->display,
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index dab85f4..1880ad1 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -377,7 +377,7 @@
 
 		if (r_config->sequence[i].sleep_ms)
 			usleep_range(r_config->sequence[i].sleep_ms * 1000,
-				     r_config->sequence[i].sleep_ms * 1000);
+				(r_config->sequence[i].sleep_ms * 1000) + 100);
 	}
 
 	if (gpio_is_valid(panel->bl_config.en_gpio)) {
@@ -1076,6 +1076,8 @@
 	host->append_tx_eot = of_property_read_bool(of_node,
 						"qcom,mdss-dsi-tx-eot-append");
 
+	host->force_hs_clk_lane = of_property_read_bool(of_node,
+					"qcom,mdss-dsi-force-clock-lane-hs");
 	return 0;
 }
 
@@ -3720,11 +3722,14 @@
 
 	mutex_lock(&panel->panel_lock);
 
-	rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_OFF);
-	if (rc) {
-		pr_err("[%s] failed to send DSI_CMD_SET_OFF cmds, rc=%d\n",
-		       panel->name, rc);
-		goto error;
+	/* Avoid sending panel off commands when ESD recovery is underway */
+	if (!atomic_read(&panel->esd_recovery_pending)) {
+		rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_OFF);
+		if (rc) {
+			pr_err("[%s] failed to send DSI_CMD_SET_OFF cmds, rc=%d\n",
+					panel->name, rc);
+			goto error;
+		}
 	}
 	panel->panel_initialized = false;
 
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
index c0ecb7f..f6a9c60 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
@@ -180,6 +180,7 @@
 	bool ulps_enabled;
 	bool ulps_suspend_enabled;
 	bool allow_phy_power_off;
+	atomic_t esd_recovery_pending;
 
 	bool panel_initialized;
 	bool te_using_watchdog_timer;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c
index e52a0f2..fdfaa5d 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -532,7 +532,7 @@
 	/* local vars */
 	int rc = 0;
 	u32 h_total, v_total;
-	u64 inter_num;
+	u32 inter_num;
 	u32 num_of_lanes = 0;
 	u32 bpp;
 	u64 x, y;
@@ -561,7 +561,7 @@
 	x = mult_frac(v_total * h_total, inter_num, num_of_lanes);
 	y = rounddown(x, 1);
 
-	clk_params.bitclk_mbps = rounddown(mult_frac(y, 1, 1000000), 1);
+	clk_params.bitclk_mbps = rounddown(DIV_ROUND_UP_ULL(y, 1000000), 1);
 	clk_params.escclk_numer = esc_clk_mhz;
 	clk_params.escclk_denom = esc_clk_mmss_cc_prediv;
 	clk_params.tlpx_numer_ns = tlpx_numer;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.h b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.h
index bae6d05..86ef6f3 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_calc.h
@@ -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
@@ -105,6 +105,9 @@
 		struct phy_timing_desc *desc);
 };
 
+#define roundup64(x, y) \
+	({ u64 _tmp = (x)+(y)-1; do_div(_tmp, y); _tmp * y; })
+
 /* DSI PHY timing functions for 14nm */
 void dsi_phy_hw_v2_0_get_default_phy_params(struct phy_clk_params *params);
 
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v2_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v2_0.c
index d3fb091..45f7577 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v2_0.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v2_0.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -31,7 +31,7 @@
 	s64 rec_temp2, rec_temp3;
 
 	rec_temp2 = (rec_temp1 - (11 * mult));
-	rec_temp3 = roundup(div_s64(rec_temp2, 8), mult);
+	rec_temp3 = roundup64(div_s64(rec_temp2, 8), mult);
 	return (div_s64(rec_temp3, mult) - 3);
 }
 
@@ -42,7 +42,7 @@
 
 	rec_temp1 = temp_mul + frac + (3 * mult);
 	rec_temp2 = div_s64(rec_temp1, 8);
-	rec_temp3 = roundup(rec_temp2, mult);
+	rec_temp3 = roundup64(rec_temp2, mult);
 
 	return div_s64(rec_temp3, mult);
 }
@@ -62,7 +62,7 @@
 	s64 rec_temp2, rec_temp3, rec_min;
 
 	rec_temp2 = temp1 - (11 * mult);
-	rec_temp3 = roundup((rec_temp2 / 8), mult);
+	rec_temp3 = roundup64((rec_temp2 / 8), mult);
 	rec_min = rec_temp3 - (3 * mult);
 	return div_s64(rec_min, mult);
 }
@@ -80,7 +80,8 @@
 
 	rec_temp1 = ((t->mipi_max * clk_params->bitclk_mbps) +
 		     (3 * clk_params->tlpx_numer_ns));
-	t->rec_max = (rec_temp1 / (8 * clk_params->tlpx_numer_ns));
+	t->rec_max = DIV_ROUND_UP_ULL(rec_temp1,
+				      (8 * clk_params->tlpx_numer_ns));
 }
 
 void dsi_phy_hw_v2_0_update_timing_params(
@@ -112,7 +113,7 @@
 		else
 			timing->lane[i][4] = desc->hs_rqst.reg_value;
 
-		timing->lane[i][5] = 0x3;
+		timing->lane[i][5] = 0x2;
 		timing->lane[i][6] = 0x4;
 		timing->lane[i][7] = 0xA0;
 		pr_debug("[%d][%d %d %d %d %d]\n", i, timing->lane[i][0],
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
index c97c87d..c0e9d44 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy_timing_v3_0.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -32,7 +32,7 @@
 	s64 rec_temp2, rec_temp3;
 
 	rec_temp2 = (rec_temp1 - mult);
-	rec_temp3 = roundup(div_s64(rec_temp2, 8), mult);
+	rec_temp3 = roundup64(div_s64(rec_temp2, 8), mult);
 	return (div_s64(rec_temp3, mult) - 1);
 }
 
@@ -43,7 +43,7 @@
 
 	rec_temp1 = temp_mul + frac;
 	rec_temp2 = div_s64(rec_temp1, 8);
-	rec_temp3 = roundup(rec_temp2, mult);
+	rec_temp3 = roundup64(rec_temp2, mult);
 	return (div_s64(rec_temp3, mult) - 1);
 }
 
@@ -59,7 +59,7 @@
 {
 	s64 rec_temp2, rec_min;
 
-	rec_temp2 = roundup((temp1 / 8), mult);
+	rec_temp2 = roundup64((temp1 / 8), mult);
 	rec_min = rec_temp2 - (1 * mult);
 	return div_s64(rec_min, mult);
 }
@@ -92,7 +92,7 @@
 	timing->lane_v3[6] = desc->hs_prepare.reg_value;
 	timing->lane_v3[7] = desc->hs_trail.reg_value;
 	timing->lane_v3[8] = desc->hs_rqst.reg_value;
-	timing->lane_v3[9] = 0x03;
+	timing->lane_v3[9] = 0x02;
 	timing->lane_v3[10] = 0x04;
 	timing->lane_v3[11] = 0x00;
 
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index ec572f8..e457322 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 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
@@ -169,6 +169,7 @@
 	.driver = {
 		.name = "msm_dsi",
 		.of_match_table = dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
index 2c9d116..3a0f180 100644
--- a/drivers/gpu/drm/msm/edp/edp.c
+++ b/drivers/gpu/drm/msm/edp/edp.c
@@ -128,6 +128,7 @@
 	.driver = {
 		.name = "msm_edp",
 		.of_match_table = dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 6279084..b8f5469 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016, 2018 The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
  *
@@ -646,6 +646,7 @@
 	.driver = {
 		.name = "hdmi_msm",
 		.of_match_table = msm_hdmi_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index f05d760..46b60b1 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016-2018 The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
  *
@@ -827,6 +827,7 @@
 	.driver = {
 		.name = "msm_mdp",
 		.of_match_table = mdp5_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 9eb62fe..0f565d3 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1994,6 +1994,7 @@
 		.name   = "msm_drm",
 		.of_match_table = dt_match,
 		.pm     = &msm_pm_ops,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index fcdddb3..978aba2 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -158,6 +158,7 @@
 	CRTC_PROP_CAPTURE_OUTPUT,
 
 	CRTC_PROP_ENABLE_SUI_ENHANCEMENT,
+	CRTC_PROP_IDLE_PC_STATE,
 
 	/* total # of properties */
 	CRTC_PROP_COUNT
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index a1c9d82..0c9c13c 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -151,8 +151,8 @@
 		}
 		dma_buf_begin_cpu_access(bo->dma_buf, DMA_BIDIRECTIONAL);
 		msm_fb->vaddr[i] = dma_buf_kmap(bo->dma_buf, 0);
-		DRM_INFO("FB[%u]: vaddr[%d]:%ux%u:0x%llx\n", fb->base.id, i,
-				fb->width, fb->height, (u64) msm_fb->vaddr[i]);
+		DRM_INFO("FB[%u]: vaddr[%d]:%ux%u\n", fb->base.id, i,
+			fb->width, fb->height);
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c
index 85867b2..ccd5e20 100644
--- a/drivers/gpu/drm/msm/msm_smmu.c
+++ b/drivers/gpu/drm/msm/msm_smmu.c
@@ -636,6 +636,7 @@
 	.driver = {
 		.name = "msmdrm_smmu",
 		.of_match_table = msm_smmu_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c
index 47ff024..8680449b 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.c
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c
@@ -282,7 +282,8 @@
 		return 0;
 	}
 
-	ret = copy_from_user(blob_ptr->data, (void *)val, blob_ptr->length);
+	ret = copy_from_user(blob_ptr->data, u64_to_user_ptr(val),
+			blob_ptr->length);
 	if (ret) {
 		DRM_ERROR("failed to get the property info ret %d", ret);
 		ret = -EFAULT;
@@ -1135,7 +1136,8 @@
 	if (!sde_crtc->num_mixers ||
 	    sde_crtc->num_mixers > ARRAY_SIZE(sde_crtc->mixers)) {
 		DRM_INFO("Invalid mixer config act cnt %d max cnt %ld\n",
-			sde_crtc->num_mixers, ARRAY_SIZE(sde_crtc->mixers));
+			sde_crtc->num_mixers,
+				(long int)ARRAY_SIZE(sde_crtc->mixers));
 		ret = -EPERM;
 		goto exit;
 	}
@@ -1295,6 +1297,33 @@
 	/* placeholder for operations needed during resume */
 }
 
+void sde_cp_crtc_clear(struct drm_crtc *crtc)
+{
+	struct sde_crtc *sde_crtc = NULL;
+	unsigned long flags;
+
+	if (!crtc) {
+		DRM_ERROR("crtc %pK\n", crtc);
+		return;
+	}
+	sde_crtc = to_sde_crtc(crtc);
+	if (!sde_crtc) {
+		DRM_ERROR("sde_crtc %pK\n", sde_crtc);
+		return;
+	}
+
+	mutex_lock(&sde_crtc->crtc_cp_lock);
+	list_del_init(&sde_crtc->active_list);
+	list_del_init(&sde_crtc->dirty_list);
+	list_del_init(&sde_crtc->ad_active);
+	list_del_init(&sde_crtc->ad_dirty);
+	mutex_unlock(&sde_crtc->crtc_cp_lock);
+
+	spin_lock_irqsave(&sde_crtc->spin_lock, flags);
+	list_del_init(&sde_crtc->user_event_list);
+	spin_unlock_irqrestore(&sde_crtc->spin_lock, flags);
+}
+
 static void dspp_pcc_install_property(struct drm_crtc *crtc)
 {
 	char feature_name[256];
@@ -1990,11 +2019,10 @@
 	struct sde_crtc *crtc;
 	struct drm_event event;
 	struct drm_msm_hist *hist_data;
-	struct drm_msm_hist tmp_hist_data;
 	struct msm_drm_private *priv;
 	struct sde_kms *kms;
 	int ret;
-	u32 i, j;
+	u32 i;
 
 	if (!crtc_drm) {
 		DRM_ERROR("invalid crtc %pK\n", crtc_drm);
@@ -2026,6 +2054,7 @@
 
 	/* read histogram data into blob */
 	hist_data = (struct drm_msm_hist *)crtc->hist_blob->data;
+	memset(hist_data->data, 0, sizeof(hist_data->data));
 	for (i = 0; i < crtc->num_mixers; i++) {
 		hw_dspp = crtc->mixers[i].hw_dspp;
 		if (!hw_dspp || !hw_dspp->ops.read_histogram) {
@@ -2035,14 +2064,7 @@
 						kms->core_client, false);
 			return;
 		}
-		if (!i) {
-			hw_dspp->ops.read_histogram(hw_dspp, hist_data);
-		} else {
-			/* Merge hist data for DSPP0 and DSPP1 */
-			hw_dspp->ops.read_histogram(hw_dspp, &tmp_hist_data);
-			for (j = 0; j < HIST_V_SIZE; j++)
-				hist_data->data[j] += tmp_hist_data.data[j];
-		}
+		hw_dspp->ops.read_histogram(hw_dspp, hist_data);
 	}
 
 	sde_power_resource_enable(&priv->phandle, kms->core_client,
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.h b/drivers/gpu/drm/msm/sde/sde_color_processing.h
index 620db26..fb8ee1f 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.h
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.h
@@ -116,6 +116,12 @@
 void sde_cp_crtc_resume(struct drm_crtc *crtc);
 
 /**
+ * sde_cp_crtc_clear: Clear the active list and dirty list of crtc features
+ * @crtc: Pointer to crtc.
+ */
+void sde_cp_crtc_clear(struct drm_crtc *crtc);
+
+/**
  * sde_cp_ad_interrupt: Api to enable/disable ad interrupt
  * @crtc: Pointer to crtc.
  * @en: Variable to enable/disable interrupt.
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index ab1d86b..9d7d1e0 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -1106,7 +1106,7 @@
 			goto end;
 		}
 
-		rc = copy_to_user((uint64_t __user *)val, &fence_fd,
+		rc = copy_to_user((uint64_t __user *)(uintptr_t)val, &fence_fd,
 			sizeof(uint64_t));
 		if (rc) {
 			SDE_ERROR("copy to user failed rc:%d\n", rc);
@@ -1117,7 +1117,8 @@
 		}
 		break;
 	case CONNECTOR_PROP_ROI_V1:
-		rc = _sde_connector_set_roi_v1(c_conn, c_state, (void *)val);
+		rc = _sde_connector_set_roi_v1(c_conn, c_state,
+				(void *)(uintptr_t)val);
 		if (rc)
 			SDE_ERROR_CONN(c_conn, "invalid roi_v1, rc: %d\n", rc);
 		break;
@@ -1140,7 +1141,7 @@
 
 	if (idx == CONNECTOR_PROP_HDR_METADATA) {
 		rc = _sde_connector_set_ext_hdr_info(c_conn,
-			c_state, (void *)val);
+			c_state, (void *)(uintptr_t)val);
 		if (rc)
 			SDE_ERROR_CONN(c_conn, "cannot set hdr info %d\n", rc);
 	}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 34a3d5f..8af8298 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -641,7 +641,7 @@
 static int _sde_debugfs_fps_status_show(struct seq_file *s, void *data)
 {
 	struct sde_crtc *sde_crtc;
-	unsigned int fps_int, fps_float;
+	u64 fps_int, fps_float;
 	ktime_t current_time_us;
 	u64 fps, diff_us;
 
@@ -670,7 +670,7 @@
 	fps_int = (unsigned int) sde_crtc->fps_info.measured_fps;
 	fps_float = do_div(fps_int, 10);
 
-	seq_printf(s, "fps: %d.%d\n", fps_int, fps_float);
+	seq_printf(s, "fps: %llu.%llu\n", fps_int, fps_float);
 
 	return 0;
 }
@@ -3689,6 +3689,7 @@
 	struct sde_kms *sde_kms;
 	struct sde_crtc_state *cstate;
 	bool is_error, reset_req;
+	enum sde_crtc_idle_pc_state idle_pc_state;
 
 	if (!crtc) {
 		SDE_ERROR("invalid argument\n");
@@ -3719,6 +3720,8 @@
 
 	is_error = _sde_crtc_prepare_for_kickoff_rot(dev, crtc);
 
+	idle_pc_state = sde_crtc_get_property(cstate, CRTC_PROP_IDLE_PC_STATE);
+
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		struct sde_encoder_kickoff_params params = { 0 };
 
@@ -3734,6 +3737,10 @@
 				crtc->state);
 		if (sde_encoder_prepare_for_kickoff(encoder, &params))
 			reset_req = true;
+
+		if (idle_pc_state != IDLE_PC_NONE)
+			sde_encoder_control_idle_pc(encoder,
+			    (idle_pc_state == IDLE_PC_ENABLE) ? true : false);
 	}
 
 	/*
@@ -4233,6 +4240,13 @@
 		sde_encoder_register_frame_event_callback(encoder, NULL, NULL);
 		cstate->rsc_client = NULL;
 		cstate->rsc_update = false;
+
+		/*
+		 * reset idle power-collapse to original state during suspend;
+		 * user-mode will change the state on resume, if required
+		 */
+		if (sde_kms->catalog->has_idle_pc)
+			sde_encoder_control_idle_pc(encoder, true);
 	}
 
 	if (sde_crtc->power_event)
@@ -4918,6 +4932,8 @@
 	sde_crtc = to_sde_crtc(crtc);
 	cstate = to_sde_crtc_state(crtc_state);
 
+	sde_cp_crtc_clear(crtc);
+
 	for (prop_idx = 0; prop_idx < CRTC_PROP_COUNT; prop_idx++) {
 		uint64_t val = cstate->property_values[prop_idx].value;
 		uint64_t def;
@@ -4974,6 +4990,12 @@
 		{CAPTURE_DSPP_OUT, "capture_pp_out"},
 	};
 
+	static const struct drm_prop_enum_list e_idle_pc_state[] = {
+		{IDLE_PC_NONE, "idle_pc_none"},
+		{IDLE_PC_ENABLE, "idle_pc_enable"},
+		{IDLE_PC_DISABLE, "idle_pc_disable"},
+	};
+
 	SDE_DEBUG("\n");
 
 	if (!crtc || !catalog) {
@@ -5053,6 +5075,12 @@
 		"enable_sui_enhancement", 0, 0, U64_MAX, 0,
 		CRTC_PROP_ENABLE_SUI_ENHANCEMENT);
 
+	if (catalog->has_idle_pc)
+		msm_property_install_enum(&sde_crtc->property_info,
+			"idle_pc_state", 0x0, 0, e_idle_pc_state,
+			ARRAY_SIZE(e_idle_pc_state),
+			CRTC_PROP_IDLE_PC_STATE);
+
 	if (catalog->has_cwb_support)
 		msm_property_install_enum(&sde_crtc->property_info,
 				"capture_mode", 0, 0, e_cwb_data_points,
@@ -5268,14 +5296,16 @@
 		_sde_crtc_set_input_fence_timeout(cstate);
 		break;
 	case CRTC_PROP_DIM_LAYER_V1:
-		_sde_crtc_set_dim_layer_v1(cstate, (void __user *)val);
+		_sde_crtc_set_dim_layer_v1(cstate,
+					(void __user *)(uintptr_t)val);
 		break;
 	case CRTC_PROP_ROI_V1:
-		ret = _sde_crtc_set_roi_v1(state, (void __user *)val);
+		ret = _sde_crtc_set_roi_v1(state,
+					(void __user *)(uintptr_t)val);
 		break;
 	case CRTC_PROP_DEST_SCALER:
 		ret = _sde_crtc_set_dest_scaler(sde_crtc, cstate,
-				(void __user *)val);
+				(void __user *)(uintptr_t)val);
 		break;
 	case CRTC_PROP_DEST_SCALER_LUT_ED:
 	case CRTC_PROP_DEST_SCALER_LUT_CIR:
@@ -5307,7 +5337,7 @@
 			goto exit;
 		}
 
-		ret = copy_to_user((uint64_t __user *)val, &fence_fd,
+		ret = copy_to_user((uint64_t __user *)(uintptr_t)val, &fence_fd,
 				sizeof(uint64_t));
 		if (ret) {
 			SDE_ERROR("copy to user failed rc:%d\n", ret);
@@ -5554,8 +5584,8 @@
 
 	if (sde_crtc->vblank_cb_count) {
 		ktime_t diff = ktime_sub(ktime_get(), sde_crtc->vblank_cb_time);
-		s64 diff_ms = ktime_to_ms(diff);
-		s64 fps = diff_ms ? DIV_ROUND_CLOSEST(
+		u32 diff_ms = ktime_to_ms(diff);
+		u64 fps = diff_ms ? DIV_ROUND_CLOSEST(
 				sde_crtc->vblank_cb_count * 1000, diff_ms) : 0;
 
 		seq_printf(s,
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 99177b1..709a51f 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -59,6 +59,18 @@
 };
 
 /**
+ * enum sde_crtc_idle_pc_state: states of idle power collapse
+ * @IDLE_PC_NONE: no-op
+ * @IDLE_PC_ENABLE: enable idle power-collapse
+ * @IDLE_PC_DISABLE: disable idle power-collapse
+ */
+enum sde_crtc_idle_pc_state {
+	IDLE_PC_NONE,
+	IDLE_PC_ENABLE,
+	IDLE_PC_DISABLE,
+};
+
+/**
  * @connectors    : Currently associated drm connectors for retire event
  * @num_connectors: Number of associated drm connectors for retire event
  * @list:	event list
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 73864b6..7f45e08 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -200,7 +200,8 @@
  * @disp_info:			local copy of msm_display_info struct
  * @misr_enable:		misr enable/disable status
  * @misr_frame_count:		misr frame count before start capturing the data
- * @idle_pc_supported:		indicate if idle power collaps is supported
+ * @idle_pc_enabled:		indicate if idle power collapse is enabled
+ *				currently. This can be controlled by user-mode
  * @rc_lock:			resource control mutex lock to protect
  *				virt encoder over various state changes
  * @rc_state:			resource controller state
@@ -250,7 +251,7 @@
 	bool misr_enable;
 	u32 misr_frame_count;
 
-	bool idle_pc_supported;
+	bool idle_pc_enabled;
 	struct mutex rc_lock;
 	enum sde_enc_rc_states rc_state;
 	struct kthread_delayed_work delayed_off_work;
@@ -1922,6 +1923,25 @@
 				&sde_enc->input_event_work);
 }
 
+void sde_encoder_control_idle_pc(struct drm_encoder *drm_enc, bool enable)
+{
+	struct sde_encoder_virt *sde_enc;
+
+	if (!drm_enc) {
+		SDE_ERROR("invalid encoder\n");
+		return;
+	}
+	sde_enc = to_sde_encoder_virt(drm_enc);
+
+	/* return early if there is no state change */
+	if (sde_enc->idle_pc_enabled == enable)
+		return;
+
+	sde_enc->idle_pc_enabled = enable;
+
+	SDE_DEBUG("idle-pc state:%d\n", sde_enc->idle_pc_enabled);
+	SDE_EVT32(sde_enc->idle_pc_enabled);
+}
 
 static int sde_encoder_resource_control(struct drm_encoder *drm_enc,
 		u32 sw_event)
@@ -1948,7 +1968,7 @@
 	 * when idle_pc is not supported, process only KICKOFF, STOP and MODESET
 	 * events and return early for other events (ie wb display).
 	 */
-	if (!sde_enc->idle_pc_supported &&
+	if (!sde_enc->idle_pc_enabled &&
 			(sw_event != SDE_ENC_RC_EVENT_KICKOFF &&
 			sw_event != SDE_ENC_RC_EVENT_PRE_MODESET &&
 			sw_event != SDE_ENC_RC_EVENT_POST_MODESET &&
@@ -1956,9 +1976,9 @@
 			sw_event != SDE_ENC_RC_EVENT_PRE_STOP))
 		return 0;
 
-	SDE_DEBUG_ENC(sde_enc, "sw_event:%d, idle_pc_supported:%d\n", sw_event,
-			sde_enc->idle_pc_supported);
-	SDE_EVT32_VERBOSE(DRMID(drm_enc), sw_event, sde_enc->idle_pc_supported,
+	SDE_DEBUG_ENC(sde_enc, "sw_event:%d, idle_pc:%d\n",
+			sw_event, sde_enc->idle_pc_enabled);
+	SDE_EVT32_VERBOSE(DRMID(drm_enc), sw_event, sde_enc->idle_pc_enabled,
 			sde_enc->rc_state, SDE_EVTLOG_FUNC_ENTRY);
 
 	switch (sw_event) {
@@ -2348,7 +2368,7 @@
 		break;
 	}
 
-	SDE_EVT32_VERBOSE(DRMID(drm_enc), sw_event, sde_enc->idle_pc_supported,
+	SDE_EVT32_VERBOSE(DRMID(drm_enc), sw_event, sde_enc->idle_pc_enabled,
 			sde_enc->rc_state, SDE_EVTLOG_FUNC_EXIT);
 	return 0;
 }
@@ -2689,14 +2709,12 @@
 	struct msm_compression_info *comp_info = NULL;
 	struct drm_display_mode *cur_mode = NULL;
 	struct msm_mode_info mode_info;
-	struct msm_display_info *disp_info;
 
 	if (!drm_enc) {
 		SDE_ERROR("invalid encoder\n");
 		return;
 	}
 	sde_enc = to_sde_encoder_virt(drm_enc);
-	disp_info = &sde_enc->disp_info;
 
 	if (!sde_kms_power_resource_is_enabled(drm_enc->dev)) {
 		SDE_ERROR("power resource is not enabled\n");
@@ -2817,14 +2835,14 @@
 
 	SDE_EVT32(DRMID(drm_enc));
 
+	if (sde_enc->input_handler)
+		input_unregister_handler(sde_enc->input_handler);
+
 	/* wait for idle */
 	sde_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE);
 
 	kthread_flush_work(&sde_enc->input_event_work);
 
-	if (sde_enc->input_handler)
-		input_unregister_handler(sde_enc->input_handler);
-
 	/*
 	 * For primary command mode encoders, execute the resource control
 	 * pre-stop operations before the physical encoders are disabled, to
@@ -4483,7 +4501,7 @@
 
 	if ((disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) ||
 	    (disp_info->capabilities & MSM_DISPLAY_CAP_VID_MODE))
-		sde_enc->idle_pc_supported = sde_kms->catalog->has_idle_pc;
+		sde_enc->idle_pc_enabled = sde_kms->catalog->has_idle_pc;
 
 	mutex_lock(&sde_enc->enc_lock);
 	for (i = 0; i < disp_info->num_of_h_tiles && !ret; i++) {
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.h b/drivers/gpu/drm/msm/sde/sde_encoder.h
index 42b9e58..c40db41 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.h
@@ -257,4 +257,11 @@
  */
 int sde_encoder_in_clone_mode(struct drm_encoder *enc);
 
+/**
+ * sde_encoder_control_idle_pc - control enable/disable of idle power collapse
+ * @drm_enc:    Pointer to drm encoder structure
+ * @enable:	enable/disable flag
+ */
+void sde_encoder_control_idle_pc(struct drm_encoder *enc, bool enable);
+
 #endif /* __SDE_ENCODER_H__ */
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 d363d62..74bf518 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -40,6 +40,20 @@
 #define POLL_TIME_USEC_FOR_LN_CNT 500
 #define MAX_POLL_CNT 10
 
+static bool _sde_encoder_phys_is_ppsplit(struct sde_encoder_phys *phys_enc)
+{
+	enum sde_rm_topology_name topology;
+
+	if (!phys_enc)
+		return false;
+
+	topology = sde_connector_get_topology_name(phys_enc->connector);
+	if (topology == SDE_RM_TOPOLOGY_PPSPLIT)
+		return true;
+
+	return false;
+}
+
 static bool sde_encoder_phys_vid_is_master(
 		struct sde_encoder_phys *phys_enc)
 {
@@ -313,12 +327,14 @@
 	if (!phys_enc->sde_kms->splash_data.cont_splash_en) {
 		SDE_EVT32(DRMID(phys_enc->parent), f.enable, f.fetch_start);
 
-		phys_enc->hw_ctl->ops.get_bitmask_intf(
-				phys_enc->hw_ctl, &flush_mask,
-				vid_enc->hw_intf->idx);
-		phys_enc->hw_ctl->ops.update_pending_flush(
-				phys_enc->hw_ctl, flush_mask);
-
+		if (!_sde_encoder_phys_is_ppsplit(phys_enc) ||
+			sde_encoder_phys_vid_is_master(phys_enc)) {
+			phys_enc->hw_ctl->ops.get_bitmask_intf(
+					phys_enc->hw_ctl, &flush_mask,
+					vid_enc->hw_intf->idx);
+			phys_enc->hw_ctl->ops.update_pending_flush(
+					phys_enc->hw_ctl, flush_mask);
+		}
 		spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
 		vid_enc->hw_intf->ops.setup_rot_start(vid_enc->hw_intf, &f);
 		spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
@@ -496,20 +512,6 @@
 			phys_enc);
 }
 
-static bool _sde_encoder_phys_is_ppsplit(struct sde_encoder_phys *phys_enc)
-{
-	enum sde_rm_topology_name topology;
-
-	if (!phys_enc)
-		return false;
-
-	topology = sde_connector_get_topology_name(phys_enc->connector);
-	if (topology == SDE_RM_TOPOLOGY_PPSPLIT)
-		return true;
-
-	return false;
-}
-
 static bool _sde_encoder_phys_is_dual_ctl(struct sde_encoder_phys *phys_enc)
 {
 	enum sde_rm_topology_name topology;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
index 82dd64a..4bbcb3a 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
@@ -32,7 +32,6 @@
 
 #define TO_S15D16(_x_)	((_x_) << 7)
 
-#define MULTIPLE_CONN_DETECTED(x) (x > 1)
 /**
  * sde_rgb2yuv_601l - rgb to yuv color space conversion matrix
  *
@@ -453,11 +452,9 @@
 static void _sde_enc_phys_wb_detect_cwb(struct sde_encoder_phys *phys_enc,
 		struct drm_crtc_state *crtc_state)
 {
-	struct drm_connector *conn;
-	struct drm_connector_state *conn_state;
+	struct drm_encoder *encoder;
 	struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc);
 	const struct sde_wb_cfg *wb_cfg = wb_enc->hw_wb->caps;
-	int conn_count = 0;
 
 	phys_enc->in_clone_mode = false;
 
@@ -465,21 +462,16 @@
 	if (!(wb_cfg->features & BIT(SDE_WB_HAS_CWB)))
 		return;
 
-	/* Count the number of connectors on the given crtc */
-	drm_for_each_connector(conn, crtc_state->crtc->dev) {
-		conn_state =
-			drm_atomic_get_connector_state(crtc_state->state, conn);
-		if ((conn->state && conn->state->crtc == crtc_state->crtc) ||
-				(conn_state &&
-				 conn_state->crtc == crtc_state->crtc))
-			conn_count++;
+	 /* if any other encoder is connected to same crtc enable clone mode*/
+	drm_for_each_encoder(encoder, crtc_state->crtc->dev) {
+		if (encoder->crtc != crtc_state->crtc)
+			continue;
+		if (phys_enc->parent != encoder) {
+			phys_enc->in_clone_mode = true;
+			break;
+		}
 	}
 
-
-	/* Enable clone mode If crtc has multiple connectors & one is WB */
-	if (MULTIPLE_CONN_DETECTED(conn_count))
-		phys_enc->in_clone_mode = true;
-
 	SDE_DEBUG("detect CWB - status:%d\n", phys_enc->in_clone_mode);
 }
 
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c b/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c
index c7989cd..61076cf 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_color_processing_v1_7.c
@@ -951,8 +951,9 @@
 	offset = ctx->cap->sblk->hist.base + PA_HIST_DATA_DSPP_OFF;
 	offset_ctl = ctx->cap->sblk->hist.base + PA_HIST_CTRL_DSPP_OFF;
 
+	/* collect hist data for given DSPPs */
 	for (i = 0; i < HIST_V_SIZE; i++)
-		hist_data->data[i] = SDE_REG_READ(&ctx->hw, offset + i * 4) &
+		hist_data->data[i] += SDE_REG_READ(&ctx->hw, offset + i * 4) &
 					REG_MASK(24);
 
 	/* unlock hist buffer */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
index 02d593b..a88f513 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1.c
@@ -187,7 +187,7 @@
 			*decode_sel |= BIT(21);
 			break;
 		default:
-			DRM_ERROR("block not supported %zx\n", BIT(i));
+			DRM_ERROR("block not supported %zx\n", (size_t)BIT(i));
 			break;
 		}
 	}
@@ -292,7 +292,7 @@
 
 	if (cfg->wrap_size < WRAP_MIN_SIZE || cfg->wrap_size > WRAP_MAX_SIZE) {
 		DRM_ERROR("invalid wrap sz %d min %d max %zd\n",
-			cfg->wrap_size, WRAP_MIN_SIZE, WRAP_MAX_SIZE);
+			cfg->wrap_size, WRAP_MIN_SIZE, (size_t)WRAP_MAX_SIZE);
 		rc = -EINVAL;
 	}
 
@@ -319,7 +319,7 @@
 	if ((SIZE_DWORD(cfg->data_size)) > MAX_DWORDS_SZ ||
 	    NOT_WORD_ALIGNED(cfg->data_size)) {
 		DRM_ERROR("Invalid data size %d max %zd align %x\n",
-			cfg->data_size, MAX_DWORDS_SZ,
+			cfg->data_size, (size_t)MAX_DWORDS_SZ,
 			NOT_WORD_ALIGNED(cfg->data_size));
 		return -EINVAL;
 	}
@@ -327,7 +327,7 @@
 	if (cfg->blk_offset > MAX_RELATIVE_OFF ||
 			NOT_WORD_ALIGNED(cfg->blk_offset)) {
 		DRM_ERROR("invalid offset %d max %zd align %x\n",
-				cfg->blk_offset, MAX_RELATIVE_OFF,
+				cfg->blk_offset, (size_t)MAX_RELATIVE_OFF,
 				NOT_WORD_ALIGNED(cfg->blk_offset));
 		return -EINVAL;
 	}
@@ -391,7 +391,7 @@
 
 	if (cfg->dma_buf->iova & GUARD_BYTES || !cfg->dma_buf->vaddr) {
 		DRM_ERROR("iova not aligned to %zx iova %x kva %pK",
-				ADDR_ALIGN, cfg->dma_buf->iova,
+				(size_t)ADDR_ALIGN, cfg->dma_buf->iova,
 				cfg->dma_buf->vaddr);
 		return -EINVAL;
 	}
@@ -449,8 +449,8 @@
 				(WRITE_TRIGGER);
 
 	if (cfg->dma_buf->iova & GUARD_BYTES) {
-		DRM_ERROR("Address is not aligned to %zx iova %x", ADDR_ALIGN,
-				cfg->dma_buf->iova);
+		DRM_ERROR("Address is not aligned to %zx iova %x",
+				(size_t)ADDR_ALIGN, cfg->dma_buf->iova);
 		return -EINVAL;
 	}
 
@@ -462,7 +462,8 @@
 	if (SIZE_DWORD(cfg->dma_buf->index) > MAX_DWORDS_SZ ||
 			!cfg->dma_buf->index) {
 		DRM_ERROR("invalid dword size %zd max %zd\n",
-			SIZE_DWORD(cfg->dma_buf->index), MAX_DWORDS_SZ);
+			(size_t)SIZE_DWORD(cfg->dma_buf->index),
+				(size_t)MAX_DWORDS_SZ);
 		return -EINVAL;
 	}
 	return 0;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_rot.c b/drivers/gpu/drm/msm/sde/sde_hw_rot.c
index facec3d..9767832 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_rot.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_rot.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
@@ -567,9 +567,14 @@
 	}
 
 	/* adjust bw for scaling */
-	if (data->dst_rect_h)
-		*prefill_bw = mult_frac(data->prefill_bw, data->crtc_h,
+	if (data->dst_rect_h) {
+		u64 temp;
+
+		temp = DIV_ROUND_UP_ULL(data->prefill_bw,
 				data->dst_rect_h);
+		*prefill_bw = temp * data->crtc_h;
+	}
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index 356f9ef..10ed954 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -865,8 +865,9 @@
 	}
 
 	if (cfg->time) {
-		ts_bytes = mult_frac(TS_CLK * 1000000ULL, cfg->size,
-				cfg->time);
+		u64 temp = DIV_ROUND_UP_ULL(TS_CLK * 1000000ULL, cfg->time);
+
+		ts_bytes = temp * cfg->size;
 		if (ts_bytes > SSPP_TRAFFIC_SHAPER_BPC_MAX)
 			ts_bytes = SSPP_TRAFFIC_SHAPER_BPC_MAX;
 	}
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index c2fffef..9a4c785 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -1686,6 +1686,16 @@
 	drm_for_each_crtc(crtc, dev)
 		sde_crtc_timeline_status(crtc);
 
+	if (mutex_is_locked(&dev->mode_config.mutex)) {
+		/*
+		 *Probably locked from last close dumping status anyway
+		 */
+		SDE_ERROR("dumping conn_timeline without mode_config lock\n");
+		drm_for_each_connector(conn, dev)
+			sde_conn_timeline_status(conn);
+		return;
+	}
+
 	mutex_lock(&dev->mode_config.mutex);
 	drm_for_each_connector(conn, dev)
 		sde_conn_timeline_status(conn);
@@ -3293,6 +3303,22 @@
 		goto power_error;
 	}
 
+	sde_kms->splash_data.resource_handoff_pending = true;
+
+	rc = _sde_kms_mmu_init(sde_kms);
+	if (rc) {
+		SDE_ERROR("sde_kms_mmu_init failed: %d\n", rc);
+		goto power_error;
+	}
+
+	/* Initialize reg dma block which is a singleton */
+	rc = sde_reg_dma_init(sde_kms->reg_dma, sde_kms->catalog,
+			sde_kms->dev);
+	if (rc) {
+		SDE_ERROR("failed: reg dma init failed\n");
+		goto power_error;
+	}
+
 	sde_dbg_init_dbg_buses(sde_kms->core_rev);
 
 	rm = &sde_kms->rm;
@@ -3322,21 +3348,6 @@
 					&sde_kms->splash_data,
 					sde_kms->catalog);
 
-	sde_kms->splash_data.resource_handoff_pending = true;
-
-	/* Initialize reg dma block which is a singleton */
-	rc = sde_reg_dma_init(sde_kms->reg_dma, sde_kms->catalog,
-			sde_kms->dev);
-	if (rc) {
-		SDE_ERROR("failed: reg dma init failed\n");
-		goto power_error;
-	}
-
-	rc = _sde_kms_mmu_init(sde_kms);
-	if (rc) {
-		SDE_ERROR("sde_kms_mmu_init failed: %d\n", rc);
-		goto power_error;
-	}
 	sde_kms->hw_mdp = sde_rm_get_mdp(&sde_kms->rm);
 	if (IS_ERR_OR_NULL(sde_kms->hw_mdp)) {
 		rc = PTR_ERR(sde_kms->hw_mdp);
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index dc55ad5..be6e756 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -831,7 +831,6 @@
 		input_fence = pstate->input_fence;
 
 		if (input_fence) {
-			psde->is_error = false;
 			prefix = sde_sync_get_name_prefix(input_fence);
 			rc = sde_sync_wait(input_fence, wait_ms);
 
@@ -971,8 +970,15 @@
 	ret = sde_format_populate_layout(aspace, fb, &pipe_cfg->layout);
 	if (ret == -EAGAIN)
 		SDE_DEBUG_PLANE(psde, "not updating same src addrs\n");
-	else if (ret)
+	else if (ret) {
 		SDE_ERROR_PLANE(psde, "failed to get format layout, %d\n", ret);
+
+		/*
+		 * Force solid fill color on error. This is to prevent
+		 * smmu faults during secure session transition.
+		 */
+		psde->is_error = true;
+	}
 	else if (psde->pipe_hw->ops.setup_sourceaddress) {
 		SDE_EVT32_VERBOSE(psde->pipe_hw->idx,
 				pipe_cfg->layout.width,
@@ -1088,6 +1094,12 @@
 		&& (src_w == dst_w))
 		return;
 
+	SDE_DEBUG_PLANE(psde,
+		"setting bilinear: src:%dx%d dst:%dx%d chroma:%dx%d fmt:%x\n",
+			src_w, src_h, dst_w, dst_h,
+			chroma_subsmpl_v, chroma_subsmpl_h,
+			fmt->base.pixel_format);
+
 	scale_cfg->dst_width = dst_w;
 	scale_cfg->dst_height = dst_h;
 	scale_cfg->y_rgb_filter_cfg = SDE_SCALE_BIL;
@@ -2055,19 +2067,19 @@
 		return;
 
 	fbo = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
-			(u64) &rstate->rot_hw->base);
+			(u64)(uintptr_t) &rstate->rot_hw->base);
 	fb = sde_crtc_res_get(cstate, SDE_CRTC_RES_ROT_OUT_FB,
-			(u64) &rstate->rot_hw->base);
+			(u64)(uintptr_t) &rstate->rot_hw->base);
 	if (fb && fbo) {
 		SDE_DEBUG("plane%d.%d get fb/fbo\n", plane->base.id,
 				rstate->sequence_id);
 	} else if (fbo) {
 		sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
-				(u64) &rstate->rot_hw->base);
+				(u64)(uintptr_t) &rstate->rot_hw->base);
 		fbo = NULL;
 	} else if (fb) {
 		sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
-				(u64) &rstate->rot_hw->base);
+				(u64)(uintptr_t) &rstate->rot_hw->base);
 		fb = NULL;
 	}
 
@@ -2136,7 +2148,7 @@
 		}
 
 		ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
-				(u64) &new_rstate->rot_hw->base,
+				(u64)(uintptr_t) &new_rstate->rot_hw->base,
 				new_rstate->out_fbo, &fbo_res_ops);
 		if (ret) {
 			SDE_ERROR("failed to add crtc resource\n");
@@ -2154,7 +2166,7 @@
 				new_rstate->out_fb->base.id);
 
 		ret = sde_crtc_res_add(cstate, SDE_CRTC_RES_ROT_OUT_FB,
-				(u64) &new_rstate->rot_hw->base,
+				(u64)(uintptr_t) &new_rstate->rot_hw->base,
 				new_rstate->out_fb, &fb_res_ops);
 		if (ret) {
 			SDE_ERROR("failed to add crtc resource %d\n", ret);
@@ -2197,12 +2209,12 @@
 	msm_framebuffer_cleanup(new_state->fb, new_pstate->aspace);
 error_prepare_input_buffer:
 	sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
-			(u64) &new_rstate->rot_hw->base);
+			(u64)(uintptr_t) &new_rstate->rot_hw->base);
 error_create_fb_res:
 	new_rstate->out_fb = NULL;
 error_create_fb:
 	sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
-			(u64) &new_rstate->rot_hw->base);
+			(u64)(uintptr_t) &new_rstate->rot_hw->base);
 error_create_fbo_res:
 	new_rstate->out_fbo = NULL;
 error_create_fbo:
@@ -2252,10 +2264,10 @@
 			msm_framebuffer_cleanup(old_rstate->out_fb,
 					old_pstate->aspace);
 			sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
-					(u64) &old_rstate->rot_hw->base);
+				(u64)(uintptr_t) &old_rstate->rot_hw->base);
 			old_rstate->out_fb = NULL;
 			sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
-					(u64) &old_rstate->rot_hw->base);
+				(u64)(uintptr_t) &old_rstate->rot_hw->base);
 			old_rstate->out_fbo = NULL;
 		}
 
@@ -2318,7 +2330,7 @@
 				state->fb ? state->fb->base.id : -1);
 
 		hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
-				(u64) state->fb);
+				(u64)(uintptr_t) state->fb);
 		if (!hw_blk) {
 			SDE_ERROR("plane%d.%d no available rotator, fb %d\n",
 					plane->base.id, rstate->sequence_id,
@@ -2334,7 +2346,7 @@
 			SDE_ERROR("plane%d.%d invalid rotator ops\n",
 					plane->base.id, rstate->sequence_id);
 			sde_crtc_res_put(cstate,
-					SDE_HW_BLK_ROT, (u64) state->fb);
+				SDE_HW_BLK_ROT, (u64)(uintptr_t) state->fb);
 			rstate->rot_hw = NULL;
 			return -EINVAL;
 		}
@@ -2385,10 +2397,10 @@
 					rstate->sequence_id, fb_id);
 
 			sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FB,
-					(u64) &rstate->rot_hw->base);
+					(u64)(uintptr_t) &rstate->rot_hw->base);
 			rstate->out_fb = NULL;
 			sde_crtc_res_put(cstate, SDE_CRTC_RES_ROT_OUT_FBO,
-					(u64) &rstate->rot_hw->base);
+					(u64)(uintptr_t) &rstate->rot_hw->base);
 			rstate->out_fbo = NULL;
 		}
 
@@ -3029,7 +3041,7 @@
 				state->fb ? state->fb->base.id : -1);
 
 		hw_blk = sde_crtc_res_get(cstate, SDE_HW_BLK_ROT,
-				(u64) state->fb);
+				(u64)(uintptr_t) state->fb);
 		if (!hw_blk) {
 			SDE_ERROR("plane%d.%d no available rotator, fb %d\n",
 					plane->base.id, rstate->sequence_id,
@@ -3574,17 +3586,16 @@
 		ret = -EINVAL;
 
 	/* decimation validation */
-	} else if (deci_w || deci_h) {
-		if ((deci_w > psde->pipe_sblk->maxhdeciexp) ||
-			(deci_h > psde->pipe_sblk->maxvdeciexp)) {
-			SDE_ERROR_PLANE(psde,
-					"too much decimation requested\n");
-			ret = -EINVAL;
-		} else if (fmt->fetch_mode != SDE_FETCH_LINEAR) {
-			SDE_ERROR_PLANE(psde,
-					"decimation requires linear fetch\n");
-			ret = -EINVAL;
-		}
+	} else if ((deci_w || deci_h)
+			&& ((deci_w > psde->pipe_sblk->maxhdeciexp)
+				|| (deci_h > psde->pipe_sblk->maxvdeciexp))) {
+		SDE_ERROR_PLANE(psde, "too much decimation requested\n");
+		ret = -EINVAL;
+
+	} else if ((deci_w || deci_h)
+			&& (fmt->fetch_mode != SDE_FETCH_LINEAR)) {
+		SDE_ERROR_PLANE(psde, "decimation requires linear fetch\n");
+		ret = -EINVAL;
 
 	} else if (!(psde->features & SDE_SSPP_SCALER) &&
 		((src.w != dst.w) || (src.h != dst.h))) {
@@ -4666,19 +4677,20 @@
 				_sde_plane_set_input_fence(psde, pstate, val);
 				break;
 			case PLANE_PROP_CSC_V1:
-				_sde_plane_set_csc_v1(psde, (void *)val);
+				_sde_plane_set_csc_v1(psde,
+						(void *)(uintptr_t)val);
 				break;
 			case PLANE_PROP_SCALER_V1:
 				_sde_plane_set_scaler_v1(psde, pstate,
-						(void *)val);
+						(void *)(uintptr_t)val);
 				break;
 			case PLANE_PROP_SCALER_V2:
 				_sde_plane_set_scaler_v2(psde, pstate,
-						(void *)val);
+						(void *)(uintptr_t)val);
 				break;
 			case PLANE_PROP_EXCL_RECT_V1:
 				_sde_plane_set_excl_rect_v1(psde, pstate,
-						(void *)val);
+						(void *)(uintptr_t)val);
 				break;
 			default:
 				/* nothing to do */
diff --git a/drivers/gpu/drm/msm/sde/sde_wb.c b/drivers/gpu/drm/msm/sde/sde_wb.c
index 71c8b63..61588bd9 100644
--- a/drivers/gpu/drm/msm/sde/sde_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_wb.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
@@ -816,6 +816,7 @@
 	.driver = {
 		.name = "sde_wb",
 		.of_match_table = dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/gpu/drm/msm/sde_dbg.c b/drivers/gpu/drm/msm/sde_dbg.c
index 758cc53..2e1422f 100644
--- a/drivers/gpu/drm/msm/sde_dbg.c
+++ b/drivers/gpu/drm/msm/sde_dbg.c
@@ -2129,7 +2129,8 @@
 
 	if (in_log)
 		dev_info(sde_dbg_base.dev, "%s: start_offset 0x%lx len 0x%zx\n",
-				dump_name, addr - base_addr, len_bytes);
+				dump_name, (unsigned long)(addr - base_addr),
+					len_bytes);
 
 	len_align = (len_bytes + REG_DUMP_ALIGN - 1) / REG_DUMP_ALIGN;
 	len_padded = len_align * REG_DUMP_ALIGN;
@@ -2147,7 +2148,7 @@
 			dev_info(sde_dbg_base.dev,
 				"%s: start_addr:0x%pK len:0x%x reg_offset=0x%lx\n",
 				dump_name, dump_addr, len_padded,
-				addr - base_addr);
+				(unsigned long)(addr - base_addr));
 		} else {
 			in_mem = 0;
 			pr_err("dump_mem: kzalloc fails!\n");
@@ -2173,7 +2174,8 @@
 		if (in_log)
 			dev_info(sde_dbg_base.dev,
 					"0x%lx : %08x %08x %08x %08x\n",
-					addr - base_addr, x0, x4, x8, xc);
+					(unsigned long)(addr - base_addr),
+					x0, x4, x8, xc);
 
 		if (dump_addr) {
 			dump_addr[i * 4] = x0;
diff --git a/drivers/gpu/drm/msm/sde_io_util.c b/drivers/gpu/drm/msm/sde_io_util.c
index d5a438e..f830010 100644
--- a/drivers/gpu/drm/msm/sde_io_util.c
+++ b/drivers/gpu/drm/msm/sde_io_util.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2012-2015, 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -230,7 +231,7 @@
 			need_sleep = !regulator_is_enabled(in_vreg[i].vreg);
 			if (in_vreg[i].pre_on_sleep && need_sleep)
 				usleep_range(in_vreg[i].pre_on_sleep * 1000,
-					in_vreg[i].pre_on_sleep * 1000);
+					(in_vreg[i].pre_on_sleep * 1000) + 10);
 			rc = regulator_set_load(in_vreg[i].vreg,
 				in_vreg[i].enable_load);
 			if (rc < 0) {
@@ -242,7 +243,7 @@
 			rc = regulator_enable(in_vreg[i].vreg);
 			if (in_vreg[i].post_on_sleep && need_sleep)
 				usleep_range(in_vreg[i].post_on_sleep * 1000,
-					in_vreg[i].post_on_sleep * 1000);
+					(in_vreg[i].post_on_sleep * 1000) + 10);
 			if (rc < 0) {
 				DEV_ERR("%pS->%s: %s enable failed\n",
 					__builtin_return_address(0), __func__,
@@ -254,13 +255,13 @@
 		for (i = num_vreg-1; i >= 0; i--) {
 			if (in_vreg[i].pre_off_sleep)
 				usleep_range(in_vreg[i].pre_off_sleep * 1000,
-					in_vreg[i].pre_off_sleep * 1000);
+					(in_vreg[i].pre_off_sleep * 1000) + 10);
 			regulator_set_load(in_vreg[i].vreg,
 				in_vreg[i].disable_load);
 			regulator_disable(in_vreg[i].vreg);
 			if (in_vreg[i].post_off_sleep)
 				usleep_range(in_vreg[i].post_off_sleep * 1000,
-					in_vreg[i].post_off_sleep * 1000);
+				(in_vreg[i].post_off_sleep * 1000) + 10);
 		}
 	}
 	return rc;
@@ -272,13 +273,13 @@
 	for (i--; i >= 0; i--) {
 		if (in_vreg[i].pre_off_sleep)
 			usleep_range(in_vreg[i].pre_off_sleep * 1000,
-				in_vreg[i].pre_off_sleep * 1000);
+				(in_vreg[i].pre_off_sleep * 1000) + 10);
 		regulator_set_load(in_vreg[i].vreg,
 			in_vreg[i].disable_load);
 		regulator_disable(in_vreg[i].vreg);
 		if (in_vreg[i].post_off_sleep)
 			usleep_range(in_vreg[i].post_off_sleep * 1000,
-				in_vreg[i].post_off_sleep * 1000);
+				(in_vreg[i].post_off_sleep * 1000) + 10);
 	}
 
 	return rc;
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index 6626cb33..721e278 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -1454,6 +1454,7 @@
 	.driver     = {
 		.name   = "sde_rsc",
 		.of_match_table = dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 757f9d73..9e47f97 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -3424,6 +3424,47 @@
 	return status;
 }
 
+/**
+ * adreno_device_private_create(): Allocate an adreno_device_private structure
+ */
+static struct kgsl_device_private *adreno_device_private_create(void)
+{
+	struct adreno_device_private *adreno_priv =
+			kzalloc(sizeof(*adreno_priv), GFP_KERNEL);
+
+	if (adreno_priv) {
+		INIT_LIST_HEAD(&adreno_priv->perfcounter_list);
+		return &adreno_priv->dev_priv;
+	}
+	return NULL;
+}
+
+/**
+ * adreno_device_private_destroy(): Destroy an adreno_device_private structure
+ * and release the perfcounters held by the kgsl fd.
+ * @dev_priv: The kgsl device private structure
+ */
+static void adreno_device_private_destroy(struct kgsl_device_private *dev_priv)
+{
+	struct kgsl_device *device = dev_priv->device;
+	struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+	struct adreno_device_private *adreno_priv =
+		container_of(dev_priv, struct adreno_device_private,
+		dev_priv);
+	struct adreno_perfcounter_list_node *p, *tmp;
+
+	mutex_lock(&device->mutex);
+	list_for_each_entry_safe(p, tmp, &adreno_priv->perfcounter_list, node) {
+		adreno_perfcounter_put(adreno_dev, p->groupid,
+					p->countable, PERFCOUNTER_FLAG_NONE);
+		list_del(&p->node);
+		kfree(p);
+	}
+	mutex_unlock(&device->mutex);
+
+	kfree(adreno_priv);
+}
+
 static inline s64 adreno_ticks_to_us(u32 ticks, u32 freq)
 {
 	freq /= 1000000;
@@ -3705,6 +3746,8 @@
 	.snapshot = adreno_snapshot,
 	.irq_handler = adreno_irq_handler,
 	.drain = adreno_drain,
+	.device_private_create = adreno_device_private_create,
+	.device_private_destroy = adreno_device_private_destroy,
 	/* Optional functions */
 	.snapshot_gmu = adreno_snapshot_gmu,
 	.drawctxt_create = adreno_drawctxt_create,
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 8e21958..fc32fb9 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -327,6 +327,29 @@
 };
 
 /**
+ * struct adreno_perfcounter_list_node - struct to store perfcounters
+ * allocated by a process on a kgsl fd.
+ * @groupid: groupid of the allocated perfcounter
+ * @countable: countable assigned to the allocated perfcounter
+ * @node: list node for perfcounter_list of a process
+ */
+struct adreno_perfcounter_list_node {
+	unsigned int groupid;
+	unsigned int countable;
+	struct list_head node;
+};
+
+/**
+ * struct adreno_device_private - Adreno private structure per fd
+ * @dev_priv: the kgsl device private structure
+ * @perfcounter_list: list of perfcounters used by the process
+ */
+struct adreno_device_private {
+	struct kgsl_device_private dev_priv;
+	struct list_head perfcounter_list;
+};
+
+/**
  * struct adreno_gpu_core - A specific GPU core definition
  * @gpurev: Unique GPU revision identifier
  * @core: Match for the core version of the GPU
@@ -1873,8 +1896,11 @@
 		ret = gpudev->oob_set(adreno_dev, OOB_PERFCNTR_SET_MASK,
 				OOB_PERFCNTR_CHECK_MASK,
 				OOB_PERFCNTR_CLEAR_MASK);
-		if (ret)
+		if (ret) {
+			adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT);
+			adreno_dispatcher_schedule(KGSL_DEVICE(adreno_dev));
 			kgsl_active_count_put(KGSL_DEVICE(adreno_dev));
+		}
 	}
 
 	return ret;
diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c
index 6c8e664..132fb02 100644
--- a/drivers/gpu/msm/adreno_a6xx_preempt.c
+++ b/drivers/gpu/msm/adreno_a6xx_preempt.c
@@ -49,8 +49,13 @@
 				OOB_PREEMPTION_SET_MASK,
 				OOB_PREEMPTION_CHECK_MASK,
 				OOB_PREEMPTION_CLEAR_MASK);
-			if (status)
+			if (status) {
+				adreno_set_gpu_fault(adreno_dev,
+					ADRENO_GMU_FAULT);
+				adreno_dispatcher_schedule(
+					KGSL_DEVICE(adreno_dev));
 				return;
+			}
 		}
 	}
 
diff --git a/drivers/gpu/msm/adreno_ioctl.c b/drivers/gpu/msm/adreno_ioctl.c
index aa8c2bf..82629c6 100644
--- a/drivers/gpu/msm/adreno_ioctl.c
+++ b/drivers/gpu/msm/adreno_ioctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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,50 @@
 #include "adreno.h"
 #include "adreno_a5xx.h"
 
+/*
+ * Add a perfcounter to the per-fd list.
+ * Call with the device mutex held
+ */
+static int adreno_process_perfcounter_add(struct kgsl_device_private *dev_priv,
+	unsigned int groupid, unsigned int countable)
+{
+	struct adreno_device_private *adreno_priv = container_of(dev_priv,
+		struct adreno_device_private, dev_priv);
+	struct adreno_perfcounter_list_node *perfctr;
+
+	perfctr = kmalloc(sizeof(*perfctr), GFP_KERNEL);
+	if (!perfctr)
+		return -ENOMEM;
+
+	perfctr->groupid = groupid;
+	perfctr->countable = countable;
+
+	/* add the pair to process perfcounter list */
+	list_add(&perfctr->node, &adreno_priv->perfcounter_list);
+	return 0;
+}
+
+/*
+ * Remove a perfcounter from the per-fd list.
+ * Call with the device mutex held
+ */
+static int adreno_process_perfcounter_del(struct kgsl_device_private *dev_priv,
+	unsigned int groupid, unsigned int countable)
+{
+	struct adreno_device_private *adreno_priv = container_of(dev_priv,
+		struct adreno_device_private, dev_priv);
+	struct adreno_perfcounter_list_node *p;
+
+	list_for_each_entry(p, &adreno_priv->perfcounter_list, node) {
+		if (p->groupid == groupid && p->countable == countable) {
+			list_del(&p->node);
+			kfree(p);
+			return 0;
+		}
+	}
+	return -ENODEV;
+}
+
 long adreno_ioctl_perfcounter_get(struct kgsl_device_private *dev_priv,
 	unsigned int cmd, void *data)
 {
@@ -42,6 +86,15 @@
 			get->groupid, get->countable, &get->offset,
 			&get->offset_hi, PERFCOUNTER_FLAG_NONE);
 
+	/* Add the perfcounter into the list */
+	if (!result) {
+		result = adreno_process_perfcounter_add(dev_priv, get->groupid,
+				get->countable);
+		if (result)
+			adreno_perfcounter_put(adreno_dev, get->groupid,
+				get->countable, PERFCOUNTER_FLAG_NONE);
+	}
+
 	adreno_perfcntr_active_oob_put(adreno_dev);
 
 	mutex_unlock(&device->mutex);
@@ -58,8 +111,15 @@
 	int result;
 
 	mutex_lock(&device->mutex);
-	result = adreno_perfcounter_put(adreno_dev, put->groupid,
-		put->countable, PERFCOUNTER_FLAG_NONE);
+
+	/* Delete the perfcounter from the process list */
+	result = adreno_process_perfcounter_del(dev_priv, put->groupid,
+		put->countable);
+
+	/* Put the perfcounter refcount */
+	if (!result)
+		adreno_perfcounter_put(adreno_dev, put->groupid,
+			put->countable, PERFCOUNTER_FLAG_NONE);
 	mutex_unlock(&device->mutex);
 
 	return (long) result;
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index b5999e6..2293919 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.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
@@ -400,6 +400,8 @@
 				ibsize = rbptr[index + 3];
 			}
 
+			index = (index + 1) % KGSL_RB_DWORDS;
+
 			/* Don't parse known global IBs */
 			if (iommu_is_setstate_addr(device, ibaddr, ibsize))
 				continue;
@@ -410,9 +412,8 @@
 
 			parse_ib(device, snapshot, snapshot->process,
 				ibaddr, ibsize);
-		}
-
-		index = (index + 1) % KGSL_RB_DWORDS;
+		} else
+			index = (index + 1) % KGSL_RB_DWORDS;
 	}
 
 }
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 3b55fc6..572dc40 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -764,7 +764,7 @@
 
 	mutex_lock(&device->mutex);
 	status = kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
-	if (status == 0)
+	if (status == 0 && device->state == KGSL_STATE_SUSPEND)
 		device->ftbl->dispatcher_halt(device);
 	mutex_unlock(&device->mutex);
 
@@ -1119,7 +1119,8 @@
 	/* Close down the process wide resources for the file */
 	kgsl_process_private_close(dev_priv, dev_priv->process_priv);
 
-	kfree(dev_priv);
+	/* Destroy the device-specific structure */
+	device->ftbl->device_private_destroy(dev_priv);
 
 	result = kgsl_close_device(device);
 	pm_runtime_put(&device->pdev->dev);
@@ -1187,7 +1188,7 @@
 	}
 	result = 0;
 
-	dev_priv = kzalloc(sizeof(struct kgsl_device_private), GFP_KERNEL);
+	dev_priv = device->ftbl->device_private_create();
 	if (dev_priv == NULL) {
 		result = -ENOMEM;
 		goto err;
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index c8c6456..4a98a24 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -156,6 +156,8 @@
 		struct kgsl_snapshot *snapshot);
 	irqreturn_t (*irq_handler)(struct kgsl_device *device);
 	int (*drain)(struct kgsl_device *device);
+	struct kgsl_device_private * (*device_private_create)(void);
+	void (*device_private_destroy)(struct kgsl_device_private *dev_priv);
 	/*
 	 * Optional functions - these functions are not mandatory.  The
 	 * driver will check that the function pointer is not NULL before
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 7e6af65..5399670 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -139,9 +139,9 @@
 #define QPNP_VADC_HC1_ADC_CH_SEL_CTL				0x44
 #define QPNP_VADC_HC1_DELAY_CTL					0x45
 #define QPNP_VADC_HC1_DELAY_CTL_MASK				0xf
-#define QPNP_VADC_MC1_EN_CTL1					0x46
+#define QPNP_VADC_HC1_EN_CTL1					0x46
 #define QPNP_VADC_HC1_ADC_EN					BIT(7)
-#define QPNP_VADC_MC1_CONV_REQ					0x47
+#define QPNP_VADC_HC1_CONV_REQ					0x47
 #define QPNP_VADC_HC1_CONV_REQ_START				BIT(7)
 
 #define QPNP_VADC_HC1_VBAT_MIN_THR0				0x48
@@ -162,6 +162,10 @@
 #define QPNP_VADC_HC1_CONV_TIME_MAX_US				214
 #define QPNP_VADC_HC1_ERR_COUNT					1600
 
+#define QPNP_VADC_CAL_DELAY_CTL_1					0x3744
+#define QPNP_VADC_CAL_DELAY_MEAS_SLOW					0x73
+#define QPNP_VADC_CAL_DELAY_MEAS_DEFAULT				0x3
+
 struct qpnp_vadc_mode_state {
 	bool				meas_int_mode;
 	bool				meas_int_request_in_queue;
@@ -417,6 +421,32 @@
 	return rc;
 }
 
+static int qpnp_vadc_wait_for_eoc(struct qpnp_vadc_chip *vadc)
+{
+	int ret;
+
+	if (vadc->vadc_poll_eoc) {
+		ret = qpnp_vadc_hc_check_conversion_status(vadc);
+		if (ret < 0) {
+			pr_err("polling mode conversion failed\n");
+			return ret;
+		}
+	} else {
+		ret = wait_for_completion_timeout(
+			&vadc->adc->adc_rslt_completion,
+			QPNP_ADC_COMPLETION_TIMEOUT);
+		if (!ret) {
+			ret = qpnp_vadc_hc_check_conversion_status(vadc);
+			if (ret < 0) {
+				pr_err("interrupt mode conversion failed\n");
+				return ret;
+			}
+			pr_debug("End of conversion status set\n");
+		}
+	}
+	return ret;
+}
+
 static void qpnp_vadc_hc_update_adc_dig_param(struct qpnp_vadc_chip *vadc,
 			struct qpnp_adc_amux_properties *amux_prop, u8 *data)
 {
@@ -435,6 +465,78 @@
 	pr_debug("VADC_DIG_PARAM value:0x%x\n", *data);
 }
 
+static int qpnp_vadc_hc_pre_configure_usb_in(struct qpnp_vadc_chip *vadc,
+						int dt_index)
+{
+	int rc = 0;
+	u8 buf;
+	u8 dig_param = 0;
+	struct qpnp_adc_amux_properties conv;
+
+	/* Setup dig params for USB_IN_V */
+	conv.decimation = DECIMATION_TYPE2;
+	conv.cal_val = ADC_HC_ABS_CAL;
+	conv.calib_type = vadc->adc->adc_channels[dt_index].calib_type;
+
+	qpnp_vadc_hc_update_adc_dig_param(vadc, &conv, &dig_param);
+
+	/* Increase calib interval and wait for other conversions to complete */
+	buf = QPNP_VADC_CAL_DELAY_MEAS_SLOW;
+	rc = regmap_bulk_write(vadc->adc->regmap,
+			QPNP_VADC_CAL_DELAY_CTL_1, &buf, 1);
+	if (rc < 0) {
+		pr_err("qpnp adc write cal_delay failed with %d\n", rc);
+		return rc;
+	}
+	msleep(20);
+
+	/* Read GND first */
+	buf = VADC_VREF_GND;
+	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_HC1_ADC_CH_SEL_CTL, &buf, 1);
+	if (rc < 0)
+		return rc;
+
+	buf = QPNP_VADC_HC1_ADC_EN;
+	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_HC1_EN_CTL1, &buf, 1);
+	if (rc < 0)
+		return rc;
+
+	if (!vadc->vadc_poll_eoc)
+		reinit_completion(&vadc->adc->adc_rslt_completion);
+
+	buf = QPNP_VADC_HC1_CONV_REQ_START;
+	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_HC1_CONV_REQ, &buf, 1);
+	if (rc < 0)
+		return rc;
+
+	/* Pre-configure USB_IN_V request */
+	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_HC1_ADC_DIG_PARAM,
+				&dig_param, 1);
+	if (rc < 0)
+		return rc;
+
+	buf = VADC_USB_IN_V_DIV_16_PM5;
+	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_HC1_ADC_CH_SEL_CTL, &buf, 1);
+	if (rc < 0)
+		return rc;
+
+	/* Wait for GND read to complete */
+	rc = qpnp_vadc_wait_for_eoc(vadc);
+	if (rc < 0)
+		return rc;
+
+	if (!vadc->vadc_poll_eoc)
+		reinit_completion(&vadc->adc->adc_rslt_completion);
+
+	/* Start USB_IN_V read */
+	buf = QPNP_VADC_HC1_CONV_REQ_START;
+	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_HC1_CONV_REQ, &buf, 1);
+	if (rc < 0)
+		return rc;
+
+	return 0;
+}
+
 static int qpnp_vadc_hc_configure(struct qpnp_vadc_chip *vadc,
 				struct qpnp_adc_amux_properties *amux_prop)
 {
@@ -489,6 +591,7 @@
 				struct qpnp_vadc_result *result)
 {
 	int rc = 0, scale_type, amux_prescaling, dt_index = 0, calib_type = 0;
+	u8 val = QPNP_VADC_CAL_DELAY_MEAS_SLOW;
 	struct qpnp_adc_amux_properties amux_prop;
 
 	if (qpnp_vadc_is_valid(vadc))
@@ -525,39 +628,44 @@
 		goto fail_unlock;
 	}
 
-	amux_prop.decimation =
-			vadc->adc->adc_channels[dt_index].adc_decimation;
-	amux_prop.calib_type = vadc->adc->adc_channels[dt_index].calib_type;
-	amux_prop.cal_val = vadc->adc->adc_channels[dt_index].cal_val;
-	amux_prop.fast_avg_setup =
-			vadc->adc->adc_channels[dt_index].fast_avg_setup;
-	amux_prop.amux_channel = channel;
-	amux_prop.hw_settle_time =
-			vadc->adc->adc_channels[dt_index].hw_settle_time;
-
-	rc = qpnp_vadc_hc_configure(vadc, &amux_prop);
-	if (rc < 0) {
-		pr_err("Configuring VADC channel failed with %d\n", rc);
-		goto fail_unlock;
-	}
-
-	if (vadc->vadc_poll_eoc) {
-		rc = qpnp_vadc_hc_check_conversion_status(vadc);
+	if (channel == VADC_USB_IN_V_DIV_16_PM5 &&
+			vadc->adc->adc_prop->is_pmic_5) {
+		rc = qpnp_vadc_hc_pre_configure_usb_in(vadc, dt_index);
 		if (rc < 0) {
-			pr_err("polling mode conversion failed\n");
+			pr_err("Configuring VADC channel failed with %d\n", rc);
 			goto fail_unlock;
 		}
 	} else {
-		rc = wait_for_completion_timeout(
-					&vadc->adc->adc_rslt_completion,
-					QPNP_ADC_COMPLETION_TIMEOUT);
-		if (!rc) {
-			rc = qpnp_vadc_hc_check_conversion_status(vadc);
-			if (rc < 0) {
-				pr_err("interrupt mode conversion failed\n");
-				goto fail_unlock;
-			}
-			pr_debug("End of conversion status set\n");
+		amux_prop.decimation =
+			vadc->adc->adc_channels[dt_index].adc_decimation;
+		amux_prop.calib_type =
+			vadc->adc->adc_channels[dt_index].calib_type;
+		amux_prop.cal_val = vadc->adc->adc_channels[dt_index].cal_val;
+		amux_prop.fast_avg_setup =
+			vadc->adc->adc_channels[dt_index].fast_avg_setup;
+		amux_prop.amux_channel = channel;
+		amux_prop.hw_settle_time =
+			vadc->adc->adc_channels[dt_index].hw_settle_time;
+
+		rc = qpnp_vadc_hc_configure(vadc, &amux_prop);
+		if (rc < 0) {
+			pr_err("Configuring VADC channel failed with %d\n", rc);
+			goto fail_unlock;
+		}
+	}
+
+	rc = qpnp_vadc_wait_for_eoc(vadc);
+	if (rc < 0)
+		goto fail_unlock;
+
+	if (channel == VADC_USB_IN_V_DIV_16_PM5 &&
+			vadc->adc->adc_prop->is_pmic_5) {
+		val = QPNP_VADC_CAL_DELAY_MEAS_DEFAULT;
+		rc = regmap_bulk_write(vadc->adc->regmap,
+				QPNP_VADC_CAL_DELAY_CTL_1, &val, 1);
+		if (rc < 0) {
+			pr_err("qpnp adc write cal_delay failed with %d\n", rc);
+			return rc;
 		}
 	}
 
diff --git a/drivers/hwtracing/coresight/coresight-csr.c b/drivers/hwtracing/coresight/coresight-csr.c
index 9069530..0252203 100644
--- a/drivers/hwtracing/coresight/coresight-csr.c
+++ b/drivers/hwtracing/coresight/coresight-csr.c
@@ -21,6 +21,7 @@
 #include <linux/of.h>
 #include <linux/coresight.h>
 #include <linux/clk.h>
+#include <linux/mutex.h>
 
 #include "coresight-priv.h"
 
@@ -88,6 +89,8 @@
 };
 
 static LIST_HEAD(csr_list);
+static DEFINE_MUTEX(csr_lock);
+
 #define to_csr_drvdata(c) container_of(c, struct csr_drvdata, csr)
 
 void msm_qdss_csr_enable_bam_to_usb(struct coresight_csr *csr)
@@ -236,12 +239,15 @@
 struct coresight_csr *coresight_csr_get(const char *name)
 {
 	struct coresight_csr *csr;
-
+	mutex_lock(&csr_lock);
 	list_for_each_entry(csr, &csr_list, link) {
-		if (!strcmp(csr->name, name))
+		if (!strcmp(csr->name, name)) {
+			mutex_unlock(&csr_lock);
 			return csr;
+		}
 	}
 
+	mutex_unlock(&csr_lock);
 	return ERR_PTR(-EINVAL);
 }
 EXPORT_SYMBOL(coresight_csr_get);
@@ -391,7 +397,10 @@
 	spin_lock_init(&drvdata->spin_lock);
 	drvdata->csr.name = ((struct coresight_platform_data *)
 					 (pdev->dev.platform_data))->name;
+
+	mutex_lock(&csr_lock);
 	list_add_tail(&drvdata->csr.link, &csr_list);
+	mutex_unlock(&csr_lock);
 
 	dev_info(dev, "CSR initialized: %s\n", drvdata->csr.name);
 	return 0;
@@ -399,12 +408,13 @@
 
 static int csr_remove(struct platform_device *pdev)
 {
-	unsigned long flags;
 	struct csr_drvdata *drvdata = platform_get_drvdata(pdev);
 
-	spin_lock_irqsave(&drvdata->spin_lock, flags);
+	mutex_lock(&csr_lock);
+	list_del(&drvdata->csr.link);
+	mutex_unlock(&csr_lock);
+
 	coresight_unregister(drvdata->csdev);
-	spin_unlock_irqrestore(&drvdata->spin_lock, flags);
 	return 0;
 }
 
diff --git a/drivers/hwtracing/coresight/coresight-remote-etm.c b/drivers/hwtracing/coresight/coresight-remote-etm.c
index 54e897d..f4512e5 100644
--- a/drivers/hwtracing/coresight/coresight-remote-etm.c
+++ b/drivers/hwtracing/coresight/coresight-remote-etm.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
@@ -362,6 +362,10 @@
 {
 	struct remote_etm_drvdata *drvdata = platform_get_drvdata(pdev);
 
+	qmi_svc_event_notifier_unregister(CORESIGHT_QMI_SVC_ID,
+					  CORESIGHT_QMI_VERSION,
+					  drvdata->inst_id,
+					  &drvdata->nb);
 	coresight_unregister(drvdata->csdev);
 	return 0;
 }
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index bc4af98..c712866 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -799,6 +799,7 @@
 		return ret;
 	}
 
+	gi2c->i2c_rsc.ctrl_dev = gi2c->dev;
 	gi2c->i2c_rsc.se_clk = devm_clk_get(&pdev->dev, "se-clk");
 	if (IS_ERR(gi2c->i2c_rsc.se_clk)) {
 		ret = PTR_ERR(gi2c->i2c_rsc.se_clk);
diff --git a/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c b/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c
index 7dda14e..15d52dc 100644
--- a/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c
+++ b/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c
@@ -31,6 +31,10 @@
 #include "inv_icm20602_iio.h"
 #include <linux/regulator/consumer.h>
 
+
+static struct regulator *reg_ldo;
+static struct inv_icm20602_state *st;
+
 /* Attribute of icm20602 device init show */
 static ssize_t inv_icm20602_init_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
@@ -379,24 +383,27 @@
 	.validate_trigger = inv_icm20602_validate_trigger,
 };
 
-static int icm20602_ldo_work(struct inv_icm20602_state *st, bool enable)
+static int icm20602_ldo_work(bool enable)
 {
 	int ret = 0;
 
+	if (reg_ldo == NULL)
+		return MPU_FAIL;
+
 	if (enable) {
-		ret = regulator_set_voltage(st->reg_ldo,
+		ret = regulator_set_voltage(reg_ldo,
 			ICM20602_LDO_VTG_MIN_UV, ICM20602_LDO_VTG_MAX_UV);
 		if (ret)
 			pr_err("Failed to request LDO voltage.\n");
 
-		ret = regulator_enable(st->reg_ldo);
+		ret = regulator_enable(reg_ldo);
 		if (ret)
 			pr_err("Failed to enable LDO %d\n", ret);
 	} else {
-		ret = regulator_disable(st->reg_ldo);
+		ret = regulator_disable(reg_ldo);
+		regulator_set_load(reg_ldo, 0);
 		if (ret)
 			pr_err("Failed to disable LDO %d\n", ret);
-		regulator_set_load(st->reg_ldo, 0);
 	}
 
 	return MPU_SUCCESS;
@@ -405,14 +412,13 @@
 static int icm20602_init_regulators(struct inv_icm20602_state *st)
 {
 	struct regulator *reg;
-
 	reg = regulator_get(&st->client->dev, "vdd-ldo");
 	if (IS_ERR_OR_NULL(reg)) {
 		pr_err("Unable to get regulator for LDO\n");
 		return -MPU_FAIL;
 	}
 
-	st->reg_ldo = reg;
+	reg_ldo = reg;
 
 	return MPU_SUCCESS;
 }
@@ -463,7 +469,6 @@
 static int inv_icm20602_probe(struct i2c_client *client,
 	const struct i2c_device_id *id)
 {
-	struct inv_icm20602_state *st;
 	struct iio_dev *indio_dev;
 	int result = MPU_SUCCESS;
 
@@ -505,7 +510,7 @@
 		goto out_remove_trigger;
 	}
 	icm20602_init_regulators(st);
-	icm20602_ldo_work(st, true);
+	icm20602_ldo_work(true);
 
 	result = inv_icm20602_probe_trigger(indio_dev);
 	if (result) {
@@ -549,20 +554,19 @@
 
 static int inv_icm20602_suspend(struct device *dev)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct inv_icm20602_state *st = iio_priv(indio_dev);
+	icm20602_ldo_work(false);
 
-	icm20602_stop_fifo(st);
-	icm20602_ldo_work(st, false);
 	return 0;
 }
 
 static int inv_icm20602_resume(struct device *dev)
 {
-	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
-	struct inv_icm20602_state *st = iio_priv(indio_dev);
+	int ret;
 
-	icm20602_ldo_work(st, true);
+	ret = icm20602_ldo_work(true);
+	if (ret == MPU_FAIL)
+		return 0;
+
 	icm20602_detect(st);
 	icm20602_init_device(st);
 	icm20602_start_fifo(st);
diff --git a/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h b/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h
index b369ae4..36f8e9c 100644
--- a/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h
+++ b/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h
@@ -41,8 +41,8 @@
 #define INV20602_SMD_IRQ_TRIGGER    1
 #endif
 
-#define ICM20602_LDO_VTG_MIN_UV 3300000
-#define ICM20602_LDO_VTG_MAX_UV 3300000
+#define ICM20602_LDO_VTG_MIN_UV 1800000
+#define ICM20602_LDO_VTG_MAX_UV 1800000
 
 #define INV_ICM20602_TIME_STAMP_TOR           5
 #define ICM20602_PACKAGE_SIZE 14
@@ -220,7 +220,6 @@
 	struct struct_icm20602_data *data_push;
 	enum inv_devices chip_type;
 	int gpio;
-	struct regulator *reg_ldo;
 	DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
 };
 
diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c
index 93c28ef..65379ed 100644
--- a/drivers/input/misc/qpnp-power-on.c
+++ b/drivers/input/misc/qpnp-power-on.c
@@ -487,6 +487,19 @@
 	return size;
 }
 
+static struct qpnp_pon_config *
+qpnp_get_cfg(struct qpnp_pon *pon, u32 pon_type)
+{
+	int i;
+
+	for (i = 0; i < pon->num_pon_config; i++) {
+		if (pon_type == pon->pon_cfg[i].pon_type)
+			return  &pon->pon_cfg[i];
+	}
+
+	return NULL;
+}
+
 static DEVICE_ATTR(debounce_us, 0664, qpnp_pon_dbc_show, qpnp_pon_dbc_store);
 
 #define PON_TWM_ENTRY_PBS_BIT           BIT(0)
@@ -496,6 +509,7 @@
 	int rc;
 	bool disable = false;
 	u16 rst_en_reg;
+	struct qpnp_pon_config *cfg;
 
 	/* Ignore the PS_HOLD reset config if TWM ENTRY is enabled */
 	if (pon->support_twm_config && pon->twm_state == PMIC_TWM_ENABLE) {
@@ -506,6 +520,18 @@
 							rc);
 			return rc;
 		}
+
+		cfg = qpnp_get_cfg(pon, PON_KPDPWR);
+		if (cfg) {
+			/* configure KPDPWR_S2 to Hard reset */
+			rc = qpnp_pon_masked_write(pon, cfg->s2_cntl_addr,
+						QPNP_PON_S2_CNTL_TYPE_MASK,
+						PON_POWER_OFF_HARD_RESET);
+			if (rc < 0)
+				pr_err("Unable to config KPDPWR_N S2 for hard-reset rc=%d\n",
+					rc);
+		}
+
 		pr_crit("PMIC configured for TWM entry\n");
 		return 0;
 	}
@@ -901,19 +927,6 @@
 	return 0;
 }
 
-static struct qpnp_pon_config *
-qpnp_get_cfg(struct qpnp_pon *pon, u32 pon_type)
-{
-	int i;
-
-	for (i = 0; i < pon->num_pon_config; i++) {
-		if (pon_type == pon->pon_cfg[i].pon_type)
-			return  &pon->pon_cfg[i];
-	}
-
-	return NULL;
-}
-
 static int
 qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type)
 {
diff --git a/drivers/input/misc/vl53l0x/stmvl53l0x_module.c b/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
index 99cbc11..34508b2 100644
--- a/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
+++ b/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
@@ -963,8 +963,10 @@
 	struct vl_data *data = dev_get_drvdata(dev);
 	struct VL_RangingMeasurementData_t Measure;
 
+	if (data->enable_ps_sensor == 0)
+		return -ENODEV;
 	papi_func_tbl->PerformSingleRangingMeasurement(data, &Measure);
-	return snprintf(buf, 4, "%d\n", Measure.RangeMilliMeter);
+	return snprintf(buf, 7, "%d\n", Measure.RangeMilliMeter);
 }
 
 /* DEVICE_ATTR(name,mode,show,store) */
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 6c4156a..ea37a9f 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1279,6 +1279,18 @@
 
 	  If unsure, say N.
 
+config TOUCHSCREEN_GT9XX_v28
+	bool "Goodix touchpanel GT9xx_v28 series"
+	depends on I2C
+	help
+	  Say Y here if you have a Goodix GT9xx_v28 touchscreen.
+	  Gt9xx controllers are multi touch controllers which can
+	  report 5 touches at a time.
+
+          If unsure, say N.
+
+source "drivers/input/touchscreen/gt9xx_v2.8/Kconfig"
+
 config TOUCHSCREEN_HIMAX_CHIPSET
 	bool "Himax touchpanel CHIPSET"
 	depends on I2C
@@ -1287,8 +1299,7 @@
 	  HIMAX controllers are multi touch controllers which can
 	  report 10 touches at a time.
 
-	  If unsure, say N.
+          If unsure, say N.
 
 source "drivers/input/touchscreen/hxchipset/Kconfig"
-
 endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index a5952ca..acd4045 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -104,4 +104,5 @@
 obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50)	+= colibri-vf50-ts.o
 obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023)	+= rohm_bu21023.o
 obj-$(CONFIG_TOUCHSCREEN_FTS)		+= focaltech_touch/
+obj-$(CONFIG_TOUCHSCREEN_GT9XX_v28)		+= gt9xx_v2.8/
 obj-$(CONFIG_TOUCHSCREEN_HIMAX_CHIPSET)	+= hxchipset/
diff --git a/drivers/input/touchscreen/ektf3xxx/Makefile b/drivers/input/touchscreen/ektf3xxx/Makefile
new file mode 100644
index 0000000..715b891
--- /dev/null
+++ b/drivers/input/touchscreen/ektf3xxx/Makefile
@@ -0,0 +1,3 @@
+# Makefile for the Elan touchscreen drivers.
+
+obj-$(CONFIG_TOUCHSCREEN_EKTF3XXX_CHIPSET)   	+= 	elan_cros_i2c.o
diff --git a/drivers/input/touchscreen/ektf3xxx/elan_cros_i2c.c b/drivers/input/touchscreen/ektf3xxx/elan_cros_i2c.c
new file mode 100644
index 0000000..3098941
--- /dev/null
+++ b/drivers/input/touchscreen/ektf3xxx/elan_cros_i2c.c
@@ -0,0 +1,1520 @@
+/*
+ * Elan Microelectronics touch panels with I2C interface
+ *
+ * Copyright (C) 2014 Elan Microelectronics Corporation.
+ * Chuming Zhang <chuming.zhang@elanic.com.cn>
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/async.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/buffer_head.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+#include <linux/input/mt.h>
+#include <linux/acpi.h>
+#include <linux/of.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <asm/unaligned.h>
+
+
+/* Device, Driver information */
+#define DEVICE_NAME	"elants_i2c"
+#define DRV_VERSION	"1.0.9"
+
+/* Convert from rows or columns into resolution */
+#define ELAN_TS_RESOLUTION(n, m)   (((n) - 1) * (m))
+#define ELAN_VTG_MAX_UV	3300000
+
+/* FW header data */
+#define HEADER_SIZE		4
+#define FW_HDR_TYPE		0
+#define FW_HDR_COUNT		1
+#define FW_HDR_LENGTH		2
+
+/* Buffer mode Queue Header information */
+#define QUEUE_HEADER_SINGLE	0x62
+#define QUEUE_HEADER_NORMAL	0X63
+#define QUEUE_HEADER_WAIT	0x64
+
+/* Command header definition */
+#define CMD_HEADER_WRITE	0x54
+#define CMD_HEADER_READ		0x53
+#define CMD_HEADER_6B_READ	0x5B
+#define CMD_HEADER_RESP		0x52
+#define CMD_HEADER_6B_RESP	0x9B
+#define CMD_HEADER_HELLO	0x55
+#define CMD_HEADER_REK		0x66
+
+/* FW position data */
+#define PACKET_SIZE		55
+#define MAX_CONTACT_NUM		10
+#define FW_POS_HEADER		0
+#define FW_POS_STATE		1
+#define FW_POS_TOTAL		2
+#define FW_POS_XY		3
+#define FW_POS_CHECKSUM		34
+#define FW_POS_WIDTH		35
+#define FW_POS_PRESSURE		45
+
+#define HEADER_REPORT_10_FINGER	0x62
+
+/* Header (4 bytes) plus 3 fill 10-finger packets */
+#define MAX_PACKET_SIZE		169
+
+#define BOOT_TIME_DELAY_MS	50
+
+/* FW read command, 0x53 0x?? 0x0, 0x01 */
+#define E_ELAN_INFO_FW_VER	0x00
+#define E_ELAN_INFO_BC_VER	0x10
+#define E_ELAN_INFO_TEST_VER	0xE0
+#define E_ELAN_INFO_FW_ID	0xF0
+#define E_INFO_OSR		0xD6
+#define E_INFO_PHY_SCAN		0xD7
+#define E_INFO_PHY_DRIVER	0xD8
+
+#define MAX_RETRIES		3
+#define MAX_FW_UPDATE_RETRIES	30
+
+#define ELAN_FW_PAGESIZE	132
+
+/* calibration timeout definition */
+#define ELAN_CALI_TIMEOUT_MSEC	12000
+
+#define ELAN_POWERON_DELAY_USEC	500
+#define ELAN_RESET_DELAY_MSEC	20
+
+/* define print buf size*/
+#define ELAN_PRINT_SIZE			1024
+
+enum elants_state {
+	ELAN_STATE_NORMAL,
+	ELAN_WAIT_QUEUE_HEADER,
+	ELAN_WAIT_RECALIBRATION,
+};
+
+enum elants_iap_mode {
+	ELAN_IAP_OPERATIONAL,
+	ELAN_IAP_RECOVERY,
+};
+
+/* struct elants_data - represents state of Elan touchscreen device */
+struct elants_data {
+	struct i2c_client *client;
+	struct input_dev *input;
+
+	struct regulator *vdd;
+	struct regulator *vccio;
+	struct gpio_desc *reset_gpio;
+
+	u16 fw_version;
+	u8 test_version;
+	u8 solution_version;
+	u8 bc_version;
+	u8 iap_version;
+	u16 hw_version;
+	unsigned int x_res;	/* resolution in units/mm */
+	unsigned int y_res;
+	unsigned int x_max;
+	unsigned int y_max;
+
+	enum elants_state state;
+	enum elants_iap_mode iap_mode;
+
+	/* Guards against concurrent access to the device via sysfs */
+	struct mutex sysfs_mutex;
+
+	u8 cmd_resp[HEADER_SIZE];
+	struct completion cmd_done;
+
+	u8 buf[MAX_PACKET_SIZE];
+
+	bool wake_irq_enabled;
+	bool keep_power_in_suspend;
+	struct workqueue_struct *elan_ic_update;
+	struct delayed_work delay_work;
+};
+
+static int elants_i2c_send(struct i2c_client *client,
+			   const void *data, size_t size)
+{
+	int ret;
+
+	ret = i2c_master_send(client, data, size);
+	if (ret == size)
+		return 0;
+
+	if (ret >= 0)
+		ret = -EIO;
+
+	dev_err(&client->dev, "%s failed (%*ph): %d\n",
+		__func__, (int)size, data, ret);
+
+	return ret;
+}
+
+static int elants_i2c_read(struct i2c_client *client, void *data, size_t size)
+{
+	int ret;
+
+	ret = i2c_master_recv(client, data, size);
+	if (ret == size)
+		return 0;
+
+	if (ret >= 0)
+		ret = -EIO;
+
+	dev_err(&client->dev, "%s failed: %d\n", __func__, ret);
+
+	return ret;
+}
+
+static int elants_i2c_execute_command(struct i2c_client *client,
+				      const u8 *cmd, size_t cmd_size,
+				      u8 *resp, size_t resp_size)
+{
+	struct i2c_msg msgs[2];
+	int ret;
+	u8 expected_response;
+
+	switch (cmd[0]) {
+	case CMD_HEADER_READ:
+		expected_response = CMD_HEADER_RESP;
+		break;
+
+	case CMD_HEADER_6B_READ:
+		expected_response = CMD_HEADER_6B_RESP;
+		break;
+
+	default:
+		dev_err(&client->dev, "%s: invalid command %*ph\n",
+			__func__, (int)cmd_size, cmd);
+		return -EINVAL;
+	}
+
+	msgs[0].addr = client->addr;
+	msgs[0].flags = client->flags & I2C_M_TEN;
+	msgs[0].len = cmd_size;
+	msgs[0].buf = (u8 *)cmd;
+
+	msgs[1].addr = client->addr;
+	msgs[1].flags = client->flags & I2C_M_TEN;
+	msgs[1].flags |= I2C_M_RD;
+	msgs[1].len = resp_size;
+	msgs[1].buf = resp;
+
+	ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
+	if (ret < 0)
+		return ret;
+
+	if (ret != ARRAY_SIZE(msgs) || resp[FW_HDR_TYPE] != expected_response)
+		return -EIO;
+
+	return 0;
+}
+
+static int elants_i2c_calibrate(struct elants_data *ts)
+{
+	struct i2c_client *client = ts->client;
+	int ret, error;
+	static const u8 w_flashkey[] = { 0x54, 0xC0, 0xE1, 0x5A };
+	static const u8 rek[] = { 0x54, 0x29, 0x00, 0x01 };
+	static const u8 rek_resp[] = { CMD_HEADER_REK, 0x66, 0x66, 0x66 };
+
+	disable_irq(client->irq);
+
+	ts->state = ELAN_WAIT_RECALIBRATION;
+	reinit_completion(&ts->cmd_done);
+
+	elants_i2c_send(client, w_flashkey, sizeof(w_flashkey));
+	elants_i2c_send(client, rek, sizeof(rek));
+
+	enable_irq(client->irq);
+
+	ret = wait_for_completion_interruptible_timeout(&ts->cmd_done,
+				msecs_to_jiffies(ELAN_CALI_TIMEOUT_MSEC));
+
+	ts->state = ELAN_STATE_NORMAL;
+
+	if (ret <= 0) {
+		error = ret < 0 ? ret : -ETIMEDOUT;
+		dev_err(&client->dev,
+			"error while waiting for calibration to complete: %d\n",
+			error);
+		return error;
+	}
+
+	if (memcmp(rek_resp, ts->cmd_resp, sizeof(rek_resp))) {
+		dev_err(&client->dev,
+			"unexpected calibration response: %*ph\n",
+			(int)sizeof(ts->cmd_resp), ts->cmd_resp);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int elants_i2c_sw_reset(struct i2c_client *client)
+{
+	const u8 soft_rst_cmd[] = { 0x77, 0x77, 0x77, 0x77 };
+	int error;
+
+	error = elants_i2c_send(client, soft_rst_cmd,
+				sizeof(soft_rst_cmd));
+	if (error) {
+		dev_err(&client->dev, "software reset failed: %d\n", error);
+		return error;
+	}
+
+	/*
+	 * We should wait at least 10 msec (but no more than 40) before
+	 * sending fastboot or IAP command to the device.
+	 */
+	msleep(30);
+
+	return 0;
+}
+
+static u16 elants_i2c_parse_version(u8 *buf)
+{
+	return get_unaligned_be32(buf) >> 4;
+}
+
+static int elants_i2c_query_hw_version(struct elants_data *ts)
+{
+	struct i2c_client *client = ts->client;
+	int error, retry_cnt;
+	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_FW_ID, 0x00, 0x01 };
+	u8 resp[HEADER_SIZE];
+
+	for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
+		error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
+						   resp, sizeof(resp));
+		if (!error) {
+			ts->hw_version = elants_i2c_parse_version(resp);
+			if (ts->hw_version != 0xffff)
+				return 0;
+		}
+		dev_dbg(&client->dev, "read fw id error=%d, buf=%*phC\n",
+			error, (int)sizeof(resp), resp);
+	}
+
+	if (error) {
+		dev_err(&client->dev,
+			"Failed to read fw id: %d\n", error);
+		return error;
+	}
+	dev_err(&client->dev, "Invalid fw id: %#04x\n", ts->hw_version);
+	return -EINVAL;
+}
+
+
+static int elants_i2c_query_fw_version(struct elants_data *ts)
+{
+	struct i2c_client *client = ts->client;
+	int error, retry_cnt;
+	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_FW_VER, 0x00, 0x01 };
+	u8 resp[HEADER_SIZE];
+
+	for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
+		error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
+						   resp, sizeof(resp));
+		if (!error) {
+			ts->fw_version = elants_i2c_parse_version(resp);
+			if (ts->fw_version != 0x0000 &&
+			    ts->fw_version != 0xffff)
+				return 0;
+		}
+
+		dev_dbg(&client->dev, "read fw version error=%d, buf=%*phC\n",
+			error, (int)sizeof(resp), resp);
+	}
+
+	dev_err(&client->dev,
+		"Failed to read fw version or fw version is invalid\n");
+
+	return -EINVAL;
+}
+
+static int elants_i2c_query_test_version(struct elants_data *ts)
+{
+	struct i2c_client *client = ts->client;
+	int error, retry_cnt;
+	u16 version;
+	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_TEST_VER, 0x00, 0x01 };
+	u8 resp[HEADER_SIZE];
+
+	for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
+		error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
+						   resp, sizeof(resp));
+		if (!error) {
+			version = elants_i2c_parse_version(resp);
+			ts->test_version = version >> 8;
+			ts->solution_version = version & 0xff;
+
+			return 0;
+		}
+
+		dev_dbg(&client->dev,
+			"read test version error rc=%d, buf=%*phC\n",
+			error, (int)sizeof(resp), resp);
+	}
+
+	dev_err(&client->dev, "Failed to read test version\n");
+
+	return -EINVAL;
+}
+
+static int elants_i2c_query_bc_version(struct elants_data *ts)
+{
+	struct i2c_client *client = ts->client;
+	const u8 cmd[] = { CMD_HEADER_READ, E_ELAN_INFO_BC_VER, 0x00, 0x01 };
+	u8 resp[HEADER_SIZE];
+	u16 version;
+	int error;
+
+	error = elants_i2c_execute_command(client, cmd, sizeof(cmd),
+					   resp, sizeof(resp));
+	if (error) {
+		dev_err(&client->dev,
+			"read BC version error=%d, buf=%*phC\n",
+			error, (int)sizeof(resp), resp);
+		return error;
+	}
+
+	version = elants_i2c_parse_version(resp);
+	ts->bc_version = version >> 8;
+	ts->iap_version = version & 0xff;
+
+	return 0;
+}
+
+static int elants_i2c_query_ts_info(struct elants_data *ts)
+{
+	struct i2c_client *client = ts->client;
+	int error;
+	u8 resp[17];
+	u16 phy_x, phy_y, rows, cols, osr;
+	const u8 get_resolution_cmd[] = {
+		CMD_HEADER_6B_READ, 0x00, 0x00, 0x00, 0x00, 0x00
+	};
+	const u8 get_osr_cmd[] = {
+		CMD_HEADER_READ, E_INFO_OSR, 0x00, 0x01
+	};
+	const u8 get_physical_scan_cmd[] = {
+		CMD_HEADER_READ, E_INFO_PHY_SCAN, 0x00, 0x01
+	};
+	const u8 get_physical_drive_cmd[] = {
+		CMD_HEADER_READ, E_INFO_PHY_DRIVER, 0x00, 0x01
+	};
+
+	/* Get trace number */
+	error = elants_i2c_execute_command(client,
+					   get_resolution_cmd,
+					   sizeof(get_resolution_cmd),
+					   resp, sizeof(resp));
+	if (error) {
+		dev_err(&client->dev, "get resolution command failed: %d\n",
+			error);
+		return error;
+	}
+
+	rows = resp[2] + resp[6] + resp[10];
+	cols = resp[3] + resp[7] + resp[11];
+
+	/* Process mm_to_pixel information */
+	error = elants_i2c_execute_command(client,
+					   get_osr_cmd, sizeof(get_osr_cmd),
+					   resp, sizeof(resp));
+	if (error) {
+		dev_err(&client->dev, "get osr command failed: %d\n",
+			error);
+		return error;
+	}
+
+	osr = resp[3];
+
+	error = elants_i2c_execute_command(client,
+					   get_physical_scan_cmd,
+					   sizeof(get_physical_scan_cmd),
+					   resp, sizeof(resp));
+	if (error) {
+		dev_err(&client->dev, "get physical scan command failed: %d\n",
+			error);
+		return error;
+	}
+
+	phy_x = get_unaligned_be16(&resp[2]);
+
+	error = elants_i2c_execute_command(client,
+					   get_physical_drive_cmd,
+					   sizeof(get_physical_drive_cmd),
+					   resp, sizeof(resp));
+	if (error) {
+		dev_err(&client->dev, "get physical drive command failed: %d\n",
+			error);
+		return error;
+	}
+
+	phy_y = get_unaligned_be16(&resp[2]);
+
+	dev_dbg(&client->dev, "phy_x=%d, phy_y=%d\n", phy_x, phy_y);
+
+	if (rows == 0 || cols == 0 || osr == 0) {
+		dev_warn(&client->dev,
+			 "invalid trace number data: %d, %d, %d\n",
+			 rows, cols, osr);
+	} else {
+		/* translate trace number to TS resolution */
+		ts->y_max = ELAN_TS_RESOLUTION(rows, osr);
+		ts->y_res = DIV_ROUND_CLOSEST(ts->y_max, phy_y);
+		ts->x_max = ELAN_TS_RESOLUTION(cols, osr);
+		ts->x_res = DIV_ROUND_CLOSEST(ts->x_max, phy_x);
+	}
+
+	return 0;
+}
+
+static int elants_i2c_fastboot(struct i2c_client *client)
+{
+	const u8 boot_cmd[] = { 0x4D, 0x61, 0x69, 0x6E };
+	int error;
+
+	error = elants_i2c_send(client, boot_cmd, sizeof(boot_cmd));
+	if (error) {
+		dev_err(&client->dev, "boot failed: %d\n", error);
+		return error;
+	}
+
+	dev_dbg(&client->dev, "boot success -- 0x%x\n", client->addr);
+	return 0;
+}
+
+static int elants_i2c_initialize(struct elants_data *ts)
+{
+	struct i2c_client *client = ts->client;
+	int error, error2, retry_cnt;
+	const u8 hello_packet[] = { 0x55, 0x55, 0x55, 0x55 };
+	const u8 recov_packet[] = { 0x55, 0x55, 0x80, 0x80 };
+	u8 buf[HEADER_SIZE];
+
+	for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
+		error = elants_i2c_sw_reset(client);
+		if (error) {
+			/* Continue initializing if it's the last try */
+			if (retry_cnt < MAX_RETRIES - 1)
+				continue;
+		}
+
+		error = elants_i2c_fastboot(client);
+		if (error) {
+			/* Continue initializing if it's the last try */
+			if (retry_cnt < MAX_RETRIES - 1)
+				continue;
+		}
+
+		/* Wait for Hello packet */
+		msleep(BOOT_TIME_DELAY_MS);
+
+		error = elants_i2c_read(client, buf, sizeof(buf));
+		if (error) {
+			dev_err(&client->dev,
+				"failed to read 'hello' packet: %d\n", error);
+			continue;
+		} else if (!memcmp(buf, hello_packet, sizeof(hello_packet))) {
+			ts->iap_mode = ELAN_IAP_OPERATIONAL;
+			break;
+		} else if (!memcmp(buf, recov_packet, sizeof(recov_packet))) {
+			/*
+			 * Setting error code will mark device
+			 * in recovery mode below.
+			 */
+			error = -EIO;
+			break;
+		}
+		error = -EINVAL;
+		dev_err(&client->dev,
+			"invalid 'hello' packet: %*ph\n",
+			(int)sizeof(buf), buf);
+	}
+
+	error2 = elants_i2c_query_hw_version(ts);
+	if (!error)
+		error = error2;
+	if (!error)
+		error = elants_i2c_query_fw_version(ts);
+	if (!error)
+		error = elants_i2c_query_test_version(ts);
+	if (!error)
+		error = elants_i2c_query_bc_version(ts);
+	if (!error)
+		error = elants_i2c_query_ts_info(ts);
+	if (error)
+		ts->iap_mode = ELAN_IAP_RECOVERY;
+	return 0;
+}
+
+/*
+ * Firmware update interface.
+ */
+
+static int elants_i2c_fw_write_page(struct i2c_client *client,
+				    const void *page, int page_num)
+{
+	const u8 ack_ok[] = { 0xaa, 0xaa };
+	u8 buf[2];
+	int retry;
+	int error;
+	int curIndex = 0;
+	const u8 *szBuff;
+	int byte_count;
+
+	for (retry = 0; retry < MAX_FW_UPDATE_RETRIES; retry++) {
+		for (byte_count = 1; byte_count <= 5; byte_count++) {
+			if (byte_count != 5) {
+				szBuff = page + curIndex;
+				curIndex = curIndex + 32;
+				error = elants_i2c_send(client, szBuff, 32);
+			} else {
+				szBuff = page + curIndex;
+				curIndex = curIndex + 4;
+				error = elants_i2c_send(client, szBuff, 4);
+			}
+
+			if (error) {
+				curIndex = 0;
+				continue;
+			}
+		}
+
+		if (error) {
+			dev_err(&client->dev,
+					"IAP Write Page failed: %d\n", error);
+			continue;
+		}
+
+		if (page_num == 1)
+			msleep(600);
+		else
+			msleep(50);
+		error = elants_i2c_read(client, buf, 2);
+		if (error) {
+			dev_err(&client->dev,
+				"IAP Ack read failed: %d\n", error);
+			return error;
+		}
+
+		if (!memcmp(buf, ack_ok, sizeof(ack_ok)))
+			return 0;
+
+		error = -EIO;
+		dev_err(&client->dev,
+			"IAP Get Ack Error [%02x:%02x]\n",
+			buf[0], buf[1]);
+	}
+
+	return error;
+}
+
+static int elants_i2c_do_update_firmware(struct i2c_client *client,
+					 const struct firmware *fw,
+					 bool force)
+{
+	const u8 enter_iap[] = { 0x45, 0x49, 0x41, 0x50 };
+	const u8 enter_iap2[] = { 0x54, 0x00, 0x12, 0x34 };
+	const u8 iap_ack[] = { 0x55, 0xaa, 0x33, 0xcc };
+	const u8 close_idle[] = {0x54, 0x2c, 0x01, 0x01};
+	u8 buf[HEADER_SIZE];
+	u16 send_id;
+	int page, n_fw_pages;
+	int error;
+
+	/* Recovery mode detection! */
+	if (force) {
+		dev_dbg(&client->dev, "Recovery mode procedure\n");
+		error = elants_i2c_send(client, enter_iap2, sizeof(enter_iap2));
+	} else {
+		/* Start IAP Procedure */
+		dev_dbg(&client->dev, "Normal IAP procedure\n");
+		/* Close idle mode */
+		error = elants_i2c_send(client, close_idle, sizeof(close_idle));
+		if (error)
+			dev_err(&client->dev, "Failed close idle: %d\n", error);
+		msleep(60);
+		elants_i2c_sw_reset(client);
+		msleep(20);
+		error = elants_i2c_send(client, enter_iap, sizeof(enter_iap));
+	}
+
+	if (error) {
+		dev_err(&client->dev, "failed to enter IAP mode: %d\n", error);
+		return error;
+	}
+
+	msleep(20);
+
+	/* check IAP state */
+	error = elants_i2c_read(client, buf, 4);
+	if (error) {
+		dev_err(&client->dev,
+			"failed to read IAP acknowledgment: %d\n",
+			error);
+		return error;
+	}
+
+	if (memcmp(buf, iap_ack, sizeof(iap_ack))) {
+		dev_err(&client->dev,
+			"failed to enter IAP: %*ph (expected %*ph)\n",
+			(int)sizeof(buf), buf, (int)sizeof(iap_ack), iap_ack);
+		return -EIO;
+	}
+
+	dev_info(&client->dev, "successfully entered IAP mode");
+
+	send_id = client->addr;
+	error = elants_i2c_send(client, &send_id, 1);
+	if (error) {
+		dev_err(&client->dev, "sending dummy byte failed: %d\n",
+			error);
+		return error;
+	}
+
+	/* Clear the last page of Master */
+	error = elants_i2c_send(client, fw->data, ELAN_FW_PAGESIZE);
+	if (error) {
+		dev_err(&client->dev, "clearing of the last page failed: %d\n",
+			error);
+		return error;
+	}
+
+	error = elants_i2c_read(client, buf, 2);
+	if (error) {
+		dev_err(&client->dev,
+			"failed to read ACK for clearing the last page: %d\n",
+			error);
+		return error;
+	}
+
+	n_fw_pages = fw->size / ELAN_FW_PAGESIZE;
+	dev_dbg(&client->dev, "IAP Pages = %d\n", n_fw_pages);
+
+	for (page = 0; page < n_fw_pages; page++) {
+		error = elants_i2c_fw_write_page(client,
+					fw->data + page * ELAN_FW_PAGESIZE,
+					page);
+		if (error) {
+			dev_err(&client->dev,
+				"failed to write FW page %d: %d\n",
+				page, error);
+			return error;
+		}
+	}
+
+	/* Old iap needs to wait 200ms for WDT and rest is for hello packets */
+	msleep(300);
+
+	dev_info(&client->dev, "firmware update completed\n");
+	return 0;
+}
+
+static int elants_i2c_fw_update(struct elants_data *ts)
+{
+	struct i2c_client *client = ts->client;
+	const struct firmware *fw;
+	char *fw_name;
+	int error;
+
+	fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%04x.bin", ts->hw_version);
+	if (!fw_name)
+		return -ENOMEM;
+
+	dev_info(&client->dev, "requesting fw name = %s\n", fw_name);
+	error = request_firmware(&fw, fw_name, &client->dev);
+	kfree(fw_name);
+	if (error) {
+		dev_err(&client->dev, "failed to request firmware: %d\n",
+			error);
+		return error;
+	}
+
+	if (fw->size % ELAN_FW_PAGESIZE) {
+		dev_err(&client->dev, "invalid firmware length: %zu\n",
+			fw->size);
+		error = -EINVAL;
+		goto out;
+	}
+
+	disable_irq(client->irq);
+
+	error = elants_i2c_do_update_firmware(client, fw,
+					ts->iap_mode == ELAN_IAP_RECOVERY);
+	if (error) {
+		dev_err(&client->dev, "firmware update failed: %d\n", error);
+		ts->iap_mode = ELAN_IAP_RECOVERY;
+		goto out_enable_irq;
+	}
+
+	error = elants_i2c_initialize(ts);
+	if (error) {
+		dev_err(&client->dev,
+			"failed to initialize device after firmware update: %d\n",
+			error);
+		ts->iap_mode = ELAN_IAP_RECOVERY;
+		goto out_enable_irq;
+	}
+
+	ts->iap_mode = ELAN_IAP_OPERATIONAL;
+
+out_enable_irq:
+	ts->state = ELAN_STATE_NORMAL;
+	enable_irq(client->irq);
+	msleep(100);
+
+	if (!error)
+		elants_i2c_calibrate(ts);
+out:
+	release_firmware(fw);
+	return error;
+}
+
+static void elants_i2c_auto_update(struct work_struct *work)
+{
+	struct elants_data *ts = container_of(work,
+			struct elants_data, delay_work.work);
+	struct i2c_client *client = ts->client;
+	const struct firmware *fw;
+	char *fw_name;
+	int error;
+	u8 *fw_data;
+	u16 new_fw_version;
+	u16 new_hw_version;
+
+	if (ts->fw_version == 0x0000 ||
+		ts->fw_version == 0xffff) {
+		dev_err(&client->dev, "invalid firmware version: %04x\n",
+			ts->fw_version);
+		return;
+	}
+
+	fw_name = kasprintf(GFP_KERNEL, "elants_i2c_%04x.bin", ts->hw_version);
+	if (!fw_name)
+		return;
+
+	dev_info(&client->dev, "requesting fw name = %s\n", fw_name);
+	error = request_firmware(&fw, fw_name, &client->dev);
+	kfree(fw_name);
+	if (error) {
+		dev_err(&client->dev, "failed to request firmware: %d\n",
+			error);
+		return;
+	}
+
+	if (fw->size % ELAN_FW_PAGESIZE) {
+		dev_err(&client->dev, "invalid firmware length: %zu\n",
+			fw->size);
+		error = -EINVAL;
+		goto out;
+	}
+
+	fw_data = (u8 *)fw->data;
+
+	new_hw_version  = fw_data[0xE2CF] << 8  | fw_data[0xE2CE];
+	new_fw_version = fw_data[0xDEC3] << 8  | fw_data[0xDEC2];
+	dev_dbg(&client->dev, "hw version=0x%x, new hw version=0x%x\n",
+			ts->hw_version, new_hw_version);
+	dev_dbg(&client->dev, "fw version=0x%x, new fw version=0x%x\n",
+			ts->fw_version, new_fw_version);
+	if ((ts->hw_version == new_hw_version) &&
+		((ts->fw_version & 0xff) < (new_fw_version & 0xff))) {
+		dev_dbg(&ts->client->dev, "start auto update\n");
+		release_firmware(fw);
+
+		error = mutex_lock_interruptible(&ts->sysfs_mutex);
+		if (error)
+			return;
+
+		error = elants_i2c_fw_update(ts);
+		dev_dbg(&client->dev, "firmware update result: %d\n", error);
+
+		mutex_unlock(&ts->sysfs_mutex);
+		return;
+	}
+
+out:
+	release_firmware(fw);
+}
+
+
+
+/*
+ * Event reporting.
+ */
+
+static void elants_i2c_mt_event(struct elants_data *ts, u8 *buf)
+{
+	struct input_dev *input = ts->input;
+	unsigned int n_fingers;
+	u16 finger_state;
+	int i;
+
+	n_fingers = buf[FW_POS_STATE + 1] & 0x0f;
+	finger_state = ((buf[FW_POS_STATE + 1] & 0x30) << 4) |
+			buf[FW_POS_STATE];
+
+	dev_dbg(&ts->client->dev,
+		"n_fingers: %u, state: %04x\n",  n_fingers, finger_state);
+
+	for (i = 0; i < MAX_CONTACT_NUM && n_fingers; i++) {
+		if (finger_state & 1) {
+			unsigned int x, y, p, w;
+			u8 *pos;
+
+			pos = &buf[FW_POS_XY + i * 3];
+			x = (((u16)pos[0] & 0xf0) << 4) | pos[1];
+			y = (((u16)pos[0] & 0x0f) << 8) | pos[2];
+			p = buf[FW_POS_PRESSURE + i];
+			w = buf[FW_POS_WIDTH + i];
+
+			dev_dbg(&ts->client->dev, "i=%d x=%d y=%d p=%d w=%d\n",
+				i, x, y, p, w);
+
+			input_mt_slot(input, i);
+			input_mt_report_slot_state(input, MT_TOOL_FINGER, true);
+			input_event(input, EV_ABS, ABS_MT_POSITION_X, x);
+			input_event(input, EV_ABS, ABS_MT_POSITION_Y, y);
+			input_event(input, EV_ABS, ABS_MT_PRESSURE, p);
+			input_event(input, EV_ABS, ABS_MT_TOUCH_MAJOR, w);
+
+			n_fingers--;
+		}
+
+		finger_state >>= 1;
+	}
+
+	input_mt_sync_frame(input);
+	input_sync(input);
+}
+
+static u8 elants_i2c_calculate_checksum(u8 *buf)
+{
+	u8 checksum = 0;
+	u8 i;
+
+	for (i = 0; i < FW_POS_CHECKSUM; i++)
+		checksum += buf[i];
+
+	return checksum;
+}
+
+static void elants_i2c_event(struct elants_data *ts, u8 *buf)
+{
+	u8 checksum = elants_i2c_calculate_checksum(buf);
+
+	if (unlikely(buf[FW_POS_CHECKSUM] != checksum))
+		dev_warn(&ts->client->dev,
+			 "%s: invalid checksum for packet %02x: %02x vs. %02x\n",
+			 __func__, buf[FW_POS_HEADER],
+			 checksum, buf[FW_POS_CHECKSUM]);
+	else if (unlikely(buf[FW_POS_HEADER] != HEADER_REPORT_10_FINGER))
+		dev_warn(&ts->client->dev,
+			 "%s: unknown packet type: %02x\n",
+			 __func__, buf[FW_POS_HEADER]);
+	else
+		elants_i2c_mt_event(ts, buf);
+}
+
+static irqreturn_t elants_i2c_irq(int irq, void *_dev)
+{
+	const u8 wait_packet[] = { 0x64, 0x64, 0x64, 0x64 };
+	struct elants_data *ts = _dev;
+	struct i2c_client *client = ts->client;
+	int report_count, report_len;
+	int i;
+	int len;
+
+	len = i2c_master_recv(client, ts->buf, sizeof(ts->buf));
+	if (len < 0) {
+		dev_err(&client->dev, "%s: failed to read data: %d\n",
+			__func__, len);
+		goto out;
+	}
+
+	dev_dbg(&client->dev, "%s: packet %*ph\n",
+		__func__, HEADER_SIZE, ts->buf);
+
+
+	switch (ts->state) {
+	case ELAN_WAIT_RECALIBRATION:
+		if (ts->buf[FW_HDR_TYPE] == CMD_HEADER_REK) {
+			memcpy(ts->cmd_resp, ts->buf, sizeof(ts->cmd_resp));
+			complete(&ts->cmd_done);
+			ts->state = ELAN_STATE_NORMAL;
+		}
+		break;
+
+	case ELAN_WAIT_QUEUE_HEADER:
+		if (ts->buf[FW_HDR_TYPE] != QUEUE_HEADER_NORMAL)
+			break;
+
+		ts->state = ELAN_STATE_NORMAL;
+		/* fall through */
+
+	case ELAN_STATE_NORMAL:
+
+		switch (ts->buf[FW_HDR_TYPE]) {
+		case CMD_HEADER_HELLO:
+		case CMD_HEADER_RESP:
+		case CMD_HEADER_REK:
+			break;
+
+		case QUEUE_HEADER_WAIT:
+			if (memcmp(ts->buf, wait_packet, sizeof(wait_packet))) {
+				dev_err(&client->dev,
+					"invalid wait packet %*ph\n",
+					HEADER_SIZE, ts->buf);
+			} else {
+				ts->state = ELAN_WAIT_QUEUE_HEADER;
+				udelay(30);
+			}
+			break;
+
+		case QUEUE_HEADER_SINGLE:
+			elants_i2c_event(ts, &ts->buf[FW_HDR_TYPE]);
+			break;
+
+		case QUEUE_HEADER_NORMAL:
+			report_count = ts->buf[FW_HDR_COUNT];
+			if (report_count == 0 || report_count > 3) {
+				dev_err(&client->dev,
+					"bad report count: %*ph\n",
+					HEADER_SIZE, ts->buf);
+				break;
+			}
+
+			report_len = ts->buf[FW_HDR_LENGTH] / report_count;
+			if (report_len != PACKET_SIZE) {
+				dev_err(&client->dev,
+					"mismatching report length: %*ph\n",
+					HEADER_SIZE, ts->buf);
+				break;
+			}
+
+			for (i = 0; i < report_count; i++) {
+				u8 *buf = ts->buf + HEADER_SIZE +
+							i * PACKET_SIZE;
+				elants_i2c_event(ts, buf);
+			}
+			break;
+
+		default:
+			dev_err(&client->dev, "unknown packet %*ph\n",
+				HEADER_SIZE, ts->buf);
+			break;
+		}
+		break;
+	}
+
+out:
+	return IRQ_HANDLED;
+}
+
+/*
+ * sysfs interface
+ */
+static ssize_t calibrate_store(struct device *dev,
+			       struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct elants_data *ts = i2c_get_clientdata(client);
+	int error;
+
+	error = mutex_lock_interruptible(&ts->sysfs_mutex);
+	if (error)
+		return error;
+
+	error = elants_i2c_calibrate(ts);
+
+	mutex_unlock(&ts->sysfs_mutex);
+	return error ?: count;
+}
+
+static ssize_t write_update_fw(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct elants_data *ts = i2c_get_clientdata(client);
+	int error;
+
+	error = mutex_lock_interruptible(&ts->sysfs_mutex);
+	if (error)
+		return error;
+
+	error = elants_i2c_fw_update(ts);
+	dev_dbg(dev, "firmware update result: %d\n", error);
+
+	mutex_unlock(&ts->sysfs_mutex);
+	return error ?: count;
+}
+
+static ssize_t show_iap_mode(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct elants_data *ts = i2c_get_clientdata(client);
+
+	return snprintf(buf, ELAN_PRINT_SIZE, "%s\n",
+		       ts->iap_mode == ELAN_IAP_OPERATIONAL ?
+				"Normal" : "Recovery");
+}
+
+static DEVICE_ATTR(calibrate, 0200, NULL, calibrate_store);
+static DEVICE_ATTR(iap_mode, 0444, show_iap_mode, NULL);
+static DEVICE_ATTR(update_fw, 0200, NULL, write_update_fw);
+
+struct elants_version_attribute {
+	struct device_attribute dattr;
+	size_t field_offset;
+	size_t field_size;
+};
+
+#define __ELANTS_FIELD_SIZE(_field)					\
+	sizeof(((struct elants_data *)NULL)->_field)
+#define __ELANTS_VERIFY_SIZE(_field)					\
+	(BUILD_BUG_ON_ZERO(__ELANTS_FIELD_SIZE(_field) > 2) +		\
+	 __ELANTS_FIELD_SIZE(_field))
+#define ELANTS_VERSION_ATTR(_field)					\
+	struct elants_version_attribute elants_ver_attr_##_field = {	\
+		.dattr = __ATTR(_field, 0444,			\
+				elants_version_attribute_show, NULL),	\
+		.field_offset = offsetof(struct elants_data, _field),	\
+		.field_size = __ELANTS_VERIFY_SIZE(_field),		\
+	}
+
+static ssize_t elants_version_attribute_show(struct device *dev,
+					     struct device_attribute *dattr,
+					     char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct elants_data *ts = i2c_get_clientdata(client);
+	struct elants_version_attribute *attr =
+		container_of(dattr, struct elants_version_attribute, dattr);
+	u8 *field = (u8 *)((char *)ts + attr->field_offset);
+	unsigned int fmt_size;
+	unsigned int val;
+
+	if (attr->field_size == 1) {
+		val = *field;
+		fmt_size = 2; /* 2 HEX digits */
+	} else {
+		val = *(u16 *)field;
+		fmt_size = 4; /* 4 HEX digits */
+	}
+
+	return snprintf(buf, ELAN_PRINT_SIZE,  "%0*x\n", fmt_size, val);
+}
+
+static ELANTS_VERSION_ATTR(fw_version);
+static ELANTS_VERSION_ATTR(hw_version);
+static ELANTS_VERSION_ATTR(test_version);
+static ELANTS_VERSION_ATTR(solution_version);
+static ELANTS_VERSION_ATTR(bc_version);
+static ELANTS_VERSION_ATTR(iap_version);
+
+static struct attribute *elants_attributes[] = {
+	&dev_attr_calibrate.attr,
+	&dev_attr_update_fw.attr,
+	&dev_attr_iap_mode.attr,
+
+	&elants_ver_attr_fw_version.dattr.attr,
+	&elants_ver_attr_hw_version.dattr.attr,
+	&elants_ver_attr_test_version.dattr.attr,
+	&elants_ver_attr_solution_version.dattr.attr,
+	&elants_ver_attr_bc_version.dattr.attr,
+	&elants_ver_attr_iap_version.dattr.attr,
+	NULL
+};
+
+static struct attribute_group elants_attribute_group = {
+	.attrs = elants_attributes,
+};
+
+static void elants_i2c_remove_sysfs_group(void *_data)
+{
+	struct elants_data *ts = _data;
+
+	sysfs_remove_group(&ts->client->dev.kobj, &elants_attribute_group);
+}
+
+static int elants_i2c_power_on(struct elants_data *ts)
+{
+	int error;
+
+	/*
+	 * If we do not have reset gpio assume platform firmware
+	 * controls regulators and does power them on for us.
+	 */
+	if (IS_ERR_OR_NULL(ts->reset_gpio))
+		return 0;
+
+	gpiod_set_value_cansleep(ts->reset_gpio, 1);
+
+	if (regulator_count_voltages(ts->vdd) > 0) {
+		error = regulator_set_voltage(ts->vdd,
+				ELAN_VTG_MAX_UV, ELAN_VTG_MAX_UV);
+	if (error) {
+		dev_err(&ts->client->dev,
+				"Regulator set_vtg failed vdd ret=%d\n",
+				error);
+		goto release_reset_gpio;
+		}
+	}
+
+	error = regulator_enable(ts->vdd);
+	if (error) {
+		dev_err(&ts->client->dev,
+			"failed to enable vdd regulator: %d\n",
+			error);
+		goto release_reset_gpio;
+	}
+
+	error = regulator_enable(ts->vccio);
+	if (error) {
+		dev_err(&ts->client->dev,
+			"failed to enable vccio regulator: %d\n",
+			error);
+		regulator_disable(ts->vdd);
+		goto release_reset_gpio;
+	}
+
+	/*
+	 * We need to wait a bit after powering on controller before
+	 * we are allowed to release reset GPIO.
+	 */
+	udelay(ELAN_POWERON_DELAY_USEC);
+
+release_reset_gpio:
+	gpiod_set_value_cansleep(ts->reset_gpio, 0);
+	if (error)
+		return error;
+
+	msleep(ELAN_RESET_DELAY_MSEC);
+
+	return 0;
+}
+
+static void elants_i2c_power_off(void *_data)
+{
+	struct elants_data *ts = _data;
+
+	if (!IS_ERR_OR_NULL(ts->reset_gpio)) {
+		/*
+		 * Activate reset gpio to prevent leakage through the
+		 * pin once we shut off power to the controller.
+		 */
+		gpiod_set_value_cansleep(ts->reset_gpio, 1);
+		regulator_disable(ts->vccio);
+		regulator_disable(ts->vdd);
+	}
+}
+
+static int elants_i2c_probe(struct i2c_client *client,
+			    const struct i2c_device_id *id)
+{
+	union i2c_smbus_data dummy;
+	struct elants_data *ts;
+	unsigned long irqflags;
+	int error;
+	unsigned long delay = 3*HZ;
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev,
+			"%s: i2c check functionality error\n", DEVICE_NAME);
+		return -ENXIO;
+	}
+
+	ts = devm_kzalloc(&client->dev, sizeof(struct elants_data), GFP_KERNEL);
+	if (!ts)
+		return -ENOMEM;
+
+	mutex_init(&ts->sysfs_mutex);
+	init_completion(&ts->cmd_done);
+
+	ts->client = client;
+	i2c_set_clientdata(client, ts);
+
+	ts->vdd = devm_regulator_get(&client->dev, "vdd");
+	if (IS_ERR(ts->vdd)) {
+		error = PTR_ERR(ts->vdd);
+		if (error != -EPROBE_DEFER)
+			dev_err(&client->dev,
+					"Failed to get 'vdd' regulator: %d\n",
+					error);
+		return error;
+	}
+
+	ts->vccio = devm_regulator_get(&client->dev, "vccio");
+	if (IS_ERR(ts->vccio)) {
+		error = PTR_ERR(ts->vccio);
+		if (error != -EPROBE_DEFER)
+			dev_err(&client->dev,
+				"Failed to get 'vccio' regulator: %d\n",
+				error);
+		return error;
+	}
+
+	ts->reset_gpio = devm_gpiod_get(&client->dev, "reset", GPIOD_OUT_LOW);
+	if (IS_ERR(ts->reset_gpio)) {
+		error = PTR_ERR(ts->reset_gpio);
+
+		if (error == -EPROBE_DEFER)
+			return error;
+
+		if (error != -ENOENT) {
+			dev_err(&client->dev,
+				"failed to get reset gpio: %d\n",
+				error);
+			return error;
+		}
+
+		ts->keep_power_in_suspend = true;
+	}
+	error = elants_i2c_power_on(ts);
+	if (error)
+		return error;
+
+	error = devm_add_action(&client->dev, elants_i2c_power_off, ts);
+	if (error) {
+		dev_err(&client->dev,
+			"failed to install power off action: %d\n", error);
+		elants_i2c_power_off(ts);
+		return error;
+	}
+
+	/* Make sure there is something at this address */
+	if (i2c_smbus_xfer(client->adapter, client->addr, 0,
+			   I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &dummy) < 0) {
+		dev_err(&client->dev, "nothing at this address\n");
+		return -ENXIO;
+	}
+
+	error = elants_i2c_initialize(ts);
+	if (error) {
+		dev_err(&client->dev, "failed to initialize: %d\n", error);
+		return error;
+	}
+
+	INIT_DELAYED_WORK(&ts->delay_work, elants_i2c_auto_update);
+	ts->elan_ic_update = create_singlethread_workqueue("elan_ic_update");
+	queue_delayed_work(ts->elan_ic_update, &ts->delay_work, delay);
+
+	ts->input = devm_input_allocate_device(&client->dev);
+	if (!ts->input) {
+		dev_err(&client->dev, "Failed to allocate input device\n");
+		return -ENOMEM;
+	}
+
+	ts->input->name = "Elan Touchscreen";
+	ts->input->id.bustype = BUS_I2C;
+
+	__set_bit(BTN_TOUCH, ts->input->keybit);
+	__set_bit(EV_ABS, ts->input->evbit);
+	__set_bit(EV_KEY, ts->input->evbit);
+
+	/* Single touch input params setup */
+	input_set_abs_params(ts->input, ABS_X, 0, ts->x_max, 0, 0);
+	input_set_abs_params(ts->input, ABS_Y, 0, ts->y_max, 0, 0);
+	input_set_abs_params(ts->input, ABS_PRESSURE, 0, 255, 0, 0);
+	input_abs_set_res(ts->input, ABS_X, ts->x_res);
+	input_abs_set_res(ts->input, ABS_Y, ts->y_res);
+
+	/* Multitouch input params setup */
+	error = input_mt_init_slots(ts->input, MAX_CONTACT_NUM,
+				    INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED);
+	if (error) {
+		dev_err(&client->dev,
+			"failed to initialize MT slots: %d\n", error);
+		return error;
+	}
+
+	input_set_abs_params(ts->input, ABS_MT_POSITION_X, 0, ts->x_max, 0, 0);
+	input_set_abs_params(ts->input, ABS_MT_POSITION_Y, 0, ts->y_max, 0, 0);
+	input_set_abs_params(ts->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0);
+	input_set_abs_params(ts->input, ABS_MT_PRESSURE, 0, 255, 0, 0);
+	input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->x_res);
+	input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res);
+
+	input_set_drvdata(ts->input, ts);
+
+	error = input_register_device(ts->input);
+	if (error) {
+		dev_err(&client->dev,
+			"unable to register input device: %d\n", error);
+		return error;
+	}
+
+	/*
+	 * Systems using device tree should set up interrupt via DTS,
+	 * the rest will use the default falling edge interrupts.
+	 */
+	irqflags = client->dev.of_node ? 0 : IRQF_TRIGGER_FALLING;
+
+	error = devm_request_threaded_irq(&client->dev, client->irq,
+					  NULL, elants_i2c_irq,
+					  irqflags | IRQF_ONESHOT,
+					  client->name, ts);
+	if (error) {
+		dev_err(&client->dev, "Failed to register interrupt\n");
+		return error;
+	}
+
+	/*
+	 * Systems using device tree should set up wakeup via DTS,
+	 * the rest will configure device as wakeup source by default.
+	 */
+	if (!client->dev.of_node)
+		device_init_wakeup(&client->dev, true);
+
+	error = sysfs_create_group(&client->dev.kobj, &elants_attribute_group);
+	if (error) {
+		dev_err(&client->dev, "failed to create sysfs attributes: %d\n",
+			error);
+		return error;
+	}
+
+	error = devm_add_action(&client->dev,
+				elants_i2c_remove_sysfs_group, ts);
+	if (error) {
+		elants_i2c_remove_sysfs_group(ts);
+		dev_err(&client->dev,
+			"Failed to add sysfs cleanup action: %d\n",
+			error);
+		return error;
+	}
+
+	return 0;
+}
+
+static int __maybe_unused elants_i2c_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct elants_data *ts = i2c_get_clientdata(client);
+	const u8 set_sleep_cmd[] = { 0x54, 0x50, 0x00, 0x01 };
+	int retry_cnt;
+	int error;
+
+	/* Command not support in IAP recovery mode */
+	if (ts->iap_mode != ELAN_IAP_OPERATIONAL)
+		return -EBUSY;
+
+	disable_irq(client->irq);
+
+	if (device_may_wakeup(dev)) {
+		/*
+		 * The device will automatically enter idle mode
+		 * that has reduced power consumption.
+		 */
+		ts->wake_irq_enabled = (enable_irq_wake(client->irq) == 0);
+	} else if (ts->keep_power_in_suspend) {
+		for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
+			error = elants_i2c_send(client, set_sleep_cmd,
+						sizeof(set_sleep_cmd));
+			if (!error)
+				break;
+
+			dev_err(&client->dev,
+				"suspend command failed: %d\n", error);
+		}
+	} else {
+		elants_i2c_power_off(ts);
+	}
+
+	return 0;
+}
+
+static int __maybe_unused elants_i2c_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct elants_data *ts = i2c_get_clientdata(client);
+	const u8 set_active_cmd[] = { 0x54, 0x58, 0x00, 0x01 };
+	int retry_cnt;
+	int error;
+
+	if (device_may_wakeup(dev)) {
+		if (ts->wake_irq_enabled)
+			disable_irq_wake(client->irq);
+		elants_i2c_sw_reset(client);
+	} else if (ts->keep_power_in_suspend) {
+		for (retry_cnt = 0; retry_cnt < MAX_RETRIES; retry_cnt++) {
+			error = elants_i2c_send(client, set_active_cmd,
+						sizeof(set_active_cmd));
+			if (!error)
+				break;
+
+			dev_err(&client->dev,
+				"resume command failed: %d\n", error);
+		}
+	} else {
+		elants_i2c_power_on(ts);
+		elants_i2c_initialize(ts);
+	}
+
+	ts->state = ELAN_STATE_NORMAL;
+	enable_irq(client->irq);
+
+	return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(elants_i2c_pm_ops,
+			 elants_i2c_suspend, elants_i2c_resume);
+
+static const struct i2c_device_id elants_i2c_id[] = {
+	{ DEVICE_NAME, 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, elants_i2c_id);
+
+#ifdef CONFIG_ACPI
+static const struct acpi_device_id elants_acpi_id[] = {
+	{ "ELAN0001", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(acpi, elants_acpi_id);
+#endif
+
+#ifdef CONFIG_OF
+static const struct of_device_id elants_of_match[] = {
+	{ .compatible = "elan,ekth3500" },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, elants_of_match);
+#endif
+
+static struct i2c_driver elants_i2c_driver = {
+	.probe = elants_i2c_probe,
+	.id_table = elants_i2c_id,
+	.driver = {
+		.name = DEVICE_NAME,
+		.pm = &elants_i2c_pm_ops,
+		.acpi_match_table = ACPI_PTR(elants_acpi_id),
+		.of_match_table = of_match_ptr(elants_of_match),
+		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
+	},
+};
+module_i2c_driver(elants_i2c_driver);
+
+MODULE_AUTHOR("Chuming Zhang <chuming.zhang@elanic.com.cn>");
+MODULE_DESCRIPTION("Elan I2c Touchscreen driver");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_core.c b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c
index b3d7322..7639c9f 100644
--- a/drivers/input/touchscreen/focaltech_touch/focaltech_core.c
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c
@@ -514,11 +514,11 @@
 #endif
 		} else {
 			uppoint++;
-			input_mt_report_slot_state(data->input_dev,
-						MT_TOOL_FINGER, false);
 #if FTS_REPORT_PRESSURE_EN
 			input_report_abs(data->input_dev, ABS_MT_PRESSURE, 0);
 #endif
+			input_mt_report_slot_state(data->input_dev,
+						MT_TOOL_FINGER, false);
 			data->touchs &= ~BIT(event->au8_finger_id[i]);
 			FTS_DEBUG("[B]P%d UP!", event->au8_finger_id[i]);
 		}
diff --git a/drivers/input/touchscreen/gt9xx_v2.8/Kconfig b/drivers/input/touchscreen/gt9xx_v2.8/Kconfig
new file mode 100644
index 0000000..7046cc9
--- /dev/null
+++ b/drivers/input/touchscreen/gt9xx_v2.8/Kconfig
@@ -0,0 +1,36 @@
+#
+# Goodix GT9xx Touchscreen driver
+#
+config TOUCHSCREEN_GT9XX_v28
+	bool "Goodix touchpanel GT9xx series"
+	depends on I2C
+	help
+	  Enable this for support Goodix GT9xx_v28 driver.
+
+	  Say Y here if you have a Goodix GT9xx touchscreen
+	  controller.
+
+          If unsure, say N.
+
+config TOUCHSCREEN_GT9XX_UPDATE
+	tristate "Goodix GT9xx touch controller auto update support"
+	depends on TOUCHSCREEN_GT9XX_v28
+	help
+	  Enable this for support firmware update.
+
+	  Say Y here if you want update touch controller
+	  firmware.
+
+	  If unsure, say N.
+
+config TOUCHSCREEN_GT9XX_TOOL
+	tristate "Goodix GT9xx Tools for debuging"
+	depends on TOUCHSCREEN_GT9XX_v28
+	help
+	  This implement interface support for Goodix GT9xx
+	  touchscreen debug.
+
+	  Say Y here if you want to have a Android app debug interface
+	  to your system.
+
+	  If unsure, say N.
diff --git a/drivers/input/touchscreen/gt9xx_v2.8/Makefile b/drivers/input/touchscreen/gt9xx_v2.8/Makefile
new file mode 100644
index 0000000..6c1c404
--- /dev/null
+++ b/drivers/input/touchscreen/gt9xx_v2.8/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for the Goodix gt9xx touchscreen driver.
+#
+#subdir-ccflags-y += -DDEBUG
+obj-$(CONFIG_TOUCHSCREEN_GT9XX_v28)	+= gt9xx.o
+obj-$(CONFIG_TOUCHSCREEN_GT9XX_UPDATE)	+= gt9xx_update.o
+obj-$(CONFIG_TOUCHSCREEN_GT9XX_TOOL)	+= goodix_tool.o
diff --git a/drivers/input/touchscreen/gt9xx_v2.8/goodix_tool.c b/drivers/input/touchscreen/gt9xx_v2.8/goodix_tool.c
new file mode 100644
index 0000000..7db5ae2
--- /dev/null
+++ b/drivers/input/touchscreen/gt9xx_v2.8/goodix_tool.c
@@ -0,0 +1,529 @@
+/*
+ * Goodix GT9xx touchscreen driver
+ *
+ * Copyright  (C)  2016 - 2017 Goodix. Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be a reference
+ * to you, when you are integrating the GOODiX's CTP IC into your system,
+ * 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 "gt9xx.h"
+
+#define DATA_LENGTH_UINT	512
+#define CMD_HEAD_LENGTH		(sizeof(struct st_cmd_head) - sizeof(u8 *))
+static char procname[20] = {0};
+
+#pragma pack(1)
+struct st_cmd_head {
+	u8	wr;		/*write read flag 0:R 1:W 2:PID 3:*/
+	u8	flag;		/*0:no need flag/int 1: need flag 2:need int*/
+	u8	flag_addr[2];	/*flag address*/
+	u8	flag_val;	/*flag val*/
+	u8	flag_relation;	/*flag_val:flag 0:not equal 1:equal 2:> 3:<*/
+	u16	circle;		/*polling cycle*/
+	u8	times;		/*plling times*/
+	u8	retry;		/*I2C retry times*/
+	u16	delay;		/*delay before read or after write*/
+	u16	data_len;	/*data length*/
+	u8	addr_len;	/*address length*/
+	u8	addr[2];	/*address*/
+	u8	res[3];		/*reserved*/
+	u8	*data; };	/*data pointer*/
+#pragma pack()
+struct st_cmd_head cmd_head;
+
+static struct i2c_client *gt_client;
+static struct proc_dir_entry *goodix_proc_entry;
+
+static ssize_t goodix_tool_read(struct file *, char __user *, size_t, loff_t *);
+static ssize_t goodix_tool_write(struct file *, const char __user *,
+						size_t, loff_t *);
+static const struct file_operations gtp_proc_ops = {
+	.owner = THIS_MODULE,
+	.read = goodix_tool_read,
+	.write = goodix_tool_write,
+};
+
+/* static s32 goodix_tool_write(struct file *filp,
+ * const char __user *buff, unsigned long len, void *data);
+ */
+/*static s32 goodix_tool_read( char *page, char
+ **start, off_t off, int count, int *eof, void *data );
+ */
+static s32 (*tool_i2c_read)(u8 *, u16);
+static s32 (*tool_i2c_write)(u8 *, u16);
+
+static s32 DATA_LENGTH = (s32)0;
+static s8 IC_TYPE[16] = "GT9XX";
+
+static void tool_set_proc_name(char *procname)
+{
+	snprintf(procname, 20, "gmnode"); /* modify for moto */
+}
+
+static s32 tool_i2c_read_no_extra(u8 *buf, u16 len)
+{
+	s32 ret = -1;
+	s32 i = 0;
+	struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client);
+
+	for (i = 0; i < cmd_head.retry; i++) {
+		ret = gtp_i2c_read(ts->client, buf, len + GTP_ADDR_LENGTH);
+		if (ret > 0)
+			break;
+	}
+	return ret;
+}
+
+static s32 tool_i2c_write_no_extra(u8 *buf, u16 len)
+{
+	s32 ret = -1;
+	s32 i = 0;
+	struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client);
+
+	for (i = 0; i < cmd_head.retry; i++) {
+		ret = gtp_i2c_write(ts->client, buf, len);
+		if (ret > 0)
+			break;
+	}
+
+	return ret;
+}
+
+static s32 tool_i2c_read_with_extra(u8 *buf, u16 len)
+{
+	s32 ret = -1;
+	u8 pre[2] = {0x0f, 0xff};
+	u8 end[2] = {0x80, 0x00};
+
+	tool_i2c_write_no_extra(pre, 2);
+	ret = tool_i2c_read_no_extra(buf, len);
+	tool_i2c_write_no_extra(end, 2);
+
+	return ret;
+}
+
+static s32 tool_i2c_write_with_extra(u8 *buf, u16 len)
+{
+	s32 ret = -1;
+	u8 pre[2] = {0x0f, 0xff};
+	u8 end[2] = {0x80, 0x00};
+
+	tool_i2c_write_no_extra(pre, 2);
+	ret = tool_i2c_write_no_extra(buf, len);
+	tool_i2c_write_no_extra(end, 2);
+
+	return ret;
+}
+
+static void register_i2c_func(void)
+{
+	/* if (!strcmp(IC_TYPE, "GT818", 5)
+	 *  || !strcmp(IC_TYPE, "GT816", 5)
+	 *  || !strcmp(IC_TYPE, "GT811", 5)
+	 *  || !strcmp(IC_TYPE, "GT818F", 6)
+	 *  || !strcmp(IC_TYPE, "GT827", 5)
+	 *  || !strcmp(IC_TYPE,"GT828", 5)
+	 *  || !strcmp(IC_TYPE, "GT813", 5))
+	 */
+	if (strcmp(IC_TYPE, "GT8110") &&
+	    strcmp(IC_TYPE, "GT8105") &&
+	    strcmp(IC_TYPE, "GT801") &&
+	    strcmp(IC_TYPE, "GT800") &&
+	    strcmp(IC_TYPE, "GT801PLUS") &&
+	    strcmp(IC_TYPE, "GT811") &&
+	    strcmp(IC_TYPE, "GTxxx") &&
+	    strcmp(IC_TYPE, "GT9XX")) {
+		tool_i2c_read = tool_i2c_read_with_extra;
+		tool_i2c_write = tool_i2c_write_with_extra;
+		dev_dbg(&gt_client->dev, "I2C function: with pre and end cmd!");
+	} else {
+		tool_i2c_read = tool_i2c_read_no_extra;
+		tool_i2c_write = tool_i2c_write_no_extra;
+		dev_info(&gt_client->dev, "I2C function: without pre and end cmd!");
+	}
+}
+
+static void unregister_i2c_func(void)
+{
+	tool_i2c_read = NULL;
+	tool_i2c_write = NULL;
+	dev_info(&gt_client->dev, "I2C function: unregister i2c transfer function!");
+}
+
+s32 init_wr_node(struct i2c_client *client)
+{
+	s32 i;
+
+	gt_client = client;
+	memset(&cmd_head, 0, sizeof(cmd_head));
+	cmd_head.data = NULL;
+
+	i = 6;
+	while ((!cmd_head.data) && i) {
+		cmd_head.data = kzalloc(i * DATA_LENGTH_UINT, GFP_KERNEL);
+		if (cmd_head.data)
+			break;
+		i--;
+	}
+	if (i) {
+		DATA_LENGTH = i * DATA_LENGTH_UINT - GTP_ADDR_LENGTH;
+		dev_info(&gt_client->dev,
+			 "Alloc memory size:%d.", DATA_LENGTH);
+	} else {
+		dev_err(&gt_client->dev, "Apply for memory failed.");
+		return FAIL;
+	}
+
+	cmd_head.addr_len = 2;
+	cmd_head.retry = 5;
+
+	register_i2c_func();
+
+	tool_set_proc_name(procname);
+	goodix_proc_entry = proc_create(procname, 0664, NULL, &gtp_proc_ops);
+	if (!goodix_proc_entry) {
+		dev_err(&gt_client->dev, "Couldn't create proc entry!");
+		return FAIL;
+	}
+
+	dev_info(&gt_client->dev, "Create proc entry success!");
+	return SUCCESS;
+}
+
+void uninit_wr_node(void)
+{
+	kfree(cmd_head.data);
+	cmd_head.data = NULL;
+	unregister_i2c_func();
+	remove_proc_entry(procname, NULL);
+}
+
+static u8 relation(u8 src, u8 dst, u8 rlt)
+{
+	u8 ret = 0;
+
+	switch (rlt) {
+	case 0:
+		ret = (src != dst) ? true : false;
+		break;
+
+	case 1:
+		ret = (src == dst) ? true : false;
+		dev_dbg(&gt_client->dev,
+			"equal:src:0x%02x  dst:0x%02x  ret:%d.",
+			src, dst, (s32)ret);
+		break;
+
+	case 2:
+		ret = (src > dst) ? true : false;
+		break;
+
+	case 3:
+		ret = (src < dst) ? true : false;
+		break;
+
+	case 4:
+		ret = (src & dst) ? true : false;
+		break;
+
+	case 5:
+		ret = (!(src | dst)) ? true : false;
+		break;
+
+	default:
+		ret = false;
+		break;
+	}
+
+	return ret;
+}
+
+/*******************************************************
+ * Function:
+ *	Comfirm function.
+ * Input:
+ *	None.
+ * Output:
+ *	Return write length.
+ ********************************************************/
+static u8 comfirm(void)
+{
+	s32 i = 0;
+	u8 buf[32];
+
+	memcpy(buf, cmd_head.flag_addr, cmd_head.addr_len);
+
+	for (i = 0; i < cmd_head.times; i++) {
+		if (tool_i2c_read(buf, 1) <= 0) {
+			dev_err(&gt_client->dev, "Read flag data failed!");
+			return FAIL;
+		}
+		if (true == relation(buf[GTP_ADDR_LENGTH],
+		 cmd_head.flag_val, cmd_head.flag_relation)) {
+			dev_dbg(&gt_client->dev, "value at flag addr:0x%02x.",
+				buf[GTP_ADDR_LENGTH]);
+			dev_dbg(&gt_client->dev, "flag value:0x%02x.",
+				cmd_head.flag_val);
+			break;
+		}
+
+		msleep(cmd_head.circle);
+	}
+
+	if (i >= cmd_head.times) {
+		dev_err(&gt_client->dev, "Can't get the continue flag!");
+		return FAIL;
+	}
+
+	return SUCCESS;
+}
+
+ssize_t goodix_tool_write(struct file *filp, const char __user *buff,
+			  size_t len, loff_t *off)
+{
+	s32 ret = 0;
+	struct goodix_ts_data *ts = i2c_get_clientdata(gt_client);
+
+	ret = copy_from_user(&cmd_head, buff, CMD_HEAD_LENGTH);
+	if (ret) {
+		dev_err(&gt_client->dev, "copy_from_user failed.");
+		return -EPERM;
+	}
+
+	dev_dbg(&gt_client->dev, "[Operation]wr: %02X", cmd_head.wr);
+	dev_dbg(&gt_client->dev,
+		"[Flag]flag: %02X,addr: %02X%02X,value: %02X,relation: %02X",
+		cmd_head.flag, cmd_head.flag_addr[0],
+		cmd_head.flag_addr[1], cmd_head.flag_val,
+		cmd_head.flag_relation);
+	dev_dbg(&gt_client->dev,
+		"[Retry]circle: %d,times: %d,retry: %d, delay: %d",
+		(s32)cmd_head.circle,
+		(s32)cmd_head.times, (s32)cmd_head.retry,
+		(s32)cmd_head.delay);
+
+	if (cmd_head.wr == 1) {
+		if (cmd_head.data_len > DATA_LENGTH) {
+			dev_err(&gt_client->dev,
+				"Tool write failed data too long");
+			return -EPERM;
+		}
+		ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH],
+				     &buff[CMD_HEAD_LENGTH],
+				     cmd_head.data_len);
+		if (ret) {
+			dev_err(&gt_client->dev, "copy_from_user failed.");
+			return -EPERM;
+		}
+		memcpy(&cmd_head.data[GTP_ADDR_LENGTH - cmd_head.addr_len],
+		       cmd_head.addr, cmd_head.addr_len);
+
+		GTP_DEBUG_ARRAY(cmd_head.data, cmd_head.data_len +
+				cmd_head.addr_len);
+
+		if (cmd_head.flag == 1) {
+			if (comfirm() == FAIL) {
+				dev_err(&gt_client->dev,
+					"[WRITE]Comfirm fail!");
+				return -EPERM;
+			}
+		} else if (cmd_head.flag == 2) {
+			/*Need interrupt!*/
+		}
+		if (tool_i2c_write(&cmd_head.data[GTP_ADDR_LENGTH -
+				   cmd_head.addr_len], cmd_head.data_len +
+				   cmd_head.addr_len) <= 0) {
+			dev_err(&gt_client->dev, "[WRITE]Write data failed!");
+			return -EPERM;
+		}
+
+		GTP_DEBUG_ARRAY(&cmd_head.data[GTP_ADDR_LENGTH -
+				cmd_head.addr_len],
+				cmd_head.data_len + cmd_head.addr_len);
+		if (cmd_head.delay)
+			msleep(cmd_head.delay);
+	} else if (cmd_head.wr == 3) {
+		if (cmd_head.data_len > DATA_LENGTH) {
+			dev_err(&gt_client->dev,
+				"Tool write failed data too long");
+			return -EPERM;
+		}
+		ret = copy_from_user(&cmd_head.data[0], &buff[CMD_HEAD_LENGTH],
+				     cmd_head.data_len);
+		if (ret) {
+			dev_err(&gt_client->dev, "copy_from_user failed.");
+			return -EPERM;
+		}
+		memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len);
+
+		register_i2c_func();
+	} else if (cmd_head.wr == 5) {
+		/*memcpy(IC_TYPE, cmd_head.data, cmd_head.data_len);*/
+	} else if (cmd_head.wr == 7) {/*disable irq!*/
+		gtp_work_control_enable(i2c_get_clientdata(gt_client), false);
+
+		if (ts->pdata->esd_protect)
+			gtp_esd_off(ts);
+	} else if (cmd_head.wr == 9) {/*enable irq!*/
+		gtp_work_control_enable(i2c_get_clientdata(gt_client), true);
+
+		if (ts->pdata->esd_protect)
+			gtp_esd_on(ts);
+	} else if (cmd_head.wr == 17) {
+		if (cmd_head.data_len > DATA_LENGTH) {
+			dev_err(&gt_client->dev,
+				"Tool write failed data too long");
+			return -EPERM;
+		}
+		ret = copy_from_user(&cmd_head.data[GTP_ADDR_LENGTH],
+				     &buff[CMD_HEAD_LENGTH],
+				     cmd_head.data_len);
+		if (ret) {
+			dev_dbg(&gt_client->dev, "copy_from_user failed.");
+			return -EPERM;
+		}
+		if (cmd_head.data[GTP_ADDR_LENGTH]) {
+			dev_info(&gt_client->dev, "gtp enter rawdiff.");
+			set_bit(RAW_DATA_MODE, &ts->flags);
+		} else {
+			clear_bit(RAW_DATA_MODE, &ts->flags);
+			dev_info(&gt_client->dev, "gtp leave rawdiff.");
+		}
+	} else if (cmd_head.wr == 19) {
+		/* add new command: reset guitar */
+		gtp_reset_guitar(gt_client, 20);
+	}
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
+	else if (cmd_head.wr == 11) {/*Enter update mode!*/
+		if (gup_enter_update_mode(gt_client) == FAIL)
+			return -EPERM;
+	} else if (cmd_head.wr == 13) {/*Leave update mode!*/
+		gup_leave_update_mode(gt_client);
+	} else if (cmd_head.wr == 15) {/*Update firmware!*/
+		show_len = 0;
+		total_len = 0;
+		if (cmd_head.data_len > DATA_LENGTH) {
+			dev_err(&gt_client->dev,
+				"Tool write failed data too long");
+			return -EPERM;
+		}
+		memset(cmd_head.data, 0, DATA_LENGTH);
+		ret = copy_from_user(cmd_head.data,
+				     &buff[CMD_HEAD_LENGTH],
+				     cmd_head.data_len);
+		if (ret) {
+			dev_dbg(&gt_client->dev, "copy_from_user failed.");
+			return -EPERM;
+		}
+
+		if (gup_update_proc((void *)cmd_head.data) == FAIL)
+			return -EPERM;
+	}
+#endif
+
+	return len;
+}
+
+/*******************************************************
+ * Function:
+ *	Goodix tool read function.
+ * Input:
+ *	standard proc read function param.
+ * Output:
+ *	Return read length.
+ ********************************************************/
+ssize_t goodix_tool_read(struct file *file, char __user *page,
+			 size_t size, loff_t *ppos)
+{
+	s32 ret = 0;
+
+	if (*ppos) {
+		/* ADB call again
+		 * dev_dbg(&gt_client->dev, "[HEAD]wr: %d", cmd_head.wr);
+		 * dev_dbg(&gt_client->dev,
+		 * "[PARAM]size: %d, *ppos: %d", size, (int)*ppos);
+		 * dev_dbg(&gt_client->dev,
+		 * "[TOOL_READ]ADB call again, return it.");
+		 */
+		*ppos = 0;
+		return 0;
+	}
+
+	if (cmd_head.wr % 2) {
+		return -EPERM;
+	} else if (!cmd_head.wr) {
+		u16 len, data_len, loc, addr;
+
+		if (cmd_head.flag == 1) {
+			if (comfirm() == FAIL) {
+				dev_err(&gt_client->dev, "[READ]Comfirm fail!");
+				return -EPERM;
+			}
+		} else if (cmd_head.flag == 2) {
+			/*Need interrupt!*/
+		}
+
+		if (cmd_head.delay)
+			msleep(cmd_head.delay);
+
+		data_len = cmd_head.data_len;
+		addr = (cmd_head.addr[0] << 8) + cmd_head.addr[1];
+		loc = 0;
+
+		while (data_len > 0) {
+			len = data_len > DATA_LENGTH ? DATA_LENGTH : data_len;
+			cmd_head.data[0] = (addr >> 8) & 0xFF;
+			cmd_head.data[1] = (addr & 0xFF);
+			if (tool_i2c_read(cmd_head.data, len) <= 0) {
+				dev_err(&gt_client->dev, "[READ]Read data failed!");
+				return -EPERM;
+			}
+			ret = simple_read_from_buffer(&page[loc], size, ppos,
+					&cmd_head.data[GTP_ADDR_LENGTH], len);
+			if (ret < 0)
+				return ret;
+			loc += len;
+			addr += len;
+			data_len -= len;
+		}
+		return cmd_head.data_len;
+	} else if (cmd_head.wr == 2) {
+		ret = simple_read_from_buffer(page, size, ppos,
+					      IC_TYPE, sizeof(IC_TYPE));
+		return ret;
+	}
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
+	else if (cmd_head.wr == 4) {
+		u8 progress_buf[4];
+
+		progress_buf[0] = show_len >> 8;
+		progress_buf[1] = show_len & 0xff;
+		progress_buf[2] = total_len >> 8;
+		progress_buf[3] = total_len & 0xff;
+
+		ret = simple_read_from_buffer(page, size, ppos,
+					      progress_buf, 4);
+		return ret;
+	}
+#endif
+	else if (cmd_head.wr == 6) {
+		/*Read error code!*/
+	} else if (cmd_head.wr == 8) {	/*Read driver version*/
+		ret = simple_read_from_buffer(page, size, ppos,
+					      GTP_DRIVER_VERSION,
+					      strlen(GTP_DRIVER_VERSION));
+		return ret;
+	}
+
+	return -EPERM;
+}
diff --git a/drivers/input/touchscreen/gt9xx_v2.8/gt9xx.c b/drivers/input/touchscreen/gt9xx_v2.8/gt9xx.c
new file mode 100644
index 0000000..03328d0
--- /dev/null
+++ b/drivers/input/touchscreen/gt9xx_v2.8/gt9xx.c
@@ -0,0 +1,2678 @@
+/*
+ * Goodix GT9xx touchscreen driver
+ *
+ * Copyright  (C)  2016 - 2017 Goodix. Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be a reference
+ * to you, when you are integrating the GOODiX's CTP IC into your system,
+ * 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/irq.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/input/mt.h>
+#include "gt9xx.h"
+
+#define GOODIX_VTG_MIN_UV	2600000
+#define GOODIX_VTG_MAX_UV	3300000
+#define GOODIX_I2C_VTG_MIN_UV	1800000
+#define GOODIX_I2C_VTG_MAX_UV	1800000
+
+#define DELAY_FOR_DISCHARGING		35
+#define GOODIX_COORDS_ARR_SIZE	4
+#define PROP_NAME_SIZE		24
+#define I2C_MAX_TRANSFER_SIZE   255
+#define GTP_PEN_BUTTON1		BTN_STYLUS
+#define GTP_PEN_BUTTON2		BTN_STYLUS2
+
+static const char *goodix_ts_name = "goodix-ts";
+static const char *goodix_input_phys = "input/ts";
+struct i2c_client *i2c_connect_client;
+static struct proc_dir_entry *gtp_config_proc;
+
+enum doze {
+	DOZE_DISABLED = 0,
+	DOZE_ENABLED = 1,
+	DOZE_WAKEUP = 2,
+};
+
+static enum doze doze_status = DOZE_DISABLED;
+
+static int gtp_i2c_test(struct i2c_client *client);
+static int gtp_enter_doze(struct goodix_ts_data *ts);
+
+static int gtp_unregister_powermanager(struct goodix_ts_data *ts);
+static int gtp_register_powermanager(struct goodix_ts_data *ts);
+
+static int gtp_esd_init(struct goodix_ts_data *ts);
+static void gtp_esd_check_func(struct work_struct *);
+static int gtp_init_ext_watchdog(struct i2c_client *client);
+
+/*
+ * return: 2 - ok, < 0 - i2c transfer error
+ */
+int gtp_i2c_read(struct i2c_client *client, u8 *buf, int len)
+{
+	unsigned int transfer_length = 0;
+	unsigned int pos = 0, address = (buf[0] << 8) + buf[1];
+	unsigned char get_buf[64], addr_buf[2];
+	int retry, r = 2;
+	struct i2c_msg msgs[] = {
+		{
+			.addr = client->addr,
+			.flags = !I2C_M_RD,
+			.buf = &addr_buf[0],
+			.len = GTP_ADDR_LENGTH,
+		}, {
+			.addr = client->addr,
+			.flags = I2C_M_RD,
+		}
+	};
+
+	len -= GTP_ADDR_LENGTH;
+	if (likely(len < sizeof(get_buf))) {
+		/* code optimize, use stack memory */
+		msgs[1].buf = &get_buf[0];
+	} else {
+		msgs[1].buf = kzalloc(len > I2C_MAX_TRANSFER_SIZE
+				? I2C_MAX_TRANSFER_SIZE : len, GFP_KERNEL);
+		if (!msgs[1].buf)
+			return -ENOMEM;
+	}
+
+	while (pos != len) {
+		if (unlikely(len - pos > I2C_MAX_TRANSFER_SIZE))
+			transfer_length = I2C_MAX_TRANSFER_SIZE;
+		else
+			transfer_length = len - pos;
+		msgs[0].buf[0] = (address >> 8) & 0xFF;
+		msgs[0].buf[1] = address & 0xFF;
+		msgs[1].len = transfer_length;
+		for (retry = 0; retry < RETRY_MAX_TIMES; retry++) {
+			if (likely(i2c_transfer(client->adapter,
+					msgs, 2) == 2)) {
+				memcpy(&buf[2 + pos], msgs[1].buf,
+					transfer_length);
+				pos += transfer_length;
+				address += transfer_length;
+				break;
+			}
+			dev_dbg(&client->dev, "I2c read retry[%d]:0x%x\n",
+				retry + 1, address);
+			usleep_range(2000, 2100);
+		}
+		if (unlikely(retry == RETRY_MAX_TIMES)) {
+			dev_err(&client->dev,
+				"I2c read failed,dev:%02x,reg:%04x,size:%u\n",
+				client->addr, address, len);
+			r = -EAGAIN;
+			goto read_exit;
+		}
+	}
+read_exit:
+	if (len >= sizeof(get_buf))
+		kfree(msgs[1].buf);
+	return r;
+}
+
+/*******************************************************
+ * Function:
+ *	Write data to the i2c slave device.
+ * Input:
+ *	client: i2c device.
+ *	buf[0~1]: write start address.
+ *	buf[2~len-1]: data buffer
+ *	len: GTP_ADDR_LENGTH + write bytes count
+ * Output:
+ *	numbers of i2c_msgs to transfer:
+ *		1: succeed, otherwise: failed
+ *********************************************************/
+int gtp_i2c_write(struct i2c_client *client, u8 *buf, int len)
+
+{
+	unsigned int pos = 0, transfer_length = 0;
+	unsigned int address = (buf[0] << 8) + buf[1];
+	unsigned char put_buf[64];
+	int retry, r = 1;
+	struct i2c_msg msg = {
+			.addr = client->addr,
+			.flags = !I2C_M_RD,
+	};
+
+	if (likely(len < sizeof(put_buf))) {
+		/* code optimize,use stack memory*/
+		msg.buf = &put_buf[0];
+	} else {
+		msg.buf = kmalloc(len > I2C_MAX_TRANSFER_SIZE
+				  ? I2C_MAX_TRANSFER_SIZE : len, GFP_KERNEL);
+		if (!msg.buf)
+			return -ENOMEM;
+	}
+
+	len -= GTP_ADDR_LENGTH;
+	while (pos != len) {
+		if (unlikely(len - pos > I2C_MAX_TRANSFER_SIZE
+						- GTP_ADDR_LENGTH))
+			transfer_length = I2C_MAX_TRANSFER_SIZE
+						- GTP_ADDR_LENGTH;
+		else
+			transfer_length = len - pos;
+		msg.buf[0] = (unsigned char)((address >> 8) & 0xFF);
+		msg.buf[1] = (unsigned char)(address & 0xFF);
+		msg.len = transfer_length + 2;
+		memcpy(&msg.buf[2], &buf[2 + pos], transfer_length);
+		for (retry = 0; retry < RETRY_MAX_TIMES; retry++) {
+			if (likely(i2c_transfer(client->adapter,
+					&msg, 1) == 1)) {
+				pos += transfer_length;
+				address += transfer_length;
+				break;
+			}
+			dev_dbg(&client->dev, "I2C write retry[%d]\n",
+					retry + 1);
+			usleep_range(2000, 2100);
+		}
+		if (unlikely(retry == RETRY_MAX_TIMES)) {
+			dev_err(&client->dev,
+				"I2c write failed,dev:%02x,reg:%04x,size:%u\n",
+				client->addr, address, len);
+			r = -EAGAIN;
+			goto write_exit;
+		}
+	}
+write_exit:
+	if (len + GTP_ADDR_LENGTH >= sizeof(put_buf))
+		kfree(msg.buf);
+	return r;
+}
+
+/*******************************************************
+ * Function:
+ *	i2c read twice, compare the results
+ * Input:
+ *	client:	i2c device
+ *	addr: operate address
+ *	rxbuf: read data to store, if compare successful
+ *	len: bytes to read
+ * Output:
+ *	FAIL: read failed
+ *	SUCCESS: read successful
+ *********************************************************/
+s32 gtp_i2c_read_dbl_check(struct i2c_client *client,
+			   u16 addr, u8 *rxbuf, int len)
+{
+	u8 buf[16] = {0};
+	u8 confirm_buf[16] = {0};
+	u8 retry = 0;
+
+	if (len + 2 > sizeof(buf)) {
+		dev_warn(&client->dev,
+			 "%s, only support length less then %zu\n",
+			 __func__, sizeof(buf) - 2);
+		return FAIL;
+	}
+	while (retry++ < 3) {
+		memset(buf, 0xAA, 16);
+		buf[0] = (u8)(addr >> 8);
+		buf[1] = (u8)(addr & 0xFF);
+		gtp_i2c_read(client, buf, len + 2);
+
+		memset(confirm_buf, 0xAB, 16);
+		confirm_buf[0] = (u8)(addr >> 8);
+		confirm_buf[1] = (u8)(addr & 0xFF);
+		gtp_i2c_read(client, confirm_buf, len + 2);
+
+		if (!memcmp(buf, confirm_buf, len + 2)) {
+			memcpy(rxbuf, confirm_buf + 2, len);
+			return SUCCESS;
+		}
+	}
+	dev_err(&client->dev,
+		"I2C read 0x%04X, %d bytes, double check failed!\n",
+		addr, len);
+
+	return FAIL;
+}
+
+/*******************************************************
+ * Function:
+ *      Send config.
+ * Input:
+ *      client: i2c device.
+ * Output:
+ *      result of i2c write operation.
+ *              1: succeed, otherwise
+ *              0: Not executed
+ *		< 0: failed
+ *********************************************************/
+s32 gtp_send_cfg(struct i2c_client *client)
+{
+	s32 ret, i;
+	u8 check_sum;
+	s32 retry = 0;
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
+	struct goodix_config_data *cfg = &ts->pdata->config;
+
+	if (!cfg->length || !ts->pdata->driver_send_cfg) {
+		dev_info(&ts->client->dev,
+			 "No config data or error occurred in panel_init\n");
+		return 0;
+	}
+
+	check_sum = 0;
+	for (i = GTP_ADDR_LENGTH; i < cfg->length; i++)
+		check_sum += cfg->data[i];
+	cfg->data[cfg->length] = (~check_sum) + 1;
+
+	dev_info(&ts->client->dev, "Driver send config\n");
+	for (retry = 0; retry < RETRY_MAX_TIMES; retry++) {
+		ret = gtp_i2c_write(client, cfg->data,
+			GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH);
+		if (ret > 0)
+			break;
+	}
+
+	return ret;
+}
+
+/*******************************************************
+ * Function:
+ *	Control enable or disable of work thread.
+ * Input:
+ *      ts: goodix i2c_client private data
+ *	enable: enable var.
+ *********************************************************/
+void gtp_work_control_enable(struct goodix_ts_data *ts, bool enable)
+{
+	if (enable) {
+		set_bit(REPORT_THREAD_ENABLED, &ts->flags);
+		dev_dbg(&ts->client->dev, "Input report thread enabled!\n");
+	} else {
+		clear_bit(REPORT_THREAD_ENABLED, &ts->flags);
+		dev_dbg(&ts->client->dev, "Input report thread disabled!\n");
+	}
+}
+
+static int gtp_gesture_handler(struct goodix_ts_data *ts)
+{
+	u8 doze_buf[3] = {GTP_REG_DOZE_BUF >> 8, GTP_REG_DOZE_BUF & 0xFF};
+	int ret;
+
+	ret = gtp_i2c_read(ts->client, doze_buf, 3);
+	if (ret < 0) {
+		dev_err(&ts->client->dev, "Failed read doze buf");
+		return -EINVAL;
+	}
+
+	dev_dbg(&ts->client->dev, "0x814B = 0x%02X", doze_buf[2]);
+	if ((doze_buf[2] == 'a') || (doze_buf[2] == 'b') ||
+	    (doze_buf[2] == 'c') || (doze_buf[2] == 'd') ||
+	    (doze_buf[2] == 'e') || (doze_buf[2] == 'g') ||
+	    (doze_buf[2] == 'h') || (doze_buf[2] == 'm') ||
+	    (doze_buf[2] == 'o') || (doze_buf[2] == 'q') ||
+	    (doze_buf[2] == 's') || (doze_buf[2] == 'v') ||
+	    (doze_buf[2] == 'w') || (doze_buf[2] == 'y') ||
+	    (doze_buf[2] == 'z') || (doze_buf[2] == 0x5E) ||
+	    (doze_buf[2] == 0xAA) || (doze_buf[2] == 0xAB) ||
+	    (doze_buf[2] == 0xBA) || (doze_buf[2] == 0xBB) ||
+	    (doze_buf[2] == 0xCC)) {
+		doze_status = DOZE_WAKEUP;
+		input_report_key(ts->input_dev, KEY_POWER, 1);
+		input_sync(ts->input_dev);
+		input_report_key(ts->input_dev, KEY_POWER, 0);
+		input_sync(ts->input_dev);
+		/*  clear 0x814B */
+		doze_buf[2] = 0x00;
+		gtp_i2c_write(ts->client, doze_buf, 3);
+	} else {
+		/*  clear 0x814B */
+		doze_buf[2] = 0x00;
+		gtp_i2c_write(ts->client, doze_buf, 3);
+		gtp_enter_doze(ts);
+	}
+	return 0;
+}
+
+/*
+ * return touch state register value
+ * pen event id fixed with 9 and set tool type TOOL_PEN
+ *
+ */
+static u8 gtp_get_points(struct goodix_ts_data *ts,
+			 struct goodix_point_t *points,
+			 u8 *key_value)
+{
+	int ret;
+	int i;
+	u8 *coor_data = NULL;
+	u8 finger_state = 0;
+	u8 touch_num = 0;
+	u8 end_cmd[3] = { GTP_READ_COOR_ADDR >> 8,
+			  GTP_READ_COOR_ADDR & 0xFF, 0 };
+	u8 point_data[2 + 1 + 8 * GTP_MAX_TOUCH_ID + 1] = {
+			GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF };
+
+	ret = gtp_i2c_read(ts->client, point_data, 12);
+	if (ret < 0) {
+		dev_err(&ts->client->dev,
+			"I2C transfer error. errno:%d\n ", ret);
+		return 0;
+	}
+	finger_state = point_data[GTP_ADDR_LENGTH];
+	if (finger_state == 0x00)
+		return 0;
+
+	touch_num = finger_state & 0x0f;
+	if ((finger_state & MASK_BIT_8) == 0 ||
+	    touch_num > ts->pdata->max_touch_id) {
+		dev_err(&ts->client->dev,
+			"Invalid touch state: 0x%x", finger_state);
+		finger_state = 0;
+		goto exit_get_point;
+	}
+
+	if (touch_num > 1) {
+		u8 buf[8 * GTP_MAX_TOUCH_ID] = {
+					  (GTP_READ_COOR_ADDR + 10) >> 8,
+					  (GTP_READ_COOR_ADDR + 10) & 0xff };
+
+		ret = gtp_i2c_read(ts->client, buf, 2 + 8 * (touch_num - 1));
+		if (ret < 0) {
+			dev_err(&ts->client->dev, "I2C error. %d\n", ret);
+			finger_state = 0;
+			goto exit_get_point;
+		}
+		memcpy(&point_data[12], &buf[2], 8 * (touch_num - 1));
+	}
+
+	/* panel have touch key */
+	/* 0x20_UPKEY 0X10_DOWNKEY 0X40_ALLKEYDOWN */
+	*key_value = point_data[3 + 8 * touch_num];
+
+	memset(points, 0, sizeof(*points) * GTP_MAX_TOUCH_ID);
+	for (i = 0; i < touch_num; i++) {
+		coor_data = &point_data[i * 8 + 3];
+		points[i].id = coor_data[0];
+		points[i].x = coor_data[1] | (coor_data[2] << 8);
+		points[i].y = coor_data[3] | (coor_data[4] << 8);
+		points[i].w = coor_data[5] | (coor_data[6] << 8);
+		/* if pen hover points[].p must set to zero */
+		points[i].p = coor_data[5] | (coor_data[6] << 8);
+
+		if (ts->pdata->swap_x2y)
+			GTP_SWAP(points[i].x, points[i].y);
+
+		dev_dbg(&ts->client->dev, "[%d][%d %d %d]\n",
+			points[i].id, points[i].x, points[i].y, points[i].p);
+
+		/* pen device coordinate */
+		if (points[i].id & 0x80) {
+			points[i].tool_type = GTP_TOOL_PEN;
+			points[i].id = 10;
+			if (ts->pdata->pen_suppress_finger) {
+				points[0] = points[i];
+				memset(++points, 0, sizeof(*points) *
+					(GTP_MAX_TOUCH_ID - 1));
+				finger_state &= 0xf0;
+				finger_state |= 0x01;
+				break;
+			}
+		} else {
+			points[i].tool_type = GTP_TOOL_FINGER;
+		}
+	}
+
+exit_get_point:
+	if (!test_bit(RAW_DATA_MODE, &ts->flags)) {
+		ret = gtp_i2c_write(ts->client, end_cmd, 3);
+		if (ret < 0)
+			dev_info(&ts->client->dev, "I2C write end_cmd error!");
+	}
+	return finger_state;
+}
+
+static void gtp_type_a_report(struct goodix_ts_data *ts, u8 touch_num,
+			      struct goodix_point_t *points)
+{
+	int i;
+	u16 cur_touch = 0;
+	static u16 pre_touch;
+	static u8 pre_pen_id;
+
+	if (touch_num)
+		input_report_key(ts->input_dev, BTN_TOUCH, 1);
+
+	for (i = 0; i < ts->pdata->max_touch_id; i++) {
+		if (touch_num && i == points->id) {
+			input_report_abs(ts->input_dev,
+					ABS_MT_TRACKING_ID, points->id);
+
+			if (points->tool_type == GTP_TOOL_PEN) {
+				input_report_key(ts->input_dev,
+							BTN_TOOL_PEN, true);
+				pre_pen_id = points->id;
+			} else {
+				input_report_key(ts->input_dev,
+							BTN_TOOL_FINGER, true);
+			}
+			input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+					 points->x);
+			input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+					 points->y);
+			input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+					 points->w);
+			input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+					 points->p);
+			input_mt_sync(ts->input_dev);
+
+			cur_touch |= 0x01 << points->id;
+			points++;
+		} else if (pre_touch & 0x01 << i) {
+			if (pre_pen_id == i) {
+				input_report_key(ts->input_dev,
+							BTN_TOOL_PEN, false);
+/* valid id will < 10, so id to 0xff to indicate a invalid state */
+				pre_pen_id = 0xff;
+			} else {
+				input_report_key(ts->input_dev,
+					BTN_TOOL_FINGER, false);
+			}
+		}
+	}
+
+	pre_touch = cur_touch;
+	if (!pre_touch) {
+		input_mt_sync(ts->input_dev);
+		input_report_key(ts->input_dev, BTN_TOUCH, 0);
+	}
+	input_sync(ts->input_dev);
+}
+
+static void gtp_mt_slot_report(struct goodix_ts_data *ts, u8 touch_num,
+			       struct goodix_point_t *points)
+{
+	int i;
+	u16 cur_touch = 0;
+	static u16 pre_touch;
+	static u8 pre_pen_id;
+
+	for (i = 0; i < ts->pdata->max_touch_id; i++) {
+		if (touch_num && i == points->id) {
+			input_mt_slot(ts->input_dev, points->id);
+
+			if (points->tool_type == GTP_TOOL_PEN) {
+				input_mt_report_slot_state(ts->input_dev,
+							   MT_TOOL_PEN, true);
+				pre_pen_id = points->id;
+			} else {
+				input_mt_report_slot_state(ts->input_dev,
+						MT_TOOL_FINGER, true);
+			}
+			input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
+					 points->x);
+			input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
+					 points->y);
+			input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+					 points->w);
+			input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
+					 points->p);
+
+			cur_touch |= 0x01 << points->id;
+			points++;
+		} else if (pre_touch & 0x01 << i) {
+			input_mt_slot(ts->input_dev, i);
+			if (pre_pen_id == i) {
+				input_mt_report_slot_state(ts->input_dev,
+							   MT_TOOL_PEN, false);
+				/* valid id will < 10, so set id to 0xff to
+				 * indicate a invalid state
+				 */
+				pre_pen_id = 0xff;
+			} else {
+				input_mt_report_slot_state(ts->input_dev,
+						MT_TOOL_FINGER, false);
+			}
+		}
+	}
+
+	pre_touch = cur_touch;
+	/* report BTN_TOUCH event */
+	input_mt_sync_frame(ts->input_dev);
+	input_sync(ts->input_dev);
+}
+
+/*******************************************************
+ * Function:
+ *	Goodix touchscreen sensor report function
+ * Input:
+ *	ts: goodix tp private data
+ * Output:
+ *	None.
+ *********************************************************/
+static void gtp_work_func(struct goodix_ts_data *ts)
+{
+	u8 point_state = 0;
+	u8 key_value = 0;
+	s32 i = 0;
+	s32 ret = -1;
+	static u8 pre_key;
+	struct goodix_point_t points[GTP_MAX_TOUCH_ID];
+
+	if (test_bit(PANEL_RESETTING, &ts->flags))
+		return;
+	if (!test_bit(REPORT_THREAD_ENABLED, &ts->flags))
+		return;
+
+	/* gesture event */
+	if (ts->pdata->slide_wakeup && test_bit(DOZE_MODE, &ts->flags)) {
+		ret =  gtp_gesture_handler(ts);
+		if (ret)
+			dev_err(&ts->client->dev,
+				"Failed handler gesture event %d\n", ret);
+		return;
+	}
+
+	point_state = gtp_get_points(ts, points, &key_value);
+	if (!point_state) {
+		dev_dbg(&ts->client->dev, "Invalid finger points\n");
+		return;
+	}
+
+	/* touch key event */
+	if (key_value & 0xf0 || pre_key & 0xf0) {
+		/* pen button */
+		switch (key_value) {
+		case 0x40:
+			input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 1);
+			input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 1);
+			break;
+		case 0x10:
+			input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 1);
+			input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 0);
+			dev_dbg(&ts->client->dev, "pen button1 down\n");
+			break;
+		case 0x20:
+			input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 0);
+			input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 1);
+			break;
+		default:
+			input_report_key(ts->input_dev, GTP_PEN_BUTTON1, 0);
+			input_report_key(ts->input_dev, GTP_PEN_BUTTON2, 0);
+			dev_dbg(&ts->client->dev, "button1 up\n");
+			break;
+		}
+		input_sync(ts->input_dev);
+		pre_key = key_value;
+	} else if (key_value & 0x0f || pre_key & 0x0f) {
+		/* panel key */
+		for (i = 0; i < ts->pdata->key_nums; i++) {
+			if ((pre_key | key_value) & (0x01 << i))
+				input_report_key(ts->input_dev,
+						 ts->pdata->key_map[i],
+						 key_value & (0x01 << i));
+		}
+		input_sync(ts->input_dev);
+		pre_key = key_value;
+	}
+
+	if (!ts->pdata->type_a_report)
+		gtp_mt_slot_report(ts, point_state & 0x0f, points);
+	else
+		gtp_type_a_report(ts, point_state & 0x0f, points);
+}
+
+/*******************************************************
+ * Function:
+ *	Timer interrupt service routine for polling mode.
+ * Input:
+ *	timer: timer struct pointer
+ * Output:
+ *	Timer work mode.
+ * HRTIMER_NORESTART:
+ *	no restart mode
+ *********************************************************/
+static enum hrtimer_restart gtp_timer_handler(struct hrtimer *timer)
+{
+	struct goodix_ts_data *ts =
+		container_of(timer, struct goodix_ts_data, timer);
+
+	gtp_work_func(ts);
+	hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME + 6) * 1000000),
+		      HRTIMER_MODE_REL);
+
+	return HRTIMER_NORESTART;
+}
+
+static irqreturn_t gtp_irq_handler(int irq, void *dev_id)
+{
+	struct goodix_ts_data *ts = dev_id;
+
+	gtp_work_func(ts);
+	return IRQ_HANDLED;
+}
+
+void gtp_int_output(struct goodix_ts_data *ts, int level)
+{
+	if (!ts->pdata->int_sync)
+		return;
+
+	if (level == 0) {
+		if (ts->pinctrl.pinctrl)
+			pinctrl_select_state(ts->pinctrl.pinctrl,
+					     ts->pinctrl.int_out_low);
+		else if (gpio_is_valid(ts->pdata->irq_gpio))
+			gpio_direction_output(ts->pdata->irq_gpio, 0);
+		else
+			dev_err(&ts->client->dev,
+				"Failed set int pin output low\n");
+	} else {
+		if (ts->pinctrl.pinctrl)
+			pinctrl_select_state(ts->pinctrl.pinctrl,
+					     ts->pinctrl.int_out_high);
+		else if (gpio_is_valid(ts->pdata->irq_gpio))
+			gpio_direction_output(ts->pdata->irq_gpio, 1);
+		else
+			dev_err(&ts->client->dev,
+				"Failed set int pin output high\n");
+	}
+}
+
+void gtp_int_sync(struct goodix_ts_data *ts, s32 ms)
+{
+	if (!ts->pdata->int_sync)
+		return;
+
+	if (ts->pinctrl.pinctrl) {
+		gtp_int_output(ts, 0);
+		msleep(ms);
+		pinctrl_select_state(ts->pinctrl.pinctrl,
+				     ts->pinctrl.int_input);
+	} else if (gpio_is_valid(ts->pdata->irq_gpio)) {
+		gpio_direction_output(ts->pdata->irq_gpio, 0);
+		msleep(ms);
+		gpio_direction_input(ts->pdata->irq_gpio);
+	} else {
+		dev_err(&ts->client->dev, "Failed sync int pin\n");
+	}
+}
+
+void gtp_rst_output(struct goodix_ts_data *ts, int level)
+{
+	if (level == 0) {
+		if (ts->pinctrl.pinctrl)
+			pinctrl_select_state(ts->pinctrl.pinctrl,
+					     ts->pinctrl.rst_out_low);
+		else if (gpio_is_valid(ts->pdata->rst_gpio))
+			gpio_direction_output(ts->pdata->rst_gpio, 0);
+		else
+			dev_err(&ts->client->dev,
+				"Failed set rst pin output low\n");
+	} else {
+		if (ts->pinctrl.pinctrl)
+			pinctrl_select_state(ts->pinctrl.pinctrl,
+					     ts->pinctrl.rst_out_high);
+		else if (gpio_is_valid(ts->pdata->rst_gpio))
+			gpio_direction_output(ts->pdata->rst_gpio, 1);
+		else
+			dev_err(&ts->client->dev,
+				"Failed set rst pin output high\n");
+	}
+}
+
+void gtp_rst_input(struct goodix_ts_data *ts)
+{
+	if (ts->pinctrl.pinctrl)
+		pinctrl_select_state(ts->pinctrl.pinctrl,
+					 ts->pinctrl.rst_input);
+	else if (gpio_is_valid(ts->pdata->rst_gpio))
+		gpio_direction_input(ts->pdata->rst_gpio);
+	else
+		dev_err(&ts->client->dev,
+			"Failed set rst pin input\n");
+}
+
+/*******************************************************
+ * Function:
+ *	Reset chip. Control the reset pin and int-pin(if
+ *	defined),
+ * Input:
+ *	client:	i2c device.
+ *	ms: reset time in millisecond
+ * Output:
+ *	None.
+ *******************************************************/
+void gtp_reset_guitar(struct i2c_client *client, s32 ms)
+{
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+	dev_info(&client->dev, "Guitar reset");
+	set_bit(PANEL_RESETTING, &ts->flags);
+	if (!gpio_is_valid(ts->pdata->rst_gpio)) {
+		dev_warn(&client->dev, "reset failed no valid reset gpio");
+		return;
+	}
+
+	gtp_rst_output(ts, 0);
+	usleep_range(ms * 1000, ms * 1000 + 100);	/*  T2: > 10ms */
+
+	gtp_int_output(ts, client->addr == 0x14);
+
+	usleep_range(2000, 3000);		/*  T3: > 100us (2ms)*/
+	gtp_rst_output(ts, 1);
+
+	usleep_range(6000, 7000);		/*  T4: > 5ms */
+	gtp_rst_input(ts);
+
+	gtp_int_sync(ts, 50);
+	if (ts->pdata->esd_protect)
+		gtp_init_ext_watchdog(client);
+
+	clear_bit(PANEL_RESETTING, &ts->flags);
+}
+
+/*******************************************************
+ * Function:
+ *	Enter doze mode for sliding wakeup.
+ * Input:
+ *	ts: goodix tp private data
+ * Output:
+ *	1: succeed, otherwise failed
+ *******************************************************/
+static int gtp_enter_doze(struct goodix_ts_data *ts)
+{
+	int ret = -1;
+	int retry = 0;
+	u8 i2c_control_buf[3] = { (u8)(GTP_REG_COMMAND >> 8),
+				  (u8)GTP_REG_COMMAND, 8 };
+
+	/*  resend doze command
+	 * if (test_and_set_bit(DOZE_MODE, &ts->flags)) {
+	 *	dev_info(&ts->client->dev, "Already in doze mode\n");
+	 *	return SUCCESS;
+	 * }
+	 */
+	set_bit(DOZE_MODE, &ts->flags);
+	dev_dbg(&ts->client->dev, "Entering gesture mode.");
+	while (retry++ < 5) {
+		i2c_control_buf[0] = (u8)(GTP_REG_COMMAND_CHECK >> 8);
+		i2c_control_buf[1] = (u8)GTP_REG_COMMAND_CHECK;
+		ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
+		if (ret < 0) {
+			dev_dbg(&ts->client->dev,
+				"failed to set doze flag into 0x8046, %d\n",
+				retry);
+			continue;
+		}
+		i2c_control_buf[0] = (u8)(GTP_REG_COMMAND >> 8);
+		i2c_control_buf[1] = (u8)GTP_REG_COMMAND;
+		ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
+		if (ret > 0) {
+			dev_dbg(&ts->client->dev, "Gesture mode enabled\n");
+			return ret;
+		}
+		usleep_range(10000, 11000);
+	}
+
+	dev_err(&ts->client->dev, "Failed enter doze mode\n");
+	clear_bit(DOZE_MODE, &ts->flags);
+	return ret;
+}
+
+static s8 gtp_enter_sleep(struct goodix_ts_data *ts)
+{
+	s8 ret = -1;
+	s8 retry = 0;
+	u8 i2c_control_buf[3] = { (u8)(GTP_REG_COMMAND >> 8),
+				  (u8)GTP_REG_COMMAND, 5 };
+
+	gtp_int_output(ts, 0);
+	usleep_range(5000, 6000);
+
+	while (retry++ < 5) {
+		ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
+		if (ret > 0) {
+			dev_info(&ts->client->dev, "Enter sleep mode\n");
+
+			return ret;
+		}
+		usleep_range(10000, 11000);
+	}
+	dev_err(&ts->client->dev, "Failed send sleep cmd\n");
+
+	return ret;
+}
+
+static int gtp_wakeup_sleep(struct goodix_ts_data *ts)
+{
+	u8 retry = 0;
+	int ret = -1;
+
+	while (retry++ < 10) {
+		gtp_int_output(ts, 1);
+		usleep_range(5000, 6000);
+
+		ret = gtp_i2c_test(ts->client);
+		if (!ret) {
+			dev_dbg(&ts->client->dev, "Success wakeup sleep\n");
+
+			gtp_int_sync(ts, 25);
+			if (ts->pdata->esd_protect)
+				gtp_init_ext_watchdog(ts->client);
+
+			return ret;
+		}
+		gtp_reset_guitar(ts->client, 20);
+	}
+
+	dev_err(&ts->client->dev, "Failed wakeup from sleep mode\n");
+	return -EINVAL;
+}
+
+static int gtp_find_valid_cfg_data(struct goodix_ts_data *ts)
+{
+	int ret = -1;
+	u8 sensor_id = 0;
+	struct goodix_config_data *cfg = &ts->pdata->config;
+
+	/* if defined CONFIG_OF, parse config data from dtsi
+	 * else parse config data form header file.
+	 */
+	cfg->length = 0;
+
+#ifndef	CONFIG_OF
+	u8 cfg_info_group0[] = CTP_CFG_GROUP0;
+	u8 cfg_info_group1[] = CTP_CFG_GROUP1;
+	u8 cfg_info_group2[] = CTP_CFG_GROUP2;
+	u8 cfg_info_group3[] = CTP_CFG_GROUP3;
+	u8 cfg_info_group4[] = CTP_CFG_GROUP4;
+	u8 cfg_info_group5[] = CTP_CFG_GROUP5;
+
+	u8 *send_cfg_buf[] = { cfg_info_group0, cfg_info_group1,
+			       cfg_info_group2, cfg_info_group3,
+			       cfg_info_group4, cfg_info_group5 };
+	u8 cfg_info_len[] = { CFG_GROUP_LEN(cfg_info_group0),
+			      CFG_GROUP_LEN(cfg_info_group1),
+			      CFG_GROUP_LEN(cfg_info_group2),
+			      CFG_GROUP_LEN(cfg_info_group3),
+			      CFG_GROUP_LEN(cfg_info_group4),
+			      CFG_GROUP_LEN(cfg_info_group5)};
+
+	dev_dbg(&ts->client->dev,
+		"Config Groups\' Lengths: %d, %d, %d, %d, %d, %d",
+		cfg_info_len[0], cfg_info_len[1], cfg_info_len[2],
+		cfg_info_len[3], cfg_info_len[4], cfg_info_len[5]);
+#endif
+
+	/* read sensor id */
+	ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID,
+				     &sensor_id, 1);
+	if (ret != SUCCESS || sensor_id >= 0x06) {
+		dev_err(&ts->client->dev,
+			"Failed get valid sensor_id(0x%02X), No Config Sent\n",
+			sensor_id);
+		return -EINVAL;
+	}
+
+	dev_dbg(&ts->client->dev, "Sensor_ID: %d", sensor_id);
+	/* parse config data */
+#ifdef CONFIG_OF
+	dev_dbg(&ts->client->dev, "Get config data from device tree\n");
+	ret = gtp_parse_dt_cfg(&ts->client->dev,
+			       &cfg->data[GTP_ADDR_LENGTH],
+			       &cfg->length, sensor_id);
+	if (ret < 0) {
+		dev_err(&ts->client->dev,
+			"Failed to parse config data form device tree\n");
+		cfg->length = 0;
+		return -EPERM;
+	}
+#else
+	dev_dbg(&ts->client->dev, "Get config data from header file\n");
+	if ((!cfg_info_len[1]) && (!cfg_info_len[2]) &&
+	    (!cfg_info_len[3]) && (!cfg_info_len[4]) &&
+	    (!cfg_info_len[5])) {
+		sensor_id = 0;
+	}
+	cfg->length = cfg_info_len[sensor_id];
+	memset(&cfg->data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);
+	memcpy(&cfg->data[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id],
+	       cfg->length);
+#endif
+
+	if (cfg->length < GTP_CONFIG_MIN_LENGTH) {
+		dev_err(&ts->client->dev,
+			"Failed get valid config data with sensor id %d\n",
+			sensor_id);
+		cfg->length = 0;
+		return -EPERM;
+	}
+
+	dev_info(&ts->client->dev, "Config group%d used,length: %d\n",
+		 sensor_id, cfg->length);
+
+	return 0;
+}
+
+/*******************************************************
+ * Function:
+ *	Get valid config data from dts or .h file.
+ *	Read firmware version info and judge firmware
+ *	working state
+ * Input:
+ *	ts: goodix private data
+ * Output:
+ *	Executive outcomes.
+ *		0: succeed, otherwise: failed
+ *******************************************************/
+static s32 gtp_init_panel(struct goodix_ts_data *ts)
+{
+	s32 ret = -1;
+	u8 opr_buf[16] = {0};
+	u8 drv_cfg_version = 0;
+	u8 flash_cfg_version = 0;
+	struct goodix_config_data *cfg = &ts->pdata->config;
+
+	if (!ts->pdata->driver_send_cfg) {
+		dev_info(&ts->client->dev, "Driver set not send config\n");
+		cfg->length = GTP_CONFIG_MAX_LENGTH;
+		ret = gtp_i2c_read(ts->client,
+				   cfg->data, cfg->length +
+				   GTP_ADDR_LENGTH);
+		if (ret < 0)
+			dev_err(&ts->client->dev, "Read origin Config Failed\n");
+
+		return 0;
+	}
+
+	gtp_find_valid_cfg_data(ts);
+
+	/* check firmware */
+	ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1);
+	if (ret == SUCCESS) {
+		if (opr_buf[0] != 0xBE) {
+			set_bit(FW_ERROR, &ts->flags);
+			dev_err(&ts->client->dev,
+				"Firmware error, no config sent!\n");
+			return -EINVAL;
+		}
+	}
+
+	ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA,
+				     &opr_buf[0], 1);
+	if (ret == SUCCESS) {
+		dev_dbg(&ts->client->dev,
+			"Config Version: %d; IC Config Version: %d\n",
+			cfg->data[GTP_ADDR_LENGTH], opr_buf[0]);
+		flash_cfg_version = opr_buf[0];
+		drv_cfg_version = cfg->data[GTP_ADDR_LENGTH];
+
+		if (flash_cfg_version < 120 &&
+		    flash_cfg_version > drv_cfg_version)
+			cfg->data[GTP_ADDR_LENGTH] = 0x00;
+	} else {
+		dev_err(&ts->client->dev,
+			"Failed to get ic config version!No config sent\n");
+		return -EPERM;
+	}
+
+	ret = gtp_send_cfg(ts->client);
+	if (ret < 0)
+		dev_err(&ts->client->dev, "Send config error\n");
+	else
+		usleep_range(10000, 11000); /* 10 ms */
+
+	/* restore config version */
+	cfg->data[GTP_ADDR_LENGTH] = drv_cfg_version;
+
+	return 0;
+}
+
+static ssize_t gtp_config_read_proc(struct file *file, char __user *page,
+				    size_t size, loff_t *ppos)
+{
+	int i, ret;
+	char *ptr;
+	size_t data_len = 0;
+	char temp_data[GTP_CONFIG_MAX_LENGTH + 2] = {
+					(u8)(GTP_REG_CONFIG_DATA >> 8),
+					(u8)GTP_REG_CONFIG_DATA };
+	struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client);
+	struct goodix_config_data *cfg = &ts->pdata->config;
+
+	ptr = kzalloc(4096, GFP_KERNEL);
+	if (!ptr)
+		return -ENOMEM;
+
+	data_len += snprintf(ptr + data_len, 4096 - data_len,
+			     "====init value====\n");
+	for (i = 0 ; i < GTP_CONFIG_MAX_LENGTH ; i++) {
+		data_len += snprintf(ptr + data_len, 4096 - data_len,
+				     "0x%02X ", cfg->data[i + 2]);
+
+		if (i % 8 == 7)
+			data_len += snprintf(ptr + data_len,
+					     4096 - data_len, "\n");
+	}
+	data_len += snprintf(ptr + data_len, 4096 - data_len, "\n");
+
+	data_len += snprintf(ptr + data_len, 4096 - data_len,
+			     "====real value====\n");
+	ret = gtp_i2c_read(i2c_connect_client, temp_data,
+			   GTP_CONFIG_MAX_LENGTH + 2);
+	if (ret < 0) {
+		data_len += snprintf(ptr + data_len, 4096 - data_len,
+				     "Failed read real config data\n");
+	} else {
+		for (i = 0; i < GTP_CONFIG_MAX_LENGTH; i++) {
+			data_len += snprintf(ptr + data_len, 4096 - data_len,
+					     "0x%02X ", temp_data[i + 2]);
+
+			if (i % 8 == 7)
+				data_len += snprintf(ptr + data_len,
+						     4096 - data_len, "\n");
+		}
+	}
+
+	data_len = simple_read_from_buffer(page, size, ppos, ptr, data_len);
+	kfree(ptr);
+	ptr = NULL;
+	return data_len;
+}
+
+int gtp_ascii_to_array(const u8 *src_buf, int src_len, u8 *dst_buf)
+{
+	int i, ret;
+	int cfg_len = 0;
+	long val;
+	char temp_buf[5];
+
+	for (i = 0; i < src_len;) {
+		if (src_buf[i] == ' ' || src_buf[i] == '\r' ||
+		    src_buf[i] == '\n') {
+			i++;
+			continue;
+		}
+
+		temp_buf[0] = src_buf[i];
+		temp_buf[1] = src_buf[i + 1];
+		temp_buf[2] = src_buf[i + 2];
+		temp_buf[3] = src_buf[i + 3];
+		temp_buf[4] = '\0';
+		if (!kstrtol(temp_buf, 16, &val)) {
+			if (cfg_len < GTP_CONFIG_MAX_LENGTH) {
+				dst_buf[cfg_len++] = val & 0xFF;
+				i += 5;
+			} else {
+				ret = -2;
+				goto convert_failed;
+			}
+		} else {
+			ret = -3;
+			goto convert_failed;
+		}
+	}
+	return cfg_len;
+
+convert_failed:
+	return ret;
+}
+
+static ssize_t gtp_config_write_proc(struct file *filp,
+				     const char __user *buffer,
+				     size_t count, loff_t *off)
+{
+	u8 *temp_buf;
+	u8 *file_config;
+	int file_cfg_len;
+	s32 ret = 0, i;
+	struct goodix_ts_data *ts = i2c_get_clientdata(i2c_connect_client);
+
+	dev_dbg(&ts->client->dev, "write count %zu\n", count);
+
+	if (count > PAGE_SIZE) {
+		dev_err(&ts->client->dev, "config to long %zu\n", count);
+		return -EFAULT;
+	}
+
+	temp_buf = kzalloc(count, GFP_KERNEL);
+	if (!temp_buf)
+		return -ENOMEM;
+
+	file_config = kzalloc(GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH,
+			      GFP_KERNEL);
+	if (!file_config) {
+		kfree(temp_buf);
+		return -ENOMEM;
+	}
+	file_config[0] = GTP_REG_CONFIG_DATA >> 8;
+	file_config[1] = GTP_REG_CONFIG_DATA & 0xff;
+
+	if (copy_from_user(temp_buf, buffer, count)) {
+		dev_err(&ts->client->dev, "Failed copy from user\n");
+		ret = -EFAULT;
+		goto send_cfg_err;
+	}
+
+	file_cfg_len = gtp_ascii_to_array(temp_buf, (int)count,
+					  &file_config[GTP_ADDR_LENGTH]);
+	if (file_cfg_len < 0) {
+		dev_err(&ts->client->dev, "failed covert ascii to hex");
+		ret = -EFAULT;
+		goto send_cfg_err;
+	}
+
+	GTP_DEBUG_ARRAY(file_config + GTP_ADDR_LENGTH, file_cfg_len);
+
+	i = 0;
+	while (i++ < 5) {
+		ret = gtp_i2c_write(ts->client, file_config, file_cfg_len + 2);
+		if (ret > 0) {
+			dev_info(&ts->client->dev, "Send config SUCCESS.");
+			break;
+		}
+		dev_err(&ts->client->dev, "Send config i2c error.");
+		ret = -EFAULT;
+		goto send_cfg_err;
+	}
+
+	ret = count;
+send_cfg_err:
+	kfree(temp_buf);
+	kfree(file_config);
+	return ret;
+}
+
+static const struct file_operations config_proc_ops = {
+	.owner = THIS_MODULE,
+	.read = gtp_config_read_proc,
+	.write = gtp_config_write_proc,
+};
+
+static ssize_t gtp_workmode_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	size_t data_len = 0;
+	struct goodix_ts_data *data = dev_get_drvdata(dev);
+
+	if (test_bit(DOZE_MODE, &data->flags))
+		data_len = scnprintf(buf, PAGE_SIZE, "%s\n",
+				     "doze_mode");
+	else if (test_bit(SLEEP_MODE, &data->flags))
+		data_len = scnprintf(buf, PAGE_SIZE, "%s\n",
+				     "sleep_mode");
+	else
+		data_len = scnprintf(buf, PAGE_SIZE, "%s\n",
+				     "normal_mode");
+
+	return data_len;
+}
+static DEVICE_ATTR(workmode, 0444, gtp_workmode_show, NULL);
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
+#define FW_NAME_MAX_LEN	80
+static ssize_t gtp_dofwupdate_store(struct device *dev,
+				    struct device_attribute *attr,
+				    const char *buf, size_t count)
+{
+	struct goodix_ts_data *ts = dev_get_drvdata(dev);
+	char update_file_name[FW_NAME_MAX_LEN];
+	int retval;
+
+	if (count > FW_NAME_MAX_LEN) {
+		dev_info(&ts->client->dev, "FW filename is too long\n");
+		retval = -EINVAL;
+		goto exit;
+	}
+
+	strlcpy(update_file_name, buf, count);
+
+	ts->force_update = true;
+	retval = gup_update_proc(update_file_name);
+	if (retval == FAIL)
+		dev_err(&ts->client->dev, "Fail to update GTP firmware.\n");
+	else
+		dev_info(&ts->client->dev, "Update success\n");
+
+	return count;
+
+exit:
+	return retval;
+}
+static DEVICE_ATTR(dofwupdate, 0664, NULL, gtp_dofwupdate_store);
+#endif
+
+static ssize_t gtp_productinfo_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct goodix_ts_data *data = dev_get_drvdata(dev);
+	struct goodix_fw_info *fw_info = &data->fw_info;
+
+	return scnprintf(buf, PAGE_SIZE, "GT%s_%x_%d\n",
+			 fw_info->pid, fw_info->version, fw_info->sensor_id);
+}
+static DEVICE_ATTR(productinfo, 0444, gtp_productinfo_show, NULL);
+
+static ssize_t gtp_drv_irq_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	unsigned long value = 0;
+	int err = 0;
+	struct goodix_ts_data *data = dev_get_drvdata(dev);
+
+	err = kstrtoul(buf, 10, &value);
+	if (err < 0) {
+		dev_err(dev, "Failed to convert value\n");
+		return -EINVAL;
+	}
+
+	switch (value) {
+	case 0:
+		/* Disable irq */
+		gtp_work_control_enable(data, false);
+		break;
+	case 1:
+		/* Enable irq */
+		gtp_work_control_enable(data, true);
+		break;
+	default:
+		dev_err(dev, "Invalid value\n");
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static ssize_t gtp_drv_irq_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct goodix_ts_data *data = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%s\n",
+			 test_bit(REPORT_THREAD_ENABLED, &data->flags)
+			 ? "enabled" : "disabled");
+}
+static DEVICE_ATTR(drv_irq, 0664, gtp_drv_irq_show, gtp_drv_irq_store);
+
+static ssize_t gtp_reset_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct goodix_ts_data *data = dev_get_drvdata(dev);
+
+	if ('1' != buf[0]) {
+		dev_err(dev, "Invalid argument for reset\n");
+		return -EINVAL;
+	}
+
+	gtp_reset_guitar(data->client, 20);
+
+	return count;
+}
+static DEVICE_ATTR(reset, 0220, NULL, gtp_reset_store);
+
+static struct attribute *gtp_attrs[] = {
+	&dev_attr_workmode.attr,
+	&dev_attr_productinfo.attr,
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
+	&dev_attr_dofwupdate.attr,
+#endif
+
+	&dev_attr_drv_irq.attr,
+	&dev_attr_reset.attr,
+	NULL
+};
+
+static const struct attribute_group gtp_attr_group = {
+	.attrs = gtp_attrs,
+};
+
+static int gtp_create_file(struct goodix_ts_data *ts)
+{
+	int ret;
+	struct i2c_client *client = ts->client;
+
+	/*  Create proc file system */
+	gtp_config_proc = NULL;
+	gtp_config_proc = proc_create(GT91XX_CONFIG_PROC_FILE, 0664,
+				      NULL, &config_proc_ops);
+	if (!gtp_config_proc)
+		dev_err(&client->dev, "create_proc_entry %s failed\n",
+			GT91XX_CONFIG_PROC_FILE);
+	else
+		dev_info(&client->dev, "create proc entry %s success\n",
+			 GT91XX_CONFIG_PROC_FILE);
+
+	ret = sysfs_create_group(&client->dev.kobj, &gtp_attr_group);
+	if (ret) {
+		dev_err(&client->dev, "Failure create sysfs group %d\n", ret);
+		/*TODO: debug change */
+		goto exit_free_config_proc;
+	}
+	return 0;
+
+exit_free_config_proc:
+	remove_proc_entry(GT91XX_CONFIG_PROC_FILE, gtp_config_proc);
+	return -ENODEV;
+}
+
+s32 gtp_get_fw_info(struct i2c_client *client, struct goodix_fw_info *fw_info)
+{
+	s32 ret = -1;
+	u8 buf[8] = {GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff};
+
+	ret = gtp_i2c_read(client, buf, sizeof(buf));
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed read fw_info\n");
+		return ret;
+	}
+
+	/* product id */
+	memset(fw_info, 0, sizeof(*fw_info));
+
+	if (buf[5] == 0x00) {
+		memcpy(fw_info->pid, buf + GTP_ADDR_LENGTH, 3);
+		dev_info(&client->dev, "IC Version: %c%c%c_%02X%02X\n",
+			 buf[2], buf[3], buf[4], buf[7], buf[6]);
+	} else {
+		memcpy(fw_info->pid, buf + GTP_ADDR_LENGTH, 4);
+		dev_info(&client->dev, "IC Version: %c%c%c%c_%02X%02X\n",
+			 buf[2], buf[3], buf[4], buf[5], buf[7], buf[6]);
+	}
+
+	/* current firmware version */
+	fw_info->version = (buf[7] << 8) | buf[6];
+
+	/* read sensor id */
+	fw_info->sensor_id = 0xff;
+	ret = gtp_i2c_read_dbl_check(client, GTP_REG_SENSOR_ID,
+				     &fw_info->sensor_id, 1);
+	if (ret != SUCCESS || fw_info->sensor_id >= 0x06) {
+		dev_err(&client->dev,
+			"Failed get valid sensor_id(0x%02X), No Config Sent\n",
+			fw_info->sensor_id);
+
+		fw_info->sensor_id = 0xff;
+	}
+
+	return ret;
+}
+
+static int gtp_i2c_test(struct i2c_client *client)
+{
+	u8 test[3] = {GTP_REG_CONFIG_DATA >> 8, GTP_REG_CONFIG_DATA & 0xff};
+	u8 retry = 0;
+	int ret = -1;
+
+	while (retry++ < 3) {
+		ret = gtp_i2c_read(client, test, 3);
+		if (ret == 2)
+			return 0;
+
+		dev_err(&client->dev, "GTP i2c test failed time %d\n", retry);
+		usleep_range(10000, 11000); /* 10 ms */
+	}
+
+	return -EAGAIN;
+}
+
+static int gtp_pinctrl_init(struct goodix_ts_data *ts)
+{
+	struct goodix_pinctrl *pinctrl = &ts->pinctrl;
+
+	pinctrl->pinctrl = devm_pinctrl_get(&ts->client->dev);
+	if (IS_ERR_OR_NULL(pinctrl->pinctrl)) {
+		dev_info(&ts->client->dev, "No pinctrl found\n");
+		pinctrl->pinctrl = NULL;
+		return 0;
+	}
+
+	/* INT pinctrl */
+	pinctrl->int_default = pinctrl_lookup_state(pinctrl->pinctrl,
+						    "gdix_ts_int_default");
+	if (IS_ERR_OR_NULL(pinctrl->int_default)) {
+		dev_info(&ts->client->dev,
+			 "Failed get pinctrl state:INT default state\n");
+		goto exit_pinctrl_init;
+	}
+
+	pinctrl->int_out_high = pinctrl_lookup_state(pinctrl->pinctrl,
+						     "gdix_ts_int_output_high");
+	if (IS_ERR_OR_NULL(pinctrl->int_out_high)) {
+		dev_info(&ts->client->dev,
+			 "Failed get pinctrl state:INT output_high\n");
+		goto exit_pinctrl_init;
+	}
+
+	pinctrl->int_out_low = pinctrl_lookup_state(pinctrl->pinctrl,
+						    "gdix_ts_int_output_low");
+	if (IS_ERR_OR_NULL(pinctrl->int_out_low)) {
+		dev_info(&ts->client->dev,
+			 "Failed get pinctrl state:INT output_low\n");
+		goto exit_pinctrl_init;
+	}
+
+	pinctrl->int_input = pinctrl_lookup_state(pinctrl->pinctrl,
+						  "gdix_ts_int_input");
+	if (IS_ERR_OR_NULL(pinctrl->int_input)) {
+		dev_info(&ts->client->dev,
+			 "Failed get pinctrl state:int-input\n");
+		goto exit_pinctrl_init;
+	}
+	dev_info(&ts->client->dev, "Success init INT pinctrl\n");
+
+	/* RST pinctrl */
+	pinctrl->rst_default = pinctrl_lookup_state(pinctrl->pinctrl,
+						    "gdix_ts_rst_default");
+	if (IS_ERR_OR_NULL(pinctrl->rst_default)) {
+		dev_info(&ts->client->dev,
+			 "Failed get pinctrl state:RST default state\n");
+		goto exit_pinctrl_init;
+	}
+
+	pinctrl->rst_out_high = pinctrl_lookup_state(pinctrl->pinctrl,
+						     "gdix_ts_rst_output_high");
+	if (IS_ERR_OR_NULL(pinctrl->rst_out_high)) {
+		dev_info(&ts->client->dev,
+			 "Failed get pinctrl state:RST output_high\n");
+		goto exit_pinctrl_init;
+	}
+
+	pinctrl->rst_out_low = pinctrl_lookup_state(pinctrl->pinctrl,
+						    "gdix_ts_rst_output_low");
+	if (IS_ERR_OR_NULL(pinctrl->rst_out_low)) {
+		dev_info(&ts->client->dev,
+			 "Failed get pinctrl state:RST output_low\n");
+		goto exit_pinctrl_init;
+	}
+
+	pinctrl->rst_input = pinctrl_lookup_state(pinctrl->pinctrl,
+						  "gdix_ts_rst_input");
+	if (IS_ERR_OR_NULL(pinctrl->rst_input)) {
+		dev_info(&ts->client->dev,
+			 "Failed get pinctrl state:rst-input\n");
+		goto exit_pinctrl_init;
+	}
+	dev_info(&ts->client->dev, "Success init RST pinctrl\n");
+
+	return 0;
+exit_pinctrl_init:
+	devm_pinctrl_put(pinctrl->pinctrl);
+	pinctrl->pinctrl = NULL;
+	pinctrl->int_default = NULL;
+	pinctrl->int_out_high = NULL;
+	pinctrl->int_out_low = NULL;
+	pinctrl->int_input = NULL;
+	pinctrl->rst_default = NULL;
+	pinctrl->rst_out_high = NULL;
+	pinctrl->rst_out_low = NULL;
+	pinctrl->rst_input = NULL;
+	return -EINVAL;
+}
+
+static void gtp_pinctrl_deinit(struct goodix_ts_data *ts)
+{
+	if (ts->pinctrl.pinctrl)
+		devm_pinctrl_put(ts->pinctrl.pinctrl);
+}
+
+static int gtp_request_io_port(struct goodix_ts_data *ts)
+{
+	int ret = 0;
+
+	if (gpio_is_valid(ts->pdata->irq_gpio)) {
+		ret = gpio_request(ts->pdata->irq_gpio, "goodix_ts_int");
+		if (ret < 0) {
+			dev_err(&ts->client->dev,
+				"Failed to request GPIO:%d, ERRNO:%d\n",
+				(s32)ts->pdata->irq_gpio, ret);
+			return -ENODEV;
+		}
+
+		gpio_direction_input(ts->pdata->irq_gpio);
+		dev_info(&ts->client->dev, "Success request irq-gpio\n");
+	}
+
+	if (gpio_is_valid(ts->pdata->rst_gpio)) {
+		ret = gpio_request(ts->pdata->rst_gpio, "goodix_ts_rst");
+		if (ret < 0) {
+			dev_err(&ts->client->dev,
+				"Failed to request GPIO:%d, ERRNO:%d\n",
+				(s32)ts->pdata->rst_gpio, ret);
+
+			if (gpio_is_valid(ts->pdata->irq_gpio))
+				gpio_free(ts->pdata->irq_gpio);
+
+			return -ENODEV;
+		}
+
+		gpio_direction_input(ts->pdata->rst_gpio);
+		dev_info(&ts->client->dev,  "Success request rst-gpio\n");
+	}
+
+	return 0;
+}
+
+/*******************************************************
+ * Function:
+ *	Request interrupt if define irq pin, else use hrtimer
+ *	as interrupt source
+ * Input:
+ *	ts: private data.
+ * Output:
+ *	Executive outcomes.
+ *		0: succeed, -1: failed.
+ *******************************************************/
+static int gtp_request_irq(struct goodix_ts_data *ts)
+{
+	int ret = -1;
+
+	/* use irq */
+	if (gpio_is_valid(ts->pdata->irq_gpio) || ts->client->irq > 0) {
+		if (gpio_is_valid(ts->pdata->irq_gpio))
+			ts->client->irq = gpio_to_irq(ts->pdata->irq_gpio);
+
+		dev_info(&ts->client->dev, "INT num %d, trigger type:%d\n",
+			 ts->client->irq, ts->pdata->irq_flags);
+		ret = request_threaded_irq(ts->client->irq, NULL,
+				gtp_irq_handler,
+				ts->pdata->irq_flags | IRQF_ONESHOT,
+				ts->client->name,
+				ts);
+		if (ret < 0) {
+			dev_err(&ts->client->dev,
+				"Failed to request irq %d\n", ts->client->irq);
+			return ret;
+		}
+	} else { /* use hrtimer */
+		dev_info(&ts->client->dev, "No hardware irq, use hrtimer\n");
+		hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+		ts->timer.function = gtp_timer_handler;
+		hrtimer_start(&ts->timer,
+			      ktime_set(0, (GTP_POLL_TIME + 6) * 1000000),
+			      HRTIMER_MODE_REL);
+		set_bit(HRTIMER_USED, &ts->flags);
+		ret = 0;
+	}
+	return ret;
+}
+
+static s8 gtp_request_input_dev(struct goodix_ts_data *ts)
+{
+	s8 ret = -1;
+	u8 index = 0;
+
+	ts->input_dev = input_allocate_device();
+	if (!ts->input_dev) {
+		dev_err(&ts->client->dev, "Failed to allocate input device\n");
+		return -ENOMEM;
+	}
+
+	ts->input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY)
+		| BIT_MASK(EV_ABS);
+	if (!ts->pdata->type_a_report) {
+		input_mt_init_slots(ts->input_dev, 16, INPUT_MT_DIRECT);
+		dev_info(&ts->client->dev, "Use slot report protocol\n");
+	} else {
+		__set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
+		__set_bit(BTN_TOUCH, ts->input_dev->keybit);
+		dev_info(&ts->client->dev, "Use type A report protocol\n");
+	}
+
+	input_set_capability(ts->input_dev, EV_KEY, GTP_PEN_BUTTON1);
+	input_set_capability(ts->input_dev, EV_KEY, GTP_PEN_BUTTON2);
+
+	/* touch key register */
+	for (index = 0; index < ts->pdata->key_nums; index++)
+		input_set_capability(ts->input_dev, EV_KEY,
+				     ts->pdata->key_map[index]);
+
+	if (ts->pdata->slide_wakeup)
+		input_set_capability(ts->input_dev, EV_KEY, KEY_POWER);
+
+	if (ts->pdata->swap_x2y)
+		GTP_SWAP(ts->pdata->abs_size_x, ts->pdata->abs_size_y);
+
+	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, 0,
+			     ts->pdata->abs_size_x, 0, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, 0,
+			     ts->pdata->abs_size_y, 0, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0,
+			     ts->pdata->max_touch_width, 0, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, 0,
+			     ts->pdata->max_touch_pressure, 0, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0,
+			     ts->pdata->max_touch_id, 0, 0);
+	if (!ts->pdata->type_a_report) {
+		input_set_abs_params(ts->input_dev, ABS_MT_TOOL_TYPE,
+				     0, MT_TOOL_MAX, 0, 0);
+	} else {
+		__set_bit(BTN_TOOL_PEN, ts->input_dev->keybit);
+		__set_bit(BTN_TOOL_FINGER, ts->input_dev->keybit);
+	}
+
+	ts->input_dev->name = goodix_ts_name;
+	ts->input_dev->phys = goodix_input_phys;
+	ts->input_dev->id.bustype = BUS_I2C;
+	ts->input_dev->id.vendor = 0xDEAD;
+	ts->input_dev->id.product = 0xBEEF;
+	ts->input_dev->id.version = 10427;
+
+	ret = input_register_device(ts->input_dev);
+	if (ret) {
+		dev_err(&ts->client->dev, "Register %s input device failed\n",
+			ts->input_dev->name);
+		input_free_device(ts->input_dev);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/*
+ * Devices Tree support
+ */
+#ifdef CONFIG_OF
+static void gtp_parse_dt_coords(struct device *dev,
+				struct goodix_ts_platform_data *pdata)
+{
+	struct device_node *np = dev->of_node;
+	int ret;
+
+	ret = of_property_read_u32(np, "touchscreen-max-id",
+				   &pdata->max_touch_id);
+	if (ret || pdata->max_touch_id > GTP_MAX_TOUCH_ID) {
+		dev_info(dev, "Unset touchscreen-max-id, use default\n");
+		pdata->max_touch_id = GTP_MAX_TOUCH_ID;
+	}
+
+	ret = of_property_read_u32(np, "touchscreen-size-x",
+				   &pdata->abs_size_x);
+	if (ret) {
+		dev_info(dev, "Unset touchscreen-size-x, use default\n");
+		pdata->abs_size_x = GTP_DEFAULT_MAX_X;
+	}
+
+	ret = of_property_read_u32(np, "touchscreen-size-y",
+				   &pdata->abs_size_y);
+	if (ret) {
+		dev_info(dev, "Unset touchscreen-size-y, use default\n");
+		pdata->abs_size_y = GTP_DEFAULT_MAX_Y;
+	}
+
+	ret = of_property_read_u32(np, "touchscreen-max-w",
+				   &pdata->max_touch_width);
+	if (ret) {
+		dev_info(dev, "Unset touchscreen-max-w, use default\n");
+		pdata->max_touch_width = GTP_DEFAULT_MAX_WIDTH;
+	}
+
+	ret = of_property_read_u32(np, "touchscreen-max-p",
+				   &pdata->max_touch_pressure);
+	if (ret) {
+		dev_info(dev, "Unset touchscreen-max-p, use default\n");
+		pdata->max_touch_pressure = GTP_DEFAULT_MAX_PRESSURE;
+	}
+	dev_info(dev, "touch input parameters is [id x y w p]<%d %d %d %d %d>\n",
+		 pdata->max_touch_id, pdata->abs_size_x, pdata->abs_size_y,
+		 pdata->max_touch_width, pdata->max_touch_pressure);
+}
+
+static int gtp_parse_dt(struct device *dev,
+			struct goodix_ts_platform_data *pdata)
+{
+	int ret;
+	u32  key_nums;
+	struct property *prop;
+	u32 key_map[MAX_KEY_NUMS];
+	struct device_node *np = dev->of_node;
+
+	gtp_parse_dt_coords(dev, pdata);
+
+	ret = of_property_read_u32(np, "irq-flags",
+				   &pdata->irq_flags);
+	if (ret) {
+		dev_info(dev,
+			 "Failed get int-trigger-type from dts,set default\n");
+		pdata->irq_flags = GTP_DEFAULT_INT_TRIGGER;
+	}
+	of_property_read_u32(np, "goodix,int-sync", &pdata->int_sync);
+	if (pdata->int_sync)
+		dev_info(dev, "int-sync enabled\n");
+
+	of_property_read_u32(np, "goodix,driver-send-cfg",
+			     &pdata->driver_send_cfg);
+	if (pdata->driver_send_cfg)
+		dev_info(dev, "driver-send-cfg enabled\n");
+
+	of_property_read_u32(np, "goodix,swap-x2y", &pdata->swap_x2y);
+	if (pdata->swap_x2y)
+		dev_info(dev, "swap-x2y enabled\n");
+
+	of_property_read_u32(np, "goodix,slide-wakeup", &pdata->slide_wakeup);
+	if (pdata->slide_wakeup)
+		dev_info(dev, "slide-wakeup enabled\n");
+
+	of_property_read_u32(np, "goodix,auto-update", &pdata->auto_update);
+	if (pdata->auto_update)
+		dev_info(dev, "auto-update enabled\n");
+
+	of_property_read_u32(np, "goodix,auto-update-cfg",
+			     &pdata->auto_update_cfg);
+	if (pdata->auto_update_cfg)
+		dev_info(dev, "auto-update-cfg enabled\n");
+
+	of_property_read_u32(np, "goodix,esd-protect", &pdata->esd_protect);
+	if (pdata->esd_protect)
+		dev_info(dev, "esd-protect enabled\n");
+
+	of_property_read_u32(np, "goodix,type-a-report",
+			     &pdata->type_a_report);
+	if (pdata->type_a_report)
+		dev_info(dev, "type-a-report enabled\n");
+
+	of_property_read_u32(np, "goodix,resume-in-workqueue",
+			     &pdata->resume_in_workqueue);
+	if (pdata->resume_in_workqueue)
+		dev_info(dev, "resume-in-workqueue enabled\n");
+
+	of_property_read_u32(np, "goodix,power-off-sleep",
+			     &pdata->power_off_sleep);
+	if (pdata->power_off_sleep)
+		dev_info(dev, "power-off-sleep enabled\n");
+
+	of_property_read_u32(np, "goodix,pen-suppress-finger",
+			     &pdata->pen_suppress_finger);
+	if (pdata->pen_suppress_finger)
+		dev_info(dev, "pen-suppress-finger enabled\n");
+
+	prop = of_find_property(np, "touchscreen-key-map", NULL);
+	if (prop) {
+		key_nums = prop->length / sizeof(key_map[0]);
+		key_nums = key_nums > MAX_KEY_NUMS ? MAX_KEY_NUMS : key_nums;
+
+		dev_dbg(dev, "key nums %d\n", key_nums);
+		ret = of_property_read_u32_array(np,
+				"touchscreen-key-map", key_map,
+				key_nums);
+		if (ret) {
+			dev_err(dev, "Unable to read key codes\n");
+			pdata->key_nums = 0;
+			memset(pdata->key_map, 0,
+			       MAX_KEY_NUMS * sizeof(pdata->key_map[0]));
+		}
+		pdata->key_nums = key_nums;
+		memcpy(pdata->key_map, key_map,
+		       key_nums * sizeof(pdata->key_map[0]));
+		dev_info(dev, "key-map is [%x %x %x %x]\n",
+			 pdata->key_map[0], pdata->key_map[1],
+			 pdata->key_map[2], pdata->key_map[3]);
+	}
+
+	pdata->irq_gpio = of_get_named_gpio(np, "irq-gpios", 0);
+	if (!gpio_is_valid(pdata->irq_gpio))
+		dev_err(dev, "No valid irq gpio");
+
+	pdata->rst_gpio = of_get_named_gpio(np, "reset-gpios", 0);
+	if (!gpio_is_valid(pdata->rst_gpio))
+		dev_err(dev, "No valid rst gpio");
+
+	return 0;
+}
+
+/*******************************************************
+ * Function:
+ *	parse config data from devices tree.
+ * Input:
+ *	dev: device that this driver attached.
+ *	cfg: pointer of the config array.
+ *	cfg_len: pointer of the config length.
+ *	sid: sensor id.
+ * Output:
+ *	Executive outcomes.
+ *		0-succeed, -1-faileds.
+ *******************************************************/
+int gtp_parse_dt_cfg(struct device *dev, u8 *cfg, int *cfg_len, u8 sid)
+{
+	struct device_node *np = dev->of_node;
+	struct property *prop;
+	char cfg_name[18];
+	int ret;
+
+	snprintf(cfg_name, sizeof(cfg_name), "goodix,cfg-group%d", sid);
+	prop = of_find_property(np, cfg_name, cfg_len);
+	if (!prop || !prop->value || *cfg_len == 0 ||
+	    *cfg_len > GTP_CONFIG_MAX_LENGTH) {
+		*cfg_len = 0;
+		ret = -EPERM;/* failed */
+	} else {
+		memcpy(cfg, prop->value, *cfg_len);
+		ret = 0;
+	}
+
+	return ret;
+}
+
+#endif
+
+static int gtp_power_on(struct goodix_ts_data *ts)
+{
+	int ret = 0;
+
+	if (ts->vdd_ana) {
+		ret = regulator_set_voltage(ts->vdd_ana, GOODIX_VTG_MIN_UV,
+					    GOODIX_VTG_MAX_UV);
+		if (ret) {
+			dev_err(&ts->client->dev,
+				"Regulator set_vtg failed vdd ret=%d\n",
+				ret);
+			goto err_set_vtg_vdd_ana;
+		}
+		ret = regulator_enable(ts->vdd_ana);
+		if (ret) {
+			dev_err(&ts->client->dev,
+				"Regulator vdd enable failed ret=%d\n",
+				ret);
+			goto err_enable_vdd_ana;
+		}
+	}
+
+	if (ts->vcc_i2c) {
+		ret = regulator_set_voltage(ts->vcc_i2c, GOODIX_I2C_VTG_MIN_UV,
+					    GOODIX_I2C_VTG_MAX_UV);
+		if (ret) {
+			dev_err(&ts->client->dev,
+				"Regulator set_vtg failed vcc_i2c ret=%d\n",
+				ret);
+			goto err_set_vtg_vcc_i2c;
+		}
+		ret = regulator_enable(ts->vcc_i2c);
+		if (ret) {
+			dev_err(&ts->client->dev,
+				"Regulator vcc_i2c enable failed ret=%d\n",
+				ret);
+			goto err_enable_vcc_i2c;
+		}
+	}
+	clear_bit(POWER_OFF_MODE, &ts->flags);
+	return 0;
+
+err_enable_vcc_i2c:
+	if (ts->vcc_i2c)
+		regulator_set_voltage(ts->vcc_i2c, 0, GOODIX_I2C_VTG_MAX_UV);
+err_set_vtg_vcc_i2c:
+	if (ts->vdd_ana)
+		regulator_disable(ts->vdd_ana);
+err_enable_vdd_ana:
+	if (ts->vdd_ana)
+		regulator_set_voltage(ts->vdd_ana, 0, GOODIX_VTG_MAX_UV);
+err_set_vtg_vdd_ana:
+	set_bit(POWER_OFF_MODE, &ts->flags);
+	return ret;
+}
+
+static int gtp_power_off(struct goodix_ts_data *ts)
+{
+	int ret = 0;
+
+	if (ts->vcc_i2c) {
+		set_bit(POWER_OFF_MODE, &ts->flags);
+		ret = regulator_set_voltage(ts->vcc_i2c, 0,
+					    GOODIX_I2C_VTG_MAX_UV);
+		if (ret < 0) {
+			dev_err(&ts->client->dev,
+				"Regulator vcc_i2c set_vtg failed ret=%d\n",
+				ret);
+			goto err_set_vtg_vcc_i2c;
+		}
+		ret = regulator_disable(ts->vcc_i2c);
+		if (ret) {
+			dev_err(&ts->client->dev,
+				"Regulator vcc_i2c disable failed ret=%d\n",
+				ret);
+			goto err_disable_vcc_i2c;
+		}
+		dev_info(&ts->client->dev,
+			 "Regulator vcc_i2c disabled\n");
+	}
+
+	if (ts->vdd_ana) {
+		set_bit(POWER_OFF_MODE, &ts->flags);
+		ret = regulator_set_voltage(ts->vdd_ana, 0, GOODIX_VTG_MAX_UV);
+		if (ret < 0) {
+			dev_err(&ts->client->dev,
+					"Regulator vdd set_vtg failed ret=%d\n",
+					ret);
+			goto err_set_vtg_vdd_ana;
+		}
+		ret = regulator_disable(ts->vdd_ana);
+		if (ret) {
+			dev_err(&ts->client->dev,
+					"Regulator vdd disable failed ret=%d\n",
+					ret);
+			goto err_disable_vdd_ana;
+		}
+		dev_info(&ts->client->dev,
+			 "Regulator vdd_ana disabled\n");
+	}
+	return ret;
+
+err_disable_vdd_ana:
+	if (ts->vdd_ana)
+		regulator_set_voltage(ts->vdd_ana, GOODIX_VTG_MIN_UV,
+				      GOODIX_VTG_MAX_UV);
+err_set_vtg_vdd_ana:
+	if (ts->vcc_i2c)
+		ret = regulator_enable(ts->vcc_i2c);
+err_disable_vcc_i2c:
+	if (ts->vcc_i2c)
+		regulator_set_voltage(ts->vcc_i2c, GOODIX_I2C_VTG_MIN_UV,
+				      GOODIX_I2C_VTG_MAX_UV);
+err_set_vtg_vcc_i2c:
+	clear_bit(POWER_OFF_MODE, &ts->flags);
+	return ret;
+}
+
+static int gtp_power_init(struct goodix_ts_data *ts)
+{
+	int ret;
+
+	ts->vdd_ana = regulator_get(&ts->client->dev, "vdd_ana");
+	if (IS_ERR(ts->vdd_ana)) {
+		ts->vdd_ana = NULL;
+		ret = PTR_ERR(ts->vdd_ana);
+		dev_info(&ts->client->dev,
+			 "Regulator get failed vdd ret=%d\n", ret);
+	}
+
+	ts->vcc_i2c = regulator_get(&ts->client->dev, "vcc_i2c");
+	if (IS_ERR(ts->vcc_i2c)) {
+		ts->vcc_i2c = NULL;
+		ret = PTR_ERR(ts->vcc_i2c);
+		dev_info(&ts->client->dev,
+			 "Regulator get failed vcc_i2c ret=%d\n", ret);
+	}
+	return 0;
+}
+
+static int gtp_power_deinit(struct goodix_ts_data *ts)
+{
+	if (ts->vdd_ana)
+		regulator_put(ts->vdd_ana);
+	if (ts->vcc_i2c)
+		regulator_put(ts->vcc_i2c);
+
+	return 0;
+}
+
+static void gtp_shutdown(struct i2c_client *client)
+{
+	struct goodix_ts_data *data = i2c_get_clientdata(client);
+
+	if (!data->init_done)
+		return;
+
+	gtp_work_control_enable(data, false);
+	gtp_power_off(data);
+}
+
+static int gtp_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	int ret = -1;
+	struct goodix_ts_data *ts;
+	struct goodix_ts_platform_data *pdata;
+
+	/* do NOT remove these logs */
+	dev_info(&client->dev, "GTP Driver Version: %s\n", GTP_DRIVER_VERSION);
+	dev_info(&client->dev, "GTP I2C Address: 0x%02x\n", client->addr);
+
+	i2c_connect_client = client;
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "Failed check I2C functionality");
+		return -ENODEV;
+	}
+
+	ts = devm_kzalloc(&client->dev, sizeof(*ts), GFP_KERNEL);
+	if (!ts)
+		return -ENOMEM;
+
+	pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		devm_kfree(&client->dev, ts);
+		return -EINVAL;
+	}
+
+	ts->init_done = false;
+
+#ifdef CONFIG_OF
+	if (client->dev.of_node) {
+		ret = gtp_parse_dt(&client->dev, pdata);
+		if (ret) {
+			dev_err(&client->dev, "Failed parse dts\n");
+			goto exit_free_client_data;
+		}
+	}
+#else
+	/* set parameters at here if you platform doesn't DTS */
+	pdata->rst_gpio = GTP_RST_PORT;
+	pdata->irq_gpio = GTP_INT_PORT;
+	pdata->slide_wakeup = false;
+	pdata->auto_update = true;
+	pdata->auto_update_cfg = false;
+	pdata->type_a_report = false;
+	pdata->esd_protect = false;
+	pdata->max_touch_id = GTP_MAX_TOUCH_ID;
+	pdata->abs_size_x = GTP_DEFAULT_MAX_X;
+	pdata->abs_size_y = GTP_DEFAULT_MAX_Y;
+	pdata->max_touch_width = GTP_DEFAULT_MAX_WIDTH;
+	pdata->max_touch_pressure = GTP_DEFAULT_MAX_PRESSURE;
+#endif
+
+	ts->client = client;
+	ts->pdata = pdata;
+
+	i2c_set_clientdata(client, ts);
+
+	ret = gtp_power_init(ts);
+	if (ret) {
+		dev_err(&client->dev, "Failed get regulator\n");
+		ret = -EINVAL;
+		goto exit_free_client_data;
+	}
+
+	ret = gtp_pinctrl_init(ts);
+	if (ret < 0) {
+		/* if define pinctrl must define the following state
+		 * to let int-pin work normally: default, int_output_high,
+		 * int_output_low, int_input
+		 */
+		dev_err(&client->dev, "Failed get wanted pinctrl state\n");
+		goto exit_deinit_power;
+	}
+
+	ret = gtp_request_io_port(ts);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed request IO port\n");
+		goto exit_pinctrl;
+	}
+
+	/*wait for discharging power, which from i2c pull-up flow backward*/
+	gtp_rst_output(ts, 0);
+	msleep(DELAY_FOR_DISCHARGING);
+
+	ret = gtp_power_on(ts);
+	if (ret) {
+		dev_err(&client->dev, "Failed power on device\n");
+		ret = -EINVAL;
+		goto exit_free_io_port;
+	}
+
+	gtp_reset_guitar(ts->client, 20);
+
+	ret = gtp_i2c_test(client);
+	if (ret) {
+		dev_err(&client->dev, "Failed communicate with IC use I2C\n");
+		goto exit_power_off;
+	}
+
+	dev_info(&client->dev, "I2C Addr is %x\n", client->addr);
+
+	ret = gtp_get_fw_info(client, &ts->fw_info);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed read FW version\n");
+		goto exit_power_off;
+	}
+
+	pdata->config.data[0] = GTP_REG_CONFIG_DATA >> 8;
+	pdata->config.data[1] = GTP_REG_CONFIG_DATA & 0xff;
+	ret = gtp_init_panel(ts);
+	if (ret < 0)
+		dev_info(&client->dev, "Panel un-initialize\n");
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
+	if (ts->pdata->auto_update) {
+		ret = gup_init_update_proc(ts);
+		if (ret < 0)
+			dev_err(&client->dev, "Failed create update thread\n");
+	}
+#endif
+
+	ret = gtp_request_input_dev(ts);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed request input device\n");
+		goto exit_power_off;
+	}
+
+	mutex_init(&ts->lock);
+
+	ret = gtp_request_irq(ts);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed create work thread");
+		goto exit_unreg_input_dev;
+	}
+	gtp_work_control_enable(ts, false);
+	if (ts->pdata->slide_wakeup) {
+		dev_info(&client->dev, "slide wakeup enabled\n");
+		ret = enable_irq_wake(client->irq);
+		if (ret < 0)
+			dev_err(&client->dev, "Failed set irq wake\n");
+	}
+
+	gtp_register_powermanager(ts);
+
+	ret = gtp_create_file(ts);
+	if (ret) {
+		dev_info(&client->dev, "Failed create attributes file");
+		goto exit_powermanager;
+	}
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_TOOL
+	init_wr_node(client);/*TODO judge return value */
+#endif
+
+	gtp_esd_init(ts);
+	gtp_esd_on(ts);
+	/* probe init finished */
+	ts->init_done = true;
+	gtp_work_control_enable(ts, true);
+
+	return 0;
+
+exit_powermanager:
+	gtp_unregister_powermanager(ts);
+exit_unreg_input_dev:
+	input_unregister_device(ts->input_dev);
+exit_power_off:
+	gtp_power_off(ts);
+exit_free_io_port:
+	if (gpio_is_valid(ts->pdata->rst_gpio))
+		gpio_free(ts->pdata->rst_gpio);
+	if (gpio_is_valid(ts->pdata->irq_gpio))
+		gpio_free(ts->pdata->irq_gpio);
+exit_pinctrl:
+	gtp_pinctrl_deinit(ts);
+exit_deinit_power:
+	gtp_power_deinit(ts);
+exit_free_client_data:
+	devm_kfree(&client->dev, pdata);
+	devm_kfree(&client->dev, ts);
+	i2c_set_clientdata(client, NULL);
+
+	return ret;
+}
+
+static int gtp_drv_remove(struct i2c_client *client)
+{
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+	gtp_work_control_enable(ts, false);
+	gtp_unregister_powermanager(ts);
+
+	remove_proc_entry(GT91XX_CONFIG_PROC_FILE, gtp_config_proc);
+
+	sysfs_remove_group(&client->dev.kobj, &gtp_attr_group);
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_TOOL
+	uninit_wr_node();
+#endif
+
+	if (ts->pdata->esd_protect)
+		gtp_esd_off(ts);
+
+	/* TODO: how to judge a irq numbers validity */
+	if (ts->client->irq)
+		free_irq(client->irq, ts);
+	else
+		hrtimer_cancel(&ts->timer);
+
+	if (gpio_is_valid(ts->pdata->rst_gpio))
+		gpio_free(ts->pdata->rst_gpio);
+
+	if (gpio_is_valid(ts->pdata->irq_gpio))
+		gpio_free(ts->pdata->irq_gpio);
+
+	gtp_power_off(ts);
+	gtp_power_deinit(ts);
+	gtp_pinctrl_deinit(ts);
+	dev_info(&client->dev, "goodix ts driver removed");
+	i2c_set_clientdata(client, NULL);
+	input_unregister_device(ts->input_dev);
+	mutex_destroy(&ts->lock);
+
+	devm_kfree(&client->dev, ts->pdata);
+	devm_kfree(&client->dev, ts);
+
+	return 0;
+}
+
+static void gtp_suspend(struct goodix_ts_data *ts)
+{
+	int ret = -1;
+
+	if (test_bit(FW_UPDATE_RUNNING, &ts->flags)) {
+		dev_warn(&ts->client->dev,
+			 "Fw upgrade in progress, can't go to suspend\n");
+		return;
+	}
+
+	if (test_and_set_bit(SLEEP_MODE, &ts->flags)) {
+		dev_info(&ts->client->dev, "Already in suspend state\n");
+		return;
+	}
+
+	dev_dbg(&ts->client->dev, "Try enter suspend mode\n");
+
+	gtp_esd_off(ts);
+	gtp_work_control_enable(ts, false);
+	if (ts->pdata->slide_wakeup) {
+		ret = gtp_enter_doze(ts);
+		gtp_work_control_enable(ts, true);
+	} else if (ts->pdata->power_off_sleep) {
+		/*TODO: power off routine */
+		gtp_power_off(ts);
+		ret = SUCCESS;
+	} else {
+		ret = gtp_enter_sleep(ts);
+	}
+
+	if (ret < 0)
+		dev_err(&ts->client->dev, "Failed enter suspend\n");
+
+	/*  to avoid waking up while not sleeping */
+	/*	delay 48 + 10ms to ensure reliability */
+	msleep(GTP_58_DLY_MS);
+}
+
+static int gtp_gesture_wakeup(struct goodix_ts_data *ts)
+{
+	int ret;
+	int retry = 10;
+
+	do {
+		gtp_reset_guitar(ts->client, 10);
+		ret = gtp_i2c_test(ts->client);
+		if (!ret)
+			break;
+	} while (--retry);
+
+	if (!retry)
+		ret = -EIO;
+
+	clear_bit(DOZE_MODE, &ts->flags);
+	return ret;
+}
+
+static void gtp_resume(struct goodix_ts_data *ts)
+{
+	int ret = 0;
+
+	if (test_bit(FW_UPDATE_RUNNING, &ts->flags)) {
+		dev_info(&ts->client->dev,
+			 "Fw upgrade in progress, can't do resume\n");
+		return;
+	}
+
+	if (!test_bit(SLEEP_MODE, &ts->flags)) {
+		dev_dbg(&ts->client->dev, "Already in awake state\n");
+		return;
+	}
+
+	dev_info(&ts->client->dev, "Try resume from sleep mode\n");
+
+	gtp_work_control_enable(ts, false);
+
+	if (ts->pdata->slide_wakeup && test_bit(DOZE_MODE, &ts->flags)) {
+		ret = gtp_gesture_wakeup(ts);
+		if (ret)
+			dev_warn(&ts->client->dev, "Failed wake up from gesture mode\n");
+	} else if (ts->pdata->power_off_sleep) {
+		ret = gtp_power_on(ts);
+		if (ret) {
+			dev_warn(&ts->client->dev, "Failed wake up from gesture mode\n");
+		} else {
+			gtp_reset_guitar(ts->client, 20);
+			ret = gtp_i2c_test(ts->client);
+			if (ret)
+				dev_warn(&ts->client->dev,
+					 "I2C communicate failed after power on\n");
+		}
+	} else {
+		ret = gtp_wakeup_sleep(ts);
+		if (ret)
+			dev_warn(&ts->client->dev,
+				 "Failed wakeup from sleep mode\n");
+	}
+
+	if (ret)
+		dev_warn(&ts->client->dev, "Later resume failed\n");
+	else
+		gtp_esd_on(ts);
+
+	clear_bit(SLEEP_MODE, &ts->flags);
+	gtp_work_control_enable(ts, true);
+}
+
+#if defined(CONFIG_FB)
+static void fb_notify_resume_work(struct work_struct *work)
+{
+	struct goodix_ts_data *ts =
+		container_of(work, struct goodix_ts_data, fb_notify_work);
+	dev_info(&ts->client->dev, "try resume in workqueue\n");
+	gtp_resume(ts);
+}
+
+/* frame buffer notifier block control the suspend/resume procedure */
+static int gtp_fb_notifier_callback(struct notifier_block *noti,
+				    unsigned long event, void *data)
+{
+	struct fb_event *ev_data = data;
+	struct goodix_ts_data *ts = container_of(noti,
+			struct goodix_ts_data, notifier);
+	int *blank;
+
+	if (ev_data && ev_data->data && event == FB_EVENT_BLANK && ts) {
+		blank = ev_data->data;
+		if (*blank == FB_BLANK_UNBLANK ||
+		    *blank == FB_BLANK_NORMAL) {
+			dev_dbg(&ts->client->dev, "ts_resume");
+			if (ts->pdata->resume_in_workqueue)
+				schedule_work(&ts->fb_notify_work);
+			else
+				gtp_resume(ts);
+		} else if (*blank == FB_BLANK_POWERDOWN) {
+			dev_dbg(&ts->client->dev, "ts_suspend");
+			if (ts->pdata->resume_in_workqueue)
+				flush_work(&ts->fb_notify_work);
+			gtp_suspend(ts);
+		}
+	}
+
+	return 0;
+}
+
+#elif defined(CONFIG_PM)
+static int gtp_pm_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+	if (ts) {
+		dev_dbg(&ts->client->dev, "Suspend by i2c pm.");
+		gtp_suspend(ts);
+	}
+
+	return 0;
+}
+
+static int gtp_pm_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+	if (ts) {
+		dev_dbg(&ts->client->dev, "Resume by i2c pm.");
+		gtp_resume(ts);
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops gtp_pm_ops = {
+	.suspend = gtp_pm_suspend,
+	.resume  = gtp_pm_resume,
+};
+
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+static void gtp_early_suspend(struct early_suspend *h)
+{
+	struct goodix_ts_data *ts = container_of(h,
+			struct goodix_ts_data, early_suspend);
+
+	if (ts) {
+		dev_dbg(&ts->client->dev, "Suspend by earlysuspend module.");
+		gtp_suspend(ts);
+	}
+}
+
+static void gtp_late_resume(struct early_suspend *h)
+{
+	struct goodix_ts_data *ts = container_of(h,
+			struct goodix_ts_data, early_suspend);
+
+	if (ts) {
+		dev_dbg(&ts->client->dev, "Resume by earlysuspend module.");
+		gtp_resume(ts);
+	}
+}
+#endif
+
+static int gtp_register_powermanager(struct goodix_ts_data *ts)
+{
+	int ret;
+#if defined(CONFIG_FB)
+	INIT_WORK(&ts->fb_notify_work, fb_notify_resume_work);
+	ts->notifier.notifier_call = gtp_fb_notifier_callback;
+	ret = fb_register_client(&ts->notifier);
+	if (ret)
+		dev_err(&ts->client->dev,
+			"Unable to register fb_notifier: %d\n", ret);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
+	ts->early_suspend.suspend = goodix_ts_early_suspend;
+	ts->early_suspend.resume = goodix_ts_late_resume;
+	register_early_suspend(&ts->early_suspend);
+#endif
+
+	return ret;
+}
+
+static int gtp_unregister_powermanager(struct goodix_ts_data *ts)
+{
+#if defined(CONFIG_FB)
+		fb_unregister_client(&ts->notifier);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+		unregister_early_suspend(&ts->early_suspend);
+#endif
+
+	return 0;
+}
+
+/*******************************************************
+ * Function:
+ *	Initialize external watchdog for esd protect
+ * Input:
+ *	client: i2c device.
+ * Output:
+ *	result of i2c write operation.
+ *		0: succeed, otherwise: failed
+ ********************************************************/
+static int gtp_init_ext_watchdog(struct i2c_client *client)
+{
+	int ret;
+	u8 opr_buffer[3] = { (u8)(GTP_REG_ESD_CHECK >> 8),
+			     (u8)GTP_REG_ESD_CHECK,
+			     (u8)GTP_ESD_CHECK_VALUE };
+
+	dev_dbg(&client->dev, "[Esd]Init external watchdog\n");
+	ret = gtp_i2c_write(client, opr_buffer, 3);
+	if (ret == 1)
+		return 0;
+
+	dev_err(&client->dev, "Failed init ext watchdog\n");
+	return -EINVAL;
+}
+
+static void gtp_esd_check_func(struct work_struct *work)
+{
+	s32 i;
+	s32 ret = -1;
+	u8 esd_buf[5] = { (u8)(GTP_REG_COMMAND >> 8), (u8)GTP_REG_COMMAND };
+	struct delayed_work *dwork = to_delayed_work(work);
+	struct goodix_ts_esd *ts_esd = container_of(dwork, struct goodix_ts_esd,
+						    delayed_work);
+	struct goodix_ts_data *ts = container_of(ts_esd, struct goodix_ts_data,
+						 ts_esd);
+
+	if (test_bit(SLEEP_MODE, &ts->flags) ||
+	    test_bit(FW_UPDATE_RUNNING, &ts->flags)) {
+		dev_dbg(&ts->client->dev,
+			"Esd cancled by power_suspend or fw_update!");
+		return;
+	}
+
+	if (ts_esd->esd_on == false)
+		return;
+
+	for (i = 0; i < 3; i++) {
+		ret = gtp_i2c_read(ts->client, esd_buf, 4);
+		if (ret < 0)
+			continue;
+
+		dev_dbg(&ts->client->dev,
+			"[Esd]0x8040 = 0x%02X, 0x8041 = 0x%02X",
+			esd_buf[2], esd_buf[3]);
+		if (esd_buf[2] == (u8)GTP_ESD_CHECK_VALUE ||
+		    esd_buf[3] != (u8)GTP_ESD_CHECK_VALUE) {
+			gtp_i2c_read(ts->client, esd_buf, 4);
+			if (ret < 0)
+				continue;
+
+			if (esd_buf[2] == (u8)GTP_ESD_CHECK_VALUE ||
+			    esd_buf[3] != (u8)GTP_ESD_CHECK_VALUE) {
+				i = 3;
+				break;
+			}
+		} else {
+			/* IC works normally, Write 0x8040 0xAA, feed the dog */
+			esd_buf[2] = (u8)GTP_ESD_CHECK_VALUE;
+			gtp_i2c_write(ts->client, esd_buf, 3);
+			break;
+		}
+	}
+	if (i >= 3) {
+		dev_err(&ts->client->dev, "IC working abnormally! Reset IC\n");
+		esd_buf[0] = 0x42;
+		esd_buf[1] = 0x26;
+		esd_buf[2] = 0x01;
+		esd_buf[3] = 0x01;
+		esd_buf[4] = 0x01;
+		gtp_i2c_write(ts->client, esd_buf, 5);
+		/* TODO: Is power off really need? */
+		msleep(GTP_50_DLY_MS);
+		gtp_power_off(ts);
+		msleep(GTP_20_DLY_MS);
+		gtp_power_on(ts);
+		msleep(GTP_20_DLY_MS);
+
+		gtp_reset_guitar(ts->client, 50);
+		msleep(GTP_50_DLY_MS);
+		gtp_send_cfg(ts->client);
+	}
+
+	if (ts_esd->esd_on == true && !test_bit(SLEEP_MODE, &ts->flags)) {
+		schedule_delayed_work(&ts_esd->delayed_work, 2 * HZ);
+		dev_dbg(&ts->client->dev, "ESD work rescheduled\n");
+	}
+}
+
+static int gtp_esd_init(struct goodix_ts_data *ts)
+{
+	struct goodix_ts_esd *ts_esd = &ts->ts_esd;
+
+	INIT_DELAYED_WORK(&ts_esd->delayed_work, gtp_esd_check_func);
+	mutex_init(&ts_esd->mutex);
+	ts_esd->esd_on = false;
+
+	return 0;
+}
+
+void gtp_esd_on(struct goodix_ts_data *ts)
+{
+	struct goodix_ts_esd *ts_esd = &ts->ts_esd;
+
+	if (!ts->pdata->esd_protect)
+		return;
+	mutex_lock(&ts_esd->mutex);
+	if (ts_esd->esd_on == false) {
+		ts_esd->esd_on = true;
+		schedule_delayed_work(&ts_esd->delayed_work, 2 * HZ);
+		dev_info(&ts->client->dev, "ESD on");
+	}
+	mutex_unlock(&ts_esd->mutex);
+}
+
+void gtp_esd_off(struct goodix_ts_data *ts)
+{
+	struct goodix_ts_esd *ts_esd = &ts->ts_esd;
+
+	if (!ts->pdata->esd_protect)
+		return;
+	mutex_lock(&ts_esd->mutex);
+	if (ts_esd->esd_on == true) {
+		ts_esd->esd_on = false;
+		cancel_delayed_work_sync(&ts_esd->delayed_work);
+		dev_info(&ts->client->dev, "ESD off");
+	}
+	mutex_unlock(&ts_esd->mutex);
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id gtp_match_table[] = {
+	{.compatible = "goodix,gt9xx",},
+	{ },
+};
+#endif
+
+static const struct i2c_device_id gtp_device_id[] = {
+	{ GTP_I2C_NAME, 0 },
+	{ }
+};
+
+static struct i2c_driver goodix_ts_driver = {
+	.probe		= gtp_probe,
+	.remove		= gtp_drv_remove,
+	.id_table	= gtp_device_id,
+	.shutdown	= gtp_shutdown,
+	.driver = {
+		.name	  = GTP_I2C_NAME,
+		.owner	  = THIS_MODULE,
+#ifdef CONFIG_OF
+		.of_match_table = gtp_match_table,
+#endif
+#if !defined(CONFIG_FB) && defined(CONFIG_PM)
+		.pm		  = &gtp_pm_ops,
+#endif
+	},
+};
+
+static int __init gtp_init(void)
+{
+	s32 ret;
+
+	pr_info("Gt9xx driver installing..\n");
+	ret = i2c_add_driver(&goodix_ts_driver);
+
+	return ret;
+}
+
+static void __exit gtp_exit(void)
+{
+	pr_info("Gt9xx driver exited\n");
+	i2c_del_driver(&goodix_ts_driver);
+}
+
+module_init(gtp_init);
+module_exit(gtp_exit);
+
+MODULE_DESCRIPTION("GT9 serials touch controller Driver");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/input/touchscreen/gt9xx_v2.8/gt9xx.h b/drivers/input/touchscreen/gt9xx_v2.8/gt9xx.h
new file mode 100644
index 0000000..78fa338
--- /dev/null
+++ b/drivers/input/touchscreen/gt9xx_v2.8/gt9xx.h
@@ -0,0 +1,375 @@
+/*
+ * Goodix GT9xx touchscreen driver
+ *
+ * Copyright  (C)  2016 - 2017 Goodix. Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be a reference
+ * to you, when you are integrating the GOODiX's CTP IC into your system,
+ * 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.
+ *
+ * Version: 2.8.0.2
+ * Release Date: 2017/12/14
+ */
+
+#ifndef _GOODIX_GT9XX_H_
+#define _GOODIX_GT9XX_H_
+
+#include <linux/kernel.h>
+#include <linux/hrtimer.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/proc_fs.h>
+#include <linux/string.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/major.h>
+#include <linux/kdev_t.h>
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+#endif
+#ifdef CONFIG_FB
+#include <linux/notifier.h>
+#include <linux/fb.h>
+#endif
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif
+#include <linux/usb.h>
+#include <linux/power_supply.h>
+
+#define GTP_TOOL_PEN	1
+#define GTP_TOOL_FINGER 2
+
+#define MAX_KEY_NUMS 4
+#define GTP_CONFIG_MAX_LENGTH 240
+#define GTP_ADDR_LENGTH       2
+
+/***************************PART1:ON/OFF define*******************************/
+#define GTP_DEBUG_ON          1
+#define GTP_DEBUG_ARRAY_ON    0
+#define GTP_DEBUG_FUNC_ON     0
+
+struct goodix_point_t {
+	int id;
+	int x;
+	int y;
+	int w;
+	int p;
+	int tool_type;
+};
+
+struct goodix_config_data {
+	int length;
+	u8 data[GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH];
+};
+
+struct goodix_ts_platform_data {
+	int irq_gpio;
+	int rst_gpio;
+	u32 irq_flags;
+	u32 abs_size_x;
+	u32 abs_size_y;
+	u32 max_touch_id;
+	u32 max_touch_width;
+	u32 max_touch_pressure;
+	u32 key_map[MAX_KEY_NUMS];
+	u32 key_nums;
+	u32 int_sync;
+	u32 driver_send_cfg;
+	u32 swap_x2y;
+	u32 slide_wakeup;
+	u32 auto_update;
+	u32 auto_update_cfg;
+	u32 esd_protect;
+	u32 type_a_report;
+	u32 power_off_sleep;
+	u32 resume_in_workqueue;
+	u32 pen_suppress_finger;
+	struct goodix_config_data config;
+};
+
+struct goodix_ts_esd {
+	struct delayed_work delayed_work;
+	struct mutex mutex;
+	bool esd_on;
+};
+
+enum {
+	REPORT_THREAD_ENABLED = 0,
+	HRTIMER_USED,
+	FW_ERROR,
+
+	DOZE_MODE,
+	SLEEP_MODE,
+	POWER_OFF_MODE,
+	RAW_DATA_MODE,
+
+	FW_UPDATE_RUNNING,
+	PANEL_RESETTING
+};
+
+struct goodix_pinctrl {
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *int_default;
+	struct pinctrl_state *int_out_high;
+	struct pinctrl_state *int_out_low;
+	struct pinctrl_state *int_input;
+	struct pinctrl_state *rst_default;
+	struct pinctrl_state *rst_out_high;
+	struct pinctrl_state *rst_out_low;
+	struct pinctrl_state *rst_input;
+};
+
+struct goodix_fw_info {
+	u8 pid[6];
+	u16 version;
+	u8 sensor_id;
+};
+
+struct goodix_ts_data {
+	unsigned long flags; /* This member record the device status */
+
+	struct goodix_ts_esd ts_esd;
+	struct i2c_client *client;
+	struct input_dev *input_dev;
+	struct input_dev *pen_dev;
+	struct goodix_ts_platform_data *pdata;
+	/* use pinctrl control int-pin output low or high */
+	struct goodix_pinctrl pinctrl;
+	struct hrtimer timer;
+	struct mutex lock;
+	struct notifier_block ps_notif;
+	struct regulator *vdd_ana;
+	struct regulator *vcc_i2c;
+#if defined(CONFIG_FB)
+	struct notifier_block notifier;
+	struct work_struct fb_notify_work;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	struct early_suspend early_suspend;
+#endif
+	struct goodix_fw_info fw_info;
+	bool force_update;
+	bool init_done;
+};
+
+/************************* PART2:TODO define *******************************/
+/* STEP_1(REQUIRED): Define Configuration Information Group(s)
+ * Sensor_ID Map:
+ *	 sensor_opt1 sensor_opt2 Sensor_ID
+ *		GND         GND          0
+ *		VDDIO      GND          1
+ *		NC           GND          2
+ *		GND         NC/300K    3
+ *		VDDIO      NC/300K    4
+ *		NC           NC/300K    5
+ */
+/* TODO: define your own default or for Sensor_ID == 0 config here.
+ *	 The predefined one is just a sample config,
+ *	 which is not suitable for your tp in most cases.
+ */
+#define CTP_CFG_GROUP0 {\
+	0x41, 0xD0, 0x02, 0x00, 0x05, 0x0A, 0x34, \
+	0x00, 0x01, 0x08, 0x28, 0x05, 0x50, 0x32, \
+	0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	0x00, 0x00, 0x17, 0x19, 0x1E, 0x14, 0x8C, \
+	0x2D, 0x0E, 0x3C, 0x3E, 0x82, 0x0A, 0x82, \
+	0x0A, 0x00, 0x99, 0x33, 0x1D, 0x00, 0x00, \
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	0x00, 0x2B, 0x19, 0x64, 0x94, 0xC0, 0x02, \
+	0x08, 0x00, 0x00, 0x04,	0xF2, 0x1C, 0x00, \
+	0xB9, 0x26, 0x00, 0x93, 0x32, 0x00, 0x77, \
+	0x42, 0x00, 0x62, 0x57, 0x00, 0x62, 0x00, \
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	0x00, 0x00, 0x00, 0xFF, 0x65, 0x00, 0x00, \
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	0x19, 0x46, 0x00, 0x00, 0x00, 0x00, 0x32, \
+	0x1C, 0x1A, 0x18, 0x16, 0x14, 0x12, 0x10, \
+	0x0E, 0x0C, 0x0A, 0x08, 0x06, 0x04, 0x02, \
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	0x00, 0x00, 0x00, 0x02,	0x04, 0x06, 0x08, \
+	0x0A, 0x0C, 0x0F, 0x10, 0x12, 0x13, 0x14, \
+	0x18, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, \
+	0x22, 0x24, 0x26, 0x28, 0x29, 0x2A, 0xFF, \
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+	0x00, 0x00, 0xB8, 0x01\
+}
+
+/* TODO: define your config for Sensor_ID == 1 here, if needed */
+#define CTP_CFG_GROUP1 {\
+}
+
+/* TODO: define your config for Sensor_ID == 2 here, if needed */
+#define CTP_CFG_GROUP2 {\
+}
+
+/* TODO: define your config for Sensor_ID == 3 here, if needed */
+#define CTP_CFG_GROUP3 {\
+}
+/* TODO: define your config for Sensor_ID == 4 here, if needed */
+#define CTP_CFG_GROUP4 {\
+}
+
+/* TODO: define your config for Sensor_ID == 5 here, if needed */
+#define CTP_CFG_GROUP5 {\
+}
+
+/* STEP_2(REQUIRED): Customize your I/O ports & I/O operations */
+#define GTP_RST_PORT    64 /* EXYNOS4_GPX2(0) */
+#define GTP_INT_PORT    65 /* EXYNOS4_GPX2(1) */
+
+#define GTP_GPIO_AS_INPUT(pin)          (gpio_direction_input(pin))
+#define GTP_GPIO_AS_INT(pin)            (GTP_GPIO_AS_INPUT(pin))
+#define GTP_GPIO_GET_VALUE(pin)         gpio_get_value(pin)
+#define GTP_GPIO_OUTPUT(pin, level)      gpio_direction_output(pin, level)
+#define GTP_GPIO_REQUEST(pin, label)    gpio_request(pin, label)
+#define GTP_GPIO_FREE(pin)              gpio_free(pin)
+
+/* STEP_3(optional): Specify your special config info if needed */
+#define GTP_DEFAULT_MAX_X	 720    /* default coordinate max values */
+#define GTP_DEFAULT_MAX_Y	 1080
+#define GTP_DEFAULT_MAX_WIDTH	 1024
+#define GTP_DEFAULT_MAX_PRESSURE 1024
+#define GTP_DEFAULT_INT_TRIGGER	 1 /* 1 rising, 2 falling */
+#define GTP_MAX_TOUCH_ID	 16
+
+/* STEP_4(optional): If keys are available and reported as keys,
+ * config your key info here
+ */
+#define GTP_KEY_TAB {KEY_MENU, KEY_HOME, KEY_BACK, KEY_HOMEPAGE, \
+	KEY_F1, KEY_F2, KEY_F3}
+
+/**************************PART3:OTHER define*******************************/
+#define GTP_DRIVER_VERSION	"V2.8.0.2<2017/12/14>"
+#define GTP_I2C_NAME		"goodix-ts"
+#define GT91XX_CONFIG_PROC_FILE	"gt9xx_config"
+#define GTP_POLL_TIME		10
+#define GTP_CONFIG_MIN_LENGTH	186
+#define GTP_ESD_CHECK_VALUE	0xAA
+#define RETRY_MAX_TIMES		5
+#define PEN_TRACK_ID		9
+#define MASK_BIT_8		0x80
+#define FAIL			0
+#define SUCCESS			1
+
+/* Registers define */
+#define GTP_REG_COMMAND		0x8040
+#define GTP_REG_ESD_CHECK	0x8041
+#define GTP_REG_COMMAND_CHECK	0x8046
+#define GTP_REG_CONFIG_DATA	0x8047
+#define GTP_REG_VERSION		0x8140
+#define GTP_REG_SENSOR_ID	0x814A
+#define GTP_REG_DOZE_BUF	0x814B
+#define GTP_READ_COOR_ADDR	0x814E
+
+/* Sleep time define */
+#define GTP_1_DLY_MS		1
+#define GTP_2_DLY_MS		2
+#define GTP_10_DLY_MS		10
+#define GTP_20_DLY_MS		20
+#define GTP_50_DLY_MS		50
+#define GTP_58_DLY_MS		58
+#define GTP_100_DLY_MS		100
+#define GTP_500_DLY_MS		500
+#define GTP_1000_DLY_MS		1000
+#define GTP_3000_DLY_MS		3000
+
+#define RESOLUTION_LOC        3
+#define TRIGGER_LOC           8
+
+#define CFG_GROUP_LEN(p_cfg_grp)  ARRAY_SIZE(p_cfg_grp)
+/* Log define */
+#define GTP_DEBUG(fmt, arg...) \
+do { \
+	if (GTP_DEBUG_ON) {\
+		pr_info("<<-GTP-DEBUG->> [%d]"fmt"\n", __LINE__, ##arg);\
+	} \
+} while (0)
+#define GTP_DEBUG_ARRAY(array, num) \
+do { \
+	s32 i;\
+	u8 *a = array;\
+	if (GTP_DEBUG_ARRAY_ON) {\
+		pr_warn("<<-GTP-DEBUG-ARRAY->>\n");\
+		for (i = 0; i < (num); i++) {\
+			pr_warn("%02x  ", (a)[i]);\
+			if ((i + 1) % 10 == 0) {\
+				pr_warn("\n");\
+			} \
+		} \
+		pr_warn("\n");\
+	} \
+} while (0)
+#define GTP_DEBUG_FUNC() \
+do {\
+	if (GTP_DEBUG_FUNC_ON) {\
+		pr_warn("<<-GTP-FUNC->>  Func:%s@Line:%d\n", \
+		__func__, __LINE__);\
+	} \
+} while (0)
+#define GTP_SWAP(x, y) \
+do {\
+	typeof(x) z = x;\
+	x = y;\
+	y = z;\
+} while (0)
+
+/******************************End of Part III********************************/
+#ifdef CONFIG_OF
+extern int gtp_parse_dt_cfg(struct device *dev, u8 *cfg, int *cfg_len, u8 sid);
+#endif
+
+extern void gtp_reset_guitar(struct i2c_client *client, s32 ms);
+extern void gtp_int_sync(struct goodix_ts_data *ts, s32 ms);
+extern void gtp_esd_on(struct goodix_ts_data *ts);
+extern void gtp_esd_off(struct goodix_ts_data *ts);
+extern void gtp_work_control_enable(struct goodix_ts_data *ts, bool enable);
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_UPDATE
+extern u16 show_len;
+extern u16 total_len;
+extern u8 gup_init_update_proc(struct goodix_ts_data *ts);
+extern s32 gup_update_proc(void *dir);
+extern s32 gup_enter_update_mode(struct i2c_client *client);
+extern void gup_leave_update_mode(struct i2c_client *client);
+#endif
+
+#ifdef CONFIG_TOUCHSCREEN_GT9XX_TOOL
+extern s32 init_wr_node(struct i2c_client *client);
+extern void uninit_wr_node(void);
+#endif
+
+/*********** For gt9xx_update Start *********/
+extern struct i2c_client *i2c_connect_client;
+extern void gtp_reset_guitar(struct i2c_client *client, s32 ms);
+extern void gtp_int_output(struct goodix_ts_data *ts, int level);
+extern void gtp_rst_output(struct goodix_ts_data *ts, int level);
+extern void gtp_rst_input(struct goodix_ts_data *ts);
+extern s32 gtp_send_cfg(struct i2c_client *client);
+extern s32 gtp_get_fw_info(struct i2c_client *client,
+			   struct goodix_fw_info *fw_info);
+extern s32 gtp_i2c_read_dbl_check(struct i2c_client *client,
+				  u16 addr, u8 *rxbuf, int len);
+extern int gtp_i2c_read(struct i2c_client *client, u8 *buf, int len);
+extern int gtp_i2c_write(struct i2c_client *client, u8 *buf, int len);
+extern s32 gtp_fw_startup(struct i2c_client *client);
+extern int gtp_ascii_to_array(const u8 *src_buf, int src_len, u8 *dst_buf);
+/*********** For gt9xx_update End *********/
+
+#endif /* _GOODIX_GT9XX_H_ */
diff --git a/drivers/input/touchscreen/gt9xx_v2.8/gt9xx_update.c b/drivers/input/touchscreen/gt9xx_v2.8/gt9xx_update.c
new file mode 100644
index 0000000..7a428a3
--- /dev/null
+++ b/drivers/input/touchscreen/gt9xx_v2.8/gt9xx_update.c
@@ -0,0 +1,2090 @@
+/*
+ * Goodix GT9xx touchscreen driver
+ *
+ * Copyright  (C)  2016 - 2017 Goodix. Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be a reference
+ * to you, when you are integrating the GOODiX's CTP IC into your system,
+ * 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/kthread.h>
+#include "gt9xx.h"
+
+#include <linux/namei.h>
+#include <linux/mount.h>
+#include <linux/firmware.h>
+#include <linux/ctype.h>
+
+#define GUP_REG_HW_INFO		0x4220
+#define GUP_REG_FW_MSG		0x41E4
+#define GUP_REG_PID_VID		0x8140
+
+#define FIRMWARE_NAME_LEN_MAX		256
+#define GOODIX_FIRMWARE_FILE_NAME	"goodix_firmware.bin"
+#define GOODIX_CONFIG_FILE_NAME		"goodix_config.cfg"
+
+#define FW_HEAD_LENGTH			14
+#define FW_SECTION_LENGTH		0x2000	/*  8K */
+#define FW_DSP_ISP_LENGTH		0x1000	/*  4K */
+#define FW_DSP_LENGTH			0x1000	/*  4K */
+#define FW_BOOT_LENGTH			0x800	/*  2K */
+#define FW_SS51_LENGTH		(4 * FW_SECTION_LENGTH)	/*  32K */
+#define FW_BOOT_ISP_LENGTH		0x800	/*  2k */
+#define FW_GLINK_LENGTH			0x3000	/*  12k */
+#define FW_GWAKE_LENGTH		(4 * FW_SECTION_LENGTH) /*  32k */
+
+#define DELAY_FOR_SENDCFG		500
+#define PACK_SIZE			256
+#define MAX_FRAME_CHECK_TIME		5
+
+#define _bRW_MISCTL__SRAM_BANK		0x4048
+#define _bRW_MISCTL__MEM_CD_EN		0x4049
+#define _bRW_MISCTL__CACHE_EN		0x404B
+#define _bRW_MISCTL__TMR0_EN		0x40B0
+#define _rRW_MISCTL__SWRST_B0_		0x4180
+#define _bWO_MISCTL__CPU_SWRST_PULSE	0x4184
+#define _rRW_MISCTL__BOOTCTL_B0_	0x4190
+#define _rRW_MISCTL__BOOT_OPT_B0_	0x4218
+#define _rRW_MISCTL__BOOT_CTL_		0x5094
+
+#pragma pack(1)
+struct st_fw_head {
+	u8	hw_info[4];			 /* hardware info */
+	u8	pid[8];				 /* product id */
+	u16 vid;				 /* version id */
+};
+#pragma pack()
+
+struct st_update_msg {
+	u8 fw_damaged;
+	u8 fw_flag;
+	const u8 *fw_data;
+	struct file *cfg_file;
+	struct st_fw_head ic_fw_msg;
+	u32 fw_total_len;
+	u32 fw_burned_len;
+	const struct firmware *fw;
+} update_msg;
+
+struct st_update_msg update_msg;
+
+u16 show_len;
+u16 total_len;
+
+static u8 gup_burn_fw_gwake_section(struct i2c_client *client,
+				    u8 *fw_section, u16 start_addr,
+				    u32 len, u8 bank_cmd);
+
+static s32 gup_init_panel(struct goodix_ts_data *ts)
+{
+	s32 ret = 0;
+	u8 opr_buf[16];
+	u8 sensor_id = 0;
+	u8 drv_cfg_version;
+	u8 flash_cfg_version;
+	struct goodix_config_data *cfg = &ts->pdata->config;
+
+	if (cfg->length < GTP_CONFIG_MIN_LENGTH) {
+		dev_err(&ts->client->dev,
+			"No valid config with sensor_ID(%d) ",
+			sensor_id);
+
+		return -EPERM;
+	}
+
+	ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA,
+				     &opr_buf[0], 1);
+	if (ret == SUCCESS) {
+		dev_dbg(&ts->client->dev,
+			"CFG_GROUP%d Config Version: %d, IC Config Version: %d",
+			sensor_id, cfg->data[GTP_ADDR_LENGTH], opr_buf[0]);
+
+		flash_cfg_version = opr_buf[0];
+		drv_cfg_version = cfg->data[GTP_ADDR_LENGTH];
+
+		if (flash_cfg_version < 90 &&
+		    flash_cfg_version > drv_cfg_version)
+			cfg->data[GTP_ADDR_LENGTH] = 0x00;
+	} else {
+		dev_err(&ts->client->dev,
+			"Failed to get ic config version!No config sent!");
+		return -EPERM;
+	}
+
+	ret = gtp_send_cfg(ts->client);
+	if (ret < 0)
+		dev_err(&ts->client->dev, "Send config error.");
+	else
+		usleep_range(10000, 11000);
+
+	/* restore config vrsion */
+	cfg->data[GTP_ADDR_LENGTH] = drv_cfg_version;
+
+	return 0;
+}
+
+
+static u8 gup_get_ic_msg(struct i2c_client *client, u16 addr, u8 *msg, s32 len)
+{
+	s32 i = 0;
+
+	msg[0] = (addr >> 8) & 0xff;
+	msg[1] = addr & 0xff;
+
+	for (i = 0; i < 5; i++) {
+		if (gtp_i2c_read(client, msg, GTP_ADDR_LENGTH + len) > 0)
+			break;
+	}
+
+	if (i >= 5) {
+		dev_err(&client->dev,
+				"Read data from 0x%02x%02x failed!",
+				msg[0], msg[1]);
+		return FAIL;
+	}
+
+	return SUCCESS;
+}
+
+static u8 gup_set_ic_msg(struct i2c_client *client, u16 addr, u8 val)
+{
+	s32 i = 0;
+	u8 msg[3];
+
+	msg[0] = (addr >> 8) & 0xff;
+	msg[1] = addr & 0xff;
+	msg[2] = val;
+
+	for (i = 0; i < 5; i++) {
+		if (gtp_i2c_write(client, msg, GTP_ADDR_LENGTH + 1) > 0)
+			break;
+	}
+
+	if (i >= 5) {
+		dev_err(&client->dev,
+			"Set data to 0x%02x%02x failed!", msg[0], msg[1]);
+		return FAIL;
+	}
+
+	return SUCCESS;
+}
+
+static u8 gup_get_ic_fw_msg(struct i2c_client *client)
+{
+	s32 ret = -1;
+	u8	retry = 0;
+	u8	buf[16];
+	u8	i;
+
+	/*  step1:get hardware info */
+	ret = gtp_i2c_read_dbl_check(client, GUP_REG_HW_INFO,
+				     &buf[GTP_ADDR_LENGTH], 4);
+	if (ret == FAIL) {
+		dev_err(&client->dev, "[get_ic_fw_msg]get hw_info failed,exit");
+		return FAIL;
+	}
+
+	/*  buf[2~5]: 00 06 90 00
+	 *  hw_info: 00 90 06 00
+	 */
+	for (i = 0; i < 4; i++)
+		update_msg.ic_fw_msg.hw_info[i] = buf[GTP_ADDR_LENGTH + 3 - i];
+		dev_dbg(&client->dev,
+			"IC Hardware info:%02x%02x%02x%02x",
+			update_msg.ic_fw_msg.hw_info[0],
+			update_msg.ic_fw_msg.hw_info[1],
+			update_msg.ic_fw_msg.hw_info[2],
+			update_msg.ic_fw_msg.hw_info[3]);
+	/*  step2:get firmware message */
+	for (retry = 0; retry < 2; retry++) {
+		ret = gup_get_ic_msg(client, GUP_REG_FW_MSG, buf, 1);
+		if (ret == FAIL) {
+			dev_err(&client->dev, "Read firmware message fail.");
+			return ret;
+		}
+
+		update_msg.fw_damaged = buf[GTP_ADDR_LENGTH];
+		if ((update_msg.fw_damaged != 0xBE) && (!retry)) {
+			dev_info(&client->dev, "The check sum in ic is error.");
+			dev_info(&client->dev, "The IC will be updated by force.");
+			continue;
+		}
+		break;
+	}
+	dev_dbg(&client->dev,
+		"IC force update flag:0x%x", update_msg.fw_damaged);
+
+	/*  step3:get pid & vid */
+	ret = gtp_i2c_read_dbl_check(client, GUP_REG_PID_VID,
+				     &buf[GTP_ADDR_LENGTH], 6);
+	if (ret == FAIL) {
+		dev_err(&client->dev, "[get_ic_fw_msg]get pid & vid failed,exit");
+		return FAIL;
+	}
+
+	memset(update_msg.ic_fw_msg.pid, 0, sizeof(update_msg.ic_fw_msg.pid));
+	memcpy(update_msg.ic_fw_msg.pid, &buf[GTP_ADDR_LENGTH], 4);
+	dev_dbg(&client->dev, "IC Product id:%s", update_msg.ic_fw_msg.pid);
+
+	/* GT9XX PID MAPPING */
+	/*|-----FLASH-----RAM-----|
+	 *|------918------918-----|
+	 *|------968------968-----|
+	 *|------913------913-----|
+	 *|------913P-----913P----|
+	 *|------927------927-----|
+	 *|------927P-----927P----|
+	 *|------9110-----9110----|
+	 *|------9110P----9111----|
+	 */
+	if (update_msg.ic_fw_msg.pid[0] != 0) {
+		if (!memcmp(update_msg.ic_fw_msg.pid, "9111", 4)) {
+			dev_dbg(&client->dev, "IC Mapping Product id:%s",
+					update_msg.ic_fw_msg.pid);
+			memcpy(update_msg.ic_fw_msg.pid, "9110P", 5);
+		}
+	}
+
+	update_msg.ic_fw_msg.vid = buf[GTP_ADDR_LENGTH + 4] +
+				   (buf[GTP_ADDR_LENGTH + 5] << 8);
+	dev_dbg(&client->dev, "IC version id:%04x", update_msg.ic_fw_msg.vid);
+
+	return SUCCESS;
+}
+
+s32 gup_enter_update_mode(struct i2c_client *client)
+{
+	s32 ret = -1;
+	s32 retry = 0;
+	u8 rd_buf[3];
+
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+	/* step1:RST output low last at least 2ms */
+	if (!gpio_is_valid(ts->pdata->rst_gpio)) {
+		dev_err(&ts->client->dev, "update failed, no rst pin\n");
+		return FAIL;
+	}
+	gtp_rst_output(ts, 0);
+	usleep_range(2000, 3000);
+
+	/* step2:select I2C slave addr,INT:0--0xBA;1--0x28. */
+	gtp_int_output(ts, client->addr == 0x14);
+	usleep_range(2000, 3000);
+
+	/* step3:RST output high reset guitar */
+	gtp_rst_output(ts, 1);
+
+	/* 20121211 modify start */
+	usleep_range(5000, 6000);
+	while (retry++ < 200) {
+		/* step4:Hold ss51 & dsp */
+		ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+		if (ret <= 0) {
+			dev_dbg(&client->dev,
+				"Hold ss51 & dsp I2C error,retry:%d",
+				retry);
+			continue;
+		}
+
+		/* step5:Confirm hold */
+		ret = gup_get_ic_msg(client, _rRW_MISCTL__SWRST_B0_, rd_buf, 1);
+		if (ret <= 0) {
+			dev_dbg(&client->dev,
+				"Hold ss51 & dsp I2C error,retry:%d",
+				retry);
+			continue;
+		}
+		if (rd_buf[GTP_ADDR_LENGTH] == 0x0C) {
+			dev_dbg(&client->dev, "Hold ss51 & dsp confirm SUCCESS");
+			break;
+		}
+		dev_dbg(&client->dev,
+			"Hold ss51 & dsp confirm 0x4180 failed,value:%d",
+			rd_buf[GTP_ADDR_LENGTH]);
+	}
+	if (retry >= 200) {
+		dev_err(&client->dev, "Enter update Hold ss51 failed.");
+		return FAIL;
+	}
+
+	/* step6:DSP_CK and DSP_ALU_CK PowerOn */
+	ret = gup_set_ic_msg(client, 0x4010, 0x00);
+
+	/* 20121211 modify end */
+	return ret;
+}
+
+void gup_leave_update_mode(struct i2c_client *client)
+{
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+	if (ts->pdata->int_sync && ts->pinctrl.pinctrl)
+		pinctrl_select_state(ts->pinctrl.pinctrl,
+				     ts->pinctrl.int_input);
+	else if (ts->pdata->int_sync && gpio_is_valid(ts->pdata->irq_gpio))
+		gpio_direction_input(ts->pdata->irq_gpio);
+	dev_dbg(&client->dev, "[leave_update_mode]reset chip.");
+	gtp_reset_guitar(i2c_connect_client, 20);
+}
+
+static u8 gup_enter_update_judge(struct i2c_client *client,
+				 struct st_fw_head *fw_head)
+{
+	u16 u16_tmp;
+	s32 i = 0;
+	u32 fw_len = 0;
+	s32 pid_cmp_len = 0;
+
+	u16_tmp = fw_head->vid;
+	fw_head->vid = (u16)(u16_tmp>>8) + (u16)(u16_tmp<<8);
+
+	dev_info(&client->dev, "FILE HARDWARE INFO:%*ph\n", 4,
+		 &fw_head->hw_info[0]);
+	dev_info(&client->dev, "FILE PID:%s\n", fw_head->pid);
+	dev_info(&client->dev, "FILE VID:%04x\n", fw_head->vid);
+
+	dev_info(&client->dev, "IC HARDWARE INFO:%*ph\n", 4,
+		 &update_msg.ic_fw_msg.hw_info[0]);
+	dev_info(&client->dev, "IC PID:%s\n", update_msg.ic_fw_msg.pid);
+	dev_info(&client->dev, "IC VID:%04x\n", update_msg.ic_fw_msg.vid);
+
+	if (!memcmp(fw_head->pid, "9158", 4) &&
+	    !memcmp(update_msg.ic_fw_msg.pid, "915S", 4)) {
+		dev_info(&client->dev, "Update GT915S to GT9158 directly!");
+		return SUCCESS;
+	}
+	/* First two conditions */
+	if (!memcmp(fw_head->hw_info, update_msg.ic_fw_msg.hw_info,
+	sizeof(update_msg.ic_fw_msg.hw_info))) {
+		fw_len = 42 * 1024;
+	} else {
+		fw_len = fw_head->hw_info[3];
+		fw_len += (((u32)fw_head->hw_info[2]) << 8);
+		fw_len += (((u32)fw_head->hw_info[1]) << 16);
+		fw_len += (((u32)fw_head->hw_info[0]) << 24);
+	}
+	if (update_msg.fw_total_len != fw_len) {
+		dev_err(&client->dev,
+			"Inconsistent firmware size, Update aborted!");
+		dev_err(&client->dev,
+			" Default size: %d(%dK), actual size: %d(%dK)",
+			fw_len, fw_len/1024, update_msg.fw_total_len,
+			update_msg.fw_total_len/1024);
+		return FAIL;
+	}
+	dev_info(&client->dev, "Firmware length:%d(%dK)",
+		 update_msg.fw_total_len,
+		 update_msg.fw_total_len/1024);
+
+	if (update_msg.fw_damaged != 0xBE) {
+		dev_info(&client->dev, "FW chksum error,need enter update.");
+		return SUCCESS;
+	}
+
+	/*  20130523 start */
+	if (strlen(update_msg.ic_fw_msg.pid) < 3) {
+		dev_info(&client->dev, "Illegal IC pid, need enter update");
+		return SUCCESS;
+	}
+
+	/* check pid legality */
+	for (i = 0; i < 3; i++) {
+		if (!isdigit(update_msg.ic_fw_msg.pid[i])) {
+			dev_info(&client->dev,
+				 "Illegal IC pid, need enter update");
+			return SUCCESS;
+		}
+	}
+	/*  20130523 end */
+
+	pid_cmp_len = strlen(fw_head->pid);
+	if (pid_cmp_len < strlen(update_msg.ic_fw_msg.pid))
+		pid_cmp_len = strlen(update_msg.ic_fw_msg.pid);
+
+	if ((!memcmp(fw_head->pid, update_msg.ic_fw_msg.pid, pid_cmp_len)) ||
+			(!memcmp(update_msg.ic_fw_msg.pid, "91XX", 4)) ||
+			(!memcmp(fw_head->pid, "91XX", 4))) {
+		if (!memcmp(fw_head->pid, "91XX", 4))
+			dev_dbg(&client->dev,
+				"Force none same pid update mode.");
+		else
+			dev_dbg(&client->dev, "Get the same pid.");
+
+		/* The third condition */
+		if (fw_head->vid != update_msg.ic_fw_msg.vid) {
+			dev_info(&client->dev, "Need enter update.");
+			return SUCCESS;
+		}
+		dev_err(&client->dev, "File VID == Ic VID, update aborted!");
+	} else {
+		dev_err(&client->dev, "File PID != Ic PID, update aborted!");
+	}
+
+	return FAIL;
+}
+
+static int gup_update_config(struct i2c_client *client)
+{
+	s32 ret = 0;
+	s32 i = 0;
+	s32 file_cfg_len = 0;
+	u8 *file_config;
+	const struct firmware *fw_cfg;
+
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+	ret = request_firmware(&fw_cfg, GOODIX_CONFIG_FILE_NAME,
+			       &client->dev);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"Cannot get config file - %s (%d)\n",
+			GOODIX_CONFIG_FILE_NAME, ret);
+		return -EFAULT;
+	}
+	if (!fw_cfg || !fw_cfg->data || fw_cfg->size > PAGE_SIZE) {
+		dev_err(&client->dev, "config file illegal");
+		ret = -EFAULT;
+		goto cfg_fw_err;
+	}
+
+	dev_dbg(&client->dev, "config firmware file len:%zu", fw_cfg->size);
+
+	file_config = kzalloc(GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH,
+			      GFP_KERNEL);
+	if (!file_config) {
+		ret = -ENOMEM;
+		goto cfg_fw_err;
+	}
+	file_config[0] = GTP_REG_CONFIG_DATA >> 8;
+	file_config[1] = GTP_REG_CONFIG_DATA & 0xff;
+	file_cfg_len = gtp_ascii_to_array(fw_cfg->data, fw_cfg->size,
+					  &file_config[GTP_ADDR_LENGTH]);
+	if (file_cfg_len < 0) {
+		dev_err(&client->dev, "failed covert ascii to hex");
+		ret = -EFAULT;
+		goto update_cfg_file_failed;
+	}
+
+	GTP_DEBUG_ARRAY(file_config + GTP_ADDR_LENGTH, file_cfg_len);
+
+	i = 0;
+	while (i++ < 5) {
+		ret = gtp_i2c_write(client, file_config, file_cfg_len + 2);
+		if (ret > 0) {
+			dev_info(&client->dev, "Send config SUCCESS.");
+			msleep(DELAY_FOR_SENDCFG);
+			break;
+		}
+		dev_err(&ts->client->dev, "Send config i2c error.");
+	}
+
+update_cfg_file_failed:
+	kfree(file_config);
+cfg_fw_err:
+	release_firmware(fw_cfg);
+	return ret;
+}
+
+static u8 gup_check_firmware_name(struct i2c_client *client,
+		u8 **path_p)
+{
+	u8 len;
+	u8 *fname;
+
+	if (!(*path_p)) {
+		*path_p = GOODIX_FIRMWARE_FILE_NAME;
+		return 0;
+	}
+
+	len = strnlen(*path_p, FIRMWARE_NAME_LEN_MAX);
+	if (len >= FIRMWARE_NAME_LEN_MAX) {
+		dev_err(&client->dev, "firmware name too long!");
+		return -EINVAL;
+	}
+
+	fname = strrchr(*path_p, '/');
+	if (fname) {
+		fname = fname + 1;
+		*path_p = fname;
+	}
+
+	return 0;
+}
+
+static u8 gup_get_update_file(struct i2c_client *client,
+				struct st_fw_head *fw_head, u8 *path)
+{
+	s32 ret = 0;
+	s32 i = 0;
+	s32 fw_checksum = 0;
+	struct goodix_ts_data *ts = i2c_get_clientdata(client);
+
+	if (ts->pdata->auto_update_cfg) {
+		ret = gup_update_config(client);
+		if (ret <= 0)
+			dev_err(&client->dev, "Update config failed.");
+	}
+
+	ret = gup_check_firmware_name(client, &path);
+	if (ret < 0)
+		return FAIL;
+
+	ret = request_firmware(&update_msg.fw, path, &client->dev);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed get firmware:%d\n", ret);
+		return FAIL;
+	}
+
+	dev_info(&client->dev, "FW File: %s size=%zu",
+		 path, update_msg.fw->size);
+	update_msg.fw_data = update_msg.fw->data;
+	update_msg.fw_total_len = update_msg.fw->size;
+
+	if (update_msg.fw_total_len <
+	    FW_HEAD_LENGTH + FW_SECTION_LENGTH * 4 + FW_DSP_ISP_LENGTH +
+	    FW_DSP_LENGTH + FW_BOOT_LENGTH) {
+		dev_err(&client->dev,
+			"INVALID bin file(size: %d), update aborted.",
+			update_msg.fw_total_len);
+		goto invalied_fw;
+	}
+
+	update_msg.fw_total_len -= FW_HEAD_LENGTH;
+
+	dev_dbg(&client->dev, "Bin firmware actual size: %d(%dK)",
+		update_msg.fw_total_len, update_msg.fw_total_len/1024);
+
+	memcpy(fw_head, update_msg.fw_data, FW_HEAD_LENGTH);
+
+	/* check firmware legality */
+	fw_checksum = 0;
+	for (i = 0; i < update_msg.fw_total_len; i += 2) {
+		u16 temp;
+
+		temp = (update_msg.fw_data[FW_HEAD_LENGTH + i] << 8) +
+			update_msg.fw_data[FW_HEAD_LENGTH + i + 1];
+		fw_checksum += temp;
+	}
+
+	dev_dbg(&client->dev, "firmware checksum:%x", fw_checksum&0xFFFF);
+	if (fw_checksum & 0xFFFF) {
+		dev_err(&client->dev, "Illegal firmware file.");
+		goto invalied_fw;
+	}
+
+	return SUCCESS;
+
+invalied_fw:
+	update_msg.fw_data = NULL;
+	update_msg.fw_total_len = 0;
+	release_firmware(update_msg.fw);
+	return FAIL;
+}
+
+static u8 gup_burn_proc(struct i2c_client *client, u8 *burn_buf,
+		u16 start_addr, u16 total_length)
+{
+	s32 ret = 0;
+	u16 burn_addr = start_addr;
+	u16 frame_length = 0;
+	u16 burn_length = 0;
+	u8 wr_buf[PACK_SIZE + GTP_ADDR_LENGTH];
+	u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH];
+	u8 retry = 0;
+
+	dev_dbg(&client->dev, "Begin burn %dk data to addr 0x%x",
+		total_length / 1024, start_addr);
+	while (burn_length < total_length) {
+		dev_dbg(&client->dev,
+			"B/T:%04d/%04d", burn_length, total_length);
+		frame_length = ((total_length - burn_length)
+		> PACK_SIZE) ? PACK_SIZE : (total_length - burn_length);
+		wr_buf[0] = (u8)(burn_addr>>8);
+		rd_buf[0] = wr_buf[0];
+		wr_buf[1] = (u8)burn_addr;
+		rd_buf[1] = wr_buf[1];
+		memcpy(&wr_buf[GTP_ADDR_LENGTH],
+		&burn_buf[burn_length], frame_length);
+
+		for (retry = 0; retry < MAX_FRAME_CHECK_TIME; retry++) {
+			ret = gtp_i2c_write(client,
+			wr_buf, GTP_ADDR_LENGTH + frame_length);
+			if (ret <= 0) {
+				dev_err(&client->dev,
+					"Write frame data i2c error.");
+				continue;
+			}
+			ret = gtp_i2c_read(client, rd_buf,
+					   GTP_ADDR_LENGTH + frame_length);
+			if (ret <= 0) {
+				dev_err(&client->dev,
+					"Read back frame data i2c error.");
+				continue;
+			}
+			if (memcmp(&wr_buf[GTP_ADDR_LENGTH],
+				&rd_buf[GTP_ADDR_LENGTH], frame_length)) {
+				dev_err(&client->dev,
+					"Check frame data fail,not equal.");
+				dev_dbg(&client->dev, "write array:");
+				GTP_DEBUG_ARRAY(&wr_buf[GTP_ADDR_LENGTH],
+				frame_length);
+				dev_dbg(&client->dev, "read array:");
+				GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH],
+				frame_length);
+				continue;
+			} else {
+				/* dev_dbg(&client->dev,
+				 * "Check frame data success.");
+				 */
+				break;
+			}
+		}
+		if (retry >= MAX_FRAME_CHECK_TIME) {
+			dev_err(&client->dev,
+				"Burn frame data time out,exit.");
+			return FAIL;
+		}
+		burn_length += frame_length;
+		burn_addr += frame_length;
+	}
+
+	return SUCCESS;
+}
+
+static u8 gup_load_section_file(u8 *buf, u32 offset, u16 length, u8 set_or_end)
+{
+	if (!update_msg.fw_data ||
+	    update_msg.fw_total_len < FW_HEAD_LENGTH + offset + length) {
+		pr_err("<<-GTP->> cannot load section data. fw_len=%d read end=%d\n",
+		update_msg.fw_total_len,
+		FW_HEAD_LENGTH + offset + length);
+		return FAIL;
+	}
+
+	if (set_or_end == SEEK_SET) {
+		memcpy(buf, &update_msg.fw_data[FW_HEAD_LENGTH + offset],
+		       length);
+	} else {
+		/* seek end */
+		memcpy(buf, &update_msg.fw_data[update_msg.fw_total_len +
+		       FW_HEAD_LENGTH - offset], length);
+	}
+
+	return SUCCESS;
+}
+
+static u8 gup_recall_check(struct i2c_client *client, u8 *chk_src,
+			   u16 start_rd_addr, u16 chk_length)
+{
+	u8 rd_buf[PACK_SIZE + GTP_ADDR_LENGTH];
+	s32 ret = 0;
+	u16 recall_addr = start_rd_addr;
+	u16 recall_length = 0;
+	u16 frame_length = 0;
+
+	while (recall_length < chk_length) {
+		frame_length = ((chk_length - recall_length)
+				> PACK_SIZE) ? PACK_SIZE :
+				(chk_length - recall_length);
+		ret = gup_get_ic_msg(client, recall_addr, rd_buf, frame_length);
+		if (ret <= 0) {
+			dev_err(&client->dev, "recall i2c error,exit");
+			return FAIL;
+		}
+
+		if (memcmp(&rd_buf[GTP_ADDR_LENGTH],
+		&chk_src[recall_length], frame_length)) {
+			dev_err(&client->dev, "Recall frame data fail,not equal.");
+			dev_dbg(&client->dev, "chk_src array:");
+			GTP_DEBUG_ARRAY(&chk_src[recall_length], frame_length);
+			dev_dbg(&client->dev, "recall array:");
+			GTP_DEBUG_ARRAY(&rd_buf[GTP_ADDR_LENGTH], frame_length);
+			return FAIL;
+		}
+
+		recall_length += frame_length;
+		recall_addr += frame_length;
+	}
+	dev_dbg(&client->dev,
+			"Recall check %dk firmware success.",
+			(chk_length/1024));
+
+	return SUCCESS;
+}
+
+static u8 gup_burn_fw_section(struct i2c_client *client, u8 *fw_section,
+			      u16 start_addr, u8 bank_cmd)
+{
+	s32 ret = 0;
+	u8	rd_buf[5];
+
+	/* step1:hold ss51 & dsp */
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_section]hold ss51 & dsp fail.");
+		return FAIL;
+	}
+
+	/* step2:set scramble */
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_section]set scramble fail.");
+		return FAIL;
+	}
+
+	/* step3:select bank */
+	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK,
+	(bank_cmd >> 4)&0x0F);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_section]select bank %d fail.",
+			(bank_cmd >> 4)&0x0F);
+		return FAIL;
+	}
+
+	/* step4:enable accessing code */
+	ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_section]enable accessing code fail.");
+		return FAIL;
+	}
+
+	/* step5:burn 8k fw section */
+	ret = gup_burn_proc(client, fw_section, start_addr, FW_SECTION_LENGTH);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_section]burn fw_section fail.");
+		return FAIL;
+	}
+
+	/* step6:hold ss51 & release dsp */
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_section]hold ss51 & release dsp fail.");
+		return FAIL;
+	}
+	/* must delay */
+	usleep_range(1000, 2000);
+
+	/* step7:send burn cmd to move data to flash from sram */
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0f);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_section]send burn cmd fail.");
+		return FAIL;
+	}
+	dev_dbg(&client->dev,
+		"[burn_fw_section]Wait for the burn is complete......");
+	do {
+		ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
+		if (ret <= 0) {
+			dev_err(&client->dev,
+				"[burn_fw_section]Get burn state fail");
+			return FAIL;
+		}
+		usleep_range(10000, 11000);
+	/* dev_dbg(&client->dev, "[burn_fw_section]Get burn state:%d.",
+	 * rd_buf[GTP_ADDR_LENGTH]);
+	 */
+	} while (rd_buf[GTP_ADDR_LENGTH]);
+
+	/* step8:select bank */
+	ret = gup_set_ic_msg(client,
+			     _bRW_MISCTL__SRAM_BANK, (bank_cmd >> 4) & 0x0F);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_section]select bank %d fail.",
+			(bank_cmd >> 4)&0x0F);
+		return FAIL;
+	}
+
+	/* step9:enable accessing code */
+	ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_section]enable accessing code fail.");
+		return FAIL;
+	}
+
+	/* step10:recall 8k fw section */
+	ret = gup_recall_check(client,
+	fw_section, start_addr, FW_SECTION_LENGTH);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_section]recall check %dk firmware fail.",
+			FW_SECTION_LENGTH / 1024);
+		return FAIL;
+	}
+
+	/* step11:disable accessing code */
+	ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x00);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_section]disable accessing code fail.");
+		return FAIL;
+	}
+
+	return SUCCESS;
+}
+
+static u8 gup_burn_dsp_isp(struct i2c_client *client)
+{
+	s32 ret = 0;
+	u8 *fw_dsp_isp = NULL;
+	u8	retry = 0;
+
+	dev_info(&client->dev, "[burn_dsp_isp]Begin burn dsp isp---->>");
+
+	/* step1:alloc memory */
+	dev_dbg(&client->dev, "[burn_dsp_isp]step1:alloc memory");
+	while (retry++ < 5) {
+		fw_dsp_isp = kzalloc(FW_DSP_ISP_LENGTH, GFP_KERNEL);
+		if (fw_dsp_isp == NULL) {
+			continue;
+		} else {
+			dev_info(&client->dev,
+				"[burn_dsp_isp]Alloc %dk byte memory success.",
+				FW_DSP_ISP_LENGTH / 1024);
+			break;
+		}
+	}
+	if (retry >= 5) {
+		dev_err(&client->dev, "[burn_dsp_isp]Alloc memory fail,exit.");
+		return FAIL;
+	}
+
+	/* step2:load dsp isp file data */
+	dev_dbg(&client->dev, "[burn_dsp_isp]step2:load dsp isp file data");
+	ret = gup_load_section_file(fw_dsp_isp,
+	FW_DSP_ISP_LENGTH, FW_DSP_ISP_LENGTH, SEEK_END);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_dsp_isp]load firmware dsp_isp fail.");
+		goto exit_burn_dsp_isp;
+	}
+
+	/* step3:disable wdt,clear cache enable */
+	dev_dbg(&client->dev,
+		"[burn_dsp_isp]step3:disable wdt,clear cache enable");
+	ret = gup_set_ic_msg(client, _bRW_MISCTL__TMR0_EN, 0x00);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_dsp_isp]disable wdt fail.");
+		ret = FAIL;
+		goto exit_burn_dsp_isp;
+	}
+	ret = gup_set_ic_msg(client, _bRW_MISCTL__CACHE_EN, 0x00);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_dsp_isp]clear cache enable fail.");
+		ret = FAIL;
+		goto exit_burn_dsp_isp;
+	}
+
+	/* step4:hold ss51 & dsp */
+	dev_dbg(&client->dev, "[burn_dsp_isp]step4:hold ss51 & dsp");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_dsp_isp]hold ss51 & dsp fail.");
+		ret = FAIL;
+		goto exit_burn_dsp_isp;
+	}
+
+	/* step5:set boot from sram */
+	dev_dbg(&client->dev, "[burn_dsp_isp]step5:set boot from sram");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOTCTL_B0_, 0x02);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_dsp_isp]set boot from sram fail");
+		ret = FAIL;
+		goto exit_burn_dsp_isp;
+	}
+
+	/* step6:software reboot */
+	dev_dbg(&client->dev, "[burn_dsp_isp]step6:software reboot");
+	ret = gup_set_ic_msg(client, _bWO_MISCTL__CPU_SWRST_PULSE, 0x01);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_dsp_isp]software reboot fail.");
+		ret = FAIL;
+		goto exit_burn_dsp_isp;
+	}
+
+	/* step7:select bank2 */
+	dev_dbg(&client->dev, "[burn_dsp_isp]step7:select bank2");
+	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x02);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_dsp_isp]select bank2 fail");
+		ret = FAIL;
+		goto exit_burn_dsp_isp;
+	}
+
+	/* step8:enable accessing code */
+	dev_dbg(&client->dev, "[burn_dsp_isp]step8:enable accessing code");
+	ret = gup_set_ic_msg(client, _bRW_MISCTL__MEM_CD_EN, 0x01);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_dsp_isp]enable accessing code fail.");
+		ret = FAIL;
+		goto exit_burn_dsp_isp;
+	}
+
+	/* step9:burn 4k dsp_isp */
+	dev_dbg(&client->dev, "[burn_dsp_isp]step9:burn 4k dsp_isp");
+	ret = gup_burn_proc(client, fw_dsp_isp, 0xC000, FW_DSP_ISP_LENGTH);
+	if (ret == FAIL) {
+		dev_err(&client->dev, "[burn_dsp_isp]burn dsp_isp fail.");
+		goto exit_burn_dsp_isp;
+	}
+
+	/* step10:set scramble */
+	dev_dbg(&client->dev, "[burn_dsp_isp]step10:set scramble");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_dsp_isp]set scramble fail.");
+		ret = FAIL;
+		goto exit_burn_dsp_isp;
+	}
+	update_msg.fw_burned_len += FW_DSP_ISP_LENGTH;
+	dev_dbg(&client->dev, "[burn_dsp_isp]Burned length:%d",
+			update_msg.fw_burned_len);
+	ret = SUCCESS;
+
+exit_burn_dsp_isp:
+	kfree(fw_dsp_isp);
+
+	return ret;
+}
+
+static u8 gup_burn_fw_ss51(struct i2c_client *client)
+{
+	u8 *fw_ss51 = NULL;
+	u8	retry = 0;
+	s32 ret = 0;
+
+	dev_info(&client->dev, "[burn_fw_ss51]Begin burn ss51 firmware---->>");
+
+	/* step1:alloc memory */
+	dev_dbg(&client->dev, "[burn_fw_ss51]step1:alloc memory");
+	while (retry++ < 5) {
+		fw_ss51 = kzalloc(FW_SECTION_LENGTH, GFP_KERNEL);
+		if (fw_ss51 == NULL) {
+			continue;
+		} else {
+			dev_dbg(&client->dev,
+				"[burn_fw_ss51]Alloc %dk byte memory success.",
+				(FW_SECTION_LENGTH / 1024));
+			break;
+		}
+	}
+	if (retry >= 5) {
+		dev_err(&client->dev, "[burn_fw_ss51]Alloc memory fail,exit.");
+		return FAIL;
+	}
+
+	dev_info(&client->dev, "[burn_fw_ss51]Reset first 8K of ss51 to 0xFF.");
+	dev_dbg(&client->dev, "[burn_fw_ss51]step2: reset bank0 0xC000~0xD000");
+	memset(fw_ss51, 0xFF, FW_SECTION_LENGTH);
+
+	/* step3:clear control flag */
+	dev_dbg(&client->dev, "[burn_fw_ss51]step3:clear control flag");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_ss51]clear control flag fail.");
+		ret = FAIL;
+		goto exit_burn_fw_ss51;
+	}
+
+	/* step4:burn ss51 firmware section 1 */
+	dev_dbg(&client->dev,
+		"[burn_fw_ss51]step4:burn ss51 firmware section 1");
+	ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_ss51]burn ss51 firmware section 1 fail.");
+		goto exit_burn_fw_ss51;
+	}
+
+	/* step5:load ss51 firmware section 2 file data */
+	dev_dbg(&client->dev,
+		"[burn_fw_ss51]step5:load ss51 firmware section 2 file data");
+	ret = gup_load_section_file(fw_ss51,
+	FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_ss51]load ss51 firmware section 2 fail.");
+		goto exit_burn_fw_ss51;
+	}
+
+	/* step6:burn ss51 firmware section 2 */
+	dev_dbg(&client->dev,
+		"[burn_fw_ss51]step6:burn ss51 firmware section 2");
+	ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x02);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_ss51]burn ss51 firmware section 2 fail.");
+		goto exit_burn_fw_ss51;
+	}
+
+	/* step7:load ss51 firmware section 3 file data */
+	dev_dbg(&client->dev,
+		"[burn_fw_ss51]step7:load ss51 firmware section 3 file data");
+	ret = gup_load_section_file(fw_ss51,
+	2 * FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_ss51]load ss51 firmware section 3 fail.");
+		goto exit_burn_fw_ss51;
+	}
+
+	/* step8:burn ss51 firmware section 3 */
+	dev_dbg(&client->dev,
+		"[burn_fw_ss51]step8:burn ss51 firmware section 3");
+	ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x13);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_ss51]burn ss51 firmware section 3 fail.");
+		goto exit_burn_fw_ss51;
+	}
+
+	/* step9:load ss51 firmware section 4 file data */
+	dev_dbg(&client->dev,
+		"[burn_fw_ss51]step9:load ss51 firmware section 4 file data");
+	ret = gup_load_section_file(fw_ss51,
+	3 * FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_ss51]load ss51 firmware section 4 fail.");
+		goto exit_burn_fw_ss51;
+	}
+
+	/* step10:burn ss51 firmware section 4 */
+	dev_dbg(&client->dev,
+		"[burn_fw_ss51]step10:burn ss51 firmware section 4");
+	ret = gup_burn_fw_section(client, fw_ss51, 0xE000, 0x14);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_ss51]burn ss51 firmware section 4 fail.");
+		goto exit_burn_fw_ss51;
+	}
+
+	update_msg.fw_burned_len += (FW_SECTION_LENGTH*4);
+	dev_dbg(&client->dev, "[burn_fw_ss51]Burned length:%d",
+		update_msg.fw_burned_len);
+	ret = SUCCESS;
+
+exit_burn_fw_ss51:
+	kfree(fw_ss51);
+	return ret;
+}
+
+static u8 gup_burn_fw_dsp(struct i2c_client *client)
+{
+	s32 ret = 0;
+	u8 *fw_dsp = NULL;
+	u8 retry = 0;
+	u8 rd_buf[5];
+
+	dev_info(&client->dev, "[burn_fw_dsp]Begin burn dsp firmware---->>");
+	/* step1:alloc memory */
+	dev_dbg(&client->dev, "[burn_fw_dsp]step1:alloc memory");
+	while (retry++ < 5) {
+		fw_dsp = kzalloc(FW_DSP_LENGTH, GFP_KERNEL);
+		if (fw_dsp == NULL) {
+			continue;
+		} else {
+			dev_dbg(&client->dev,
+				"[burn_fw_dsp]Alloc %dk byte memory success.",
+				FW_SECTION_LENGTH / 1024);
+			break;
+		}
+	}
+	if (retry >= 5) {
+		dev_err(&client->dev, "[burn_fw_dsp]Alloc memory fail,exit.");
+		return FAIL;
+	}
+
+	/* step2:load firmware dsp */
+	dev_dbg(&client->dev, "[burn_fw_dsp]step2:load firmware dsp");
+	ret = gup_load_section_file(fw_dsp,
+	4 * FW_SECTION_LENGTH, FW_DSP_LENGTH, SEEK_SET);
+	if (ret == FAIL) {
+		dev_err(&client->dev, "[burn_fw_dsp]load firmware dsp fail.");
+		goto exit_burn_fw_dsp;
+	}
+
+	/* step3:select bank3 */
+	dev_dbg(&client->dev, "[burn_fw_dsp]step3:select bank3");
+	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_dsp]select bank3 fail.");
+		ret = FAIL;
+		goto exit_burn_fw_dsp;
+	}
+
+	/* step4:hold ss51 & dsp */
+	dev_dbg(&client->dev, "[burn_fw_dsp]step4:hold ss51 & dsp");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_dsp]hold ss51 & dsp fail.");
+		ret = FAIL;
+		goto exit_burn_fw_dsp;
+	}
+
+	/* step5:set scramble */
+	dev_dbg(&client->dev, "[burn_fw_dsp]step5:set scramble");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_dsp]set scramble fail.");
+		ret = FAIL;
+		goto exit_burn_fw_dsp;
+	}
+
+	/* step6:release ss51 & dsp */
+	dev_dbg(&client->dev, "[burn_fw_dsp]step6:release ss51 & dsp");
+	ret = gup_set_ic_msg(
+	client, _rRW_MISCTL__SWRST_B0_, 0x04);/* 20121211 */
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_dsp]release ss51 & dsp fail.");
+		ret = FAIL;
+		goto exit_burn_fw_dsp;
+	}
+	/* must delay */
+	usleep_range(1000, 1100);
+
+	/* step7:burn 4k dsp firmware */
+	dev_dbg(&client->dev, "[burn_fw_dsp]step7:burn 4k dsp firmware");
+	ret = gup_burn_proc(client, fw_dsp, 0x9000, FW_DSP_LENGTH);
+	if (ret == FAIL) {
+		dev_err(&client->dev, "[burn_fw_dsp]burn fw_section fail.");
+		goto exit_burn_fw_dsp;
+	}
+
+	/* step8:send burn cmd to move data to flash from sram */
+	dev_dbg(&client->dev,
+	"[burn_fw_dsp]step8:send burn cmd to move data to flash from sram");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x05);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_dsp]send burn cmd fail.");
+		goto exit_burn_fw_dsp;
+	}
+	dev_dbg(&client->dev, "[burn_fw_dsp]Wait for the burn is complete......");
+	do {
+		ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
+		if (ret <= 0) {
+			dev_err(&client->dev, "[burn_fw_dsp]Get burn state fail");
+			goto exit_burn_fw_dsp;
+		}
+		usleep_range(10000, 11000);
+	/* dev_dbg(&client->dev, "[burn_fw_dsp]Get burn state:%d.",
+	 * rd_buf[GTP_ADDR_LENGTH]);
+	 */
+	} while (rd_buf[GTP_ADDR_LENGTH]);
+
+	/* step9:recall check 4k dsp firmware */
+	dev_dbg(&client->dev,
+		"[burn_fw_dsp]step9:recall check 4k dsp firmware");
+	ret = gup_recall_check(client, fw_dsp, 0x9000, FW_DSP_LENGTH);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_dsp]recall check 4k dsp firmware fail.");
+		goto exit_burn_fw_dsp;
+	}
+
+	update_msg.fw_burned_len += FW_DSP_LENGTH;
+	dev_dbg(&client->dev, "[burn_fw_dsp]Burned length:%d",
+			update_msg.fw_burned_len);
+	ret = SUCCESS;
+
+exit_burn_fw_dsp:
+	kfree(fw_dsp);
+
+	return ret;
+}
+
+static u8 gup_burn_fw_boot(struct i2c_client *client)
+{
+	s32 ret = 0;
+	u8 *fw_boot = NULL;
+	u8	retry = 0;
+	u8	rd_buf[5];
+
+	dev_info(&client->dev,
+		 "[burn_fw_boot]Begin burn bootloader firmware---->>");
+
+	/* step1:Alloc memory */
+	dev_dbg(&client->dev, "[burn_fw_boot]step1:Alloc memory");
+	while (retry++ < 5) {
+		fw_boot = kzalloc(FW_BOOT_LENGTH, GFP_KERNEL);
+		if (fw_boot == NULL) {
+			continue;
+		} else {
+			dev_dbg(&client->dev,
+				"[burn_fw_boot]Alloc %dk byte memory success.",
+				FW_BOOT_LENGTH / 1024);
+			break;
+		}
+	}
+	if (retry >= 5) {
+		dev_err(&client->dev, "[burn_fw_boot]Alloc memory fail,exit.");
+		return FAIL;
+	}
+
+	/* step2:load firmware bootloader */
+	dev_dbg(&client->dev, "[burn_fw_boot]step2:load firmware bootloader");
+	ret = gup_load_section_file(fw_boot,
+	(4 * FW_SECTION_LENGTH + FW_DSP_LENGTH), FW_BOOT_LENGTH, SEEK_SET);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_boot]load firmware bootcode fail.");
+		goto exit_burn_fw_boot;
+	}
+
+	/* step3:hold ss51 & dsp */
+	dev_dbg(&client->dev, "[burn_fw_boot]step3:hold ss51 & dsp");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_boot]hold ss51 & dsp fail.");
+		ret = FAIL;
+		goto exit_burn_fw_boot;
+	}
+
+	/* step4:set scramble */
+	dev_dbg(&client->dev, "[burn_fw_boot]step4:set scramble");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_boot]set scramble fail.");
+		ret = FAIL;
+		goto exit_burn_fw_boot;
+	}
+
+	/* step5:hold ss51 & release dsp */
+	dev_dbg(&client->dev, "[burn_fw_boot]step5:hold ss51 & release dsp");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
+	/* 20121211 */
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_boot]release ss51 & dsp fail");
+		ret = FAIL;
+		goto exit_burn_fw_boot;
+	}
+	/* must delay */
+	usleep_range(1000, 1100);
+
+	/* step6:select bank3 */
+	dev_dbg(&client->dev, "[burn_fw_boot]step6:select bank3");
+	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_boot]select bank3 fail.");
+		ret = FAIL;
+		goto exit_burn_fw_boot;
+	}
+
+	/* step6:burn 2k bootloader firmware */
+	dev_dbg(&client->dev,
+		"[burn_fw_boot]step6:burn 2k bootloader firmware");
+	ret = gup_burn_proc(client, fw_boot, 0x9000, FW_BOOT_LENGTH);
+	if (ret == FAIL) {
+		dev_err(&client->dev, "[burn_fw_boot]burn fw_boot fail.");
+		goto exit_burn_fw_boot;
+	}
+
+	/* step7:send burn cmd to move data to flash from sram */
+	dev_dbg(&client->dev,
+	"[burn_fw_boot]step7:send burn cmd to move data to flash from sram");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x06);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_boot]send burn cmd fail.");
+		goto exit_burn_fw_boot;
+	}
+	dev_dbg(&client->dev,
+		"[burn_fw_boot]Wait for the burn is complete......");
+	do {
+		ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
+		if (ret <= 0) {
+			dev_err(&client->dev,
+				"[burn_fw_boot]Get burn state fail");
+			goto exit_burn_fw_boot;
+		}
+		usleep_range(10000, 11000);
+	/* dev_dbg(&client->dev, "[burn_fw_boot]Get burn state:%d.",
+	 * rd_buf[GTP_ADDR_LENGTH]);
+	 */
+	} while (rd_buf[GTP_ADDR_LENGTH]);
+
+	/* step8:recall check 2k bootloader firmware */
+	dev_dbg(&client->dev,
+		"[burn_fw_boot]step8:recall check 2k bootloader firmware");
+	ret = gup_recall_check(client, fw_boot, 0x9000, FW_BOOT_LENGTH);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_boot]recall check 2k bootcode firmware fail");
+		goto exit_burn_fw_boot;
+	}
+
+	update_msg.fw_burned_len += FW_BOOT_LENGTH;
+	dev_dbg(&client->dev, "[burn_fw_boot]Burned length:%d",
+		update_msg.fw_burned_len);
+	ret = SUCCESS;
+
+exit_burn_fw_boot:
+	kfree(fw_boot);
+
+	return ret;
+}
+static u8 gup_burn_fw_boot_isp(struct i2c_client *client)
+{
+	s32 ret = 0;
+	u8 *fw_boot_isp = NULL;
+	u8	retry = 0;
+	u8	rd_buf[5];
+
+	if (update_msg.fw_burned_len >= update_msg.fw_total_len) {
+		dev_dbg(&client->dev, "No need to upgrade the boot_isp code!");
+		return SUCCESS;
+	}
+	dev_info(&client->dev,
+		"[burn_fw_boot_isp]Begin burn boot_isp firmware---->>");
+
+	/* step1:Alloc memory */
+	dev_dbg(&client->dev, "[burn_fw_boot_isp]step1:Alloc memory");
+	while (retry++ < 5) {
+		fw_boot_isp = kzalloc(FW_BOOT_ISP_LENGTH, GFP_KERNEL);
+		if (fw_boot_isp == NULL) {
+			continue;
+		} else {
+			dev_dbg(&client->dev,
+				"[burn_fw_boot_isp]Alloc %dk byte memory success.",
+				(FW_BOOT_ISP_LENGTH/1024));
+			break;
+		}
+	}
+	if (retry >= 5) {
+		dev_err(&client->dev,
+			"[burn_fw_boot_isp]Alloc memory fail,exit.");
+		return FAIL;
+	}
+
+	/* step2:load firmware bootloader */
+	dev_dbg(&client->dev,
+		"[burn_fw_boot_isp]step2:load firmware bootloader isp");
+	/* ret = gup_load_section_file(fw_boot_isp,
+	 * (4*FW_SECTION_LENGTH+FW_DSP_LENGTH +
+	 * FW_BOOT_LENGTH+FW_DSP_ISP_LENGTH), FW_BOOT_ISP_LENGTH, SEEK_SET);
+	 */
+	ret = gup_load_section_file(fw_boot_isp,
+	(update_msg.fw_burned_len - FW_DSP_ISP_LENGTH),
+	FW_BOOT_ISP_LENGTH, SEEK_SET);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_boot_isp]load firmware boot_isp fail.");
+		goto exit_burn_fw_boot_isp;
+	}
+
+	/* step3:hold ss51 & dsp */
+	dev_dbg(&client->dev, "[burn_fw_boot_isp]step3:hold ss51 & dsp");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_boot_isp]hold ss51 & dsp fail");
+		ret = FAIL;
+		goto exit_burn_fw_boot_isp;
+	}
+
+	/* step4:set scramble */
+	dev_dbg(&client->dev, "[burn_fw_boot_isp]step4:set scramble");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_boot_isp]set scramble fail.");
+		ret = FAIL;
+		goto exit_burn_fw_boot_isp;
+	}
+
+
+	/* step5:hold ss51 & release dsp */
+	dev_dbg(&client->dev,
+		"[burn_fw_boot_isp]step5:hold ss51 & release dsp");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
+	/* 20121211 */
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_boot_isp]release ss51 & dsp fail.");
+		ret = FAIL;
+		goto exit_burn_fw_boot_isp;
+	}
+	/* must delay */
+	usleep_range(1000, 2000);
+
+	/* step6:select bank3 */
+	dev_dbg(&client->dev, "[burn_fw_boot_isp]step6:select bank3");
+	ret = gup_set_ic_msg(client, _bRW_MISCTL__SRAM_BANK, 0x03);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_boot_isp]select bank3 fail.");
+		ret = FAIL;
+		goto exit_burn_fw_boot_isp;
+	}
+
+	/* step7:burn 2k bootload_isp firmware */
+	dev_dbg(&client->dev,
+		"[burn_fw_boot_isp]step7:burn 2k bootloader firmware");
+	ret = gup_burn_proc(client, fw_boot_isp, 0x9000, FW_BOOT_ISP_LENGTH);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_boot_isp]burn fw_section fail.");
+		goto exit_burn_fw_boot_isp;
+	}
+
+	/* step7:send burn cmd to move data to flash from sram */
+	dev_dbg(&client->dev,
+	"[burn_fw_boot_isp]step8:send burn cmd to move data to flash from sram");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x07);
+	if (ret <= 0) {
+		dev_err(&client->dev, "[burn_fw_boot_isp]send burn cmd fail.");
+		goto exit_burn_fw_boot_isp;
+	}
+	dev_dbg(&client->dev,
+		"[burn_fw_boot_isp]Wait for the burn is complete......");
+	do {
+		ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
+		if (ret <= 0) {
+			dev_err(&client->dev,
+				"[burn_fw_boot_isp]Get burn state fail");
+			goto exit_burn_fw_boot_isp;
+		}
+		usleep_range(10000, 11000);
+	/* dev_dbg(&client->dev, "[burn_fw_boot_isp]Get
+	 * burn state:%d.", rd_buf[GTP_ADDR_LENGTH]);
+	 */
+	} while (rd_buf[GTP_ADDR_LENGTH]);
+
+	/* step8:recall check 2k bootload_isp firmware */
+	dev_dbg(&client->dev,
+		"[burn_fw_boot_isp]step9:recall check 2k bootloader firmware");
+	ret = gup_recall_check(client, fw_boot_isp, 0x9000, FW_BOOT_ISP_LENGTH);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+		"[burn_fw_boot_isp]recall check 2k bootcode_isp firmware fail.");
+		goto exit_burn_fw_boot_isp;
+	}
+
+	update_msg.fw_burned_len += FW_BOOT_ISP_LENGTH;
+	dev_dbg(&client->dev,
+		"[burn_fw_boot_isp]Burned length:%d", update_msg.fw_burned_len);
+	ret = SUCCESS;
+
+exit_burn_fw_boot_isp:
+	kfree(fw_boot_isp);
+
+	return ret;
+}
+
+static u8 gup_burn_fw_link(struct i2c_client *client)
+{
+	u8 *fw_link = NULL;
+	u8	retry = 0;
+	s32 ret = 0;
+	u32 offset;
+
+	if (update_msg.fw_burned_len >= update_msg.fw_total_len) {
+		dev_dbg(&client->dev, "No need to upgrade the link code!");
+		return SUCCESS;
+	}
+	dev_info(&client->dev, "[burn_fw_link]Begin burn link firmware---->>");
+
+	/* step1:Alloc memory */
+	dev_dbg(&client->dev, "[burn_fw_link]step1:Alloc memory");
+	while (retry++ < 5) {
+		fw_link = kzalloc(FW_SECTION_LENGTH, GFP_KERNEL);
+		if (fw_link == NULL) {
+			continue;
+		} else {
+			dev_dbg(&client->dev,
+				"[burn_fw_link]Alloc %dk byte memory success.",
+				(FW_SECTION_LENGTH/1024));
+			break;
+		}
+	}
+	if (retry >= 5) {
+		dev_err(&client->dev, "[burn_fw_link]Alloc memory fail,exit.");
+		return FAIL;
+	}
+
+	/* step2:load firmware link section 1 */
+	dev_dbg(&client->dev,
+		"[burn_fw_link]step2:load firmware link section 1");
+	offset = update_msg.fw_burned_len - FW_DSP_ISP_LENGTH;
+	ret = gup_load_section_file(
+	fw_link, offset, FW_SECTION_LENGTH, SEEK_SET);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_link]load firmware link section 1 fail.");
+		goto exit_burn_fw_link;
+	}
+
+	/* step3:burn link firmware section 1 */
+	dev_dbg(&client->dev,
+		"[burn_fw_link]step3:burn link firmware section 1");
+	ret = gup_burn_fw_gwake_section(
+	client, fw_link, 0x9000, FW_SECTION_LENGTH, 0x38);
+
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_link]burn link firmware section 1 fail.");
+		goto exit_burn_fw_link;
+	}
+
+	/* step4:load link firmware section 2 file data */
+	dev_dbg(&client->dev,
+		"[burn_fw_link]step4:load link firmware section 2 file data");
+	offset += FW_SECTION_LENGTH;
+	ret = gup_load_section_file(
+	fw_link, offset, FW_GLINK_LENGTH - FW_SECTION_LENGTH, SEEK_SET);
+
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_link]load link firmware section 2 fail.");
+		goto exit_burn_fw_link;
+	}
+
+	/* step5:burn link firmware section 2 */
+	dev_dbg(&client->dev,
+		"[burn_fw_link]step4:burn link firmware section 2");
+	ret = gup_burn_fw_gwake_section(client,
+	fw_link, 0x9000, FW_GLINK_LENGTH - FW_SECTION_LENGTH, 0x39);
+
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_link]burn link firmware section 2 fail.");
+		goto exit_burn_fw_link;
+	}
+
+	update_msg.fw_burned_len += FW_GLINK_LENGTH;
+	dev_dbg(&client->dev,
+		"[burn_fw_link]Burned length:%d", update_msg.fw_burned_len);
+	ret = SUCCESS;
+
+exit_burn_fw_link:
+	kfree(fw_link);
+
+	return ret;
+}
+
+static u8 gup_burn_fw_gwake_section(struct i2c_client *client,
+		u8 *fw_section, u16 start_addr, u32 len, u8 bank_cmd)
+{
+	s32 ret = 0;
+	u8	rd_buf[5];
+
+	/* step1:hold ss51 & dsp */
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x0C);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_app_section]hold ss51 & dsp fail.");
+		return FAIL;
+	}
+
+	/* step2:set scramble */
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_OPT_B0_, 0x00);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_app_section]set scramble fail.");
+		return FAIL;
+	}
+
+	/* step3:hold ss51 & release dsp */
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x04);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_app_section]hold ss51 & release dsp fail.");
+		return FAIL;
+	}
+	/* must delay */
+	usleep_range(1000, 2000);
+
+	/* step4:select bank */
+	ret = gup_set_ic_msg(
+	client, _bRW_MISCTL__SRAM_BANK, (bank_cmd >> 4)&0x0F);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_section]select bank %d fail.",
+			(bank_cmd >> 4)&0x0F);
+		return FAIL;
+	}
+
+	/* step5:burn fw section */
+	ret = gup_burn_proc(client, fw_section, start_addr, len);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_app_section]burn fw_section fail.");
+		return FAIL;
+	}
+
+	/* step6:send burn cmd to move data to flash from sram */
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, bank_cmd&0x0F);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_app_section]send burn cmd fail.");
+		return FAIL;
+	}
+	dev_dbg(&client->dev,
+		"[burn_fw_section]Wait for the burn is complete......");
+	do {
+		ret = gup_get_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, rd_buf, 1);
+		if (ret <= 0) {
+			dev_err(&client->dev,
+				"[burn_fw_app_section]Get burn state fail");
+			return FAIL;
+		}
+		usleep_range(10000, 11000);
+	/* dev_dbg(&client->dev, "[burn_fw_app_section]Get burn state:%d."
+	 * rd_buf[GTP_ADDR_LENGTH]);
+	 */
+	} while (rd_buf[GTP_ADDR_LENGTH]);
+
+	/* step7:recall fw section */
+	ret = gup_recall_check(client, fw_section, start_addr, len);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_app_section]recall check %dk firmware fail.",
+			len/1024);
+		return FAIL;
+	}
+
+	return SUCCESS;
+}
+
+static u8 gup_burn_fw_gwake(struct i2c_client *client)
+{
+	u8 *fw_gwake = NULL;
+	u8	retry = 0;
+	s32 ret = 0;
+	u16 start_index = 4*FW_SECTION_LENGTH +
+	FW_DSP_LENGTH + FW_BOOT_LENGTH +
+	FW_BOOT_ISP_LENGTH + FW_GLINK_LENGTH;/* 32 + 4 + 2 + 4 = 42K */
+	/* u16 start_index; */
+
+	if (start_index >= update_msg.fw_total_len) {
+		dev_dbg(&client->dev, "No need to upgrade the gwake code!");
+		return SUCCESS;
+	}
+	/* start_index = update_msg.fw_burned_len - FW_DSP_ISP_LENGTH; */
+	dev_info(&client->dev,
+		 "[burn_fw_gwake]Begin burn gwake firmware---->>");
+
+	/* step1:alloc memory */
+	dev_dbg(&client->dev, "[burn_fw_gwake]step1:alloc memory");
+	while (retry++ < 5) {
+		fw_gwake =
+	kzalloc(FW_SECTION_LENGTH, GFP_KERNEL);
+		if (fw_gwake == NULL) {
+			continue;
+		} else {
+			dev_dbg(&client->dev,
+				"[burn_fw_gwake]Alloc %dk byte memory success.",
+				(FW_SECTION_LENGTH/1024));
+			break;
+		}
+	}
+	if (retry >= 5) {
+		dev_err(&client->dev, "[burn_fw_gwake]Alloc memory fail,exit.");
+		return FAIL;
+	}
+
+	/* clear control flag */
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_finish]clear control flag fail.");
+		goto exit_burn_fw_gwake;
+	}
+
+	/* step2:load app_code firmware section 1 file data */
+	dev_dbg(&client->dev,
+		"[burn_fw_gwake]step2:load app_code firmware section 1 file data");
+	ret = gup_load_section_file(fw_gwake,
+	start_index, FW_SECTION_LENGTH, SEEK_SET);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_gwake]load app_code firmware section 1 fail.");
+		goto exit_burn_fw_gwake;
+	}
+
+	/* step3:burn app_code firmware section 1 */
+	dev_dbg(&client->dev,
+		"[burn_fw_gwake]step3:burn app_code firmware section 1");
+	ret = gup_burn_fw_gwake_section(client,
+	fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3A);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_gwake]burn app_code firmware section 1 fail.");
+		goto exit_burn_fw_gwake;
+	}
+
+	/* step5:load app_code firmware section 2 file data */
+	dev_dbg(&client->dev,
+		"[burn_fw_gwake]step5:load app_code firmware section 2 file data");
+	ret = gup_load_section_file(
+	fw_gwake, start_index+FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_gwake]load app_code firmware section 2 fail.");
+		goto exit_burn_fw_gwake;
+	}
+
+	/* step6:burn app_code firmware section 2 */
+	dev_dbg(&client->dev,
+		"[burn_fw_gwake]step6:burn app_code firmware section 2");
+	ret = gup_burn_fw_gwake_section(client,
+	fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3B);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_gwake]burn app_code firmware section 2 fail.");
+		goto exit_burn_fw_gwake;
+	}
+
+	/* step7:load app_code firmware section 3 file data */
+	dev_dbg(&client->dev,
+		"[burn_fw_gwake]step7:load app_code firmware section 3 file data");
+	ret = gup_load_section_file(
+	fw_gwake, start_index + 2*FW_SECTION_LENGTH,
+	FW_SECTION_LENGTH, SEEK_SET);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_gwake]load app_code firmware section 3 fail.");
+		goto exit_burn_fw_gwake;
+	}
+
+	/* step8:burn app_code firmware section 3 */
+	dev_dbg(&client->dev,
+		"[burn_fw_gwake]step8:burn app_code firmware section 3");
+	ret = gup_burn_fw_gwake_section(
+	client, fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3C);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_gwake]burn app_code firmware section 3 fail.");
+		goto exit_burn_fw_gwake;
+	}
+
+	/* step9:load app_code firmware section 4 file data */
+	dev_dbg(&client->dev,
+		"[burn_fw_gwake]step9:load app_code firmware section 4 file data");
+	ret = gup_load_section_file(fw_gwake,
+	start_index + 3*FW_SECTION_LENGTH, FW_SECTION_LENGTH, SEEK_SET);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_gwake]load app_code firmware section 4 fail.");
+		goto exit_burn_fw_gwake;
+	}
+
+	/* step10:burn app_code firmware section 4 */
+	dev_dbg(&client->dev,
+		"[burn_fw_gwake]step10:burn app_code firmware section 4");
+	ret = gup_burn_fw_gwake_section(
+	client, fw_gwake, 0x9000, FW_SECTION_LENGTH, 0x3D);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_gwake]burn app_code firmware section 4 fail.");
+		goto exit_burn_fw_gwake;
+	}
+
+	/* update_msg.fw_burned_len += FW_GWAKE_LENGTH; */
+	dev_dbg(&client->dev,
+		"[burn_fw_gwake]Burned length:%d", update_msg.fw_burned_len);
+	ret = SUCCESS;
+
+exit_burn_fw_gwake:
+	kfree(fw_gwake);
+
+	return ret;
+}
+
+static u8 gup_burn_fw_finish(struct i2c_client *client)
+{
+	u8 *fw_ss51 = NULL;
+	u8	retry = 0;
+	s32 ret = 0;
+
+	dev_info(&client->dev,
+		 "[burn_fw_finish]burn first 8K of ss51 and finish update.");
+	/* step1:alloc memory */
+	dev_dbg(&client->dev, "[burn_fw_finish]step1:alloc memory");
+	while (retry++ < 5) {
+		fw_ss51 = kzalloc(FW_SECTION_LENGTH, GFP_KERNEL);
+		if (fw_ss51 == NULL) {
+			continue;
+		} else {
+			dev_dbg(&client->dev,
+				"[burn_fw_finish]Alloc %dk byte memory success.",
+				(FW_SECTION_LENGTH/1024));
+			break;
+		}
+	}
+	if (retry >= 5) {
+		dev_err(&client->dev,
+			"[burn_fw_finish]Alloc memory fail,exit.");
+		return FAIL;
+	}
+
+	dev_dbg(&client->dev, "[burn_fw_finish]step2: burn ss51 first 8K.");
+	ret = gup_load_section_file(fw_ss51, 0, FW_SECTION_LENGTH, SEEK_SET);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_finish]load ss51 firmware section 1 fail.");
+		goto exit_burn_fw_finish;
+	}
+
+	dev_dbg(&client->dev, "[burn_fw_finish]step3:clear control flag");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x00);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_finish]clear control flag fail.");
+		goto exit_burn_fw_finish;
+	}
+
+	dev_dbg(&client->dev,
+		"[burn_fw_finish]step4:burn ss51 firmware section 1");
+	ret = gup_burn_fw_section(client, fw_ss51, 0xC000, 0x01);
+	if (ret == FAIL) {
+		dev_err(&client->dev,
+			"[burn_fw_finish]burn ss51 firmware section 1 fail.");
+		goto exit_burn_fw_finish;
+	}
+
+	/* step11:enable download DSP code */
+	dev_dbg(&client->dev,
+		"[burn_fw_finish]step5:enable download DSP code ");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__BOOT_CTL_, 0x99);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_finish]enable download DSP code fail.");
+		goto exit_burn_fw_finish;
+	}
+
+	/* step12:release ss51 & hold dsp */
+	dev_dbg(&client->dev, "[burn_fw_finish]step6:release ss51 & hold dsp");
+	ret = gup_set_ic_msg(client, _rRW_MISCTL__SWRST_B0_, 0x08);
+	if (ret <= 0) {
+		dev_err(&client->dev,
+			"[burn_fw_finish]release ss51 & hold dsp fail.");
+		goto exit_burn_fw_finish;
+	}
+
+	if (fw_ss51 != NULL)
+		kfree(fw_ss51);
+	return SUCCESS;
+
+exit_burn_fw_finish:
+	if (fw_ss51 != NULL)
+		kfree(fw_ss51);
+
+	return FAIL;
+}
+
+/* return 0 can update, else no update condition */
+static int gup_update_condition_check(struct goodix_ts_data *ts)
+{
+	if (test_bit(SLEEP_MODE, &ts->flags)) {
+		dev_info(&ts->client->dev, "Update abort, tp in sleep mode\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+s32 gup_update_proc(void *dir)
+{
+	s32 ret = 0;
+	s32 update_ret = FAIL;
+	u8	retry = 0;
+	struct st_fw_head fw_head;
+	struct goodix_ts_data *ts = NULL;
+
+	ts = i2c_get_clientdata(i2c_connect_client);
+
+	dev_dbg(&ts->client->dev, "[update_proc]Begin update ......\n");
+
+	show_len = 1;
+	total_len = 100;
+
+	ret = gup_update_condition_check(ts);
+	if (ret) {
+		dev_warn(&ts->client->dev, "Update start failed\n");
+		return FAIL;
+	}
+
+	if (test_and_set_bit(FW_UPDATE_RUNNING, &ts->flags)) {
+		dev_warn(&ts->client->dev, "FW update may already running\n");
+		return FAIL;
+	}
+
+	ret = gup_get_update_file(i2c_connect_client, &fw_head, (u8 *)dir);
+	if (ret == FAIL) {
+		dev_err(&ts->client->dev,
+			"Failed get valied firmware data\n");
+		clear_bit(FW_UPDATE_RUNNING, &ts->flags);
+		return FAIL;
+	}
+
+	gtp_work_control_enable(ts, false);
+	gtp_esd_off(ts);
+
+	ret = gup_get_ic_fw_msg(i2c_connect_client);
+	if (ret == FAIL) {
+		dev_err(&ts->client->dev, "[update_proc]get ic message fail.");
+		goto file_fail;
+	}
+
+	if (ts->force_update || dir) {
+		dev_dbg(&ts->client->dev, "Enter force update.");
+	} else {
+		ret = gup_enter_update_judge(i2c_connect_client, &fw_head);
+		if (ret == FAIL) {
+			dev_err(&ts->client->dev,
+				"[update_proc]Doesn't meet update condition\n");
+			goto file_fail;
+		}
+	}
+
+	ret = gup_enter_update_mode(ts->client);
+	if (ret == FAIL) {
+		dev_err(&ts->client->dev,
+			"[update_proc]enter update mode fail.");
+		goto update_fail;
+	}
+
+	while (retry++ < 5) {
+		show_len = 10;
+		total_len = 100;
+		update_msg.fw_burned_len = 0;
+		ret = gup_burn_dsp_isp(i2c_connect_client);
+		if (ret == FAIL) {
+			dev_err(&ts->client->dev,
+				"[update_proc]burn dsp isp fail.");
+			continue;
+		}
+
+		show_len = 20;
+		ret = gup_burn_fw_gwake(i2c_connect_client);
+		if (ret == FAIL) {
+			dev_err(&ts->client->dev,
+				"[update_proc]burn app_code firmware fail.");
+			continue;
+		}
+
+		show_len = 30;
+		ret = gup_burn_fw_ss51(i2c_connect_client);
+		if (ret == FAIL) {
+			dev_err(&ts->client->dev,
+				"[update_proc]burn ss51 firmware fail.");
+			continue;
+		}
+
+		show_len = 40;
+		ret = gup_burn_fw_dsp(i2c_connect_client);
+		if (ret == FAIL) {
+			dev_err(&ts->client->dev,
+				"[update_proc]burn dsp firmware fail.");
+			continue;
+		}
+
+		show_len = 50;
+		ret = gup_burn_fw_boot(i2c_connect_client);
+		if (ret == FAIL) {
+			dev_err(&ts->client->dev,
+				"[update_proc]burn bootloader firmware fail.");
+			continue;
+		}
+		show_len = 60;
+
+		ret = gup_burn_fw_boot_isp(i2c_connect_client);
+		if (ret == FAIL) {
+			dev_err(&ts->client->dev,
+				"[update_proc]burn boot_isp firmware fail.");
+			continue;
+		}
+
+		show_len = 70;
+		ret = gup_burn_fw_link(i2c_connect_client);
+		if (ret == FAIL) {
+			dev_err(&ts->client->dev,
+				"[update_proc]burn link firmware fail.");
+			continue;
+		}
+
+		show_len = 80;
+		ret = gup_burn_fw_finish(i2c_connect_client);
+		if (ret == FAIL) {
+			dev_err(&ts->client->dev,
+				"[update_proc]burn finish fail.");
+			continue;
+		}
+		show_len = 90;
+		dev_info(&ts->client->dev, "[update_proc]UPDATE SUCCESS.");
+		retry = 0;
+		break;
+	}
+
+	if (retry >= 5) {
+		dev_err(&ts->client->dev,
+			"[update_proc]retry timeout,UPDATE FAIL.");
+		update_ret = FAIL;
+	} else {
+		update_ret = SUCCESS;
+	}
+
+update_fail:
+	dev_dbg(&ts->client->dev, "[update_proc]leave update mode.");
+	gup_leave_update_mode(i2c_connect_client);
+
+	msleep(GTP_100_DLY_MS);
+
+	if (update_ret == SUCCESS) {
+		dev_info(&ts->client->dev,
+			"firmware error auto update, resent config!\n");
+		gup_init_panel(ts);
+	}
+	gtp_get_fw_info(ts->client, &ts->fw_info);
+
+file_fail:
+
+	update_msg.fw_data = NULL;
+	update_msg.fw_total_len = 0;
+	release_firmware(update_msg.fw);
+
+	clear_bit(FW_UPDATE_RUNNING, &ts->flags);
+	gtp_work_control_enable(ts, true);
+	gtp_esd_on(ts);
+	total_len = 100;
+	ts->force_update = false;
+	if (update_ret == SUCCESS) {
+		show_len = 100;
+		clear_bit(FW_ERROR, &ts->flags);
+		return SUCCESS;
+	}
+
+	show_len = 200;
+	return FAIL;
+}
+
+u8 gup_init_update_proc(struct goodix_ts_data *ts)
+{
+	struct task_struct *thread = NULL;
+
+	dev_info(&ts->client->dev, "Ready to run update thread.");
+
+	thread = kthread_run(gup_update_proc,
+			(void *)NULL, "guitar_update");
+
+	if (IS_ERR(thread)) {
+		dev_err(&ts->client->dev,
+				"Failed to create update thread.\n");
+		return -EPERM;
+	}
+
+	return 0;
+}
diff --git a/drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i b/drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i
deleted file mode 100644
index e69de29..0000000
--- a/drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i
+++ /dev/null
diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_124.i b/drivers/input/touchscreen/hxchipset/HX_CRC_124.i
deleted file mode 100644
index e69de29..0000000
--- a/drivers/input/touchscreen/hxchipset/HX_CRC_124.i
+++ /dev/null
diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_128.i b/drivers/input/touchscreen/hxchipset/HX_CRC_128.i
deleted file mode 100644
index e69de29..0000000
--- a/drivers/input/touchscreen/hxchipset/HX_CRC_128.i
+++ /dev/null
diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_60.i b/drivers/input/touchscreen/hxchipset/HX_CRC_60.i
deleted file mode 100644
index e69de29..0000000
--- a/drivers/input/touchscreen/hxchipset/HX_CRC_60.i
+++ /dev/null
diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_64.i b/drivers/input/touchscreen/hxchipset/HX_CRC_64.i
deleted file mode 100644
index e69de29..0000000
--- a/drivers/input/touchscreen/hxchipset/HX_CRC_64.i
+++ /dev/null
diff --git a/drivers/input/touchscreen/hxchipset/Kconfig b/drivers/input/touchscreen/hxchipset/Kconfig
index ebf3aa4..3dc5a02 100644
--- a/drivers/input/touchscreen/hxchipset/Kconfig
+++ b/drivers/input/touchscreen/hxchipset/Kconfig
@@ -3,19 +3,44 @@
 #
 
 config TOUCHSCREEN_HIMAX_I2C
-        tristate "HIMAX chipset i2c touchscreen"
-		depends on TOUCHSCREEN_HIMAX_CHIPSET
-		help
+	tristate "HIMAX chipset i2c touchscreen"
+	depends on TOUCHSCREEN_HIMAX_CHIPSET
+	help
+		Say Y here to enable support for HIMAX CHIPSET over I2C based touchscreens.
+		If unsure, say N.
+
+		To compile this driver as a module,
 		This enables support for HIMAX CHIPSET over I2C based touchscreens.
 
 config TOUCHSCREEN_HIMAX_DEBUG
-        tristate "HIMAX debug function"
-		depends on TOUCHSCREEN_HIMAX_I2C
-		help
+	tristate "HIMAX debug function"
+	depends on TOUCHSCREEN_HIMAX_I2C
+	help
+		Say Y here to enable support for HIMAX debug function.
+
+		If unsure, say N.
+
+		To compile this driver as a module,
 		This enables support for HIMAX debug function.
 
+config TOUCHSCREEN_HIMAX_ITO_TEST
+	tristate "HIMAX driver test over Dragon Board"
+	depends on TOUCHSCREEN_HIMAX_I2C
+	help
+		Say Y here to enable support for HIMAX driver test over Dragon Board.
+
+		If unsure, say N.
+
+		To compile this driver as a module,
+		this enables support for HIMAX driver test over Dragon Board.
+
 config HMX_DB
 	tristate "HIMAX driver test over Dragon Board"
 	depends on TOUCHSCREEN_HIMAX_I2C
 	help
-	  This enables support for HIMAX driver test over Dragon Board.
+		Say Y here to enable support for HIMAX driver test over Dragon Board.
+
+		If unsure, say N.
+
+		To compile this driver as a module,
+		this enables support for HIMAX driver test over Dragon Board.
diff --git a/drivers/input/touchscreen/hxchipset/Makefile b/drivers/input/touchscreen/hxchipset/Makefile
index 509d491..522907a 100644
--- a/drivers/input/touchscreen/hxchipset/Makefile
+++ b/drivers/input/touchscreen/hxchipset/Makefile
@@ -1,3 +1,4 @@
 # Makefile for the Himax touchscreen drivers.
 
 obj-$(CONFIG_TOUCHSCREEN_HIMAX_I2C)   	+= himax_platform.o himax_ic.o himax_common.o himax_debug.o
+obj-$(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST)   	+= 	himax_ito_test.o
\ No newline at end of file
diff --git a/drivers/input/touchscreen/hxchipset/himax_common.c b/drivers/input/touchscreen/hxchipset/himax_common.c
index 417b0c0..d4bc5be 100644
--- a/drivers/input/touchscreen/hxchipset/himax_common.c
+++ b/drivers/input/touchscreen/hxchipset/himax_common.c
@@ -1,4 +1,4 @@
-/* Himax Android Driver Sample Code for Himax chipset
+	/* Himax Android Driver Sample Code for Himax chipset
 *
 * Copyright (C) 2015 Himax Corporation.
 *
@@ -21,107 +21,32 @@
 #define FRAME_COUNT 5
 
 #if defined(HX_AUTO_UPDATE_FW)
-	static unsigned char i_CTPM_FW[]=
-	{
-		#include "HX83100_Amber_0901_030B.i"
-	};
+	char *i_CTPM_firmware_name = "HX83100_Amber_0B01_030E.bin";
+	const struct firmware *i_CTPM_FW = NULL;
 #endif
 
-#ifdef HX_ESD_WORKAROUND
-	extern void HX_report_ESD_event(void);
-	unsigned char ESD_00_counter = 0;
-	unsigned char ESD_00_Flag = 0;
-#endif
-
-//static int		tpd_keys_local[HX_KEY_MAX_COUNT] = HX_KEY_ARRAY; // for Virtual key array
+/*static int tpd_keys_local[HX_KEY_MAX_COUNT] = HX_KEY_ARRAY;
+// for Virtual key array */
 
 struct himax_ts_data *private_ts;
-struct himax_ic_data* ic_data;
+struct himax_ic_data *ic_data;
 
-static int		HX_TOUCH_INFO_POINT_CNT;
+static int HX_TOUCH_INFO_POINT_CNT;
 
-#ifdef HX_AUTO_UPDATE_FW
-extern unsigned long	FW_VER_MAJ_FLASH_ADDR;
-extern unsigned long 	FW_VER_MIN_FLASH_ADDR;
-extern unsigned long 	CFG_VER_MAJ_FLASH_ADDR;
-extern unsigned long 	CFG_VER_MIN_FLASH_ADDR;
-#endif
-extern unsigned long 	FW_VER_MAJ_FLASH_LENG;
-extern unsigned long 	FW_VER_MIN_FLASH_LENG;
-extern unsigned long 	CFG_VER_MAJ_FLASH_LENG;
-extern unsigned long 	CFG_VER_MIN_FLASH_LENG;
-extern unsigned char	IC_TYPE;
-extern unsigned char	IC_CHECKSUM;
-
-#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
-extern int himax_touch_proc_init(void);
-extern void himax_touch_proc_deinit(void);
-//PROC-START
-#ifdef HX_TP_PROC_FLASH_DUMP
-extern void	himax_ts_flash_func(void);
-extern void setFlashBuffer(void);
-extern bool getFlashDumpGoing(void);
-extern uint8_t getSysOperation(void);
-extern void setSysOperation(uint8_t operation);
-#endif
-
-#ifdef HX_TP_PROC_HITOUCH
-extern bool hitouch_is_connect;
-#endif
-
-#ifdef HX_TP_PROC_DIAG
-	extern int touch_monitor_stop_flag;
-	extern int touch_monitor_stop_limit;
-	extern void	himax_ts_diag_func(void);
-	extern int16_t *getMutualBuffer(void);
-	extern int16_t *getMutualNewBuffer(void);
-	extern int16_t *getMutualOldBuffer(void);
-	extern int16_t *getSelfBuffer(void);
-	extern uint8_t getXChannel(void);
-	extern uint8_t getYChannel(void);
-	extern uint8_t getDiagCommand(void);
-	extern void setXChannel(uint8_t x);
-	extern void setYChannel(uint8_t y);
-	extern void setMutualBuffer(void);
-	extern void setMutualNewBuffer(void);
-	extern void setMutualOldBuffer(void);
-	extern uint8_t	coordinate_dump_enable;
-	extern struct file	*coordinate_fn;
-	extern uint8_t diag_coor[128];
-#ifdef HX_TP_PROC_2T2R
-	extern int16_t *getMutualBuffer_2(void);
-	extern uint8_t getXChannel_2(void);
-	extern uint8_t getYChannel_2(void);
-	extern void setXChannel_2(uint8_t x);
-	extern void setYChannel_2(uint8_t y);
-	extern void setMutualBuffer_2(void);
-#endif
-#endif
-//PROC-END
-#endif
-
-extern int himax_parse_dt(struct himax_ts_data *ts,
-				struct himax_i2c_platform_data *pdata);
-extern int himax_ts_pinctrl_init(struct himax_ts_data *ts);
-
-static uint8_t 	vk_press;
-static uint8_t 	AA_press;
-static uint8_t 	EN_NoiseFilter;
-static uint8_t	Last_EN_NoiseFilter;
-static int	hx_point_num;																	// for himax_ts_work_func use
-static int	p_point_num	= 0xFFFF;
-static int	tpd_key;
-static int	tpd_key_old;
-static int	probe_fail_flag;
-static bool	config_load;
+static uint8_t vk_press = 0x00;
+static uint8_t AA_press = 0x00;
+static uint8_t EN_NoiseFilter = 0x00;
+static int hx_point_num; /*for himax_ts_work_func use*/
+static int p_point_num = 0xFFFF;
+static int tpd_key = 0x00;
+static int tpd_key_old = 0x00;
+static int probe_fail_flag;
+static bool config_load;
 static struct himax_config *config_selected;
 
-//static int iref_number = 11;
-//static bool iref_found = false;    
+/*static int iref_number = 11;*/
+/*static bool iref_found = false;*/
 
-#ifdef HX_USB_DETECT2
-extern bool USB_Flag;
-#endif
 
 #if defined(CONFIG_FB)
 int fb_notifier_callback(struct notifier_block *self,
@@ -134,6 +59,7 @@
 int himax_input_register(struct himax_ts_data *ts)
 {
 	int ret;
+
 	ts->input_dev = input_allocate_device();
 	if (ts->input_dev == NULL) {
 		ret = -ENOMEM;
@@ -175,25 +101,36 @@
 	set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit);
 
 	if (ts->protocol_type == PROTOCOL_TYPE_A) {
-		//ts->input_dev->mtsize = ts->nFinger_support;
+		/*ts->input_dev->mtsize = ts->nFinger_support;*/
 		input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID,
 		0, 3, 0, 0);
 	} else {/* PROTOCOL_TYPE_B */
 		set_bit(MT_TOOL_FINGER, ts->input_dev->keybit);
-		input_mt_init_slots(ts->input_dev, ts->nFinger_support,0);
+		input_mt_init_slots(ts->input_dev, ts->nFinger_support, 0);
 	}
 
 	I("input_set_abs_params: mix_x %d, max_x %d, min_y %d, max_y %d\n",
-		ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max);
+		ts->pdata->abs_x_min, ts->pdata->abs_x_max,
+		ts->pdata->abs_y_min, ts->pdata->abs_y_max);
 
-	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_x_fuzz, 0);
-	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,ts->pdata->abs_y_min, ts->pdata->abs_y_max, ts->pdata->abs_y_fuzz, 0);
-	input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR,ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0);
-	input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE,ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0);
-	input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR,ts->pdata->abs_width_min, ts->pdata->abs_width_max, ts->pdata->abs_pressure_fuzz, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
+	ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_x_fuzz, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,
+	ts->pdata->abs_y_min, ts->pdata->abs_y_max, ts->pdata->abs_y_fuzz, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR,
+	ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max,
+	ts->pdata->abs_pressure_fuzz, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE,
+	ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max,
+	ts->pdata->abs_pressure_fuzz, 0);
+	input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR,
+	ts->pdata->abs_width_min, ts->pdata->abs_width_max,
+	ts->pdata->abs_pressure_fuzz, 0);
 
-//	input_set_abs_params(ts->input_dev, ABS_MT_AMPLITUDE, 0, ((ts->pdata->abs_pressure_max << 16) | ts->pdata->abs_width_max), 0, 0);
-//	input_set_abs_params(ts->input_dev, ABS_MT_POSITION, 0, (BIT(31) | (ts->pdata->abs_x_max << 16) | ts->pdata->abs_y_max), 0, 0);
+/*input_set_abs_params(ts->input_dev, ABS_MT_AMPLITUDE, 0,
+((ts->pdata->abs_pressure_max << 16) | ts->pdata->abs_width_max), 0, 0);*/
+/*input_set_abs_params(ts->input_dev, ABS_MT_POSITION, 0,
+(BIT(31) | (ts->pdata->abs_x_max << 16) | ts->pdata->abs_y_max), 0, 0);*/
 
 	return input_register_device(ts->input_dev);
 }
@@ -201,87 +138,103 @@
 static void calcDataSize(uint8_t finger_num)
 {
 	struct himax_ts_data *ts_data = private_ts;
+
 	ts_data->coord_data_size = 4 * finger_num;
-	ts_data->area_data_size = ((finger_num / 4) + (finger_num % 4 ? 1 : 0)) * 4;
-	ts_data->raw_data_frame_size = 128 - ts_data->coord_data_size - ts_data->area_data_size - 4 - 4 - 1;
-	ts_data->raw_data_nframes  = ((uint32_t)ts_data->x_channel * ts_data->y_channel +
-																					ts_data->x_channel + ts_data->y_channel) / ts_data->raw_data_frame_size +
-															(((uint32_t)ts_data->x_channel * ts_data->y_channel +
-		  																		ts_data->x_channel + ts_data->y_channel) % ts_data->raw_data_frame_size)? 1 : 0;
-	I("%s: coord_data_size: %d, area_data_size:%d, raw_data_frame_size:%d, raw_data_nframes:%d", __func__, ts_data->coord_data_size, ts_data->area_data_size, ts_data->raw_data_frame_size, ts_data->raw_data_nframes);
+	ts_data->area_data_size = ((finger_num / 4) +
+	(finger_num % 4 ? 1 : 0)) * 4;
+	ts_data->raw_data_frame_size = 128 -
+	ts_data->coord_data_size -
+	ts_data->area_data_size - 4 - 4 - 1;
+
+	ts_data->raw_data_nframes =
+	((uint32_t)ts_data->x_channel *
+	ts_data->y_channel + ts_data->x_channel + ts_data->y_channel) /
+	ts_data->raw_data_frame_size + (((uint32_t)ts_data->x_channel *
+	ts_data->y_channel + ts_data->x_channel + ts_data->y_channel) %
+	ts_data->raw_data_frame_size) ? 1 : 0;
+
+	I("%s: coord_data_size: %d, area_data_size:%d",
+	__func__, ts_data->coord_data_size, ts_data->area_data_size);
+	I("raw_data_frame_size:%d, raw_data_nframes:%d",
+	ts_data->raw_data_frame_size, ts_data->raw_data_nframes);
 }
 
 static void calculate_point_number(void)
 {
-	HX_TOUCH_INFO_POINT_CNT = ic_data->HX_MAX_PT * 4 ;
+	HX_TOUCH_INFO_POINT_CNT = ic_data->HX_MAX_PT * 4;
 
-	if ( (ic_data->HX_MAX_PT % 4) == 0)
-		HX_TOUCH_INFO_POINT_CNT += (ic_data->HX_MAX_PT / 4) * 4 ;
+	if ((ic_data->HX_MAX_PT % 4) == 0)
+		HX_TOUCH_INFO_POINT_CNT += (ic_data->HX_MAX_PT / 4) * 4;
 	else
-		HX_TOUCH_INFO_POINT_CNT += ((ic_data->HX_MAX_PT / 4) +1) * 4 ;
+		HX_TOUCH_INFO_POINT_CNT += ((ic_data->HX_MAX_PT / 4) + 1) * 4;
 }
 
-#if 0
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
 static int himax_read_Sensor_ID(struct i2c_client *client)
-{	
-	uint8_t val_high[1], val_low[1], ID0=0, ID1=0;
+{
+	uint8_t val_high[1], val_low[1], ID0 = 0, ID1 = 0;
 	char data[3];
 	const int normalRetry = 10;
 	int sensor_id;
-	
-	data[0] = 0x56; data[1] = 0x02; data[2] = 0x02;/*ID pin PULL High*/
-	i2c_himax_master_write(client, &data[0],3,normalRetry);
-	usleep_range(1000, 2000);
 
-	//read id pin high
+	data[0] = 0x56; data[1] = 0x02;
+	data[2] = 0x02;/*ID pin PULL High*/
+	i2c_himax_master_write(client, &data[0], 3, normalRetry);
+	usleep(1000);
+
+	/*read id pin high*/
 	i2c_himax_read(client, 0x57, val_high, 1, normalRetry);
 
-	data[0] = 0x56; data[1] = 0x01; data[2] = 0x01;/*ID pin PULL Low*/
-	i2c_himax_master_write(client, &data[0],3,normalRetry);
-	usleep_range(1000, 2000);
+	data[0] = 0x56; data[1] = 0x01;
+	data[2] = 0x01;/*ID pin PULL Low*/
+	i2c_himax_master_write(client, &data[0], 3, normalRetry);
+	usleep(1000);
 
-	//read id pin low
+	/*read id pin low*/
 	i2c_himax_read(client, 0x57, val_low, 1, normalRetry);
 
-	if((val_high[0] & 0x01) ==0)
-		ID0=0x02;/*GND*/
-	else if((val_low[0] & 0x01) ==0)
-		ID0=0x01;/*Floating*/
+	if ((val_high[0] & 0x01) == 0)
+		ID0 = 0x02;/*GND*/
+	else if ((val_low[0] & 0x01) == 0)
+		ID0 = 0x01;/*Floating*/
 	else
-		ID0=0x04;/*VCC*/
-	
-	if((val_high[0] & 0x02) ==0)
-		ID1=0x02;/*GND*/
-	else if((val_low[0] & 0x02) ==0)
-		ID1=0x01;/*Floating*/
+		ID0 = 0x04;/*VCC*/
+
+	if ((val_high[0] & 0x02) == 0)
+		ID1 = 0x02;/*GND*/
+	else if ((val_low[0] & 0x02) == 0)
+		ID1 = 0x01;/*Floating*/
 	else
-		ID1=0x04;/*VCC*/
-	if((ID0==0x04)&&(ID1!=0x04))
-		{
-			data[0] = 0x56; data[1] = 0x02; data[2] = 0x01;/*ID pin PULL High,Low*/
-			i2c_himax_master_write(client, &data[0],3,normalRetry);
-			usleep_range(1000, 2000);
+		ID1 = 0x04;/*VCC*/
+	if ((ID0 == 0x04) && (ID1 != 0x04)) {
+			data[0] = 0x56; data[1] = 0x02;
+			data[2] = 0x01;/*ID pin PULL High,Low*/
+			i2c_himax_master_write(client,
+			&data[0], 3, normalRetry);
+			usleep(1000);
 
-		}
-	else if((ID0!=0x04)&&(ID1==0x04))
-		{
-			data[0] = 0x56; data[1] = 0x01; data[2] = 0x02;/*ID pin PULL Low,High*/
-			i2c_himax_master_write(client, &data[0],3,normalRetry);
-			usleep_range(1000, 2000);
+	} else if ((ID0 != 0x04) && (ID1 == 0x04)) {
+			data[0] = 0x56; data[1] = 0x01;
+			data[2] = 0x02;/*ID pin PULL Low,High*/
+			i2c_himax_master_write(client,
+			&data[0], 3, normalRetry);
+			usleep(1000);
 
-		}
-	else if((ID0==0x04)&&(ID1==0x04))
-		{
-			data[0] = 0x56; data[1] = 0x02; data[2] = 0x02;/*ID pin PULL High,High*/
-			i2c_himax_master_write(client, &data[0],3,normalRetry);
-			usleep_range(1000, 2000);
+	} else if ((ID0 == 0x04) && (ID1 == 0x04)) {
+			data[0] = 0x56; data[1] = 0x02;
+			data[2] = 0x02;/*ID pin PULL High,High*/
+			i2c_himax_master_write(client,
+			&data[0], 3, normalRetry);
+			usleep(1000);
 
-		}
-	sensor_id=(ID1<<4)|ID0;
+	}
+	sensor_id = (ID1<<4)|ID0;
 
 	data[0] = 0xE4; data[1] = sensor_id;
-	i2c_himax_master_write(client, &data[0],2,normalRetry);/*Write to MCU*/
-	usleep_range(1000, 2000);
+	i2c_himax_master_write(client,
+	&data[0], 2, normalRetry);/*Write to MCU*/
+	usleep(1000);
 
 	return sensor_id;
 
@@ -290,125 +243,173 @@
 static void himax_power_on_initCMD(struct i2c_client *client)
 {
 	I("%s:\n", __func__);
-
 	himax_touch_information(client);
-
-    //himax_sense_on(private_ts->client, 0x01);//1=Flash, 0=SRAM
+    /*himax_sense_on(private_ts->client, 0x01);//1=Flash, 0=SRAM */
 }
 
 #ifdef HX_AUTO_UPDATE_FW
 static int i_update_FW(void)
 {
 	int upgrade_times = 0;
-	unsigned char* ImageBuffer = i_CTPM_FW;
-	int fullFileLength = sizeof(i_CTPM_FW);
+	int fullFileLength = 0;
 	int i_FW_VER = 0, i_CFG_VER = 0;
-	uint8_t ret = -1, result = 0;
-//	uint8_t tmp_addr[4];
-//	uint8_t tmp_data[4];
+	int ret = -1, result = 0;
+	/*uint8_t tmp_addr[4];*/
+	/*uint8_t tmp_data[4];*/
 	int CRC_from_FW = 0;
 	int CRC_Check_result = 0;
 
-	i_FW_VER = i_CTPM_FW[FW_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW[FW_VER_MIN_FLASH_ADDR];
-	i_CFG_VER = i_CTPM_FW[CFG_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW[CFG_VER_MIN_FLASH_ADDR];
+	ret = himax_load_CRC_bin_file(private_ts->client);
+	if (ret < 0) {
+		E("%s: himax_load_CRC_bin_file fail Error Code=%d.\n",
+		__func__, ret);
+		ret = -1;
+		return ret;
+	}
+	I("file name = %s\n", i_CTPM_firmware_name);
+	ret = request_firmware(&i_CTPM_FW,
+	i_CTPM_firmware_name, private_ts->dev);
+	if (ret < 0) {
+		E("%s,fail in line%d error code=%d\n",
+		__func__, __LINE__, ret);
+		ret = -2;
+		return ret;
+	}
 
-	I("%s: i_fullFileLength = %d\n", __func__,fullFileLength);
+	if (i_CTPM_FW == NULL) {
+		I("%s: i_CTPM_FW = NULL\n", __func__);
+		ret = -3;
+		return ret;
+	}
+	fullFileLength = i_CTPM_FW->size;
+
+	i_FW_VER = i_CTPM_FW->data[FW_VER_MAJ_FLASH_ADDR]<<8
+	| i_CTPM_FW->data[FW_VER_MIN_FLASH_ADDR];
+	i_CFG_VER = i_CTPM_FW->data[CFG_VER_MAJ_FLASH_ADDR]<<8
+	| i_CTPM_FW->data[CFG_VER_MIN_FLASH_ADDR];
+
+	I("%s: i_fullFileLength = %d\n", __func__, fullFileLength);
 
 	himax_sense_off(private_ts->client);
 	msleep(500);
 
-	CRC_from_FW = himax_check_CRC(private_ts->client,fw_image_64k);
-	CRC_Check_result = Calculate_CRC_with_AP(ImageBuffer, CRC_from_FW,fw_image_64k);
-	I("%s: Check sum result = %d\n", __func__,CRC_Check_result);
-	//I("%s: ic_data->vendor_fw_ver = %X, i_FW_VER = %X,\n", __func__,ic_data->vendor_fw_ver, i_FW_VER);
-	//I("%s: ic_data->vendor_config_ver = %X, i_CFG_VER = %X,\n", __func__,ic_data->vendor_config_ver, i_CFG_VER);
-	
-	if ((CRC_Check_result == 0)|| ( ic_data->vendor_fw_ver < i_FW_VER ) || ( ic_data->vendor_config_ver < i_CFG_VER ))
-		{
-			himax_int_enable(private_ts->client->irq,0);
+	CRC_from_FW = himax_check_CRC(private_ts->client, fw_image_64k);
+	CRC_Check_result =
+	Calculate_CRC_with_AP((unsigned char *)i_CTPM_FW->data,
+	CRC_from_FW, fw_image_64k);
+	I("%s: Check sum result = %d\n", __func__, CRC_Check_result);
+	/*I("%s: ic_data->vendor_fw_ver = %X, i_FW_VER = %X,\n",
+	__func__, ic_data->vendor_fw_ver, i_FW_VER);*/
+	/*I("%s: ic_data->vendor_config_ver = %X, i_CFG_VER = %X,\n",
+	__func__, ic_data->vendor_config_ver, i_CFG_VER);*/
+
+	if ((CRC_Check_result == 0) ||
+	(ic_data->vendor_fw_ver < i_FW_VER) ||
+	(ic_data->vendor_config_ver < i_CFG_VER)) {
+		himax_int_enable(private_ts->client->irq, 0);
 update_retry:
-			if(fullFileLength == FW_SIZE_60k){
-				ret = fts_ctpm_fw_upgrade_with_sys_fs_60k(private_ts->client,ImageBuffer,fullFileLength,false);
-			}else if (fullFileLength == FW_SIZE_64k){
-				ret = fts_ctpm_fw_upgrade_with_sys_fs_64k(private_ts->client,ImageBuffer,fullFileLength,false);
-			}else if (fullFileLength == FW_SIZE_124k){
-				ret = fts_ctpm_fw_upgrade_with_sys_fs_124k(private_ts->client,ImageBuffer,fullFileLength,false);
-			}else if (fullFileLength == FW_SIZE_128k){
-				ret = fts_ctpm_fw_upgrade_with_sys_fs_128k(private_ts->client,ImageBuffer,fullFileLength,false);
-			}
-			if(ret == 0){
-				upgrade_times++;
-				E("%s: TP upgrade error, upgrade_times = %d\n", __func__, upgrade_times);
-				if(upgrade_times < 3)
-					goto update_retry;
-				else
-				{
-					himax_sense_on(private_ts->client, 0x01);
-					msleep(120);
-#ifdef HX_ESD_WORKAROUND
-					HX_ESD_RESET_ACTIVATE = 1;
-#endif
-					result = -1;//upgrade fail
-				}
-			}
-			else if(ret == 1){
-/*
-				// 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver)
-				tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-				tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
-				himax_register_write(private_ts->client, tmp_addr, 1, tmp_data);
-
-				// 2. Write driver initial code condition
-				//	  write value from AHB I2C : 0x8001_C603 = 0x000000FF
-				tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xC6; tmp_addr[0] = 0x03;
-				tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xFF;
-				himax_register_write(private_ts->client, tmp_addr, 1, tmp_data);
-
-				// 1. Set DDREG_Req = 0 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver)
-				tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-				tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-				himax_register_write(private_ts->client, tmp_addr, 1, tmp_data);
-*/
+		if (fullFileLength == FW_SIZE_60k) {
+			ret = fts_ctpm_fw_upgrade_with_sys_fs_60k
+			(private_ts->client,
+			(unsigned char *)i_CTPM_FW->data,
+			fullFileLength, false);
+		} else if (fullFileLength == FW_SIZE_64k) {
+			ret = fts_ctpm_fw_upgrade_with_sys_fs_64k
+			(private_ts->client,
+			(unsigned char *)i_CTPM_FW->data,
+			fullFileLength, false);
+		} else if (fullFileLength == FW_SIZE_124k) {
+			ret = fts_ctpm_fw_upgrade_with_sys_fs_124k
+			(private_ts->client,
+			(unsigned char *)i_CTPM_FW->data,
+			fullFileLength, false);
+		} else if (fullFileLength == FW_SIZE_128k) {
+			ret = fts_ctpm_fw_upgrade_with_sys_fs_128k
+			(private_ts->client,
+			(unsigned char *)i_CTPM_FW->data,
+			fullFileLength, false);
+		}
+		if (ret == 0) {
+			upgrade_times++;
+			E("%s: TP upgrade error, upgrade_times = %d\n",
+			__func__, upgrade_times);
+			if (upgrade_times < 3)
+				goto update_retry;
+			else {
 				himax_sense_on(private_ts->client, 0x01);
 				msleep(120);
 #ifdef HX_ESD_WORKAROUND
 				HX_ESD_RESET_ACTIVATE = 1;
 #endif
-
-				ic_data->vendor_fw_ver = i_FW_VER;
-				ic_data->vendor_config_ver = i_CFG_VER;
-				result = 1;//upgrade success
-				I("%s: TP upgrade OK\n", __func__);
+				result = -1;/*upgrade fail*/
 			}
+		} else if (ret == 1) {
+			/*
+			// 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001)
+					(Lock register R/W from driver)
+					tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+					tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+					tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+					tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+					himax_register_write(private_ts->client,
+					tmp_addr, 1, tmp_data);
 
-				himax_int_enable(private_ts->client->irq,1);
-			return result;
-		}
-	else
-		{
+			// 2. Write driver initial code condition
+			//write value from AHB I2C:0x8001_C603 = 0x000000FF
+					tmp_addr[3] = 0x80; tmp_addr[2] = 0x01;
+					tmp_addr[1] = 0xC6; tmp_addr[0] = 0x03;
+					tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+					tmp_data[1] = 0x00; tmp_data[0] = 0xFF;
+					himax_register_write(private_ts->client,
+					tmp_addr, 1, tmp_data);
+
+			// 1. Set DDREG_Req = 0(0x9000_0020 = 0x0000_0001)
+					(Lock register R/W from driver)
+					tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+					tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+					tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+					tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+					himax_register_write(private_ts->client,
+					tmp_addr, 1, tmp_data);
+			*/
 			himax_sense_on(private_ts->client, 0x01);
-			return 0;//NO upgrade
+			msleep(120);
+#ifdef HX_ESD_WORKAROUND
+			HX_ESD_RESET_ACTIVATE = 1;
+#endif
+
+			ic_data->vendor_fw_ver = i_FW_VER;
+			ic_data->vendor_config_ver = i_CFG_VER;
+			result = 1;/*upgrade success*/
+			I("%s: TP upgrade OK\n", __func__);
 		}
+
+		himax_int_enable(private_ts->client->irq, 1);
+		return result;
+
+	} else {
+		himax_sense_on(private_ts->client, 0x01);
+		return 0;/*NO upgrade*/
+	}
 }
-#endif 
+#endif
 
 #ifdef HX_RST_PIN_FUNC
-void himax_HW_reset(uint8_t loadconfig,uint8_t int_off)
+void himax_HW_reset(uint8_t loadconfig, uint8_t int_off)
 {
 	struct himax_ts_data *ts = private_ts;
 	int ret = 0;
 
 	return;
 	if (ts->rst_gpio) {
-		if(int_off)
-			{
-				if (ts->use_irq)
-					himax_int_enable(private_ts->client->irq,0);
-				else {
-					hrtimer_cancel(&ts->timer);
-					ret = cancel_work_sync(&ts->work);
-				}
+		if (int_off) {
+			if (ts->use_irq)
+				himax_int_enable(private_ts->client->irq, 0);
+			else {
+				hrtimer_cancel(&ts->timer);
+				ret = cancel_work_sync(&ts->work);
 			}
+		}
 
 		I("%s: Now reset the Touch chip.\n", __func__);
 
@@ -417,51 +418,51 @@
 		himax_rst_gpio_set(ts->rst_gpio, 1);
 		msleep(20);
 
-		if(loadconfig)
-			himax_loadSensorConfig(private_ts->client,private_ts->pdata);
+		if (loadconfig)
+			himax_loadSensorConfig(private_ts->client,
+			private_ts->pdata);
 
-		if(int_off)
-			{
-				if (ts->use_irq)
-					himax_int_enable(private_ts->client->irq,1);
-				else
-					hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL);
-			}
+		if (int_off) {
+			if (ts->use_irq)
+				himax_int_enable(private_ts->client->irq, 1);
+			else
+				hrtimer_start(&ts->timer,
+				ktime_set(1, 0), HRTIMER_MODE_REL);
+		}
 	}
 }
 #endif
 
-int himax_loadSensorConfig(struct i2c_client *client, struct himax_i2c_platform_data *pdata)
+int himax_loadSensorConfig(struct i2c_client *client,
+struct himax_i2c_platform_data *pdata)
 {
+	int err = -1;
 
 	if (!client) {
 		E("%s: Necessary parameters client are null!\n", __func__);
-		return -EINVAL;
+		return err;
 	}
-
-	if(config_load == false)
-		{
-			config_selected = kzalloc(sizeof(*config_selected), GFP_KERNEL);
-			if (config_selected == NULL) {
-				E("%s: alloc config_selected fail!\n", __func__);
-				return -ENOMEM;
-			}
+	if (config_load == false) {
+		config_selected = kzalloc(sizeof(*config_selected), GFP_KERNEL);
+		if (config_selected == NULL) {
+			E("%s: alloc config_selected fail!\n", __func__);
+			return err;
 		}
+	}
+	himax_power_on_initCMD(client);
 
-		himax_power_on_initCMD(client);
-
-		himax_int_enable(client->irq,0);
-		himax_read_FW_ver(client);
+	himax_int_enable(client->irq, 0);
+	himax_read_FW_ver(client);
 #ifdef HX_RST_PIN_FUNC
-	himax_HW_reset(true,false);
+	himax_HW_reset(true, false);
 #endif
-	himax_int_enable(client->irq,1);
-		I("FW_VER : %X \n",ic_data->vendor_fw_ver);
+	himax_int_enable(client->irq, 1);
+	I("FW_VER : %X\n", ic_data->vendor_fw_ver);
 
-		ic_data->vendor_sensor_id=0x2602;
-		I("sensor_id=%x.\n",ic_data->vendor_sensor_id);
+	ic_data->vendor_sensor_id = 0x2602;
+	I("sensor_id=%x.\n", ic_data->vendor_sensor_id);
 
-	himax_sense_on(private_ts->client, 0x01);//1=Flash, 0=SRAM
+	himax_sense_on(private_ts->client, 0x01);/*1=Flash, 0=SRAM*/
 	msleep(120);
 #ifdef HX_ESD_WORKAROUND
 	HX_ESD_RESET_ACTIVATE = 1;
@@ -474,47 +475,49 @@
 #ifdef HX_ESD_WORKAROUND
 void ESD_HW_REST(void)
 {
-	I("START_Himax TP: ESD - Reset\n");	
-	
+	I("START_Himax TP: ESD - Reset\n");
+
 	HX_report_ESD_event();
 	ESD_00_counter = 0;
 	ESD_00_Flag = 0;
-	/*************************************/
-		if (private_ts->protocol_type == PROTOCOL_TYPE_A)
+    /*************************************/
+	if (private_ts->protocol_type == PROTOCOL_TYPE_A)
 		input_mt_sync(private_ts->input_dev);
-		input_report_key(private_ts->input_dev, BTN_TOUCH, 0);
-		input_sync(private_ts->input_dev);
-		/*************************************/
+	input_report_key(private_ts->input_dev, BTN_TOUCH, 0);
+	input_sync(private_ts->input_dev);
+	/*************************************/
 
 	I("END_Himax TP: ESD - Reset\n");
 }
 #endif
 #ifdef HX_HIGH_SENSE
-void himax_set_HSEN_func(struct i2c_client *client,uint8_t HSEN_enable)
+void himax_set_HSEN_func(struct i2c_client *client, uint8_t HSEN_enable)
 {
 	uint8_t tmp_data[4];
 
-	if(HSEN_enable)
-	{
+	if (HSEN_enable) {
 		I(" %s in", __func__);
-		HSEN_bit_retry:
-		himax_set_HSEN_enable(client,HSEN_enable);
+HSEN_bit_retry:
+		himax_set_HSEN_enable(client, HSEN_enable);
 		msleep(20);
-		himax_get_HSEN_enable(client,tmp_data);
-		I("%s: Read HSEN bit data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
-			,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
-		if(tmp_data[0]!= 0x01)
-			{
-				I("%s: retry HSEN bit write data[0]=%x  \n",__func__,tmp_data[0]);
-				goto HSEN_bit_retry;
-			}
+		himax_get_HSEN_enable(client, tmp_data);
+		I("%s: Read HSEN bit data[0]=%x data[1]=%x",
+		__func__, tmp_data[0], tmp_data[1]);
+		I("data[2]=%x data[3]=%x\n",
+		tmp_data[2], tmp_data[3]);
+
+		if (tmp_data[0] != 0x01) {
+			I("%s: retry HSEN bit write data[0]=%x\n",
+			__func__, tmp_data[0]);
+			goto HSEN_bit_retry;
+		}
 	}
 }
 
 static void himax_HSEN_func(struct work_struct *work)
 {
-	struct himax_ts_data *ts = container_of(work, struct himax_ts_data,
-							hsen_work.work);
+	struct himax_ts_data *ts =
+	container_of(work, struct himax_ts_data, hsen_work.work);
 
 	himax_set_HSEN_func(ts->client, ts->HSEN_enable);
 }
@@ -525,9 +528,10 @@
 #ifdef HX_GESTURE_TRACK
 static void gest_pt_log_coordinate(int rx, int tx)
 {
-	//driver report x y with range 0 - 255 , we scale it up to x/y pixel
-	gest_pt_x[gest_pt_cnt] = rx*(ic_data->HX_X_RES)/255;
-	gest_pt_y[gest_pt_cnt] = tx*(ic_data->HX_Y_RES)/255;
+	/*driver report x y with range 0 - 255*/
+	/* And we scale it up to x/y coordinates*/
+	gest_pt_x[gest_pt_cnt] = rx * (ic_data->HX_X_RES) / 255;
+	gest_pt_y[gest_pt_cnt] = tx * (ic_data->HX_Y_RES) / 255;
 }
 #endif
 static int himax_parse_wake_event(struct himax_ts_data *ts)
@@ -535,145 +539,143 @@
 	uint8_t buf[64];
 	unsigned char check_sum_cal = 0;
 #ifdef HX_GESTURE_TRACK
-	int tmp_max_x=0x00,tmp_min_x=0xFFFF,tmp_max_y=0x00,tmp_min_y=0xFFFF;
+	int tmp_max_x = 0x00, tmp_min_x = 0xFFFF,
+	tmp_max_y = 0x00, tmp_min_y = 0xFFFF;
 	int gest_len;
 #endif
-	int i=0, check_FC = 0, gesture_flag = 0;
+	int i = 0, check_FC = 0, gesture_flag = 0;
 
 	himax_burst_enable(ts->client, 0);
-	himax_read_event_stack(ts->client,buf,56);
+	himax_read_event_stack(ts->client, buf, 56);
 
-	for(i=0;i<GEST_PTLG_ID_LEN;i++)
-	{
-		if (check_FC==0)
-		{
-			if((buf[0]!=0x00)&&((buf[0]<=0x0F)||(buf[0]==0x80)))
-			{
+	for (i = 0 ; i < GEST_PTLG_ID_LEN ; i++) {
+		if (check_FC == 0) {
+			if ((buf[0] != 0x00) &&
+			((buf[0] <= 0x0F) || (buf[0] == 0x80))) {
 				check_FC = 1;
 				gesture_flag = buf[i];
-			}
-			else
-			{
+			} else {
 				check_FC = 0;
-				I("ID START at %x , value = %x skip the event\n", i, buf[i]);
+				I("ID START at %x,value = %x skip event\n",
+				i, buf[i]);
 				break;
 			}
-		}
-		else
-		{
-			if(buf[i]!=gesture_flag)
-			{
+		} else {
+			if (buf[i] != gesture_flag) {
 				check_FC = 0;
-				I("ID NOT the same %x != %x So STOP parse event\n", buf[i], gesture_flag);
+				I("ID NOT same %x != %x So STOP parse event\n",
+				buf[i], gesture_flag);
 				break;
 			}
 		}
 
 		I("0x%2.2X ", buf[i]);
 		if (i % 8 == 7)
-				I("\n");
+			I("\n");
 	}
-	I("Himax gesture_flag= %x\n",gesture_flag );
+	I("Himax gesture_flag= %x\n", gesture_flag);
 	I("Himax check_FC is %d\n", check_FC);
 
 	if (check_FC == 0)
 		return 0;
-	if(buf[GEST_PTLG_ID_LEN] != GEST_PTLG_HDR_ID1 ||
-			buf[GEST_PTLG_ID_LEN+1] != GEST_PTLG_HDR_ID2)
+	if (buf[GEST_PTLG_ID_LEN] != GEST_PTLG_HDR_ID1
+	|| buf[GEST_PTLG_ID_LEN+1] != GEST_PTLG_HDR_ID2)
 		return 0;
-	for(i=0;i<(GEST_PTLG_ID_LEN+GEST_PTLG_HDR_LEN);i++)
-	{
-		I("P[%x]=0x%2.2X \n", i, buf[i]);
-		I("checksum=0x%2.2X \n", check_sum_cal);
+	for (i = 0 ; i < (GEST_PTLG_ID_LEN + GEST_PTLG_HDR_LEN) ; i++) {
+		I("P[%x]=0x%2.2X\n", i, buf[i]);
+		I("checksum=0x%2.2X\n", check_sum_cal);
 		check_sum_cal += buf[i];
 	}
-	if ((check_sum_cal != 0x00) )
-	{
-		I(" %s : check_sum_cal: 0x%02X\n",__func__ ,check_sum_cal);
+	if ((check_sum_cal != 0x00)) {
+		I(" %s : check_sum_cal: 0x%02X\n", __func__ , check_sum_cal);
 		return 0;
 	}
 #ifdef HX_GESTURE_TRACK
-	if(buf[GEST_PTLG_ID_LEN] == GEST_PTLG_HDR_ID1 &&
-			buf[GEST_PTLG_ID_LEN+1] == GEST_PTLG_HDR_ID2)
-	{
-		gest_len = buf[GEST_PTLG_ID_LEN+2];
-
-		I("gest_len = %d ",gest_len);
-
+	if (buf[GEST_PTLG_ID_LEN] == GEST_PTLG_HDR_ID1
+	&& buf[GEST_PTLG_ID_LEN+1] == GEST_PTLG_HDR_ID2) {
+		gest_len = buf[GEST_PTLG_ID_LEN + 2];
+		I("gest_len = %d ", gest_len);
 		i = 0;
 		gest_pt_cnt = 0;
-		I("gest doornidate start \n %s",__func__);
-		while(i<(gest_len+1)/2)
-		{
-			gest_pt_log_coordinate(buf[GEST_PTLG_ID_LEN+4+i*2],buf[GEST_PTLG_ID_LEN+4+i*2+1]);
+		I("gest doornidate start\n %s", __func__);
+		while (i < (gest_len + 1) / 2) {
+			gest_pt_log_coordinate
+			(buf[GEST_PTLG_ID_LEN + 4 + i * 2],
+			buf[GEST_PTLG_ID_LEN + 4 + i * 2 + 1]);
 			i++;
 
-			I("gest_pt_x[%d]=%d \n",gest_pt_cnt,gest_pt_x[gest_pt_cnt]);
-			I("gest_pt_y[%d]=%d \n",gest_pt_cnt,gest_pt_y[gest_pt_cnt]);
+			I("gest_pt_x[%d]=%d\n",
+			gest_pt_cnt, gest_pt_x[gest_pt_cnt]);
+			I("gest_pt_y[%d]=%d\n",
+			gest_pt_cnt, gest_pt_y[gest_pt_cnt]);
 
-			gest_pt_cnt +=1;
+			gest_pt_cnt += 1;
 		}
-		if(gest_pt_cnt)
-			{
-				for(i=0; i<gest_pt_cnt; i++)
-					{
-						if(tmp_max_x<gest_pt_x[i])
-							tmp_max_x=gest_pt_x[i];
-						if(tmp_min_x>gest_pt_x[i])
-							tmp_min_x=gest_pt_x[i];
-						if(tmp_max_y<gest_pt_y[i])
-							tmp_max_y=gest_pt_y[i];
-						if(tmp_min_y>gest_pt_y[i])
-							tmp_min_y=gest_pt_y[i];
-					}
-				I("gest_point x_min= %d, x_max= %d, y_min= %d, y_max= %d\n",tmp_min_x,tmp_max_x,tmp_min_y,tmp_max_y);
-				gest_start_x=gest_pt_x[0];
-				gn_gesture_coor[0] = gest_start_x;
-				gest_start_y=gest_pt_y[0];
-				gn_gesture_coor[1] = gest_start_y;
-				gest_end_x=gest_pt_x[gest_pt_cnt-1];
-				gn_gesture_coor[2] = gest_end_x;
-				gest_end_y=gest_pt_y[gest_pt_cnt-1];
-				gn_gesture_coor[3] = gest_end_y;
-				gest_width = tmp_max_x - tmp_min_x;
-				gn_gesture_coor[4] = gest_width;
-				gest_height = tmp_max_y - tmp_min_y;
-				gn_gesture_coor[5] = gest_height;
-				gest_mid_x = (tmp_max_x + tmp_min_x)/2;
-				gn_gesture_coor[6] = gest_mid_x;
-				gest_mid_y = (tmp_max_y + tmp_min_y)/2;
-				gn_gesture_coor[7] = gest_mid_y;
-				gn_gesture_coor[8] = gest_mid_x;//gest_up_x
-				gn_gesture_coor[9] = gest_mid_y-gest_height/2;//gest_up_y
-				gn_gesture_coor[10] = gest_mid_x;//gest_down_x
-				gn_gesture_coor[11] = gest_mid_y+gest_height/2;	//gest_down_y
-				gn_gesture_coor[12] = gest_mid_x-gest_width/2;	//gest_left_x
-				gn_gesture_coor[13] = gest_mid_y;	//gest_left_y
-				gn_gesture_coor[14] = gest_mid_x+gest_width/2;	//gest_right_x
-				gn_gesture_coor[15] = gest_mid_y; //gest_right_y
-
+		if (gest_pt_cnt) {
+			for (i = 0 ; i < gest_pt_cnt ; i++) {
+				if (tmp_max_x < gest_pt_x[i])
+					tmp_max_x = gest_pt_x[i];
+				if (tmp_min_x > gest_pt_x[i])
+					tmp_min_x = gest_pt_x[i];
+				if (tmp_max_y < gest_pt_y[i])
+					tmp_max_y = gest_pt_y[i];
+				if (tmp_min_y > gest_pt_y[i])
+					tmp_min_y = gest_pt_y[i];
 			}
+			I("gest_point x_min= %d, x_max= %d\n",
+			tmp_min_x, tmp_max_x);
+			I("y_min= %d, y_max= %d\n",
+			tmp_min_y, tmp_max_y);
+			gest_start_x = gest_pt_x[0];
+			gn_gesture_coor[0] = gest_start_x;
+			gest_start_y = gest_pt_y[0];
+			gn_gesture_coor[1] = gest_start_y;
+			gest_end_x = gest_pt_x[gest_pt_cnt - 1];
+			gn_gesture_coor[2] = gest_end_x;
+			gest_end_y = gest_pt_y[gest_pt_cnt - 1];
+			gn_gesture_coor[3] = gest_end_y;
+			gest_width = tmp_max_x - tmp_min_x;
+			gn_gesture_coor[4] = gest_width;
+			gest_height = tmp_max_y - tmp_min_y;
+			gn_gesture_coor[5] = gest_height;
+			gest_mid_x = (tmp_max_x + tmp_min_x) / 2;
+			gn_gesture_coor[6] = gest_mid_x;
+			gest_mid_y = (tmp_max_y + tmp_min_y) / 2;
+			gn_gesture_coor[7] = gest_mid_y;
+			/*gest_up_x*/
+			gn_gesture_coor[8] = gest_mid_x;
+			/*gest_up_y*/
+			gn_gesture_coor[9] = gest_mid_y - gest_height / 2;
+			/*gest_down_x*/
+			gn_gesture_coor[10] = gest_mid_x;
+			/*gest_down_y*/
+			gn_gesture_coor[11] = gest_mid_y + gest_height / 2;
+			/*gest_left_x*/
+			gn_gesture_coor[12] = gest_mid_x - gest_width / 2;
+			/*gest_left_y*/
+			gn_gesture_coor[13] = gest_mid_y;
+			/*gest_right_x*/
+			gn_gesture_coor[14] = gest_mid_x + gest_width / 2;
+			/*gest_right_y*/
+			gn_gesture_coor[15] = gest_mid_y;
+
+		}
 
 	}
 #endif
-	if(gesture_flag != 0x80)
-	{
-		if(!ts->gesture_cust_en[gesture_flag])
-			{
-				I("%s NOT report customer key \n ",__func__);
-				return 0;//NOT report customer key
-			}
-	}
-	else
-	{
-		if(!ts->gesture_cust_en[0])
-			{
-				I("%s NOT report report double click \n",__func__);
-				return 0;//NOT report power key
-			}
+	if (gesture_flag != 0x80) {
+		if (!ts->gesture_cust_en[gesture_flag]) {
+			I("%s NOT report customer key\n ", __func__);
+			return 0;/*NOT report customer key*/
+		}
+	} else {
+		if (!ts->gesture_cust_en[0]) {
+			I("%s NOT report report double click\n", __func__);
+			return 0;/*NOT report power key*/
+		}
 	}
 
-	if(gesture_flag == 0x80)
+	if (gesture_flag == 0x80)
 		return EV_GESTURE_PWR;
 	else
 		return gesture_flag;
@@ -685,225 +687,242 @@
 
 	ret_event = himax_parse_wake_event(private_ts);
 	switch (ret_event) {
-		case EV_GESTURE_PWR:
-			KEY_EVENT = KEY_POWER;
+	case EV_GESTURE_PWR:
+		KEY_EVENT = KEY_POWER;
 		break;
-		case EV_GESTURE_01:
-			KEY_EVENT = KEY_CUST_01;
+	case EV_GESTURE_01:
+		KEY_EVENT = KEY_CUST_01;
 		break;
-		case EV_GESTURE_02:
-			KEY_EVENT = KEY_CUST_02;
+	case EV_GESTURE_02:
+		KEY_EVENT = KEY_CUST_02;
 		break;
-		case EV_GESTURE_03:
-			KEY_EVENT = KEY_CUST_03;
+	case EV_GESTURE_03:
+		KEY_EVENT = KEY_CUST_03;
 		break;
-		case EV_GESTURE_04:
-			KEY_EVENT = KEY_CUST_04;
+	case EV_GESTURE_04:
+		KEY_EVENT = KEY_CUST_04;
 		break;
-		case EV_GESTURE_05:
-			KEY_EVENT = KEY_CUST_05;
+	case EV_GESTURE_05:
+		KEY_EVENT = KEY_CUST_05;
 		break;
-		case EV_GESTURE_06:
-			KEY_EVENT = KEY_CUST_06;
+	case EV_GESTURE_06:
+		KEY_EVENT = KEY_CUST_06;
 		break;
-		case EV_GESTURE_07:
-			KEY_EVENT = KEY_CUST_07;
+	case EV_GESTURE_07:
+		KEY_EVENT = KEY_CUST_07;
 		break;
-		case EV_GESTURE_08:
-			KEY_EVENT = KEY_CUST_08;
+	case EV_GESTURE_08:
+		KEY_EVENT = KEY_CUST_08;
 		break;
-		case EV_GESTURE_09:
-			KEY_EVENT = KEY_CUST_09;
+	case EV_GESTURE_09:
+		KEY_EVENT = KEY_CUST_09;
 		break;
-		case EV_GESTURE_10:
-			KEY_EVENT = KEY_CUST_10;
+	case EV_GESTURE_10:
+		KEY_EVENT = KEY_CUST_10;
 		break;
-		case EV_GESTURE_11:
-			KEY_EVENT = KEY_CUST_11;
+	case EV_GESTURE_11:
+		KEY_EVENT = KEY_CUST_11;
 		break;
-		case EV_GESTURE_12:
-			KEY_EVENT = KEY_CUST_12;
+	case EV_GESTURE_12:
+		KEY_EVENT = KEY_CUST_12;
 		break;
-		case EV_GESTURE_13:
-			KEY_EVENT = KEY_CUST_13;
+	case EV_GESTURE_13:
+		KEY_EVENT = KEY_CUST_13;
 		break;
-		case EV_GESTURE_14:
-			KEY_EVENT = KEY_CUST_14;
+	case EV_GESTURE_14:
+		KEY_EVENT = KEY_CUST_14;
 		break;
-		case EV_GESTURE_15:
-			KEY_EVENT = KEY_CUST_15;
+	case EV_GESTURE_15:
+		KEY_EVENT = KEY_CUST_15;
 		break;
 	}
-	if(ret_event)
-		{
-			I(" %s SMART WAKEUP KEY event %x press\n",__func__,KEY_EVENT);
-			input_report_key(private_ts->input_dev, KEY_EVENT, 1);
-			input_sync(private_ts->input_dev);
-			//msleep(100);
-			I(" %s SMART WAKEUP KEY event %x release\n",__func__,KEY_EVENT);
-			input_report_key(private_ts->input_dev, KEY_EVENT, 0);
-			input_sync(private_ts->input_dev);
-			FAKE_POWER_KEY_SEND=true;
+	if (ret_event) {
+		I(" %s SMART WAKEUP KEY event %x press\n",
+		__func__, KEY_EVENT);
+		input_report_key(private_ts->input_dev, KEY_EVENT, 1);
+		input_sync(private_ts->input_dev);
+		/*msleep(100);*/
+		I(" %s SMART WAKEUP KEY event %x release\n",
+		__func__, KEY_EVENT);
+		input_report_key(private_ts->input_dev, KEY_EVENT, 0);
+		input_sync(private_ts->input_dev);
+		FAKE_POWER_KEY_SEND = true;
 #ifdef HX_GESTURE_TRACK
-			I("gest_start_x= %d, gest_start_y= %d, gest_end_x= %d, gest_end_y= %d\n",gest_start_x,gest_start_y,
-			gest_end_x,gest_end_y);
-			I("gest_width= %d, gest_height= %d, gest_mid_x= %d, gest_mid_y= %d\n",gest_width,gest_height,
-			gest_mid_x,gest_mid_y);
-			I("gest_up_x= %d, gest_up_y= %d, gest_down_x= %d, gest_down_y= %d\n",gn_gesture_coor[8],gn_gesture_coor[9],
-			gn_gesture_coor[10],gn_gesture_coor[11]);
-			I("gest_left_x= %d, gest_left_y= %d, gest_right_x= %d, gest_right_y= %d\n",gn_gesture_coor[12],gn_gesture_coor[13],
-			gn_gesture_coor[14],gn_gesture_coor[15]);
+		I("gest_start_x= %d, gest_start_y= %d\n",
+		gest_start_x, gest_start_y);
+		I("gest_end_x= %d, gest_end_y= %d\n",
+		gest_end_x, gest_end_y);
+		I("gest_width= %d, gest_height= %d\n",
+		gest_width, gest_height);
+		I("gest_mid_x= %d, gest_mid_y= %d\n",
+		gest_mid_x, gest_mid_y);
+		I("gest_up_x= %d, gest_up_y= %d\n",
+		gn_gesture_coor[8], gn_gesture_coor[9]);
+		I("gest_down_x= %d, gest_down_y= %d\n",
+		gn_gesture_coor[10], gn_gesture_coor[11]);
+		I("gest_left_x= %d, gest_left_y= %d\n",
+		gn_gesture_coor[12], gn_gesture_coor[13]);
+		I("gest_right_x= %d, gest_right_y= %d\n",
+		gn_gesture_coor[14], gn_gesture_coor[15]);
 #endif
-		}
+	}
 }
 
 #endif
-static void himax_ts_button_func(int tp_key_index,struct himax_ts_data *ts)
+static void himax_ts_button_func(int tp_key_index, struct himax_ts_data *ts)
 {
 	uint16_t x_position = 0, y_position = 0;
-if ( tp_key_index != 0x00)
-	{
-		I("virtual key index =%x\n",tp_key_index);
-		if ( tp_key_index == 0x01) {
+
+	if (tp_key_index != 0x00) {
+		I("virtual key index =%x\n", tp_key_index);
+		if (tp_key_index == 0x01) {
 			vk_press = 1;
 			I("back key pressed\n");
-				if (ts->pdata->virtual_key)
-				{
-					if (ts->button[0].index) {
-						x_position = (ts->button[0].x_range_min + ts->button[0].x_range_max) / 2;
-						y_position = (ts->button[0].y_range_min + ts->button[0].y_range_max) / 2;
-					}
-					if (ts->protocol_type == PROTOCOL_TYPE_A) {
-						input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
-						input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
-							x_position);
-						input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
-							y_position);
-						input_mt_sync(ts->input_dev);
-					} else if (ts->protocol_type == PROTOCOL_TYPE_B) {
-						input_mt_slot(ts->input_dev, 0);
-						input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
-						1);
-						input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
-							x_position);
-						input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
-							y_position);
-					}
+			if (ts->pdata->virtual_key) {
+				if (ts->button[0].index) {
+					x_position = (ts->button[0].x_range_min
+					+ ts->button[0].x_range_max) / 2;
+					y_position = (ts->button[0].y_range_min
+					+ ts->button[0].y_range_max) / 2;
 				}
-				else
-					input_report_key(ts->input_dev, KEY_BACK, 1);
-		}
-		else if ( tp_key_index == 0x02) {
+				if (ts->protocol_type == PROTOCOL_TYPE_A) {
+					input_report_abs(ts->input_dev,
+					ABS_MT_TRACKING_ID, 0);
+					input_report_abs(ts->input_dev,
+					ABS_MT_TOUCH_MAJOR, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_WIDTH_MAJOR, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_PRESSURE, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_POSITION_X, x_position);
+					input_report_abs(ts->input_dev,
+					ABS_MT_POSITION_Y, y_position);
+					input_mt_sync(ts->input_dev);
+				} else if (ts->protocol_type
+					== PROTOCOL_TYPE_B) {
+					input_mt_slot(ts->input_dev, 0);
+
+					input_mt_report_slot_state
+					(ts->input_dev, MT_TOOL_FINGER, 1);
+
+					input_report_abs(ts->input_dev,
+					ABS_MT_TOUCH_MAJOR, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_WIDTH_MAJOR, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_PRESSURE, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_POSITION_X, x_position);
+					input_report_abs(ts->input_dev,
+					ABS_MT_POSITION_Y, y_position);
+				}
+			} else
+				input_report_key(ts->input_dev, KEY_BACK, 1);
+		} else if (tp_key_index == 0x02) {
 			vk_press = 1;
 			I("home key pressed\n");
-				if (ts->pdata->virtual_key)
-				{
-					if (ts->button[1].index) {
-						x_position = (ts->button[1].x_range_min + ts->button[1].x_range_max) / 2;
-						y_position = (ts->button[1].y_range_min + ts->button[1].y_range_max) / 2;
-					}
-						if (ts->protocol_type == PROTOCOL_TYPE_A) {
-						input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
-						input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
-							x_position);
-						input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
-							y_position);
-						input_mt_sync(ts->input_dev);
-					} else if (ts->protocol_type == PROTOCOL_TYPE_B) {
-						input_mt_slot(ts->input_dev, 0);
-						input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
-						1);
-						input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
-							x_position);
-						input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
-							y_position);
-					}
+			if (ts->pdata->virtual_key) {
+				if (ts->button[1].index) {
+					x_position = (ts->button[1].x_range_min
+					+ ts->button[1].x_range_max) / 2;
+					y_position = (ts->button[1].y_range_min
+					+ ts->button[1].y_range_max) / 2;
 				}
-				else
-					input_report_key(ts->input_dev, KEY_HOME, 1);
-		}
-		else if ( tp_key_index == 0x04) {
+				if (ts->protocol_type == PROTOCOL_TYPE_A) {
+					input_report_abs(ts->input_dev,
+					ABS_MT_TRACKING_ID, 0);
+					input_report_abs(ts->input_dev,
+					ABS_MT_TOUCH_MAJOR, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_WIDTH_MAJOR, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_PRESSURE, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_POSITION_X, x_position);
+					input_report_abs(ts->input_dev,
+					ABS_MT_POSITION_Y, y_position);
+					input_mt_sync(ts->input_dev);
+				} else if (ts->protocol_type
+				== PROTOCOL_TYPE_B) {
+					input_mt_slot(ts->input_dev, 0);
+
+					input_mt_report_slot_state
+					(ts->input_dev, MT_TOOL_FINGER, 1);
+
+					input_report_abs(ts->input_dev,
+					ABS_MT_TOUCH_MAJOR, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_WIDTH_MAJOR, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_PRESSURE, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_POSITION_X, x_position);
+					input_report_abs(ts->input_dev,
+					ABS_MT_POSITION_Y, y_position);
+				}
+			} else
+				input_report_key(ts->input_dev, KEY_HOME, 1);
+		} else if (tp_key_index == 0x04) {
 			vk_press = 1;
 			I("APP_switch key pressed\n");
-				if (ts->pdata->virtual_key)
-				{
-					if (ts->button[2].index) {
-						x_position = (ts->button[2].x_range_min + ts->button[2].x_range_max) / 2;
-						y_position = (ts->button[2].y_range_min + ts->button[2].y_range_max) / 2;
-					}
-						if (ts->protocol_type == PROTOCOL_TYPE_A) {
-						input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0);
-						input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
-							x_position);
-						input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
-							y_position);
-						input_mt_sync(ts->input_dev);
-					} else if (ts->protocol_type == PROTOCOL_TYPE_B) {
-						input_mt_slot(ts->input_dev, 0);
-						input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER,
-						1);
-						input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_PRESSURE,
-							100);
-						input_report_abs(ts->input_dev, ABS_MT_POSITION_X,
-							x_position);
-						input_report_abs(ts->input_dev, ABS_MT_POSITION_Y,
-							y_position);
-					}
+			if (ts->pdata->virtual_key) {
+				if (ts->button[2].index) {
+					x_position = (ts->button[2].x_range_min
+					+ ts->button[2].x_range_max) / 2;
+					y_position = (ts->button[2].y_range_min
+					+ ts->button[2].y_range_max) / 2;
 				}
-				else
-					input_report_key(ts->input_dev, KEY_F10, 1);	
+				if (ts->protocol_type == PROTOCOL_TYPE_A) {
+					input_report_abs(ts->input_dev,
+					ABS_MT_TRACKING_ID, 0);
+					input_report_abs(ts->input_dev,
+					ABS_MT_TOUCH_MAJOR, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_WIDTH_MAJOR, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_PRESSURE, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_POSITION_X, x_position);
+					input_report_abs(ts->input_dev,
+					ABS_MT_POSITION_Y, y_position);
+					input_mt_sync(ts->input_dev);
+				} else if (ts->protocol_type ==
+				PROTOCOL_TYPE_B) {
+					input_mt_slot(ts->input_dev, 0);
+
+					input_mt_report_slot_state
+					(ts->input_dev, MT_TOOL_FINGER, 1);
+
+					input_report_abs(ts->input_dev,
+					ABS_MT_TOUCH_MAJOR, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_WIDTH_MAJOR, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_PRESSURE, 100);
+					input_report_abs(ts->input_dev,
+					ABS_MT_POSITION_X, x_position);
+					input_report_abs(ts->input_dev,
+					ABS_MT_POSITION_Y, y_position);
+				}
+			} else
+				input_report_key(ts->input_dev, KEY_F10, 1);
 		}
 		input_sync(ts->input_dev);
-	}
-else/*tp_key_index =0x00*/
-	{
+	} else {/*tp_key_index =0x00*/
 		I("virtual key released\n");
 		vk_press = 0;
 		if (ts->protocol_type == PROTOCOL_TYPE_A) {
 			input_mt_sync(ts->input_dev);
-		}
-		else if (ts->protocol_type == PROTOCOL_TYPE_B) {
+		} else if (ts->protocol_type == PROTOCOL_TYPE_B) {
 			input_mt_slot(ts->input_dev, 0);
-			input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
+			input_mt_report_slot_state(ts->input_dev,
+			MT_TOOL_FINGER, 0);
 		}
 		input_report_key(ts->input_dev, KEY_BACK, 0);
 		input_report_key(ts->input_dev, KEY_HOME, 0);
 		input_report_key(ts->input_dev, KEY_F10, 0);
-	input_sync(ts->input_dev);
+		input_sync(ts->input_dev);
 	}
 }
 
@@ -915,8 +934,8 @@
 	uint8_t finger_on = 0;
 	int32_t loop_i;
 	uint16_t check_sum_cal = 0;
-	int raw_cnt_max ;
-	int raw_cnt_rmd ;
+	int raw_cnt_max;
+	int raw_cnt_rmd;
 	int hx_touch_info_size;
 	uint8_t coordInfoSize = ts->coord_data_size + ts->area_data_size + 4;
 
@@ -924,121 +943,111 @@
 	int16_t *mutual_data;
 	int16_t *self_data;
 	uint8_t diag_cmd;
-	int  	i;
-	int 	mul_num;
-	int 	self_num;
+	int i;
+	int mul_num;
+	int self_num;
 	int RawDataLen = 0;
-	//coordinate dump start
-	char coordinate_char[15+(ic_data->HX_MAX_PT+5)*2*5+2];
-	//coordinate dump end
+	/*coordinate dump start*/
+	char coordinate_char[15 + (ic_data->HX_MAX_PT + 5) * 2 * 5 + 2];
+	struct timeval t;
+	struct tm broken;
+	/*coordinate dump end*/
 #endif
 
 	memset(buf, 0x00, sizeof(buf));
 	memset(hw_reset_check, 0x00, sizeof(hw_reset_check));
 
-	raw_cnt_max = ic_data->HX_MAX_PT/4;
-	raw_cnt_rmd = ic_data->HX_MAX_PT%4;
-	
+	raw_cnt_max = ic_data->HX_MAX_PT / 4;
+	raw_cnt_rmd = ic_data->HX_MAX_PT % 4;
 #if defined(HX_USB_DETECT2)
 	himax_cable_detect_func();
 #endif
 
-	if (raw_cnt_rmd != 0x00) //more than 4 fingers
-	{
-		RawDataLen = cal_data_len(raw_cnt_rmd, ic_data->HX_MAX_PT, raw_cnt_max);
-		hx_touch_info_size = (ic_data->HX_MAX_PT+raw_cnt_max+2)*4;
-	}
-	else //less than 4 fingers
-	{
-		RawDataLen = cal_data_len(raw_cnt_rmd, ic_data->HX_MAX_PT, raw_cnt_max);
-		hx_touch_info_size = (ic_data->HX_MAX_PT+raw_cnt_max+1)*4;
+	if (raw_cnt_rmd != 0x00) { /*more than 4 fingers*/
+		RawDataLen = cal_data_len(raw_cnt_rmd,
+		ic_data->HX_MAX_PT, raw_cnt_max);
+		hx_touch_info_size = (ic_data->HX_MAX_PT + raw_cnt_max + 2) * 4;
+	} else { /*less than 4 fingers*/
+		RawDataLen = cal_data_len(raw_cnt_rmd,
+		ic_data->HX_MAX_PT, raw_cnt_max);
+		hx_touch_info_size = (ic_data->HX_MAX_PT + raw_cnt_max + 1) * 4;
 	}
 
 #ifdef HX_TP_PROC_DIAG
 	diag_cmd = getDiagCommand();
-	if( diag_cmd ){
+	if (diag_cmd) {
 		ret = read_event_stack(ts->client, buf, 128);
-	}
-	else{
-		if(touch_monitor_stop_flag != 0){
+	} else {
+		if (touch_monitor_stop_flag != 0) {
 			ret = read_event_stack(ts->client, buf, 128);
-			touch_monitor_stop_flag-- ;
-		}
-		else{
-			ret = read_event_stack(ts->client, buf, hx_touch_info_size);
+			touch_monitor_stop_flag--;
+		} else {
+			ret = read_event_stack(ts->client,
+					buf, hx_touch_info_size);
 		}
 	}
 
 	if (!ret)
 #else
-	if(!read_event_stack(ts->client, buf, hx_touch_info_size))
-#endif		
-	{
-		E("%s: can't read data from chip!\n", __func__);
-		goto err_workqueue_out;
-	}
+	if (!read_event_stack(ts->client, buf, hx_touch_info_size))
+#endif
+		{
+			E("%s: can't read data from chip!\n", __func__);
+			goto err_workqueue_out;
+		}
 	post_read_event_stack(ts->client);
 #ifdef HX_ESD_WORKAROUND
-	for(i = 0; i < hx_touch_info_size; i++)
-	{
-		if(buf[i] == 0xED)/*case 1 ESD recovery flow*/
-		{
+	for (i = 0; i < hx_touch_info_size; i++) {
+		if (buf[i] == 0xED)	{ /*case 1 ESD recovery flow*/
 			check_sum_cal = 1;
 
-		}else if(buf[i] == 0x00)
-		{
+		} else if (buf[i] == 0x00) {
 			ESD_00_Flag = 1;
-		}
-		else
-		{
+		} else {
 			check_sum_cal = 0;
 			ESD_00_counter = 0;
-	    ESD_00_Flag = 0;
+			ESD_00_Flag = 0;
 			i = hx_touch_info_size;
 			break;
-		}		
+		}
 	}
-	if (ESD_00_Flag == 1){
-		ESD_00_counter ++;
-	}
-	if (ESD_00_counter > 1){
+	if (ESD_00_Flag == 1)
+		ESD_00_counter++;
+	if (ESD_00_counter > 1)
 		check_sum_cal = 2;
-	}
-	
-	 if (check_sum_cal == 2 && HX_ESD_RESET_ACTIVATE == 0)
-	 {
-	  I("[HIMAX TP MSG]: ESD event checked - ALL Zero.\n");
-	  ESD_HW_REST();
-	  return;
-	 }
-	 
-	if (check_sum_cal == 1 && HX_ESD_RESET_ACTIVATE == 0)
-	{
-		I("[HIMAX TP MSG]: ESD event checked - ALL 0xED.\n");
+	if (check_sum_cal == 2 && HX_ESD_RESET_ACTIVATE == 0) {
+		I("[HIMAX TP MSG]: ESD event checked - ALL Zero.\n");
 		ESD_HW_REST();
 		return;
 	}
-	else if (HX_ESD_RESET_ACTIVATE)
-	{
+	if (check_sum_cal == 1 && HX_ESD_RESET_ACTIVATE == 0) {
+		I("[HIMAX TP MSG]: ESD event checked - ALL 0xED.\n");
+		ESD_HW_REST();
+		return;
+	} else if (HX_ESD_RESET_ACTIVATE) {
 #ifdef HX_SMART_WAKEUP
-		queue_delayed_work(ts->himax_smwp_wq, &ts->smwp_work, msecs_to_jiffies(50));
+		queue_delayed_work(ts->himax_smwp_wq,
+		&ts->smwp_work, msecs_to_jiffies(50));
 #endif
 #ifdef HX_HIGH_SENSE
-		queue_delayed_work(ts->himax_hsen_wq, &ts->hsen_work, msecs_to_jiffies(50));
+		queue_delayed_work(ts->himax_hsen_wq,
+		&ts->hsen_work, msecs_to_jiffies(50));
 #endif
-		HX_ESD_RESET_ACTIVATE = 0;/*drop 1st interrupts after chip reset*/
-		I("[HIMAX TP MSG]:%s: Back from reset, ready to serve.\n", __func__);
+/*drop 1st interrupts after chip reset*/
+		HX_ESD_RESET_ACTIVATE = 0;
+		I("[HIMAX TP MSG]:%s: Back from reset,ready to serve.\n",
+		__func__);
 	}
 #endif
-	for (loop_i = 0, check_sum_cal = 0; loop_i < hx_touch_info_size; loop_i++)
+	for (loop_i = 0, check_sum_cal = 0;
+	loop_i < hx_touch_info_size; loop_i++)
 		check_sum_cal += buf[loop_i];
-	
-	if ((check_sum_cal % 0x100 != 0) )
-	{
-		I("[HIMAX TP MSG] checksum fail : check_sum_cal: 0x%02X\n", check_sum_cal);
+
+	if ((check_sum_cal % 0x100 != 0)) {
+		I("[HIMAX TP MSG] checksum fail : check_sum_cal: 0x%02X\n",
+		check_sum_cal);
 		return;
 	}
-
 	if (ts->debug_log_level & BIT(0)) {
 		I("%s: raw data:\n", __func__);
 		for (loop_i = 0; loop_i < hx_touch_info_size; loop_i++) {
@@ -1048,260 +1057,289 @@
 		}
 	}
 
-	//touch monitor raw data fetch
+	/*touch monitor raw data fetch*/
 #ifdef HX_TP_PROC_DIAG
 	diag_cmd = getDiagCommand();
-	if (diag_cmd >= 1 && diag_cmd <= 6)
-	{
-		//Check 124th byte CRC
-		if(!diag_check_sum(hx_touch_info_size, buf))
-		{
+	if (diag_cmd >= 1 && diag_cmd <= 6) {
+		/*Check 124th byte CRC*/
+		if (!diag_check_sum(hx_touch_info_size, buf))
 			goto bypass_checksum_failed_packet;
-		}
-#ifdef HX_TP_PROC_2T2R
-		if(Is_2T2R && diag_cmd == 4)
-		{
-			mutual_data = getMutualBuffer_2();
-			self_data 	= getSelfBuffer();
 
-			// initiallize the block number of mutual and self
+#ifdef HX_TP_PROC_2T2R
+		if (Is_2T2R && diag_cmd == 4) {
+			mutual_data = getMutualBuffer_2();
+			self_data = getSelfBuffer();
+
+			/* initiallize the block number of mutual and self*/
 			mul_num = getXChannel_2() * getYChannel_2();
 
 #ifdef HX_EN_SEL_BUTTON
-			self_num = getXChannel_2() + getYChannel_2() + ic_data->HX_BT_NUM;
+			self_num = getXChannel_2() +
+					getYChannel_2() + ic_data->HX_BT_NUM;
 #else
 			self_num = getXChannel_2() + getYChannel_2();
 #endif
-		}
-		else
-#endif			
+		} else
+#endif
 		{
 			mutual_data = getMutualBuffer();
-			self_data 	= getSelfBuffer();
+			self_data = getSelfBuffer();
 
-			// initiallize the block number of mutual and self
+			/* initiallize the block number of mutual and self*/
 			mul_num = getXChannel() * getYChannel();
 
 #ifdef HX_EN_SEL_BUTTON
-			self_num = getXChannel() + getYChannel() + ic_data->HX_BT_NUM;
+			self_num = getXChannel() +
+					getYChannel() + ic_data->HX_BT_NUM;
 #else
 			self_num = getXChannel() + getYChannel();
 #endif
 		}
 
-		diag_parse_raw_data(hx_touch_info_size, RawDataLen, mul_num, self_num, buf, diag_cmd, mutual_data,	self_data);
+		diag_parse_raw_data(hx_touch_info_size,
+		RawDataLen, mul_num, self_num, buf,
+		diag_cmd, mutual_data, self_data);
 
-	}
-	else if (diag_cmd == 7)
-	{
+	} else if (diag_cmd == 7) {
 		memcpy(&(diag_coor[0]), &buf[0], 128);
 	}
-	//coordinate dump start
-	if (coordinate_dump_enable == 1)
-	{
-		for(i=0; i<(15 + (ic_data->HX_MAX_PT+5)*2*5); i++)
-		{
+	/*coordinate dump start*/
+	if (coordinate_dump_enable == 1) {
+		for (i = 0; i < (15 + (ic_data->
+			HX_MAX_PT + 5) * 2 * 5);
+		i++) {
 			coordinate_char[i] = 0x20;
 		}
-		coordinate_char[15 + (ic_data->HX_MAX_PT+5)*2*5] = 0xD;
-		coordinate_char[15 + (ic_data->HX_MAX_PT+5)*2*5 + 1] = 0xA;
+		coordinate_char[15 +
+		(ic_data->HX_MAX_PT + 5) * 2 * 5] = 0xD;
+		coordinate_char[15 +
+		(ic_data->HX_MAX_PT + 5) * 2 * 5 + 1] = 0xA;
 	}
-	//coordinate dump end
+	/*coordinate dump end*/
 bypass_checksum_failed_packet:
 #endif
-		EN_NoiseFilter = (buf[HX_TOUCH_INFO_POINT_CNT+2]>>3);
-		//I("EN_NoiseFilter=%d\n",EN_NoiseFilter);
-		EN_NoiseFilter = EN_NoiseFilter & 0x01;
-		//I("EN_NoiseFilter2=%d\n",EN_NoiseFilter);
+	EN_NoiseFilter = (buf[HX_TOUCH_INFO_POINT_CNT + 2] >> 3);
+	/*I("EN_NoiseFilter=%d\n",EN_NoiseFilter);*/
+	EN_NoiseFilter = EN_NoiseFilter & 0x01;
+	/*I("EN_NoiseFilter2=%d\n",EN_NoiseFilter);*/
 
 #if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON)
-		tpd_key = (buf[HX_TOUCH_INFO_POINT_CNT+2]>>4);
-		if (tpd_key == 0x0F)/*All (VK+AA)leave*/
-		{
-			tpd_key = 0x00;
-		}
-		//I("[DEBUG] tpd_key:  %x\r\n", tpd_key);
-#else
+	tpd_key = (buf[HX_TOUCH_INFO_POINT_CNT + 2] >> 4);
+	if (tpd_key == 0x0F) {/*All (VK+AA)leave*/
 		tpd_key = 0x00;
+	}
+	/*I("[DEBUG] tpd_key:  %x\r\n", tpd_key);*/
+#else
+	tpd_key = 0x00;
 #endif
 
-		p_point_num = hx_point_num;
+	p_point_num = hx_point_num;
 
-		if (buf[HX_TOUCH_INFO_POINT_CNT] == 0xff)
-			hx_point_num = 0;
-		else
-			hx_point_num= buf[HX_TOUCH_INFO_POINT_CNT] & 0x0f;
+	if (buf[HX_TOUCH_INFO_POINT_CNT] == 0xff)
+		hx_point_num = 0;
+	else
+		hx_point_num = buf[HX_TOUCH_INFO_POINT_CNT] & 0x0f;
 
-		// Touch Point information
-		if (hx_point_num != 0 ) {
-			if(vk_press == 0x00)
-				{
-					uint16_t old_finger = ts->pre_finger_mask;
-					ts->pre_finger_mask = 0;
-					finger_num = buf[coordInfoSize - 4] & 0x0F;
-					finger_on = 1;
-					AA_press = 1;
-					for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) {
-							int base = loop_i * 4;
-							int x = buf[base] << 8 | buf[base + 1];
-							int y = (buf[base + 2] << 8 | buf[base + 3]);
-							int w = buf[(ts->nFinger_support * 4) + loop_i];
-						if(x >= 0 && x <= ts->pdata->abs_x_max && y >= 0 && y <= ts->pdata->abs_y_max){
-							finger_num--;
+	/* Touch Point information*/
+	if ((hx_point_num != 0) && (vk_press == 0x00)) {
+		uint16_t old_finger = ts->pre_finger_mask;
 
-							if ((ts->debug_log_level & BIT(3)) > 0)
-							{
-								if (old_finger >> loop_i == 0)
-								{
-									if (ts->useScreenRes)
-									{
-										I("status: Screen:F:%02d Down, X:%d, Y:%d, W:%d, N:%d\n",
-										loop_i+1, x * ts->widthFactor >> SHIFTBITS,
-										y * ts->heightFactor >> SHIFTBITS, w, EN_NoiseFilter);
-									}
-									else
-									{
-										I("status: Raw:F:%02d Down, X:%d, Y:%d, W:%d, N:%d\n",
-										loop_i+1, x, y, w, EN_NoiseFilter);
-									}
-								}
-							}
+		ts->pre_finger_mask = 0;
+		finger_num = buf[coordInfoSize - 4] & 0x0F;
+		finger_on = 1;
+		AA_press = 1;
+		for (i = 0; i < ts->nFinger_support; i++) {
+			int base = i * 4;
+			int x = buf[base] << 8 | buf[base + 1];
+			int y = (buf[base + 2] << 8 | buf[base + 3]);
+			int w = buf[(ts->nFinger_support * 4) + i];
 
-							if (ts->protocol_type == PROTOCOL_TYPE_B)
-							{
-								input_mt_slot(ts->input_dev, loop_i);
-							}
-
-							input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
-							input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
-							input_report_abs(ts->input_dev, ABS_MT_PRESSURE, w);
-							input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
-							input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
-							
-							if (ts->protocol_type == PROTOCOL_TYPE_A)
-							{
-								input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, loop_i);
-								input_mt_sync(ts->input_dev);
-							}
-							else
-							{
-								ts->last_slot = loop_i;
-								input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1);
-							}
-
-							if (!ts->first_pressed)
-							{
-								ts->first_pressed = 1;
-								I("S1@%d, %d\n", x, y);
-							}
-
-							ts->pre_finger_data[loop_i][0] = x;
-							ts->pre_finger_data[loop_i][1] = y;
-
-
-							if (ts->debug_log_level & BIT(1))
-								I("Finger %d=> X:%d, Y:%d W:%d, Z:%d, F:%d, N:%d\n",
-									loop_i + 1, x, y, w, w, loop_i + 1, EN_NoiseFilter);
-										
-							ts->pre_finger_mask = ts->pre_finger_mask + (1 << loop_i);
-											
-						} else {
-							if (ts->protocol_type == PROTOCOL_TYPE_B)
-							{
-								input_mt_slot(ts->input_dev, loop_i);
-								input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
-							}
-
-							if (loop_i == 0 && ts->first_pressed == 1)
-							{
-								ts->first_pressed = 2;
-								I("E1@%d, %d\n",
-								ts->pre_finger_data[0][0] , ts->pre_finger_data[0][1]);
-							}
-							if ((ts->debug_log_level & BIT(3)) > 0)
-							{
-								if (old_finger >> loop_i == 1)
-								{
-									if (ts->useScreenRes)
-									{
-										I("status: Screen:F:%02d Up, X:%d, Y:%d, N:%d\n",
-										loop_i+1, ts->pre_finger_data[loop_i][0] * ts->widthFactor >> SHIFTBITS,
-										ts->pre_finger_data[loop_i][1] * ts->heightFactor >> SHIFTBITS, Last_EN_NoiseFilter);
-									}
-									else
-									{
-										I("status: Raw:F:%02d Up, X:%d, Y:%d, N:%d\n",
-										loop_i+1, ts->pre_finger_data[loop_i][0],
-										ts->pre_finger_data[loop_i][1], Last_EN_NoiseFilter);
-									}
-								}
-							}
-						}
-					}
-
-				}else if ((tpd_key_old != 0x00)&&(tpd_key == 0x00)) {
-					//temp_x[0] = 0xFFFF;
-					//temp_y[0] = 0xFFFF;
-					//temp_x[1] = 0xFFFF;
-					//temp_y[1] = 0xFFFF;
-					himax_ts_button_func(tpd_key,ts);
-					finger_on = 0;
+			if (x >= 0 && x <= ts->pdata->abs_x_max
+			&& y >= 0 && y <= ts->pdata->abs_y_max) {
+				finger_num--;
+				if ((((ts->debug_log_level & BIT(3)) > 0)
+				&& (old_finger >> i == 0))
+				&& (ts->useScreenRes)) {
+					I("status:Screen:F:%02d", i + 1);
+					I("Down,X:%d,Y:%d,W:%d,N:%d\n",
+					x * ts->widthFactor >> SHIFTBITS,
+					y * ts->heightFactor >> SHIFTBITS,
+					w, EN_NoiseFilter);
+				} else if ((((ts->debug_log_level & BIT(3)) > 0)
+				&& (old_finger >> i == 0))
+				&& !(ts->useScreenRes)) {
+					I("status:Raw:F:%02d", i + 1);
+					I("Down,X:%d,Y:%d,W:%d,N:%d\n",
+					x, y, w, EN_NoiseFilter);
 				}
-			input_report_key(ts->input_dev, BTN_TOUCH, finger_on);
-			input_sync(ts->input_dev);
-		} else if (hx_point_num == 0){
-			if(AA_press)
-				{
-				// leave event
-				finger_on = 0;
-				AA_press = 0;
-				if (ts->protocol_type == PROTOCOL_TYPE_A)
+
+				if (ts->protocol_type == PROTOCOL_TYPE_B)
+					input_mt_slot(ts->input_dev, i);
+
+				input_report_abs(ts->input_dev,
+				ABS_MT_TOUCH_MAJOR, w);
+				input_report_abs(ts->input_dev,
+				ABS_MT_WIDTH_MAJOR, w);
+				input_report_abs(ts->input_dev,
+				ABS_MT_PRESSURE, w);
+				input_report_abs(ts->input_dev,
+				ABS_MT_POSITION_X, x);
+				input_report_abs(ts->input_dev,
+				ABS_MT_POSITION_Y, y);
+
+				if (ts->protocol_type == PROTOCOL_TYPE_A) {
+					input_report_abs(ts->input_dev,
+					ABS_MT_TRACKING_ID, i);
 					input_mt_sync(ts->input_dev);
-
-				for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) {
-						if (((ts->pre_finger_mask >> loop_i) & 1) == 1) {
-							if (ts->protocol_type == PROTOCOL_TYPE_B) {
-								input_mt_slot(ts->input_dev, loop_i);
-								input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0);
-							}
-						}
-					}
-				if (ts->pre_finger_mask > 0) {
-					for (loop_i = 0; loop_i < ts->nFinger_support && (ts->debug_log_level & BIT(3)) > 0; loop_i++) {
-						if (((ts->pre_finger_mask >> loop_i) & 1) == 1) {
-							if (ts->useScreenRes) {
-								I("status:%X, Screen:F:%02d Up, X:%d, Y:%d, N:%d\n", 0, loop_i+1, ts->pre_finger_data[loop_i][0] * ts->widthFactor >> SHIFTBITS,
-									ts->pre_finger_data[loop_i][1] * ts->heightFactor >> SHIFTBITS, Last_EN_NoiseFilter);
-							} else {
-								I("status:%X, Raw:F:%02d Up, X:%d, Y:%d, N:%d\n",0, loop_i+1, ts->pre_finger_data[loop_i][0],ts->pre_finger_data[loop_i][1], Last_EN_NoiseFilter);
-							}
-						}
-					}
-					ts->pre_finger_mask = 0;
+				} else {
+					ts->last_slot = i;
+					input_mt_report_slot_state
+					(ts->input_dev,
+					MT_TOOL_FINGER, 1);
 				}
 
-				if (ts->first_pressed == 1) {
+				if (!ts->first_pressed) {
+					ts->first_pressed = 1;
+					I("S1@%d, %d\n", x, y);
+				}
+
+				ts->pre_finger_data[i][0] = x;
+				ts->pre_finger_data[i][1] = y;
+
+				if (ts->debug_log_level & BIT(1)) {
+					I("Finger %d=> X:%d,Y:%d,W:%d,",
+					i + 1, x, y, w);
+					I("Z:%d,F:%d,N:%d\n",
+					w, i + 1, EN_NoiseFilter);
+				}
+				ts->pre_finger_mask =
+				ts->pre_finger_mask + (1 << i);
+
+			} else {
+				if (ts->protocol_type == PROTOCOL_TYPE_B) {
+					input_mt_slot(ts->input_dev, i);
+					input_mt_report_slot_state
+					(ts->input_dev, MT_TOOL_FINGER, 0);
+				}
+				if (i == 0 && ts->first_pressed == 1) {
 					ts->first_pressed = 2;
-					I("E1@%d, %d\n",ts->pre_finger_data[0][0] , ts->pre_finger_data[0][1]);
+					I("E1@%d, %d\n",
+					ts->pre_finger_data[0][0],
+					ts->pre_finger_data[0][1]);
 				}
-
-				if (ts->debug_log_level & BIT(1))
-					I("All Finger leave\n");
-
+				if ((((ts->debug_log_level & BIT(3)) > 0)
+				&& (old_finger >> i == 1))
+				&& (ts->useScreenRes)) {
+					I("status:Screen:F:%02d,Up,X:%d,Y:%d\n",
+					i + 1, ts->pre_finger_data[i][0]
+					* ts->widthFactor >> SHIFTBITS,
+					ts->pre_finger_data[i][1]
+					* ts->heightFactor >> SHIFTBITS);
+				} else if ((((ts->debug_log_level & BIT(3)) > 0)
+				&& (old_finger >> i == 1))
+				&& !(ts->useScreenRes)) {
+					I("status:Raw:F:%02d,Up,X:%d,Y:%d\n",
+					i + 1, ts->pre_finger_data[i][0],
+					ts->pre_finger_data[i][1]);
+				}
 			}
-			else if (tpd_key != 0x00) {
-				himax_ts_button_func(tpd_key,ts);
-				finger_on = 1;
-			}
-			else if ((tpd_key_old != 0x00)&&(tpd_key == 0x00)) {
-				himax_ts_button_func(tpd_key,ts);
-				finger_on = 0;
-			}
-			input_report_key(ts->input_dev, BTN_TOUCH, finger_on);
-			input_sync(ts->input_dev);
 		}
-		tpd_key_old = tpd_key;
-		Last_EN_NoiseFilter = EN_NoiseFilter;
+		input_report_key(ts->input_dev, BTN_TOUCH, finger_on);
+		input_sync(ts->input_dev);
+	} else if ((hx_point_num != 0)
+		&& ((tpd_key_old != 0x00) && (tpd_key == 0x00))) {
+		/*temp_x[0] = 0xFFFF;*/
+		/*temp_y[0] = 0xFFFF;*/
+		/*temp_x[1] = 0xFFFF;*/
+		/*temp_y[1] = 0xFFFF;*/
+		himax_ts_button_func(tpd_key, ts);
+		finger_on = 0;
+		input_report_key(ts->input_dev, BTN_TOUCH, finger_on);
+		input_sync(ts->input_dev);
+	} else if (hx_point_num == 0) {
+		if (AA_press) {
+			/*leave event*/
+			finger_on = 0;
+			AA_press = 0;
+			if (ts->protocol_type == PROTOCOL_TYPE_A)
+				input_mt_sync(ts->input_dev);
+
+			for (i = 0 ; i < ts->nFinger_support ; i++) {
+				if ((((ts->pre_finger_mask >> i) & 1) == 1)
+				&& (ts->protocol_type == PROTOCOL_TYPE_B)) {
+					input_mt_slot(ts->input_dev, i);
+					input_mt_report_slot_state
+					(ts->input_dev, MT_TOOL_FINGER, 0);
+				}
+			}
+			if (ts->pre_finger_mask > 0) {
+				for (i = 0; i < ts->nFinger_support
+				&& (ts->debug_log_level & BIT(3)) > 0; i++) {
+					if ((((ts->pre_finger_mask
+					>> i) & 1) == 1)
+					&& (ts->useScreenRes)) {
+						I("status:%X,", 0);
+						I("Screen:F:%02d,", i + 1);
+						I("Up,X:%d,Y:%d\n",
+						ts->pre_finger_data[i][0]
+						* ts->widthFactor >> SHIFTBITS,
+						ts->pre_finger_data[i][1]
+						* ts->heightFactor >> SHIFTBITS
+						);
+					} else if ((((ts->pre_finger_mask
+					>> i) & 1) == 1)
+					&& !(ts->useScreenRes)) {
+						I("status:%X,", 0);
+						I("Screen:F:%02d,", i + 1);
+						I("Up,X:%d,Y:%d\n",
+						ts->pre_finger_data[i][0],
+						ts->pre_finger_data[i][1]);
+					}
+				}
+				ts->pre_finger_mask = 0;
+			}
+
+			if (ts->first_pressed == 1) {
+				ts->first_pressed = 2;
+				I("E1@%d, %d\n", ts->pre_finger_data[0][0],
+				ts->pre_finger_data[0][1]);
+			}
+
+			if (ts->debug_log_level & BIT(1))
+				I("All Finger leave\n");
+
+#ifdef HX_TP_PROC_DIAG
+				/*coordinate dump start*/
+				if (coordinate_dump_enable == 1) {
+					do_gettimeofday(&t);
+					time_to_tm(t.tv_sec, 0, &broken);
+					snprintf(&coordinate_char[0], 15,
+					"%2d:%2d:%2d:%lu,", broken.tm_hour,
+					broken.tm_min, broken.tm_sec,
+					t.tv_usec / 1000);
+
+					snprintf(&coordinate_char[15], 10,
+					"Touch up!");
+
+					coordinate_fn->f_op->write
+					(coordinate_fn, &coordinate_char[0],
+					15 + (ic_data->HX_MAX_PT + 5)
+					* 2 * sizeof(char) * 5 + 2,
+					&coordinate_fn->f_pos);
+				}
+				/*coordinate dump end*/
+#endif
+		} else if (tpd_key != 0x00) {
+			himax_ts_button_func(tpd_key, ts);
+			finger_on = 1;
+		} else if ((tpd_key_old != 0x00) && (tpd_key == 0x00)) {
+			himax_ts_button_func(tpd_key, ts);
+			finger_on = 0;
+		}
+		input_report_key(ts->input_dev, BTN_TOUCH, finger_on);
+		input_sync(ts->input_dev);
+	}
+	tpd_key_old = tpd_key;
 
 workqueue_out:
 	return;
@@ -1310,7 +1348,7 @@
 	I("%s: Now reset the Touch chip.\n", __func__);
 
 #ifdef HX_RST_PIN_FUNC
-	himax_HW_reset(true,false);
+	himax_HW_reset(true, false);
 #endif
 
 	goto workqueue_out;
@@ -1329,6 +1367,7 @@
 static void himax_cable_tp_status_handler_func(int connect_status)
 {
 	struct himax_ts_data *ts;
+
 	I("Touch: cable change to %d\n", connect_status);
 	ts = private_ts;
 	if (ts->cable_config) {
@@ -1342,18 +1381,23 @@
 					ts->usb_connected = 0x00;
 				}
 
-				i2c_himax_master_write(ts->client, ts->cable_config,
-					sizeof(ts->cable_config), HIMAX_I2C_RETRY_TIMES);
+				i2c_himax_master_write(ts->client,
+				ts->cable_config,
+				sizeof(ts->cable_config),
+				HIMAX_I2C_RETRY_TIMES);
 
-				I("%s: Cable status change: 0x%2.2X\n", __func__, ts->cable_config[1]);
+				I("%s: Cable status change: 0x%2.2X\n",
+				__func__, ts->cable_config[1]);
 			} else
-				I("%s: Cable status is the same as previous one, ignore.\n", __func__);
+				I("%s: Cable status is same, ignore.\n",
+				__func__);
 		} else {
 			if (connect_status)
 				ts->usb_connected = 0x01;
 			else
 				ts->usb_connected = 0x00;
-			I("%s: Cable status remembered: 0x%2.2X\n", __func__, ts->usb_connected);
+			I("%s: Cable status remembered: 0x%2.2X\n",
+			__func__, ts->usb_connected);
 		}
 	}
 }
@@ -1373,16 +1417,20 @@
 	struct himax_ts_data *ts;
 	u32 connect_status = 0;
 
-	connect_status = USB_Flag;//upmu_is_chr_det();
+	connect_status = USB_Flag;/*upmu_is_chr_det();*/
 	ts = private_ts;
-	//I("Touch: cable status=%d, cable_config=%p, usb_connected=%d \n", connect_status,ts->cable_config, ts->usb_connected);
+	/*I("Touch: cable status=%d, cable_config=%p,
+	usb_connected=%d\n", connect_status,
+	ts->cable_config, ts->usb_connected);*/
+
 	if (ts->cable_config) {
 		if ((!!connect_status) != ts->usb_connected) {
-			//notify USB plug/unplug
-			// 0x9008_8060 ==> 0x0000_0000/0001
-			tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x60;
-			tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00;
-			
+			/*notify USB plug/unplug*/
+			/*0x9008_8060 ==> 0x0000_0000/0001*/
+			tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+			tmp_addr[1] = 0x80; tmp_addr[0] = 0x60;
+			tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+			tmp_data[1] = 0x00;
 			if (!!connect_status) {
 				tmp_data[0] = 0x01;
 				ts->usb_connected = 0x01;
@@ -1393,10 +1441,13 @@
 
 			himax_flash_write_burst(ts->client, tmp_addr, tmp_data);
 
-			I("%s: Cable status change: 0x%2.2X\n", __func__, ts->usb_connected);
-			}
-		//else
-			//I("%s: Cable status is the same as previous one, ignore.\n", __func__);
+			I("%s: Cable status change: 0x%2.2X\n",
+			__func__, ts->usb_connected);
+		}
+		/*else*/
+			/*I("%s: Cable status is the same as previous one,
+			ignore.\n", __func__);*/
+
 	}
 }
 #endif
@@ -1417,52 +1468,52 @@
 #endif
 
 #ifdef HX_SMART_WAKEUP
-void himax_set_SMWP_func(struct i2c_client *client,uint8_t SMWP_enable)
+void himax_set_SMWP_func(struct i2c_client *client, uint8_t SMWP_enable)
 {
 	uint8_t tmp_data[4];
 
-	if(SMWP_enable)
-	{
-		SMWP_bit_retry:
+	if (SMWP_enable) {
+SMWP_bit_retry:
 		himax_set_SMWP_enable(client, SMWP_enable);
 		msleep(20);
-		himax_get_SMWP_enable(client,tmp_data);
-		I("%s: Read SMWP bit data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
-			,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
-		if(tmp_data[0]!= 0x01)
-			{
-				I("%s: retry SMWP bit write data[0]=%x  \n",__func__,tmp_data[0]);
-				goto SMWP_bit_retry;
-			}
+		himax_get_SMWP_enable(client, tmp_data);
+I("%s: Read SMWP bit data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n",
+__func__, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]);
+
+		if (tmp_data[0] != 0x01) {
+			I("%s: retry SMWP bit write data[0]=%x\n",
+			__func__, tmp_data[0]);
+			goto SMWP_bit_retry;
+		}
 	}
 }
 
 static void himax_SMWP_work(struct work_struct *work)
 {
-	struct himax_ts_data *ts = container_of(work, struct himax_ts_data,
-							smwp_work.work);
+	struct himax_ts_data *ts =
+	container_of(work, struct himax_ts_data, smwp_work.work);
 	I(" %s in", __func__);
 
-	himax_set_SMWP_func(ts->client,ts->SMWP_enable);
+	himax_set_SMWP_func(ts->client, ts->SMWP_enable);
 
 }
 #endif
 
-#ifdef  HX_TP_PROC_FLASH_DUMP
+#ifdef HX_TP_PROC_FLASH_DUMP
 static void himax_ts_flash_work_func(struct work_struct *work)
 {
 	himax_ts_flash_func();
 }
 #endif
 
-#ifdef  HX_TP_PROC_DIAG
+#ifdef HX_TP_PROC_DIAG
 static void himax_ts_diag_work_func(struct work_struct *work)
 {
 	himax_ts_diag_func();
 }
 #endif
 
-void himax_ts_init(struct himax_ts_data *ts)
+bool himax_ts_init(struct himax_ts_data *ts)
 {
 	int ret = 0, err = 0;
 	struct himax_i2c_platform_data *pdata;
@@ -1476,15 +1527,14 @@
 	/* Set pinctrl in active state */
 	if (ts->ts_pinctrl) {
 		ret = pinctrl_select_state(ts->ts_pinctrl,
-					ts->pinctrl_state_active);
-		if (ret < 0) {
-			E("Failed to set pin in active state %d",ret);
-		}
+		ts->pinctrl_state_active);
+		if (ret < 0)
+			E("Failed to set pin in active state %d", ret);
 	}
 
 	himax_burst_enable(client, 0);
 
-	//Get Himax IC Type / FW information / Calculate the point number
+	/*Get Himax IC Type / FW information / Calculate the point number */
 	if (himax_check_chip_version(ts->client) == false) {
 		E("Himax chip doesn NOT EXIST");
 		goto err_ic_package_failed;
@@ -1496,10 +1546,9 @@
 
 	if (pdata->virtual_key)
 		ts->button = pdata->virtual_key;
-#ifdef  HX_TP_PROC_FLASH_DUMP
+#ifdef HX_TP_PROC_FLASH_DUMP
 	ts->flash_wq = create_singlethread_workqueue("himax_flash_wq");
-	if (!ts->flash_wq)
-	{
+	if (!ts->flash_wq) {
 		E("%s: create flash workqueue failed\n", __func__);
 		err = -ENOMEM;
 		goto err_create_wq_failed;
@@ -1511,10 +1560,9 @@
 	setFlashBuffer();
 #endif
 
-#ifdef  HX_TP_PROC_DIAG
+#ifdef HX_TP_PROC_DIAG
 	ts->himax_diag_wq = create_singlethread_workqueue("himax_diag");
-	if (!ts->himax_diag_wq)
-	{
+	if (!ts->himax_diag_wq) {
 		E("%s: create diag workqueue failed\n", __func__);
 		err = -ENOMEM;
 		goto err_create_wq_failed;
@@ -1526,40 +1574,42 @@
 
 #ifdef HX_AUTO_UPDATE_FW
 	I(" %s in", __func__);
-	if(i_update_FW() == false)
-		I("NOT Have new FW=NOT UPDATE=\n");
+	if (i_update_FW() <= 0)
+		I("FW NOT UPDATE=\n");
 	else
 		I("Have new FW=UPDATE=\n");
 #endif
 
-	//Himax Power On and Load Config
+	/*Himax Power On and Load Config*/
 	if (himax_loadSensorConfig(client, pdata) < 0) {
-		E("%s: Load Sesnsor configuration failed, unload driver.\n", __func__);
+		E("%s: Load Sesnsor config failed,unload driver.\n",
+		__func__);
 		goto err_detect_failed;
 	}
 
 	calculate_point_number();
 #ifdef HX_TP_PROC_DIAG
-	setXChannel(ic_data->HX_RX_NUM); // X channel
-	setYChannel(ic_data->HX_TX_NUM); // Y channel
+	setXChannel(ic_data->HX_RX_NUM); /*X channel*/
+	setYChannel(ic_data->HX_TX_NUM); /*Y channel*/
 
 	setMutualBuffer();
 	setMutualNewBuffer();
 	setMutualOldBuffer();
 	if (getMutualBuffer() == NULL) {
 		E("%s: mutual buffer allocate fail failed\n", __func__);
-		return;
+		return false;
 	}
 #ifdef HX_TP_PROC_2T2R
-	if(Is_2T2R){
-		setXChannel_2(ic_data->HX_RX_NUM_2); // X channel
-		setYChannel_2(ic_data->HX_TX_NUM_2); // Y channel
+	if (Is_2T2R) {
+		setXChannel_2(ic_data->HX_RX_NUM_2); /*X channel*/
+		setYChannel_2(ic_data->HX_TX_NUM_2); /*Y channel*/
 
 		setMutualBuffer_2();
 
 		if (getMutualBuffer_2() == NULL) {
-			E("%s: mutual buffer 2 allocate fail failed\n", __func__);
-			return;
+			E("%s: mutual buffer 2 allocate fail failed\n",
+			__func__);
+			return false;
 		}
 	}
 #endif
@@ -1572,7 +1622,7 @@
 	ts->x_channel = ic_data->HX_RX_NUM;
 	ts->y_channel = ic_data->HX_TX_NUM;
 	ts->nFinger_support = ic_data->HX_MAX_PT;
-	//calculate the i2c data size
+	/*calculate the i2c data size*/
 	calcDataSize(ts->nFinger_support);
 	I("%s: calcDataSize complete\n", __func__);
 #ifdef CONFIG_OF
@@ -1584,14 +1634,13 @@
 	pdata->cable_config[1] = 0x00;
 #endif
 	ts->suspended = false;
-#if defined(HX_USB_DETECT)||defined(HX_USB_DETECT2)
+#if defined(HX_USB_DETECT) || defined(HX_USB_DETECT2)
 	ts->usb_connected = 0x00;
 	ts->cable_config = pdata->cable_config;
 #endif
 	ts->protocol_type = pdata->protocol_type;
 	I("%s: Use Protocol Type %c\n", __func__,
 	ts->protocol_type == PROTOCOL_TYPE_A ? 'A' : 'B');
-
 	ret = himax_input_register(ts);
 	if (ret) {
 		E("%s: Unable to register %s input device\n",
@@ -1599,8 +1648,9 @@
 		goto err_input_register_device_failed;
 	}
 #ifdef HX_SMART_WAKEUP
-	ts->SMWP_enable=0;
-	wake_lock_init(&ts->ts_SMWP_wake_lock, WAKE_LOCK_SUSPEND, HIMAX_common_NAME);
+	ts->SMWP_enable = 0;
+	wakeup_source_init(&ts->ts_SMWP_wake_lock,
+	WAKE_LOCK_SUSPEND, HIMAX_common_NAME);
 
 	ts->himax_smwp_wq = create_singlethread_workqueue("HMX_SMWP_WORK");
 	if (!ts->himax_smwp_wq) {
@@ -1611,7 +1661,7 @@
 	INIT_DELAYED_WORK(&ts->smwp_work, himax_SMWP_work);
 #endif
 #ifdef HX_HIGH_SENSE
-	ts->HSEN_enable=0;
+	ts->HSEN_enable = 0;
 	ts->himax_hsen_wq = create_singlethread_workqueue("HMX_HSEN_WORK");
 	if (!ts->himax_hsen_wq) {
 		E(" allocate himax_hsen_wq failed\n");
@@ -1633,7 +1683,7 @@
 	err = himax_ts_register_interrupt(ts->client);
 	if (err)
 		goto err_register_interrupt_failed;
-	return;
+	return true;
 
 err_register_interrupt_failed:
 #ifdef HX_HIGH_SENSE
@@ -1641,26 +1691,26 @@
 #endif
 #ifdef HX_SMART_WAKEUP
 err_smwp_wq_failed:
-	wake_lock_destroy(&ts->ts_SMWP_wake_lock);
+	wakeup_source_trash(&ts->ts_SMWP_wake_lock);
 #endif
 err_input_register_device_failed:
 	input_free_device(ts->input_dev);
 err_detect_failed:
-#ifdef  HX_TP_PROC_FLASH_DUMP
+#ifdef HX_TP_PROC_FLASH_DUMP
 err_create_wq_failed:
 #endif
 err_ic_package_failed:
-
-return;
+return false;
 }
 
-int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_id *id)
+int himax_chip_common_probe(struct i2c_client *client,
+const struct i2c_device_id *id)
 {
 	int err = 0;
 	struct himax_ts_data *ts;
 	struct himax_i2c_platform_data *pdata;
 
-	//Check I2C functionality
+	/*Check I2C functionality*/
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
 		E("%s: i2c check functionality error\n", __func__);
 		err = -ENODEV;
@@ -1677,6 +1727,7 @@
 	i2c_set_clientdata(client, ts);
 	ts->client = client;
 	ts->dev = &client->dev;
+	mutex_init(&ts->rw_lock);
 
 	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
 	if (pdata == NULL) { /*Allocate Platform data space*/
@@ -1691,7 +1742,8 @@
 	}
 
 #ifdef CONFIG_OF
-	if (client->dev.of_node) { /*DeviceTree Init Platform_data*/
+	/*DeviceTree Init Platform_data*/
+	if (client->dev.of_node) {
 		err = himax_parse_dt(ts, pdata);
 		if (err < 0) {
 			I(" pdata is NULL for DT\n");
@@ -1704,12 +1756,11 @@
 	ts->rst_gpio = pdata->gpio_reset;
 #endif
 
-himax_gpio_power_config(ts->client, pdata);
+	himax_gpio_power_config(ts->client, pdata);
 
 	err = himax_ts_pinctrl_init(ts);
-	if (err || ts->ts_pinctrl == NULL) {
+	if (err || ts->ts_pinctrl == NULL)
 		E(" Pinctrl init failed\n");
-	}
 
 #ifndef CONFIG_OF
 	if (pdata->power) {
@@ -1736,7 +1787,7 @@
 	}
 #endif
 
-    return 0;
+	return 0;
 
 #ifdef CONFIG_FB
 err_fb_notif_wq_create:
@@ -1783,8 +1834,10 @@
 	himax_touch_proc_deinit();
 #endif
 #ifdef CONFIG_FB
-	if (fb_unregister_client(&ts->fb_notif))
-		dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n");
+	if (fb_unregister_client(&ts->fb_notif)) {
+		dev_err(&client->dev,
+		"Error occurred while unregistering fb_notifier.\n");
+	}
 #endif
 
 	if (!ts->use_irq)
@@ -1810,7 +1863,7 @@
 		}
 	}
 #ifdef HX_SMART_WAKEUP
-		wake_lock_destroy(&ts->ts_SMWP_wake_lock);
+		wakeup_source_trash(&ts->ts_SMWP_wake_lock);
 #endif
 	kfree(ts);
 
@@ -1822,38 +1875,36 @@
 {
 	int ret;
 
-	if(ts->suspended)
-	{
-		I("%s: Already suspended. Skipped. \n", __func__);
+	if (ts->suspended) {
+		I("%s: Already suspended. Skipped.\n", __func__);
 		return 0;
-	}
-	else
-	{
+
+	} else {
 		ts->suspended = true;
-		I("%s: enter \n", __func__);
+		I("%s: enter\n", __func__);
 	}
 
 #ifdef HX_TP_PROC_FLASH_DUMP
-	if (getFlashDumpGoing())
-	{
-		I("[himax] %s: Flash dump is going, reject suspend\n",__func__);
+	if (getFlashDumpGoing()) {
+		I("[himax] %s: Flash dump is going,reject suspend\n",
+		__func__);
 		return 0;
 	}
 #endif
 #ifdef HX_TP_PROC_HITOUCH
-	if(hitouch_is_connect)
-	{
-		I("[himax] %s: Hitouch connect, reject suspend\n",__func__);
+	if (hitouch_is_connect) {
+		I("[himax] %s: Hitouch connect,reject suspend\n",
+		__func__);
 		return 0;
 	}
 #endif
 #ifdef HX_SMART_WAKEUP
-	if(ts->SMWP_enable)
-	{
+	if (ts->SMWP_enable) {
 		atomic_set(&ts->suspend_mode, 1);
 		ts->pre_finger_mask = 0;
-		FAKE_POWER_KEY_SEND=false;
-		I("[himax] %s: SMART_WAKEUP enable, reject suspend\n",__func__);
+		FAKE_POWER_KEY_SEND = false;
+		I("[himax] %s: SMART_WAKEUP enable,reject suspend\n",
+		__func__);
 		return 0;
 	}
 #endif
@@ -1864,19 +1915,18 @@
 	if (!ts->use_irq) {
 		ret = cancel_work_sync(&ts->work);
 		if (ret)
-			himax_int_enable(ts->client->irq,1);
+			himax_int_enable(ts->client->irq, 1);
 	}
 
-	//ts->first_pressed = 0;
+	/*ts->first_pressed = 0;*/
 	atomic_set(&ts->suspend_mode, 1);
 	ts->pre_finger_mask = 0;
 
 	if (ts->ts_pinctrl) {
 		ret = pinctrl_select_state(ts->ts_pinctrl,
 				ts->pinctrl_state_suspend);
-		if (ret < 0) {
+		if (ret < 0)
 			E("Failed to get idle pinctrl state %d\n", ret);
-		}
 	}
 
 	if (ts->pdata->powerOff3V3 && ts->pdata->power)
@@ -1889,20 +1939,16 @@
 {
 	int retval;
 
-	I("%s: enter \n", __func__);
+	I("%s: enter\n", __func__);
 
 	if (ts->pdata->powerOff3V3 && ts->pdata->power)
 		ts->pdata->power(1);
-		
-		
-		/*************************************/
+
 		if (ts->protocol_type == PROTOCOL_TYPE_A)
-		input_mt_sync(ts->input_dev);
+			input_mt_sync(ts->input_dev);
 		input_report_key(ts->input_dev, BTN_TOUCH, 0);
 		input_sync(ts->input_dev);
-		/*************************************/
-		
-		
+
 	if (ts->ts_pinctrl) {
 		retval = pinctrl_select_state(ts->ts_pinctrl,
 				ts->pinctrl_state_active);
@@ -1914,7 +1960,7 @@
 
 	atomic_set(&ts->suspend_mode, 0);
 
-	himax_int_enable(ts->client->irq,1);
+	himax_int_enable(ts->client->irq, 1);
 
 	ts->suspended = false;
 #if defined(HX_USB_DETECT2)
@@ -1922,10 +1968,12 @@
 	himax_cable_detect_func();
 #endif
 #ifdef HX_SMART_WAKEUP
-	queue_delayed_work(ts->himax_smwp_wq, &ts->smwp_work, msecs_to_jiffies(1000));
+	queue_delayed_work(ts->himax_smwp_wq,
+	&ts->smwp_work, msecs_to_jiffies(1000));
 #endif
 #ifdef HX_HIGH_SENSE
-	queue_delayed_work(ts->himax_hsen_wq, &ts->hsen_work, msecs_to_jiffies(1000));
+	queue_delayed_work(ts->himax_hsen_wq,
+	&ts->hsen_work, msecs_to_jiffies(1000));
 #endif
 	return 0;
 err_pinctrl_select_resume:
diff --git a/drivers/input/touchscreen/hxchipset/himax_common.h b/drivers/input/touchscreen/hxchipset/himax_common.h
index 27ce9aa..c4e24ba 100644
--- a/drivers/input/touchscreen/hxchipset/himax_common.h
+++ b/drivers/input/touchscreen/hxchipset/himax_common.h
@@ -16,9 +16,13 @@
 #ifndef HIMAX_COMMON_H
 #define HIMAX_COMMON_H
 
+#include "himax_platform.h"
+
 #include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <asm/atomic.h>
+/*#include <asm/uaccess.h>*/
+/*#include <asm/atomic.h>*/
+#include <linux/uaccess.h>
+#include <linux/atomic.h>
 
 #include <linux/delay.h>
 #include <linux/i2c.h>
@@ -36,7 +40,6 @@
 #include <linux/buffer_head.h>
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
-#include "himax_platform.h"
 
 #if defined(CONFIG_FB)
 #include <linux/notifier.h>
@@ -48,7 +51,7 @@
 #ifdef CONFIG_OF
 #include <linux/of_gpio.h>
 #endif
-#define HIMAX_DRIVER_VER "0.2.4.0"
+#define HIMAX_DRIVER_VER "0.3.1.0"
 
 #define FLASH_DUMP_FILE "/data/user/Flash_Dump.bin"
 #define DIAG_COORDINATE_FILE "/sdcard/Coordinate_Dump.csv"
@@ -62,39 +65,39 @@
 #define HX_TP_PROC_SELF_TEST
 #define HX_TP_PROC_RESET
 #define HX_TP_PROC_SENSE_ON_OFF
-//#define HX_TP_PROC_2T2R
+/*#define HX_TP_PROC_2T2R*/
 
 int himax_touch_proc_init(void);
 void himax_touch_proc_deinit(void);
 #endif
 
-//===========Himax Option function=============
-//#define HX_RST_PIN_FUNC
-//#define HX_AUTO_UPDATE_FW
-//#define HX_HIGH_SENSE
-//#define HX_SMART_WAKEUP
-//#define HX_USB_DETECT
-//#define HX_ESD_WORKAROUND
-//#define HX_USB_DETECT2
+/*===========Himax Option function=============*/
+/*#define HX_RST_PIN_FUNC*/
+#define HX_AUTO_UPDATE_FW
+/*#define HX_HIGH_SENSE*/
+/*#define HX_SMART_WAKEUP*/
+/*#define HX_USB_DETECT*/
+/*#define HX_ESD_WORKAROUND*/
+/*#define HX_USB_DETECT2*/
+/*#define HX_EN_SEL_BUTTON*//* Support Self Virtual key ,default is close*/
+#define HX_EN_MUT_BUTTON/*  Support Mutual Virtual Key ,default is close*/
+/*#define HX_EN_CHECK_PATCH*/
 
-//#define HX_EN_SEL_BUTTON		       // Support Self Virtual key		,default is close
-#define HX_EN_MUT_BUTTON		    // Support Mutual Virtual Key	,default is close
+#define HX_KEY_MAX_COUNT  4
+#define DEFAULT_RETRY_CNT 3
 
-#define HX_KEY_MAX_COUNT             4			
-#define DEFAULT_RETRY_CNT            3
-
-#define HX_VKEY_0   KEY_BACK
-#define HX_VKEY_1   KEY_HOME
-#define HX_VKEY_2   KEY_RESERVED
-#define HX_VKEY_3   KEY_RESERVED
-#define HX_KEY_ARRAY    {HX_VKEY_0, HX_VKEY_1, HX_VKEY_2, HX_VKEY_3}
+#define HX_VKEY_0 KEY_BACK
+#define HX_VKEY_1 KEY_HOME
+#define HX_VKEY_2 KEY_RESERVED
+#define HX_VKEY_3 KEY_RESERVED
+#define HX_KEY_ARRAY {HX_VKEY_0, HX_VKEY_1, HX_VKEY_2, HX_VKEY_3}
 
 #define SHIFTBITS 5
-//#define FLASH_SIZE 131072
-#define  FW_SIZE_60k 	61440
-#define  FW_SIZE_64k 	65536
-#define  FW_SIZE_124k 	126976
-#define  FW_SIZE_128k 	131072
+/*#define FLASH_SIZE 131072*/
+#define  FW_SIZE_60k  61440
+#define  FW_SIZE_64k  65536
+#define  FW_SIZE_124k 126976
+#define  FW_SIZE_128k 131072
 
 struct himax_ic_data {
 	int vendor_fw_ver;
@@ -183,12 +186,12 @@
 	bool suspended;
 	bool probe_done;
 	struct mutex fb_mutex;
+	struct mutex rw_lock;
 	atomic_t suspend_mode;
 	uint8_t x_channel;
 	uint8_t y_channel;
 	uint8_t useScreenRes;
 	uint8_t diag_command;
-	
 	uint8_t protocol_type;
 	uint8_t first_pressed;
 	uint8_t coord_data_size;
@@ -198,11 +201,9 @@
 	uint8_t nFinger_support;
 	uint8_t irq_enabled;
 	uint8_t diag_self[50];
-	
 	uint16_t finger_pressed;
 	uint16_t last_slot;
 	uint16_t pre_finger_mask;
-
 	uint32_t debug_log_level;
 	uint32_t widthFactor;
 	uint32_t heightFactor;
@@ -214,20 +215,20 @@
 	uint32_t pl_x_max;
 	uint32_t pl_y_min;
 	uint32_t pl_y_max;
-	
+
 	int use_irq;
 	int (*power)(int on);
 	int pre_finger_data[10][2];
-	
+
 	struct device *dev;
 	struct workqueue_struct *himax_wq;
 	struct work_struct work;
 	struct input_dev *input_dev;
 	struct hrtimer timer;
 	struct i2c_client *client;
-	struct himax_i2c_platform_data *pdata;	
+	struct himax_i2c_platform_data *pdata;
 	struct himax_virtual_key *button;
-	
+
 #if defined(CONFIG_FB)
 	struct notifier_block fb_notif;
 #elif defined(CONFIG_HAS_EARLYSUSPEND)
@@ -235,8 +236,8 @@
 #endif
 
 #ifdef HX_TP_PROC_FLASH_DUMP
-	struct workqueue_struct 			*flash_wq;
-	struct work_struct 					flash_work;
+	struct workqueue_struct *flash_wq;
+	struct work_struct flash_work;
 #endif
 
 #ifdef HX_RST_PIN_FUNC
@@ -250,7 +251,7 @@
 #ifdef HX_SMART_WAKEUP
 	uint8_t SMWP_enable;
 	uint8_t gesture_cust_en[16];
-	struct wake_lock ts_SMWP_wake_lock;
+	struct wakeup_source ts_SMWP_wake_lock;
 	struct workqueue_struct *himax_smwp_wq;
 	struct delayed_work smwp_work;
 #endif
@@ -261,7 +262,7 @@
 	struct delayed_work hsen_work;
 #endif
 
-#if defined(HX_USB_DETECT)||defined(HX_USB_DETECT2)
+#if defined(HX_USB_DETECT) || defined(HX_USB_DETECT2)
 	uint8_t usb_connected;
 	uint8_t *cable_config;
 #endif
@@ -273,30 +274,30 @@
 	struct pinctrl_state *pinctrl_state_release;
 };
 
-#define HX_CMD_NOP					 0x00	
-#define HX_CMD_SETMICROOFF			 0x35	
-#define HX_CMD_SETROMRDY			 0x36	
-#define HX_CMD_TSSLPIN				 0x80	
-#define HX_CMD_TSSLPOUT 			 0x81	
-#define HX_CMD_TSSOFF				 0x82	
-#define HX_CMD_TSSON				 0x83	
-#define HX_CMD_ROE					 0x85	
-#define HX_CMD_RAE					 0x86	
-#define HX_CMD_RLE					 0x87	
-#define HX_CMD_CLRES				 0x88	
-#define HX_CMD_TSSWRESET			 0x9E	
-#define HX_CMD_SETDEEPSTB			 0xD7	
-#define HX_CMD_SET_CACHE_FUN		 0xDD	
-#define HX_CMD_SETIDLE				 0xF2	
-#define HX_CMD_SETIDLEDELAY 		 0xF3	
-#define HX_CMD_SELFTEST_BUFFER		 0x8D	
+#define HX_CMD_NOP					 0x00
+#define HX_CMD_SETMICROOFF			 0x35
+#define HX_CMD_SETROMRDY			 0x36
+#define HX_CMD_TSSLPIN				 0x80
+#define HX_CMD_TSSLPOUT				 0x81
+#define HX_CMD_TSSOFF				 0x82
+#define HX_CMD_TSSON				 0x83
+#define HX_CMD_ROE					 0x85
+#define HX_CMD_RAE					 0x86
+#define HX_CMD_RLE					 0x87
+#define HX_CMD_CLRES				 0x88
+#define HX_CMD_TSSWRESET			 0x9E
+#define HX_CMD_SETDEEPSTB			 0xD7
+#define HX_CMD_SET_CACHE_FUN		 0xDD
+#define HX_CMD_SETIDLE				 0xF2
+#define HX_CMD_SETIDLEDELAY			 0xF3
+#define HX_CMD_SELFTEST_BUFFER		 0x8D
 #define HX_CMD_MANUALMODE			 0x42
-#define HX_CMD_FLASH_ENABLE 		 0x43
+#define HX_CMD_FLASH_ENABLE			 0x43
 #define HX_CMD_FLASH_SET_ADDRESS	 0x44
 #define HX_CMD_FLASH_WRITE_REGISTER  0x45
 #define HX_CMD_FLASH_SET_COMMAND	 0x47
 #define HX_CMD_FLASH_WRITE_BUFFER	 0x48
-#define HX_CMD_FLASH_PAGE_ERASE 	 0x4D
+#define HX_CMD_FLASH_PAGE_ERASE		 0x4D
 #define HX_CMD_FLASH_SECTOR_ERASE	 0x4E
 #define HX_CMD_CB					 0xCB
 #define HX_CMD_EA					 0xEA
@@ -311,7 +312,7 @@
 };
 
 #ifdef HX_HIGH_SENSE
-void himax_set_HSEN_func(struct i2c_client *client,uint8_t HSEN_enable);
+void himax_set_HSEN_func(struct i2c_client *client, uint8_t HSEN_enable);
 #endif
 
 #ifdef HX_SMART_WAKEUP
@@ -319,18 +320,18 @@
 #define GEST_PTLG_HDR_LEN	(4)
 #define GEST_PTLG_HDR_ID1	(0xCC)
 #define GEST_PTLG_HDR_ID2	(0x44)
-#define GEST_PT_MAX_NUM 	(128)
+#define GEST_PT_MAX_NUM		(128)
 
 #ifdef HX_GESTURE_TRACK
 static int gest_pt_cnt;
 static int gest_pt_x[GEST_PT_MAX_NUM];
 static int gest_pt_y[GEST_PT_MAX_NUM];
-static int gest_start_x,gest_start_y,gest_end_x,gest_end_y;
-static int gest_width,gest_height,gest_mid_x,gest_mid_y;
+static int gest_start_x, gest_start_y, gest_end_x, gest_end_y;
+static int gest_width, gest_height, gest_mid_x, gest_mid_y;
 static int gn_gesture_coor[16];
 #endif
 
-void himax_set_SMWP_func(struct i2c_client *client,uint8_t SMWP_enable);
+void himax_set_SMWP_func(struct i2c_client *client, uint8_t SMWP_enable);
 extern bool FAKE_POWER_KEY_SEND;
 
 	enum gesture_event_type {
@@ -380,16 +381,91 @@
 int himax_input_register(struct himax_ts_data *ts);
 #endif
 
-extern int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_id *id);
-extern int himax_chip_common_remove(struct i2c_client *client);
-extern int himax_chip_common_suspend(struct himax_ts_data *ts);
-extern int himax_chip_common_resume(struct himax_ts_data *ts);
-int himax_loadSensorConfig(struct i2c_client *client, struct himax_i2c_platform_data *pdata);
+int himax_chip_common_probe(struct i2c_client *client,
+const struct i2c_device_id *id);
+int himax_chip_common_remove(struct i2c_client *client);
+int himax_chip_common_suspend(struct himax_ts_data *ts);
+int himax_chip_common_resume(struct himax_ts_data *ts);
+int himax_loadSensorConfig(struct i2c_client *client,
+struct himax_i2c_platform_data *pdata);
 
 #ifdef HX_USB_DETECT2
-//extern kal_bool upmu_is_chr_det(void);
+/*extern kal_bool upmu_is_chr_det(void);*/
 void himax_cable_detect_func(void);
 #endif
 
+#ifdef HX_AUTO_UPDATE_FW
+extern unsigned long	FW_VER_MAJ_FLASH_ADDR;
+extern unsigned long	FW_VER_MIN_FLASH_ADDR;
+extern unsigned long	CFG_VER_MAJ_FLASH_ADDR;
+extern unsigned long	CFG_VER_MIN_FLASH_ADDR;
+#endif
+extern unsigned long	FW_VER_MAJ_FLASH_LENG;
+extern unsigned long	FW_VER_MIN_FLASH_LENG;
+extern unsigned long	CFG_VER_MAJ_FLASH_LENG;
+extern unsigned long	CFG_VER_MIN_FLASH_LENG;
+extern unsigned char	IC_TYPE;
+extern unsigned char	IC_CHECKSUM;
+
+#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
+extern int himax_touch_proc_init(void);
+extern void himax_touch_proc_deinit(void);
+/*PROC-START*/
+#ifdef HX_TP_PROC_FLASH_DUMP
+extern void	himax_ts_flash_func(void);
+extern void setFlashBuffer(void);
+extern bool getFlashDumpGoing(void);
+extern uint8_t getSysOperation(void);
+extern void setSysOperation(uint8_t operation);
+#endif
+
+#ifdef HX_TP_PROC_HITOUCH
+extern bool hitouch_is_connect;
+#endif
+
+#ifdef HX_TP_PROC_DIAG
+	extern int touch_monitor_stop_flag;
+
+	extern int touch_monitor_stop_limit;
+
+	extern void	himax_ts_diag_func(void);
+
+	extern int16_t *getMutualBuffer(void);
+	extern int16_t *getMutualNewBuffer(void);
+	extern int16_t *getMutualOldBuffer(void);
+	extern int16_t *getSelfBuffer(void);
+	extern uint8_t getXChannel(void);
+	extern uint8_t getYChannel(void);
+	extern uint8_t getDiagCommand(void);
+	extern void setXChannel(uint8_t x);
+	extern void setYChannel(uint8_t y);
+	extern void setMutualBuffer(void);
+	extern void setMutualNewBuffer(void);
+	extern void setMutualOldBuffer(void);
+	extern uint8_t coordinate_dump_enable;
+	extern struct file *coordinate_fn;
+	extern uint8_t diag_coor[128];
+#ifdef HX_TP_PROC_2T2R
+	extern int16_t *getMutualBuffer_2(void);
+	extern uint8_t getXChannel_2(void);
+	extern uint8_t getYChannel_2(void);
+	extern void setXChannel_2(uint8_t x);
+	extern void setYChannel_2(uint8_t y);
+	extern void setMutualBuffer_2(void);
+#endif
+#endif
+/*PROC-END*/
+#endif
+
+#ifdef HX_USB_DETECT2
+	extern bool USB_Flag;
+#endif
+#ifdef HX_ESD_WORKAROUND
+	extern void HX_report_ESD_event(void);
+	unsigned char ESD_00_counter = 0;
+	unsigned char ESD_00_Flag = 0;
+#endif
+bool himax_ts_init(struct himax_ts_data *ts);
+
 #endif
 
diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.c b/drivers/input/touchscreen/hxchipset/himax_debug.c
index f8bee11..a5bdbf2 100644
--- a/drivers/input/touchscreen/hxchipset/himax_debug.c
+++ b/drivers/input/touchscreen/hxchipset/himax_debug.c
@@ -16,32 +16,16 @@
 #include "himax_debug.h"
 #include "himax_ic.h"
 
-//struct himax_debug_data* debug_data;
-
-extern struct himax_ic_data* ic_data;
-extern struct himax_ts_data *private_ts;
-extern unsigned char	IC_TYPE;
-extern unsigned char	IC_CHECKSUM;
-extern int himax_input_register(struct himax_ts_data *ts);
-#ifdef QCT
-extern irqreturn_t himax_ts_thread(int irq, void *ptr);
-#endif
-#ifdef MTK
-#ifdef CONFIG_OF_TOUCH
-extern irqreturn_t tpd_eint_interrupt_handler(int irq, void *desc);
-#else
-extern void tpd_eint_interrupt_handler(void);
-#endif
-#endif
+/*struct himax_debug_data* debug_data;*/
 
 #ifdef HX_TP_PROC_DIAG
 #ifdef HX_TP_PROC_2T2R
-int	HX_RX_NUM_2			= 0;
-int	HX_TX_NUM_2			= 0;
+int	HX_RX_NUM_2;
+int	HX_TX_NUM_2;
 #endif
-int	touch_monitor_stop_flag		= 0;
+int	touch_monitor_stop_flag;
 int	touch_monitor_stop_limit	= 5;
-uint8_t	g_diag_arr_num			= 0;
+uint8_t	g_diag_arr_num;
 #endif
 
 #ifdef HX_ESD_WORKAROUND
@@ -52,11 +36,11 @@
 bool FAKE_POWER_KEY_SEND;
 #endif
 
-//=============================================================================================================
-//
-//	Segment : Himax PROC Debug Function
-//
-//=============================================================================================================
+/*========================================================
+
+Segment : Himax PROC Debug Function
+
+==========================================================*/
 #if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
 
 static ssize_t himax_vendor_read(struct file *file, char *buf,
@@ -65,33 +49,26 @@
 	ssize_t ret = 0;
 	char *temp_buf;
 
-	if(!HX_PROC_SEND_FLAG)
-	{
+	if (!HX_PROC_SEND_FLAG) {
 		temp_buf = kzalloc(len, GFP_KERNEL);
-		if (!temp_buf) {
-			HX_PROC_SEND_FLAG=0;
-			return ret;
-		}
+		ret += snprintf(temp_buf, len,
+		"%s_FW:%#x_CFG:%#x_SensorId:%#x\n",
+		HIMAX_common_NAME, ic_data->vendor_fw_ver,
+		ic_data->vendor_config_ver, ic_data->vendor_sensor_id);
 
-		ret += snprintf(temp_buf, len, "%s_FW:%#x_CFG:%#x_SensorId:%#x\n", HIMAX_common_NAME,
-		ic_data->vendor_fw_ver, ic_data->vendor_config_ver, ic_data->vendor_sensor_id);
-		HX_PROC_SEND_FLAG=1;
+		HX_PROC_SEND_FLAG = 1;
 
 		if (copy_to_user(buf, temp_buf, len))
-		{
 			I("%s,here:%d\n", __func__, __LINE__);
-		}
 
 		kfree(temp_buf);
-	}
-	else
-		HX_PROC_SEND_FLAG=0;
+	} else
+		HX_PROC_SEND_FLAG = 0;
 
 	return ret;
 }
 
-static const struct file_operations himax_proc_vendor_ops =
-{
+const struct file_operations himax_proc_vendor_ops = {
 	.owner = THIS_MODULE,
 	.read = himax_vendor_read,
 };
@@ -107,29 +84,21 @@
 
 	if (!HX_PROC_SEND_FLAG) {
 		temp_buf = kzalloc(len, GFP_KERNEL);
-		if (!temp_buf) {
-			HX_PROC_SEND_FLAG=0;
-			return ret;
-		}
-		ret += snprintf(temp_buf, len, "attn = %x\n", himax_int_gpio_read(ts_data->pdata->gpio_irq));
+		ret += snprintf(temp_buf, len, "attn = %x\n",
+		himax_int_gpio_read(ts_data->pdata->gpio_irq));
 
 		if (copy_to_user(buf, temp_buf, len))
-		{
 			I("%s,here:%d\n", __func__, __LINE__);
-		}
 
 		kfree(temp_buf);
 		HX_PROC_SEND_FLAG = 1;
-	}
-	else
-		HX_PROC_SEND_FLAG=0;
+	} else
+		HX_PROC_SEND_FLAG = 0;
 
 	return ret;
 }
 
-
-static const struct file_operations himax_proc_attn_ops =
-{
+const struct file_operations himax_proc_attn_ops = {
 	.owner = THIS_MODULE,
 	.read = himax_attn_read,
 };
@@ -143,23 +112,16 @@
 
 	if (!HX_PROC_SEND_FLAG) {
 		temp_buf = kzalloc(len, GFP_KERNEL);
-		if (!temp_buf) {
-			HX_PROC_SEND_FLAG=0;
-			return ret;
-		}
-		ret += snprintf(temp_buf, len, "%d ", ts->irq_enabled);
-		ret += snprintf(temp_buf+ret, len-ret, "\n");
+		ret += snprintf(temp_buf, len-1, "%d ", ts->irq_enabled);
+		ret += snprintf(temp_buf, 1, "\n");
 
 		if (copy_to_user(buf, temp_buf, len))
-		{
 			I("%s,here:%d\n", __func__, __LINE__);
-		}
 
 		kfree(temp_buf);
 		HX_PROC_SEND_FLAG = 1;
-	}
-	else
-		HX_PROC_SEND_FLAG=0;
+	} else
+		HX_PROC_SEND_FLAG = 0;
 	return ret;
 }
 
@@ -167,18 +129,15 @@
 	size_t len, loff_t *pos)
 {
 	struct himax_ts_data *ts = private_ts;
-	char buf_tmp[12]= {0};
-	int value, ret=0;
+	char buf_tmp[12] = {0};
+	int value, ret = 0;
 
-	if (len >= 12)
-	{
+	if (len >= 12) {
 		I("%s: no command exceeds 12 chars.\n", __func__);
 		return -EFAULT;
 	}
 	if (copy_from_user(buf_tmp, buff, len))
-	{
 		return -EFAULT;
-	}
 
 	if (buf_tmp[0] == '0')
 		value = false;
@@ -188,36 +147,43 @@
 		return -EINVAL;
 
 	if (value) {
-		if(ic_data->HX_INT_IS_EDGE)
-		{
+		if (ic_data->HX_INT_IS_EDGE) {
 #ifdef MTK
 #ifdef CONFIG_OF_TOUCH
-			himax_int_enable(ts->client->irq,1);
+			himax_int_enable(ts->client->irq, 1);
 #else
-			//mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE);
-			//mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);
-			mt_eint_registration(ts->client->irq, EINTF_TRIGGER_FALLING, tpd_eint_interrupt_handler, 1);
+			/*mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM,
+			CUST_EINT_TOUCH_PANEL_TYPE);
+			mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM,
+			CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);*/
+			mt_eint_registration(ts->client->irq,
+			EINTF_TRIGGER_FALLING, tpd_eint_interrupt_handler, 1);
 #endif
 #endif
 #ifdef QCT
-			ret = request_threaded_irq(ts->client->irq, NULL, himax_ts_thread,
-					IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ts->client->name, ts);
+			ret = request_threaded_irq(ts->client->irq,
+					NULL, himax_ts_thread,
+					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					ts->client->name, ts);
 #endif
-		}
-		else
-		{
+		} else {
 #ifdef MTK
 #ifdef CONFIG_OF_TOUCH
-			himax_int_enable(ts->client->irq,1);
+			himax_int_enable(ts->client->irq, 1);
 #else
-			//mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE);
-			//mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);
-			mt_eint_registration(ts->client->irq, EINTF_TRIGGER_LOW, tpd_eint_interrupt_handler, 1);
+			/*mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM,
+			CUST_EINT_TOUCH_PANEL_TYPE);
+			mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM,
+			CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);*/
+			mt_eint_registration(ts->client->irq,
+			EINTF_TRIGGER_LOW, tpd_eint_interrupt_handler, 1);
 #endif
 #endif
 #ifdef QCT
-			ret = request_threaded_irq(ts->client->irq, NULL, himax_ts_thread,
-					IRQF_TRIGGER_LOW | IRQF_ONESHOT, ts->client->name, ts);
+			ret = request_threaded_irq(ts->client->irq,
+					NULL, himax_ts_thread,
+					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+					ts->client->name, ts);
 #endif
 		}
 		if (ret == 0) {
@@ -225,7 +191,7 @@
 			irq_enable_count = 1;
 		}
 	} else {
-		himax_int_enable(ts->client->irq,0);
+		himax_int_enable(ts->client->irq, 0);
 		free_irq(ts->client->irq, ts);
 		ts->irq_enabled = 0;
 	}
@@ -233,8 +199,7 @@
 	return len;
 }
 
-static const struct file_operations himax_proc_int_en_ops =
-{
+const struct file_operations himax_proc_int_en_ops = {
 	.owner = THIS_MODULE,
 	.read = himax_int_en_read,
 	.write = himax_int_en_write,
@@ -249,26 +214,19 @@
 
 	if (!HX_PROC_SEND_FLAG) {
 		temp_buf = kzalloc(len, GFP_KERNEL);
-		if (!temp_buf) {
-			HX_PROC_SEND_FLAG=0;
-			return ret;
-		}
-		ret += snprintf(temp_buf, len,  "%d ", ts->pdata->abs_x_min);
-		ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_x_max);
-		ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_y_min);
-		ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_y_max);
-		ret += snprintf(temp_buf+ret, len-ret, "\n");
+		ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_x_min);
+		ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_x_max);
+		ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_y_min);
+		ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_y_max);
+		ret += snprintf(temp_buf, len, "\n");
 
 		if (copy_to_user(buf, temp_buf, len))
-		{
 			I("%s,here:%d\n", __func__, __LINE__);
-		}
 
 		kfree(temp_buf);
 		HX_PROC_SEND_FLAG = 1;
-	}
-	else
-		HX_PROC_SEND_FLAG=0;
+	} else
+		HX_PROC_SEND_FLAG = 0;
 
 	return ret;
 }
@@ -283,17 +241,14 @@
 	int layout[4] = {0};
 	char buf[80] = {0};
 
-	if (len >= 80)
-	{
+	if (len >= 80) {
 		I("%s: no command exceeds 80 chars.\n", __func__);
 		return -EFAULT;
 	}
 	if (copy_from_user(buf, buff, len))
-	{
 		return -EFAULT;
-	}
 
-	for (i = 0; i < 20; i++) {
+	for (i = 0 ; i < 20 ; i++) {
 		if (buf[i] == ',' || buf[i] == '\n') {
 			memset(buf_tmp, 0x0, sizeof(buf_tmp));
 			if (i - j <= 5)
@@ -310,20 +265,24 @@
 		}
 	}
 	if (k == 4) {
-		ts->pdata->abs_x_min=layout[0];
-		ts->pdata->abs_x_max=layout[1];
-		ts->pdata->abs_y_min=layout[2];
-		ts->pdata->abs_y_max=layout[3];
-		I("%d, %d, %d, %d\n",ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max);
+		ts->pdata->abs_x_min = layout[0];
+		ts->pdata->abs_x_max = layout[1];
+		ts->pdata->abs_y_min = layout[2];
+		ts->pdata->abs_y_max = layout[3];
+		I("%d, %d, %d, %d\n", ts->pdata->abs_x_min,
+		ts->pdata->abs_x_max, ts->pdata->abs_y_min,
+		ts->pdata->abs_y_max);
 		input_unregister_device(ts->input_dev);
 		himax_input_register(ts);
-	} else
-		I("ERR@%d, %d, %d, %d\n",ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max);
+	} else {
+		I("ERR@%d, %d, %d, %d\n", ts->pdata->abs_x_min,
+		ts->pdata->abs_x_max, ts->pdata->abs_y_min,
+		ts->pdata->abs_y_max);
+	}
 	return len;
 }
 
-static const struct file_operations himax_proc_layout_ops =
-{
+const struct file_operations himax_proc_layout_ops = {
 	.owner = THIS_MODULE,
 	.read = himax_layout_read,
 	.write = himax_layout_write,
@@ -335,26 +294,21 @@
 	struct himax_ts_data *ts_data;
 	size_t ret = 0;
 	char *temp_buf;
+
 	ts_data = private_ts;
 
 	if (!HX_PROC_SEND_FLAG) {
 		temp_buf = kzalloc(len, GFP_KERNEL);
-		if (!temp_buf) {
-			HX_PROC_SEND_FLAG=0;
-			return ret;
-		}
-		ret += snprintf(temp_buf, len, "%d\n", ts_data->debug_log_level);
+		ret += snprintf(temp_buf, len, "%d\n",
+		ts_data->debug_log_level);
 
 		if (copy_to_user(buf, temp_buf, len))
-		{
 			I("%s,here:%d\n", __func__, __LINE__);
-		}
 
 		kfree(temp_buf);
 		HX_PROC_SEND_FLAG = 1;
-	}
-	else
-		HX_PROC_SEND_FLAG=0;
+	} else
+		HX_PROC_SEND_FLAG = 0;
 
 	return ret;
 }
@@ -365,29 +319,26 @@
 	struct himax_ts_data *ts;
 	char buf_tmp[11];
 	int i;
+
 	ts = private_ts;
 
-	if (len >= 12)
-	{
+	if (len >= 12) {
 		I("%s: no command exceeds 12 chars.\n", __func__);
 		return -EFAULT;
 	}
 	if (copy_from_user(buf_tmp, buff, len))
-	{
 		return -EFAULT;
-	}
 
 	ts->debug_log_level = 0;
-	for(i=0; i<len-1; i++)
-	{
-		if( buf_tmp[i]>='0' && buf_tmp[i]<='9' )
-			ts->debug_log_level |= (buf_tmp[i]-'0');
-		else if( buf_tmp[i]>='A' && buf_tmp[i]<='F' )
-			ts->debug_log_level |= (buf_tmp[i]-'A'+10);
-		else if( buf_tmp[i]>='a' && buf_tmp[i]<='f' )
-			ts->debug_log_level |= (buf_tmp[i]-'a'+10);
+	for (i = 0 ; i < len - 1 ; i++) {
+		if (buf_tmp[i] >= '0' && buf_tmp[i] <= '9')
+			ts->debug_log_level |= (buf_tmp[i] - '0');
+		else if (buf_tmp[i] >= 'A' && buf_tmp[i] <= 'F')
+			ts->debug_log_level |= (buf_tmp[i]-'A' + 10);
+		else if (buf_tmp[i] >= 'a' && buf_tmp[i] <= 'f')
+			ts->debug_log_level |= (buf_tmp[i] - 'a' + 10);
 
-		if(i!=len-2)
+		if (i != len - 2)
 			ts->debug_log_level <<= 4;
 	}
 
@@ -395,8 +346,12 @@
 		if (ts->pdata->screenWidth > 0 && ts->pdata->screenHeight > 0 &&
 		 (ts->pdata->abs_x_max - ts->pdata->abs_x_min) > 0 &&
 		 (ts->pdata->abs_y_max - ts->pdata->abs_y_min) > 0) {
-			ts->widthFactor = (ts->pdata->screenWidth << SHIFTBITS)/(ts->pdata->abs_x_max - ts->pdata->abs_x_min);
-			ts->heightFactor = (ts->pdata->screenHeight << SHIFTBITS)/(ts->pdata->abs_y_max - ts->pdata->abs_y_min);
+			ts->widthFactor =
+			(ts->pdata->screenWidth << SHIFTBITS)
+			/ (ts->pdata->abs_x_max - ts->pdata->abs_x_min);
+			ts->heightFactor =
+			(ts->pdata->screenHeight << SHIFTBITS)
+			/ (ts->pdata->abs_y_max - ts->pdata->abs_y_min);
 			if (ts->widthFactor > 0 && ts->heightFactor > 0)
 				ts->useScreenRes = 1;
 			else {
@@ -415,8 +370,7 @@
 	return len;
 }
 
-static const struct file_operations himax_proc_debug_level_ops =
-{
+const struct file_operations himax_proc_debug_level_ops = {
 	.owner = THIS_MODULE,
 	.read = himax_debug_level_read,
 	.write = himax_debug_level_write,
@@ -433,35 +387,33 @@
 
 	memset(data, 0x00, sizeof(data));
 
-	I("himax_register_show: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]);
-	if(!HX_PROC_SEND_FLAG)
-	{
+	I("himax_register_show: %x,%x,%x,%x\n", register_command[0],
+	register_command[1], register_command[2], register_command[3]);
+
+	if (!HX_PROC_SEND_FLAG) {
 		temp_buf = kzalloc(len, GFP_KERNEL);
-		if (!temp_buf) {
-			HX_PROC_SEND_FLAG=0;
-			return ret;
-		}
-		himax_register_read(private_ts->client, register_command, 1, data);
+		himax_register_read(private_ts->client,
+		register_command, 1, data);
 
-		ret += snprintf(temp_buf, len, "command:  %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]);
+		ret += snprintf(temp_buf, len, "command: %x,%x,%x,%x\n",
+		register_command[0], register_command[1],
+		register_command[2], register_command[3]);
 
-		for (loop_i = 0; loop_i < 128; loop_i++) {
-			ret += snprintf(temp_buf+ret, len-ret, "0x%2.2X ", data[loop_i]);
+		for (loop_i = 0 ; loop_i < 128 ; loop_i++) {
+			ret += snprintf(temp_buf + ret,
+			sizeof(data[loop_i]), "0x%2.2X ", data[loop_i]);
 			if ((loop_i % 16) == 15)
-				ret += snprintf(temp_buf+ret, len-ret, "\n");
+				ret += snprintf(temp_buf + ret, 1, "\n");
 		}
-		ret += snprintf(temp_buf+ret, len-ret, "\n");
-		HX_PROC_SEND_FLAG=1;
+		ret += snprintf(temp_buf + ret, len, "\n");
+		HX_PROC_SEND_FLAG = 1;
 
 		if (copy_to_user(buf, temp_buf, len))
-		{
 			I("%s,here:%d\n", __func__, __LINE__);
-		}
 
 		kfree(temp_buf);
-	}
-	else
-		HX_PROC_SEND_FLAG=0;
+	} else
+		HX_PROC_SEND_FLAG = 0;
 	return ret;
 }
 
@@ -475,40 +427,48 @@
 	uint8_t write_da[128];
 	char buf[80] = {0};
 
-	if (len >= 80)
-	{
+	if (len >= 80) {
 		I("%s: no command exceeds 80 chars.\n", __func__);
 		return -EFAULT;
 	}
 	if (copy_from_user(buf, buff, len))
-	{
 		return -EFAULT;
-	}
 
 	memset(buf_tmp, 0x0, sizeof(buf_tmp));
 	memset(write_da, 0x0, sizeof(write_da));
 
-	I("himax %s \n",buf);
+	I("himax %s\n", buf);
 
 	if ((buf[0] == 'r' || buf[0] == 'w') && buf[1] == ':') {
 
 		if (buf[2] == 'x') {
 			memcpy(buf_tmp, buf + 3, 8);
-			if (!kstrtoul(buf_tmp, 16, &result))
-				{
-					register_command[0] = (uint8_t)result;
-					register_command[1] = (uint8_t)(result >> 8);
-					register_command[2] = (uint8_t)(result >> 16);
-					register_command[3] = (uint8_t)(result >> 24);
-				}
+			if (!kstrtoul(buf_tmp, 16, &result)) {
+					register_command[0] =
+					(uint8_t)result;
+					register_command[1] =
+					(uint8_t)(result >> 8);
+					register_command[2] =
+					(uint8_t)(result >> 16);
+					register_command[3] =
+					(uint8_t)(result >> 24);
+			}
 			base = 11;
-			I("CMD: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]);
+			I("CMD: %x,%x,%x,%x\n", register_command[0],
+			register_command[1], register_command[2],
+			register_command[3]);
 
-			for (loop_i = 0; loop_i < 128 && (base+10)<80; loop_i++) {
+			for (loop_i = 0 ; loop_i < 128 ; loop_i++) {
 				if (buf[base] == '\n') {
 					if (buf[0] == 'w') {
-						himax_register_write(private_ts->client, register_command, 1, write_da);
-						I("CMD: %x, %x, %x, %x, len=%d\n", write_da[0], write_da[1],write_da[2],write_da[3],length);
+						himax_register_write
+						(private_ts->client,
+						register_command
+						, 1, write_da);
+						I("CMD:%x, %x, %x, %x,len=%d\n",
+						write_da[0], write_da[1],
+						write_da[2], write_da[3],
+						length);
 					}
 					I("\n");
 					return len;
@@ -518,12 +478,16 @@
 					buf_tmp[11] = '\0';
 					memcpy(buf_tmp, buf + base + 2, 8);
 					if (!kstrtoul(buf_tmp, 16, &result)) {
-						write_da[loop_i] = (uint8_t)result;
-						write_da[loop_i+1] = (uint8_t)(result >> 8);
-						write_da[loop_i+2] = (uint8_t)(result >> 16);
-						write_da[loop_i+3] = (uint8_t)(result >> 24);
+						write_da[loop_i] =
+						(uint8_t)result;
+						write_da[loop_i+1] =
+						(uint8_t)(result >> 8);
+						write_da[loop_i+2] =
+						(uint8_t)(result >> 16);
+						write_da[loop_i+3] =
+						(uint8_t)(result >> 24);
 					}
-					length+=4;
+					length += 4;
 				}
 				base += 10;
 			}
@@ -532,8 +496,7 @@
 	return len;
 }
 
-static const struct file_operations himax_proc_register_ops =
-{
+const struct file_operations himax_proc_register_ops = {
 	.owner = THIS_MODULE,
 	.read = himax_proc_register_read,
 	.write = himax_proc_register_write,
@@ -579,15 +542,18 @@
 }
 void setMutualBuffer(void)
 {
-	diag_mutual = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
+	diag_mutual = kzalloc
+	(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
 }
 void setMutualNewBuffer(void)
 {
-	diag_mutual_new = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
+	diag_mutual_new = kzalloc
+	(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
 }
 void setMutualOldBuffer(void)
 {
-	diag_mutual_old = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
+	diag_mutual_old = kzalloc
+	(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL);
 }
 
 #ifdef HX_TP_PROC_2T2R
@@ -613,94 +579,82 @@
 }
 void setMutualBuffer_2(void)
 {
-	diag_mutual_2 = kzalloc(x_channel_2 * y_channel_2 * sizeof(int16_t), GFP_KERNEL);
+	diag_mutual_2 = kzalloc
+	(x_channel_2 * y_channel_2 * sizeof(int16_t), GFP_KERNEL);
 }
 #endif
 
 static ssize_t himax_diag_arrange_write(struct file *file, const char *buff,
 	size_t len, loff_t *pos)
 {
-	//struct himax_ts_data *ts = private_ts;
+	/*struct himax_ts_data *ts = private_ts;*/
 	char buf[80] = {0};
 
-	if (len >= 80)
-	{
+	if (len >= 80) {
 		I("%s: no command exceeds 80 chars.\n", __func__);
 		return -EFAULT;
 	}
 	if (copy_from_user(buf, buff, len))
-	{
 		return -EFAULT;
-	}
 
 	g_diag_arr_num = buf[0] - '0';
-	I("%s: g_diag_arr_num = %d \n", __func__,g_diag_arr_num);
+	I("%s: g_diag_arr_num = %d\n", __func__, g_diag_arr_num);
 
 	return len;
 }
 
-static const struct file_operations himax_proc_diag_arrange_ops =
-{
+const struct file_operations himax_proc_diag_arrange_ops = {
 	.owner = THIS_MODULE,
 	.write = himax_diag_arrange_write,
 };
 
-static void himax_diag_arrange_print(struct seq_file *s, int i, int j, int transpose)
+static void himax_diag_arrange_print
+(struct seq_file *s, int i, int j, int transpose)
 {
-	if(transpose)
-		seq_printf(s, "%6d", diag_mutual[ j + i*x_channel]);
+	if (transpose)
+		seq_printf(s, "%6d", diag_mutual[j + i * x_channel]);
 	else
-		seq_printf(s, "%6d", diag_mutual[ i + j*x_channel]);
+		seq_printf(s, "%6d", diag_mutual[i + j * x_channel]);
 }
 
-static void himax_diag_arrange_inloop(struct seq_file *s, int in_init,bool transpose, int j)
+static void himax_diag_arrange_inloop
+(struct seq_file *s, int in_init, bool transpose, int j)
 {
 	int i;
 	int in_max = 0;
 
-	if(transpose)
+	if (transpose)
 		in_max = y_channel;
 	else
 		in_max = x_channel;
 
-	if (in_init > 0)
-	{
-		for(i = in_init-1;i >= 0;i--)
-		{
+	if (in_init > 0) {
+		for (i = in_init - 1 ; i >= 0 ; i--)
 			himax_diag_arrange_print(s, i, j, transpose);
-		}
-	}
-	else
-	{
-		for (i = 0; i < in_max; i++)
-		{
+	} else {
+		for (i = 0 ; i < in_max ; i++)
 			himax_diag_arrange_print(s, i, j, transpose);
-		}
 	}
 }
 
-static void himax_diag_arrange_outloop(struct seq_file *s, int transpose, int out_init, int in_init)
+static void himax_diag_arrange_outloop
+(struct seq_file *s, int transpose, int out_init, int in_init)
 {
 	int j;
 	int out_max = 0;
 
-	if(transpose)
+	if (transpose)
 		out_max = x_channel;
 	else
 		out_max = y_channel;
 
-	if(out_init > 0)
-	{
-		for(j = out_init-1;j >= 0;j--)
-		{
+	if (out_init > 0) {
+		for (j = out_init - 1 ; j >= 0 ; j--) {
 			himax_diag_arrange_inloop(s, in_init, transpose, j);
 			seq_printf(s, " %5d\n", diag_self[j]);
 		}
-	}
-	else
-	{
-		for(j = 0;j < out_max;j++)
-		{
+	} else {
+		for (j = 0 ; j < out_max ; j++) {
 			himax_diag_arrange_inloop(s, in_init, transpose, j);
 			seq_printf(s, " %5d\n", diag_self[j]);
 		}
@@ -709,33 +663,35 @@
 
 static void himax_diag_arrange(struct seq_file *s)
 {
-	int bit2,bit1,bit0;
+	int bit2, bit1, bit0;
 	int i;
 
 	bit2 = g_diag_arr_num >> 2;
 	bit1 = g_diag_arr_num >> 1 & 0x1;
 	bit0 = g_diag_arr_num & 0x1;
 
-	if (g_diag_arr_num < 4)
-	{
-		himax_diag_arrange_outloop(s, bit2, bit1 * y_channel, bit0 * x_channel);
-		for (i = y_channel; i < x_channel + y_channel; i++) {
+	if (g_diag_arr_num < 4) {
+		himax_diag_arrange_outloop(s,
+		bit2, bit1 * y_channel, bit0 * x_channel);
+
+		for (i = y_channel ; i < x_channel + y_channel ; i++)
 			seq_printf(s, "%6d", diag_self[i]);
-		}
-	}
-	else
-	{
-		himax_diag_arrange_outloop(s, bit2, bit1 * x_channel, bit0 * y_channel);
-		for (i = x_channel; i < x_channel + y_channel; i++) {
+
+	} else {
+		himax_diag_arrange_outloop(s,
+		bit2, bit1 * x_channel, bit0 * y_channel);
+
+		for (i = x_channel ; i < x_channel + y_channel ; i++)
 			seq_printf(s, "%6d", diag_self[i]);
-		}
+
 	}
 }
 
 static void *himax_diag_seq_start(struct seq_file *s, loff_t *pos)
 {
-	if (*pos>=1) return NULL;
-	return (void *)((unsigned long) *pos+1);
+	if (*pos >= 1)
+		return NULL;
+	return (void *)((unsigned long) *pos + 1);
 }
 
 static void *himax_diag_seq_next(struct seq_file *s, void *v, loff_t *pos)
@@ -748,87 +704,96 @@
 static int himax_diag_seq_read(struct seq_file *s, void *v)
 {
 	size_t count = 0;
-	int32_t loop_i;//,loop_j
+	int32_t loop_i;/*loop_j*/
 	uint16_t mutual_num, self_num, width;
 
 #ifdef HX_TP_PROC_2T2R
-	if(Is_2T2R && diag_command == 4)
-	{
+	if (Is_2T2R && diag_command == 4) {
 		mutual_num	= x_channel_2 * y_channel_2;
-		self_num	= x_channel_2 + y_channel_2; //don't add KEY_COUNT
+		/*don't add KEY_COUNT*/
+		self_num	= x_channel_2 + y_channel_2;
 		width		= x_channel_2;
-		seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel_2, y_channel_2);
-	}
-	else
+		seq_printf(s, "ChannelStart: %4d, %4d\n\n",
+		x_channel_2, y_channel_2);
+	} else
 #endif
 	{
 		mutual_num	= x_channel * y_channel;
-		self_num	= x_channel + y_channel; //don't add KEY_COUNT
+		/*don't add KEY_COUNT*/
+		self_num	= x_channel + y_channel;
 		width		= x_channel;
-		seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel, y_channel);
+		seq_printf(s, "ChannelStart: %4d, %4d\n\n",
+		x_channel, y_channel);
 	}
 
-	// start to show out the raw data in adb shell
+	/* start to show out the raw data in adb shell*/
 	if (diag_command >= 1 && diag_command <= 6) {
 		if (diag_command <= 3) {
 			himax_diag_arrange(s);
-			seq_printf(s, "\n\n");
+			seq_puts(s, "\n\n");
 #ifdef HX_EN_SEL_BUTTON
-			seq_printf(s, "\n");
-			for (loop_i = 0; loop_i < HX_BT_NUM; loop_i++)
-					seq_printf(s, "%6d", diag_self[HX_RX_NUM + HX_TX_NUM + loop_i]);
+			seq_putc(s, '\n');
+			for (loop_i = 0 ; loop_i < HX_BT_NUM ; loop_i++)
+				seq_printf(s, "%6d",
+				diag_self[HX_RX_NUM + HX_TX_NUM + loop_i]);
 #endif
 #ifdef HX_TP_PROC_2T2R
-		}else if(Is_2T2R && diag_command == 4 ) {
-			for (loop_i = 0; loop_i < mutual_num; loop_i++) {
+		} else if (Is_2T2R && diag_command == 4) {
+			for (loop_i = 0 ; loop_i < mutual_num ; loop_i++) {
 				seq_printf(s, "%4d", diag_mutual_2[loop_i]);
 				if ((loop_i % width) == (width - 1))
-					seq_printf(s, " %6d\n", diag_self[width + loop_i/width]);
+					seq_printf(s, " %6d\n",
+					diag_self[width + loop_i / width]);
 			}
-			seq_printf(s, "\n");
-			for (loop_i = 0; loop_i < width; loop_i++) {
+			seq_putc(s, '\n');
+			for (loop_i = 0 ; loop_i < width ; loop_i++) {
 				seq_printf(s, "%6d", diag_self[loop_i]);
 				if (((loop_i) % width) == (width - 1))
-					seq_printf(s, "\n");
+					seq_putc(s, '\n');
 			}
 #ifdef HX_EN_SEL_BUTTON
-			seq_printf(s, "\n");
-			for (loop_i = 0; loop_i < HX_BT_NUM; loop_i++)
-				seq_printf(s, "%4d", diag_self[HX_RX_NUM_2 + HX_TX_NUM_2 + loop_i]);
+			seq_putc(s, '\n');
+			for (loop_i = 0 ; loop_i < HX_BT_NUM ; loop_i++) {
+				seq_printf(s, "%4d",
+				diag_self[HX_RX_NUM_2 + HX_TX_NUM_2 + loop_i]);
+			}
 #endif
 #endif
 		} else if (diag_command > 4) {
-			for (loop_i = 0; loop_i < self_num; loop_i++) {
+			for (loop_i = 0 ; loop_i < self_num ; loop_i++) {
 				seq_printf(s, "%4d", diag_self[loop_i]);
-				if (((loop_i - mutual_num) % width) == (width - 1))
-					seq_printf(s, "\n");
+				if (((loop_i - mutual_num) % width)
+				== (width - 1)) {
+					seq_putc(s, '\n');
+				}
 			}
 		} else {
-			for (loop_i = 0; loop_i < mutual_num; loop_i++) {
+			for (loop_i = 0 ; loop_i < mutual_num ; loop_i++) {
 				seq_printf(s, "%4d", diag_mutual[loop_i]);
 				if ((loop_i % width) == (width - 1))
-					seq_printf(s, "\n");
+					seq_putc(s, '\n');
 			}
 		}
-		seq_printf(s, "ChannelEnd");
-		seq_printf(s, "\n");
+		seq_puts(s, "ChannelEnd");
+		seq_putc(s, '\n');
 	} else if (diag_command == 7) {
-		for (loop_i = 0; loop_i < 128 ;loop_i++) {
+		for (loop_i = 0; loop_i < 128 ; loop_i++) {
 			if ((loop_i % 16) == 0)
-				seq_printf(s, "LineStart:");
+				seq_puts(s, "LineStart:");
 				seq_printf(s, "%4d", diag_coor[loop_i]);
 			if ((loop_i % 16) == 15)
-				seq_printf(s, "\n");
+				seq_putc(s, '\n');
 		}
-	} else if (diag_command == 9 || diag_command == 91 || diag_command == 92){
+	} else if (diag_command == 9 ||
+	diag_command == 91 || diag_command == 92) {
+
 		himax_diag_arrange(s);
-		seq_printf(s, "\n");
+		seq_putc(s, '\n');
 	}
 
 	return count;
 }
-static const struct seq_operations himax_diag_seq_ops =
-{
+const struct seq_operations himax_diag_seq_ops = {
 	.start	= himax_diag_seq_start,
 	.next	= himax_diag_seq_next,
 	.stop	= himax_diag_seq_stop,
@@ -838,25 +803,24 @@
 {
 	return seq_open(file, &himax_diag_seq_ops);
 };
-bool DSRAM_Flag;
+bool DSRAM_Flag = false;
 
-//DSRAM thread
+/*DSRAM thread*/
 void himax_ts_diag_func(void)
 {
-	int i=0, j=0;
+	int i = 0, j = 0;
 	unsigned int index = 0;
 	int total_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM * 2;
 	uint8_t  info_data[total_size];
-	int16_t *mutual_data     = NULL;
+	int16_t *mutual_data = NULL;
 	int16_t *mutual_data_new = NULL;
 	int16_t *mutual_data_old = NULL;
 	int16_t new_data;
 
 	himax_burst_enable(private_ts->client, 1);
-	if(diag_command == 9 || diag_command == 91)
-	{
+	if (diag_command == 9 || diag_command == 91) {
 		mutual_data = getMutualBuffer();
-	}else if(diag_command == 92){
+	} else if (diag_command == 92) {
 		mutual_data = getMutualBuffer();
 		mutual_data_new = getMutualNewBuffer();
 		mutual_data_old = getMutualOldBuffer();
@@ -864,49 +828,63 @@
 	himax_get_DSRAM_data(private_ts->client, info_data);
 
 	index = 0;
-	for (i = 0; i < ic_data->HX_TX_NUM; i++)
-	{
-		for (j = 0; j < ic_data->HX_RX_NUM; j++)
-		{
-			new_data = (short)(info_data[index + 1] << 8 | info_data[index]);
-			if(diag_command == 9){
-				mutual_data[i*ic_data->HX_RX_NUM+j] = new_data;
-			}else if(diag_command == 91){ //Keep max data for 100 frame
-				if(mutual_data[i * ic_data->HX_RX_NUM + j] < new_data)
-				mutual_data[i * ic_data->HX_RX_NUM + j] = new_data;
-			}else if(diag_command == 92){ //Cal data for [N]-[N-1] frame
-				mutual_data_new[i * ic_data->HX_RX_NUM + j] = new_data;
-				mutual_data[i * ic_data->HX_RX_NUM + j] = mutual_data_new[i * ic_data->HX_RX_NUM + j] - mutual_data_old[i * ic_data->HX_RX_NUM + j];
+	for (i = 0 ; i < ic_data->HX_TX_NUM ; i++) {
+		for (j = 0 ; j < ic_data->HX_RX_NUM ; j++) {
+			new_data = (short)(info_data[index + 1]
+			<< 8 | info_data[index]);
+			if (diag_command == 9) {
+				mutual_data[i * ic_data->HX_RX_NUM + j]
+				= new_data;
+			/*Keep max data for 100 frame*/
+			} else if (diag_command == 91) {
+				if (mutual_data[i * ic_data->HX_RX_NUM + j]
+				< new_data) {
+					mutual_data[i * ic_data->HX_RX_NUM + j]
+					= new_data;
+				}
+			/*Cal data for [N]-[N-1] frame*/
+			} else if (diag_command == 92) {
+				mutual_data_new[i * ic_data->HX_RX_NUM + j]
+				= new_data;
+
+				mutual_data[i * ic_data->HX_RX_NUM + j] =
+				mutual_data_new[i * ic_data->HX_RX_NUM + j] -
+				mutual_data_old[i * ic_data->HX_RX_NUM + j];
 			}
 			index += 2;
 		}
 	}
-	if(diag_command == 92){
-		memcpy(mutual_data_old,mutual_data_new,x_channel * y_channel * sizeof(int16_t)); //copy N data to N-1 array
+	/*copy N data to N-1 array*/
+	if (diag_command == 92) {
+		memcpy(mutual_data_old, mutual_data_new,
+		x_channel * y_channel * sizeof(int16_t));
 	}
+
 	diag_max_cnt++;
-	if(diag_command == 9 || diag_command == 92){
-		queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 1/10*HZ);
-	}else if(diag_command == 91){
-		if(diag_max_cnt > 100) //count for 100 frame
-		{
-			//Clear DSRAM flag
+	if (diag_command == 9 || diag_command == 92) {
+		queue_delayed_work(private_ts->himax_diag_wq,
+		&private_ts->himax_diag_delay_wrok, 1/10*HZ);
+	} else if (diag_command == 91) {
+		if (diag_max_cnt > 100) {/*count for 100 frame*/
+			/*Clear DSRAM flag*/
 			DSRAM_Flag = false;
 
-			//Enable ISR
-			himax_int_enable(private_ts->client->irq,1);
+			/*Enable ISR*/
+			himax_int_enable(private_ts->client->irq, 1);
 
-			//=====================================
-			// test result command : 0x8002_0324 ==> 0x00
-			//=====================================
+			/*=====================================
+			test result command : 0x8002_0324 ==> 0x00
+			=====================================*/
 			himax_diag_register_set(private_ts->client, 0x00);
-		}else{
-			queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 1/10*HZ);
+		} else {
+			queue_delayed_work(private_ts->himax_diag_wq,
+			&private_ts->himax_diag_delay_wrok, 1 / 10 * HZ);
 		}
 	}
 }
 
-static ssize_t himax_diag_write(struct file *filp, const char __user *buff, size_t len, loff_t *data)
+static ssize_t himax_diag_write
+(struct file *filp, const char __user *buff, size_t len, loff_t *data)
 {
 	char messages[80] = {0};
 
@@ -915,67 +893,66 @@
 
 	memset(receive, 0x00, sizeof(receive));
 
-	if (len >= 80)
-	{
+	if (len >= 80) {
 		I("%s: no command exceeds 80 chars.\n", __func__);
 		return -EFAULT;
 	}
 	if (copy_from_user(messages, buff, len))
-	{
 		return -EFAULT;
-	}
-	if (messages[1] == 0x0A){
-		diag_command =messages[0] - '0';
-	}else{
-		diag_command =(messages[0] - '0')*10 + (messages[1] - '0');
-	}
 
-	I("[Himax]diag_command=0x%x\n",diag_command);
-	if (diag_command < 0x04){
-		if(DSRAM_Flag)
-		{
-			//1. Clear DSRAM flag
+	if (messages[1] == 0x0A)
+		diag_command = messages[0] - '0';
+	else
+		diag_command = (messages[0] - '0') * 10 + (messages[1] - '0');
+
+
+	I("[Himax]diag_command=0x%x\n", diag_command);
+	if (diag_command < 0x04) {
+		if (DSRAM_Flag) {
+			/*1. Clear DSRAM flag*/
 			DSRAM_Flag = false;
 
-			//2. Stop DSRAM thread
-			cancel_delayed_work_sync(&private_ts->himax_diag_delay_wrok);
+			/*2. Stop DSRAM thread*/
+			cancel_delayed_work_sync
+			(&private_ts->himax_diag_delay_wrok);
 
-			//3. Enable ISR
-			himax_int_enable(private_ts->client->irq,1);
+			/*3. Enable ISR*/
+			himax_int_enable(private_ts->client->irq, 1);
 		}
 		command[0] = diag_command;
 		himax_diag_register_set(private_ts->client, command[0]);
-	}
-	//coordinate dump start
-	else if (diag_command == 0x08)	{
-		E("%s: coordinate_dump_file_create error\n", __func__);
-	}
-	else if (diag_command == 0x09 || diag_command == 91 || diag_command == 92){
+	/*coordinate dump start*/
+	} else if (diag_command == 0x09 ||
+	diag_command == 91 || diag_command == 92) {
+
 		diag_max_cnt = 0;
-		memset(diag_mutual, 0x00, x_channel * y_channel * sizeof(int16_t)); //Set data 0 everytime
+		 /*Set data 0 everytime*/
+		memset(diag_mutual, 0x00,
+		x_channel * y_channel * sizeof(int16_t));
 
-		//1. Disable ISR
-		himax_int_enable(private_ts->client->irq,0);
+		/*1. Disable ISR*/
+		himax_int_enable(private_ts->client->irq, 0);
 
-		//2. Start DSRAM thread
-		//himax_diag_register_set(private_ts->client, 0x0A);
+		/*2. Start DSRAM thread*/
+		/*himax_diag_register_set(private_ts->client, 0x0A);*/
 
-		queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 2*HZ/100);
+		queue_delayed_work(private_ts->himax_diag_wq,
+		&private_ts->himax_diag_delay_wrok, 2 * HZ / 100);
 
 		I("%s: Start get raw data in DSRAM\n", __func__);
 
-		//3. Set DSRAM flag
+		/*3. Set DSRAM flag*/
 		DSRAM_Flag = true;
-	}else{
+	} else {
 		command[0] = 0x00;
 		himax_diag_register_set(private_ts->client, command[0]);
-		E("[Himax]Diag command error!diag_command=0x%x\n",diag_command);
+		E("[Himax]Diag command error!diag_command=0x%x\n",
+		diag_command);
 	}
 	return len;
 }
 
-static const struct file_operations himax_proc_diag_ops =
-{
+const struct file_operations himax_proc_diag_ops = {
 	.owner = THIS_MODULE,
 	.open = himax_diag_proc_open,
 	.read = seq_read,
@@ -989,23 +966,20 @@
 {
 	char buf_tmp[12];
 
-	if (len >= 12)
-	{
+	if (len >= 12) {
 		I("%s: no command exceeds 12 chars.\n", __func__);
 		return -EFAULT;
 	}
 	if (copy_from_user(buf_tmp, buff, len))
-	{
 		return -EFAULT;
-	}
-	//if (buf_tmp[0] == '1')
-	//	ESD_HW_REST();
+
+	/*if (buf_tmp[0] == '1')
+		ESD_HW_REST();*/
 
 	return len;
 }
 
-static const struct file_operations himax_proc_reset_ops =
-{
+const struct file_operations himax_proc_reset_ops = {
 	.owner = THIS_MODULE,
 	.write = himax_reset_write,
 };
@@ -1018,291 +992,263 @@
 	size_t count = 0;
 	char *temp_buf;
 
-	if(!HX_PROC_SEND_FLAG)
-	{
+	if (!HX_PROC_SEND_FLAG) {
 		temp_buf = kzalloc(len, GFP_KERNEL);
-		if (!temp_buf){
-			HX_PROC_SEND_FLAG=0;
-			return count;
-		}
-
-		if (debug_level_cmd == 't')
-		{
-			if (fw_update_complete)
-				count += snprintf(temp_buf+count, len-count, "FW Update Complete ");
-			else
-			{
-				count += snprintf(temp_buf+count, len-count, "FW Update Fail ");
-			}
-		}
-		else if (debug_level_cmd == 'h')
-		{
-			if (handshaking_result == 0)
-			{
-				count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (MCU Running)\n", handshaking_result);
-			}
-			else if (handshaking_result == 1)
-			{
-				count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (MCU Stop)\n", handshaking_result);
-			}
-			else if (handshaking_result == 2)
-			{
-				count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (I2C Error)\n", handshaking_result);
-			}
-			else
-			{
-				count += snprintf(temp_buf+count, len-count, "Handshaking Result = error\n");
-			}
-		}
-		else if (debug_level_cmd == 'v')
-		{
-			count += snprintf(temp_buf+count, len-count, "FW_VER = ");
-			count += snprintf(temp_buf+count, len-count, "0x%2.2X\n", ic_data->vendor_fw_ver);
-			count += snprintf(temp_buf+count, len-count, "CONFIG_VER = ");
-			count += snprintf(temp_buf+count, len-count, "0x%2.2X\n", ic_data->vendor_config_ver);
-			count += snprintf(temp_buf+count, len-count, "\n");
-		}
-		else if (debug_level_cmd == 'd')
-		{
-			count += snprintf(temp_buf+count, len-count, "Himax Touch IC Information :\n");
-			if (IC_TYPE == HX_85XX_D_SERIES_PWON)
-			{
-				count += snprintf(temp_buf+count, len-count, "IC Type : D\n");
-			}
-			else if (IC_TYPE == HX_85XX_E_SERIES_PWON)
-			{
-				count += snprintf(temp_buf+count, len-count, "IC Type : E\n");
-			}
-			else if (IC_TYPE == HX_85XX_ES_SERIES_PWON)
-			{
-				count += snprintf(temp_buf+count, len-count, "IC Type : ES\n");
-			}
-			else if (IC_TYPE == HX_85XX_F_SERIES_PWON)
-			{
-				count += snprintf(temp_buf+count, len-count, "IC Type : F\n");
-			}
-			else
-			{
-				count += snprintf(temp_buf+count, len-count, "IC Type error.\n");
+		if (debug_level_cmd == 't') {
+			if (fw_update_complete) {
+				count += snprintf(temp_buf, len,
+				"FW Update Complete ");
+			} else {
+				count += snprintf(temp_buf, len,
+				"FW Update Fail ");
 			}
 
-			if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_SW)
-			{
-				count += snprintf(temp_buf+count, len-count, "IC Checksum : SW\n");
+		} else if (debug_level_cmd == 'h') {
+			if (handshaking_result == 0) {
+				count += snprintf(temp_buf, len,
+				"Handshaking Result = %d (MCU Running)\n",
+				handshaking_result);
+			} else if (handshaking_result == 1) {
+				count += snprintf(temp_buf, len,
+				"Handshaking Result = %d (MCU Stop)\n",
+				handshaking_result);
+			} else if (handshaking_result == 2) {
+				count += snprintf(temp_buf, len,
+				"Handshaking Result = %d (I2C Error)\n",
+				handshaking_result);
+			} else {
+				count += snprintf(temp_buf, len,
+				"Handshaking Result = error\n");
 			}
-			else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_HW)
-			{
-				count += snprintf(temp_buf+count, len-count, "IC Checksum : HW\n");
+		} else if (debug_level_cmd == 'v') {
+			count += snprintf(temp_buf + count, len,
+			"FW_VER = ");
+			count += snprintf(temp_buf + count, len,
+			"0x%2.2X\n", ic_data->vendor_fw_ver);
+			count += snprintf(temp_buf + count, len,
+			"CONFIG_VER = ");
+			count += snprintf(temp_buf + count, len,
+			"0x%2.2X\n", ic_data->vendor_config_ver);
+			count += snprintf(temp_buf + count, len,
+			"\n");
+		} else if (debug_level_cmd == 'd') {
+			count += snprintf(temp_buf + count, len,
+			"Himax Touch IC Information :\n");
+			if (IC_TYPE == HX_85XX_D_SERIES_PWON) {
+				count += snprintf(temp_buf + count, len,
+				"IC Type : D\n");
+			} else if (IC_TYPE == HX_85XX_E_SERIES_PWON) {
+				count += snprintf(temp_buf + count, len,
+				"IC Type : E\n");
+			} else if (IC_TYPE == HX_85XX_ES_SERIES_PWON) {
+				count += snprintf(temp_buf + count, len,
+				"IC Type : ES\n");
+			} else if (IC_TYPE == HX_85XX_F_SERIES_PWON) {
+				count += snprintf(temp_buf + count, len,
+				"IC Type : F\n");
+			} else {
+				count += snprintf(temp_buf + count, len,
+				"IC Type error.\n");
 			}
-			else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_CRC)
-			{
-				count += snprintf(temp_buf+count, len-count, "IC Checksum : CRC\n");
+			if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_SW) {
+				count += snprintf(temp_buf + count, len,
+				"IC Checksum : SW\n");
+			} else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_HW) {
+				count += snprintf(temp_buf + count, len,
+				"IC Checksum : HW\n");
+			} else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_CRC) {
+				count += snprintf(temp_buf + count, len,
+				"IC Checksum : CRC\n");
+			} else {
+				count += snprintf(temp_buf + count, len,
+				"IC Checksum error.\n");
 			}
-			else
-			{
-				count += snprintf(temp_buf+count, len-count, "IC Checksum error.\n");
+			if (ic_data->HX_INT_IS_EDGE) {
+				count += snprintf(temp_buf + count, len,
+				"Interrupt : EDGE TIRGGER\n");
+			} else {
+				count += snprintf(temp_buf + count, len,
+				"Interrupt : LEVEL TRIGGER\n");
 			}
-
-			if (ic_data->HX_INT_IS_EDGE)
-			{
-				count += snprintf(temp_buf+count, len-count, "Interrupt : EDGE TIRGGER\n");
-			}
-			else
-			{
-				count += snprintf(temp_buf+count, len-count, "Interrupt : LEVEL TRIGGER\n");
-			}
-
-			count += snprintf(temp_buf+count, len-count, "RX Num : %d\n", ic_data->HX_RX_NUM);
-			count += snprintf(temp_buf+count, len-count, "TX Num : %d\n", ic_data->HX_TX_NUM);
-			count += snprintf(temp_buf+count, len-count, "BT Num : %d\n", ic_data->HX_BT_NUM);
-			count += snprintf(temp_buf+count, len-count, "X Resolution : %d\n", ic_data->HX_X_RES);
-			count += snprintf(temp_buf+count, len-count, "Y Resolution : %d\n", ic_data->HX_Y_RES);
-			count += snprintf(temp_buf+count, len-count, "Max Point : %d\n", ic_data->HX_MAX_PT);
-			count += snprintf(temp_buf+count, len-count, "XY reverse : %d\n", ic_data->HX_XY_REVERSE);
+			count += snprintf(temp_buf + count, len,
+			"RX Num : %d\n", ic_data->HX_RX_NUM);
+			count += snprintf(temp_buf + count, len,
+			"TX Num : %d\n", ic_data->HX_TX_NUM);
+			count += snprintf(temp_buf + count, len,
+			"BT Num : %d\n", ic_data->HX_BT_NUM);
+			count += snprintf(temp_buf + count, len,
+			"X Resolution : %d\n", ic_data->HX_X_RES);
+			count += snprintf(temp_buf + count, len,
+			"Y Resolution : %d\n", ic_data->HX_Y_RES);
+			count += snprintf(temp_buf + count, len,
+			"Max Point : %d\n", ic_data->HX_MAX_PT);
+			count += snprintf(temp_buf + count, len,
+			"XY reverse : %d\n", ic_data->HX_XY_REVERSE);
 	#ifdef HX_TP_PROC_2T2R
-			if(Is_2T2R)
-			{
-				count += snprintf(temp_buf+count, len-count, "2T2R panel\n");
-				count += snprintf(temp_buf+count, len-count, "RX Num_2 : %d\n", HX_RX_NUM_2);
-				count += snprintf(temp_buf+count, len-count, "TX Num_2 : %d\n", HX_TX_NUM_2);
+			if (Is_2T2R) {
+				count += snprintf(temp_buf + count, len,
+				"2T2R panel\n");
+				count += snprintf(temp_buf + count, len,
+				"RX Num_2 : %d\n", HX_RX_NUM_2);
+				count += snprintf(temp_buf + count, len,
+				"TX Num_2 : %d\n", HX_TX_NUM_2);
 			}
 	#endif
-		}
-		else if (debug_level_cmd == 'i')
-		{
-			count += snprintf(temp_buf+count, len-count, "Himax Touch Driver Version:\n");
-			count += snprintf(temp_buf+count, len-count, "%s\n", HIMAX_DRIVER_VER);
+		} else if (debug_level_cmd == 'i') {
+			count += snprintf(temp_buf + count, len,
+			"Himax Touch Driver Version:\n");
+			count += snprintf(temp_buf + count, len,
+			"%s\n", HIMAX_DRIVER_VER);
 		}
 		if (copy_to_user(buf, temp_buf, len))
-		{
 			I("%s,here:%d\n", __func__, __LINE__);
-		}
 
 		kfree(temp_buf);
-		HX_PROC_SEND_FLAG=1;
-	}
-	else
-		HX_PROC_SEND_FLAG=0;
+		HX_PROC_SEND_FLAG = 1;
+	} else
+		HX_PROC_SEND_FLAG = 0;
 	return count;
 }
 
 static ssize_t himax_debug_write(struct file *file, const char *buff,
 	size_t len, loff_t *pos)
 {
-	const struct firmware *fw = NULL;
-	unsigned char *fw_data = NULL;
+	int result = 0;
 	char fileName[128];
 	char buf[80] = {0};
-	int result;
+	const struct firmware *fw = NULL;
 
-	if (len >= 80)
-	{
+	if (len >= 80) {
 		I("%s: no command exceeds 80 chars.\n", __func__);
 		return -EFAULT;
 	}
 	if (copy_from_user(buf, buff, len))
-	{
 		return -EFAULT;
-	}
 
-	if ( buf[0] == 'h') //handshaking
-	{
+	if (buf[0] == 'h') {/*handshaking*/
 		debug_level_cmd = buf[0];
 
-		himax_int_enable(private_ts->client->irq,0);
+		himax_int_enable(private_ts->client->irq, 0);
 
-		handshaking_result = himax_hand_shaking(private_ts->client); //0:Running, 1:Stop, 2:I2C Fail
+		/*0:Running, 1:Stop, 2:I2C Fail*/
+		handshaking_result = himax_hand_shaking(private_ts->client);
 
-		himax_int_enable(private_ts->client->irq,1);
+		himax_int_enable(private_ts->client->irq, 1);
 
 		return len;
-	}
-
-	else if ( buf[0] == 'v') //firmware version
-	{
+	} else if (buf[0] == 'v') { /*firmware version*/
 		debug_level_cmd = buf[0];
-		himax_int_enable(private_ts->client->irq,0);
+		himax_int_enable(private_ts->client->irq, 0);
 #ifdef HX_RST_PIN_FUNC
-		himax_HW_reset(false,false);
+		himax_HW_reset(false, false);
 #endif
 		himax_read_FW_ver(private_ts->client);
-		//himax_check_chip_version();
+		/*himax_check_chip_version();*/
 #ifdef HX_RST_PIN_FUNC
-	himax_HW_reset(true,false);
+	himax_HW_reset(true, false);
 #endif
-	himax_int_enable(private_ts->client->irq,1);
+	himax_int_enable(private_ts->client->irq, 1);
 		return len;
-	}
+	} else if (buf[0] == 'd') { /*ic information*/
 
-	else if ( buf[0] == 'd') //ic information
-	{
 		debug_level_cmd = buf[0];
 		return len;
-	}
+	} else if (buf[0] == 'i') {/*driver version*/
 
-	else if ( buf[0] == 'i') //driver version
-	{
 		debug_level_cmd = buf[0];
 		return len;
-	}
+	} else if (buf[0] == 't') {
 
-	else if (buf[0] == 't')
-	{
+		himax_int_enable(private_ts->client->irq, 0);
+		debug_level_cmd = buf[0];
+		fw_update_complete = false;
 
-		himax_int_enable(private_ts->client->irq,0);
-
-		debug_level_cmd 		= buf[0];
-		fw_update_complete		= false;
-
-		memset(fileName, 0, 128);
-		// parse the file name
-		snprintf(fileName, len-4, "%s", &buf[4]);
-		I("%s: upgrade from file(%s) start!\n", __func__, fileName);
-		// open file
-		result = request_firmware(&fw, fileName, private_ts->dev);
-		if (result) {
-			E("%s: open firmware file failed\n", __func__);
-			goto firmware_upgrade_done;
-			//return len;
+		result = himax_load_CRC_bin_file(private_ts->client);
+		if (result < 0) {
+			E("%s: himax_load_CRC_bin_file fail Error Code=%d.\n",
+			__func__, result);
+			return result;
 		}
 
-		I("%s: FW len %d\n", __func__, fw->size);
-		fw_data = (unsigned char *)fw->data;
+		memset(fileName, 0, 128);
+/* parse the file name*/
+		snprintf(fileName, len-4, "%s", &buf[4]);
+		I("%s: upgrade from file(%s) start!\n", __func__, fileName);
+		result = request_firmware(&fw, fileName, private_ts->dev);
+		if (result < 0) {
+			I("fail to request_firmware fwpath: %s (ret:%d)\n",
+			fileName, result);
+			return result;
+		}
+		I("%s: FW image: %02X, %02X, %02X, %02X ret=%d\n", __func__,
+		fw->data[0], fw->data[1], fw->data[2], fw->data[3], result);
+		if (result >= 0) {
+			/*start to upgrade*/
+			himax_int_enable(private_ts->client->irq, 0);
 
-		I("%s: FW image,len %d: %02X, %02X, %02X, %02X\n", __func__, result, upgrade_fw[0], upgrade_fw[1], upgrade_fw[2], upgrade_fw[3]);
-
-		if (fw_data != NULL)
-		{
-			// start to upgrade
-			himax_int_enable(private_ts->client->irq,0);
-
-			if ((buf[1] == '6') && (buf[2] == '0'))
-			{
-				if (fts_ctpm_fw_upgrade_with_sys_fs_60k(private_ts->client,upgrade_fw, result, false) == 0)
-				{
-					E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+			if ((buf[1] == '6') && (buf[2] == '0')) {
+				if (fts_ctpm_fw_upgrade_with_sys_fs_60k
+				(private_ts->client, (unsigned char *)fw->data,
+				fw->size, false) == 0) {
+					E("%s: TP upgrade error, line: %d\n",
+					__func__, __LINE__);
 					fw_update_complete = false;
-				}
-				else
-				{
-					I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+				} else {
+					I("%s: TP upgrade OK, line: %d\n",
+					__func__, __LINE__);
 					fw_update_complete = true;
 				}
-			}
-			else if ((buf[1] == '6') && (buf[2] == '4'))
-			{
-				if (fts_ctpm_fw_upgrade_with_sys_fs_64k(private_ts->client,upgrade_fw, result, false) == 0)
-				{
-					E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+			} else if ((buf[1] == '6') && (buf[2] == '4')) {
+				if (fts_ctpm_fw_upgrade_with_sys_fs_64k
+				(private_ts->client, (unsigned char *)fw->data,
+				fw->size, false) == 0) {
+					E("%s: TP upgrade error, line: %d\n",
+					__func__, __LINE__);
 					fw_update_complete = false;
-				}
-				else
-				{
-					I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+				} else {
+					I("%s: TP upgrade OK, line: %d\n",
+					__func__, __LINE__);
 					fw_update_complete = true;
 				}
-			}
-			else if ((buf[1] == '2') && (buf[2] == '4'))
-			{
-				if (fts_ctpm_fw_upgrade_with_sys_fs_124k(private_ts->client,upgrade_fw, result, false) == 0)
-				{
-					E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+			} else if ((buf[1] == '2') && (buf[2] == '4')) {
+				if (fts_ctpm_fw_upgrade_with_sys_fs_124k
+				(private_ts->client, (unsigned char *)fw->data,
+				fw->size, false) == 0) {
+					E("%s: TP upgrade error, line: %d\n",
+					__func__, __LINE__);
 					fw_update_complete = false;
-				}
-				else
-				{
-					I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+				} else {
+					I("%s: TP upgrade OK, line: %d\n",
+					__func__, __LINE__);
 					fw_update_complete = true;
 				}
-			}
-			else if ((buf[1] == '2') && (buf[2] == '8'))
-			{
-				if (fts_ctpm_fw_upgrade_with_sys_fs_128k(private_ts->client,upgrade_fw, result, false) == 0)
-				{
-					E("%s: TP upgrade error, line: %d\n", __func__, __LINE__);
+			} else if ((buf[1] == '2') && (buf[2] == '8')) {
+				if (fts_ctpm_fw_upgrade_with_sys_fs_128k
+				(private_ts->client, (unsigned char *)fw->data,
+				fw->size, false) == 0) {
+					E("%s: TP upgrade error, line: %d\n",
+					__func__, __LINE__);
 					fw_update_complete = false;
-				}
-				else
-				{
-					I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__);
+				} else {
+					I("%s: TP upgrade OK, line: %d\n",
+					__func__, __LINE__);
 					fw_update_complete = true;
 				}
-			}
-			else
-			{
-				E("%s: Flash command fail: %d\n", __func__, __LINE__);
+			} else {
+				E("%s: Flash command fail: %d\n",
+				__func__, __LINE__);
 				fw_update_complete = false;
 			}
 			release_firmware(fw);
 			goto firmware_upgrade_done;
-			//return count;
+			/*return count;*/
 		}
 	}
 
-	firmware_upgrade_done:
+firmware_upgrade_done:
 
 #ifdef HX_RST_PIN_FUNC
-	himax_HW_reset(true,false);
+	himax_HW_reset(true, false);
 #endif
 
 	himax_sense_on(private_ts->client, 0x01);
@@ -1310,16 +1256,15 @@
 #ifdef HX_ESD_WORKAROUND
 	HX_ESD_RESET_ACTIVATE = 1;
 #endif
-	himax_int_enable(private_ts->client->irq,1);
+	himax_int_enable(private_ts->client->irq, 1);
 
-	//todo himax_chip->tp_firmware_upgrade_proceed = 0;
-	//todo himax_chip->suspend_state = 0;
-	//todo enable_irq(himax_chip->irq);
+	/*todo himax_chip->tp_firmware_upgrade_proceed = 0;
+	todo himax_chip->suspend_state = 0;
+	todo enable_irq(himax_chip->irq);*/
 	return len;
 }
 
-static const struct file_operations himax_proc_debug_ops =
-{
+const struct file_operations himax_proc_debug_ops = {
 	.owner = THIS_MODULE,
 	.read = himax_debug_read,
 	.write = himax_debug_write,
@@ -1376,9 +1321,9 @@
 
 void setFlashBuffer(void)
 {
-	flash_buffer = kzalloc(Flash_Size * sizeof(uint8_t), GFP_KERNEL);
-	if (flash_buffer)
-		memset(flash_buffer,0x00,Flash_Size);
+	flash_buffer = kzalloc
+	(Flash_Size * sizeof(uint8_t), GFP_KERNEL);
+	memset(flash_buffer, 0x00, Flash_Size);
 }
 
 void setSysOperation(uint8_t operation)
@@ -1389,7 +1334,8 @@
 static void setFlashDumpProgress(uint8_t progress)
 {
 	flash_progress = progress;
-	//I("setFlashDumpProgress : progress = %d ,flash_progress = %d \n",progress,flash_progress);
+	/*I("setFlashDumpProgress : progress = %d ,
+	flash_progress = %d\n",progress,flash_progress);*/
 }
 
 static void setFlashDumpComplete(uint8_t status)
@@ -1432,130 +1378,113 @@
 {
 	int ret = 0;
 	int loop_i;
-	uint8_t local_flash_read_step=0;
+	uint8_t local_flash_read_step = 0;
 	uint8_t local_flash_complete = 0;
 	uint8_t local_flash_progress = 0;
 	uint8_t local_flash_command = 0;
 	uint8_t local_flash_fail = 0;
 	char *temp_buf;
+
 	local_flash_complete = getFlashDumpComplete();
 	local_flash_progress = getFlashDumpProgress();
 	local_flash_command = getFlashCommand();
 	local_flash_fail = getFlashDumpFail();
 
-	I("flash_progress = %d \n",local_flash_progress);
-	if(!HX_PROC_SEND_FLAG)
-	{
+	I("flash_progress = %d\n", local_flash_progress);
+	if (!HX_PROC_SEND_FLAG) {
 		temp_buf = kzalloc(len, GFP_KERNEL);
-		if (!temp_buf) {
-			HX_PROC_SEND_FLAG=0;
-			return ret;
-		}
-
-		if (local_flash_fail)
-		{
-			ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Fail \n");
-			ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
-			ret += snprintf(temp_buf+ret, len-ret, "\n");
+		if (local_flash_fail) {
+			ret += snprintf(temp_buf + ret, len,
+			"FlashStart:Fail\n");
+			ret += snprintf(temp_buf + ret, len,
+			"FlashEnd");
+			ret += snprintf(temp_buf + ret, len,
+			"\n");
 
 			if (copy_to_user(buf, temp_buf, len))
-			{
 				I("%s,here:%d\n", __func__, __LINE__);
-			}
 
 			kfree(temp_buf);
 			HX_PROC_SEND_FLAG = 1;
 			return ret;
 		}
 
-		if (!local_flash_complete)
-		{
-			ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Ongoing:0x%2.2x \n",flash_progress);
-			ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
-			ret += snprintf(temp_buf+ret, len-ret, "\n");
+		if (!local_flash_complete) {
+			ret += snprintf(temp_buf+ret, len,
+			"FlashStart:Ongoing:0x%2.2x\n", flash_progress);
+			ret += snprintf(temp_buf + ret, len, "FlashEnd");
+			ret += snprintf(temp_buf + ret, len, "\n");
 
 			if (copy_to_user(buf, temp_buf, len))
-			{
 				I("%s,here:%d\n", __func__, __LINE__);
-			}
 
 			kfree(temp_buf);
 			HX_PROC_SEND_FLAG = 1;
 			return ret;
 		}
 
-		if (local_flash_command == 1 && local_flash_complete)
-		{
-			ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Complete \n");
-			ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
-			ret += snprintf(temp_buf+ret, len-ret, "\n");
+		if (local_flash_command == 1 && local_flash_complete) {
+			ret += snprintf(temp_buf+ret, len,
+			"FlashStart:Complete\n");
+			ret += snprintf(temp_buf + ret, len, "FlashEnd");
+			ret += snprintf(temp_buf + ret, len, "\n");
 
 			if (copy_to_user(buf, temp_buf, len))
-			{
 				I("%s,here:%d\n", __func__, __LINE__);
-			}
 
 			kfree(temp_buf);
 			HX_PROC_SEND_FLAG = 1;
 			return ret;
 		}
 
-		if (local_flash_command == 3 && local_flash_complete)
-		{
-			ret += snprintf(temp_buf+ret, len-ret, "FlashStart: \n");
-			for(loop_i = 0; loop_i < 128; loop_i++)
-			{
-				ret += snprintf(temp_buf+ret, len-ret, "x%2.2x", flash_buffer[loop_i]);
+		if (local_flash_command == 3 && local_flash_complete) {
+			ret += snprintf(temp_buf+ret, len, "FlashStart:\n");
+			for (loop_i = 0 ; loop_i < 128 ; loop_i++) {
+				ret += snprintf(temp_buf + ret, len,
+				"x%2.2x", flash_buffer[loop_i]);
 				if ((loop_i % 16) == 15)
-				{
-					ret += snprintf(temp_buf+ret, len-ret, "\n");
-				}
+					ret += snprintf(temp_buf + ret, len,
+					"\n");
 			}
-			ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
-			ret += snprintf(temp_buf+ret, len-ret, "\n");
+			ret += snprintf(temp_buf + ret, len, "FlashEnd");
+			ret += snprintf(temp_buf + ret, len, "\n");
 
 			if (copy_to_user(buf, temp_buf, len))
-			{
 				I("%s,here:%d\n", __func__, __LINE__);
-			}
 
 			kfree(temp_buf);
 			HX_PROC_SEND_FLAG = 1;
 			return ret;
 		}
 
-		//flash command == 0 , report the data
+		/*flash command == 0 , report the data*/
 		local_flash_read_step = getFlashReadStep();
 
-		ret += snprintf(temp_buf+ret, len-ret, "FlashStart:%2.2x \n",local_flash_read_step);
+		ret += snprintf(temp_buf + ret, len,
+		"FlashStart:%2.2x\n", local_flash_read_step);
 
-		for (loop_i = 0; loop_i < 1024; loop_i++)
-		{
-			ret += snprintf(temp_buf+ret, len-ret, "x%2.2X", flash_buffer[local_flash_read_step*1024 + loop_i]);
+		for (loop_i = 0 ; loop_i < 1024 ; loop_i++) {
+			ret += snprintf(temp_buf + ret, len, "x%2.2X",
+			flash_buffer[local_flash_read_step * 1024 + loop_i]);
 
 			if ((loop_i % 16) == 15)
-			{
-				ret += snprintf(temp_buf+ret, len-ret, "\n");
-			}
+				ret += snprintf(temp_buf + ret, len, "\n");
 		}
 
-		ret += snprintf(temp_buf+ret, len-ret, "FlashEnd");
-		ret += snprintf(temp_buf+ret, len-ret, "\n");
+		ret += snprintf(temp_buf + ret, len, "FlashEnd");
+		ret += snprintf(temp_buf + ret, len, "\n");
 		if (copy_to_user(buf, temp_buf, len))
-		{
 			I("%s,here:%d\n", __func__, __LINE__);
-		}
 
 		kfree(temp_buf);
 		HX_PROC_SEND_FLAG = 1;
-	}
-	else
-		HX_PROC_SEND_FLAG=0;
+	} else
+		HX_PROC_SEND_FLAG = 0;
 	return ret;
 }
 
-static ssize_t himax_proc_flash_write(struct file *file, const char *buff,
-	size_t len, loff_t *pos)
+static ssize_t himax_proc_flash_write(struct file *file,
+const char *buff, size_t len, loff_t *pos)
 {
 	char buf_tmp[6];
 	unsigned long result = 0;
@@ -1563,85 +1492,74 @@
 	int base = 0;
 	char buf[80] = {0};
 
-	if (len >= 80)
-	{
+	if (len >= 80) {
 		I("%s: no command exceeds 80 chars.\n", __func__);
 		return -EFAULT;
 	}
 	if (copy_from_user(buf, buff, len))
-	{
 		return -EFAULT;
-	}
 	memset(buf_tmp, 0x0, sizeof(buf_tmp));
 
 	I("%s: buf[0] = %s\n", __func__, buf);
 
-	if (getSysOperation() == 1)
-	{
+	if (getSysOperation() == 1) {
 		E("%s: PROC is busy , return!\n", __func__);
 		return len;
 	}
 
-	if (buf[0] == '0')
-	{
+	if (buf[0] == '0') {
 		setFlashCommand(0);
-		if (buf[1] == ':' && buf[2] == 'x')
-		{
+		if (buf[1] == ':' && buf[2] == 'x') {
 			memcpy(buf_tmp, buf + 3, 2);
 			I("%s: read_Step = %s\n", __func__, buf_tmp);
-			if (!kstrtoul(buf_tmp, 16, &result))
-			{
-				I("%s: read_Step = %lu \n", __func__, result);
+			if (!kstrtoul(buf_tmp, 16, &result)) {
+				I("%s: read_Step = %lu\n", __func__, result);
 				setFlashReadStep(result);
 			}
 		}
-	}
-	else if (buf[0] == '1')// 1_60,1_64,1_24,1_28 for flash size 60k,64k,124k,128k
-	{
+	/* 1_60,1_64,1_24,1_28 for flash size 60k,64k,124k,128k*/
+	} else if (buf[0] == '1') {
+
 		setSysOperation(1);
 		setFlashCommand(1);
 		setFlashDumpProgress(0);
 		setFlashDumpComplete(0);
 		setFlashDumpFail(0);
-		if ((buf[1] == '_' ) && (buf[2] == '6' )){
-			if (buf[3] == '0'){
+		if ((buf[1] == '_') && (buf[2] == '6')) {
+			if (buf[3] == '0')
 				Flash_Size = FW_SIZE_60k;
-			}else if (buf[3] == '4'){
+			else if (buf[3] == '4')
 				Flash_Size = FW_SIZE_64k;
-			}
-		}else if ((buf[1] == '_' ) && (buf[2] == '2' )){
-			if (buf[3] == '4'){
+
+		} else if ((buf[1] == '_') && (buf[2] == '2')) {
+			if (buf[3] == '4')
 				Flash_Size = FW_SIZE_124k;
-			}else if (buf[3] == '8'){
+			else if (buf[3] == '8')
 				Flash_Size = FW_SIZE_128k;
-			}
 		}
 		queue_work(private_ts->flash_wq, &private_ts->flash_work);
-	}
-	else if (buf[0] == '2') // 2_60,2_64,2_24,2_28 for flash size 60k,64k,124k,128k
-	{
+	/* 2_60,2_64,2_24,2_28 for flash size 60k,64k,124k,128k*/
+	} else if (buf[0] == '2') {
 		setSysOperation(1);
 		setFlashCommand(2);
 		setFlashDumpProgress(0);
 		setFlashDumpComplete(0);
 		setFlashDumpFail(0);
-		if ((buf[1] == '_' ) && (buf[2] == '6' )){
-			if (buf[3] == '0'){
+		if ((buf[1] == '_') && (buf[2] == '6')) {
+			if (buf[3] == '0')
 				Flash_Size = FW_SIZE_60k;
-			}else if (buf[3] == '4'){
+			else if (buf[3] == '4')
 				Flash_Size = FW_SIZE_64k;
-			}
-		}else if ((buf[1] == '_' ) && (buf[2] == '2' )){
-			if (buf[3] == '4'){
+
+		} else if ((buf[1] == '_') && (buf[2] == '2')) {
+			if (buf[3] == '4')
 				Flash_Size = FW_SIZE_124k;
-			}else if (buf[3] == '8'){
+			else if (buf[3] == '8')
 				Flash_Size = FW_SIZE_128k;
-			}
+
 		}
 		queue_work(private_ts->flash_wq, &private_ts->flash_work);
-	}
-	else if (buf[0] == '3')
-	{
+	} else if (buf[0] == '3') {
 		setSysOperation(1);
 		setFlashCommand(3);
 		setFlashDumpProgress(0);
@@ -1650,20 +1568,14 @@
 
 		memcpy(buf_tmp, buf + 3, 2);
 		if (!kstrtoul(buf_tmp, 16, &result))
-		{
 			setFlashDumpSector(result);
-		}
 
 		memcpy(buf_tmp, buf + 7, 2);
 		if (!kstrtoul(buf_tmp, 16, &result))
-		{
 			setFlashDumpPage(result);
-		}
 
 		queue_work(private_ts->flash_wq, &private_ts->flash_work);
-	}
-	else if (buf[0] == '4')
-	{
+	} else if (buf[0] == '4') {
 		I("%s: command 4 enter.\n", __func__);
 		setSysOperation(1);
 		setFlashCommand(4);
@@ -1673,40 +1585,29 @@
 
 		memcpy(buf_tmp, buf + 3, 2);
 		if (!kstrtoul(buf_tmp, 16, &result))
-		{
 			setFlashDumpSector(result);
-		}
 		else
-		{
 			E("%s: command 4 , sector error.\n", __func__);
 			return len;
-		}
+
 
 		memcpy(buf_tmp, buf + 7, 2);
 		if (!kstrtoul(buf_tmp, 16, &result))
-		{
 			setFlashDumpPage(result);
-		}
 		else
-		{
 			E("%s: command 4 , page error.\n", __func__);
 			return len;
-		}
 
 		base = 11;
 
 		I("=========Himax flash page buffer start=========\n");
-		for(loop_i=0;loop_i<128 && base<80;loop_i++)
-		{
+		for (loop_i = 0 ; loop_i < 128 ; loop_i++) {
 			memcpy(buf_tmp, buf + base, 2);
-			if (!kstrtoul(buf_tmp, 16, &result))
-			{
+			if (!kstrtoul(buf_tmp, 16, &result)) {
 				flash_buffer[loop_i] = result;
-				I("%d ",flash_buffer[loop_i]);
+				I("%d ", flash_buffer[loop_i]);
 				if (loop_i % 16 == 15)
-				{
 					I("\n");
-				}
 			}
 			base += 3;
 		}
@@ -1717,8 +1618,7 @@
 	return len;
 }
 
-static const struct file_operations himax_proc_flash_ops =
-{
+const struct file_operations himax_proc_flash_ops = {
 	.owner = THIS_MODULE,
 	.read = himax_proc_flash_read,
 	.write = himax_proc_flash_write,
@@ -1728,31 +1628,44 @@
 {
 	uint8_t local_flash_command = 0;
 
-	himax_int_enable(private_ts->client->irq,0);
+	himax_int_enable(private_ts->client->irq, 0);
 	setFlashDumpGoing(true);
 
-	//sector = getFlashDumpSector();
-	//page = getFlashDumpPage();
+	/*sector = getFlashDumpSector();*/
+	/*page = getFlashDumpPage();*/
 
 	local_flash_command = getFlashCommand();
 
 	msleep(100);
 
-	I("%s: local_flash_command = %d enter.\n", __func__,local_flash_command);
+	I("%s: local_flash_command = %d enter.\n",
+	__func__, local_flash_command);
 
-	if ((local_flash_command == 1 || local_flash_command == 2)|| (local_flash_command==0x0F))
-	{
-		himax_flash_dump_func(private_ts->client, local_flash_command,Flash_Size, flash_buffer);
+	if ((local_flash_command == 1 || local_flash_command == 2)
+		|| (local_flash_command == 0x0F)) {
+		himax_flash_dump_func(private_ts->client,
+		local_flash_command, Flash_Size, flash_buffer);
 	}
 
+
 	I("Complete~~~~~~~~~~~~~~~~~~~~~~~\n");
 
-	if (local_flash_command == 2)
-	{
-		E("Flash dump failed\n");
+	if (local_flash_command == 2) {
+		struct file *fn;
+		struct filename *vts_name;
+
+		vts_name = getname_kernel(FLASH_DUMP_FILE);
+		fn = file_open_name(vts_name, O_CREAT | O_WRONLY, 0);
+		if (!IS_ERR(fn)) {
+			I("%s create file and ready to write\n", __func__);
+			fn->f_op->write(fn, flash_buffer,
+			Flash_Size * sizeof(uint8_t), &fn->f_pos);
+
+			filp_close(fn, NULL);
+		}
 	}
 
-	himax_int_enable(private_ts->client->irq,1);
+	himax_int_enable(private_ts->client->irq, 1);
 	setFlashDumpGoing(false);
 
 	setFlashDumpComplete(1);
@@ -1761,7 +1674,7 @@
 
 /*	Flash_Dump_i2c_transfer_error:
 
-	himax_int_enable(private_ts->client->irq,1);
+	himax_int_enable(private_ts->client->irq, 1);
 	setFlashDumpGoing(false);
 	setFlashDumpComplete(0);
 	setFlashDumpFail(1);
@@ -1776,53 +1689,47 @@
 static ssize_t himax_self_test_read(struct file *file, char *buf,
 	size_t len, loff_t *pos)
 {
-	int val=0x00;
+	int val = 0x00;
 	int ret = 0;
 	char *temp_buf;
 
-	I("%s: enter, %d \n", __func__, __LINE__);
-	if(!HX_PROC_SEND_FLAG)
-	{
+	I("%s:enter, %d\n", __func__, __LINE__);
+	if (!HX_PROC_SEND_FLAG) {
 		temp_buf = kzalloc(len, GFP_KERNEL);
-		if (!temp_buf) {
-			HX_PROC_SEND_FLAG=0;
-			return ret;
-		}
-		himax_int_enable(private_ts->client->irq,0);//disable irq
+		himax_int_enable(private_ts->client->irq, 0);/*disable irq*/
 		val = himax_chip_self_test(private_ts->client);
 #ifdef HX_ESD_WORKAROUND
 		HX_ESD_RESET_ACTIVATE = 1;
 #endif
-		himax_int_enable(private_ts->client->irq,1);//enable irq
+		himax_int_enable(private_ts->client->irq, 1);/*enable irq*/
 
 		if (val == 0x01) {
-			ret += snprintf(temp_buf+ret, len-ret, "Self_Test Pass\n");
+			ret += snprintf(temp_buf + ret, len,
+			"Self_Test Pass\n");
 		} else {
-			ret += snprintf(temp_buf+ret, len-ret, "Self_Test Fail\n");
+			ret += snprintf(temp_buf + ret, len,
+			"Self_Test Fail\n");
 		}
-
 		if (copy_to_user(buf, temp_buf, len))
-		{
 			I("%s,here:%d\n", __func__, __LINE__);
-		}
 
 		kfree(temp_buf);
 		HX_PROC_SEND_FLAG = 1;
-	}
-	else
-		HX_PROC_SEND_FLAG=0;
+	} else
+		HX_PROC_SEND_FLAG = 0;
 	return ret;
 }
 
 /*
-static ssize_t himax_chip_self_test_store(struct device *dev,struct device_attribute *attr, const char *buf, size_t count)
+static ssize_t himax_chip_self_test_store(struct device *dev,
+struct device_attribute *attr, const char *buf, size_t count)
 {
 	char buf_tmp[2];
 	unsigned long result = 0;
 
 	memset(buf_tmp, 0x0, sizeof(buf_tmp));
 	memcpy(buf_tmp, buf, 2);
-	if(!kstrtoul(buf_tmp, 16, &result))
+	if (!kstrtoul(buf_tmp, 16, &result))
 		{
 			sel_type = (uint8_t)result;
 		}
@@ -1831,8 +1738,7 @@
 }
 */
 
-static const struct file_operations himax_proc_self_test_ops =
-{
+const struct file_operations himax_proc_self_test_ops = {
 	.owner = THIS_MODULE,
 	.read = himax_self_test_read,
 };
@@ -1844,42 +1750,33 @@
 {
 	char buf[80] = {0};
 
-	if (len >= 80)
-	{
+	if (len >= 80) {
 		I("%s: no command exceeds 80 chars.\n", __func__);
 		return -EFAULT;
 	}
 	if (copy_from_user(buf, buff, len))
-	{
 		return -EFAULT;
-	}
 
-	if(buf[0] == '0')
-	{
+	if (buf[0] == '0') {
 		himax_sense_off(private_ts->client);
-		I("Sense off \n");
-	}
-	else if(buf[0] == '1')
-	{
-		if(buf[1] == '1'){
+		I("Sense off\n");
+	} else if (buf[0] == '1') {
+		if (buf[1] == '1') {
 			himax_sense_on(private_ts->client, 0x01);
-			I("Sense on re-map off, run flash \n");
-		}else if(buf[1] == '0'){
+			I("Sense on re-map off, run flash\n");
+		} else if (buf[1] == '0') {
 			himax_sense_on(private_ts->client, 0x00);
-			I("Sense on re-map on, run sram \n");
-		}else{
-			I("Do nothing \n");
+			I("Sense on re-map on, run sram\n");
+		} else {
+			I("Do nothing\n");
 		}
-	}
-	else
-	{
-		I("Do nothing \n");
+	} else {
+		I("Do nothing\n");
 	}
 	return len;
 }
 
-static const struct file_operations himax_proc_sense_on_off_ops =
-{
+const struct file_operations himax_proc_sense_on_off_ops = {
 	.owner = THIS_MODULE,
 	.write = himax_sense_on_off_write,
 };
@@ -1893,25 +1790,18 @@
 	size_t count = 0;
 	char *temp_buf;
 
-	if(!HX_PROC_SEND_FLAG)
-	{
+	if (!HX_PROC_SEND_FLAG) {
 		temp_buf = kzalloc(len, GFP_KERNEL);
-		if (!temp_buf) {
-			HX_PROC_SEND_FLAG=0;
-			return count;
-		}
 		count = snprintf(temp_buf, len, "%d\n", ts->HSEN_enable);
-		HX_PROC_SEND_FLAG=1;
+		HX_PROC_SEND_FLAG = 1;
 
 		if (copy_to_user(buf, temp_buf, len))
-		{
 			I("%s,here:%d\n", __func__, __LINE__);
-		}
+
 
 		kfree(temp_buf);
-	}
-	else
-		HX_PROC_SEND_FLAG=0;
+	} else
+		HX_PROC_SEND_FLAG = 0;
 	return count;
 }
 
@@ -1922,22 +1812,17 @@
 	char buf[80] = {0};
 
 
-	if (len >= 80)
-	{
+	if (len >= 80) {
 		I("%s: no command exceeds 80 chars.\n", __func__);
 		return -EFAULT;
 	}
 	if (copy_from_user(buf, buff, len))
-	{
 		return -EFAULT;
-	}
 
-	if (buf[0] == '0'){
+	if (buf[0] == '0')
 		ts->HSEN_enable = 0;
-	}
-	else if (buf[0] == '1'){
+	else if (buf[0] == '1')
 		ts->HSEN_enable = 1;
-	}
 	else
 		return -EINVAL;
 
@@ -1948,8 +1833,7 @@
 	return len;
 }
 
-static const struct file_operations himax_proc_HSEN_ops =
-{
+const struct file_operations himax_proc_HSEN_ops = {
 	.owner = THIS_MODULE,
 	.read = himax_HSEN_read,
 	.write = himax_HSEN_write,
@@ -1964,25 +1848,17 @@
 	struct himax_ts_data *ts = private_ts;
 	char *temp_buf;
 
-	if(!HX_PROC_SEND_FLAG)
-	{
+	if (!HX_PROC_SEND_FLAG) {
 		temp_buf = kzalloc(len, GFP_KERNEL);
-		if (!temp_buf) {
-			HX_PROC_SEND_FLAG=0;
-			return count;
-		}
-		count = snprintf(temp_buf, len, "%d\n", ts->SMWP_enable);
+		count = snprintf(temp_buf, "%d\n", len, ts->SMWP_enable);
 
 		if (copy_to_user(buf, temp_buf, len))
-		{
 			I("%s,here:%d\n", __func__, __LINE__);
-		}
 
 		kfree(temp_buf);
-		HX_PROC_SEND_FLAG=1;
-	}
-	else
-		HX_PROC_SEND_FLAG=0;
+		HX_PROC_SEND_FLAG = 1;
+	} else
+		HX_PROC_SEND_FLAG = 0;
 
 	return count;
 }
@@ -1993,25 +1869,17 @@
 	struct himax_ts_data *ts = private_ts;
 	char buf[80] = {0};
 
-	if (len >= 80)
-	{
+	if (len >= 80) {
 		I("%s: no command exceeds 80 chars.\n", __func__);
 		return -EFAULT;
 	}
 	if (copy_from_user(buf, buff, len))
-	{
 		return -EFAULT;
-	}
-
 
 	if (buf[0] == '0')
-	{
 		ts->SMWP_enable = 0;
-	}
 	else if (buf[0] == '1')
-	{
 		ts->SMWP_enable = 1;
-	}
 	else
 		return -EINVAL;
 
@@ -2022,41 +1890,33 @@
 	return len;
 }
 
-static const struct file_operations himax_proc_SMWP_ops =
-{
+const struct file_operations himax_proc_SMWP_ops = {
 	.owner = THIS_MODULE,
 	.read = himax_SMWP_read,
 	.write = himax_SMWP_write,
 };
 
-static ssize_t himax_GESTURE_read(struct file *file, char *buf,
-	size_t len, loff_t *pos)
+static ssize_t himax_GESTURE_read(struct file *file,
+char *buf, size_t len, loff_t *pos)
 {
 	struct himax_ts_data *ts = private_ts;
-	int i =0;
+	int i = 0;
 	int ret = 0;
 	char *temp_buf;
 
-	if(!HX_PROC_SEND_FLAG)
-	{
+	if (!HX_PROC_SEND_FLAG) {
 		temp_buf = kzalloc(len, GFP_KERNEL);
-		if (!temp_buf) {
-			HX_PROC_SEND_FLAG=0;
-			return ret;
-		}
-		for(i=0;i<16;i++)
-			ret += snprintf(temp_buf+ret, len-ret, "ges_en[%d]=%d\n", i, ts->gesture_cust_en[i]);
+		for (i = 0 ; i < 16 ; i++)
+			ret += snprintf(temp_buf + ret, len,
+			"ges_en[%d]=%d\n", i, ts->gesture_cust_en[i]);
+
 		HX_PROC_SEND_FLAG = 1;
 		if (copy_to_user(buf, temp_buf, len))
-		{
 			I("%s,here:%d\n", __func__, __LINE__);
-		}
 
 		kfree(temp_buf);
 		HX_PROC_SEND_FLAG = 1;
-	}
-	else
-	{
+	} else {
 		HX_PROC_SEND_FLAG = 0;
 		ret = 0;
 	}
@@ -2067,35 +1927,30 @@
 	size_t len, loff_t *pos)
 {
 	struct himax_ts_data *ts = private_ts;
-	int i =0;
+	int i = 0;
 	char buf[80] = {0};
 
-	if (len >= 80)
-	{
+	if (len >= 80) {
 		I("%s: no command exceeds 80 chars.\n", __func__);
 		return -EFAULT;
 	}
 	if (copy_from_user(buf, buff, len))
-	{
 		return -EFAULT;
-	}
 
-	I("himax_GESTURE_store= %s \n",buf);
-	for (i=0;i<16;i++)
-	{
+	I("himax_GESTURE_store= %s\n", buf);
+	for (i = 0 ; i < 16 ; i++) {
 		if (buf[i] == '0')
-			ts->gesture_cust_en[i]= 0;
+			ts->gesture_cust_en[i] = 0;
 		else if (buf[i] == '1')
-			ts->gesture_cust_en[i]= 1;
+			ts->gesture_cust_en[i] = 1;
 		else
-			ts->gesture_cust_en[i]= 0;
-		I("gesture en[%d]=%d \n", i, ts->gesture_cust_en[i]);
+			ts->gesture_cust_en[i] = 0;
+		I("gesture en[%d]=%d\n", i, ts->gesture_cust_en[i]);
 	}
 	return len;
 }
 
-static const struct file_operations himax_proc_Gesture_ops =
-{
+const struct file_operations himax_proc_Gesture_ops = {
 	.owner = THIS_MODULE,
 	.read = himax_GESTURE_read,
 	.write = himax_GESTURE_write,
@@ -2104,202 +1959,223 @@
 
 int himax_touch_proc_init(void)
 {
-	himax_touch_proc_dir = proc_mkdir( HIMAX_PROC_TOUCH_FOLDER, NULL);
-	if (himax_touch_proc_dir == NULL)
-	{
+	himax_touch_proc_dir = proc_mkdir(HIMAX_PROC_TOUCH_FOLDER, NULL);
+	if (himax_touch_proc_dir == NULL) {
 		E(" %s: himax_touch_proc_dir file create failed!\n", __func__);
 		return -ENOMEM;
 	}
 
-	himax_proc_debug_level_file = proc_create(HIMAX_PROC_DEBUG_LEVEL_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_level_ops);
-	if (himax_proc_debug_level_file == NULL)
-	{
+	himax_proc_debug_level_file = proc_create(HIMAX_PROC_DEBUG_LEVEL_FILE,
+	(S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_level_ops);
+
+	if (himax_proc_debug_level_file == NULL) {
 		E(" %s: proc debug_level file create failed!\n", __func__);
 		goto fail_1;
 	}
 
-	himax_proc_vendor_file = proc_create(HIMAX_PROC_VENDOR_FILE, (S_IRUGO),himax_touch_proc_dir, &himax_proc_vendor_ops);
-	if(himax_proc_vendor_file == NULL)
-	{
+	himax_proc_vendor_file = proc_create(HIMAX_PROC_VENDOR_FILE,
+	(S_IRUGO), himax_touch_proc_dir, &himax_proc_vendor_ops);
+
+	if (himax_proc_vendor_file == NULL) {
 		E(" %s: proc vendor file create failed!\n", __func__);
 		goto fail_2;
 	}
 
-	himax_proc_attn_file = proc_create(HIMAX_PROC_ATTN_FILE, (S_IRUGO),himax_touch_proc_dir, &himax_proc_attn_ops);
-	if(himax_proc_attn_file == NULL)
-	{
+	himax_proc_attn_file = proc_create(HIMAX_PROC_ATTN_FILE,
+	(S_IRUGO), himax_touch_proc_dir, &himax_proc_attn_ops);
+
+	if (himax_proc_attn_file == NULL) {
 		E(" %s: proc attn file create failed!\n", __func__);
 		goto fail_3;
 	}
 
-	himax_proc_int_en_file = proc_create(HIMAX_PROC_INT_EN_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_int_en_ops);
-	if(himax_proc_int_en_file == NULL)
-	{
+	himax_proc_int_en_file = proc_create(HIMAX_PROC_INT_EN_FILE,
+	(S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_int_en_ops);
+
+	if (himax_proc_int_en_file == NULL) {
 		E(" %s: proc int en file create failed!\n", __func__);
 		goto fail_4;
 	}
 
-	himax_proc_layout_file = proc_create(HIMAX_PROC_LAYOUT_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_layout_ops);
-	if(himax_proc_layout_file == NULL)
-	{
+	himax_proc_layout_file = proc_create(HIMAX_PROC_LAYOUT_FILE,
+	(S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_layout_ops);
+
+	if (himax_proc_layout_file == NULL) {
 		E(" %s: proc layout file create failed!\n", __func__);
 		goto fail_5;
 	}
 
 #ifdef HX_TP_PROC_RESET
-	himax_proc_reset_file = proc_create(HIMAX_PROC_RESET_FILE, (S_IWUSR), himax_touch_proc_dir, &himax_proc_reset_ops);
-	if(himax_proc_reset_file == NULL)
-	{
+	himax_proc_reset_file = proc_create(HIMAX_PROC_RESET_FILE,
+	(S_IWUSR), himax_touch_proc_dir, &himax_proc_reset_ops);
+
+	if (himax_proc_reset_file == NULL) {
 		E(" %s: proc reset file create failed!\n", __func__);
 		goto fail_6;
 	}
 #endif
 
 #ifdef HX_TP_PROC_DIAG
-	himax_proc_diag_file = proc_create(HIMAX_PROC_DIAG_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_diag_ops);
-	if(himax_proc_diag_file == NULL)
-	{
+	himax_proc_diag_file = proc_create(HIMAX_PROC_DIAG_FILE,
+	(S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_diag_ops);
+
+	if (himax_proc_diag_file == NULL) {
 		E(" %s: proc diag file create failed!\n", __func__);
 		goto fail_7;
 	}
-	himax_proc_diag_arrange_file = proc_create(HIMAX_PROC_DIAG_ARR_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_diag_arrange_ops);
-	if(himax_proc_diag_arrange_file == NULL)
-	{
+	himax_proc_diag_arrange_file = proc_create(HIMAX_PROC_DIAG_ARR_FILE,
+	(S_IWUSR | S_IRUGO),
+	himax_touch_proc_dir, &himax_proc_diag_arrange_ops);
+
+	if (himax_proc_diag_arrange_file == NULL) {
 		E(" %s: proc diag file create failed!\n", __func__);
 		goto fail_7_1;
 	}
 #endif
 
 #ifdef HX_TP_PROC_REGISTER
-	himax_proc_register_file = proc_create(HIMAX_PROC_REGISTER_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_register_ops);
-	if(himax_proc_register_file == NULL)
-	{
+	himax_proc_register_file = proc_create(HIMAX_PROC_REGISTER_FILE,
+	(S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_register_ops);
+
+	if (himax_proc_register_file == NULL) {
 		E(" %s: proc register file create failed!\n", __func__);
 		goto fail_8;
 	}
 #endif
 
 #ifdef HX_TP_PROC_DEBUG
-	himax_proc_debug_file = proc_create(HIMAX_PROC_DEBUG_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_ops);
-	if(himax_proc_debug_file == NULL)
-	{
+	himax_proc_debug_file = proc_create(HIMAX_PROC_DEBUG_FILE,
+	(S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_ops);
+
+	if (himax_proc_debug_file == NULL) {
 		E(" %s: proc debug file create failed!\n", __func__);
 		goto fail_9;
 	}
 #endif
 
 #ifdef HX_TP_PROC_FLASH_DUMP
-	himax_proc_flash_dump_file = proc_create(HIMAX_PROC_FLASH_DUMP_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_flash_ops);
-	if(himax_proc_flash_dump_file == NULL)
-	{
+	himax_proc_flash_dump_file = proc_create(HIMAX_PROC_FLASH_DUMP_FILE,
+	(S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_flash_ops);
+
+	if (himax_proc_flash_dump_file == NULL) {
 		E(" %s: proc flash dump file create failed!\n", __func__);
 		goto fail_10;
 	}
 #endif
 
 #ifdef HX_TP_PROC_SELF_TEST
-	himax_proc_self_test_file = proc_create(HIMAX_PROC_SELF_TEST_FILE, (S_IRUGO), himax_touch_proc_dir, &himax_proc_self_test_ops);
-	if(himax_proc_self_test_file == NULL)
-	{
+	himax_proc_self_test_file = proc_create(HIMAX_PROC_SELF_TEST_FILE,
+	(S_IRUGO), himax_touch_proc_dir, &himax_proc_self_test_ops);
+
+	if (himax_proc_self_test_file == NULL) {
 		E(" %s: proc self_test file create failed!\n", __func__);
 		goto fail_11;
 	}
 #endif
 
 #ifdef HX_HIGH_SENSE
-	himax_proc_HSEN_file = proc_create(HIMAX_PROC_HSEN_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_HSEN_ops);
-	if(himax_proc_HSEN_file == NULL)
-	{
+	himax_proc_HSEN_file = proc_create(HIMAX_PROC_HSEN_FILE,
+	(S_IWUSR | S_IRUGO | S_IWUGO),
+	himax_touch_proc_dir, &himax_proc_HSEN_ops);
+
+	if (himax_proc_HSEN_file == NULL) {
 		E(" %s: proc HSEN file create failed!\n", __func__);
 		goto fail_12;
 	}
 #endif
 
 #ifdef HX_SMART_WAKEUP
-	himax_proc_SMWP_file = proc_create(HIMAX_PROC_SMWP_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_SMWP_ops);
-	if(himax_proc_SMWP_file == NULL)
-	{
+	himax_proc_SMWP_file = proc_create(HIMAX_PROC_SMWP_FILE,
+	(S_IWUSR | S_IRUGO | S_IWUGO),
+	himax_touch_proc_dir, &himax_proc_SMWP_ops);
+
+	if (himax_proc_SMWP_file == NULL) {
 		E(" %s: proc SMWP file create failed!\n", __func__);
 		goto fail_13;
 	}
-	himax_proc_GESTURE_file = proc_create(HIMAX_PROC_GESTURE_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_Gesture_ops);
-	if(himax_proc_GESTURE_file == NULL)
-	{
+
+	himax_proc_GESTURE_file = proc_create(HIMAX_PROC_GESTURE_FILE,
+	(S_IWUSR | S_IRUGO | S_IWUGO),
+	himax_touch_proc_dir, &himax_proc_Gesture_ops);
+
+	if (himax_proc_GESTURE_file == NULL) {
 		E(" %s: proc GESTURE file create failed!\n", __func__);
 		goto fail_14;
 	}
 #endif
 
 #ifdef HX_TP_PROC_SENSE_ON_OFF
-	himax_proc_SENSE_ON_OFF_file = proc_create(HIMAX_PROC_SENSE_ON_OFF_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_sense_on_off_ops);
-	if(himax_proc_SENSE_ON_OFF_file == NULL)
-	{
+	himax_proc_SENSE_ON_OFF_file = proc_create(HIMAX_PROC_SENSE_ON_OFF_FILE,
+	(S_IWUSR | S_IRUGO | S_IWUGO),
+	himax_touch_proc_dir, &himax_proc_sense_on_off_ops);
+
+	if (himax_proc_SENSE_ON_OFF_file == NULL) {
 		E(" %s: proc SENSE_ON_OFF file create failed!\n", __func__);
 		goto fail_15;
 	}
 #endif
 
-	return 0 ;
+	return 0;
 
 #ifdef HX_TP_PROC_SENSE_ON_OFF
-	fail_15:
+fail_15:
 #endif
 #ifdef HX_SMART_WAKEUP
-	remove_proc_entry( HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir );
-	fail_14:
-	remove_proc_entry( HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir );
-	fail_13:
+	remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir);
+fail_14:
+	remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir);
+fail_13:
 #endif
 #ifdef HX_HIGH_SENSE
-	remove_proc_entry( HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir );
-	fail_12:
+	remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir);
+fail_12:
 #endif
 #ifdef HX_TP_PROC_SELF_TEST
-	remove_proc_entry( HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir );
-	fail_11:
+	remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir);
+fail_11:
 #endif
 #ifdef HX_TP_PROC_FLASH_DUMP
-	remove_proc_entry( HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir );
-	fail_10:
+	remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir);
+fail_10:
 #endif
 #ifdef HX_TP_PROC_DEBUG
-	remove_proc_entry( HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir );
-	fail_9:
+	remove_proc_entry(HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir);
+fail_9:
 #endif
 #ifdef HX_TP_PROC_REGISTER
-	remove_proc_entry( HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir );
-	fail_8:
+	remove_proc_entry(HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir);
+fail_8:
 #endif
 #ifdef HX_TP_PROC_DIAG
-	remove_proc_entry( HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir );
-	fail_7:
-	remove_proc_entry( HIMAX_PROC_DIAG_ARR_FILE, himax_touch_proc_dir );
-	fail_7_1:
+	remove_proc_entry(HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir);
+fail_7:
+	remove_proc_entry(HIMAX_PROC_DIAG_ARR_FILE, himax_touch_proc_dir);
+fail_7_1:
 #endif
 #ifdef HX_TP_PROC_RESET
-	remove_proc_entry( HIMAX_PROC_RESET_FILE, himax_touch_proc_dir );
-	fail_6:
+	remove_proc_entry(HIMAX_PROC_RESET_FILE, himax_touch_proc_dir);
+fail_6:
 #endif
-	remove_proc_entry( HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir );
-	fail_5: remove_proc_entry( HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir );
-	fail_4: remove_proc_entry( HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir );
-	fail_3: remove_proc_entry( HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir );
-	fail_2: remove_proc_entry( HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir );
-	fail_1: remove_proc_entry( HIMAX_PROC_TOUCH_FOLDER, NULL );
+	remove_proc_entry(HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir);
+fail_5: remove_proc_entry(HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir);
+fail_4: remove_proc_entry(HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir);
+fail_3: remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir);
+fail_2: remove_proc_entry(HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir);
+fail_1: remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL);
 	return -ENOMEM;
 }
 
 void himax_touch_proc_deinit(void)
 {
 #ifdef HX_TP_PROC_SENSE_ON_OFF
-	remove_proc_entry( HIMAX_PROC_SENSE_ON_OFF_FILE, himax_touch_proc_dir );
+	remove_proc_entry(HIMAX_PROC_SENSE_ON_OFF_FILE, himax_touch_proc_dir);
 #endif
 #ifdef HX_SMART_WAKEUP
-	remove_proc_entry( HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir );
-	remove_proc_entry( HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir );
+	remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir);
+	remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir);
 #endif
 #ifdef HX_DOT_VIEW
-	remove_proc_entry( HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir );
+	remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir);
 #endif
 #ifdef HX_TP_PROC_SELF_TEST
 	remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir);
@@ -2308,7 +2184,7 @@
 	remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir);
 #endif
 #ifdef HX_TP_PROC_DEBUG
-	remove_proc_entry( HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir );
+	remove_proc_entry(HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir);
 #endif
 #ifdef HX_TP_PROC_REGISTER
 	remove_proc_entry(HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir);
@@ -2317,13 +2193,13 @@
 	remove_proc_entry(HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir);
 #endif
 #ifdef HX_TP_PROC_RESET
-	remove_proc_entry( HIMAX_PROC_RESET_FILE, himax_touch_proc_dir );
+	remove_proc_entry(HIMAX_PROC_RESET_FILE, himax_touch_proc_dir);
 #endif
-	remove_proc_entry( HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir );
-	remove_proc_entry( HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir );
-	remove_proc_entry( HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir );
-	remove_proc_entry( HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir );
-	remove_proc_entry( HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir );
-	remove_proc_entry( HIMAX_PROC_TOUCH_FOLDER, NULL );
+	remove_proc_entry(HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir);
+	remove_proc_entry(HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir);
+	remove_proc_entry(HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir);
+	remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir);
+	remove_proc_entry(HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir);
+	remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL);
 }
 #endif
diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.h b/drivers/input/touchscreen/hxchipset/himax_debug.h
index 91a7ae2..7a24a17 100644
--- a/drivers/input/touchscreen/hxchipset/himax_debug.h
+++ b/drivers/input/touchscreen/hxchipset/himax_debug.h
@@ -17,7 +17,7 @@
 #include "himax_common.h"
 
 #if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
-	#define HIMAX_PROC_TOUCH_FOLDER 	"android_touch"
+	#define HIMAX_PROC_TOUCH_FOLDER	"android_touch"
 	#define HIMAX_PROC_DEBUG_LEVEL_FILE	"debug_level"
 	#define HIMAX_PROC_VENDOR_FILE		"vendor"
 	#define HIMAX_PROC_ATTN_FILE		"attn"
@@ -33,60 +33,76 @@
 
 	uint8_t HX_PROC_SEND_FLAG;
 
-extern int himax_touch_proc_init(void);
-extern void himax_touch_proc_deinit(void);
-bool getFlashDumpGoing(void);
+	extern int himax_touch_proc_init(void);
+	extern void himax_touch_proc_deinit(void);
+	bool getFlashDumpGoing(void);
+
+	extern struct himax_ic_data *ic_data;
+	extern struct himax_ts_data *private_ts;
+	extern unsigned char	IC_TYPE;
+	extern unsigned char	IC_CHECKSUM;
+
+#ifdef QCT
+	extern irqreturn_t himax_ts_thread(int irq, void *ptr);
+#endif
+#ifdef MTK
+#ifdef CONFIG_OF_TOUCH
+	extern irqreturn_t tpd_eint_interrupt_handler(int irq, void *desc);
+#else
+	extern void tpd_eint_interrupt_handler(void);
+#endif
+#endif
 
 #ifdef HX_TP_PROC_REGISTER
 	#define HIMAX_PROC_REGISTER_FILE	"register"
-	struct proc_dir_entry *himax_proc_register_file;
+	struct proc_dir_entry *himax_proc_register_file = NULL;
 	uint8_t register_command[4];
 #endif
 
 #ifdef HX_TP_PROC_DIAG
 	#define HIMAX_PROC_DIAG_FILE	"diag"
-	struct proc_dir_entry *himax_proc_diag_file;
+	struct proc_dir_entry *himax_proc_diag_file = NULL;
 	#define HIMAX_PROC_DIAG_ARR_FILE	"diag_arr"
-	struct proc_dir_entry *himax_proc_diag_arrange_file;
+	struct proc_dir_entry *himax_proc_diag_arrange_file = NULL;
 
 #ifdef HX_TP_PROC_2T2R
 	static bool Is_2T2R;
 	static uint8_t x_channel_2;
 	static uint8_t y_channel_2;
 	static uint8_t *diag_mutual_2;
-	
-	int16_t *getMutualBuffer_2(void);
-	uint8_t 	getXChannel_2(void);
-	uint8_t 	getYChannel_2(void);
-	
-	void 	setMutualBuffer_2(void);
-	void 	setXChannel_2(uint8_t x);
-	void 	setYChannel_2(uint8_t y);
-#endif
-	uint8_t x_channel;
-	uint8_t y_channel;
-	int16_t *diag_mutual;
-	int16_t *diag_mutual_new;
-	int16_t *diag_mutual_old;
-	uint8_t diag_max_cnt;
 
-	int diag_command;
-	uint8_t diag_coor[128];// = {0xFF};
+	int16_t *getMutualBuffer_2(void);
+	uint8_t	getXChannel_2(void);
+	uint8_t	getYChannel_2(void);
+
+	void	setMutualBuffer_2(void);
+	void	setXChannel_2(uint8_t x);
+	void	setYChannel_2(uint8_t y);
+#endif
+	uint8_t x_channel	= 0;
+	uint8_t y_channel	= 0;
+	int16_t *diag_mutual = NULL;
+	int16_t *diag_mutual_new = NULL;
+	int16_t *diag_mutual_old = NULL;
+	uint8_t diag_max_cnt = 0;
+
+	int diag_command = 0;
+	uint8_t diag_coor[128];/* = {0xFF};*/
 	int16_t diag_self[100] = {0};
 
 	int16_t *getMutualBuffer(void);
 	int16_t *getMutualNewBuffer(void);
 	int16_t *getMutualOldBuffer(void);
 	int16_t *getSelfBuffer(void);
-	uint8_t 	getDiagCommand(void);
-	uint8_t 	getXChannel(void);
-	uint8_t 	getYChannel(void);
-	
-	void 	setMutualBuffer(void);
-	void 	setMutualNewBuffer(void);
-	void 	setMutualOldBuffer(void);
-	void 	setXChannel(uint8_t x);
-	void 	setYChannel(uint8_t y);
+	uint8_t	getDiagCommand(void);
+	uint8_t	getXChannel(void);
+	uint8_t	getYChannel(void);
+
+	void	setMutualBuffer(void);
+	void	setMutualNewBuffer(void);
+	void	setMutualOldBuffer(void);
+	void	setXChannel(uint8_t x);
+	void	setYChannel(uint8_t y);
 	uint8_t	coordinate_dump_enable = 0;
 	struct file	*coordinate_fn;
 #endif
@@ -106,24 +122,24 @@
 	struct proc_dir_entry *himax_proc_flash_dump_file = NULL;
 
 	static int Flash_Size = 131072;
-	static uint8_t *flash_buffer 				= NULL;
-	static uint8_t flash_command 				= 0;
-	static uint8_t flash_read_step 			= 0;
-	static uint8_t flash_progress 			= 0;
-	static uint8_t flash_dump_complete	= 0;
-	static uint8_t flash_dump_fail 			= 0;
-	static uint8_t sys_operation				= 0;
-	static uint8_t flash_dump_sector	 	= 0;
-	static uint8_t flash_dump_page 			= 0;
-	static bool    flash_dump_going			= false;
+	static uint8_t *flash_buffer;
+	static uint8_t flash_command;
+	static uint8_t flash_read_step;
+	static uint8_t flash_progress;
+	static uint8_t flash_dump_complete;
+	static uint8_t flash_dump_fail;
+	static uint8_t sys_operation;
+	static uint8_t flash_dump_sector;
+	static uint8_t flash_dump_page;
+	static bool    flash_dump_going;
 
 	static uint8_t getFlashCommand(void);
 	static uint8_t getFlashDumpComplete(void);
 	static uint8_t getFlashDumpFail(void);
 	static uint8_t getFlashDumpProgress(void);
 	static uint8_t getFlashReadStep(void);
-	//static uint8_t getFlashDumpSector(void);
-	//static uint8_t getFlashDumpPage(void);
+	/*static uint8_t getFlashDumpSector(void);*/
+	/*static uint8_t getFlashDumpPage(void);*/
 
 	void setFlashBuffer(void);
 	uint8_t getSysOperation(void);
@@ -150,8 +166,8 @@
 
 #ifdef HX_TP_PROC_RESET
 #define HIMAX_PROC_RESET_FILE		"reset"
-extern void himax_HW_reset(uint8_t loadconfig,uint8_t int_off);
-struct proc_dir_entry *himax_proc_reset_file 		= NULL;
+extern void himax_HW_reset(uint8_t loadconfig, uint8_t int_off);
+struct proc_dir_entry *himax_proc_reset_file;
 #endif
 
 #ifdef HX_HIGH_SENSE
@@ -165,16 +181,16 @@
 #endif
 
 #ifdef HX_RST_PIN_FUNC
-	void himax_HW_reset(uint8_t loadconfig,uint8_t int_off);
+	void himax_HW_reset(uint8_t loadconfig, uint8_t int_off);
 #endif
 
 #ifdef HX_SMART_WAKEUP
 #define HIMAX_PROC_SMWP_FILE "SMWP"
-struct proc_dir_entry *himax_proc_SMWP_file = NULL;
+struct proc_dir_entry *himax_proc_SMWP_file;
 #define HIMAX_PROC_GESTURE_FILE "GESTURE"
-struct proc_dir_entry *himax_proc_GESTURE_file = NULL;
-uint8_t HX_SMWP_EN = 0;
-//extern bool FAKE_POWER_KEY_SEND;
+struct proc_dir_entry *himax_proc_GESTURE_file;
+uint8_t HX_SMWP_EN;
+/*extern bool FAKE_POWER_KEY_SEND;*/
 #endif
 
 #endif
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic.c b/drivers/input/touchscreen/hxchipset/himax_ic.c
index 6ad8dc0..e2934c2 100644
--- a/drivers/input/touchscreen/hxchipset/himax_ic.c
+++ b/drivers/input/touchscreen/hxchipset/himax_ic.c
@@ -15,45 +15,31 @@
 
 #include "himax_ic.h"
 
-static unsigned char i_TP_CRC_FW_128K[]=
-{
-	#include "HX_CRC_128.i"
-};
-static unsigned char i_TP_CRC_FW_64K[]=
-{
-	#include "HX_CRC_64.i"
-};
-static unsigned char i_TP_CRC_FW_124K[]=
-{
-	#include "HX_CRC_124.i"
-};
-static unsigned char i_TP_CRC_FW_60K[]=
-{
-	#include "HX_CRC_60.i"
-};
+const struct firmware *i_TP_CRC_FW_128K;
+const struct firmware *i_TP_CRC_FW_64K;
+const struct firmware *i_TP_CRC_FW_124K;
+const struct firmware *i_TP_CRC_FW_60K;
 
+unsigned long FW_VER_MAJ_FLASH_ADDR;
+unsigned long FW_VER_MAJ_FLASH_LENG;
+unsigned long FW_VER_MIN_FLASH_ADDR;
+unsigned long FW_VER_MIN_FLASH_LENG;
+unsigned long CFG_VER_MAJ_FLASH_ADDR;
+unsigned long CFG_VER_MAJ_FLASH_LENG;
+unsigned long CFG_VER_MIN_FLASH_ADDR;
+unsigned long CFG_VER_MIN_FLASH_LENG;
 
-unsigned long	FW_VER_MAJ_FLASH_ADDR;
-unsigned long 	FW_VER_MAJ_FLASH_LENG;
-unsigned long 	FW_VER_MIN_FLASH_ADDR;
-unsigned long 	FW_VER_MIN_FLASH_LENG;
-unsigned long 	CFG_VER_MAJ_FLASH_ADDR;
-unsigned long 	CFG_VER_MAJ_FLASH_LENG;
-unsigned long 	CFG_VER_MIN_FLASH_ADDR;
-unsigned long 	CFG_VER_MIN_FLASH_LENG;
+unsigned char IC_TYPE;
+unsigned char IC_CHECKSUM;
 
-unsigned char	IC_TYPE = 0;
-unsigned char	IC_CHECKSUM = 0;
-
-extern struct himax_ic_data* ic_data;
-
-int himax_hand_shaking(struct i2c_client *client)    //0:Running, 1:Stop, 2:I2C Fail
+ /*0:Running, 1:Stop, 2:I2C Fail*/
+int himax_hand_shaking(struct i2c_client *client)
 {
 	int ret, result;
 	uint8_t hw_reset_check[1];
 	uint8_t hw_reset_check_2[1];
 	uint8_t buf0[2];
-	uint8_t	IC_STATUS_CHECK = 0xAA;	
+	uint8_t	IC_STATUS_CHECK = 0xAA;
 
 	memset(hw_reset_check, 0x00, sizeof(hw_reset_check));
 	memset(hw_reset_check_2, 0x00, sizeof(hw_reset_check_2));
@@ -67,45 +53,50 @@
 		IC_STATUS_CHECK = 0xAA;
 	}
 
-	ret = i2c_himax_master_write(client, buf0, 2, HIMAX_I2C_RETRY_TIMES);
+	ret = i2c_himax_master_write(client,
+	buf0, 2, HIMAX_I2C_RETRY_TIMES);
 	if (ret < 0) {
-		E("[Himax]:write 0xF2 failed line: %d \n",__LINE__);
+		E("[Himax]:write 0xF2 failed line: %d\n", __LINE__);
 		goto work_func_send_i2c_msg_fail;
 	}
-	msleep(50); 
-  	
+	msleep(50);
+
 	buf0[0] = 0xF2;
 	buf0[1] = 0x00;
-	ret = i2c_himax_master_write(client, buf0, 2, HIMAX_I2C_RETRY_TIMES);
+	ret = i2c_himax_master_write(client,
+	buf0, 2, HIMAX_I2C_RETRY_TIMES);
 	if (ret < 0) {
-		E("[Himax]:write 0x92 failed line: %d \n",__LINE__);
+		E("[Himax]:write 0x92 failed line: %d\n", __LINE__);
 		goto work_func_send_i2c_msg_fail;
 	}
-	usleep_range(2000, 4000);
-  	
-	ret = i2c_himax_read(client, 0xD1, hw_reset_check, 1, HIMAX_I2C_RETRY_TIMES);
+	usleep_range(1999, 2000);
+
+	ret = i2c_himax_read(client, 0xD1,
+	hw_reset_check, 1, HIMAX_I2C_RETRY_TIMES);
 	if (ret < 0) {
-		E("[Himax]:i2c_himax_read 0xD1 failed line: %d \n",__LINE__);
+		E("[Himax]:i2c_himax_read 0xD1 failed line: %d\n", __LINE__);
 		goto work_func_send_i2c_msg_fail;
 	}
-	
-	if ((IC_STATUS_CHECK != hw_reset_check[0])) {
-		usleep_range(2000, 4000);
-		ret = i2c_himax_read(client, 0xD1, hw_reset_check_2, 1, HIMAX_I2C_RETRY_TIMES);
+
+	if (IC_STATUS_CHECK != hw_reset_check[0]) {
+		usleep_range(1999, 2000);
+		ret = i2c_himax_read(client, 0xD1,
+		hw_reset_check_2, 1, HIMAX_I2C_RETRY_TIMES);
 		if (ret < 0) {
-			E("[Himax]:i2c_himax_read 0xD1 failed line: %d \n",__LINE__);
+			E("[Himax]:i2c_himax_read 0xD1 failed line: %d\n",
+			__LINE__);
 			goto work_func_send_i2c_msg_fail;
 		}
-	
-		if (hw_reset_check[0] == hw_reset_check_2[0]) {
-			result = 1; 
-		} else {
-			result = 0; 
-		}
+
+		if (hw_reset_check[0] == hw_reset_check_2[0])
+			result = 1;
+		else
+			result = 0;
+
 	} else {
-		result = 0; 
+		result = 0;
 	}
-	
+
 	return result;
 
 work_func_send_i2c_msg_fail:
@@ -117,66 +108,71 @@
 	uint8_t tmp_addr[4];
 	uint8_t tmp_data[4];
 
-	if(diag_command != 0)
+	if (diag_command != 0)
 		diag_command = diag_command + 5;
 
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0x80;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = diag_command;
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
+	tmp_addr[1] = 0x01; tmp_addr[0] = 0x80;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = diag_command;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 }
 
-void himax_flash_dump_func(struct i2c_client *client, uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer)
+void himax_flash_dump_func(struct i2c_client *client,
+uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer)
 {
-	//struct himax_ts_data *ts = container_of(work, struct himax_ts_data, flash_work);
-
-//	uint8_t sector = 0;
-//	uint8_t page = 0;
+	/*struct himax_ts_data *ts =
+	container_of(work, struct himax_ts_data, flash_work);*/
+	/*uint8_t sector = 0;*/
+	/*uint8_t page = 0;*/
 	uint8_t tmp_addr[4];
 	uint8_t tmp_data[4];
 	uint8_t out_buffer[20];
-	uint8_t in_buffer[260] = {0};
+	uint8_t in_buffer[260];
 	int page_prog_start = 0;
 	int i = 0;
 
 	himax_sense_off(client);
 	himax_burst_enable(client, 0);
 	/*=============Dump Flash Start=============*/
-	//=====================================
-	// SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
-	//=====================================
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+	/*=====================================*/
+	/* SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780*/
+	/*=====================================*/
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+	tmp_data[1] = 0x07; tmp_data[0] = 0x80;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-	for (page_prog_start = 0; page_prog_start < Flash_Size; page_prog_start = page_prog_start + 256)
-	{
-		//=================================
-		// SPI Transfer Control
-		// Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
-		// Set read start address  : 0x8000_0028 ==> 0x0000_0000
-		// Set command			   : 0x8000_0024 ==> 0x0000_003B
-		//=================================
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-		tmp_data[3] = 0x69; tmp_data[2] = 0x40; tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
+	for (page_prog_start = 0 ; page_prog_start < Flash_Size;
+		page_prog_start = page_prog_start + 256) {
+		/*=====================================
+		SPI Transfer Control
+		Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
+		Set read start address  : 0x8000_0028 ==> 0x0000_0000
+		Set command			   : 0x8000_0024 ==> 0x0000_003B
+		=====================================*/
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+		tmp_data[3] = 0x69; tmp_data[2] = 0x40;
+		tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
 		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
-		if (page_prog_start < 0x100)
-		{
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+		if (page_prog_start < 0x100) {
 			tmp_data[3] = 0x00;
 			tmp_data[2] = 0x00;
 			tmp_data[1] = 0x00;
 			tmp_data[0] = (uint8_t)page_prog_start;
-		}
-		else if (page_prog_start >= 0x100 && page_prog_start < 0x10000)
-		{
+		} else if (page_prog_start >= 0x100
+			&& page_prog_start < 0x10000) {
 			tmp_data[3] = 0x00;
 			tmp_data[2] = 0x00;
 			tmp_data[1] = (uint8_t)(page_prog_start >> 8);
 			tmp_data[0] = (uint8_t)page_prog_start;
-		}
-		else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000)
-		{
+		} else if (page_prog_start >= 0x10000
+			&& page_prog_start < 0x1000000) {
 			tmp_data[3] = 0x00;
 			tmp_data[2] = (uint8_t)(page_prog_start >> 16);
 			tmp_data[1] = (uint8_t)(page_prog_start >> 8);
@@ -184,43 +180,46 @@
 		}
 		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
-		tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
 		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-		//==================================
-		// AHB_I2C Burst Read
-		// Set SPI data register : 0x8000_002C ==> 0x00
-		//==================================
+		/*=====================================
+		AHB_I2C Burst Read
+		Set SPI data register : 0x8000_002C ==> 0x00
+		=====================================*/
 		out_buffer[0] = 0x2C;
 		out_buffer[1] = 0x00;
 		out_buffer[2] = 0x00;
 		out_buffer[3] = 0x80;
-		i2c_himax_write(client, 0x00 ,out_buffer, 4, 3);
+		i2c_himax_write(client, 0x00, out_buffer, 4, 3);
 
-		//==================================
-		// Read access : 0x0C ==> 0x00
-		//==================================
+		/*=====================================
+		Read access : 0x0C ==> 0x00
+		=====================================*/
 		out_buffer[0] = 0x00;
-		i2c_himax_write(client, 0x0C ,out_buffer, 1, 3);
+		i2c_himax_write(client, 0x0C, out_buffer, 1, 3);
 
-		//==================================
-		// Read 128 bytes two times
-		//==================================
-		i2c_himax_read(client, 0x08 ,in_buffer, 128, 3);
-		for (i = 0; i < 128; i++)
-			flash_buffer[i + page_prog_start] = in_buffer[i];
+		/*=====================================
+		Read 128 bytes two times
+		=====================================*/
+		i2c_himax_read(client, 0x08, in_buffer, 128, 3);
+		for (i = 0 ; i < 128 ; i++)
+			flash_buffer[i + page_prog_start]
+			= in_buffer[i];
 
-		i2c_himax_read(client, 0x08 ,in_buffer, 128, 3);
-		for (i = 0; i < 128; i++)
-			flash_buffer[(i + 128) + page_prog_start] = in_buffer[i];
+		i2c_himax_read(client, 0x08 , in_buffer, 128, 3);
+		for (i = 0 ; i < 128 ; i++)
+			flash_buffer[(i + 128) + page_prog_start]
+			= in_buffer[i];
 
 		I("%s:Verify Progress: %x\n", __func__, page_prog_start);
 	}
 
 /*=============Dump Flash End=============*/
-		//msleep(100);
-		/*
+		/*//msleep(100);
 		for( i=0 ; i<8 ;i++)
 		{
 			for(j=0 ; j<64 ; j++)
@@ -239,7 +238,7 @@
 {
 	uint8_t tmp_addr[4];
 	uint8_t tmp_data[128];
-	int pf_value=0x00;
+	int pf_value = 0x00;
 	uint8_t test_result_id = 0;
 	int j;
 
@@ -249,19 +248,24 @@
 	himax_interface_on(client);
 	himax_sense_off(client);
 
-	//Set criteria
+	/*Set criteria*/
 	himax_burst_enable(client, 1);
 
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x94;
-	tmp_data[3] = 0x14; tmp_data[2] = 0xC8; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-	tmp_data[7] = 0x13; tmp_data[6] = 0x60; tmp_data[5] = 0x0A; tmp_data[4] = 0x99;
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+	tmp_addr[1] = 0x80; tmp_addr[0] = 0x94;
+	tmp_data[3] = 0x14; tmp_data[2] = 0xC8;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+	tmp_data[7] = 0x13; tmp_data[6] = 0x60;
+	tmp_data[5] = 0x0A; tmp_data[4] = 0x99;
 
-	himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 8);
+	himax_flash_write_burst_length(client, tmp_addr, tmp_data, 8);
 
-	//start selftest
-	// 0x9008_805C ==> 0x0000_0001
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x5C;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+	/*start selftest*/
+	/* 0x9008_805C ==> 0x0000_0001*/
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+	tmp_addr[1] = 0x80; tmp_addr[0] = 0x5C;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x01;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
 	himax_sense_on(client, 1);
@@ -271,19 +275,21 @@
 	himax_sense_off(client);
 	msleep(20);
 
-	//=====================================
-	// Read test result ID : 0x9008_8078 ==> 0xA/0xB/0xC/0xF
-	//=====================================
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x78;
+	/*=====================================
+	Read test result ID : 0x9008_8078 ==> 0xA/0xB/0xC/0xF
+	=====================================*/
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+	tmp_addr[1] = 0x80; tmp_addr[0] = 0x78;
 	himax_register_read(client, tmp_addr, 1, tmp_data);
 
 	test_result_id = tmp_data[0];
 
-	I("%s: check test result, test_result_id=%x, test_result=%x\n", __func__
-	,test_result_id,tmp_data[0]);
+	I("%s: check test result, test_result_id=%x, test_result=%x\n",
+	__func__ , test_result_id, tmp_data[0]);
 
-	if (test_result_id==0xF) {
+	if (test_result_id == 0xF) {
 		I("[Himax]: self-test pass\n");
 		pf_value = 0x1;
 	} else {
@@ -292,22 +298,28 @@
 	}
 	himax_burst_enable(client, 1);
 
-	for (j = 0;j < 10; j++){
-		tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-		tmp_addr[3] = 0x90; tmp_addr[2] = 0x06; tmp_addr[1] = 0x00; tmp_addr[0] = 0x0C;
+	for (j = 0 ; j < 10 ; j++) {
+		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+		tmp_addr[3] = 0x90; tmp_addr[2] = 0x06;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x0C;
 		himax_register_read(client, tmp_addr, 1, tmp_data);
 		I("[Himax]: 9006000C = %d\n", tmp_data[0]);
-		if (tmp_data[0] != 0){
-		tmp_data[3] = 0x90; tmp_data[2] = 0x06; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-		if ( i2c_himax_write(client, 0x00 ,tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
-			E("%s: i2c access fail!\n", __func__);
-		}
-		tmp_data[0] = 0x00;
-		if ( i2c_himax_write(client, 0x0C ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
-			E("%s: i2c access fail!\n", __func__);
-		}
-			i2c_himax_read(client, 0x08, tmp_data, 124,HIMAX_I2C_RETRY_TIMES);
-		}else{
+		if (tmp_data[0] != 0) {
+			tmp_data[3] = 0x90; tmp_data[2] = 0x06;
+			tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+			if (i2c_himax_write(client, 0x00,
+			tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+				E("%s: i2c access fail!\n", __func__);
+			}
+			tmp_data[0] = 0x00;
+			if (i2c_himax_write(client, 0x0C,
+			tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+				E("%s: i2c access fail!\n", __func__);
+			}
+				i2c_himax_read(client, 0x08,
+				tmp_data, 124, HIMAX_I2C_RETRY_TIMES);
+		} else {
 			break;
 		}
 	}
@@ -324,15 +336,18 @@
 	uint8_t tmp_data[4];
 
 	himax_burst_enable(client, 0);
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = HSEN_enable;
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+	tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = HSEN_enable;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 }
-void himax_get_HSEN_enable(struct i2c_client *client,uint8_t *tmp_data)
+void himax_get_HSEN_enable(struct i2c_client *client, uint8_t *tmp_data)
 {
 	uint8_t tmp_addr[4];
 
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+	tmp_addr[1] = 0x80; tmp_addr[0] = 0x50;
 	himax_register_read(client, tmp_addr, 1, tmp_data);
 }
 
@@ -341,206 +356,232 @@
 	uint8_t tmp_addr[4];
 	uint8_t tmp_data[4];
 
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = SMWP_enable;
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+	tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = SMWP_enable;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 }
 
-void himax_get_SMWP_enable(struct i2c_client *client,uint8_t *tmp_data)
+void himax_get_SMWP_enable(struct i2c_client *client,
+uint8_t *tmp_data)
 {
 	uint8_t tmp_addr[4];
 
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+	tmp_addr[1] = 0x80; tmp_addr[0] = 0x54;
 	himax_register_read(client, tmp_addr, 1, tmp_data);
 }
 
 int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte)
 {
 	uint8_t tmp_data[4];
+	int err = -1;
 
 	tmp_data[0] = 0x31;
-	if ( i2c_himax_write(client, 0x13 ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+
+	if (i2c_himax_write(client, 0x13,
+	tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
-		return -EBUSY;
+		return err;
 	}
-	
+
 	tmp_data[0] = (0x10 | auto_add_4_byte);
-	if ( i2c_himax_write(client, 0x0D ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(client, 0x0D,
+	tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
-		return -EBUSY;
+		return err;
 	}
 	return 0;
 
 }
 
-void himax_register_read(struct i2c_client *client, uint8_t *read_addr, int read_length, uint8_t *read_data)
+void himax_register_read(struct i2c_client *client,
+uint8_t *read_addr, int read_length, uint8_t *read_data)
 {
 	uint8_t tmp_data[4];
 	int i = 0;
 	int address = 0;
 
-	if(read_length>256)
-	{
+	if (read_length > 256) {
 		E("%s: read len over 256!\n", __func__);
 		return;
 	}
 	if (read_length > 1)
 		himax_burst_enable(client, 1);
 	else
-	himax_burst_enable(client, 0);
-	address = (read_addr[3] << 24) + (read_addr[2] << 16) + (read_addr[1] << 8) + read_addr[0];
+		himax_burst_enable(client, 0);
+
+	address = (read_addr[3] << 24) +
+	(read_addr[2] << 16) +
+	(read_addr[1] << 8) +
+	read_addr[0];
+
 	i = address;
-		tmp_data[0] = (uint8_t)i;
-		tmp_data[1] = (uint8_t)(i >> 8);
-		tmp_data[2] = (uint8_t)(i >> 16);
-		tmp_data[3] = (uint8_t)(i >> 24);
-		if ( i2c_himax_write(client, 0x00 ,tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
-				E("%s: i2c access fail!\n", __func__);
-				return;
-		 	}
-		tmp_data[0] = 0x00;
-		if ( i2c_himax_write(client, 0x0C ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
-				E("%s: i2c access fail!\n", __func__);
-				return;
-		 	}
-		
-		if ( i2c_himax_read(client, 0x08 ,read_data, read_length * 4, HIMAX_I2C_RETRY_TIMES) < 0) {
-			E("%s: i2c access fail!\n", __func__);
-			return;
-		}
+	tmp_data[0] = (uint8_t)i;
+	tmp_data[1] = (uint8_t)(i >> 8);
+	tmp_data[2] = (uint8_t)(i >> 16);
+	tmp_data[3] = (uint8_t)(i >> 24);
+	if (i2c_himax_write(client, 0x00,
+	tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+		E("%s: i2c access fail!\n", __func__);
+		return;
+	}
+	tmp_data[0] = 0x00;
+	if (i2c_himax_write(client, 0x0C,
+	tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+		E("%s: i2c access fail!\n", __func__);
+		return;
+	}
+	if (i2c_himax_read(client, 0x08,
+	read_data, read_length * 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+		E("%s: i2c access fail!\n", __func__);
+		return;
+	}
 	if (read_length > 1)
 		himax_burst_enable(client, 0);
 }
 
-void himax_flash_read(struct i2c_client *client, uint8_t *reg_byte, uint8_t *read_data)
+void himax_flash_read(struct i2c_client *client,
+uint8_t *reg_byte, uint8_t *read_data)
 {
-    uint8_t tmpbyte[2];
-    
-    if ( i2c_himax_write(client, 0x00 ,&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	uint8_t tmpbyte[2];
+
+	if (i2c_himax_write(client, 0x00,
+	&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_write(client, 0x01 ,&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(client, 0x01,
+	&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_write(client, 0x02 ,&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(client, 0x02,
+	&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_write(client, 0x03 ,&reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(client, 0x03,
+	&reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-    tmpbyte[0] = 0x00;
-    if ( i2c_himax_write(client, 0x0C ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	tmpbyte[0] = 0x00;
+	if (i2c_himax_write(client, 0x0C,
+	&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_read(client, 0x08 ,&read_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_read(client, 0x08,
+	&read_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_read(client, 0x09 ,&read_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_read(client, 0x09,
+	&read_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_read(client, 0x0A ,&read_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_read(client, 0x0A,
+	&read_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_read(client, 0x0B ,&read_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_read(client, 0x0B,
+	&read_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_read(client, 0x18 ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_read(client, 0x18,
+	&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
-	}// No bus request
+	} /* No bus request*/
 
-	if ( i2c_himax_read(client, 0x0F ,&tmpbyte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_read(client, 0x0F,
+	&tmpbyte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
-	}// idle state
+	} /* idle state*/
 
 }
 
-void himax_flash_write_burst(struct i2c_client *client, uint8_t * reg_byte, uint8_t * write_data)
+void himax_flash_write_burst(struct i2c_client *client,
+uint8_t *reg_byte, uint8_t *write_data)
 {
-    uint8_t data_byte[8];
+	uint8_t data_byte[8];
 	int i = 0, j = 0;
 
-     for (i = 0; i < 4; i++)
-     { 
-         data_byte[i] = reg_byte[i];
-     }
-     for (j = 4; j < 8; j++)
-     {
-         data_byte[j] = write_data[j-4];
-     }
-	 
-	 if ( i2c_himax_write(client, 0x00 ,data_byte, 8, HIMAX_I2C_RETRY_TIMES) < 0) {
-		 E("%s: i2c access fail!\n", __func__);
-		 return;
-	 }
+	for (i = 0 ; i < 4; i++)
+		data_byte[i] = reg_byte[i];
 
-}
+	for (j = 4 ; j < 8; j++)
+		data_byte[j] = write_data[j-4];
 
-int himax_flash_write_burst_lenth(struct i2c_client *client, uint8_t *reg_byte, uint8_t *write_data, int length)
-{
-    uint8_t data_byte[256];
-	int i = 0, j = 0;
-
-    for (i = 0; i < 4; i++)
-    {
-        data_byte[i] = reg_byte[i];
-    }
-    for (j = 4; j < length + 4; j++)
-    {
-        data_byte[j] = write_data[j - 4];
-    }
-   
-	if ( i2c_himax_write(client, 0x00 ,data_byte, length + 4, HIMAX_I2C_RETRY_TIMES) < 0) {
-		 E("%s: i2c access fail!\n", __func__);
-		 return -EBUSY;
+	if (i2c_himax_write(client, 0x00,
+		data_byte, 8, HIMAX_I2C_RETRY_TIMES) < 0) {
+		E("%s: i2c access fail!\n", __func__);
+		return;
 	}
 
-    return 0;
 }
 
-int himax_register_write(struct i2c_client *client, uint8_t *write_addr, int write_length, uint8_t *write_data)
+int himax_flash_write_burst_length(struct i2c_client *client,
+uint8_t *reg_byte, uint8_t *write_data, int length)
 {
-	int i =0, address = 0;
-	int ret = 0;
+	uint8_t data_byte[256];
+	int i = 0, j = 0, err = -1;
 
-	address = (write_addr[3] << 24) + (write_addr[2] << 16) + (write_addr[1] << 8) + write_addr[0];
+	for (i = 0 ; i < 4 ; i++)
+		data_byte[i] = reg_byte[i];
 
-	for (i = address; i < address + write_length * 4; i = i + 4)
-	{
-		if (write_length > 1)
-		{
+	for (j = 4 ; j < length + 4 ; j++)
+		data_byte[j] = write_data[j - 4];
+
+	if (i2c_himax_write(client, 0x00,
+	data_byte, length + 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+		E("%s: i2c access fail!\n", __func__);
+		return err;
+	}
+	return 0;
+}
+
+int himax_register_write(struct i2c_client *client,
+uint8_t *write_addr, int write_length, uint8_t *write_data)
+{
+	int i = 0, address = 0;
+	int ret = 0, err = -1;
+
+	address = (write_addr[3] << 24) +
+				(write_addr[2] << 16) +
+				(write_addr[1] << 8) +
+				write_addr[0];
+
+	for (i = address ; i < address + write_length * 4;
+		i = i + 4) {
+		if (write_length > 1) {
 			ret = himax_burst_enable(client, 1);
-			if(ret)
-				return ret;
-		}
-		else
-		{
+			if (ret)
+				return err;
+		} else {
 			ret = himax_burst_enable(client, 0);
-			if(ret)
-				return ret;
+			if (ret)
+				return err;
 		}
-	ret = himax_flash_write_burst_lenth(client, write_addr, write_data, write_length * 4);
-	if(ret < 0)
-		return ret;
+	ret = himax_flash_write_burst_length(client,
+		write_addr, write_data, write_length * 4);
+	if (ret < 0)
+		return err;
 	}
 
 	return 0;
@@ -550,50 +591,62 @@
 {
 	uint8_t wdt_off = 0x00;
 	uint8_t tmp_addr[4];
-	uint8_t tmp_data[5];	
+	uint8_t tmp_data[5];
 
 	himax_burst_enable(client, 0);
 
-	while(wdt_off == 0x00)
-	{
-		// 0x9000_800C ==> 0x0000_AC53
-		tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
-		tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0xAC; tmp_data[0] = 0x53;
+	while (wdt_off == 0x00) {
+		/* 0x9000_800C ==> 0x0000_AC53*/
+		tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
+		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0xAC; tmp_data[0] = 0x53;
 		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-		//=====================================
-    // Read Watch Dog disable password : 0x9000_800C ==> 0x0000_AC53
-    //=====================================
-		tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
+		/*=====================================*/
+		/* Read Watch Dog disable password :
+		0x9000_800C ==> 0x0000_AC53 */
+		/*=====================================*/
+		tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C;
 		himax_register_read(client, tmp_addr, 1, tmp_data);
-		
-		//Check WDT
-		if (tmp_data[0] == 0x53 && tmp_data[1] == 0xAC && tmp_data[2] == 0x00 && tmp_data[3] == 0x00)
+
+		/*Check WDT*/
+		if (tmp_data[0] == 0x53 && tmp_data[1] == 0xAC
+		&& tmp_data[2] == 0x00 && tmp_data[3] == 0x00)
 			wdt_off = 0x01;
 		else
 			wdt_off = 0x00;
 	}
 
-	// VCOM		//0x9008_806C ==> 0x0000_0001
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x6C;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+	/* VCOM		//0x9008_806C ==> 0x0000_0001*/
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x08;
+	tmp_addr[1] = 0x80; tmp_addr[0] = 0x6C;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x01;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
 	msleep(20);
 
-	// 0x9000_0010 ==> 0x0000_00DA
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xDA;
+	/* 0x9000_0010 ==> 0x0000_00DA*/
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0xDA;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-	//=====================================
-	// Read CPU clock off password : 0x9000_0010 ==> 0x0000_00DA
-	//=====================================
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+	/*=====================================
+	Read CPU clock off password : 0x9000_0010 ==> 0x0000_00DA
+	=====================================*/
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
 	himax_register_read(client, tmp_addr, 1, tmp_data);
-	I("%s: CPU clock off password data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
-		,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
+	I("%s: CPU clock off password data[0]=%x",
+	__func__, tmp_data[0]);
+	I(" data[1]=%x data[2]=%x data[3]=%x\n",
+	tmp_data[1], tmp_data[2], tmp_data[3]);
 
 }
 
@@ -602,11 +655,12 @@
 	uint8_t tmp_addr[4];
 	uint8_t tmp_data[5];
 
-    //===========================================
-    //  Any Cmd for ineterface on : 0x9000_0000 ==> 0x0000_0000
-    //===========================================
-    tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
-    himax_flash_read(client, tmp_addr, tmp_data); //avoid RD/WR fail
+    /*=====================================
+	Any Cmd for ineterface on : 0x9000_0000 ==> 0x0000_0000
+	=====================================*/
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
+	himax_flash_read(client, tmp_addr, tmp_data); /*avoid RD/WR fail*/
 }
 
 bool wait_wip(struct i2c_client *client, int Timing)
@@ -614,55 +668,64 @@
 	uint8_t tmp_addr[4];
 	uint8_t tmp_data[4];
 	uint8_t in_buffer[10];
-	//uint8_t out_buffer[20];
+	/*uint8_t out_buffer[20];*/
 	int retry_cnt = 0;
 
-	//=====================================
-	// SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
-	//=====================================
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+	/*=====================================
+	SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+	=====================================*/
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+	tmp_data[1] = 0x07; tmp_data[0] = 0x80;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
 	in_buffer[0] = 0x01;
 
-	do
-	{
-		//=====================================
-		// SPI Transfer Control : 0x8000_0020 ==> 0x4200_0003
-		//=====================================
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-		tmp_data[3] = 0x42; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x03;
+	do {
+		/*=====================================
+		SPI Transfer Control : 0x8000_0020 ==> 0x4200_0003
+		=====================================*/
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+		tmp_data[3] = 0x42; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x03;
 		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-		//=====================================
-		// SPI Command : 0x8000_0024 ==> 0x0000_0005
-		// read 0x8000_002C for 0x01, means wait success
-		//=====================================
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
-		tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x05;
+		/*=====================================
+		SPI Command : 0x8000_0024 ==> 0x0000_0005
+		read 0x8000_002C for 0x01, means wait success
+		=====================================*/
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x05;
 		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-		in_buffer[0] = in_buffer[1] = in_buffer[2] = in_buffer[3] = 0xFF;
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
+		in_buffer[0] = in_buffer[1] =
+		in_buffer[2] = in_buffer[3] = 0xFF;
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
 		himax_register_read(client, tmp_addr, 1, in_buffer);
-		
+
 		if ((in_buffer[0] & 0x01) == 0x00)
 			return true;
 
 		retry_cnt++;
-		
-		if (in_buffer[0] != 0x00 || in_buffer[1] != 0x00 || in_buffer[2] != 0x00 || in_buffer[3] != 0x00)
-        	I("%s:Wait wip retry_cnt:%d, buffer[0]=%d, buffer[1]=%d, buffer[2]=%d, buffer[3]=%d \n", __func__, 
-            retry_cnt,in_buffer[0],in_buffer[1],in_buffer[2],in_buffer[3]);
 
-		if (retry_cnt > 100)
-        {        	
+		if (in_buffer[0] != 0x00 || in_buffer[1] != 0x00
+		|| in_buffer[2] != 0x00 || in_buffer[3] != 0x00){
+			I("%s:Wait wip retry_cnt:%d, buffer[0]=%d, ",
+			__func__, retry_cnt, in_buffer[0]);
+			I("buffer[1]=%d, buffer[2]=%d, buffer[3]=%d\n",
+			in_buffer[1], in_buffer[2], in_buffer[3]);
+		}
+		if (retry_cnt > 100) {
 			E("%s: Wait wip error!\n", __func__);
-            return false;
-        }
+			return false;
+		}
 		msleep(Timing);
-	}while ((in_buffer[0] & 0x01) == 0x01);
+	} while ((in_buffer[0] & 0x01) == 0x01);
 	return true;
 }
 
@@ -673,74 +736,93 @@
 
 	himax_interface_on(client);
 	himax_burst_enable(client, 0);
-	//CPU reset
-	// 0x9000_0014 ==> 0x0000_00CA
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xCA;
+	/*CPU reset*/
+	/* 0x9000_0014 ==> 0x0000_00CA*/
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0xCA;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-	//=====================================
-	// Read pull low CPU reset signal : 0x9000_0014 ==> 0x0000_00CA
-	//=====================================
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+	/*=====================================
+	Read pull low CPU reset signal : 0x9000_0014 ==> 0x0000_00CA
+	=====================================*/
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
 	himax_register_read(client, tmp_addr, 1, tmp_data);
 
-	I("%s: check pull low CPU reset signal  data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
-	,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
+	I("%s: check pull low CPU reset signal  data[0]=%x data[1]=%x ",
+	__func__, tmp_data[0], tmp_data[1]);
+	I("data[2]=%x data[3]=%x\n",
+	tmp_data[2], tmp_data[3]);
 
-	// 0x9000_0014 ==> 0x0000_0000
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+	/* 0x9000_0014 ==> 0x0000_0000*/
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-	//=====================================
-	// Read revert pull low CPU reset signal : 0x9000_0014 ==> 0x0000_0000
-	//=====================================
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
+	/*=====================================
+	Read revert pull low CPU reset signal : 0x9000_0014 ==> 0x0000_0000
+	=====================================*/
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x14;
 	himax_register_read(client, tmp_addr, 1, tmp_data);
 
-	I("%s: revert pull low CPU reset signal data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__
-	,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]);
+	I("%s: revert pull low CPU reset signal data[0]=%x data[1]=%x ",
+	__func__, tmp_data[0], tmp_data[1]);
+	I("data[2]=%x data[3]=%x\n",
+	tmp_data[2], tmp_data[3]);
 
-	//=====================================
-  // Reset TCON
-  //=====================================
-  tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
-  tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-  himax_flash_write_burst(client, tmp_addr, tmp_data);
-	usleep_range(10000, 20000);
-  tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
-  tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
-  himax_flash_write_burst(client, tmp_addr, tmp_data);
+	/*=====================================
+	Reset TCON
+	=====================================*/
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
+	tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+	himax_flash_write_burst(client, tmp_addr, tmp_data);
+	usleep_range(9999, 10000);
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x02;
+	tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-	if (FlashMode == 0x00)	//SRAM
-	{
-		//=====================================
-		//			Re-map
-		//=====================================
-		tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
-		tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xF1;
-		himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4);
+	if (FlashMode == 0x00) { /*SRAM*/
+		/*=====================================
+					Re-map
+		=====================================*/
+		tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
+		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0xF1;
+		himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);
 		I("%s:83100_Chip_Re-map ON\n", __func__);
-	}
-	else
-	{
-		//=====================================
-		//			Re-map off
-		//=====================================
-		tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
-		tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-		himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4);
+	} else {
+		/*=====================================
+					Re-map off
+		=====================================*/
+		tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
+		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+		himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);
 		I("%s:83100_Chip_Re-map OFF\n", __func__);
 	}
-	//=====================================
-	//			CPU clock on
-	//=====================================
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-	himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4);
+	/*=====================================
+				CPU clock on
+	=====================================*/
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+	himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4);
 
 }
 
@@ -751,36 +833,45 @@
 
 	himax_burst_enable(client, 0);
 
-	//=====================================
-	// SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
-	//=====================================
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+	/*=====================================
+	SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+	=====================================*/
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+	tmp_data[1] = 0x07; tmp_data[0] = 0x80;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-	//=====================================
-	// Chip Erase
-	// Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
-	//				  2. 0x8000_0024 ==> 0x0000_0006
-	//=====================================
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-	tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+	/*=====================================
+	Chip Erase
+	Write Enable :
+	1. 0x8000_0020 ==> 0x4700_0000
+	2. 0x8000_0024 ==> 0x0000_0006
+	=====================================*/
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+	tmp_data[3] = 0x47; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x06;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-	//=====================================
-	// Chip Erase
-	// Erase Command : 0x8000_0024 ==> 0x0000_00C7
-	//=====================================
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xC7;
+	/*=====================================
+	Chip Erase
+	Erase Command : 0x8000_0024 ==> 0x0000_00C7
+	=====================================*/
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0xC7;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
-	
+
 	msleep(2000);
-	
+
 	if (!wait_wip(client, 100))
 		E("%s:83100_Chip_Erase Fail\n", __func__);
 
@@ -793,53 +884,64 @@
 
 	himax_burst_enable(client, 0);
 
-	//=====================================
-	// SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
-	//=====================================
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+	/*=====================================
+	SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+	=====================================*/
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+	tmp_data[1] = 0x07; tmp_data[0] = 0x80;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-	//=====================================
-	// Chip Erase
-	// Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
-	//				  2. 0x8000_0024 ==> 0x0000_0006
-	//=====================================
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-	tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+	/*=====================================
+	Chip Erase
+	Write Enable :
+	1. 0x8000_0020 ==> 0x4700_0000
+	2. 0x8000_0024 ==> 0x0000_0006
+	=====================================*/
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+	tmp_data[3] = 0x47; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x06;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-	//=====================================
-	// Block Erase
-	// Erase Command : 0x8000_0028 ==> 0x0000_0000 //SPI addr
-	//				   0x8000_0020 ==> 0x6700_0000 //control
-	//				   0x8000_0024 ==> 0x0000_0052 //BE
-	//=====================================
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+	/*=====================================
+	Block Erase
+	Erase Command :
+	0x8000_0028 ==> 0x0000_0000 //SPI addr
+	0x8000_0020 ==> 0x6700_0000 //control
+	0x8000_0024 ==> 0x0000_0052 //BE
+	=====================================*/
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
-	
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-	tmp_data[3] = 0x67; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+	tmp_data[3] = 0x67; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
-	
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x52;
+
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x52;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
 	msleep(1000);
 
-	if (!wait_wip(client, 100))
-	{
+	if (!wait_wip(client, 100)) {
 		E("%s:83100_Erase Fail\n", __func__);
 		return false;
-	}
-	else
-	{
+	} else {
 		return true;
 	}
 
@@ -853,97 +955,110 @@
 
 	himax_burst_enable(client, 0);
 
-	//=====================================
-	// SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
-	//=====================================
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+	/*=====================================
+	SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+	=====================================*/
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+	tmp_data[1] = 0x07; tmp_data[0] = 0x80;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
-	for (page_prog_start = start_addr; page_prog_start < start_addr + 0x0F000; page_prog_start = page_prog_start + 0x1000)
-		{
-			//=====================================
-			// Chip Erase
-			// Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
-			//				  2. 0x8000_0024 ==> 0x0000_0006
-			//=====================================
-			tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-			tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-			himax_flash_write_burst(client, tmp_addr, tmp_data);
+	for (page_prog_start = start_addr;
+	page_prog_start < start_addr + 0x0F000;
+	page_prog_start = page_prog_start + 0x1000) {
+		/*=====================================
+		Chip Erase
+		Write Enable :
+		1. 0x8000_0020 ==> 0x4700_0000
+		2. 0x8000_0024 ==> 0x0000_0006
+		=====================================*/
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+		tmp_data[3] = 0x47; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-			tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
-			tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06;
-			himax_flash_write_burst(client, tmp_addr, tmp_data);
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-			//=====================================
-			// Sector Erase
-			// Erase Command : 0x8000_0028 ==> 0x0000_0000 //SPI addr
-			// 				0x8000_0020 ==> 0x6700_0000 //control
-			// 				0x8000_0024 ==> 0x0000_0020 //SE
-			//=====================================
-			tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
-			if (page_prog_start < 0x100)
-			{
-			 tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = (uint8_t)page_prog_start;
-			}
-			else if (page_prog_start >= 0x100 && page_prog_start < 0x10000)
-			{
-			 tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start;
-			}
-			else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000)
-			{
-			 tmp_data[3] = 0x00; tmp_data[2] = (uint8_t)(page_prog_start >> 16); tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start;
-			}
-			himax_flash_write_burst(client, tmp_addr, tmp_data);
+		/*=====================================
+		Sector Erase
+		Erase Command :
+		0x8000_0028 ==> 0x0000_0000 //SPI addr
+		0x8000_0020 ==> 0x6700_0000 //control
+		0x8000_0024 ==> 0x0000_0020 //SE
+		=====================================*/
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+		if (page_prog_start < 0x100) {
+			tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+			tmp_data[1] = 0x00;
+			tmp_data[0] = (uint8_t)page_prog_start;
+		} else if (page_prog_start >= 0x100
+		&& page_prog_start < 0x10000) {
+			tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+			tmp_data[1] = (uint8_t)(page_prog_start >> 8);
+			tmp_data[0] = (uint8_t)page_prog_start;
+		} else if (page_prog_start >= 0x10000
+		&& page_prog_start < 0x1000000) {
+			tmp_data[3] = 0x00;
+			tmp_data[2] = (uint8_t)(page_prog_start >> 16);
+			tmp_data[1] = (uint8_t)(page_prog_start >> 8);
+			tmp_data[0] = (uint8_t)page_prog_start;
+		}
+		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-			tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-			tmp_data[3] = 0x67; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-			himax_flash_write_burst(client, tmp_addr, tmp_data);
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+		tmp_data[3] = 0x67; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-			tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
-			tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x20;
-			himax_flash_write_burst(client, tmp_addr, tmp_data);
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x20;
+		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-			msleep(200);
+		msleep(200);
 
-			if (!wait_wip(client, 100))
-			{
-				E("%s:83100_Erase Fail\n", __func__);
-				return false;
-			}
-		}	
-		return true;
+		if (!wait_wip(client, 100)) {
+			E("%s:83100_Erase Fail\n", __func__);
+			return false;
+		}
+	}
+	return true;
 }
 
 void himax_sram_write(struct i2c_client *client, uint8_t *FW_content)
 {
 	int i = 0;
 	uint8_t tmp_addr[4];
-	uint8_t tmp_data[128];
-	int FW_length = 0x4000; // 0x4000 = 16K bin file
-	
-	//himax_sense_off(client);
+	uint8_t tmp_data[64];
+	int FW_length = 0x4000; /* 0x4000 = 16K bin file */
 
-	for (i = 0; i < FW_length; i = i + 128) 
-	{
+	/*himax_sense_off(client);*/
+
+	for (i = 0; i < FW_length; i = i + 64) {
 		himax_burst_enable(client, 1);
 
-		if (i < 0x100)
-		{
-			tmp_addr[3] = 0x08; 
-			tmp_addr[2] = 0x00; 
-			tmp_addr[1] = 0x00; 
+		if (i < 0x100) {
+			tmp_addr[3] = 0x08;
+			tmp_addr[2] = 0x00;
+			tmp_addr[1] = 0x00;
 			tmp_addr[0] = i;
-		}
-		else if (i >= 0x100 && i < 0x10000)
-		{
-			tmp_addr[3] = 0x08; 
-			tmp_addr[2] = 0x00; 
-			tmp_addr[1] = (i >> 8); 
+		} else if (i >= 0x100 && i < 0x10000) {
+			tmp_addr[3] = 0x08;
+			tmp_addr[2] = 0x00;
+			tmp_addr[1] = (i >> 8);
 			tmp_addr[0] = i;
 		}
 
-		memcpy(&tmp_data[0], &FW_content[i], 128);
-		himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 128);
+		memcpy(&tmp_data[0], &FW_content[i], 64);
+		himax_flash_write_burst_length(client, tmp_addr, tmp_data, 64);
 
 	}
 
@@ -951,182 +1066,197 @@
 		E("%s:83100_Sram_Write Fail\n", __func__);
 }
 
-bool himax_sram_verify(struct i2c_client *client, uint8_t *FW_File, int FW_Size)
+bool himax_sram_verify(struct i2c_client *client,
+uint8_t *FW_File, int FW_Size)
 {
 	int i = 0;
 	uint8_t out_buffer[20];
 	uint8_t in_buffer[128];
 	uint8_t *get_fw_content;
 
-	get_fw_content = kzalloc(0x4000*sizeof(uint8_t), GFP_KERNEL);
-	if (!get_fw_content)
-		return false;
+	get_fw_content = kzalloc(0x4000 * sizeof(uint8_t), GFP_KERNEL);
 
-	for (i = 0; i < 0x4000; i = i + 128)
-	{
+	for (i = 0 ; i < 0x4000 ; i = i + 128) {
 		himax_burst_enable(client, 1);
 
-		//==================================
-		//	AHB_I2C Burst Read
-		//==================================
-		if (i < 0x100)
-		{
-			out_buffer[3] = 0x08; 
-			out_buffer[2] = 0x00; 
-			out_buffer[1] = 0x00; 
+		/*=====================================
+				AHB_I2C Burst Read
+		=====================================*/
+		if (i < 0x100) {
+			out_buffer[3] = 0x08;
+			out_buffer[2] = 0x00;
+			out_buffer[1] = 0x00;
 			out_buffer[0] = i;
-		}
-		else if (i >= 0x100 && i < 0x10000)
-		{
-			out_buffer[3] = 0x08; 
-			out_buffer[2] = 0x00; 
-			out_buffer[1] = (i >> 8); 
+		} else if (i >= 0x100 && i < 0x10000) {
+			out_buffer[3] = 0x08;
+			out_buffer[2] = 0x00;
+			out_buffer[1] = (i >> 8);
 			out_buffer[0] = i;
 		}
 
-		if ( i2c_himax_write(client, 0x00 ,out_buffer, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+		if (i2c_himax_write(client, 0x00, out_buffer,
+		4, HIMAX_I2C_RETRY_TIMES) < 0) {
 			E("%s: i2c access fail!\n", __func__);
 			return false;
 		}
 
-		out_buffer[0] = 0x00;		
-		if ( i2c_himax_write(client, 0x0C ,out_buffer, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+		out_buffer[0] = 0x00;
+		if (i2c_himax_write(client, 0x0C, out_buffer,
+		1, HIMAX_I2C_RETRY_TIMES) < 0) {
 			E("%s: i2c access fail!\n", __func__);
 			return false;
 		}
 
-		if ( i2c_himax_read(client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES) < 0) {
+		if (i2c_himax_read(client, 0x08, in_buffer,
+		128, HIMAX_I2C_RETRY_TIMES) < 0) {
 			E("%s: i2c access fail!\n", __func__);
 			return false;
 		}
 		memcpy(&get_fw_content[i], &in_buffer[0], 128);
 	}
 
-	for (i = 0; i < FW_Size; i++)
-		{
-	        if (FW_File[i] != get_fw_content[i])
-	        	{
-					E("%s: fail! SRAM[%x]=%x NOT CRC_ifile=%x\n", __func__,i,get_fw_content[i],FW_File[i]);
-		            return false;
-	        	}
+	for (i = 0 ; i < FW_Size ; i++) {
+		if (FW_File[i] != get_fw_content[i]) {
+			E("%s: fail! SRAM[%x]=%x NOT CRC_ifile=%x\n",
+			__func__, i, get_fw_content[i], FW_File[i]);
+			return false;
 		}
+	}
 
 	kfree(get_fw_content);
 
 	return true;
 }
 
-void himax_flash_programming(struct i2c_client *client, uint8_t *FW_content, int FW_Size)
+void himax_flash_programming(struct i2c_client *client,
+uint8_t *FW_content, int FW_Size)
 {
 	int page_prog_start = 0;
 	int program_length = 48;
 	int i = 0, j = 0, k = 0;
 	uint8_t tmp_addr[4];
 	uint8_t tmp_data[4];
-	uint8_t buring_data[256];    // Read for flash data, 128K
-									 // 4 bytes for 0x80002C padding
+	/* // Read for flash data, 128K //4 bytes for 0x80002C padding */
+	uint8_t buring_data[256];
 
-	//himax_interface_on(client);
+	/*himax_interface_on(client);*/
 	himax_burst_enable(client, 0);
 
-	//=====================================
-	// SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
-	//=====================================
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+	/*=====================================
+	SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+	=====================================*/
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+	tmp_data[1] = 0x07; tmp_data[0] = 0x80;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-	for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start = page_prog_start + 256)
-	{
-		//msleep(5);
-		//=====================================
-		// Write Enable : 1. 0x8000_0020 ==> 0x4700_0000
-		//				  2. 0x8000_0024 ==> 0x0000_0006
-		//=====================================
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-		tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+	for (page_prog_start = 0 ; page_prog_start < FW_Size;
+	page_prog_start = page_prog_start + 256) {
+		/*msleep(5);*/
+		/*=====================================
+		Write Enable :
+		1. 0x8000_0020 ==> 0x4700_0000
+		2. 0x8000_0024 ==> 0x0000_0006
+		=====================================*/
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+		tmp_data[3] = 0x47; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x00;
 		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
-		tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06;
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x06;
 		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-		//=================================
-		// SPI Transfer Control
-		// Set 256 bytes page write : 0x8000_0020 ==> 0x610F_F000
-		// Set read start address	: 0x8000_0028 ==> 0x0000_0000			
-		//=================================
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-		tmp_data[3] = 0x61; tmp_data[2] = 0x0F; tmp_data[1] = 0xF0; tmp_data[0] = 0x00;
-		// data bytes should be 0x6100_0000 + ((word_number)*4-1)*4096 = 0x6100_0000 + 0xFF000 = 0x610F_F000
-		// Programmable size = 1 page = 256 bytes, word_number = 256 byte / 4 = 64
+		/*=====================================
+		SPI Transfer Control
+		Set 256 bytes page write : 0x8000_0020 ==> 0x610F_F000
+		Set read start address	: 0x8000_0028 ==> 0x0000_0000
+		=====================================*/
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+		tmp_data[3] = 0x61; tmp_data[2] = 0x0F;
+		tmp_data[1] = 0xF0; tmp_data[0] = 0x00;
+		/*data bytes should be 0x6100_0000 +
+		((word_number)*4-1)*4096 = 0x6100_0000 +
+		0xFF000 = 0x610F_F000
+		Programmable size = 1 page = 256 bytes,
+		word_number = 256 byte / 4 = 64*/
 		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
-		//tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; // Flash start address 1st : 0x0000_0000
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+		/* tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+		// Flash start address 1st : 0x0000_0000 */
 
-		if (page_prog_start < 0x100)
-		{
-			tmp_data[3] = 0x00; 
-			tmp_data[2] = 0x00; 
-			tmp_data[1] = 0x00; 
+		if (page_prog_start < 0x100) {
+			tmp_data[3] = 0x00;
+			tmp_data[2] = 0x00;
+			tmp_data[1] = 0x00;
+			tmp_data[0] = (uint8_t)page_prog_start;
+		} else if (page_prog_start >= 0x100
+		&& page_prog_start < 0x10000) {
+			tmp_data[3] = 0x00;
+			tmp_data[2] = 0x00;
+			tmp_data[1] = (uint8_t)(page_prog_start >> 8);
+			tmp_data[0] = (uint8_t)page_prog_start;
+		} else if (page_prog_start >= 0x10000
+		&& page_prog_start < 0x1000000) {
+			tmp_data[3] = 0x00;
+			tmp_data[2] = (uint8_t)(page_prog_start >> 16);
+			tmp_data[1] = (uint8_t)(page_prog_start >> 8);
 			tmp_data[0] = (uint8_t)page_prog_start;
 		}
-		else if (page_prog_start >= 0x100 && page_prog_start < 0x10000)
-		{
-			tmp_data[3] = 0x00; 
-			tmp_data[2] = 0x00; 
-			tmp_data[1] = (uint8_t)(page_prog_start >> 8); 
-			tmp_data[0] = (uint8_t)page_prog_start;
-		}
-		else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000)
-		{
-			tmp_data[3] = 0x00; 
-			tmp_data[2] = (uint8_t)(page_prog_start >> 16); 
-			tmp_data[1] = (uint8_t)(page_prog_start >> 8); 
-			tmp_data[0] = (uint8_t)page_prog_start;
-		}
-		
+
 		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-
-		//=================================
-		// Send 16 bytes data : 0x8000_002C ==> 16 bytes data	  
-		//=================================
+		/*=====================================
+		Send 16 bytes data : 0x8000_002C ==> 16 bytes data
+		=====================================*/
 		buring_data[0] = 0x2C;
 		buring_data[1] = 0x00;
 		buring_data[2] = 0x00;
 		buring_data[3] = 0x80;
-		
-		for (i = /*0*/page_prog_start, j = 0; i < 16 + page_prog_start/**/; i++, j++)	/// <------ bin file
-		{
+
+		for (i = /*0*/page_prog_start, j = 0;
+			i < 16 + page_prog_start/**/;
+			i++, j++) {	/* <------ bin file*/
+
 			buring_data[j + 4] = FW_content[i];
 		}
 
-
-		if ( i2c_himax_write(client, 0x00 ,buring_data, 20, HIMAX_I2C_RETRY_TIMES) < 0) {
+		if (i2c_himax_write(client, 0x00, buring_data,
+			20, HIMAX_I2C_RETRY_TIMES) < 0) {
 			E("%s: i2c access fail!\n", __func__);
 			return;
 		}
-		//=================================
-		// Write command : 0x8000_0024 ==> 0x0000_0002
-		//=================================
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
-		tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x02;
+		/*=====================================
+		Write command : 0x8000_0024 ==> 0x0000_0002
+		=====================================*/
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x02;
 		himax_flash_write_burst(client, tmp_addr, tmp_data);
 
-		//=================================
-		// Send 240 bytes data : 0x8000_002C ==> 240 bytes data	 
-		//=================================
+		/*=====================================
+		Send 240 bytes data : 0x8000_002C ==> 240 bytes data
+		=====================================*/
 
-		for (j = 0; j < 5; j++)
-		{
-			for (i = (page_prog_start + 16 + (j * 48)), k = 0; i < (page_prog_start + 16 + (j * 48)) + program_length; i++, k++)   /// <------ bin file
-			{
-				buring_data[k+4] = FW_content[i];//(byte)i;
+		for (j = 0; j < 5; j++) {
+			for (i = (page_prog_start + 16 + (j * 48)), k = 0;
+			i < (page_prog_start + 16 + (j * 48)) + program_length;
+			i++, k++) {  /*<------ bin file*/
+				buring_data[k+4] = FW_content[i];/*(byte)i;*/
 			}
 
-			if ( i2c_himax_write(client, 0x00 ,buring_data, program_length+4, HIMAX_I2C_RETRY_TIMES) < 0) {
+			if (i2c_himax_write(client, 0x00, buring_data,
+				program_length + 4,
+				HIMAX_I2C_RETRY_TIMES) < 0) {
 				E("%s: i2c access fail!\n", __func__);
 				return;
 			}
@@ -1145,52 +1275,61 @@
 	uint8_t ret_data = 0x00;
 	int i = 0;
 	int ret = 0;
+
 	himax_sense_off(client);
-	for (i = 0; i < 5; i++)
-	{
-		// 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver)
-		tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-		tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01;
+
+	for (i = 0 ; i < 5 ; i++) {
+		/* 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001)
+		(Lock register R/W from driver) */
+		tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x01;
 		ret = himax_register_write(client, tmp_addr, 1, tmp_data);
-		if(ret)
+		if (ret)
 			return false;
 
-		// 2. Set bank as 0 (0x8001_BD01 = 0x0000_0000)
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xBD; tmp_addr[0] = 0x01;
-		tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+		/* 2. Set bank as 0 (0x8001_BD01 = 0x0000_0000)*/
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x01;
+		tmp_addr[1] = 0xBD; tmp_addr[0] = 0x01;
+		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x00;
 		ret = himax_register_write(client, tmp_addr, 1, tmp_data);
-		if(ret)
+		if (ret)
 			return false;
 
-		// 3. Read driver ID register RF4H 1 byte (0x8001_F401)
-		//	  Driver register RF4H 1 byte value = 0x84H, read back value will become 0x84848484
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xF4; tmp_addr[0] = 0x01;
+		/* 3. Read driver ID register RF4H 1 byte (0x8001_F401)
+		//	  Driver register RF4H 1 byte value = 0x84H,
+		read back value will become 0x84848484 */
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x01;
+		tmp_addr[1] = 0xF4; tmp_addr[0] = 0x01;
 		himax_register_read(client, tmp_addr, 1, tmp_data);
 		ret_data = tmp_data[0];
 
 		I("%s:Read driver IC ID = %X\n", __func__, ret_data);
-		if (ret_data == 0x84)
-		{
+		if (ret_data == 0x84) {
 			IC_TYPE         = HX_83100_SERIES_PWON;
-			//himax_sense_on(client, 0x01);
+			/*himax_sense_on(client, 0x01);*/
 			ret_data = true;
 			break;
-		}
-		else
-		{
+
+		} else {
 			ret_data = false;
 			E("%s:Read driver ID register Fail:\n", __func__);
 		}
 	}
-	// 4. After read finish, set DDREG_Req = 0 (0x9000_0020 = 0x0000_0000) (Unlock register R/W from driver)
-	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+	/* 4. After read finish, set DDREG_Req = 0
+	(0x9000_0020 = 0x0000_0000) (Unlock register R/W from driver)*/
+	tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x00; tmp_data[0] = 0x00;
 	himax_register_write(client, tmp_addr, 1, tmp_data);
-	//himax_sense_on(client, 0x01);
+	/*himax_sense_on(client, 0x01);*/
 	return ret_data;
 }
 
-#if 1
+/*#if 1*/
 int himax_check_CRC(struct i2c_client *client, int mode)
 {
 	bool burnFW_success = false;
@@ -1200,52 +1339,70 @@
 	int CRC_value = 0;
 
 	memset(tmp_data, 0x00, sizeof(tmp_data));
+	if (i_TP_CRC_FW_60K == NULL) {
+		I("%s: i_TP_CRC_FW_60K = NULL\n", __func__);
+		return 0;
+	} else if (i_TP_CRC_FW_64K == NULL) {
+		I("%s: i_TP_CRC_FW_64K = NULL\n", __func__);
+		return 0;
+	} else if (i_TP_CRC_FW_124K == NULL) {
+		I("%s: i_TP_CRC_FW_124K = NULL\n", __func__);
+		return 0;
+	} else if (i_TP_CRC_FW_128K == NULL) {
+		I("%s: i_TP_CRC_FW_128K = NULL\n", __func__);
+		return 0;
+	}
 
-	if (1)
-	{
-		if(mode == fw_image_60k)
-		{
-			himax_sram_write(client, (i_TP_CRC_FW_60K));
-			burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_60K, 0x4000);
+	if (1) {
+		if (mode == fw_image_60k) {
+			himax_sram_write(client,
+			(unsigned char *)i_TP_CRC_FW_60K->data);
+			burnFW_success = himax_sram_verify(client,
+			(unsigned char *)i_TP_CRC_FW_60K->data, 0x4000);
+		} else if (mode == fw_image_64k) {
+			himax_sram_write(client,
+			(unsigned char *)i_TP_CRC_FW_64K->data);
+			burnFW_success = himax_sram_verify(client,
+			(unsigned char *)i_TP_CRC_FW_64K->data, 0x4000);
+		} else if (mode == fw_image_124k) {
+			himax_sram_write(client,
+			(unsigned char *)i_TP_CRC_FW_124K->data);
+			burnFW_success = himax_sram_verify(client,
+			(unsigned char *)i_TP_CRC_FW_124K->data, 0x4000);
+		} else if (mode == fw_image_128k) {
+			himax_sram_write(client,
+			(unsigned char *)i_TP_CRC_FW_128K->data);
+			burnFW_success = himax_sram_verify(client,
+			(unsigned char *)i_TP_CRC_FW_128K->data, 0x4000);
 		}
-		else if(mode == fw_image_64k)
-		{
-			himax_sram_write(client, (i_TP_CRC_FW_64K));
-			burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_64K, 0x4000);
-		}
-		else if(mode == fw_image_124k)
-		{
-			himax_sram_write(client, (i_TP_CRC_FW_124K));
-			burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_124K, 0x4000);
-		}
-		else if(mode == fw_image_128k)
-		{
-			himax_sram_write(client, (i_TP_CRC_FW_128K));
-			burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_128K, 0x4000);
-		}
-		if (burnFW_success)
-		{
-			I("%s: Start to do CRC FW mode=%d \n", __func__,mode);
-			himax_sense_on(client, 0x00);	// run CRC firmware
+		if (burnFW_success) {
+			I("%s: Start to do CRC FW mode=%d\n", __func__, mode);
+			himax_sense_on(client, 0x00);	/* run CRC firmware*/
 
-			while(true)
-			{
+			while (true) {
 				msleep(100);
-
-				tmp_addr[3] = 0x90; 
-				tmp_addr[2] = 0x08; 
-				tmp_addr[1] = 0x80; 
+				tmp_addr[3] = 0x90;
+				tmp_addr[2] = 0x08;
+				tmp_addr[1] = 0x80;
 				tmp_addr[0] = 0x94;
-				himax_register_read(client, tmp_addr, 1, tmp_data);
+				himax_register_read(client,
+				tmp_addr, 1, tmp_data);
 
-				I("%s: CRC from firmware is %x, %x, %x, %x \n", __func__,tmp_data[3],
-					tmp_data[2],tmp_data[1],tmp_data[0]);
-
-				if (tmp_data[3] == 0xFF && tmp_data[2] == 0xFF && tmp_data[1] == 0xFF && tmp_data[0] == 0xFF)
-				{ 
-					}
-				else
+				I("%s: CRC from firmware is %x, %x, %x, %x\n",
+				__func__, tmp_data[3], tmp_data[2],
+				tmp_data[1], tmp_data[0]);
+/*
+				if (tmp_data[3] == 0xFF && tmp_data[2] == 0xFF
+				&& tmp_data[1] == 0xFF && tmp_data[0] == 0xFF) {
+				} else
 					break;
+				*/
+				if (!(tmp_data[3] == 0xFF
+				&& tmp_data[2] == 0xFF
+				&& tmp_data[1] == 0xFF
+				&& tmp_data[0] == 0xFF)) {
+					break;
+				}
 			}
 
 			CRC_value = tmp_data[3];
@@ -1259,30 +1416,32 @@
 			tmp_value = tmp_data[0] << 24;
 			CRC_value += tmp_value;
 
-			I("%s: CRC Value is %x \n", __func__, CRC_value);
+			I("%s: CRC Value is %x\n", __func__, CRC_value);
 
-			//Close Remapping
-	        //=====================================
-	        //          Re-map close
-	        //=====================================
-	        tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
-	        tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00;
-	        himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4);
-			return CRC_value;				
-		}
-		else
-		{
+			/*Close Remapping*/
+			/*=====================================
+			Re-map close
+			=====================================*/
+			tmp_addr[3] = 0x90; tmp_addr[2] = 0x00;
+			tmp_addr[1] = 0x00; tmp_addr[0] = 0x00;
+			tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+			tmp_data[1] = 0x00; tmp_data[0] = 0x00;
+			himax_flash_write_burst_length(client,
+			tmp_addr, tmp_data, 4);
+			return CRC_value;
+
+		} else {
 			E("%s: SRAM write fail\n", __func__);
 			return 0;
-		}		
-	}
-	else
-		I("%s: NO CRC Check File \n", __func__);
+		}
+	} else
+		I("%s: NO CRC Check File\n", __func__);
 
 	return 0;
 }
 
-bool Calculate_CRC_with_AP(unsigned char *FW_content , int CRC_from_FW, int mode)
+bool Calculate_CRC_with_AP(unsigned char *FW_content,
+int CRC_from_FW, int mode)
 {
 	uint8_t tmp_data[4];
 	int i, j;
@@ -1291,42 +1450,35 @@
 	int CRC = 0xFFFFFFFF;
 	int PolyNomial = 0x82F63B78;
 	int length = 0;
-	
+
 	if (mode == fw_image_128k)
 		length = 0x8000;
 	else if (mode == fw_image_124k)
 		length = 0x7C00;
 	else if (mode == fw_image_64k)
 		length = 0x4000;
-	else //if (mode == fw_image_60k)
+	else /*if (mode == fw_image_60k)*/
 		length = 0x3C00;
 
-	for (i = 0; i < length; i++)
-	{
-		fw_data = FW_content[i * 4 ];
-		
-		for (j = 1; j < 4; j++)
-		{
+	for (i = 0 ; i < length ; i++) {
+		fw_data = FW_content[i * 4];
+
+		for (j = 1 ; j < 4 ; j++) {
 			fw_data_2 = FW_content[i * 4 + j];
 			fw_data += (fw_data_2) << (8 * j);
 		}
 
 		CRC = fw_data ^ CRC;
 
-		for (j = 0; j < 32; j++)
-		{
+		for (j = 0 ; j < 32 ; j++) {
 			if ((CRC % 2) != 0)
-			{
-				CRC = ((CRC >> 1) & 0x7FFFFFFF) ^ PolyNomial;				
-			}
+				CRC = ((CRC >> 1) & 0x7FFFFFFF) ^ PolyNomial;
 			else
-			{
-				CRC = (((CRC >> 1) ^ 0x7FFFFFFF)& 0x7FFFFFFF);				
-			}
+				CRC = (((CRC >> 1) ^ 0x7FFFFFFF) & 0x7FFFFFFF);
 		}
 	}
 
-	I("%s: CRC calculate from bin file is %x \n", __func__, CRC);
+	I("%s: CRC calculate from bin file is %x\n", __func__, CRC);
 
 	tmp_data[0] = (uint8_t)(CRC >> 24);
 	tmp_data[1] = (uint8_t)(CRC >> 16);
@@ -1334,58 +1486,129 @@
 	tmp_data[3] = (uint8_t) CRC;
 
 	CRC = tmp_data[0];
-	CRC += tmp_data[1] << 8;			
+	CRC += tmp_data[1] << 8;
 	CRC += tmp_data[2] << 16;
 	CRC += tmp_data[3] << 24;
 
-	I("%s: CRC calculate from bin file REVERSE %x \n", __func__, CRC);
-	I("%s: CRC calculate from FWis %x \n", __func__, CRC_from_FW);
+	I("%s: CRC calculate from bin file REVERSE %x\n", __func__, CRC);
+	I("%s: CRC calculate from FWis %x\n", __func__, CRC_from_FW);
 	if (CRC_from_FW == CRC)
 		return true;
 	else
 		return false;
 }
-#endif
+/*#endif*/
 
-int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
+int himax_load_CRC_bin_file(struct i2c_client *client)
+{
+	int err = 0;
+	char *CRC_60_firmware_name = "HX_CRC_60.bin";
+	char *CRC_64_firmware_name = "HX_CRC_64.bin";
+	char *CRC_124_firmware_name = "HX_CRC_124.bin";
+	char *CRC_128_firmware_name = "HX_CRC_128.bin";
+
+	I("%s,Entering\n", __func__);
+	if (i_TP_CRC_FW_60K == NULL)	{
+		I("load file name = %s\n", CRC_60_firmware_name);
+		err = request_firmware(&i_TP_CRC_FW_60K,
+		CRC_60_firmware_name, private_ts->dev);
+		if (err < 0) {
+			E("%s,fail in line%d error code=%d\n",
+			__func__, __LINE__, err);
+			err = -1;
+			goto request_60k_fw_fail;
+		}
+	} else
+		I("%s already load i_TP_CRC_FW_60K\n", __func__);
+
+	if (i_TP_CRC_FW_64K == NULL)	{
+		I("load file name = %s\n", CRC_64_firmware_name);
+		err = request_firmware(&i_TP_CRC_FW_64K,
+		CRC_64_firmware_name, private_ts->dev);
+		if (err < 0) {
+			E("%s,fail in line%d error code=%d\n",
+			__func__, __LINE__, err);
+			err = -2;
+			goto request_64k_fw_fail;
+		}
+	} else
+		I("%s already load i_TP_CRC_FW_64K\n", __func__);
+
+	if (i_TP_CRC_FW_124K == NULL) {
+		I("load file name = %s\n", CRC_124_firmware_name);
+		err = request_firmware(&i_TP_CRC_FW_124K,
+		CRC_124_firmware_name, private_ts->dev);
+		if (err < 0) {
+			E("%s,fail in line%d error code=%d\n",
+			__func__, __LINE__, err);
+			err = -3;
+			goto request_124k_fw_fail;
+		}
+	} else
+		I("%s already load i_TP_CRC_FW_124K\n", __func__);
+
+	if (i_TP_CRC_FW_128K == NULL) {
+		I("load file name = %s\n", CRC_128_firmware_name);
+		err = request_firmware(&i_TP_CRC_FW_128K,
+		CRC_128_firmware_name, private_ts->dev);
+		if (err < 0) {
+			E("%s,fail in line%d error code=%d\n",
+			__func__, __LINE__, err);
+			err = -4;
+			goto request_128k_fw_fail;
+		}
+	} else
+		I("%s already load  i_TP_CRC_FW_128K\n", __func__);
+
+	return err;
+
+request_128k_fw_fail:
+	release_firmware(i_TP_CRC_FW_124K);
+request_124k_fw_fail:
+	release_firmware(i_TP_CRC_FW_64K);
+request_64k_fw_fail:
+	release_firmware(i_TP_CRC_FW_60K);
+request_60k_fw_fail:
+	return err;
+}
+int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client,
+unsigned char *fw, int len, bool change_iref)
 {
 	int CRC_from_FW = 0;
 	int burnFW_success = 0;
 
-	if (len != 0x10000)   //64k
-    {
-    	E("%s: The file size is not 64K bytes\n", __func__);
-    	return false;
-		}
+	if (len != 0x10000) {/*64k*/
+		E("%s: The file size is not 64K bytes\n", __func__);
+		return false;
+	}
 	himax_sense_off(client);
 	msleep(500);
 	himax_interface_on(client);
-  if (!himax_sector_erase(client, 0x00000))
-			{
-            E("%s:Sector erase fail!Please restart the IC.\n", __func__);
-            return false;
-      }
+	if (!himax_sector_erase(client, 0x00000)) {
+		E("%s:Sector erase fail!Please restart the IC.\n", __func__);
+		return false;
+	}
 	himax_flash_programming(client, fw, 0x0F000);
 
-	//burnFW_success = himax_83100_Verify(fw, len);
-	//if(burnFW_success==false)
-	//	return burnFW_success;
+	/*burnFW_success = himax_83100_Verify(fw, len);
+	if(burnFW_success==false)
+		return burnFW_success;*/
 
-	CRC_from_FW = himax_check_CRC(client,fw_image_60k);
-	burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_60k);
-	//himax_sense_on(client, 0x01);
+	CRC_from_FW = himax_check_CRC(client, fw_image_60k);
+	burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_60k);
+	/*himax_sense_on(client, 0x01);*/
 	return burnFW_success;
 }
 
-int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
+int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client,
+unsigned char *fw, int len, bool change_iref)
 {
 	int CRC_from_FW = 0;
 	int burnFW_success = 0;
 
-	if (len != 0x10000)   //64k
-  {
-    	E("%s: The file size is not 64K bytes\n", __func__);
-    	return false;
+	if (len != 0x10000) {   /*64k*/
+		E("%s: The file size is not 64K bytes\n", __func__);
+		return false;
 	}
 	himax_sense_off(client);
 	msleep(500);
@@ -1393,62 +1616,58 @@
 	himax_chip_erase(client);
 	himax_flash_programming(client, fw, len);
 
-	//burnFW_success = himax_83100_Verify(fw, len);
-	//if(burnFW_success==false)
-	//	return burnFW_success;
+	/*burnFW_success = himax_83100_Verify(fw, len);
+	if(burnFW_success==false)
+		return burnFW_success;*/
 
-	CRC_from_FW = himax_check_CRC(client,fw_image_64k);
-	burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_64k);
-	//himax_sense_on(client, 0x01);
+	CRC_from_FW = himax_check_CRC(client, fw_image_64k);
+	burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_64k);
+	/*himax_sense_on(client, 0x01);*/
 	return burnFW_success;
 }
 
-int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
+int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client,
+unsigned char *fw, int len, bool change_iref)
 {
 	int CRC_from_FW = 0;
 	int burnFW_success = 0;
 
-	if (len != 0x20000)   //128k
-  {
-    	E("%s: The file size is not 128K bytes\n", __func__);
-    	return false;
+	if (len != 0x20000) {   /*128k*/
+		E("%s: The file size is not 128K bytes\n", __func__);
+		return false;
 	}
 	himax_sense_off(client);
 	msleep(500);
 	himax_interface_on(client);
-	if (!himax_block_erase(client))
-    	{
-            E("%s:Block erase fail!Please restart the IC.\n", __func__);
-            return false;
-      }
-
-    if (!himax_sector_erase(client, 0x10000))
-    	{
-            E("%s:Sector erase fail!Please restart the IC.\n", __func__);
-            return false;
-      }
+	if (!himax_block_erase(client)) {
+		E("%s:Block erase fail!Please restart the IC.\n", __func__);
+		return false;
+	}
+	if (!himax_sector_erase(client, 0x10000)) {
+		E("%s:Sector erase fail!Please restart the IC.\n", __func__);
+		return false;
+	}
 	himax_flash_programming(client, fw, 0x1F000);
 
+	/*burnFW_success = himax_83100_Verify(fw, len);
+	if(burnFW_success==false)
+		return burnFW_success;*/
 
-	//burnFW_success = himax_83100_Verify(fw, len);
-	//if(burnFW_success==false)
-	//	return burnFW_success;
-
-	CRC_from_FW = himax_check_CRC(client,fw_image_124k);
-	burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_124k);
-	//himax_sense_on(client, 0x01);
+	CRC_from_FW = himax_check_CRC(client, fw_image_124k);
+	burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_124k);
+	/*himax_sense_on(client, 0x01);*/
 	return burnFW_success;
 }
 
-int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref)
+int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client,
+unsigned char *fw, int len, bool change_iref)
 {
 	int CRC_from_FW = 0;
 	int burnFW_success = 0;
 
-	if (len != 0x20000)   //128k
-  {
-    	E("%s: The file size is not 128K bytes\n", __func__);
-    	return false;
+	if (len != 0x20000) {   /*128k*/
+		E("%s: The file size is not 128K bytes\n", __func__);
+		return false;
 	}
 	himax_sense_off(client);
 	msleep(500);
@@ -1457,13 +1676,13 @@
 
 	himax_flash_programming(client, fw, len);
 
-	//burnFW_success = himax_83100_Verify(fw, len);
-	//if(burnFW_success==false)
-	//	return burnFW_success;
+	/*burnFW_success = himax_83100_Verify(fw, len);
+	if(burnFW_success==false)
+		return burnFW_success;*/
 
-	CRC_from_FW = himax_check_CRC(client,fw_image_128k);
-	burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_128k);
-	//himax_sense_on(client, 0x01);
+	CRC_from_FW = himax_check_CRC(client, fw_image_128k);
+	burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_128k);
+	/*himax_sense_on(client, 0x01); */
 	return burnFW_success;
 }
 
@@ -1472,10 +1691,9 @@
 	uint8_t cmd[4];
 	char data[12] = {0};
 
-	I("%s:IC_TYPE =%d\n", __func__,IC_TYPE);
+	I("%s:IC_TYPE =%d\n", __func__, IC_TYPE);
 
-	if(IC_TYPE == HX_83100_SERIES_PWON)
-	{
+	if (IC_TYPE == HX_83100_SERIES_PWON) {
 		cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xF8;
 		himax_register_read(client, cmd, 1, data);
 
@@ -1486,11 +1704,11 @@
 		cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xFC;
 		himax_register_read(client, cmd, 1, data);
 
-	  if((data[1] & 0x04) == 0x04) {
+		if ((data[1] & 0x04) == 0x04)
 			ic_data->HX_XY_REVERSE = true;
-	  } else {
+		else
 			ic_data->HX_XY_REVERSE = false;
-	  }
+
 		ic_data->HX_Y_RES = data[3]*256;
 		cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x01; cmd[0] = 0x00;
 		himax_register_read(client, cmd, 1, data);
@@ -1498,32 +1716,35 @@
 		ic_data->HX_X_RES = data[1]*256 + data[2];
 		cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x8C;
 		himax_register_read(client, cmd, 1, data);
-	  if((data[0] & 0x01) == 1) {
+		if ((data[0] & 0x01) == 1)
 			ic_data->HX_INT_IS_EDGE = true;
-	  } else {
+		else
 			ic_data->HX_INT_IS_EDGE = false;
-	  }
-	  if (ic_data->HX_RX_NUM > 40)
+
+		if (ic_data->HX_RX_NUM > 40)
 			ic_data->HX_RX_NUM = 29;
-	  if (ic_data->HX_TX_NUM > 20)
+		if (ic_data->HX_TX_NUM > 20)
 			ic_data->HX_TX_NUM = 16;
-	  if (ic_data->HX_MAX_PT > 10)
+		if (ic_data->HX_MAX_PT > 10)
 			ic_data->HX_MAX_PT = 10;
-	  if (ic_data->HX_Y_RES > 2000)
+		if (ic_data->HX_Y_RES > 2000)
 			ic_data->HX_Y_RES = 1280;
-	  if (ic_data->HX_X_RES > 2000)
+		if (ic_data->HX_X_RES > 2000)
 			ic_data->HX_X_RES = 720;
 #ifdef HX_EN_MUT_BUTTON
 		cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xE8;
 		himax_register_read(client, cmd, 1, data);
 		ic_data->HX_BT_NUM				= data[3];
 #endif
-		I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d \n", __func__,ic_data->HX_RX_NUM,ic_data->HX_TX_NUM,ic_data->HX_MAX_PT);
-		I("%s:HX_XY_REVERSE =%d,HX_Y_RES =%d,HX_X_RES=%d \n", __func__,ic_data->HX_XY_REVERSE,ic_data->HX_Y_RES,ic_data->HX_X_RES);
-		I("%s:HX_INT_IS_EDGE =%d \n", __func__,ic_data->HX_INT_IS_EDGE);
-	}
-	else
-	{
+		I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d\n",
+		__func__, ic_data->HX_RX_NUM,
+		ic_data->HX_TX_NUM, ic_data->HX_MAX_PT);
+		I("%s:HX_XY_REVERSE =%d,HX_Y_RES =%d,HX_X_RES=%d\n",
+		__func__, ic_data->HX_XY_REVERSE,
+		ic_data->HX_Y_RES, ic_data->HX_X_RES);
+		I("%s:HX_INT_IS_EDGE =%d\n",
+		__func__, ic_data->HX_INT_IS_EDGE);
+	} else {
 		ic_data->HX_RX_NUM				= 0;
 		ic_data->HX_TX_NUM				= 0;
 		ic_data->HX_BT_NUM				= 0;
@@ -1538,35 +1759,34 @@
 void himax_read_FW_ver(struct i2c_client *client)
 {
 	uint8_t cmd[4];
-	uint8_t data[64] = {0};
+	uint8_t data[64];
 
-	//=====================================
-	// Read FW version : 0x0000_E303
-	//=====================================
+	/*=====================================
+	Read FW version : 0x0000_E303
+	=====================================*/
 	cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x00;
 	himax_register_read(client, cmd, 1, data);
 
-	ic_data->vendor_config_ver = data[3]<<8;
+	ic_data->vendor_config_ver = data[3] << 8;
 
 	cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x04;
 	himax_register_read(client, cmd, 1, data);
 
 	ic_data->vendor_config_ver = data[0] | ic_data->vendor_config_ver;
-	I("CFG_VER : %X \n",ic_data->vendor_config_ver);
+	I("CFG_VER : %X\n", ic_data->vendor_config_ver);
 
 	cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x28;
 	himax_register_read(client, cmd, 1, data);
 
 	ic_data->vendor_fw_ver = data[0]<<8 | data[1];
-	I("FW_VER : %X \n",ic_data->vendor_fw_ver);
+	I("FW_VER : %X\n", ic_data->vendor_fw_ver);
 
-
-	return;
 }
 
 bool himax_ic_package_check(struct i2c_client *client)
 {
-#if 0
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
 	uint8_t cmd[3];
 	uint8_t data[3];
 
@@ -1574,260 +1794,284 @@
 	memset(data, 0x00, sizeof(data));
 
 	if (i2c_himax_read(client, 0xD1, cmd, 3, HIMAX_I2C_RETRY_TIMES) < 0)
-		return false ;
+		return false;
 
 	if (i2c_himax_read(client, 0x31, data, 3, HIMAX_I2C_RETRY_TIMES) < 0)
 		return false;
 
-	if((data[0] == 0x85 && data[1] == 0x29))
-		{
-			IC_TYPE         = HX_85XX_F_SERIES_PWON;
-    	IC_CHECKSUM 		= HX_TP_BIN_CHECKSUM_CRC;
-    	//Himax: Set FW and CFG Flash Address                                          
-    	FW_VER_MAJ_FLASH_ADDR   = 64901;  //0xFD85                              
-    	FW_VER_MAJ_FLASH_LENG   = 1;
-    	FW_VER_MIN_FLASH_ADDR   = 64902;  //0xFD86                                     
-    	FW_VER_MIN_FLASH_LENG   = 1;
-    	CFG_VER_MAJ_FLASH_ADDR 	= 64928;   //0xFDA0         
-    	CFG_VER_MAJ_FLASH_LENG 	= 12;
-    	CFG_VER_MIN_FLASH_ADDR 	= 64940;   //0xFDAC
-    	CFG_VER_MIN_FLASH_LENG 	= 12;
-			I("Himax IC package 852x F\n");
-			}
-	if((data[0] == 0x85 && data[1] == 0x30) || (cmd[0] == 0x05 && cmd[1] == 0x85 && cmd[2] == 0x29))
-		{
-			IC_TYPE 		= HX_85XX_E_SERIES_PWON;
-			IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
-			//Himax: Set FW and CFG Flash Address                                          
-			FW_VER_MAJ_FLASH_ADDR	= 133;	//0x0085                              
-			FW_VER_MAJ_FLASH_LENG	= 1;                                               
-			FW_VER_MIN_FLASH_ADDR	= 134;  //0x0086                                     
-			FW_VER_MIN_FLASH_LENG	= 1;                                                
-			CFG_VER_MAJ_FLASH_ADDR = 160;	//0x00A0         
-			CFG_VER_MAJ_FLASH_LENG = 12; 	                                 
-			CFG_VER_MIN_FLASH_ADDR = 172;	//0x00AC
-			CFG_VER_MIN_FLASH_LENG = 12;   
-			I("Himax IC package 852x E\n");
-		}
-	else if((data[0] == 0x85 && data[1] == 0x31))
-		{
-			IC_TYPE         = HX_85XX_ES_SERIES_PWON;
-    	IC_CHECKSUM 		= HX_TP_BIN_CHECKSUM_CRC;
-    	//Himax: Set FW and CFG Flash Address                                          
-    	FW_VER_MAJ_FLASH_ADDR   = 133;  //0x0085                              
-    	FW_VER_MAJ_FLASH_LENG   = 1;
-    	FW_VER_MIN_FLASH_ADDR   = 134;  //0x0086                                     
-    	FW_VER_MIN_FLASH_LENG   = 1;
-    	CFG_VER_MAJ_FLASH_ADDR 	= 160;   //0x00A0         
-    	CFG_VER_MAJ_FLASH_LENG 	= 12;
-    	CFG_VER_MIN_FLASH_ADDR 	= 172;   //0x00AC
-    	CFG_VER_MIN_FLASH_LENG 	= 12;
-			I("Himax IC package 852x ES\n");
-			}
-	else if ((data[0] == 0x85 && data[1] == 0x28) || (cmd[0] == 0x04 && cmd[1] == 0x85 &&
-		(cmd[2] == 0x26 || cmd[2] == 0x27 || cmd[2] == 0x28))) {
-		IC_TYPE                = HX_85XX_D_SERIES_PWON;
-		IC_CHECKSUM            = HX_TP_BIN_CHECKSUM_CRC;
-		//Himax: Set FW and CFG Flash Address
-		FW_VER_MAJ_FLASH_ADDR  = 133;                    // 0x0085
-		FW_VER_MAJ_FLASH_LENG  = 1;
-		FW_VER_MIN_FLASH_ADDR  = 134;                    // 0x0086
-		FW_VER_MIN_FLASH_LENG  = 1;
-		CFG_VER_MAJ_FLASH_ADDR = 160;                    // 0x00A0
+	if ((data[0] == 0x85 && data[1] == 0x29)) {
+		IC_TYPE = HX_85XX_F_SERIES_PWON;
+		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+		/*Himax: Set FW and CFG Flash Address*/
+		FW_VER_MAJ_FLASH_ADDR = 64901;  /*0xFD85*/
+		FW_VER_MAJ_FLASH_LENG = 1;
+		FW_VER_MIN_FLASH_ADDR = 64902;  /*0xFD86*/
+		FW_VER_MIN_FLASH_LENG = 1;
+		CFG_VER_MAJ_FLASH_ADDR = 64928;   /*0xFDA0*/
 		CFG_VER_MAJ_FLASH_LENG = 12;
-		CFG_VER_MIN_FLASH_ADDR = 172;                    // 0x00AC
+		CFG_VER_MIN_FLASH_ADDR = 64940;   /*0xFDAC*/
+		CFG_VER_MIN_FLASH_LENG = 12;
+		I("Himax IC package 852x F\n");
+	}
+	if ((data[0] == 0x85 && data[1] == 0x30)
+		|| (cmd[0] == 0x05 && cmd[1] == 0x85 && cmd[2] == 0x29)) {
+		IC_TYPE = HX_85XX_E_SERIES_PWON;
+		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+		/*Himax: Set FW and CFG Flash Address*/
+		FW_VER_MAJ_FLASH_ADDR = 133;	/*0x0085*/
+		FW_VER_MAJ_FLASH_LENG = 1;
+		FW_VER_MIN_FLASH_ADDR = 134;  /*0x0086*/
+		FW_VER_MIN_FLASH_LENG = 1;
+		CFG_VER_MAJ_FLASH_ADDR = 160;	/*0x00A0*/
+		CFG_VER_MAJ_FLASH_LENG = 12;
+		CFG_VER_MIN_FLASH_ADDR = 172;	/*0x00AC*/
+		CFG_VER_MIN_FLASH_LENG = 12;
+		I("Himax IC package 852x E\n");
+	} else if ((data[0] == 0x85 && data[1] == 0x31)) {
+		IC_TYPE = HX_85XX_ES_SERIES_PWON;
+		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+		/*Himax: Set FW and CFG Flash Address*/
+		FW_VER_MAJ_FLASH_ADDR = 133;  /*0x0085*/
+		FW_VER_MAJ_FLASH_LENG = 1;
+		FW_VER_MIN_FLASH_ADDR = 134;  /*0x0086*/
+		FW_VER_MIN_FLASH_LENG = 1;
+		CFG_VER_MAJ_FLASH_ADDR = 160;   /*0x00A0*/
+		CFG_VER_MAJ_FLASH_LENG = 12;
+		CFG_VER_MIN_FLASH_ADDR = 172;   /*0x00AC*/
+		CFG_VER_MIN_FLASH_LENG = 12;
+		I("Himax IC package 852x ES\n");
+	} else if ((data[0] == 0x85 && data[1] == 0x28)
+		|| (cmd[0] == 0x04 && cmd[1] == 0x85
+		&& (cmd[2] == 0x26 || cmd[2] == 0x27
+		|| cmd[2] == 0x28))) {
+		IC_TYPE = HX_85XX_D_SERIES_PWON;
+		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+		/*Himax: Set FW and CFG Flash Address*/
+		FW_VER_MAJ_FLASH_ADDR = 133;    /*0x0085*/
+		FW_VER_MAJ_FLASH_LENG = 1;
+		FW_VER_MIN_FLASH_ADDR = 134;   /*0x0086*/
+		FW_VER_MIN_FLASH_LENG = 1;
+		CFG_VER_MAJ_FLASH_ADDR = 160;  /*0x00A0*/
+		CFG_VER_MAJ_FLASH_LENG = 12;
+		CFG_VER_MIN_FLASH_ADDR = 172;  /* 0x00AC*/
 		CFG_VER_MIN_FLASH_LENG = 12;
 		I("Himax IC package 852x D\n");
-	} else if ((data[0] == 0x85 && data[1] == 0x23) || (cmd[0] == 0x03 && cmd[1] == 0x85 &&
-			(cmd[2] == 0x26 || cmd[2] == 0x27 || cmd[2] == 0x28 || cmd[2] == 0x29))) {
-		IC_TYPE                = HX_85XX_C_SERIES_PWON;
-		IC_CHECKSUM            = HX_TP_BIN_CHECKSUM_SW;
-		//Himax: Set FW and CFG Flash Address
-		FW_VER_MAJ_FLASH_ADDR  = 133;                   // 0x0085
-		FW_VER_MAJ_FLASH_LENG  = 1;
-		FW_VER_MIN_FLASH_ADDR  = 134;                   // 0x0086
-		FW_VER_MIN_FLASH_LENG  = 1;
-		CFG_VER_MAJ_FLASH_ADDR = 135;                   // 0x0087
+	} else if ((data[0] == 0x85 && data[1] == 0x23) ||
+		(cmd[0] == 0x03 && cmd[1] == 0x85 &&
+		(cmd[2] == 0x26 || cmd[2] == 0x27 ||
+		cmd[2] == 0x28 || cmd[2] == 0x29))) {
+		IC_TYPE = HX_85XX_C_SERIES_PWON;
+		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
+		/*Himax: Set FW and CFG Flash Address*/
+		FW_VER_MAJ_FLASH_ADDR = 133;                   /*0x0085*/
+		FW_VER_MAJ_FLASH_LENG = 1;
+		FW_VER_MIN_FLASH_ADDR = 134;                   /*0x0086*/
+		FW_VER_MIN_FLASH_LENG = 1;
+		CFG_VER_MAJ_FLASH_ADDR = 135;                   /*0x0087*/
 		CFG_VER_MAJ_FLASH_LENG = 12;
-		CFG_VER_MIN_FLASH_ADDR = 147;                   // 0x0093
+		CFG_VER_MIN_FLASH_ADDR = 147;                   /*0x0093*/
 		CFG_VER_MIN_FLASH_LENG = 12;
 		I("Himax IC package 852x C\n");
 	} else if ((data[0] == 0x85 && data[1] == 0x26) ||
-		   (cmd[0] == 0x02 && cmd[1] == 0x85 &&
-		   (cmd[2] == 0x19 || cmd[2] == 0x25 || cmd[2] == 0x26))) {
+		(cmd[0] == 0x02 && cmd[1] == 0x85 &&
+		(cmd[2] == 0x19 || cmd[2] == 0x25 || cmd[2] == 0x26))) {
 		IC_TYPE                = HX_85XX_B_SERIES_PWON;
 		IC_CHECKSUM            = HX_TP_BIN_CHECKSUM_SW;
-		//Himax: Set FW and CFG Flash Address
-		FW_VER_MAJ_FLASH_ADDR  = 133;                   // 0x0085
-		FW_VER_MAJ_FLASH_LENG  = 1;
-		FW_VER_MIN_FLASH_ADDR  = 728;                   // 0x02D8
-		FW_VER_MIN_FLASH_LENG  = 1;
-		CFG_VER_MAJ_FLASH_ADDR = 692;                   // 0x02B4
+		/*Himax: Set FW and CFG Flash Address*/
+		FW_VER_MAJ_FLASH_ADDR = 133;                   /*0x0085*/
+		FW_VER_MAJ_FLASH_LENG = 1;
+		FW_VER_MIN_FLASH_ADDR = 728;                   /*0x02D8*/
+		FW_VER_MIN_FLASH_LENG = 1;
+		CFG_VER_MAJ_FLASH_ADDR = 692;                   /*0x02B4*/
 		CFG_VER_MAJ_FLASH_LENG = 3;
-		CFG_VER_MIN_FLASH_ADDR = 704;                   // 0x02C0
+		CFG_VER_MIN_FLASH_ADDR = 704;                   /*0x02C0*/
 		CFG_VER_MIN_FLASH_LENG = 3;
 		I("Himax IC package 852x B\n");
 	} else if ((data[0] == 0x85 && data[1] == 0x20) || (cmd[0] == 0x01 &&
-			cmd[1] == 0x85 && cmd[2] == 0x19)) {
+		cmd[1] == 0x85 && cmd[2] == 0x19)) {
 		IC_TYPE     = HX_85XX_A_SERIES_PWON;
 		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW;
 		I("Himax IC package 852x A\n");
 	} else {
 		E("Himax IC package incorrect!!\n");
-	}*/
+	}
 #else
-		IC_TYPE         = HX_83100_SERIES_PWON;
-    IC_CHECKSUM 		= HX_TP_BIN_CHECKSUM_CRC;
-    //Himax: Set FW and CFG Flash Address
-    FW_VER_MAJ_FLASH_ADDR   = 57384;   //0xE028
-    FW_VER_MAJ_FLASH_LENG   = 1;
-    FW_VER_MIN_FLASH_ADDR   = 57385;   //0xE029
-    FW_VER_MIN_FLASH_LENG   = 1;
-    CFG_VER_MAJ_FLASH_ADDR 	= 58115;  //0xE303
-    CFG_VER_MAJ_FLASH_LENG 	= 1;
-    CFG_VER_MIN_FLASH_ADDR 	= 58116;  //0xE304
-    CFG_VER_MIN_FLASH_LENG 	= 1;
+		IC_TYPE = HX_83100_SERIES_PWON;
+		IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC;
+		/*Himax: Set FW and CFG Flash Address*/
+		FW_VER_MAJ_FLASH_ADDR = 57384;   /*0xE028*/
+		FW_VER_MAJ_FLASH_LENG = 1;
+		FW_VER_MIN_FLASH_ADDR = 57385;   /*0xE029*/
+		FW_VER_MIN_FLASH_LENG = 1;
+		CFG_VER_MAJ_FLASH_ADDR = 58115;  /*0xE303*/
+		CFG_VER_MAJ_FLASH_LENG = 1;
+		CFG_VER_MIN_FLASH_ADDR = 58116;  /*0xE304*/
+		CFG_VER_MIN_FLASH_LENG = 1;
 		I("Himax IC package 83100_in\n");
 
 #endif
 	return true;
 }
 
-void himax_read_event_stack(struct i2c_client *client, 	uint8_t *buf, uint8_t length)
+void himax_read_event_stack(struct i2c_client *client,
+uint8_t *buf, uint8_t length)
 {
 	uint8_t cmd[4];
 
-	cmd[3] = 0x90; cmd[2] = 0x06; cmd[1] = 0x00; cmd[0] = 0x00;	
-	if ( i2c_himax_write(client, 0x00 ,cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
-		E("%s: i2c access fail!\n", __func__);		
+	cmd[3] = 0x90; cmd[2] = 0x06;
+	cmd[1] = 0x00; cmd[0] = 0x00;
+	if (i2c_himax_write(client, 0x00,
+		cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+		E("%s: i2c access fail!\n", __func__);
 	}
 
-	cmd[0] = 0x00;		
-	if ( i2c_himax_write(client, 0x0C ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
-		E("%s: i2c access fail!\n", __func__);		
+	cmd[0] = 0x00;
+	if (i2c_himax_write(client, 0x0C,
+		cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+		E("%s: i2c access fail!\n", __func__);
 	}
 
-	i2c_himax_read(client, 0x08, buf, length, HIMAX_I2C_RETRY_TIMES);
+	i2c_himax_read(client, 0x08,
+	buf, length, HIMAX_I2C_RETRY_TIMES);
 }
 
-#if 0
-static void himax_83100_Flash_Write(uint8_t * reg_byte, uint8_t * write_data)
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
+static void himax_83100_Flash_Write(uint8_t *reg_byte, uint8_t *write_data)
 {
 	uint8_t tmpbyte[2];
 
-    if ( i2c_himax_write(private_ts->client, 0x00 ,&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(private_ts->client, 0x00,
+		&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_write(private_ts->client, 0x01 ,&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(private_ts->client, 0x01,
+		&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_write(private_ts->client, 0x02 ,&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(private_ts->client, 0x02,
+		&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_write(private_ts->client, 0x03 ,&reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(private_ts->client,
+		0x03, &reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_write(private_ts->client, 0x04 ,&write_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(private_ts->client,
+		0x04, &write_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_write(private_ts->client, 0x05 ,&write_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(private_ts->client,
+		0x05, &write_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_write(private_ts->client, 0x06 ,&write_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(private_ts->client,
+		0x06, &write_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_write(private_ts->client, 0x07 ,&write_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(private_ts->client,
+		0x07, &write_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-    if (isBusrtOn == false)
-    {
-        tmpbyte[0] = 0x01;
-		if ( i2c_himax_write(private_ts->client, 0x0C ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
-		E("%s: i2c access fail!\n", __func__);
-		return;
+	if (isBusrtOn == false) {
+		tmpbyte[0] = 0x01;
+		if (i2c_himax_write(private_ts->client,
+			0x0C, &tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+			E("%s: i2c access fail!\n", __func__);
+			return;
 		}
-    }
+	}
 }
 #endif
-#if 0
-static void himax_83100_Flash_Burst_Write(uint8_t * reg_byte, uint8_t * write_data)
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
+static void himax_83100_Flash_Burst_Write
+(uint8_t *reg_byte, uint8_t *write_data)
 {
-    //uint8_t tmpbyte[2];
+    /*uint8_t tmpbyte[2];*/
 	int i = 0;
 
-	if ( i2c_himax_write(private_ts->client, 0x00 ,&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(private_ts->client, 0x00,
+		&reg_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_write(private_ts->client, 0x01 ,&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(private_ts->client, 0x01,
+		&reg_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_write(private_ts->client, 0x02 ,&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(private_ts->client, 0x02,
+		&reg_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-	if ( i2c_himax_write(private_ts->client, 0x03 ,&reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(private_ts->client, 0x03,
+		&reg_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		return;
 	}
 
-    // Write 256 bytes with continue burst mode
-    for (i = 0; i < 256; i = i + 4)
+    /*Write 256 bytes with continue burst mode*/
+	for (i = 0 ; i < 256 ; i = i + 4) {
+		if (i2c_himax_write(private_ts->client,
+			0x04, &write_data[i], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+			E("%s: i2c access fail!\n", __func__);
+			return;
+		}
+
+		if (i2c_himax_write(private_ts->client, 0x05,
+			&write_data[i+1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+			E("%s: i2c access fail!\n", __func__);
+			return;
+		}
+
+		if (i2c_himax_write(private_ts->client, 0x06,
+			&write_data[i+2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+			E("%s: i2c access fail!\n", __func__);
+			return;
+		}
+
+		if (i2c_himax_write(private_ts->client, 0x07,
+			&write_data[i+3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+			E("%s: i2c access fail!\n", __func__);
+			return;
+		}
+	}
+
+    /*if (isBusrtOn == false)
     {
-		if ( i2c_himax_write(private_ts->client, 0x04 ,&write_data[i], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
-			E("%s: i2c access fail!\n", __func__);
-			return;
-		}
-
-		if ( i2c_himax_write(private_ts->client, 0x05 ,&write_data[i+1], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
-			E("%s: i2c access fail!\n", __func__);
-			return;
-		}
-
-		if ( i2c_himax_write(private_ts->client, 0x06 ,&write_data[i+2], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
-			E("%s: i2c access fail!\n", __func__);
-			return;
-		}
-
-		if ( i2c_himax_write(private_ts->client, 0x07 ,&write_data[i+3], 1, HIMAX_I2C_RETRY_TIMES) < 0) {
-			E("%s: i2c access fail!\n", __func__);
-			return;
-		}
-    }
-
-    //if (isBusrtOn == false)
-    //{
-    //   tmpbyte[0] = 0x01;
-	//	if ( i2c_himax_write(private_ts->client, 0x0C ,&tmpbyte[0], 1, 3) < 0) {
-	//	E("%s: i2c access fail!\n", __func__);
-	//	return;
-	//	}
-    //}
+       tmpbyte[0] = 0x01;
+		if (i2c_himax_write(private_ts->client,
+		0x0C, &tmpbyte[0], 1, 3) < 0) {
+		E("%s: i2c access fail!\n", __func__);
+		return;
+    }*/
 
 }
 #endif
 
-#if 0
+/*#if 0*/
+#ifdef HX_EN_CHECK_PATCH
 static bool himax_83100_Verify(uint8_t *FW_File, int FW_Size)
 {
 	uint8_t tmp_addr[4];
@@ -1835,49 +2079,51 @@
 	uint8_t out_buffer[20];
 	uint8_t in_buffer[260];
 
-	int fail_addr=0, fail_cnt=0;
+	int fail_addr = 0, fail_cnt = 0;
 	int page_prog_start = 0;
 	int i = 0;
 
 	himax_interface_on(private_ts->client);
 	himax_burst_enable(private_ts->client, 0);
 
-	//=====================================
-	// SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
-	//=====================================
-	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80;
+	/*=====================================
+	SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780
+	=====================================*/
+	tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x00; tmp_addr[0] = 0x10;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x02;
+	tmp_data[1] = 0x07; tmp_data[0] = 0x80;
 	himax_83100_Flash_Write(tmp_addr, tmp_data);
 
-	for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start = page_prog_start + 256)
-	{
-		//=================================
-		// SPI Transfer Control
-		// Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
-		// Set read start address  : 0x8000_0028 ==> 0x0000_0000
-		// Set command			   : 0x8000_0024 ==> 0x0000_003B
-		//=================================
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
-		tmp_data[3] = 0x69; tmp_data[2] = 0x40; tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
+	for (page_prog_start = 0; page_prog_start < FW_Size;
+	page_prog_start = page_prog_start + 256) {
+		/*=====================================
+		SPI Transfer Control
+		Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF
+		Set read start address  : 0x8000_0028 ==> 0x0000_0000
+		Set command			   : 0x8000_0024 ==> 0x0000_003B
+		=====================================*/
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x20;
+		tmp_data[3] = 0x69; tmp_data[2] = 0x40;
+		tmp_data[1] = 0x02; tmp_data[0] = 0xFF;
 		himax_83100_Flash_Write(tmp_addr, tmp_data);
 
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
-		if (page_prog_start < 0x100)
-		{
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x28;
+		if (page_prog_start < 0x100) {
 			tmp_data[3] = 0x00;
 			tmp_data[2] = 0x00;
 			tmp_data[1] = 0x00;
 			tmp_data[0] = (uint8_t)page_prog_start;
-		}
-		else if (page_prog_start >= 0x100 && page_prog_start < 0x10000)
-		{
+		} else if (page_prog_start >= 0x100
+		&& page_prog_start < 0x10000) {
 			tmp_data[3] = 0x00;
 			tmp_data[2] = 0x00;
 			tmp_data[1] = (uint8_t)(page_prog_start >> 8);
 			tmp_data[0] = (uint8_t)page_prog_start;
-		}
-		else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000)
-		{
+		} else if (page_prog_start >= 0x10000
+		&& page_prog_start < 0x1000000) {
 			tmp_data[3] = 0x00;
 			tmp_data[2] = (uint8_t)(page_prog_start >> 16);
 			tmp_data[1] = (uint8_t)(page_prog_start >> 8);
@@ -1885,65 +2131,73 @@
 		}
 		himax_83100_Flash_Write(tmp_addr, tmp_data);
 
-		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
-		tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x24;
+		tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+		tmp_data[1] = 0x00; tmp_data[0] = 0x3B;
 		himax_83100_Flash_Write(tmp_addr, tmp_data);
 
-		//==================================
-		// AHB_I2C Burst Read
-		// Set SPI data register : 0x8000_002C ==> 0x00
-		//==================================
+		/*==================================
+		AHB_I2C Burst Read
+		Set SPI data register : 0x8000_002C ==> 0x00
+		==================================*/
 		out_buffer[0] = 0x2C;
 		out_buffer[1] = 0x00;
 		out_buffer[2] = 0x00;
 		out_buffer[3] = 0x80;
-		i2c_himax_write(private_ts->client, 0x00 ,out_buffer, 4, HIMAX_I2C_RETRY_TIMES);
+		i2c_himax_write(private_ts->client, 0x00,
+		out_buffer, 4, HIMAX_I2C_RETRY_TIMES);
 
-		//==================================
-		// Read access : 0x0C ==> 0x00
-		//==================================
+		/*==================================
+		Read access : 0x0C ==> 0x00
+		==================================*/
 		out_buffer[0] = 0x00;
-		i2c_himax_write(private_ts->client, 0x0C ,out_buffer, 1, HIMAX_I2C_RETRY_TIMES);
+		i2c_himax_write(private_ts->client, 0x0C,
+		out_buffer, 1, HIMAX_I2C_RETRY_TIMES);
 
-		//==================================
-		// Read 128 bytes two times
-		//==================================
-		i2c_himax_read(private_ts->client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
+		/*==================================
+		Read 128 bytes two times
+		==================================*/
+		i2c_himax_read(private_ts->client, 0x08,
+		in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
 		for (i = 0; i < 128; i++)
 			flash_buffer[i + page_prog_start] = in_buffer[i];
 
-		i2c_himax_read(private_ts->client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
+		i2c_himax_read(private_ts->client, 0x08,
+		in_buffer, 128, HIMAX_I2C_RETRY_TIMES);
 		for (i = 0; i < 128; i++)
-			flash_buffer[(i + 128) + page_prog_start] = in_buffer[i];
+			flash_buffer[(i + 128)
+			+ page_prog_start] = in_buffer[i];
 
-		//tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
-		//himax_register_read(tmp_addr, 32, out in_buffer);
-		//for (int i = 0; i < 128; i++)
-		//	  flash_buffer[i + page_prog_start] = in_buffer[i];
-		//tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
-		//himax_register_read(tmp_addr, 32, out in_buffer);
-		//for (int i = 0; i < 128; i++)
-		//	  flash_buffer[i + page_prog_start] = in_buffer[i];
-
+		/*tmp_addr[3] = 0x80;
+		tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
+		himax_register_read(tmp_addr, 32, out in_buffer);
+		for (int i = 0; i < 128; i++)
+			  flash_buffer[i + page_prog_start] = in_buffer[i];
+		tmp_addr[3] = 0x80; tmp_addr[2] = 0x00;
+		tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C;
+		himax_register_read(tmp_addr, 32, out in_buffer);
+		for (int i = 0; i < 128; i++)
+			  flash_buffer[i + page_prog_start] = in_buffer[i];
+		*/
 		I("%s:Verify Progress: %x\n", __func__, page_prog_start);
 	}
 
 	fail_cnt = 0;
-	for (i = 0; i < FW_Size; i++)
-	{
-		if (FW_File[i] != flash_buffer[i])
-		{
+	for (i = 0; i < FW_Size; i++) {
+		if (FW_File[i] != flash_buffer[i]) {
 			if (fail_cnt == 0)
 				fail_addr = i;
 
 			fail_cnt++;
-			//E("%s Fail Block:%x\n", __func__, i);
-			//return false;
+			/*E("%s Fail Block:%x\n", __func__, i);
+			return false;*/
 		}
 	}
-	if (fail_cnt > 0)
-	{
-		E("%s:Start Fail Block:%x and fail block count=%x\n" , __func__,fail_addr,fail_cnt);
+	if (fail_cnt > 0) {
+		E("%s:Start Fail Block:%x and fail block count=%x\n",
+		__func__, fail_addr, fail_cnt);
 		return false;
 	}
 
@@ -1959,56 +2213,60 @@
 	int cnt = 0;
 	unsigned char tmp_addr[4];
 	unsigned char tmp_data[4];
-  uint8_t max_i2c_size = 32;
+	uint8_t max_i2c_size = 32;
 	int total_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM * 2;
 	int total_size_4bytes = total_size / 4;
 	int total_read_times = 0;
 	unsigned long address = 0x08000468;
-  tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
-	tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x5A; tmp_data[0] = 0xA5;
+
+	tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
+	tmp_data[3] = 0x00; tmp_data[2] = 0x00;
+	tmp_data[1] = 0x5A; tmp_data[0] = 0xA5;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
-  do
-	{
+	do {
 		cnt++;
 		himax_register_read(client, tmp_addr, 1, tmp_data);
-		usleep_range(10000, 20000);
+		usleep_range(9999, 10000);
 	} while ((tmp_data[1] != 0xA5 || tmp_data[0] != 0x5A) && cnt < 100);
-  tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x68;
-  if (total_size_4bytes % max_i2c_size == 0)
-	{
+	tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x04; tmp_addr[0] = 0x68;
+	if (total_size_4bytes % max_i2c_size == 0)
 		total_read_times = total_size_4bytes / max_i2c_size;
-	}
 	else
-	{
 		total_read_times = total_size_4bytes / max_i2c_size + 1;
-	}
-	for (i = 0; i < (total_read_times); i++)
-	{
-		if ( total_size_4bytes >= max_i2c_size)
-		{
-			himax_register_read(client, tmp_addr, max_i2c_size, &info_data[i*max_i2c_size*4]);
+
+	for (i = 0 ; i < (total_read_times) ; i++) {
+		if (total_size_4bytes >= max_i2c_size) {
+			himax_register_read(client, tmp_addr,
+			max_i2c_size,
+			&info_data[i*max_i2c_size*4]);
 			total_size_4bytes = total_size_4bytes - max_i2c_size;
+		} else {
+			himax_register_read(client, tmp_addr,
+			total_size_4bytes % max_i2c_size,
+			&info_data[i*max_i2c_size*4]);
 		}
-		else
-		{
-			himax_register_read(client, tmp_addr, total_size_4bytes % max_i2c_size, &info_data[i*max_i2c_size*4]);
-		}
-		address += max_i2c_size*4;
-		tmp_addr[1] = (uint8_t)((address>>8)&0x00FF);
-		tmp_addr[0] = (uint8_t)((address)&0x00FF);
+		address += max_i2c_size * 4;
+		tmp_addr[1] = (uint8_t)((address>>8) & 0x00FF);
+		tmp_addr[0] = (uint8_t)((address) & 0x00FF);
 	}
-	tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
-	tmp_data[3] = 0x11; tmp_data[2] = 0x22; tmp_data[1] = 0x33; tmp_data[0] = 0x44;
+	tmp_addr[3] = 0x08; tmp_addr[2] = 0x00;
+	tmp_addr[1] = 0x04; tmp_addr[0] = 0x64;
+	tmp_data[3] = 0x11; tmp_data[2] = 0x22;
+	tmp_data[1] = 0x33; tmp_data[0] = 0x44;
 	himax_flash_write_burst(client, tmp_addr, tmp_data);
 }
-//ts_work
-int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max){
+/*ts_work*/
+int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max)
+{
 	int RawDataLen;
-	if (raw_cnt_rmd != 0x00) {
-		RawDataLen = 124 - ((HX_MAX_PT+raw_cnt_max+3)*4) - 1;
-	}else{
-		RawDataLen = 124 - ((HX_MAX_PT+raw_cnt_max+2)*4) - 1;
-	}
+
+	if (raw_cnt_rmd != 0x00)
+		RawDataLen = 124 - ((HX_MAX_PT + raw_cnt_max + 3) * 4) - 1;
+	else
+		RawDataLen = 124 - ((HX_MAX_PT + raw_cnt_max + 2) * 4) - 1;
+
 	return RawDataLen;
 }
 
@@ -2016,40 +2274,40 @@
 {
 	uint8_t cmd[4];
 
-	if(length > 56)
+	if (length > 56)
 		length = 124;
-	//=====================
-	//AHB I2C Burst Read
-	//=====================
+	/*=====================
+	AHB I2C Burst Read
+	=====================*/
 	cmd[0] = 0x31;
-	if ( i2c_himax_write(client, 0x13 ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(client, 0x13, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		goto err_workqueue_out;
 	}
 
 	cmd[0] = 0x10;
-	if ( i2c_himax_write(client, 0x0D ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(client, 0x0D, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		goto err_workqueue_out;
 	}
-	//=====================
-	//Read event stack
-	//=====================
+	/*=====================
+	Read event stack
+	=====================*/
 	cmd[3] = 0x90; cmd[2] = 0x06; cmd[1] = 0x00; cmd[0] = 0x00;
-	if ( i2c_himax_write(client, 0x00 ,cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(client, 0x00, cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		goto err_workqueue_out;
 	}
 
 	cmd[0] = 0x00;
-	if ( i2c_himax_write(client, 0x0C ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
+	if (i2c_himax_write(client, 0x0C, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) {
 		E("%s: i2c access fail!\n", __func__);
 		goto err_workqueue_out;
 	}
-	i2c_himax_read(client, 0x08, buf, length,HIMAX_I2C_RETRY_TIMES);
+	i2c_himax_read(client, 0x08, buf, length, HIMAX_I2C_RETRY_TIMES);
 	return 1;
-	
-	err_workqueue_out:
+
+err_workqueue_out:
 	return 0;
 }
 
@@ -2057,62 +2315,67 @@
 {
 	return 1;
 }
-bool diag_check_sum( uint8_t hx_touch_info_size, uint8_t *buf) //return checksum value
+bool diag_check_sum(uint8_t hx_touch_info_size,
+uint8_t *buf) /*return checksum value*/
 {
 	uint16_t check_sum_cal = 0;
 	int i;
 
-	//Check 124th byte CRC
-	for (i = hx_touch_info_size, check_sum_cal = 0; i < 124; i=i+2)
-	{
-		check_sum_cal += (buf[i+1]*256 + buf[i]);
-	}
-	if (check_sum_cal % 0x10000 != 0)
-	{
-		I("%s: diag check sum fail! check_sum_cal=%X, hx_touch_info_size=%d, \n",__func__,check_sum_cal, hx_touch_info_size);
+	/*Check 124th byte CRC*/
+	for (i = hx_touch_info_size, check_sum_cal = 0 ; i < 124 ; i = i + 2)
+		check_sum_cal += (buf[i + 1] * 256 + buf[i]);
+
+	if (check_sum_cal % 0x10000 != 0) {
+		I("%s:diag chksum fail!check_sum_cal=%X,hx_touchinfo_sz=%d,\n",
+		__func__, check_sum_cal, hx_touch_info_size);
 		return 0;
 	}
 	return 1;
 }
 
-
-void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen, int mul_num, int self_num, uint8_t *buf, uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data)
+void diag_parse_raw_data(int hx_touch_info_size,
+int RawDataLen, int mul_num, int self_num, uint8_t *buf,
+uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data)
 {
 	int RawDataLen_word;
 	int index = 0;
-	int temp1, temp2,i;
-	
-	if (buf[hx_touch_info_size] == 0x3A && buf[hx_touch_info_size+1] == 0xA3 && buf[hx_touch_info_size+2] > 0 && buf[hx_touch_info_size+3] == diag_cmd+5 )
-	{
-			RawDataLen_word = RawDataLen/2;
-			index = (buf[hx_touch_info_size+2] - 1) * RawDataLen_word;
-		//I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num);
-			for (i = 0; i < RawDataLen_word; i++)
-		{
+	int temp1, temp2, i;
+
+	if (buf[hx_touch_info_size] == 0x3A &&
+		buf[hx_touch_info_size + 1] == 0xA3 &&
+		buf[hx_touch_info_size + 2] > 0 &&
+		buf[hx_touch_info_size + 3] == diag_cmd + 5) {
+		RawDataLen_word = RawDataLen / 2;
+		index = (buf[hx_touch_info_size + 2] - 1) * RawDataLen_word;
+		/*I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n",
+		index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num);*/
+		for (i = 0; i < RawDataLen_word; i++) {
 			temp1 = index + i;
 
-			if (temp1 < mul_num)
-			{ //mutual
-					mutual_data[index + i] = buf[i*2 + hx_touch_info_size+4+1]*256 + buf[i*2 + hx_touch_info_size+4];	//4: RawData Header, 1:HSB
-			}
-			else
-			{//self
+			if (temp1 < mul_num) { /*mutual*/
+					/*4: RawData Header, 1:HSB */
+					mutual_data[index + i]
+					= buf[i*2 + hx_touch_info_size + 4 + 1]
+					* 256
+					+ buf[i * 2 + hx_touch_info_size + 4];
+			} else { /*self*/
 				temp1 = i + index;
 				temp2 = self_num + mul_num;
-				
-				if (temp1 >= temp2)
-				{
-					break;
-				}
 
-					self_data[i+index-mul_num] = buf[i*2 + hx_touch_info_size+4];	//4: RawData Header
-					self_data[i+index-mul_num+1] = buf[i*2 + hx_touch_info_size+4+1];
+				if (temp1 >= temp2)
+					break;
+
+				/*4: RawData Header*/
+				self_data[i + index - mul_num]
+				= buf[i * 2 + hx_touch_info_size + 4];
+				self_data[i + index - mul_num + 1]
+				= buf[i * 2 + hx_touch_info_size + 4 + 1];
 			}
 		}
-	}
-	else
-	{
+	} else {
 		I("[HIMAX TP MSG]%s: header format is wrong!\n", __func__);
-			I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num);
+			I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n",
+			index, buf[56], buf[57], buf[58], buf[59],
+			mul_num, self_num);
 	}
 }
diff --git a/drivers/input/touchscreen/hxchipset/himax_ic.h b/drivers/input/touchscreen/hxchipset/himax_ic.h
index 18cd12b..ce7d0d4 100644
--- a/drivers/input/touchscreen/hxchipset/himax_ic.h
+++ b/drivers/input/touchscreen/hxchipset/himax_ic.h
@@ -18,7 +18,6 @@
 
 #include <linux/slab.h>
 
-
 #define HX_85XX_A_SERIES_PWON		1
 #define HX_85XX_B_SERIES_PWON		2
 #define HX_85XX_C_SERIES_PWON		3
@@ -40,43 +39,110 @@
 };
 
 int himax_hand_shaking(struct i2c_client *client);
-void himax_set_SMWP_enable(struct i2c_client *client,uint8_t SMWP_enable);
-void himax_get_SMWP_enable(struct i2c_client *client,uint8_t *tmp_data);
-void himax_set_HSEN_enable(struct i2c_client *client,uint8_t HSEN_enable);
-void himax_get_HSEN_enable(struct i2c_client *client,uint8_t *tmp_data);
+void himax_set_SMWP_enable(struct i2c_client *client, uint8_t SMWP_enable);
+void himax_get_SMWP_enable(struct i2c_client *client, uint8_t *tmp_data);
+void himax_set_HSEN_enable(struct i2c_client *client, uint8_t HSEN_enable);
+void himax_get_HSEN_enable(struct i2c_client *client, uint8_t *tmp_data);
 void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command);
-void himax_flash_dump_func(struct i2c_client *client, uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer);
+
+void himax_flash_dump_func(struct i2c_client *client,
+uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer);
+
 int himax_chip_self_test(struct i2c_client *client);
-int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte); ////himax_83100_BURST_INC0_EN
-void himax_register_read(struct i2c_client *client, uint8_t *read_addr, int read_length, uint8_t *read_data); ////RegisterRead83100
-void himax_flash_read(struct i2c_client *client, uint8_t *reg_byte, uint8_t *read_data); ////himax_83100_Flash_Read
-void himax_flash_write_burst(struct i2c_client *client, uint8_t * reg_byte, uint8_t * write_data); ////himax_83100_Flash_Write_Burst
-int himax_flash_write_burst_lenth(struct i2c_client *client, uint8_t *reg_byte, uint8_t *write_data, int length); ////himax_83100_Flash_Write_Burst_lenth
-int himax_register_write(struct i2c_client *client, uint8_t *write_addr, int write_length, uint8_t *write_data); ////RegisterWrite83100
-void himax_sense_off(struct i2c_client *client); ////himax_83100_SenseOff
-void himax_interface_on(struct i2c_client *client); ////himax_83100_Interface_on
+
+/*himax_83100_BURST_INC0_EN*/
+int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte);
+
+/*RegisterRead83100*/
+void himax_register_read(struct i2c_client *client,
+	uint8_t *read_addr, int read_length, uint8_t *read_data);
+
+/*himax_83100_Flash_Read*/
+void himax_flash_read(struct i2c_client *client,
+	uint8_t *reg_byte, uint8_t *read_data);
+
+/*himax_83100_Flash_Write_Burst*/
+void himax_flash_write_burst(struct i2c_client *client,
+	uint8_t *reg_byte, uint8_t *write_data);
+
+/*himax_83100_Flash_Write_Burst_length*/
+int himax_flash_write_burst_length(struct i2c_client *client,
+	uint8_t *reg_byte, uint8_t *write_data, int length);
+
+/*RegisterWrite83100*/
+int himax_register_write(struct i2c_client *client,
+	uint8_t *write_addr, int write_length, uint8_t *write_data);
+
+/*himax_83100_SenseOff*/
+void himax_sense_off(struct i2c_client *client);
+/*himax_83100_Interface_on*/
+void himax_interface_on(struct i2c_client *client);
 bool wait_wip(struct i2c_client *client, int Timing);
-void himax_sense_on(struct i2c_client *client, uint8_t FlashMode); ////himax_83100_SenseOn
-void himax_chip_erase(struct i2c_client *client); ////himax_83100_Chip_Erase
-bool himax_block_erase(struct i2c_client *client); ////himax_83100_Block_Erase
-bool himax_sector_erase(struct i2c_client *client, int start_addr); ////himax_83100_Sector_Erase
-void himax_sram_write(struct i2c_client *client, uint8_t *FW_content); ////himax_83100_Sram_Write
-bool himax_sram_verify(struct i2c_client *client, uint8_t *FW_File, int FW_Size); ////himax_83100_Sram_Verify
-void himax_flash_programming(struct i2c_client *client, uint8_t *FW_content, int FW_Size); ////himax_83100_Flash_Programming
-bool himax_check_chip_version(struct i2c_client *client); ////himax_83100_CheckChipVersion
-int himax_check_CRC(struct i2c_client *client, int mode); ////himax_83100_Check_CRC
-bool Calculate_CRC_with_AP(unsigned char *FW_content , int CRC_from_FW, int mode);
-int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref);
-int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref);
-int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref);
-int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref);
+
+/*himax_83100_SenseOn*/
+void himax_sense_on(struct i2c_client *client,
+	uint8_t FlashMode);
+
+/*himax_83100_Chip_Erase*/
+void himax_chip_erase(struct i2c_client *client);
+/*himax_83100_Block_Erase*/
+bool himax_block_erase(struct i2c_client *client);
+
+/*himax_83100_Sector_Erase*/
+bool himax_sector_erase(struct i2c_client *client, int start_addr);
+
+/*himax_83100_Sram_Write*/
+void himax_sram_write(struct i2c_client *client, uint8_t *FW_content);
+
+/*himax_83100_Sram_Verify*/
+bool himax_sram_verify(struct i2c_client *client,
+	uint8_t *FW_File, int FW_Size);
+
+/*himax_83100_Flash_Programming*/
+void himax_flash_programming(struct i2c_client *client,
+	uint8_t *FW_content, int FW_Size);
+
+/*himax_83100_CheckChipVersion*/
+bool himax_check_chip_version(struct i2c_client *client);
+
+/*himax_83100_Check_CRC*/
+int himax_check_CRC(struct i2c_client *client, int mode);
+
+bool Calculate_CRC_with_AP(unsigned char *FW_content,
+	int CRC_from_FW, int mode);
+
+int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client,
+	unsigned char *fw, int len, bool change_iref);
+
+int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client,
+	unsigned char *fw, int len, bool change_iref);
+
+int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client,
+	unsigned char *fw, int len, bool change_iref);
+
+int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client,
+	unsigned char *fw, int len, bool change_iref);
+
 void himax_touch_information(struct i2c_client *client);
 void himax_read_FW_ver(struct i2c_client *client);
 bool himax_ic_package_check(struct i2c_client *client);
-void himax_read_event_stack(struct i2c_client *client, uint8_t *buf, uint8_t length);
+
+void himax_read_event_stack(struct i2c_client *client,
+	uint8_t *buf, uint8_t length);
+
 int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max);
 bool read_event_stack(struct i2c_client *client, uint8_t *buf_ts, int length);
 bool post_read_event_stack(struct i2c_client *client);
-bool diag_check_sum( uint8_t hx_touch_info_size, uint8_t *buf_ts); //return checksum value
-void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen, int mul_num, int self_num, uint8_t *buf_ts, uint8_t diag_cmd, int16_t *mutual_data,	int16_t *self_data);
-void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data);
\ No newline at end of file
+
+/*return checksum value*/
+bool diag_check_sum(uint8_t hx_touch_info_size, uint8_t *buf_ts);
+
+void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen,
+	int mul_num, int self_num, uint8_t *buf_ts,
+	uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data);
+
+void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data);
+extern struct himax_ts_data *private_ts;
+extern struct himax_ic_data *ic_data;
+
+int himax_load_CRC_bin_file(struct i2c_client *client);
diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.c b/drivers/input/touchscreen/hxchipset/himax_platform.c
index 7e8a1d6..309bb5e 100644
--- a/drivers/input/touchscreen/hxchipset/himax_platform.c
+++ b/drivers/input/touchscreen/hxchipset/himax_platform.c
@@ -16,6 +16,13 @@
 #include "himax_platform.h"
 #include "himax_common.h"
 
+#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
+#define D(x...) pr_info("[HXTP][DEBUG] " x)
+#define I(x...) pr_info("[HXTP][INFO] " x)
+#define W(x...) pr_info("[HXTP][WARNING] " x)
+#define E(x...) pr_info("[HXTP][ERROR] " x)
+#endif
+
 int irq_enable_count = 0;
 #ifdef HX_SMART_WAKEUP
 #define TS_WAKE_LOCK_TIMEOUT		(2 * HZ)
@@ -25,16 +32,7 @@
 #define PINCTRL_STATE_SUSPEND	"pmx_ts_suspend"
 #define PINCTRL_STATE_RELEASE	"pmx_ts_release"
 
-extern struct himax_ic_data* ic_data;
-extern void himax_ts_work(struct himax_ts_data *ts);
-extern enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer);
-extern int himax_ts_init(struct himax_ts_data *ts);
-
-extern int tp_rst_gpio;
-
-#ifdef HX_TP_PROC_DIAG
-extern uint8_t getDiagCommand(void);
-#endif
+/*extern int himax_ts_init(struct himax_ts_data *ts);*/
 
 void himax_vk_parser(struct device_node *dt,
 				struct himax_i2c_platform_data *pdata)
@@ -49,30 +47,34 @@
 	if (node == NULL) {
 		I(" DT-No vk info in DT");
 		return;
+
 	} else {
 		while ((pp = of_get_next_child(node, pp)))
 			cnt++;
 		if (!cnt)
 			return;
 
-		vk = kzalloc(cnt * (sizeof *vk), GFP_KERNEL);
-		if (!vk)
-			return;
+		vk = kcalloc(cnt, sizeof(*vk), GFP_KERNEL);
 		pp = NULL;
 		while ((pp = of_get_next_child(node, pp))) {
 			if (of_property_read_u32(pp, "idx", &data) == 0)
 				vk[i].index = data;
-			if (of_property_read_u32_array(pp, "range", coords, 4) == 0) {
-				vk[i].x_range_min = coords[0], vk[i].x_range_max = coords[1];
-				vk[i].y_range_min = coords[2], vk[i].y_range_max = coords[3];
+			if (of_property_read_u32_array(pp, "range",
+				coords, 4) == 0) {
+				vk[i].x_range_min = coords[0],
+				vk[i].x_range_max = coords[1];
+				vk[i].y_range_min = coords[2],
+				vk[i].y_range_max = coords[3];
 			} else
 				I(" range faile");
 			i++;
 		}
 		pdata->virtual_key = vk;
 		for (i = 0; i < cnt; i++)
-			I(" vk[%d] idx:%d x_min:%d, y_max:%d", i,pdata->virtual_key[i].index,
-				pdata->virtual_key[i].x_range_min, pdata->virtual_key[i].y_range_max);
+			I(" vk[%d] idx:%d x_min:%d, y_max:%d",
+				i, pdata->virtual_key[i].index,
+				pdata->virtual_key[i].x_range_min,
+				pdata->virtual_key[i].y_range_max);
 	}
 }
 
@@ -89,25 +91,31 @@
 	if (prop) {
 		coords_size = prop->length / sizeof(u32);
 		if (coords_size != 4)
-			D(" %s:Invalid panel coords size %d", __func__, coords_size);
+			D(" %s:Invalid panel coords size %d",
+		__func__, coords_size);
 	}
 
-	if (of_property_read_u32_array(dt, "himax,panel-coords", coords, coords_size) == 0) {
+	if (of_property_read_u32_array(dt, "himax,panel-coords",
+		coords, coords_size) == 0) {
 		pdata->abs_x_min = coords[0], pdata->abs_x_max = coords[1];
 		pdata->abs_y_min = coords[2], pdata->abs_y_max = coords[3];
-		I(" DT-%s:panel-coords = %d, %d, %d, %d\n", __func__, pdata->abs_x_min,
-				pdata->abs_x_max, pdata->abs_y_min, pdata->abs_y_max);
+		I(" DT-%s:panel-coords = %d, %d, %d, %d\n",
+		__func__, pdata->abs_x_min, pdata->abs_x_max,
+		pdata->abs_y_min, pdata->abs_y_max);
 	}
 
 	prop = of_find_property(dt, "himax,display-coords", NULL);
 	if (prop) {
 		coords_size = prop->length / sizeof(u32);
 		if (coords_size != 4)
-			D(" %s:Invalid display coords size %d", __func__, coords_size);
+			D(" %s:Invalid display coords size %d",
+			__func__, coords_size);
 	}
-	rc = of_property_read_u32_array(dt, "himax,display-coords", coords, coords_size);
+	rc = of_property_read_u32_array(dt, "himax,display-coords",
+		coords, coords_size);
 	if (rc && (rc != -EINVAL)) {
-		D(" %s:Fail to read display-coords %d\n", __func__, rc);
+		D(" %s:Fail to read display-coords %d\n",
+		__func__, rc);
 		return rc;
 	}
 	pdata->screenWidth  = coords[1];
@@ -116,19 +124,19 @@
 		pdata->screenHeight);
 
 	pdata->gpio_irq = of_get_named_gpio(dt, "himax,irq-gpio", 0);
-	if (!gpio_is_valid(pdata->gpio_irq)) {
+	if (!gpio_is_valid(pdata->gpio_irq))
 		I(" DT:gpio_irq value is not valid\n");
-	}
 
 	pdata->gpio_reset = of_get_named_gpio(dt, "himax,rst-gpio", 0);
-	if (!gpio_is_valid(pdata->gpio_reset)) {
+	if (!gpio_is_valid(pdata->gpio_reset))
 		I(" DT:gpio_rst value is not valid\n");
-	}
+
 	pdata->gpio_3v3_en = of_get_named_gpio(dt, "himax,3v3-gpio", 0);
-	if (!gpio_is_valid(pdata->gpio_3v3_en)) {
+	if (!gpio_is_valid(pdata->gpio_3v3_en))
 		I(" DT:gpio_3v3_en value is not valid\n");
-	}
-	I(" DT:gpio_irq=%d, gpio_rst=%d, gpio_3v3_en=%d", pdata->gpio_irq, pdata->gpio_reset, pdata->gpio_3v3_en);
+
+	I(" DT:gpio_irq=%d, gpio_rst=%d, gpio_3v3_en=%d",
+	pdata->gpio_irq, pdata->gpio_reset, pdata->gpio_3v3_en);
 
 	if (of_property_read_u32(dt, "report_type", &data) == 0) {
 		pdata->protocol_type = data;
@@ -140,7 +148,8 @@
 	return 0;
 }
 
-int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry)
+int i2c_himax_read(struct i2c_client *client,
+uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry)
 {
 	int retry;
 	struct i2c_msg msg[] = {
@@ -157,7 +166,7 @@
 			.buf = data,
 		}
 	};
-
+	mutex_lock(&private_ts->rw_lock);
 	for (retry = 0; retry < toRetry; retry++) {
 		if (i2c_transfer(client->adapter, msg, 2) == 2)
 			break;
@@ -166,13 +175,16 @@
 	if (retry == toRetry) {
 		E("%s: i2c_read_block retry over %d\n",
 			__func__, toRetry);
+		mutex_unlock(&private_ts->rw_lock);
 		return -EIO;
 	}
+	mutex_unlock(&private_ts->rw_lock);
 	return 0;
 
 }
 
-int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry)
+int i2c_himax_write(struct i2c_client *client,
+uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry)
 {
 	int retry/*, loop_i*/;
 	uint8_t buf[length + 1];
@@ -188,7 +200,7 @@
 
 	buf[0] = command;
 	memcpy(buf+1, data, length);
-	
+	mutex_lock(&private_ts->rw_lock);
 	for (retry = 0; retry < toRetry; retry++) {
 		if (i2c_transfer(client->adapter, msg, 1) == 1)
 			break;
@@ -198,13 +210,16 @@
 	if (retry == toRetry) {
 		E("%s: i2c_write_block retry over %d\n",
 			__func__, toRetry);
+		mutex_unlock(&private_ts->rw_lock);
 		return -EIO;
 	}
+	mutex_unlock(&private_ts->rw_lock);
 	return 0;
 
 }
 
-int i2c_himax_read_command(struct i2c_client *client, uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry)
+int i2c_himax_read_command(struct i2c_client *client,
+uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry)
 {
 	int retry;
 	struct i2c_msg msg[] = {
@@ -215,7 +230,7 @@
 		.buf = data,
 		}
 	};
-
+	mutex_lock(&private_ts->rw_lock);
 	for (retry = 0; retry < toRetry; retry++) {
 		if (i2c_transfer(client->adapter, msg, 1) == 1)
 			break;
@@ -224,17 +239,21 @@
 	if (retry == toRetry) {
 		E("%s: i2c_read_block retry over %d\n",
 		       __func__, toRetry);
+		mutex_unlock(&private_ts->rw_lock);
 		return -EIO;
 	}
+	mutex_unlock(&private_ts->rw_lock);
 	return 0;
 }
 
-int i2c_himax_write_command(struct i2c_client *client, uint8_t command, uint8_t toRetry)
+int i2c_himax_write_command(struct i2c_client *client,
+uint8_t command, uint8_t toRetry)
 {
 	return i2c_himax_write(client, command, NULL, 0, toRetry);
 }
 
-int i2c_himax_master_write(struct i2c_client *client, uint8_t *data, uint8_t length, uint8_t toRetry)
+int i2c_himax_master_write(struct i2c_client *client,
+uint8_t *data, uint8_t length, uint8_t toRetry)
 {
 	int retry/*, loop_i*/;
 	uint8_t buf[length];
@@ -249,7 +268,7 @@
 	};
 
 	memcpy(buf, data, length);
-	
+	mutex_lock(&private_ts->rw_lock);
 	for (retry = 0; retry < toRetry; retry++) {
 		if (i2c_transfer(client->adapter, msg, 1) == 1)
 			break;
@@ -259,8 +278,10 @@
 	if (retry == toRetry) {
 		E("%s: i2c_write_block retry over %d\n",
 		       __func__, toRetry);
+		mutex_unlock(&private_ts->rw_lock);
 		return -EIO;
 	}
+	mutex_unlock(&private_ts->rw_lock);
 	return 0;
 }
 
@@ -287,62 +308,51 @@
 }
 
 #if defined(CONFIG_HMX_DB)
-static int himax_regulator_configure(struct i2c_client *client,struct himax_i2c_platform_data *pdata)
+static int himax_regulator_configure(struct i2c_client *client,
+struct himax_i2c_platform_data *pdata)
 {
-    int retval;
-    pdata->vcc_dig = regulator_get(&client->dev,
-                                   "vdd");
-    if (IS_ERR(pdata->vcc_dig))
-    {
-        E("%s: Failed to get regulator vdd\n",
-          __func__);
-        retval = PTR_ERR(pdata->vcc_dig);
-        return retval;
-    }
-    pdata->vcc_ana = regulator_get(&client->dev,
-                                   "avdd");
-    if (IS_ERR(pdata->vcc_ana))
-    {
-        E("%s: Failed to get regulator avdd\n",
-          __func__);
-        retval = PTR_ERR(pdata->vcc_ana);
-        regulator_put(pdata->vcc_ana);
-        return retval;
-    }
+	int retval;
 
-    return 0;
+	pdata->vcc_dig = regulator_get(&client->dev, "vdd");
+	if (IS_ERR(pdata->vcc_dig)) {
+		E("%s: Failed to get regulator vdd\n", __func__);
+		retval = PTR_ERR(pdata->vcc_dig);
+		return retval;
+	}
+	pdata->vcc_ana = regulator_get(&client->dev, "avdd");
+	if (IS_ERR(pdata->vcc_ana)) {
+		E("%s: Failed to get regulator avdd\n", __func__);
+		retval = PTR_ERR(pdata->vcc_ana);
+		regulator_put(pdata->vcc_ana);
+		return retval;
+	}
+
+	return 0;
 };
 
-static int himax_power_on(struct himax_i2c_platform_data *pdata, bool on)
+static int himax_power_on(struct himax_i2c_platform_data *pdata,
+bool on)
 {
-    int retval;
+	int retval;
 
-    if (on)
-    {
-        retval = regulator_enable(pdata->vcc_dig);
-        if (retval)
-        {
-            E("%s: Failed to enable regulator vdd\n",
-              __func__);
-            return retval;
-        }
-        msleep(100);
-        retval = regulator_enable(pdata->vcc_ana);
-        if (retval)
-        {
-            E("%s: Failed to enable regulator avdd\n",
-              __func__);
-            regulator_disable(pdata->vcc_dig);
-            return retval;
-        }
-    }
-    else
-    {
-        regulator_disable(pdata->vcc_dig);
-        regulator_disable(pdata->vcc_ana);
-    }
-
-    return 0;
+	if (on) {
+		retval = regulator_enable(pdata->vcc_dig);
+		if (retval) {
+			E("%s: Failed to enable regulator vdd\n", __func__);
+			return retval;
+		}
+		msleep(100);
+		retval = regulator_enable(pdata->vcc_ana);
+		if (retval) {
+			E("%s: Failed to enable regulator avdd\n", __func__);
+			regulator_disable(pdata->vcc_dig);
+			return retval;
+		}
+	} else {
+		regulator_disable(pdata->vcc_dig);
+		regulator_disable(pdata->vcc_ana);
+	}
+	return 0;
 }
 
 int himax_ts_pinctrl_init(struct himax_ts_data *ts)
@@ -353,41 +363,35 @@
 	ts->ts_pinctrl = devm_pinctrl_get(&(ts->client->dev));
 	if (IS_ERR_OR_NULL(ts->ts_pinctrl)) {
 		retval = PTR_ERR(ts->ts_pinctrl);
-		dev_dbg(&ts->client->dev,
-			"Target does not use pinctrl %d\n", retval);
+		dev_dbg(&ts->client->dev, "Target does not use pinctrl %d\n",
+		retval);
 		goto err_pinctrl_get;
 	}
 
-	ts->pinctrl_state_active
-		= pinctrl_lookup_state(ts->ts_pinctrl,
-				PINCTRL_STATE_ACTIVE);
+	ts->pinctrl_state_active = pinctrl_lookup_state(ts->ts_pinctrl,
+						PINCTRL_STATE_ACTIVE);
 	if (IS_ERR_OR_NULL(ts->pinctrl_state_active)) {
 		retval = PTR_ERR(ts->pinctrl_state_active);
-		dev_err(&ts->client->dev,
-			"Can not lookup %s pinstate %d\n",
-			PINCTRL_STATE_ACTIVE, retval);
+		dev_err(&ts->client->dev, "Can not lookup %s pinstate %d\n",
+		PINCTRL_STATE_ACTIVE, retval);
 		goto err_pinctrl_lookup;
 	}
 
-	ts->pinctrl_state_suspend
-		= pinctrl_lookup_state(ts->ts_pinctrl,
-			PINCTRL_STATE_SUSPEND);
+	ts->pinctrl_state_suspend = pinctrl_lookup_state(ts->ts_pinctrl,
+						PINCTRL_STATE_SUSPEND);
 	if (IS_ERR_OR_NULL(ts->pinctrl_state_suspend)) {
 		retval = PTR_ERR(ts->pinctrl_state_suspend);
-		dev_err(&ts->client->dev,
-			"Can not lookup %s pinstate %d\n",
-			PINCTRL_STATE_SUSPEND, retval);
+		dev_err(&ts->client->dev, "Can not lookup %s pinstate %d\n",
+		PINCTRL_STATE_SUSPEND, retval);
 		goto err_pinctrl_lookup;
 	}
 
-	ts->pinctrl_state_release
-		= pinctrl_lookup_state(ts->ts_pinctrl,
-			PINCTRL_STATE_RELEASE);
+	ts->pinctrl_state_release = pinctrl_lookup_state(ts->ts_pinctrl,
+						PINCTRL_STATE_RELEASE);
 	if (IS_ERR_OR_NULL(ts->pinctrl_state_release)) {
 		retval = PTR_ERR(ts->pinctrl_state_release);
-		dev_dbg(&ts->client->dev,
-			"Can not lookup %s pinstate %d\n",
-			PINCTRL_STATE_RELEASE, retval);
+		dev_dbg(&ts->client->dev, "Can not lookup %s pinstate %d\n",
+		PINCTRL_STATE_RELEASE, retval);
 	}
 
 	return 0;
@@ -399,187 +403,163 @@
 	return retval;
 }
 
-int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata)
+int himax_gpio_power_config(struct i2c_client *client,
+struct himax_i2c_platform_data *pdata)
 {
-    int error;
+	int error;
 
-    error = himax_regulator_configure(client, pdata);
-    if (error)
-    {
-        E("Failed to intialize hardware\n");
-        goto err_regulator_not_on;
-    }
+	error = himax_regulator_configure(client, pdata);
+	if (error) {
+		E("Failed to initialize hardware\n");
+		goto err_regulator_not_on;
+	}
 
 #ifdef HX_RST_PIN_FUNC
-    if (gpio_is_valid(pdata->gpio_reset))
-    {
-        /* configure touchscreen reset out gpio */
-        error = gpio_request(pdata->gpio_reset, "hmx_reset_gpio");
-        if (error)
-        {
-            E("unable to request gpio [%d]\n",
-              pdata->gpio_reset);
-            goto err_regulator_on;
-        }
-
-        error = gpio_direction_output(pdata->gpio_reset, 0);
-        if (error)
-        {
-            E("unable to set direction for gpio [%d]\n",
-              pdata->gpio_reset);
-            goto err_gpio_reset_req;
-        }
-    }
+	if (gpio_is_valid(pdata->gpio_reset)) {
+		/* configure touchscreen reset out gpio */
+		error = gpio_request(pdata->gpio_reset, "hmx_reset_gpio");
+		if (error) {
+			E("unable to request gpio [%d]\n",
+			pdata->gpio_reset);
+			goto err_regulator_on;
+		}
+		error = gpio_direction_output(pdata->gpio_reset, 0);
+		if (error) {
+			E("unable to set direction for gpio [%d]\n",
+			pdata->gpio_reset);
+			goto err_gpio_reset_req;
+		}
+	}
 #endif
 
-    error = himax_power_on(pdata, true);
-    if (error)
-    {
-        E("Failed to power on hardware\n");
-        goto err_gpio_reset_req;
-    }
+	error = himax_power_on(pdata, true);
+	if (error) {
+		E("Failed to power on hardware\n");
+		goto err_gpio_reset_req;
+	}
 #ifdef HX_IRQ_PIN_FUNC
-    if (gpio_is_valid(pdata->gpio_irq))
-    {
-        /* configure touchscreen irq gpio */
-        error = gpio_request(pdata->gpio_irq, "hmx_gpio_irq");
-        if (error)
-        {
-            E("unable to request gpio [%d]\n",
-              pdata->gpio_irq);
-            goto err_power_on;
-        }
-        error = gpio_direction_input(pdata->gpio_irq);
-        if (error)
-        {
-            E("unable to set direction for gpio [%d]\n",
-              pdata->gpio_irq);
-            goto err_gpio_irq_req;
-        }
-        client->irq = gpio_to_irq(pdata->gpio_irq);
-    }
-    else
-    {
-        E("irq gpio not provided\n");
-        goto err_power_on;
-    }
+	/* configure touchscreen irq gpio */
+	if (gpio_is_valid(pdata->gpio_irq)) {
+		error = gpio_request(pdata->gpio_irq, "hmx_gpio_irq");
+		if (error) {
+			E("unable to request gpio [%d]\n", pdata->gpio_irq);
+			goto err_power_on;
+		}
+		error = gpio_direction_input(pdata->gpio_irq);
+		if (error) {
+			E("unable to set direction for gpio [%d]\n",
+			pdata->gpio_irq);
+			goto err_gpio_irq_req;
+		}
+		client->irq = gpio_to_irq(pdata->gpio_irq);
+	} else {
+		E("irq gpio not provided\n");
+		goto err_power_on;
+	}
 #endif
-
-    msleep(20);
+	msleep(20);
 
 #ifdef HX_RST_PIN_FUNC
-    if (gpio_is_valid(pdata->gpio_reset))
-    {
-        error = gpio_direction_output(pdata->gpio_reset, 1);
-        if (error)
-        {
-            E("unable to set direction for gpio [%d]\n",
-              pdata->gpio_reset);
-            goto err_gpio_irq_req;
-        }
-    }
+	if (gpio_is_valid(pdata->gpio_reset)) {
+		error = gpio_direction_output(pdata->gpio_reset, 1);
+		if (error) {
+			E("unable to set direction for gpio [%d]\n",
+			pdata->gpio_reset);
+			goto err_gpio_irq_req;
+		}
+	}
 #endif
-    return 0;
+	return 0;
 #ifdef HX_RST_PIN_FUNC
-	err_gpio_irq_req:
+err_gpio_irq_req:
 #endif
 #ifdef HX_IRQ_PIN_FUNC
-    if (gpio_is_valid(pdata->gpio_irq))
-        gpio_free(pdata->gpio_irq);
-	err_power_on:
+	if (gpio_is_valid(pdata->gpio_irq))
+		gpio_free(pdata->gpio_irq);
+err_power_on:
 #endif
-    himax_power_on(pdata, false);
-	err_gpio_reset_req:
+	himax_power_on(pdata, false);
+err_gpio_reset_req:
 #ifdef HX_RST_PIN_FUNC
-    if (gpio_is_valid(pdata->gpio_reset))
-        gpio_free(pdata->gpio_reset);
-	err_regulator_on:
+	if (gpio_is_valid(pdata->gpio_reset))
+		gpio_free(pdata->gpio_reset);
+err_regulator_on:
 #endif
-	err_regulator_not_on:
+err_regulator_not_on:
 
-    return error;
+	return error;
 }
 
 #else
-int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata)
+int himax_gpio_power_config(struct i2c_client *client,
+struct himax_i2c_platform_data *pdata)
 {
-		int error=0;
-	
-#ifdef HX_RST_PIN_FUNC
-		if (pdata->gpio_reset >= 0)
-		{
-			error = gpio_request(pdata->gpio_reset, "himax-reset");
-			if (error < 0)
-			{
-				E("%s: request reset pin failed\n", __func__);
-				return error;
-			}
-			error = gpio_direction_output(pdata->gpio_reset, 0);
-			if (error)
-			{
-				E("unable to set direction for gpio [%d]\n",
-				  pdata->gpio_reset);
-				return error;
-			}
-		}
-#endif
-		if (pdata->gpio_3v3_en >= 0)
-		{
-			error = gpio_request(pdata->gpio_3v3_en, "himax-3v3_en");
-			if (error < 0)
-			{
-				E("%s: request 3v3_en pin failed\n", __func__);
-				return error;
-			}
-			gpio_direction_output(pdata->gpio_3v3_en, 1);
-			I("3v3_en pin =%d\n", gpio_get_value(pdata->gpio_3v3_en));
-		}
+	int error = 0;
 
-#ifdef HX_IRQ_PIN_FUNC
-		if (gpio_is_valid(pdata->gpio_irq))
-		{
-			/* configure touchscreen irq gpio */
-			error = gpio_request(pdata->gpio_irq, "himax_gpio_irq");
-			if (error)
-			{
-				E("unable to request gpio [%d]\n",pdata->gpio_irq);
-				return error;
-			}
-			error = gpio_direction_input(pdata->gpio_irq);
-			if (error)
-			{
-				E("unable to set direction for gpio [%d]\n",pdata->gpio_irq);
-				return error;
-			}
-			client->irq = gpio_to_irq(pdata->gpio_irq);
-		}
-		else
-		{
-			E("irq gpio not provided\n");
+#ifdef HX_RST_PIN_FUNC
+	if (pdata->gpio_reset >= 0) {
+		error = gpio_request(pdata->gpio_reset, "himax-reset");
+		if (error < 0) {
+			E("%s: request reset pin failed\n", __func__);
 			return error;
 		}
-#endif
-
-		msleep(20);
-	
-#ifdef HX_RST_PIN_FUNC
-		if (pdata->gpio_reset >= 0)
-		{
-			error = gpio_direction_output(pdata->gpio_reset, 1);
-			if (error)
-			{
-				E("unable to set direction for gpio [%d]\n",
-				  pdata->gpio_reset);
-				return error;
-			}
+		error = gpio_direction_output(pdata->gpio_reset, 0);
+		if (error) {
+			E("unable to set direction for gpio [%d]\n",
+			  pdata->gpio_reset);
+			return error;
 		}
-		msleep(20);
+	}
 #endif
-	
+	if (pdata->gpio_3v3_en >= 0) {
+		error = gpio_request(pdata->gpio_3v3_en, "himax-3v3_en");
+		if (error < 0) {
+			E("%s: request 3v3_en pin failed\n", __func__);
+			return error;
+		}
+		gpio_direction_output(pdata->gpio_3v3_en, 1);
+		I("3v3_en pin =%d\n", gpio_get_value(pdata->gpio_3v3_en));
+	}
+
+#ifdef HX_IRQ_PIN_FUNC
+	if (gpio_is_valid(pdata->gpio_irq)) {
+		/* configure touchscreen irq gpio */
+		error = gpio_request(pdata->gpio_irq, "himax_gpio_irq");
+		if (error) {
+			E("unable to request gpio [%d]\n", pdata->gpio_irq);
+			return error;
+		}
+		error = gpio_direction_input(pdata->gpio_irq);
+		if (error) {
+			E("unable to set direction for gpio [%d]\n",
+			pdata->gpio_irq);
+			return error;
+		}
+		client->irq = gpio_to_irq(pdata->gpio_irq);
+	} else {
+		E("irq gpio not provided\n");
 		return error;
 	}
 #endif
 
+	msleep(20);
+
+#ifdef HX_RST_PIN_FUNC
+	if (pdata->gpio_reset >= 0) {
+		error = gpio_direction_output(pdata->gpio_reset, 1);
+		if (error) {
+			E("unable to set direction for gpio [%d]\n",
+			  pdata->gpio_reset);
+			return error;
+		}
+	}
+	msleep(20);
+#endif
+
+	return error;
+}
+#endif
+
 static void himax_ts_isr_func(struct himax_ts_data *ts)
 {
 	himax_ts_work(ts);
@@ -595,34 +575,40 @@
 
 	if (ts->debug_log_level & BIT(2)) {
 			getnstimeofday(&timeStart);
-			usleep_range(5000, 7000);
-			//I(" Irq start time = %ld.%06ld s\n",
-			//	timeStart.tv_sec, timeStart.tv_nsec/1000);
+			usleep_range(4999, 5000);
+			/*I(" Irq start time = %ld.%06ld s\n",
+			timeStart.tv_sec, timeStart.tv_nsec/1000);*/
 	}
 
 #ifdef HX_SMART_WAKEUP
-	if (atomic_read(&ts->suspend_mode)&&(!FAKE_POWER_KEY_SEND)&&(ts->SMWP_enable)&&(!diag_cmd)) {
-		wake_lock_timeout(&ts->ts_SMWP_wake_lock, TS_WAKE_LOCK_TIMEOUT);
+	if (atomic_read(&ts->suspend_mode)
+		&& (!FAKE_POWER_KEY_SEND)
+		&& (ts->SMWP_enable)
+		&& (!diag_cmd)) {
+		__pm_wakeup_event(&ts->ts_SMWP_wake_lock, TS_WAKE_LOCK_TIMEOUT);
 		msleep(200);
 		himax_wake_check_func();
 		return IRQ_HANDLED;
 	}
 #endif
 	himax_ts_isr_func((struct himax_ts_data *)ptr);
-	if(ts->debug_log_level & BIT(2)) {
-			getnstimeofday(&timeEnd);
-				timeDelta.tv_nsec = (timeEnd.tv_sec*1000000000+timeEnd.tv_nsec)
-				-(timeStart.tv_sec*1000000000+timeStart.tv_nsec);
-			//I("Irq finish time = %ld.%06ld s\n",
-			//	timeEnd.tv_sec, timeEnd.tv_nsec/1000);
-			//I("Touch latency = %ld us\n", timeDelta.tv_nsec/1000);
+	if (ts->debug_log_level & BIT(2)) {
+		getnstimeofday(&timeEnd);
+		timeDelta.tv_nsec
+		= (timeEnd.tv_sec * 1000000000 + timeEnd.tv_nsec)
+		- (timeStart.tv_sec * 1000000000 + timeStart.tv_nsec);
+		/*I("Irq finish time = %ld.%06ld s\n",
+			timeEnd.tv_sec, timeEnd.tv_nsec/1000);
+		I("Touch latency = %ld us\n", timeDelta.tv_nsec/1000);*/
 	}
 	return IRQ_HANDLED;
 }
 
 static void himax_ts_work_func(struct work_struct *work)
 {
-	struct himax_ts_data *ts = container_of(work, struct himax_ts_data, work);
+	struct himax_ts_data *ts =
+	container_of(work, struct himax_ts_data, work);
+
 	himax_ts_work(ts);
 }
 
@@ -634,24 +620,26 @@
 	int ret = 0;
 
 	ts->irq_enabled = 0;
-	//Work functon
+	/*Work functon*/
 	if (client->irq) {/*INT mode*/
 		ts->use_irq = 1;
-		if(ic_data->HX_INT_IS_EDGE)
-			{
-				I("%s edge triiger falling\n ",__func__);
-				ret = request_threaded_irq(client->irq, NULL, himax_ts_thread,IRQF_TRIGGER_FALLING | IRQF_ONESHOT, client->name, ts);
-			}
-		else
-			{
-				I("%s level trigger low\n ",__func__);
-				ret = request_threaded_irq(client->irq, NULL, himax_ts_thread,IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ts);
+		if (ic_data->HX_INT_IS_EDGE) {
+				I("%s edge triiger falling\n ", __func__);
+				ret = request_threaded_irq(client->irq,
+				NULL, himax_ts_thread, IRQF_TRIGGER_FALLING
+				| IRQF_ONESHOT, client->name, ts);
+			} else {
+				I("%s level trigger low\n ", __func__);
+				ret = request_threaded_irq(client->irq,
+				NULL, himax_ts_thread, IRQF_TRIGGER_LOW
+				| IRQF_ONESHOT, client->name, ts);
 			}
 		if (ret == 0) {
 			ts->irq_enabled = 1;
 			irq_enable_count = 1;
 			tp_irq = client->irq;
-			I("%s: irq enabled at qpio: %d\n", __func__, client->irq);
+			I("%s: irq enabled at qpio: %d\n",
+			__func__, client->irq);
 #ifdef HX_SMART_WAKEUP
 			irq_set_irq_wake(client->irq, 1);
 #endif
@@ -662,8 +650,8 @@
 	} else {
 		I("%s: client->irq is empty, use polling mode.\n", __func__);
 	}
-
-	if (!ts->use_irq) {/*if use polling mode need to disable HX_ESD_WORKAROUND function*/
+	/*if use polling mode need to disable HX_ESD_WORKAROUND function*/
+	if (!ts->use_irq) {
 		ts->himax_wq = create_singlethread_workqueue("himax_touch");
 
 		INIT_WORK(&ts->work, himax_ts_work_func);
@@ -680,7 +668,7 @@
 {
 	struct himax_ts_data *ts = dev_get_drvdata(dev);
 
-	I("%s: enter \n", __func__);
+	I("%s: enter\n", __func__);
 
 	himax_chip_common_suspend(ts);
 	return 0;
@@ -690,7 +678,7 @@
 {
 	struct himax_ts_data *ts = dev_get_drvdata(dev);
 
-	I("%s: enter \n", __func__);
+	I("%s: enter\n", __func__);
 
 	himax_chip_common_resume(ts);
 	return 0;
@@ -702,23 +690,28 @@
 {
 	struct fb_event *evdata = data;
 	int *blank;
-	struct himax_ts_data *ts=
-		container_of(self, struct himax_ts_data, fb_notif);
+	struct himax_ts_data *ts
+	= container_of(self, struct himax_ts_data, fb_notif);
+	int ERR = 1;
 
 	I(" %s\n", __func__);
-	if (evdata && evdata->data && event == FB_EVENT_BLANK && ts &&
-			ts->client) {
+	if (evdata && evdata->data && event
+	== FB_EVENT_BLANK && ts && ts->client) {
 		blank = evdata->data;
 
 		mutex_lock(&ts->fb_mutex);
 		switch (*blank) {
 		case FB_BLANK_UNBLANK:
 			if (!ts->probe_done) {
-				himax_ts_init(ts);
-				ts->probe_done = true;
-			} else {
+				if (himax_ts_init(ts) == true) {
+					I("himax_ts_init return OK\n");
+					ts->probe_done = true;
+				} else {
+					I("himax_ts_init return Fail\n");
+					return -ERR;
+				}
+			} else
 				himax_common_resume(&ts->client->dev);
-			}
 		break;
 
 		case FB_BLANK_POWERDOWN:
@@ -748,7 +741,7 @@
 };
 
 #ifdef CONFIG_OF
-static const struct of_device_id himax_match_table[] = {
+static struct of_device_id himax_match_table[] = {
 	{.compatible = "himax,hxcommon" },
 	{},
 };
@@ -770,16 +763,10 @@
 	},
 };
 
-static void __init himax_common_init_async(void *unused, async_cookie_t cookie)
-{
-	I("%s:Enter \n", __func__);
-	i2c_add_driver(&himax_common_driver);
-}
-
 static int __init himax_common_init(void)
 {
 	I("Himax common touch panel driver init\n");
-	async_schedule(himax_common_init_async, NULL);
+	i2c_add_driver(&himax_common_driver);
 	return 0;
 }
 
@@ -792,5 +779,5 @@
 module_exit(himax_common_exit);
 
 MODULE_DESCRIPTION("Himax_common driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
 
diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.h b/drivers/input/touchscreen/hxchipset/himax_platform.h
index 1223685..6871e53 100644
--- a/drivers/input/touchscreen/hxchipset/himax_platform.h
+++ b/drivers/input/touchscreen/hxchipset/himax_platform.h
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
+
 #if defined(CONFIG_HMX_DB)
 #include <linux/regulator/consumer.h>
 #endif
@@ -31,15 +32,11 @@
 #define HIMAX_I2C_RETRY_TIMES 10
 
 #if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG)
-#define D(x...) pr_debug("[HXTP] " x)
-#define I(x...) pr_info("[HXTP] " x)
-#define W(x...) pr_warning("[HXTP][WARNING] " x)
-#define E(x...) pr_err("[HXTP][ERROR] " x)
-#define DIF(x...) \
-do {\
-	if (debug_flag) \
-	pr_debug("[HXTP][DEBUG] " x) \
-} while(0)
+#define D(x...) pr_info("[HXTP][DEBUG] " x)
+#define I(x...) pr_info("[HXTP][INFO] " x)
+#define W(x...) pr_info("[HXTP][WARNING] " x)
+#define E(x...) pr_info("[HXTP][ERROR] " x)
+#define DIF(x...) do { if (debug_flag) pr_info("[HXTP][DEBUG] " x) } while (0)
 #else
 #define D(x...)
 #define I(x...)
@@ -53,24 +50,24 @@
 #define HX_VTG_MIN_UV			2700000
 #define HX_VTG_MAX_UV			3300000
 #define HX_ACTIVE_LOAD_UA		15000
-#define HX_LPM_LOAD_UA 			10
+#define HX_LPM_LOAD_UA			10
 /* Digital voltage @1.8 V */
 #define HX_VTG_DIG_MIN_UV		1800000
 #define HX_VTG_DIG_MAX_UV		1800000
 #define HX_ACTIVE_LOAD_DIG_UA	10000
-#define HX_LPM_LOAD_DIG_UA 		10
+#define HX_LPM_LOAD_DIG_UA		10
 
 #define HX_I2C_VTG_MIN_UV		1800000
 #define HX_I2C_VTG_MAX_UV		1800000
-#define HX_I2C_LOAD_UA 			10000
-#define HX_I2C_LPM_LOAD_UA 		10
+#define HX_I2C_LOAD_UA			10000
+#define HX_I2C_LPM_LOAD_UA		10
 #endif
 
-#define HIMAX_common_NAME 				"himax_tp"
+#define HIMAX_common_NAME				"himax_tp"
 #define HIMAX_I2C_ADDR					0x48
 #define INPUT_DEV_NAME					"himax-touchscreen"
 
-struct himax_i2c_platform_data {	
+struct himax_i2c_platform_data {
 	int abs_x_min;
 	int abs_x_max;
 	int abs_x_fuzz;
@@ -108,28 +105,53 @@
 	int irq_gpio;
 	u32 irq_gpio_flags;
 
-	struct regulator *vcc_ana; //For Dragon Board
-	struct regulator *vcc_dig; //For Dragon Board
-	struct regulator *vcc_i2c; //For Dragon Board
-#endif	
+	struct regulator *vcc_ana; /*For Dragon Board*/
+	struct regulator *vcc_dig; /*For Dragon Board*/
+	struct regulator *vcc_i2c; /*For Dragon Board*/
+#endif
 };
 
 
 extern int irq_enable_count;
-extern int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry);
-extern int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry);
-extern int i2c_himax_write_command(struct i2c_client *client, uint8_t command, uint8_t toRetry);
-extern int i2c_himax_master_write(struct i2c_client *client, uint8_t *data, uint8_t length, uint8_t toRetry);
-extern int i2c_himax_read_command(struct i2c_client *client, uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry);
-extern void himax_int_enable(int irqnum, int enable);
-extern int himax_ts_register_interrupt(struct i2c_client *client);
-extern void himax_rst_gpio_set(int pinnum, uint8_t value);
-extern uint8_t himax_int_gpio_read(int pinnum);
+int i2c_himax_read(struct i2c_client *client,
+	uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry);
 
-extern int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata);
+int i2c_himax_write(struct i2c_client *client,
+	uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry);
+
+int i2c_himax_write_command(struct i2c_client *client,
+	uint8_t command, uint8_t toRetry);
+
+int i2c_himax_master_write(struct i2c_client *client,
+	uint8_t *data, uint8_t length, uint8_t toRetry);
+
+int i2c_himax_read_command(struct i2c_client *client,
+	uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry);
+
+void himax_int_enable(int irqnum, int enable);
+int himax_ts_register_interrupt(struct i2c_client *client);
+void himax_rst_gpio_set(int pinnum, uint8_t value);
+uint8_t himax_int_gpio_read(int pinnum);
+
+int himax_gpio_power_config(struct i2c_client *client,
+	struct himax_i2c_platform_data *pdata);
 
 #if defined(CONFIG_FB)
-extern int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data);
+extern int fb_notifier_callback(struct notifier_block *self,
+	unsigned long event, void *data);
 #endif
+extern struct himax_ts_data *private_ts;
+extern struct himax_ic_data *ic_data;
+extern void himax_ts_work(struct himax_ts_data *ts);
+extern enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer);
+extern int tp_rst_gpio;
+
+#ifdef HX_TP_PROC_DIAG
+extern uint8_t getDiagCommand(void);
+#endif
+
+int himax_parse_dt(struct himax_ts_data *ts,
+		struct himax_i2c_platform_data *pdata);
+int himax_ts_pinctrl_init(struct himax_ts_data *ts);
 
 #endif
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index d52b534..c1a07a5 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -60,7 +60,7 @@
 
 config IOMMU_IO_PGTABLE_FAST
 	bool "Fast ARMv7/v8 Long Descriptor Format"
-	select IOMMU_IO_PGTABLE
+	depends on ARM64_DMA_USE_IOMMU || ARM_DMA_USE_IOMMU
 	help
           Enable support for a subset of the ARM long descriptor pagetable
 	  format.  This allocator achieves fast performance by
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index c3376df..a836169 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -376,6 +376,7 @@
 	u32				mair[2];
 	struct arm_smmu_cfg		*cfg;
 	u32				actlr;
+	bool				has_actlr;
 	u32 				attributes;
 };
 
@@ -1776,7 +1777,8 @@
 	}
 
 	/* ACTLR (implementation defined) */
-	writel_relaxed(cb->actlr, cb_base + ARM_SMMU_CB_ACTLR);
+	if (cb->has_actlr)
+		writel_relaxed(cb->actlr, cb_base + ARM_SMMU_CB_ACTLR);
 
 	/* SCTLR */
 	reg = SCTLR_CFCFG | SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE;
@@ -3775,6 +3777,7 @@
 		ACTLR_QCOM_OSH << ACTLR_QCOM_OSH_SHIFT |
 		ACTLR_QCOM_NSH << ACTLR_QCOM_NSH_SHIFT;
 		cb->actlr = val;
+		cb->has_actlr = true;
 	}
 
 	/* Program implementation defined registers */
@@ -4861,6 +4864,10 @@
 
 	arm_smmu_exit_power_resources(smmu->pwr);
 
+	spin_lock(&arm_smmu_devices_lock);
+	list_del(&smmu->list);
+	spin_unlock(&arm_smmu_devices_lock);
+
 	return 0;
 }
 
@@ -5526,6 +5533,7 @@
 		return;
 
 	cb->actlr = iommudata->actlr;
+	cb->has_actlr = true;
 	/*
 	 * Prefetch only works properly if the start and end of all
 	 * buffers in the page table are aligned to 16 Kb.
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 5b284ab..08fcdbf 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -228,16 +228,21 @@
 	void __iomem *base = gic_data.dist_base;
 	int reg, i;
 
+	bitmap_zero(irqs_restore, MAX_IRQ);
+
 	for (reg = SAVED_ICFGR; reg < NUM_SAVED_GICD_REGS; reg++) {
 		for_each_spi_irq_word(i, reg) {
 			saved_spi_regs_start[reg][i] =
 				read_spi_word_offset(base, reg, i);
+			changed_spi_regs_start[reg][i] = 0;
 		}
 	}
 
-	for (i = 32; i < IRQ_NR_BOUND(gic_data.irq_nr); i++)
+	for (i = 32; i < IRQ_NR_BOUND(gic_data.irq_nr); i++) {
 		gic_data.saved_spi_router[i] =
 			gic_read_irouter(base + GICD_IROUTER + i * 8);
+		gic_data.changed_spi_router[i] = 0;
+	}
 }
 
 static void _gicd_check_reg(enum gicd_save_restore_reg reg)
@@ -336,7 +341,7 @@
 }
 
 #define _gic_v3_dist_restore_isenabler()		\
-		_gic_v3_dist_restore_set_reg(GICD_ISENABLER)
+		_gic_v3_dist_restore_reg(SAVED_IS_ENABLER)
 
 #define _gic_v3_dist_restore_ispending()		\
 		_gic_v3_dist_restore_set_reg(GICD_ISPENDR)
@@ -414,7 +419,7 @@
  *
  * 5. Set pending for the interrupt.
  *
- * 6. Enable interrupt and wait for its completion.
+ * 6. Restore Enable bit of interrupt and wait for its completion.
  *
  */
 void gic_v3_dist_restore(void)
diff --git a/drivers/leds/leds-qpnp-haptics.c b/drivers/leds/leds-qpnp-haptics.c
index 8a850c5..3f97c803 100644
--- a/drivers/leds/leds-qpnp-haptics.c
+++ b/drivers/leds/leds-qpnp-haptics.c
@@ -2515,6 +2515,16 @@
 	return 0;
 }
 
+static void qpnp_haptics_shutdown(struct platform_device *pdev)
+{
+	struct hap_chip *chip = dev_get_drvdata(&pdev->dev);
+
+	cancel_work_sync(&chip->haptics_work);
+
+	/* disable haptics */
+	qpnp_haptics_mod_enable(chip, false);
+}
+
 static const struct dev_pm_ops qpnp_haptics_pm_ops = {
 	.suspend	= qpnp_haptics_suspend,
 };
@@ -2532,6 +2542,7 @@
 	},
 	.probe		= qpnp_haptics_probe,
 	.remove		= qpnp_haptics_remove,
+	.shutdown	= qpnp_haptics_shutdown,
 };
 module_platform_driver(qpnp_haptics_driver);
 
diff --git a/drivers/mailbox/qcom-rpmh-mailbox.c b/drivers/mailbox/qcom-rpmh-mailbox.c
index c81fe52..57329f7 100644
--- a/drivers/mailbox/qcom-rpmh-mailbox.c
+++ b/drivers/mailbox/qcom-rpmh-mailbox.c
@@ -695,9 +695,10 @@
 		}
 		/* sanity check to ensure the seq is same */
 		for (j = 1; j < len; j++) {
-			WARN((tcs->cmd_addr[i + j] != cmd[j].addr),
-				"Message does not match previous sequence.\n");
+			if (tcs->cmd_addr[i + j] != cmd[j].addr) {
+				pr_debug("Message does not match previous sequence.\n");
 				return -EINVAL;
+			}
 		}
 		found = true;
 		break;
@@ -725,12 +726,12 @@
 	do {
 		slot = bitmap_find_next_zero_area(tcs->slots, MAX_TCS_SLOTS,
 						n, msg->num_payload, 0);
-		if (slot == MAX_TCS_SLOTS)
+		if (slot >= MAX_TCS_SLOTS)
 			break;
 		n += tcs->ncpt;
 	} while (slot + msg->num_payload - 1 >= n);
 
-	return (slot != MAX_TCS_SLOTS) ? slot : -ENOMEM;
+	return (slot < MAX_TCS_SLOTS) ? slot : -ENOMEM;
 }
 
 static int tcs_mbox_write(struct mbox_chan *chan, struct tcs_mbox_msg *msg,
@@ -1311,6 +1312,7 @@
 	.driver = {
 		.name = KBUILD_MODNAME,
 		.of_match_table = rsc_drv_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
index 29de315..cddbd83 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_hw_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
@@ -1125,6 +1125,7 @@
 		.name = "msm_cam_cdm",
 		.owner = THIS_MODULE,
 		.of_match_table = msm_cam_hw_cdm_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c
index fa98be2..e4ec08b 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_intf.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
@@ -561,6 +561,7 @@
 	.name = "msm_cam_cdm_intf",
 	.owner = THIS_MODULE,
 	.of_match_table = msm_cam_cdm_intf_dt_match,
+	.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c
index c8b830f..a97a5196 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.c
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.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
@@ -22,6 +22,14 @@
 
 #define CAM_CDM_DWORD 4
 
+#define CAM_CDM_SW_CMD_COUNT    2
+#define CAM_CMD_LENGTH_MASK     0xFFFF
+#define CAM_CDM_COMMAND_OFFSET  24
+#define CAM_CDM_REG_OFFSET_MASK 0x00FFFFFF
+
+#define CAM_CDM_DMI_DATA_HI_OFFSET   8
+#define CAM_CDM_DMI_DATA_LO_OFFSET   12
+
 static unsigned int CDMCmdHeaderSizes[
 	CAM_CDM_CMD_PRIVATE_BASE + CAM_CDM_SW_CMD_COUNT] = {
 	0, /* UNUSED*/
@@ -33,7 +41,7 @@
 	2, /* GenerateIRQ*/
 	3, /* WaitForEvent*/
 	1, /* ChangeBase*/
-	1, /* PERF_CONTINUOUSROL*/
+	1, /* PERF_CONTROL*/
 	3, /* DMI32*/
 	3, /* DMI64*/
 };
@@ -540,3 +548,169 @@
 
 	return ret;
 }
+
+static long cam_cdm_util_dump_dmi_cmd(uint32_t *cmd_buf_addr)
+{
+	long ret = 0;
+
+	ret += CDMCmdHeaderSizes[CAM_CDM_CMD_DMI];
+	CAM_INFO(CAM_CDM, "DMI");
+	return ret;
+}
+
+static long cam_cdm_util_dump_buff_indirect(uint32_t *cmd_buf_addr)
+{
+	long ret = 0;
+
+	ret += CDMCmdHeaderSizes[CAM_CDM_CMD_BUFF_INDIRECT];
+	CAM_INFO(CAM_CDM, "Buff Indirect");
+	return ret;
+}
+
+static long cam_cdm_util_dump_reg_cont_cmd(uint32_t *cmd_buf_addr)
+{
+	long ret = 0;
+	struct cdm_regcontinuous_cmd *p_regcont_cmd;
+	uint32_t *temp_ptr = cmd_buf_addr;
+	int i = 0;
+
+	p_regcont_cmd = (struct cdm_regcontinuous_cmd *)temp_ptr;
+	temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT];
+	ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT];
+
+	CAM_INFO(CAM_CDM, "REG_CONT: COUNT: %u OFFSET: 0x%X",
+		p_regcont_cmd->count, p_regcont_cmd->offset);
+
+	for (i = 0; i < p_regcont_cmd->count; i++) {
+		CAM_INFO(CAM_CDM, "DATA_%d: 0x%X", i,
+			*temp_ptr);
+		temp_ptr++;
+		ret++;
+	}
+
+	return ret;
+}
+
+static long cam_cdm_util_dump_reg_random_cmd(uint32_t *cmd_buf_addr)
+{
+	struct cdm_regrandom_cmd *p_regrand_cmd;
+	uint32_t *temp_ptr = cmd_buf_addr;
+	long ret = 0;
+	int i = 0;
+
+	p_regrand_cmd = (struct cdm_regrandom_cmd *)temp_ptr;
+	temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM];
+	ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM];
+
+	CAM_INFO(CAM_CDM, "REG_RAND: COUNT: %u",
+		p_regrand_cmd->count);
+
+	for (i = 0; i < p_regrand_cmd->count; i++) {
+		CAM_INFO(CAM_CDM, "OFFSET_%d: 0x%X DATA_%d: 0x%X",
+			i, *temp_ptr & CAM_CDM_REG_OFFSET_MASK, i,
+			*(temp_ptr + 1));
+		temp_ptr += 2;
+		ret += 2;
+	}
+
+	return ret;
+}
+
+static long cam_cdm_util_dump_gen_irq_cmd(uint32_t *cmd_buf_addr)
+{
+	long ret = 0;
+
+	ret += CDMCmdHeaderSizes[CAM_CDM_CMD_GEN_IRQ];
+
+	CAM_INFO(CAM_CDM, "GEN_IRQ");
+
+	return ret;
+}
+
+static long cam_cdm_util_dump_wait_event_cmd(uint32_t *cmd_buf_addr)
+{
+	long ret = 0;
+
+	ret += CDMCmdHeaderSizes[CAM_CDM_CMD_WAIT_EVENT];
+
+	CAM_INFO(CAM_CDM, "WAIT_EVENT");
+
+	return ret;
+}
+
+static long cam_cdm_util_dump_change_base_cmd(uint32_t *cmd_buf_addr)
+{
+	long ret = 0;
+	struct cdm_changebase_cmd *p_cbase_cmd;
+	uint32_t *temp_ptr = cmd_buf_addr;
+
+	p_cbase_cmd = (struct cdm_changebase_cmd *)temp_ptr;
+	ret += CDMCmdHeaderSizes[CAM_CDM_CMD_CHANGE_BASE];
+
+	CAM_INFO(CAM_CDM, "CHANGE_BASE: 0x%X",
+		p_cbase_cmd->base);
+
+	return ret;
+}
+
+static long cam_cdm_util_dump_perf_ctrl_cmd(uint32_t *cmd_buf_addr)
+{
+	long ret = 0;
+
+	ret += CDMCmdHeaderSizes[CAM_CDM_CMD_PERF_CTRL];
+
+	CAM_INFO(CAM_CDM, "PERF_CTRL");
+
+	return ret;
+}
+
+void cam_cdm_util_dump_cmd_buf(
+	uint32_t *cmd_buf_start, uint32_t *cmd_buf_end)
+{
+	uint32_t *buf_now = cmd_buf_start;
+	uint32_t cmd = 0;
+
+	if (!cmd_buf_start || !cmd_buf_end) {
+		CAM_INFO(CAM_CDM, "Invalid args");
+		return;
+	}
+
+	do {
+		cmd = *buf_now;
+		cmd = cmd >> CAM_CDM_COMMAND_OFFSET;
+
+		switch (cmd) {
+		case CAM_CDM_CMD_DMI:
+		case CAM_CDM_CMD_DMI_32:
+		case CAM_CDM_CMD_DMI_64:
+			buf_now += cam_cdm_util_dump_dmi_cmd(buf_now);
+			break;
+		case CAM_CDM_CMD_REG_CONT:
+			buf_now += cam_cdm_util_dump_reg_cont_cmd(buf_now);
+			break;
+		case CAM_CDM_CMD_REG_RANDOM:
+			buf_now += cam_cdm_util_dump_reg_random_cmd(buf_now);
+			break;
+		case CAM_CDM_CMD_BUFF_INDIRECT:
+			buf_now += cam_cdm_util_dump_buff_indirect(buf_now);
+			break;
+		case CAM_CDM_CMD_GEN_IRQ:
+			buf_now += cam_cdm_util_dump_gen_irq_cmd(buf_now);
+			break;
+		case CAM_CDM_CMD_WAIT_EVENT:
+			buf_now += cam_cdm_util_dump_wait_event_cmd(buf_now);
+			break;
+		case CAM_CDM_CMD_CHANGE_BASE:
+			buf_now += cam_cdm_util_dump_change_base_cmd(buf_now);
+			break;
+		case CAM_CDM_CMD_PERF_CTRL:
+			buf_now += cam_cdm_util_dump_perf_ctrl_cmd(buf_now);
+			break;
+		default:
+			CAM_INFO(CAM_CDM, "Invalid CMD: 0x%x buf 0x%x",
+				cmd, *buf_now);
+			buf_now++;
+			break;
+		}
+	} while (buf_now <= cmd_buf_end);
+}
diff --git a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.h b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.h
index 09d0d63..8f2b488 100644
--- a/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_util.h
+++ b/drivers/media/platform/msm/camera/cam_cdm/cam_cdm_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
@@ -13,13 +13,6 @@
 #ifndef _CAM_CDM_UTIL_H_
 #define _CAM_CDM_UTIL_H_
 
-#define CAM_CDM_SW_CMD_COUNT    2
-#define CAM_CMD_LENGTH_MASK     0xFFFF
-#define CAM_CDM_COMMAND_OFFSET  24
-
-#define CAM_CDM_DMI_DATA_HI_OFFSET   8
-#define CAM_CDM_DMI_DATA_LO_OFFSET   12
-
 enum cam_cdm_command {
 	CAM_CDM_CMD_UNUSED = 0x0,
 	CAM_CDM_CMD_DMI = 0x1,
@@ -158,4 +151,18 @@
 	uint32_t  userdata);
 };
 
+/**
+ * cam_cdm_util_log_cmd_bufs()
+ *
+ * @brief:            Util function to log cdm command buffers
+ *
+ * @cmd_buffer_start: Pointer to start of cmd buffer
+ * @cmd_buffer_end:   Pointer to end of cmd buffer
+ *
+ */
+void cam_cdm_util_dump_cmd_buf(
+	uint32_t *cmd_buffer_start, uint32_t *cmd_buffer_end);
+
+
+
 #endif /* _CAM_CDM_UTIL_H_ */
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 f167ef7..fce7fc6 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
@@ -91,10 +91,19 @@
 	 */
 	list_del_init(&req->list);
 	spin_unlock(&ctx->lock);
-	if (!bubble_state)
+	if (!bubble_state) {
 		result = CAM_SYNC_STATE_SIGNALED_SUCCESS;
-	else
+	} else {
+		CAM_DBG(CAM_REQ,
+			"[%s][ctx_id %d] : req[%llu] is done with error",
+			ctx->dev_name, ctx->ctx_id, req->request_id);
+
+		for (j = 0; j < req->num_out_map_entries; j++)
+			CAM_DBG(CAM_REQ, "fence %d signaled with error",
+				req->out_map_entries[j].sync_id);
+
 		result = CAM_SYNC_STATE_SIGNALED_ERROR;
+	}
 
 	for (j = 0; j < req->num_out_map_entries; j++) {
 		cam_sync_signal(req->out_map_entries[j].sync_id, result);
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
index 90603de..2120650 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
@@ -594,11 +594,8 @@
 		CAM_DBG(CAM_CPAS, "Setting camnoc axi clk rate : %llu %d",
 			required_camnoc_bw, clk_rate);
 
-		rc = cam_soc_util_set_clk_rate(
-			soc_info->clk[soc_info->src_clk_idx],
-			soc_info->clk_name[soc_info->src_clk_idx],
-			clk_rate);
-		if (!rc)
+		rc = cam_soc_util_set_src_clk_rate(soc_info, clk_rate);
+		if (rc)
 			CAM_ERR(CAM_CPAS,
 				"Failed in setting camnoc axi clk %llu %d %d",
 				required_camnoc_bw, clk_rate, rc);
@@ -736,7 +733,7 @@
 		goto unlock_client;
 	}
 
-	CAM_DBG(CAM_CPAS,
+	CAM_DBG(CAM_PERF,
 		"Client=[%d][%s][%d] Requested compressed[%llu], uncompressed[%llu]",
 		client_indx, cpas_client->data.identifier,
 		cpas_client->data.cell_index, axi_vote.compressed_bw,
@@ -898,7 +895,7 @@
 		goto unlock_client;
 	}
 
-	CAM_DBG(CAM_CPAS,
+	CAM_DBG(CAM_PERF,
 		"client=[%d][%s][%d] : type[%d], level[%d], freq[%ld], applied[%d]",
 		client_indx, cpas_client->data.identifier,
 		cpas_client->data.cell_index, ahb_vote.type,
@@ -1212,17 +1209,26 @@
 
 	rc = cam_common_util_get_string_index(soc_private->client_name,
 		soc_private->num_clients, client_name, &client_indx);
+
+	mutex_lock(&cpas_core->client_mutex[client_indx]);
+
 	if (rc || !CAM_CPAS_CLIENT_VALID(client_indx) ||
 		CAM_CPAS_CLIENT_REGISTERED(cpas_core, client_indx)) {
-		CAM_ERR(CAM_CPAS, "Invalid Client register : %s %d, %d",
+		CAM_ERR(CAM_CPAS,
+			"Inval client %s %d : %d %d %pK %d",
 			register_params->identifier,
-			register_params->cell_index, client_indx);
+			register_params->cell_index,
+			CAM_CPAS_CLIENT_VALID(client_indx),
+			CAM_CPAS_CLIENT_REGISTERED(cpas_core, client_indx),
+			cpas_core->cpas_client[client_indx], rc);
+		mutex_unlock(&cpas_core->client_mutex[client_indx]);
 		mutex_unlock(&cpas_hw->hw_mutex);
 		return -EPERM;
 	}
 
 	cpas_client = kzalloc(sizeof(struct cam_cpas_client), GFP_KERNEL);
 	if (!cpas_client) {
+		mutex_unlock(&cpas_core->client_mutex[client_indx]);
 		mutex_unlock(&cpas_hw->hw_mutex);
 		return -ENOMEM;
 	}
@@ -1235,6 +1241,7 @@
 			client_indx, cpas_client->data.identifier,
 			cpas_client->data.cell_index, rc);
 		kfree(cpas_client);
+		mutex_unlock(&cpas_core->client_mutex[client_indx]);
 		mutex_unlock(&cpas_hw->hw_mutex);
 		return -EINVAL;
 	}
@@ -1246,12 +1253,13 @@
 	cpas_core->cpas_client[client_indx] = cpas_client;
 	cpas_core->registered_clients++;
 
-	mutex_unlock(&cpas_hw->hw_mutex);
-
 	CAM_DBG(CAM_CPAS, "client=[%d][%s][%d], registered_clients=%d",
 		client_indx, cpas_client->data.identifier,
 		cpas_client->data.cell_index, cpas_core->registered_clients);
 
+	mutex_unlock(&cpas_core->client_mutex[client_indx]);
+	mutex_unlock(&cpas_hw->hw_mutex);
+
 	return 0;
 }
 
@@ -1498,27 +1506,6 @@
 	return rc;
 }
 
-static int cam_cpas_util_get_hw_version(struct platform_device *pdev,
-	struct cam_hw_soc_info *soc_info)
-{
-	struct device_node *of_node = pdev->dev.of_node;
-	int rc;
-
-	soc_info->hw_version = 0;
-
-	rc = of_property_read_u32(of_node,
-		"qcom,cpas-hw-ver", &soc_info->hw_version);
-
-	CAM_DBG(CAM_CPAS, "CPAS HW VERSION %x", soc_info->hw_version);
-
-	if (rc) {
-		CAM_ERR(CAM_CPAS, "failed to get CPAS HW Version rc=%d", rc);
-		return -EINVAL;
-	}
-
-	return rc;
-}
-
 int cam_cpas_hw_probe(struct platform_device *pdev,
 	struct cam_hw_intf **hw_intf)
 {
@@ -1661,10 +1648,6 @@
 	if (rc)
 		goto axi_cleanup;
 
-	rc = cam_cpas_util_get_hw_version(pdev, &cpas_hw->soc_info);
-	if (rc)
-		goto axi_cleanup;
-
 	*hw_intf = cpas_hw_intf;
 	return 0;
 
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c
index 0187a64..cdc8a3b 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_intf.c
@@ -619,6 +619,7 @@
 	}
 
 	mutex_lock(&g_cpas_intf->intf_lock);
+	g_cpas_intf->probe_done = false;
 	cam_unregister_subdev(&g_cpas_intf->subdev);
 	cam_cpas_hw_remove(g_cpas_intf->hw_intf);
 	mutex_unlock(&g_cpas_intf->intf_lock);
@@ -641,6 +642,7 @@
 		.name = CAM_CPAS_DEV_NAME,
 		.owner = THIS_MODULE,
 		.of_match_table = cam_cpas_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
index b73b32a..83cd326 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
@@ -44,18 +44,6 @@
 		return rc;
 	}
 
-
-	soc_private->hw_version = 0;
-	rc = of_property_read_u32(of_node,
-		"qcom,cpas-hw-ver", &soc_private->hw_version);
-	if (rc) {
-		CAM_ERR(CAM_CPAS, "device %s failed to read cpas-hw-ver",
-			pdev->name);
-		return rc;
-	}
-
-	CAM_DBG(CAM_CPAS, "CPAS HW VERSION %x", soc_private->hw_version);
-
 	soc_private->camnoc_axi_min_ib_bw = 0;
 	rc = of_property_read_u64(of_node,
 		"camnoc-axi-min-ib-bw",
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h
index f6ae8a8..7f50d12 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h
@@ -33,7 +33,6 @@
  * struct cam_cpas_private_soc : CPAS private DT info
  *
  * @arch_compat: ARCH compatible string
- * @hw_version: Camera HW version
  * @client_id_based: Whether clients are id based
  * @num_clients: Number of clients supported
  * @client_name: Client names
@@ -53,7 +52,6 @@
  */
 struct cam_cpas_private_soc {
 	const char *arch_compat;
-	uint32_t hw_version;
 	bool client_id_based;
 	uint32_t num_clients;
 	const char *client_name[CAM_CPAS_MAX_CLIENTS];
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 158bbb9..f8687cf 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
@@ -76,6 +76,38 @@
 		hw_caps->cpas_version.major, hw_caps->cpas_version.minor,
 		hw_caps->cpas_version.incr, hw_caps->camera_capability);
 
+	soc_info->hw_version = CAM_CPAS_TITAN_NONE;
+
+	if ((hw_caps->camera_version.major == 1) &&
+		(hw_caps->camera_version.minor == 7) &&
+		(hw_caps->camera_version.incr == 0)) {
+		if ((hw_caps->cpas_version.major == 1) &&
+			(hw_caps->cpas_version.minor == 0) &&
+			(hw_caps->cpas_version.incr == 0))
+			soc_info->hw_version = CAM_CPAS_TITAN_170_V100;
+		else if ((hw_caps->cpas_version.major == 1) &&
+			(hw_caps->cpas_version.minor == 1) &&
+			(hw_caps->cpas_version.incr == 0))
+			soc_info->hw_version = CAM_CPAS_TITAN_170_V110;
+		else if ((hw_caps->cpas_version.major == 1) &&
+			(hw_caps->cpas_version.minor == 2) &&
+			(hw_caps->cpas_version.incr == 0))
+			soc_info->hw_version = CAM_CPAS_TITAN_170_V120;
+	} else if ((hw_caps->camera_version.major == 1) &&
+		(hw_caps->camera_version.minor == 7) &&
+		(hw_caps->camera_version.incr == 5)) {
+		if ((hw_caps->cpas_version.major == 1) &&
+			(hw_caps->cpas_version.minor == 0) &&
+			(hw_caps->cpas_version.incr == 0))
+			soc_info->hw_version = CAM_CPAS_TITAN_175_V100;
+		else if ((hw_caps->cpas_version.major == 1) &&
+			(hw_caps->cpas_version.minor == 0) &&
+			(hw_caps->cpas_version.incr == 1))
+			soc_info->hw_version = CAM_CPAS_TITAN_175_V101;
+	}
+
+	CAM_DBG(CAM_CPAS, "CPAS HW VERSION %x", soc_info->hw_version);
+
 	return 0;
 }
 
@@ -583,12 +615,11 @@
 	struct cam_cpas_hw_caps *hw_caps)
 {
 	int rc = 0;
-	struct cam_cpas_private_soc *soc_private =
-		(struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
+	struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
 
 	CAM_DBG(CAM_CPAS,
 		"hw_version=0x%x Camera Version %d.%d.%d, cpas version %d.%d.%d",
-		soc_private->hw_version,
+		soc_info->hw_version,
 		hw_caps->camera_version.major,
 		hw_caps->camera_version.minor,
 		hw_caps->camera_version.incr,
@@ -596,7 +627,7 @@
 		hw_caps->cpas_version.minor,
 		hw_caps->cpas_version.incr);
 
-	switch (soc_private->hw_version) {
+	switch (soc_info->hw_version) {
 	case CAM_CPAS_TITAN_170_V100:
 		camnoc_info = &cam170_cpas100_camnoc_info;
 		break;
diff --git a/drivers/media/platform/msm/camera/cam_fd/cam_fd_dev.c b/drivers/media/platform/msm/camera/cam_fd/cam_fd_dev.c
index 3f01244..d5068ca 100644
--- a/drivers/media/platform/msm/camera/cam_fd/cam_fd_dev.c
+++ b/drivers/media/platform/msm/camera/cam_fd/cam_fd_dev.c
@@ -194,6 +194,7 @@
 		.name = "cam_fd",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_fd_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
index a15ccdc..d3c39f9 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1884,7 +1884,7 @@
 	}
 
 	rc = cam_req_mgr_workq_create("cam_fd_worker", CAM_FD_WORKQ_NUM_TASK,
-		&g_fd_hw_mgr.work, CRM_WORKQ_USAGE_IRQ);
+		&g_fd_hw_mgr.work, CRM_WORKQ_USAGE_IRQ, 0);
 	if (rc) {
 		CAM_ERR(CAM_FD, "Unable to create a worker, rc=%d", rc);
 		goto detach_smmu;
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
index a18afc6..87dc694 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
@@ -532,7 +532,7 @@
 
 	if (!fd_hw) {
 		CAM_ERR(CAM_FD, "Invalid data in IRQ callback");
-		return -EINVAL;
+		return IRQ_NONE;
 	}
 
 	fd_core = (struct cam_fd_core *) fd_hw->core_info;
@@ -570,7 +570,7 @@
 		CAM_ERR(CAM_FD,
 			"Invalid number of IRQs, value=0x%x, num_irqs=%d",
 			reg_value, num_irqs);
-		return -EINVAL;
+		return IRQ_NONE;
 	}
 
 	trace_cam_irq_activated("FD", irq_type);
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
index 6d9d330..c7ef37c 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
@@ -24,6 +24,8 @@
 #include "cam_fd_hw_v41.h"
 #include "cam_fd_hw_v501.h"
 
+static char fd_dev_name[8];
+
 static int cam_fd_hw_dev_probe(struct platform_device *pdev)
 {
 	struct cam_hw_info *fd_hw;
@@ -32,6 +34,7 @@
 	const struct of_device_id *match_dev = NULL;
 	struct cam_fd_hw_static_info *hw_static_info = NULL;
 	int rc = 0;
+	uint32_t hw_idx;
 	struct cam_fd_hw_init_args init_args;
 	struct cam_fd_hw_deinit_args deinit_args;
 
@@ -51,14 +54,21 @@
 		kfree(fd_hw_intf);
 		return -ENOMEM;
 	}
+	of_property_read_u32(pdev->dev.of_node,
+			"cell-index", &hw_idx);
 
 	fd_hw_intf->hw_priv = fd_hw;
 	fd_hw->core_info = fd_core;
+	fd_hw_intf->hw_idx = hw_idx;
+
+	memset(fd_dev_name, 0, sizeof(fd_dev_name));
+	snprintf(fd_dev_name, sizeof(fd_dev_name),
+		"fd%1u", fd_hw_intf->hw_idx);
 
 	fd_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
 	fd_hw->soc_info.pdev = pdev;
 	fd_hw->soc_info.dev = &pdev->dev;
-	fd_hw->soc_info.dev_name = pdev->name;
+	fd_hw->soc_info.dev_name = fd_dev_name;
 	fd_hw->open_count = 0;
 	mutex_init(&fd_hw->hw_mutex);
 	spin_lock_init(&fd_hw->hw_lock);
@@ -104,8 +114,6 @@
 		goto free_memory;
 	}
 
-	fd_hw_intf->hw_idx = fd_hw->soc_info.index;
-
 	memset(&init_args, 0x0, sizeof(init_args));
 	memset(&deinit_args, 0x0, sizeof(deinit_args));
 	rc = cam_fd_hw_init(fd_hw, &init_args, sizeof(init_args));
@@ -209,6 +217,7 @@
 		.name = "cam_fd_hw",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_fd_hw_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c b/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c
index 4f91f73..7df806b 100644
--- a/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c
+++ b/drivers/media/platform/msm/camera/cam_icp/cam_icp_subdev.c
@@ -236,6 +236,7 @@
 		.name = "cam_icp",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_icp_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
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 2c364e01..3e636c6 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
@@ -35,6 +35,7 @@
  * @cmd_q: command queue hfi memory for host to firmware communication
  * @msg_q: message queue hfi memory for firmware to host communication
  * @dbg_q: debug queue hfi memory for firmware debug information
+ * @sfr_buf: buffer for subsystem failure reason[SFR]
  * @sec_heap: secondary heap hfi memory for firmware
  * @qdss: qdss mapped memory for fw
  * @icp_base: icp base address
@@ -44,6 +45,7 @@
 	struct hfi_mem cmd_q;
 	struct hfi_mem msg_q;
 	struct hfi_mem dbg_q;
+	struct hfi_mem sfr_buf;
 	struct hfi_mem sec_heap;
 	struct hfi_mem shmem;
 	struct hfi_mem qdss;
@@ -153,4 +155,10 @@
 int cam_hfi_resume(struct hfi_mem_info *hfi_mem,
 	void __iomem *icp_base, bool debug);
 
+/**
+ * cam_hfi_queue_dump() - utility function to dump hfi queues
+ */
+void cam_hfi_queue_dump(void);
+
+
 #endif /* _HFI_INTF_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h
index 2153cea..f652cfa 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_reg.h
@@ -43,6 +43,7 @@
 #define HFI_REG_UNCACHED_HEAP_SIZE              0x60
 #define HFI_REG_QDSS_IOVA                       0x6C
 #define HFI_REG_QDSS_IOVA_SIZE                  0x70
+#define HFI_REG_SFR_PTR                         0x68
 /* end of ICP CSR registers */
 
 /* flags for ICP CSR registers */
@@ -72,6 +73,7 @@
 #define ICP_CMD_Q_SIZE_IN_BYTES                 4096
 #define ICP_MSG_Q_SIZE_IN_BYTES                 4096
 #define ICP_DBG_Q_SIZE_IN_BYTES                 102400
+#define ICP_MSG_SFR_SIZE_IN_BYTES               4096
 
 #define ICP_SHARED_MEM_IN_BYTES                 (1024 * 1024)
 #define ICP_UNCACHED_HEAP_SIZE_IN_BYTES         (2 * 1024 * 1024)
@@ -128,10 +130,14 @@
 /**
  * @INTR_DISABLE: Disable interrupt
  * @INTR_ENABLE: Enable interrupt
+ * @INTR_ENABLE_WD0: Enable WD0
+ * @INTR_ENABLE_WD1: Enable WD1
  */
 enum intr_status {
 	INTR_DISABLE,
-	INTR_ENABLE
+	INTR_ENABLE,
+	INTR_ENABLE_WD0,
+	INTR_ENABLE_WD1 = 0x4
 };
 
 /**
@@ -286,6 +292,16 @@
 };
 
 /**
+ * struct sfr_buf
+ * @size: Number of characters
+ * @msg : Subsystem failure reason
+ */
+struct sfr_buf {
+	uint32_t size;
+	char msg[ICP_MSG_SFR_SIZE_IN_BYTES];
+};
+
+/**
  * struct hfi_q_tbl
  * @q_tbl_hdr: Queue table header
  * @q_hdr: Queue header info, it holds info of cmd, msg and debug queues
diff --git a/drivers/media/platform/msm/camera/cam_icp/hfi.c b/drivers/media/platform/msm/camera/cam_icp/hfi.c
index a0752f5..14a3e65 100644
--- a/drivers/media/platform/msm/camera/cam_icp/hfi.c
+++ b/drivers/media/platform/msm/camera/cam_icp/hfi.c
@@ -47,6 +47,49 @@
 static DEFINE_MUTEX(hfi_cmd_q_mutex);
 static DEFINE_MUTEX(hfi_msg_q_mutex);
 
+void cam_hfi_queue_dump(void)
+{
+	struct hfi_qtbl *qtbl;
+	struct hfi_qtbl_hdr *qtbl_hdr;
+	struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr;
+	struct hfi_mem_info *hfi_mem = NULL;
+	uint32_t *read_q, *read_ptr;
+	int i;
+
+	hfi_mem = &g_hfi->map;
+	if (!hfi_mem) {
+		CAM_ERR(CAM_HFI, "Unable to dump queues hfi memory is NULL");
+		return;
+	}
+
+	qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva;
+	qtbl_hdr = &qtbl->q_tbl_hdr;
+	CAM_INFO(CAM_HFI,
+		"qtbl: version = %x size = %u num q = %u qhdr_size = %u",
+		qtbl_hdr->qtbl_version, qtbl_hdr->qtbl_size,
+		qtbl_hdr->qtbl_num_q, qtbl_hdr->qtbl_qhdr_size);
+
+	cmd_q_hdr = &qtbl->q_hdr[Q_CMD];
+	CAM_INFO(CAM_HFI, "cmd: size = %u r_idx = %u w_idx = %u addr = %x",
+		cmd_q_hdr->qhdr_q_size, cmd_q_hdr->qhdr_read_idx,
+		cmd_q_hdr->qhdr_write_idx, hfi_mem->cmd_q.iova);
+	read_q = (uint32_t *)g_hfi->map.cmd_q.kva;
+	read_ptr = (uint32_t *)(read_q + 0);
+	CAM_INFO(CAM_HFI, "CMD Q START");
+	for (i = 0; i < ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; i++)
+		CAM_INFO(CAM_HFI, "Word: %d Data: 0x%08x ", i, read_ptr[i]);
+
+	msg_q_hdr = &qtbl->q_hdr[Q_MSG];
+	CAM_INFO(CAM_HFI, "msg: size = %u r_idx = %u w_idx = %u addr = %x",
+		msg_q_hdr->qhdr_q_size, msg_q_hdr->qhdr_read_idx,
+		msg_q_hdr->qhdr_write_idx, hfi_mem->msg_q.iova);
+	read_q = (uint32_t *)g_hfi->map.msg_q.kva;
+	read_ptr = (uint32_t *)(read_q + 0);
+	CAM_INFO(CAM_HFI, "MSG Q START");
+	for (i = 0; i < ICP_MSG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT; i++)
+		CAM_INFO(CAM_HFI, "Word: %d Data: 0x%08x ", i, read_ptr[i]);
+}
+
 int hfi_write_cmd(void *cmd_ptr)
 {
 	uint32_t size_in_words, empty_space, new_write_idx, read_idx, temp;
@@ -92,7 +135,8 @@
 		(q->qhdr_q_size - (q->qhdr_write_idx - read_idx)) :
 		(read_idx - q->qhdr_write_idx);
 	if (empty_space <= size_in_words) {
-		CAM_ERR(CAM_HFI, "failed");
+		CAM_ERR(CAM_HFI, "failed: empty space %u, size_in_words %u",
+			empty_space, size_in_words);
 		rc = -EIO;
 		goto err;
 	}
@@ -556,7 +600,7 @@
 		return -EINVAL;
 	}
 
-	cam_io_w_mb((uint32_t)INTR_ENABLE,
+	cam_io_w_mb((uint32_t)(INTR_ENABLE|INTR_ENABLE_WD0),
 		icp_base + HFI_REG_A5_CSR_A2HOSTINTEN);
 
 	fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION);
@@ -566,6 +610,8 @@
 	CAM_DBG(CAM_HFI, "wfi status = %x", (int)data);
 
 	cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR);
+	cam_io_w_mb((uint32_t)hfi_mem->sfr_buf.iova,
+		icp_base + HFI_REG_SFR_PTR);
 	cam_io_w_mb((uint32_t)hfi_mem->shmem.iova,
 		icp_base + HFI_REG_SHARED_MEM_PTR);
 	cam_io_w_mb((uint32_t)hfi_mem->shmem.len,
@@ -591,6 +637,7 @@
 	struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr;
 	uint32_t hw_version, soc_version, fw_version, status = 0;
 	uint32_t retry_cnt = 0;
+	struct sfr_buf *sfr_buffer;
 
 	mutex_lock(&hfi_cmd_q_mutex);
 	mutex_lock(&hfi_msg_q_mutex);
@@ -672,6 +719,9 @@
 	dbg_q_hdr->qhdr_read_idx = RESET;
 	dbg_q_hdr->qhdr_write_idx = RESET;
 
+	sfr_buffer = (struct sfr_buf *)hfi_mem->sfr_buf.kva;
+	sfr_buffer->size = ICP_MSG_SFR_SIZE_IN_BYTES;
+
 	switch (event_driven_mode) {
 	case INTR_MODE:
 		cmd_q_hdr->qhdr_type = Q_CMD;
@@ -744,7 +794,10 @@
 		break;
 	}
 
-	cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR);
+	cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova,
+		icp_base + HFI_REG_QTBL_PTR);
+	cam_io_w_mb((uint32_t)hfi_mem->sfr_buf.iova,
+		icp_base + HFI_REG_SFR_PTR);
 	cam_io_w_mb((uint32_t)hfi_mem->shmem.iova,
 		icp_base + HFI_REG_SHARED_MEM_PTR);
 	cam_io_w_mb((uint32_t)hfi_mem->shmem.len,
@@ -801,7 +854,7 @@
 	g_hfi->hfi_state = HFI_READY;
 	g_hfi->cmd_q_state = true;
 	g_hfi->msg_q_state = true;
-	cam_io_w_mb((uint32_t)INTR_ENABLE,
+	cam_io_w_mb((uint32_t)(INTR_ENABLE|INTR_ENABLE_WD0),
 		icp_base + HFI_REG_A5_CSR_A2HOSTINTEN);
 
 	mutex_unlock(&hfi_cmd_q_mutex);
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.h
index 4aa6b4b..f4bc813 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -25,8 +25,8 @@
 #define A5_CSR_BASE             2
 
 #define A5_HOST_INT             0x1
-#define A5_WDT_0                0x10
-#define A5_WDT_1                0x100
+#define A5_WDT_0                0x2
+#define A5_WDT_1                0x4
 
 #define ELF_GUARD_PAGE          (2 * 1024 * 1024)
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_dev.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_dev.c
index 14c3c9c..3b652e7 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_dev.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_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
@@ -215,6 +215,7 @@
 		.name = "cam-a5",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_a5_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c
index 5bd7f1c..d016374 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_core.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_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
@@ -18,6 +18,7 @@
 #include <linux/firmware.h>
 #include <linux/delay.h>
 #include <linux/timer.h>
+#include <linux/iopoll.h>
 #include "cam_io_util.h"
 #include "cam_hw.h"
 #include "cam_hw_intf.h"
@@ -30,6 +31,9 @@
 #include "cam_icp_hw_mgr_intf.h"
 #include "cam_cpas_api.h"
 #include "cam_debug_util.h"
+#include "hfi_reg.h"
+
+#define HFI_MAX_POLL_TRY 5
 
 static int cam_bps_cpas_vote(struct cam_bps_device_core_info *core_info,
 			struct cam_icp_cpas_vote *cpas_vote)
@@ -210,6 +214,77 @@
 	return rc;
 }
 
+static int cam_bps_cmd_reset(struct cam_hw_soc_info *soc_info,
+	struct cam_bps_device_core_info *core_info)
+{
+	uint32_t retry_cnt = 0;
+	uint32_t status = 0;
+	int pwr_ctrl, pwr_status, rc = 0;
+	bool reset_bps_cdm_fail = false;
+	bool reset_bps_top_fail = false;
+
+	CAM_DBG(CAM_ICP, "CAM_ICP_BPS_CMD_RESET");
+	/* Reset BPS CDM core*/
+	cam_io_w_mb((uint32_t)0xF,
+		soc_info->reg_map[0].mem_base + BPS_CDM_RST_CMD);
+	while (retry_cnt < HFI_MAX_POLL_TRY) {
+		readw_poll_timeout((soc_info->reg_map[0].mem_base +
+			BPS_CDM_IRQ_STATUS),
+			status, ((status & BPS_RST_DONE_IRQ_STATUS_BIT) == 0x1),
+			100, 10000);
+
+		CAM_DBG(CAM_ICP, "bps_cdm_irq_status = %u", status);
+
+		if ((status & BPS_RST_DONE_IRQ_STATUS_BIT) == 0x1)
+			break;
+		retry_cnt++;
+	}
+	status = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+		BPS_CDM_IRQ_STATUS);
+	if ((status & BPS_RST_DONE_IRQ_STATUS_BIT) != 0x1) {
+		CAM_ERR(CAM_ICP, "BPS CDM rst failed status 0x%x", status);
+		reset_bps_cdm_fail = true;
+	}
+
+	/* Reset BPS core*/
+	status = 0;
+	cam_io_w_mb((uint32_t)0x3,
+		soc_info->reg_map[0].mem_base + BPS_TOP_RST_CMD);
+	while (retry_cnt < HFI_MAX_POLL_TRY) {
+		readw_poll_timeout((soc_info->reg_map[0].mem_base +
+			BPS_TOP_IRQ_STATUS),
+			status, ((status & BPS_RST_DONE_IRQ_STATUS_BIT) == 0x1),
+			100, 10000);
+
+		CAM_DBG(CAM_ICP, "bps_top_irq_status = %u", status);
+
+		if ((status & BPS_RST_DONE_IRQ_STATUS_BIT) == 0x1)
+			break;
+		retry_cnt++;
+	}
+	status = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+		BPS_TOP_IRQ_STATUS);
+	if ((status & BPS_RST_DONE_IRQ_STATUS_BIT) != 0x1) {
+		CAM_ERR(CAM_ICP, "BPS top rst failed status 0x%x", status);
+		reset_bps_top_fail = true;
+	}
+
+	cam_bps_get_gdsc_control(soc_info);
+	cam_cpas_reg_read(core_info->cpas_handle,
+		CAM_CPAS_REG_CPASTOP, core_info->bps_hw_info->pwr_ctrl,
+		true, &pwr_ctrl);
+	cam_cpas_reg_read(core_info->cpas_handle,
+		CAM_CPAS_REG_CPASTOP, core_info->bps_hw_info->pwr_status,
+		true, &pwr_status);
+	CAM_DBG(CAM_ICP, "(After) pwr_ctrl = %x pwr_status = %x",
+		pwr_ctrl, pwr_status);
+
+	if (reset_bps_cdm_fail || reset_bps_top_fail)
+		rc = -EAGAIN;
+
+	return rc;
+}
+
 int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type,
 	void *cmd_args, uint32_t arg_size)
 {
@@ -311,7 +386,12 @@
 			cam_bps_toggle_clk(soc_info, false);
 		core_info->clk_enable = false;
 		break;
+	case CAM_ICP_BPS_CMD_RESET:
+		rc = cam_bps_cmd_reset(soc_info, core_info);
+		break;
 	default:
+		CAM_ERR(CAM_ICP, "Invalid Cmd Type:%u", cmd_type);
+		rc = -EINVAL;
 		break;
 	}
 	return rc;
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_dev.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_dev.c
index feb0bd8..56abb4b 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_dev.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_dev.c
@@ -33,6 +33,8 @@
 };
 EXPORT_SYMBOL(cam_bps_hw_info);
 
+static char bps_dev_name[8];
+
 static bool cam_bps_cpas_cb(uint32_t client_handle, void *userdata,
 	struct cam_cpas_irq_data *irq_data)
 {
@@ -111,9 +113,14 @@
 		kfree(bps_dev_intf);
 		return -ENOMEM;
 	}
+
+	memset(bps_dev_name, 0, sizeof(bps_dev_name));
+	snprintf(bps_dev_name, sizeof(bps_dev_name),
+		"bps%1u", bps_dev_intf->hw_idx);
+
 	bps_dev->soc_info.pdev = pdev;
 	bps_dev->soc_info.dev = &pdev->dev;
-	bps_dev->soc_info.dev_name = pdev->name;
+	bps_dev->soc_info.dev_name = bps_dev_name;
 	bps_dev_intf->hw_priv = bps_dev;
 	bps_dev_intf->hw_ops.init = cam_bps_init_hw;
 	bps_dev_intf->hw_ops.deinit = cam_bps_deinit_hw;
@@ -187,6 +194,7 @@
 		.name = "cam-bps",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_bps_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c
index d2314c4..1da99a4 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/bps_hw/bps_soc.c
@@ -154,8 +154,7 @@
 		clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx];
 	}
 
-	return cam_soc_util_set_clk_rate(soc_info->clk[soc_info->src_clk_idx],
-		soc_info->clk_name[soc_info->src_clk_idx], clk_rate);
+	return cam_soc_util_set_src_clk_rate(soc_info, clk_rate);
 }
 
 int cam_bps_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_enable)
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 16e97ea..d32d4b6 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
@@ -995,6 +995,8 @@
 		id = CAM_ICP_IPE_CMD_UPDATE_CLK;
 	}
 
+	CAM_DBG(CAM_PERF, "clk_rate %u for dev_type %d", curr_clk_rate,
+		ctx_data->icp_dev_acquire_info->dev_type);
 	clk_upd_cmd.curr_clk_rate = curr_clk_rate;
 	clk_upd_cmd.ipe_bps_pc_enable = icp_hw_mgr.ipe_bps_pc_flag;
 
@@ -1058,6 +1060,10 @@
 	 * anyway.
 	 */
 
+	CAM_DBG(CAM_ICP, "compress_bw %llu uncompress_bw %llu dev_type %d",
+		clk_info->compressed_bw, clk_info->uncompressed_bw,
+		ctx_data->icp_dev_acquire_info->dev_type);
+
 	return 0;
 }
 
@@ -1179,7 +1185,7 @@
 		if (hw_mgr->bps_ctxt_cnt)
 			goto end;
 
-		if (icp_hw_mgr.ipe_bps_pc_flag) {
+		if (icp_hw_mgr.ipe_bps_pc_flag && !hw_mgr->recovery) {
 			rc = bps_dev_intf->hw_ops.process_cmd(
 				bps_dev_intf->hw_priv,
 				CAM_ICP_BPS_CMD_POWER_COLLAPSE,
@@ -1201,11 +1207,10 @@
 		if (hw_mgr->ipe_ctxt_cnt)
 			goto end;
 
-		if (icp_hw_mgr.ipe_bps_pc_flag) {
+		if (icp_hw_mgr.ipe_bps_pc_flag && !hw_mgr->recovery) {
 			rc = ipe0_dev_intf->hw_ops.process_cmd(
 				ipe0_dev_intf->hw_priv,
 				CAM_ICP_IPE_CMD_POWER_COLLAPSE, NULL, 0);
-
 		}
 
 		if (hw_mgr->ipe_clk_state)
@@ -1213,7 +1218,7 @@
 				ipe0_dev_intf->hw_priv, NULL, 0);
 
 		if (ipe1_dev_intf) {
-			if (icp_hw_mgr.ipe_bps_pc_flag) {
+			if (icp_hw_mgr.ipe_bps_pc_flag && !hw_mgr->recovery) {
 				rc = ipe1_dev_intf->hw_ops.process_cmd(
 					ipe1_dev_intf->hw_priv,
 					CAM_ICP_IPE_CMD_POWER_COLLAPSE,
@@ -1226,7 +1231,7 @@
 		}
 
 		hw_mgr->ipe_clk_state = false;
-		if (icp_hw_mgr.ipe_bps_pc_flag) {
+		if (icp_hw_mgr.ipe_bps_pc_flag && !hw_mgr->recovery) {
 			hw_mgr->core_info = hw_mgr->core_info &
 				(~(ICP_PWR_CLP_IPE0 | ICP_PWR_CLP_IPE1));
 		}
@@ -1317,7 +1322,6 @@
 		rc = -ENOMEM;
 		goto err;
 	}
-	icp_hw_mgr.icp_pc_flag = false;
 
 	if (!debugfs_create_bool("ipe_bps_pc",
 		0644,
@@ -1328,8 +1332,6 @@
 		goto err;
 	}
 
-	icp_hw_mgr.ipe_bps_pc_flag = false;
-
 	if (!debugfs_create_file("icp_debug_clk",
 		0644,
 		icp_hw_mgr.dentry, NULL,
@@ -1377,6 +1379,7 @@
 	return rc;
 err:
 	debugfs_remove_recursive(icp_hw_mgr.dentry);
+	icp_hw_mgr.dentry = NULL;
 	return rc;
 }
 
@@ -1456,8 +1459,10 @@
 		CAM_ERR(CAM_ICP, "Invalid Context");
 		return -EINVAL;
 	}
-	CAM_DBG(CAM_ICP, "ctx : %pK, request_id :%lld",
-		(void *)ctx_data->context_priv, request_id);
+	CAM_DBG(CAM_REQ,
+		"ctx_id : %u, request_id :%lld dev_type: %d",
+		ctx_data->ctx_id, request_id,
+		ctx_data->icp_dev_acquire_info->dev_type);
 
 	mutex_lock(&ctx_data->ctx_mutex);
 	cam_icp_ctx_timer_reset(ctx_data);
@@ -1718,11 +1723,121 @@
 	return rc;
 }
 
+static int cam_icp_ipebps_reset(struct cam_icp_hw_mgr *hw_mgr)
+{
+	int rc = 0;
+	struct cam_hw_intf *ipe0_dev_intf;
+	struct cam_hw_intf *ipe1_dev_intf;
+	struct cam_hw_intf *bps_dev_intf;
+
+	ipe0_dev_intf = hw_mgr->ipe0_dev_intf;
+	ipe1_dev_intf = hw_mgr->ipe1_dev_intf;
+	bps_dev_intf = hw_mgr->bps_dev_intf;
+
+	rc = bps_dev_intf->hw_ops.process_cmd(
+		bps_dev_intf->hw_priv,
+		CAM_ICP_BPS_CMD_RESET,
+		NULL, 0);
+	if (rc)
+		CAM_ERR(CAM_ICP, "bps reset failed");
+
+	rc = ipe0_dev_intf->hw_ops.process_cmd(
+		ipe0_dev_intf->hw_priv,
+		CAM_ICP_IPE_CMD_RESET,
+		NULL, 0);
+	if (rc)
+		CAM_ERR(CAM_ICP, "ipe0 reset failed");
+
+	if (ipe1_dev_intf) {
+		rc = ipe1_dev_intf->hw_ops.process_cmd(
+			ipe1_dev_intf->hw_priv,
+			CAM_ICP_IPE_CMD_RESET,
+			NULL, 0);
+		if (rc)
+			CAM_ERR(CAM_ICP, "ipe1 reset failed");
+	}
+
+	return 0;
+}
+
+static int cam_icp_mgr_trigger_recovery(struct cam_icp_hw_mgr *hw_mgr)
+{
+	int rc = 0;
+	int i = 0;
+	struct sfr_buf *sfr_buffer = NULL;
+
+	CAM_DBG(CAM_ICP, "Enter");
+
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+	if (hw_mgr->recovery) {
+		CAM_ERR(CAM_ICP, "Recovery is set");
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		return rc;
+	}
+
+	sfr_buffer = (struct sfr_buf *)icp_hw_mgr.hfi_mem.sfr_buf.kva;
+	CAM_WARN(CAM_ICP, "SFR:%s", sfr_buffer->msg);
+
+	cam_icp_ipebps_reset(hw_mgr);
+
+	hw_mgr->recovery = true;
+
+	if (hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog) {
+		hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog_reset_counter = 0;
+		crm_timer_exit(&hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog);
+		hw_mgr->clk_info[ICP_CLK_HW_BPS].watch_dog = NULL;
+	}
+	if (hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog) {
+		hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog_reset_counter = 0;
+		crm_timer_exit(&hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog);
+		hw_mgr->clk_info[ICP_CLK_HW_IPE].watch_dog = NULL;
+	}
+
+	for (i = 0; i < CAM_ICP_CTX_MAX; i++) {
+		mutex_lock(&hw_mgr->ctx_data[i].ctx_mutex);
+		if (hw_mgr->ctx_data[i].state != CAM_ICP_CTX_STATE_RELEASE)
+			cam_icp_ctx_timer_stop(&hw_mgr->ctx_data[i]);
+		mutex_unlock(&hw_mgr->ctx_data[i].ctx_mutex);
+	}
+
+	mutex_unlock(&hw_mgr->hw_mgr_mutex);
+
+	CAM_DBG(CAM_ICP, "Done");
+	return rc;
+}
+static int cam_icp_mgr_process_fatal_error(
+	struct cam_icp_hw_mgr *hw_mgr, uint32_t *msg_ptr)
+{
+	struct hfi_msg_event_notify *event_notify;
+	int rc = 0;
+
+	CAM_DBG(CAM_ICP, "Enter");
+
+	event_notify = (struct hfi_msg_event_notify *)msg_ptr;
+	if (!event_notify) {
+		CAM_ERR(CAM_ICP, "Empty event message");
+		return -EINVAL;
+	}
+
+	CAM_DBG(CAM_ICP, "evt_id: %u evt_data1: %u evt_data2: %u",
+		event_notify->event_id,
+		event_notify->event_data1,
+		event_notify->event_data2);
+
+	if (event_notify->event_id == HFI_EVENT_SYS_ERROR) {
+		CAM_INFO(CAM_ICP, "received HFI_EVENT_SYS_ERROR");
+		rc = cam_icp_mgr_trigger_recovery(hw_mgr);
+	}
+
+	return rc;
+}
+
 static void cam_icp_mgr_process_dbg_buf(void)
 {
 	uint32_t *msg_ptr = NULL, *pkt_ptr = NULL;
 	struct hfi_msg_debug *dbg_msg;
 	uint32_t read_len, size_processed = 0;
+	uint64_t timestamp = 0;
 	char *dbg_buf;
 	int rc = 0;
 
@@ -1736,7 +1851,9 @@
 		if (pkt_ptr[ICP_PACKET_TYPE] == HFI_MSG_SYS_DEBUG) {
 			dbg_msg = (struct hfi_msg_debug *)pkt_ptr;
 			dbg_buf = (char *)&dbg_msg->msg_data;
-			trace_cam_icp_fw_dbg(dbg_buf);
+			timestamp = ((((uint64_t)(dbg_msg->timestamp_hi) << 32)
+				| dbg_msg->timestamp_lo) >> 16);
+			trace_cam_icp_fw_dbg(dbg_buf, timestamp/2);
 		}
 		size_processed += (pkt_ptr[ICP_PACKET_SIZE] >>
 			BYTE_WORD_SHIFT);
@@ -1802,6 +1919,10 @@
 		CAM_DBG(CAM_ICP, "received EVENT_NOTIFY");
 		size_processed = (
 			(struct hfi_msg_event_notify *)msg_ptr)->size;
+		rc = cam_icp_mgr_process_fatal_error(hw_mgr, msg_ptr);
+		if (rc)
+			CAM_ERR(CAM_ICP, "failed in processing evt notify");
+
 		break;
 
 	default:
@@ -1833,7 +1954,7 @@
 
 	rc = hfi_read_message(icp_hw_mgr.msg_buf, Q_MSG, &read_len);
 	if (rc) {
-		CAM_DBG(CAM_ICP, "Unable to read msg q");
+		CAM_DBG(CAM_ICP, "Unable to read msg q rc %d", rc);
 	} else {
 		read_len = read_len << BYTE_WORD_SHIFT;
 		msg_ptr = (uint32_t *)icp_hw_mgr.msg_buf;
@@ -1862,6 +1983,13 @@
 		HFI_DEBUG_MODE_QUEUE)
 		cam_icp_mgr_process_dbg_buf();
 
+	if ((task_data->irq_status & A5_WDT_0) ||
+		(task_data->irq_status & A5_WDT_1)) {
+		CAM_ERR_RATE_LIMIT(CAM_ICP, "watch dog interrupt from A5");
+
+		rc = cam_icp_mgr_trigger_recovery(hw_mgr);
+	}
+
 	return rc;
 }
 
@@ -1906,6 +2034,7 @@
 	cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.cmd_q);
 	cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.msg_q);
 	cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.dbg_q);
+	cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.sfr_buf);
 }
 
 static int cam_icp_alloc_secheap_mem(struct cam_mem_mgr_memory_desc *secheap)
@@ -1945,6 +2074,31 @@
 	return rc;
 }
 
+static int cam_icp_alloc_sfr_mem(struct cam_mem_mgr_memory_desc *sfr)
+{
+	int rc;
+	struct cam_mem_mgr_request_desc alloc;
+	struct cam_mem_mgr_memory_desc out;
+
+	memset(&alloc, 0, sizeof(alloc));
+	memset(&out, 0, sizeof(out));
+	alloc.size = SZ_8K;
+	alloc.align = 0;
+	alloc.flags = CAM_MEM_FLAG_HW_READ_WRITE |
+		CAM_MEM_FLAG_HW_SHARED_ACCESS;
+
+	alloc.smmu_hdl = icp_hw_mgr.iommu_hdl;
+	rc = cam_mem_mgr_request_mem(&alloc, &out);
+	if (rc)
+		return rc;
+
+	*sfr = out;
+	CAM_DBG(CAM_ICP, "kva: %llX, iova: %x, hdl: %x, len: %lld",
+		out.kva, out.iova, out.mem_handle, out.len);
+
+	return rc;
+}
+
 static int cam_icp_alloc_shared_mem(struct cam_mem_mgr_memory_desc *qtbl)
 {
 	int rc;
@@ -2060,6 +2214,12 @@
 		goto dbg_q_alloc_failed;
 	}
 
+	rc = cam_icp_alloc_sfr_mem(&icp_hw_mgr.hfi_mem.sfr_buf);
+	if (rc) {
+		CAM_ERR(CAM_ICP, "Unable to allocate sfr buffer");
+		goto sfr_buf_alloc_failed;
+	}
+
 	rc = cam_icp_alloc_secheap_mem(&icp_hw_mgr.hfi_mem.sec_heap);
 	if (rc) {
 		CAM_ERR(CAM_ICP, "Unable to allocate sec heap memory");
@@ -2068,6 +2228,8 @@
 
 	return rc;
 sec_heap_alloc_failed:
+	cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.sfr_buf);
+sfr_buf_alloc_failed:
 	cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.dbg_q);
 dbg_q_alloc_failed:
 	cam_mem_mgr_release_mem(&icp_hw_mgr.hfi_mem.msg_q);
@@ -2172,6 +2334,7 @@
 	struct cam_icp_hw_mgr *hw_mgr = hw_priv;
 	int rc = 0;
 
+	CAM_DBG(CAM_ICP, "UMD calls close");
 	if (!hw_mgr) {
 		CAM_ERR(CAM_ICP, "Null hw mgr");
 		return 0;
@@ -2188,6 +2351,7 @@
 {
 	struct cam_icp_hw_mgr *hw_mgr = hw_priv;
 
+	CAM_DBG(CAM_ICP, "KMD calls close");
 	if (!hw_mgr) {
 		CAM_ERR(CAM_ICP, "Null hw mgr");
 		return 0;
@@ -2212,11 +2376,12 @@
 	}
 	a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv;
 
-	if (!hw_mgr->icp_pc_flag) {
+	if (!hw_mgr->icp_pc_flag || hw_mgr->recovery) {
 		cam_hfi_disable_cpu(
 			a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base);
 		rc = cam_icp_mgr_hw_close_k(hw_mgr, NULL);
 	} else {
+		CAM_DBG(CAM_PERF, "Sending PC prep ICP PC enabled");
 		rc = cam_icp_mgr_send_pc_prep(hw_mgr);
 		cam_hfi_disable_cpu(
 			a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base);
@@ -2243,27 +2408,34 @@
 	hfi_mem.qtbl.kva = icp_hw_mgr.hfi_mem.qtbl.kva;
 	hfi_mem.qtbl.iova = icp_hw_mgr.hfi_mem.qtbl.iova;
 	hfi_mem.qtbl.len = icp_hw_mgr.hfi_mem.qtbl.len;
-	 CAM_DBG(CAM_ICP, "kva = %llX IOVA = %X length = %lld\n",
+	 CAM_DBG(CAM_ICP, "qtbl kva = %llX IOVA = %X length = %lld\n",
 		hfi_mem.qtbl.kva, hfi_mem.qtbl.iova, hfi_mem.qtbl.len);
 
 	hfi_mem.cmd_q.kva = icp_hw_mgr.hfi_mem.cmd_q.kva;
 	hfi_mem.cmd_q.iova = icp_hw_mgr.hfi_mem.cmd_q.iova;
 	hfi_mem.cmd_q.len = icp_hw_mgr.hfi_mem.cmd_q.len;
-	CAM_DBG(CAM_ICP, "kva = %llX IOVA = %X length = %lld\n",
+	CAM_DBG(CAM_ICP, "cmd_q kva = %llX IOVA = %X length = %lld\n",
 		hfi_mem.cmd_q.kva, hfi_mem.cmd_q.iova, hfi_mem.cmd_q.len);
 
 	hfi_mem.msg_q.kva = icp_hw_mgr.hfi_mem.msg_q.kva;
 	hfi_mem.msg_q.iova = icp_hw_mgr.hfi_mem.msg_q.iova;
 	hfi_mem.msg_q.len = icp_hw_mgr.hfi_mem.msg_q.len;
-	CAM_DBG(CAM_ICP, "kva = %llX IOVA = %X length = %lld\n",
+	CAM_DBG(CAM_ICP, "msg_q kva = %llX IOVA = %X length = %lld\n",
 		hfi_mem.msg_q.kva, hfi_mem.msg_q.iova, hfi_mem.msg_q.len);
 
 	hfi_mem.dbg_q.kva = icp_hw_mgr.hfi_mem.dbg_q.kva;
 	hfi_mem.dbg_q.iova = icp_hw_mgr.hfi_mem.dbg_q.iova;
 	hfi_mem.dbg_q.len = icp_hw_mgr.hfi_mem.dbg_q.len;
-	CAM_DBG(CAM_ICP, "kva = %llX IOVA = %X length = %lld\n",
+	CAM_DBG(CAM_ICP, "dbg_q kva = %llX IOVA = %X length = %lld\n",
 		hfi_mem.dbg_q.kva, hfi_mem.dbg_q.iova, hfi_mem.dbg_q.len);
 
+	hfi_mem.sfr_buf.kva = icp_hw_mgr.hfi_mem.sfr_buf.kva;
+	hfi_mem.sfr_buf.iova = icp_hw_mgr.hfi_mem.sfr_buf.iova;
+	hfi_mem.sfr_buf.len = icp_hw_mgr.hfi_mem.sfr_buf.len;
+	CAM_DBG(CAM_ICP, "sfr kva = %llX IOVA = %X length = %lld\n",
+		hfi_mem.sfr_buf.kva, hfi_mem.sfr_buf.iova,
+		hfi_mem.sfr_buf.len);
+
 	hfi_mem.sec_heap.kva = icp_hw_mgr.hfi_mem.sec_heap.kva;
 	hfi_mem.sec_heap.iova = icp_hw_mgr.hfi_mem.sec_heap.iova;
 	hfi_mem.sec_heap.len = icp_hw_mgr.hfi_mem.sec_heap.len;
@@ -2323,6 +2495,7 @@
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW timeout/err in abort handle command");
+		cam_hfi_queue_dump();
 	}
 
 	kfree(abort_cmd);
@@ -2379,6 +2552,7 @@
 		if (icp_hw_mgr.a5_debug_type ==
 			HFI_DEBUG_MODE_QUEUE)
 			cam_icp_mgr_process_dbg_buf();
+		cam_hfi_queue_dump();
 	}
 	kfree(destroy_cmd);
 	return rc;
@@ -2405,7 +2579,8 @@
 	cam_icp_mgr_ipe_bps_power_collapse(hw_mgr,
 		&hw_mgr->ctx_data[ctx_id], 0);
 	hw_mgr->ctx_data[ctx_id].state = CAM_ICP_CTX_STATE_RELEASE;
-	CAM_DBG(CAM_ICP, "E: ctx_id = %d", ctx_id);
+	CAM_DBG(CAM_ICP, "E: ctx_id = %d recovery = %d",
+		ctx_id, hw_mgr->recovery);
 	cam_icp_mgr_abort_handle(&hw_mgr->ctx_data[ctx_id]);
 	cam_icp_mgr_destroy_handle(&hw_mgr->ctx_data[ctx_id]);
 	cam_icp_mgr_cleanup_ctx(&hw_mgr->ctx_data[ctx_id]);
@@ -2638,6 +2813,10 @@
 	hfi_mem.dbg_q.iova = icp_hw_mgr.hfi_mem.dbg_q.iova;
 	hfi_mem.dbg_q.len = icp_hw_mgr.hfi_mem.dbg_q.len;
 
+	hfi_mem.sfr_buf.kva = icp_hw_mgr.hfi_mem.sfr_buf.kva;
+	hfi_mem.sfr_buf.iova = icp_hw_mgr.hfi_mem.sfr_buf.iova;
+	hfi_mem.sfr_buf.len = icp_hw_mgr.hfi_mem.sfr_buf.len;
+
 	hfi_mem.sec_heap.kva = icp_hw_mgr.hfi_mem.sec_heap.kva;
 	hfi_mem.sec_heap.iova = icp_hw_mgr.hfi_mem.sec_heap.iova;
 	hfi_mem.sec_heap.len = icp_hw_mgr.hfi_mem.sec_heap.len;
@@ -2680,6 +2859,7 @@
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+		cam_hfi_queue_dump();
 	}
 	CAM_DBG(CAM_ICP, "Done Waiting for INIT DONE Message");
 
@@ -2797,6 +2977,7 @@
 
 	hw_mgr->ctxt_cnt = 0;
 	hw_mgr->fw_download = true;
+	hw_mgr->recovery = false;
 
 	CAM_INFO(CAM_ICP, "FW download done successfully");
 
@@ -2858,8 +3039,10 @@
 	struct hfi_cmd_work_data *task_data;
 	struct hfi_cmd_ipebps_async *hfi_cmd;
 	struct cam_hw_update_entry *hw_update_entries;
+	struct icp_frame_info *frame_info = NULL;
 
-	request_id = *(uint64_t *)config_args->priv;
+	frame_info = (struct icp_frame_info *)config_args->priv;
+	request_id = frame_info->request_id;
 	hw_update_entries = config_args->hw_update_entries;
 	CAM_DBG(CAM_ICP, "req_id = %lld %pK", request_id, config_args->priv);
 
@@ -2881,6 +3064,82 @@
 	return rc;
 }
 
+static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data,
+	uint32_t io_buf_addr)
+{
+	int rc = 0;
+	struct hfi_cmd_work_data *task_data;
+	struct hfi_cmd_ipebps_async ioconfig_cmd;
+	unsigned long rem_jiffies;
+	int timeout = 5000;
+	struct crm_workq_task *task;
+	uint32_t size_in_words;
+
+	task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
+	if (!task)
+		return -ENOMEM;
+
+	ioconfig_cmd.size = sizeof(struct hfi_cmd_ipebps_async);
+	ioconfig_cmd.pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT;
+	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS)
+		ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO;
+	else
+		ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO;
+
+	reinit_completion(&ctx_data->wait_complete);
+
+	ioconfig_cmd.num_fw_handles = 1;
+	ioconfig_cmd.fw_handles[0] = ctx_data->fw_handle;
+	ioconfig_cmd.payload.indirect = io_buf_addr;
+	ioconfig_cmd.user_data1 = (uint64_t)ctx_data;
+	ioconfig_cmd.user_data2 = (uint64_t)0x0;
+	task_data = (struct hfi_cmd_work_data *)task->payload;
+	task_data->data = (void *)&ioconfig_cmd;
+	task_data->request_id = 0;
+	task_data->type = ICP_WORKQ_TASK_MSG_TYPE;
+	task->process_cb = cam_icp_mgr_process_cmd;
+	size_in_words = (*(uint32_t *)task_data->data) >> 2;
+	CAM_INFO(CAM_ICP, "size_in_words %u", size_in_words);
+	rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
+		CRM_TASK_PRIORITY_0);
+	if (rc)
+		return rc;
+
+	rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete,
+		msecs_to_jiffies((timeout)));
+	if (!rem_jiffies) {
+		rc = -ETIMEDOUT;
+		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+		cam_hfi_queue_dump();
+	}
+
+	return rc;
+}
+
+static int cam_icp_mgr_send_recfg_io(struct cam_icp_hw_ctx_data *ctx_data,
+	struct hfi_cmd_ipebps_async *ioconfig_cmd, uint64_t req_id)
+{
+	int rc = 0;
+	struct hfi_cmd_work_data *task_data;
+	struct crm_workq_task *task;
+
+	task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
+	if (!task)
+		return -ENOMEM;
+
+	task_data = (struct hfi_cmd_work_data *)task->payload;
+	task_data->data = (void *)ioconfig_cmd;
+	task_data->request_id = req_id;
+	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);
+	if (rc)
+		return rc;
+
+	return rc;
+}
+
 static int cam_icp_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
 {
 	int rc = 0;
@@ -2889,6 +3148,7 @@
 	struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv;
 	struct cam_hw_config_args *config_args = config_hw_args;
 	struct cam_icp_hw_ctx_data *ctx_data = NULL;
+	struct icp_frame_info *frame_info = NULL;
 
 	if (!hw_mgr || !config_args) {
 		CAM_ERR(CAM_ICP, "Invalid arguments %pK %pK",
@@ -2912,16 +3172,30 @@
 		return -EINVAL;
 	}
 
-	req_id = *(uint64_t *)config_args->priv;
+	frame_info = (struct icp_frame_info *)config_args->priv;
+	req_id = frame_info->request_id;
 	idx = cam_icp_clk_idx_from_req_id(ctx_data, req_id);
 	ctx_data->hfi_frame_process.fw_process_flag[idx] = true;
 	cam_icp_mgr_ipe_bps_clk_update(hw_mgr, ctx_data, idx);
 
+	CAM_DBG(CAM_ICP, "req_id %llu, io config %llu", req_id,
+		frame_info->io_config);
+
+	if (frame_info->io_config != 0) {
+		CAM_INFO(CAM_ICP, "Send recfg io");
+		rc = cam_icp_mgr_send_recfg_io(ctx_data,
+			&frame_info->hfi_cfg_io_cmd, req_id);
+		if (rc)
+			CAM_ERR(CAM_ICP, "Fail to send reconfig io cmd");
+	}
+
 	rc = cam_icp_mgr_enqueue_config(hw_mgr, config_args);
 	if (rc)
 		goto config_err;
-	CAM_DBG(CAM_ICP, "req_id = %lld %u",
-		req_id, ctx_data->ctx_id);
+	CAM_DBG(CAM_REQ,
+		"req_id = %lld on ctx_id %u for dev %d queued to FW",
+		req_id, ctx_data->ctx_id,
+		ctx_data->icp_dev_acquire_info->dev_type);
 	mutex_unlock(&ctx_data->ctx_mutex);
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 
@@ -3107,8 +3381,11 @@
 				io_cfg_ptr[i].fence;
 			prepare_args->num_out_map_entries++;
 		}
-		CAM_DBG(CAM_ICP, "dir[%d]: %u, fence: %u",
-			i, io_cfg_ptr[i].direction, io_cfg_ptr[i].fence);
+		CAM_DBG(CAM_REQ,
+			"ctx_id: %u req_id: %llu dir[%d]: %u, fence: %u resource_type = %u",
+			ctx_data->ctx_id, packet->header.request_id, i,
+			io_cfg_ptr[i].direction, io_cfg_ptr[i].fence,
+			io_cfg_ptr[i].resource_type);
 	}
 
 	if (prepare_args->num_in_map_entries > 1) {
@@ -3124,7 +3401,9 @@
 			merged_sync_in_obj;
 		prepare_args->in_map_entries[0].sync_id = merged_sync_in_obj;
 		prepare_args->num_in_map_entries = 1;
-		CAM_DBG(CAM_ICP, "Merged Sync obj = %d", merged_sync_in_obj);
+		CAM_DBG(CAM_REQ, "ctx_id: %u req_id: %llu Merged Sync obj: %d",
+			ctx_data->ctx_id, packet->header.request_id,
+			merged_sync_in_obj);
 	} else if (prepare_args->num_in_map_entries == 1) {
 		prepare_args->in_map_entries[0].sync_id = sync_in_obj[0];
 		prepare_args->num_in_map_entries = 1;
@@ -3147,7 +3426,9 @@
 	struct icp_cmd_generic_blob *blob;
 	struct cam_icp_hw_ctx_data *ctx_data;
 	uint32_t index;
+	size_t io_buf_size;
 	int rc = 0;
+	uint64_t pResource;
 
 	if (!blob_data || (blob_size == 0)) {
 		CAM_ERR(CAM_ICP, "Invalid blob info %pK %d", blob_data,
@@ -3176,6 +3457,28 @@
 			clk_info->compressed_bw);
 		break;
 
+	case CAM_ICP_CMD_GENERIC_BLOB_CFG_IO:
+		CAM_DBG(CAM_ICP, "CAM_ICP_CMD_GENERIC_BLOB_CFG_IO");
+		pResource = *((uint32_t *)blob_data);
+		if (copy_from_user(&ctx_data->icp_dev_io_info,
+			(void __user *)pResource,
+			sizeof(struct cam_icp_acquire_dev_info))) {
+			CAM_ERR(CAM_ICP, "Failed in copy from user");
+			return -EFAULT;
+		}
+		CAM_DBG(CAM_ICP, "buf handle %d",
+			ctx_data->icp_dev_io_info.io_config_cmd_handle);
+		rc = cam_mem_get_io_buf(
+			ctx_data->icp_dev_io_info.io_config_cmd_handle,
+			icp_hw_mgr.iommu_hdl,
+			blob->io_buf_addr, &io_buf_size);
+		if (rc)
+			CAM_ERR(CAM_ICP, "Failed in blob update");
+		else
+			CAM_DBG(CAM_ICP, "io buf addr %llu",
+				*blob->io_buf_addr);
+		break;
+
 	default:
 		CAM_WARN(CAM_ICP, "Invalid blob type %d", blob_type);
 		break;
@@ -3186,7 +3489,8 @@
 static int cam_icp_process_generic_cmd_buffer(
 	struct cam_packet *packet,
 	struct cam_icp_hw_ctx_data *ctx_data,
-	int32_t index)
+	int32_t index,
+	uint64_t *io_buf_addr)
 {
 	int i, rc = 0;
 	struct cam_cmd_buf_desc *cmd_desc = NULL;
@@ -3194,6 +3498,7 @@
 
 	cmd_generic_blob.ctx = ctx_data;
 	cmd_generic_blob.frame_info_idx = index;
+	cmd_generic_blob.io_buf_addr = io_buf_addr;
 
 	cmd_desc = (struct cam_cmd_buf_desc *)
 		((uint32_t *) &packet->payload + packet->cmd_buf_offset/4);
@@ -3213,6 +3518,28 @@
 	return rc;
 }
 
+static int cam_icp_mgr_process_cfg_io_cmd(
+	struct cam_icp_hw_ctx_data *ctx_data,
+	struct hfi_cmd_ipebps_async *ioconfig_cmd,
+	uint64_t request_id,
+	uint64_t io_config)
+{
+	ioconfig_cmd->size = sizeof(struct hfi_cmd_ipebps_async);
+	ioconfig_cmd->pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT;
+	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS)
+		ioconfig_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO;
+	else
+		ioconfig_cmd->opcode = HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO;
+
+	ioconfig_cmd->num_fw_handles = 1;
+	ioconfig_cmd->fw_handles[0] = ctx_data->fw_handle;
+	ioconfig_cmd->payload.indirect = io_config;
+	ioconfig_cmd->user_data1 = (uint64_t)ctx_data;
+	ioconfig_cmd->user_data2 = request_id;
+
+	return 0;
+}
+
 static int cam_icp_mgr_update_hfi_frame_process(
 	struct cam_icp_hw_ctx_data *ctx_data,
 	struct cam_packet *packet,
@@ -3220,6 +3547,7 @@
 	int32_t *idx)
 {
 	int32_t index, rc;
+	struct hfi_cmd_ipebps_async *hfi_cmd = NULL;
 
 	index = find_first_zero_bit(ctx_data->hfi_frame_process.bitmap,
 		ctx_data->hfi_frame_process.bits);
@@ -3231,15 +3559,27 @@
 
 	ctx_data->hfi_frame_process.request_id[index] =
 		packet->header.request_id;
-	rc = cam_icp_process_generic_cmd_buffer(packet, ctx_data, index);
+	ctx_data->hfi_frame_process.frame_info[index].request_id =
+		packet->header.request_id;
+	ctx_data->hfi_frame_process.frame_info[index].io_config = 0;
+	rc = cam_icp_process_generic_cmd_buffer(packet, ctx_data, index,
+		&ctx_data->hfi_frame_process.frame_info[index].io_config);
 	if (rc) {
 		clear_bit(index, ctx_data->hfi_frame_process.bitmap);
 		ctx_data->hfi_frame_process.request_id[index] = -1;
 		return rc;
 	}
+
+	if (ctx_data->hfi_frame_process.frame_info[index].io_config)  {
+		hfi_cmd = (struct hfi_cmd_ipebps_async *)&ctx_data->
+			hfi_frame_process.frame_info[index].hfi_cfg_io_cmd;
+		rc = cam_icp_mgr_process_cfg_io_cmd(ctx_data, hfi_cmd,
+			packet->header.request_id, ctx_data->
+			hfi_frame_process.frame_info[index].io_config);
+	}
 	*idx = index;
 
-	return 0;
+	return rc;
 }
 
 static int cam_icp_mgr_prepare_hw_update(void *hw_mgr_priv,
@@ -3284,7 +3624,8 @@
 		return rc;
 	}
 
-	CAM_DBG(CAM_ICP, "E: req id = %lld", packet->header.request_id);
+	CAM_DBG(CAM_REQ, "req id = %lld for ctx = %u",
+		packet->header.request_id, ctx_data->ctx_id);
 	/* Update Buffer Address from handles and patch information */
 	rc = cam_packet_util_process_patches(packet, hw_mgr->iommu_hdl,
 		hw_mgr->iommu_sec_hdl);
@@ -3320,7 +3661,7 @@
 
 	prepare_args->num_hw_update_entries = 1;
 	prepare_args->hw_update_entries[0].addr = (uint64_t)hfi_cmd;
-	prepare_args->priv = &ctx_data->hfi_frame_process.request_id[idx];
+	prepare_args->priv = &ctx_data->hfi_frame_process.frame_info[idx];
 
 	CAM_DBG(CAM_ICP, "X: req id = %lld ctx_id = %u",
 		packet->header.request_id, ctx_data->ctx_id);
@@ -3480,6 +3821,7 @@
 {
 	struct cam_hw_flush_args *flush_args = hw_flush_args;
 	struct cam_icp_hw_ctx_data *ctx_data;
+	struct cam_icp_hw_mgr *hw_mgr = hw_priv;
 
 	if ((!hw_priv) || (!hw_flush_args)) {
 		CAM_ERR(CAM_ICP, "Input params are Null:");
@@ -3499,10 +3841,22 @@
 		return -EINVAL;
 	}
 
+	CAM_DBG(CAM_REQ, "ctx_id %d req %lld Flush type %d",
+		ctx_data->ctx_id,
+		*(int64_t *)flush_args->flush_req_pending[0],
+		flush_args->flush_type);
+
 	switch (flush_args->flush_type) {
 	case CAM_FLUSH_TYPE_ALL:
-		if (flush_args->num_req_active)
-			cam_icp_mgr_abort_handle(ctx_data);
+		mutex_lock(&hw_mgr->hw_mgr_mutex);
+		if (!hw_mgr->recovery) {
+			if (flush_args->num_req_active) {
+				mutex_unlock(&hw_mgr->hw_mgr_mutex);
+				cam_icp_mgr_abort_handle(ctx_data);
+			}
+		} else {
+			mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		}
 		mutex_lock(&ctx_data->ctx_mutex);
 		cam_icp_mgr_flush_all(ctx_data, flush_args);
 		mutex_unlock(&ctx_data->ctx_mutex);
@@ -3540,7 +3894,7 @@
 		return -EINVAL;
 	}
 
-	CAM_DBG(CAM_ICP, "Enter");
+	CAM_DBG(CAM_ICP, "Enter recovery set %d", hw_mgr->recovery);
 	ctx_data = release_hw->ctxt_to_hw_map;
 	if (!ctx_data) {
 		CAM_ERR(CAM_ICP, "NULL ctx data");
@@ -3561,9 +3915,15 @@
 	}
 	mutex_unlock(&hw_mgr->ctx_data[ctx_id].ctx_mutex);
 
-	if (release_hw->active_req) {
-		cam_icp_mgr_abort_handle(ctx_data);
-		cam_icp_mgr_send_abort_status(ctx_data);
+	mutex_lock(&hw_mgr->hw_mgr_mutex);
+	if (!hw_mgr->recovery) {
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		if (release_hw->active_req) {
+			cam_icp_mgr_abort_handle(ctx_data);
+			cam_icp_mgr_send_abort_status(ctx_data);
+		}
+	} else {
+		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 	}
 
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
@@ -3577,57 +3937,10 @@
 	}
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 
-	if (!hw_mgr->bps_ctxt_cnt || !hw_mgr->ipe_ctxt_cnt)
+	if ((!hw_mgr->bps_ctxt_cnt || !hw_mgr->ipe_ctxt_cnt))
 		cam_icp_device_timer_stop(hw_mgr);
 
-	CAM_DBG(CAM_ICP, "Exit");
-	return rc;
-}
-
-static int cam_icp_mgr_send_config_io(struct cam_icp_hw_ctx_data *ctx_data,
-	uint32_t io_buf_addr)
-{
-	int rc = 0;
-	struct hfi_cmd_work_data *task_data;
-	struct hfi_cmd_ipebps_async ioconfig_cmd;
-	unsigned long rem_jiffies;
-	int timeout = 5000;
-	struct crm_workq_task *task;
-
-	task = cam_req_mgr_workq_get_task(icp_hw_mgr.cmd_work);
-	if (!task)
-		return -ENOMEM;
-
-	ioconfig_cmd.size = sizeof(struct hfi_cmd_ipebps_async);
-	ioconfig_cmd.pkt_type = HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT;
-	if (ctx_data->icp_dev_acquire_info->dev_type == CAM_ICP_RES_TYPE_BPS)
-		ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_BPS_CONFIG_IO;
-	else
-		ioconfig_cmd.opcode = HFI_IPEBPS_CMD_OPCODE_IPE_CONFIG_IO;
-
-	reinit_completion(&ctx_data->wait_complete);
-	ioconfig_cmd.num_fw_handles = 1;
-	ioconfig_cmd.fw_handles[0] = ctx_data->fw_handle;
-	ioconfig_cmd.payload.indirect = io_buf_addr;
-	ioconfig_cmd.user_data1 = (uint64_t)ctx_data;
-	ioconfig_cmd.user_data2 = (uint64_t)0x0;
-	task_data = (struct hfi_cmd_work_data *)task->payload;
-	task_data->data = (void *)&ioconfig_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);
-	if (rc)
-		return rc;
-
-	rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete,
-			msecs_to_jiffies((timeout)));
-	if (!rem_jiffies) {
-		rc = -ETIMEDOUT;
-		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
-	}
-
+	CAM_DBG(CAM_ICP, "Release done for ctx_id %d", ctx_id);
 	return rc;
 }
 
@@ -3665,6 +3978,7 @@
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+		cam_hfi_queue_dump();
 	}
 
 	if (ctx_data->fw_handle == 0) {
@@ -3710,6 +4024,7 @@
 	if (!rem_jiffies) {
 		rc = -ETIMEDOUT;
 		CAM_ERR(CAM_ICP, "FW response timed out %d", rc);
+		cam_hfi_queue_dump();
 	}
 
 	return rc;
@@ -3802,6 +4117,21 @@
 	return 0;
 }
 
+static const char *cam_icp_dev_type_to_name(
+	uint32_t dev_type)
+{
+	switch (dev_type) {
+	case CAM_ICP_RES_TYPE_BPS:
+		return "BPS";
+	case CAM_ICP_RES_TYPE_IPE_RT:
+		return "IPE_RT";
+	case CAM_ICP_RES_TYPE_IPE:
+		return "IPE";
+	default:
+		return "Invalid dev type";
+	}
+}
+
 static int cam_icp_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
 {
 	int rc = 0, bitmap_size = 0;
@@ -3843,6 +4173,8 @@
 
 	icp_dev_acquire_info = ctx_data->icp_dev_acquire_info;
 
+	CAM_DBG(CAM_ICP, "acquire io buf handle %d",
+		icp_dev_acquire_info->io_config_cmd_handle);
 	rc = cam_mem_get_io_buf(
 		icp_dev_acquire_info->io_config_cmd_handle,
 		hw_mgr->iommu_hdl,
@@ -3931,7 +4263,10 @@
 	cam_icp_ctx_timer_start(ctx_data);
 	hw_mgr->ctxt_cnt++;
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
-	CAM_DBG(CAM_ICP, "Acquire Done");
+	CAM_DBG(CAM_ICP, "Acquire Done for ctx_id %u dev name %s dev type %d",
+		ctx_data->ctx_id, cam_icp_dev_type_to_name(
+		icp_dev_acquire_info->dev_type),
+		icp_dev_acquire_info->dev_type);
 
 	return 0;
 
@@ -4134,21 +4469,22 @@
 	int i;
 
 	rc = cam_req_mgr_workq_create("icp_command_queue", ICP_WORKQ_NUM_TASK,
-		&icp_hw_mgr.cmd_work, CRM_WORKQ_USAGE_NON_IRQ);
+		&icp_hw_mgr.cmd_work, CRM_WORKQ_USAGE_NON_IRQ,
+		0);
 	if (rc) {
 		CAM_ERR(CAM_ICP, "unable to create a command worker");
 		goto cmd_work_failed;
 	}
 
 	rc = cam_req_mgr_workq_create("icp_message_queue", ICP_WORKQ_NUM_TASK,
-		&icp_hw_mgr.msg_work, CRM_WORKQ_USAGE_IRQ);
+		&icp_hw_mgr.msg_work, CRM_WORKQ_USAGE_IRQ, 0);
 	if (rc) {
 		CAM_ERR(CAM_ICP, "unable to create a message worker");
 		goto msg_work_failed;
 	}
 
 	rc = cam_req_mgr_workq_create("icp_timer_queue", ICP_WORKQ_NUM_TASK,
-		&icp_hw_mgr.timer_work, CRM_WORKQ_USAGE_IRQ);
+		&icp_hw_mgr.timer_work, CRM_WORKQ_USAGE_IRQ, 0);
 	if (rc) {
 		CAM_ERR(CAM_ICP, "unable to create a timer worker");
 		goto timer_work_failed;
@@ -4176,6 +4512,9 @@
 	if (rc)
 		goto debugfs_create_failed;
 
+	icp_hw_mgr.icp_pc_flag = true;
+	icp_hw_mgr.ipe_bps_pc_flag = true;
+
 	for (i = 0; i < ICP_WORKQ_NUM_TASK; i++)
 		icp_hw_mgr.msg_work->task.pool[i].payload =
 				&icp_hw_mgr.msg_work_data[i];
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 8746ee2..0b931f3 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
@@ -79,6 +79,7 @@
  * @sec_heap: Memory info of secondary heap
  * @fw_buf: Memory info of firmware
  * @qdss_buf: Memory info of qdss
+ * @sfr_buf: Memory info for sfr buffer
  */
 struct icp_hfi_mem_info {
 	struct cam_mem_mgr_memory_desc qtbl;
@@ -88,6 +89,7 @@
 	struct cam_mem_mgr_memory_desc sec_heap;
 	struct cam_mem_mgr_memory_desc fw_buf;
 	struct cam_mem_mgr_memory_desc qdss_buf;
+	struct cam_mem_mgr_memory_desc sfr_buf;
 	struct cam_smmu_region_info shmem;
 };
 
@@ -126,6 +128,19 @@
 };
 
 /**
+  * struct icp_frame_info
+  * @request_id: request id
+  * @io_config: the address of io config
+  * @hfi_cfg_io_cmd: command struct to be sent to hfi
+  */
+struct icp_frame_info {
+	uint64_t request_id;
+	uint64_t io_config;
+	struct hfi_cmd_ipebps_async hfi_cfg_io_cmd;
+};
+
+
+/**
  * struct hfi_frame_process_info
  * @hfi_frame_cmd: Frame process command info
  * @bitmap: Bitmap for hfi_frame_cmd
@@ -136,6 +151,7 @@
  * @out_resource: Out sync info
  * @fw_process_flag: Frame process flag
  * @clk_info: Clock information for a request
+ * @frame_info: information needed to process request
  */
 struct hfi_frame_process_info {
 	struct hfi_cmd_ipebps_async hfi_frame_cmd[CAM_FRAME_CMD_MAX];
@@ -149,6 +165,7 @@
 	uint32_t in_free_resource[CAM_FRAME_CMD_MAX];
 	uint32_t fw_process_flag[CAM_FRAME_CMD_MAX];
 	struct cam_icp_clk_bw_request clk_info[CAM_FRAME_CMD_MAX];
+	struct icp_frame_info frame_info[CAM_FRAME_CMD_MAX];
 };
 
 /**
@@ -189,6 +206,7 @@
  * @clk_info: Current clock info of a context
  * @watch_dog: watchdog timer handle
  * @watch_dog_reset_counter: Counter for watch dog reset
+ * @icp_dev_io_info: io config resource
  */
 struct cam_icp_hw_ctx_data {
 	void *context_priv;
@@ -208,16 +226,19 @@
 	struct cam_ctx_clk_info clk_info;
 	struct cam_req_mgr_timer *watch_dog;
 	uint32_t watch_dog_reset_counter;
+	struct cam_icp_acquire_dev_info icp_dev_io_info;
 };
 
 /**
  * struct icp_cmd_generic_blob
  * @ctx: Current context info
  * @frame_info_idx: Index used for frame process info
+ * @io_buf_addr: pointer to io buffer address
  */
 struct icp_cmd_generic_blob {
 	struct cam_icp_hw_ctx_data *ctx;
 	uint32_t frame_info_idx;
+	uint64_t *io_buf_addr;
 };
 
 /**
@@ -290,6 +311,9 @@
  * @bps_dev_intf: Device interface for BPS
  * @ipe_clk_state: IPE clock state flag
  * @bps_clk_state: BPS clock state flag
+ * @recovery: Flag to validate if in previous session FW
+ *            reported a fatal error or wdt. If set FW is
+ *            re-downloaded for new camera session.
  */
 struct cam_icp_hw_mgr {
 	struct mutex hw_mgr_mutex;
@@ -337,6 +361,7 @@
 	struct cam_hw_intf *bps_dev_intf;
 	bool ipe_clk_state;
 	bool bps_clk_state;
+	bool recovery;
 };
 
 static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args);
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_bps_hw_intf.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_bps_hw_intf.h
index 4f07172..0f76a05 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_bps_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_bps_hw_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,15 @@
 #include "cam_hw_mgr_intf.h"
 #include "cam_icp_hw_intf.h"
 
+/* BPS register */
+#define BPS_TOP_RST_CMD              0x1008
+#define BPS_CDM_RST_CMD              0x10
+#define BPS_CDM_IRQ_STATUS           0x44
+#define BPS_TOP_IRQ_STATUS           0x100C
+
+/* BPS CDM/TOP status register */
+#define BPS_RST_DONE_IRQ_STATUS_BIT  0x1
+
 enum cam_icp_bps_cmd_type {
 	CAM_ICP_BPS_CMD_FW_DOWNLOAD,
 	CAM_ICP_BPS_CMD_POWER_COLLAPSE,
@@ -28,6 +37,7 @@
 	CAM_ICP_BPS_CMD_CPAS_STOP,
 	CAM_ICP_BPS_CMD_UPDATE_CLK,
 	CAM_ICP_BPS_CMD_DISABLE_CLK,
+	CAM_ICP_BPS_CMD_RESET,
 	CAM_ICP_BPS_CMD_MAX,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_ipe_hw_intf.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_ipe_hw_intf.h
index 0943bef..d1e3b9a 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_ipe_hw_intf.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/include/cam_ipe_hw_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -18,6 +18,15 @@
 #include "cam_hw_mgr_intf.h"
 #include "cam_icp_hw_intf.h"
 
+/* IPE registers */
+#define IPE_TOP_RST_CMD              0x1008
+#define IPE_CDM_RST_CMD              0x10
+#define IPE_CDM_IRQ_STATUS           0x44
+#define IPE_TOP_IRQ_STATUS           0x100C
+
+/* IPE CDM/TOP status register */
+#define IPE_RST_DONE_IRQ_STATUS_BIT  0x1
+
 enum cam_icp_ipe_cmd_type {
 	CAM_ICP_IPE_CMD_FW_DOWNLOAD,
 	CAM_ICP_IPE_CMD_POWER_COLLAPSE,
@@ -28,6 +37,7 @@
 	CAM_ICP_IPE_CMD_CPAS_STOP,
 	CAM_ICP_IPE_CMD_UPDATE_CLK,
 	CAM_ICP_IPE_CMD_DISABLE_CLK,
+	CAM_ICP_IPE_CMD_RESET,
 	CAM_ICP_IPE_CMD_MAX,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c
index 87478af..620a4bd 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_core.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_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
@@ -18,6 +18,7 @@
 #include <linux/firmware.h>
 #include <linux/delay.h>
 #include <linux/timer.h>
+#include <linux/iopoll.h>
 #include "cam_io_util.h"
 #include "cam_hw.h"
 #include "cam_hw_intf.h"
@@ -29,6 +30,9 @@
 #include "cam_icp_hw_mgr_intf.h"
 #include "cam_cpas_api.h"
 #include "cam_debug_util.h"
+#include "hfi_reg.h"
+
+#define HFI_MAX_POLL_TRY 5
 
 static int cam_ipe_caps_vote(struct cam_ipe_device_core_info *core_info,
 	struct cam_icp_cpas_vote *cpas_vote)
@@ -206,6 +210,77 @@
 	return rc;
 }
 
+static int cam_ipe_cmd_reset(struct cam_hw_soc_info *soc_info,
+	struct cam_ipe_device_core_info *core_info)
+{
+	int pwr_ctrl, pwr_status, rc = 0;
+	uint32_t status = 0, retry_cnt = 0;
+	bool reset_ipe_cdm_fail = false;
+	bool reset_ipe_top_fail = false;
+
+	CAM_DBG(CAM_ICP, "CAM_ICP_IPE_CMD_RESET");
+	/* IPE CDM core reset*/
+	cam_io_w_mb((uint32_t)0xF,
+		soc_info->reg_map[0].mem_base + IPE_CDM_RST_CMD);
+	while (retry_cnt < HFI_MAX_POLL_TRY) {
+		readw_poll_timeout((soc_info->reg_map[0].mem_base +
+			IPE_CDM_IRQ_STATUS),
+			status, ((status & IPE_RST_DONE_IRQ_STATUS_BIT) == 0x1),
+			100, 10000);
+
+		CAM_DBG(CAM_HFI, "ipe_cdm_irq_status = %u", status);
+
+		if ((status & IPE_RST_DONE_IRQ_STATUS_BIT) == 0x1)
+			break;
+		retry_cnt++;
+	}
+	status = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+		IPE_CDM_IRQ_STATUS);
+	if ((status & IPE_RST_DONE_IRQ_STATUS_BIT) != 0x1) {
+		CAM_ERR(CAM_ICP, "IPE CDM rst failed status 0x%x", status);
+		reset_ipe_cdm_fail = true;
+	}
+
+	/* IPE reset*/
+	status = 0;
+	cam_io_w_mb((uint32_t)0x3,
+		soc_info->reg_map[0].mem_base + IPE_TOP_RST_CMD);
+	while (retry_cnt < HFI_MAX_POLL_TRY) {
+		readw_poll_timeout((soc_info->reg_map[0].mem_base +
+			IPE_TOP_IRQ_STATUS),
+			status, ((status & IPE_RST_DONE_IRQ_STATUS_BIT) == 0x1),
+			100, 10000);
+
+		CAM_DBG(CAM_HFI, "ipe_top_irq_status = %u", status);
+
+
+		if ((status & IPE_RST_DONE_IRQ_STATUS_BIT) == 0x1)
+			break;
+		retry_cnt++;
+	}
+	status = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+		IPE_TOP_IRQ_STATUS);
+	if ((status & IPE_RST_DONE_IRQ_STATUS_BIT) != 0x1) {
+		CAM_ERR(CAM_ICP, "IPE top rst failed status 0x%x", status);
+		reset_ipe_top_fail = true;
+	}
+
+	cam_ipe_get_gdsc_control(soc_info);
+	cam_cpas_reg_read(core_info->cpas_handle,
+		CAM_CPAS_REG_CPASTOP, core_info->ipe_hw_info->pwr_ctrl,
+		true, &pwr_ctrl);
+	cam_cpas_reg_read(core_info->cpas_handle,
+		CAM_CPAS_REG_CPASTOP, core_info->ipe_hw_info->pwr_status,
+		true, &pwr_status);
+	CAM_DBG(CAM_ICP, "(After)pwr_ctrl = %x pwr_status = %x",
+		pwr_ctrl, pwr_status);
+
+	if (reset_ipe_cdm_fail || reset_ipe_top_fail)
+		rc = -EAGAIN;
+
+	return rc;
+}
+
 int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type,
 	void *cmd_args, uint32_t arg_size)
 {
@@ -302,7 +377,12 @@
 			cam_ipe_toggle_clk(soc_info, false);
 		core_info->clk_enable = false;
 		break;
+	case CAM_ICP_IPE_CMD_RESET:
+		rc = cam_ipe_cmd_reset(soc_info, core_info);
+		break;
 	default:
+		CAM_ERR(CAM_ICP, "Invalid Cmd Type:%u", cmd_type);
+		rc = -EINVAL;
 		break;
 	}
 	return rc;
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_dev.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_dev.c
index cc2b1b1..a01d114 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_dev.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_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
@@ -41,6 +41,8 @@
 };
 EXPORT_SYMBOL(cam_ipe_hw_info);
 
+static char ipe_dev_name[8];
+
 int cam_ipe_register_cpas(struct cam_hw_soc_info *soc_info,
 	struct cam_ipe_device_core_info *core_info,
 	uint32_t hw_idx)
@@ -96,9 +98,14 @@
 		kfree(ipe_dev_intf);
 		return -ENOMEM;
 	}
+
+	memset(ipe_dev_name, 0, sizeof(ipe_dev_name));
+	snprintf(ipe_dev_name, sizeof(ipe_dev_name),
+		"ipe%1u", ipe_dev_intf->hw_idx);
+
 	ipe_dev->soc_info.pdev = pdev;
 	ipe_dev->soc_info.dev = &pdev->dev;
-	ipe_dev->soc_info.dev_name = pdev->name;
+	ipe_dev->soc_info.dev_name = ipe_dev_name;
 	ipe_dev_intf->hw_priv = ipe_dev;
 	ipe_dev_intf->hw_ops.init = cam_ipe_init_hw;
 	ipe_dev_intf->hw_ops.deinit = cam_ipe_deinit_hw;
@@ -179,6 +186,7 @@
 		.name = "cam-ipe",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_ipe_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c
index d24305a..91d440f 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/ipe_hw/ipe_soc.c
@@ -157,8 +157,7 @@
 		clk_rate = soc_info->clk_rate[CAM_TURBO_VOTE][src_clk_idx];
 	}
 
-	return cam_soc_util_set_clk_rate(soc_info->clk[soc_info->src_clk_idx],
-		soc_info->clk_name[soc_info->src_clk_idx], clk_rate);
+	return cam_soc_util_set_src_clk_rate(soc_info, clk_rate);
 }
 
 int cam_ipe_toggle_clk(struct cam_hw_soc_info *soc_info, bool clk_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 7b02aac..f5b1bb1 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
@@ -435,8 +435,8 @@
 		list_del_init(&req->list);
 		list_add_tail(&req->list, &ctx->free_req_list);
 		ctx_isp->active_req_cnt--;
-		CAM_DBG(CAM_ISP,
-			"Move active request %lld to free list(cnt = %d)",
+		CAM_DBG(CAM_REQ,
+			"Move active request %lld to free list(cnt = %d) [all fences done]",
 			 req->request_id, ctx_isp->active_req_cnt);
 	}
 
@@ -536,7 +536,7 @@
 	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)",
+		CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)",
 			 req->request_id, ctx_isp->active_req_cnt);
 	} else {
 		/* no io config, so the request is completed. */
@@ -697,7 +697,7 @@
 			/* need to handle the buf done */
 			list_add_tail(&req->list, &ctx->active_req_list);
 			ctx_isp->active_req_cnt++;
-			CAM_DBG(CAM_ISP,
+			CAM_DBG(CAM_REQ,
 				"move request %lld to active list(cnt = %d)",
 				 req->request_id,
 				ctx_isp->active_req_cnt);
@@ -761,7 +761,7 @@
 		list_del_init(&req->list);
 		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)",
+		CAM_DBG(CAM_REQ, "move request %lld to active list(cnt = %d)",
 			 req->request_id, ctx_isp->active_req_cnt);
 		req_isp->bubble_report = 0;
 	}
@@ -895,8 +895,9 @@
 		notify.req_id = req->request_id;
 		notify.error = CRM_KMD_ERR_BUBBLE;
 		ctx->ctx_crm_intf->notify_err(&notify);
-		CAM_DBG(CAM_ISP, "Notify CRM about Bubble frame %lld",
-			ctx_isp->frame_id);
+		CAM_DBG(CAM_REQ,
+			"Notify CRM about Bubble req_id %llu frame %lld",
+			req->request_id, ctx_isp->frame_id);
 	} else {
 		/*
 		 * If we can not report bubble, then treat it as if no bubble
@@ -1227,7 +1228,8 @@
 		goto end;
 	}
 
-	CAM_DBG(CAM_ISP, "Apply request %lld", req->request_id);
+	CAM_DBG(CAM_REQ, "Apply request %lld in substate %d", req->request_id,
+		ctx_isp->substate_activated);
 	req_isp = (struct cam_isp_ctx_req *) req->req_priv;
 
 	if (ctx_isp->active_req_cnt >=  2) {
@@ -1342,6 +1344,8 @@
 		return 0;
 	}
 
+	CAM_DBG(CAM_REQ, "Flush [%u] in progress for req_id %llu",
+		flush_req->type, flush_req->req_id);
 	list_for_each_entry_safe(req, req_temp, req_list, list) {
 		if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ) {
 			if (req->request_id != flush_req->req_id) {
@@ -2016,7 +2020,8 @@
 	ctx->state = CAM_CTX_AVAILABLE;
 
 	trace_cam_context_state("ISP", ctx);
-	CAM_DBG(CAM_ISP, "next state %d", ctx->state);
+	CAM_DBG(CAM_ISP, "Release device success[%u] next state %d",
+		ctx->ctx_id, ctx->state);
 	return rc;
 }
 
@@ -2142,8 +2147,9 @@
 	if (rc)
 		goto free_req;
 
-	CAM_DBG(CAM_ISP, "Preprocessing Config %lld successful",
-		req->request_id);
+	CAM_DBG(CAM_REQ,
+		"Preprocessing Config req_id %lld successful on ctx %u",
+		req->request_id, ctx->ctx_id);
 
 	return rc;
 
@@ -2274,7 +2280,10 @@
 	ctx->state = CAM_CTX_ACQUIRED;
 
 	trace_cam_context_state("ISP", ctx);
-	CAM_DBG(CAM_ISP, "Acquire success.");
+	CAM_DBG(CAM_ISP,
+		"Acquire success on session_hdl 0x%x num_rsrces %d RDI only %d ctx %u",
+		cmd->session_handle, cmd->num_resources,
+		(hw_cmd_args.u.is_rdi_only_context ? 1 : 0), ctx->ctx_id);
 	kfree(isp_res);
 	return rc;
 
@@ -2416,7 +2425,7 @@
 		trace_cam_context_state("ISP", ctx);
 		goto end;
 	}
-	CAM_DBG(CAM_ISP, "start device success");
+	CAM_DBG(CAM_ISP, "start device success ctx %u", ctx->ctx_id);
 
 	if (req_isp->num_fence_map_out) {
 		list_del_init(&req->list);
@@ -2499,7 +2508,8 @@
 	ctx_isp->active_req_cnt = 0;
 	ctx_isp->reported_req_id = 0;
 
-	CAM_DBG(CAM_ISP, "next state %d", ctx->state);
+	CAM_DBG(CAM_ISP, "Stop device success next state %d on ctx %u",
+		ctx->state, ctx->ctx_id);
 	return rc;
 }
 
@@ -2560,6 +2570,24 @@
 	return rc;
 }
 
+static int __cam_isp_ctx_handle_sof_freeze_evt(
+	struct cam_context *ctx)
+{
+	int rc = 0;
+	struct cam_isp_hw_cmd_args   hw_cmd_args;
+	struct cam_isp_context      *ctx_isp =
+		(struct cam_isp_context *) ctx->ctx_priv;
+
+	hw_cmd_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
+	hw_cmd_args.cmd_type = CAM_ISP_HW_MGR_CMD_SOF_DEBUG;
+	hw_cmd_args.u.sof_irq_enable = 1;
+
+	rc = ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
+		&hw_cmd_args);
+
+	return rc;
+}
+
 static int __cam_isp_ctx_process_evt(struct cam_context *ctx,
 	struct cam_req_mgr_link_evt_data *link_evt_data)
 {
@@ -2575,6 +2603,9 @@
 	case CAM_REQ_MGR_LINK_EVT_RESUME:
 		__cam_isp_ctx_link_resume(ctx);
 		break;
+	case CAM_REQ_MGR_LINK_EVT_SOF_FREEZE:
+		__cam_isp_ctx_handle_sof_freeze_evt(ctx);
+		break;
 	default:
 		CAM_WARN(CAM_ISP, "Unknown event from CRM");
 		break;
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c
index e775daa..a067915 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_dev.c
@@ -136,6 +136,7 @@
 		.name = "cam_isp",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_isp_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
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 c1aa501..8d764b0 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
@@ -225,6 +225,8 @@
 				CAM_ERR(CAM_ISP, "Can not start HW resources");
 				goto err;
 			}
+			CAM_DBG(CAM_ISP, "Start HW %d Res %d", hw_intf->hw_idx,
+				isp_hw_res->hw_res[i]->res_id);
 		} else {
 			CAM_ERR(CAM_ISP, "function null");
 			goto err;
@@ -366,7 +368,8 @@
 			isp_res = hw_mgr_res->hw_res[i];
 			if (isp_res->hw_intf->hw_idx != base_idx)
 				continue;
-
+			CAM_DBG(CAM_ISP, "base_idx %d res_id %d cnt %u",
+				base_idx, isp_res->res_id, cnt);
 			stop_res[cnt] = isp_res;
 			cnt++;
 		}
@@ -483,8 +486,8 @@
 			"Add split id = %d for base idx = %d num_base=%d",
 			split_id, base_idx, ctx->num_base);
 	} else {
-		/*Check if base index is alreay exist in the list */
-		for (i = 0; i < CAM_IFE_HW_NUM_MAX; i++) {
+		/*Check if base index already exists in the list */
+		for (i = 0; i < ctx->num_base; i++) {
 			if (ctx->base[i].idx == base_idx) {
 				if (split_id != CAM_ISP_HW_SPLIT_MAX &&
 					ctx->base[i].split_id ==
@@ -495,7 +498,7 @@
 			}
 		}
 
-		if (i == CAM_IFE_HW_NUM_MAX) {
+		if (i == ctx->num_base) {
 			ctx->base[ctx->num_base].split_id = split_id;
 			ctx->base[ctx->num_base].idx      = base_idx;
 			ctx->num_base++;
@@ -845,7 +848,8 @@
 			}
 			ife_src_res->hw_res[i] = vfe_acquire.vfe_in.rsrc_node;
 			CAM_DBG(CAM_ISP,
-				"acquire success res type :0x%x res id:0x%x",
+				"acquire success IFE:%d  res type :0x%x res id:0x%x",
+				hw_intf->hw_idx,
 				ife_src_res->hw_res[i]->res_type,
 				ife_src_res->hw_res[i]->res_id);
 
@@ -871,29 +875,75 @@
 static int cam_ife_mgr_acquire_cid_res(
 	struct cam_ife_hw_mgr_ctx          *ife_ctx,
 	struct cam_isp_in_port_info        *in_port,
-	uint32_t                           *cid_res_id,
+	struct cam_ife_hw_mgr_res         **cid_res,
 	enum cam_ife_pix_path_res_id        csid_path)
 {
 	int rc = -1;
 	int i, j;
 	struct cam_ife_hw_mgr               *ife_hw_mgr;
-	struct cam_ife_hw_mgr_res           *cid_res;
 	struct cam_hw_intf                  *hw_intf;
+	struct cam_ife_hw_mgr_res           *cid_res_temp, *cid_res_iterator;
 	struct cam_csid_hw_reserve_resource_args  csid_acquire;
+	uint32_t acquired_cnt = 0;
 
 	ife_hw_mgr = ife_ctx->hw_mgr;
+	*cid_res = NULL;
 
-	rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &cid_res);
+	rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, cid_res);
 	if (rc) {
 		CAM_ERR(CAM_ISP, "No more free hw mgr resource");
-		goto err;
+		goto end;
 	}
-	cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_cid, &cid_res);
+
+	cid_res_temp = *cid_res;
 
 	csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
 	csid_acquire.in_port = in_port;
 	csid_acquire.res_id =  csid_path;
+	CAM_DBG(CAM_ISP, "path %d", csid_path);
 
+	/* Try acquiring CID resource from previously acquired HW */
+	list_for_each_entry(cid_res_iterator, &ife_ctx->res_list_ife_cid,
+		list) {
+
+		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+			if (!cid_res_iterator->hw_res[i])
+				continue;
+
+			hw_intf = cid_res_iterator->hw_res[i]->hw_intf;
+			rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+				&csid_acquire, sizeof(csid_acquire));
+			if (rc) {
+				CAM_DBG(CAM_ISP,
+					"No ife cid resource from hw %d",
+					hw_intf->hw_idx);
+				continue;
+			}
+
+			cid_res_temp->hw_res[acquired_cnt++] =
+				csid_acquire.node_res;
+
+			CAM_DBG(CAM_ISP,
+				"acquired csid(%s)=%d CID rsrc successfully",
+				(i == 0) ? "left" : "right",
+				hw_intf->hw_idx);
+
+			if (in_port->usage_type && acquired_cnt == 1 &&
+				csid_path == CAM_IFE_PIX_PATH_RES_IPP)
+				/* Continue to acquire Right */
+				continue;
+
+			if (acquired_cnt)
+				/*
+				 * If successfully acquired CID from
+				 * previously acquired HW, skip the next
+				 * part
+				 */
+				goto acquire_successful;
+		}
+	}
+
+	/* Acquire Left if not already acquired */
 	for (i = 0; i < CAM_IFE_CSID_HW_NUM_MAX; i++) {
 		if (!ife_hw_mgr->csid_devices[i])
 			continue;
@@ -903,31 +953,45 @@
 			sizeof(csid_acquire));
 		if (rc)
 			continue;
-		else
+		else {
+			cid_res_temp->hw_res[acquired_cnt++] =
+				csid_acquire.node_res;
 			break;
+		}
 	}
 
 	if (i == CAM_IFE_CSID_HW_NUM_MAX || !csid_acquire.node_res) {
-		CAM_ERR(CAM_ISP, "Can not acquire ife csid rdi resource");
-		goto err;
+		CAM_ERR(CAM_ISP, "Can not acquire ife cid resource for path %d",
+			csid_path);
+		goto put_res;
 	}
 
-	cid_res->res_type = CAM_IFE_HW_MGR_RES_CID;
-	cid_res->res_id = csid_acquire.node_res->res_id;
-	cid_res->is_dual_vfe = in_port->usage_type;
-	cid_res->hw_res[0] = csid_acquire.node_res;
-	cid_res->hw_res[1] = NULL;
-	/* CID(DT_ID) value of acquire device, require for path */
-	*cid_res_id = csid_acquire.node_res->res_id;
+acquire_successful:
+	CAM_DBG(CAM_ISP, "CID left acquired success is_dual %d",
+		in_port->usage_type);
 
-	if (cid_res->is_dual_vfe) {
+	cid_res_temp->res_type = CAM_IFE_HW_MGR_RES_CID;
+	/* CID(DT_ID) value of acquire device, require for path */
+	cid_res_temp->res_id = csid_acquire.node_res->res_id;
+	cid_res_temp->is_dual_vfe = in_port->usage_type;
+	cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_cid, cid_res);
+
+	/*
+	 * Acquire Right if not already acquired.
+	 * Dual IFE for RDI is not currently supported.
+	 */
+	if (cid_res_temp->is_dual_vfe && csid_path
+		== CAM_IFE_PIX_PATH_RES_IPP && acquired_cnt == 1) {
 		csid_acquire.node_res = NULL;
 		csid_acquire.res_type = CAM_ISP_RESOURCE_CID;
 		csid_acquire.in_port = in_port;
-		for (j = i + 1; j < CAM_IFE_CSID_HW_NUM_MAX; j++) {
+		for (j = 0; j < CAM_IFE_CSID_HW_NUM_MAX; j++) {
 			if (!ife_hw_mgr->csid_devices[j])
 				continue;
 
+			if (j == cid_res_temp->hw_res[0]->hw_intf->hw_idx)
+				continue;
+
 			hw_intf = ife_hw_mgr->csid_devices[j];
 			rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
 				&csid_acquire, sizeof(csid_acquire));
@@ -940,16 +1004,20 @@
 		if (j == CAM_IFE_CSID_HW_NUM_MAX) {
 			CAM_ERR(CAM_ISP,
 				"Can not acquire ife csid rdi resource");
-			goto err;
+			goto end;
 		}
-		cid_res->hw_res[1] = csid_acquire.node_res;
+		cid_res_temp->hw_res[1] = csid_acquire.node_res;
+		CAM_DBG(CAM_ISP, "CID right acquired success is_dual %d",
+			in_port->usage_type);
 	}
-	cid_res->parent = &ife_ctx->res_list_ife_in;
+	cid_res_temp->parent = &ife_ctx->res_list_ife_in;
 	ife_ctx->res_list_ife_in.child[
-		ife_ctx->res_list_ife_in.num_children++] = cid_res;
+		ife_ctx->res_list_ife_in.num_children++] = cid_res_temp;
 
 	return 0;
-err:
+put_res:
+	cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, cid_res);
+end:
 	return rc;
 
 }
@@ -966,35 +1034,25 @@
 	struct cam_ife_hw_mgr_res           *csid_res;
 	struct cam_ife_hw_mgr_res           *cid_res;
 	struct cam_hw_intf                  *hw_intf;
-	uint32_t                             cid_res_id;
 	struct cam_csid_hw_reserve_resource_args  csid_acquire;
 
+	ife_hw_mgr = ife_ctx->hw_mgr;
 	/* get cid resource */
-	rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res_id,
+	rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res,
 		CAM_IFE_PIX_PATH_RES_IPP);
 	if (rc) {
 		CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed");
-		goto err;
+		goto end;
 	}
 
-	ife_hw_mgr = ife_ctx->hw_mgr;
-
 	rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list, &csid_res);
 	if (rc) {
 		CAM_ERR(CAM_ISP, "No more free hw mgr resource");
-		goto err;
+		goto end;
 	}
-	cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res);
-
-	csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH;
-	csid_acquire.res_id = CAM_IFE_PIX_PATH_RES_IPP;
-	csid_acquire.cid = cid_res_id;
-	csid_acquire.in_port = in_port;
-	csid_acquire.out_port = in_port->data;
 
 	csid_res->res_type = CAM_ISP_RESOURCE_PIX_PATH;
 	csid_res->res_id = CAM_IFE_PIX_PATH_RES_IPP;
-	csid_res->is_dual_vfe = in_port->usage_type;
 
 	if (in_port->usage_type)
 		csid_res->is_dual_vfe = 1;
@@ -1003,66 +1061,60 @@
 		csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE;
 	}
 
-	list_for_each_entry(cid_res, &ife_ctx->res_list_ife_cid,
-		list) {
-		if (cid_res->res_id != cid_res_id)
-			continue;
+	/* IPP resource needs to be from same HW as CID resource */
+	for (i = 0; i <= csid_res->is_dual_vfe; i++) {
+		CAM_DBG(CAM_ISP, "i %d is_dual %d", i, csid_res->is_dual_vfe);
+		csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH;
+		csid_acquire.res_id = CAM_IFE_PIX_PATH_RES_IPP;
+		csid_acquire.cid = cid_res->hw_res[i]->res_id;
+		csid_acquire.in_port = in_port;
+		csid_acquire.out_port = in_port->data;
+		csid_acquire.node_res = NULL;
 
-		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
-			if (!cid_res->hw_res[i])
-				continue;
+		hw_intf = cid_res->hw_res[i]->hw_intf;
 
-			hw_intf = ife_hw_mgr->csid_devices[
-				cid_res->hw_res[i]->hw_intf->hw_idx];
-
-			csid_acquire.node_res = NULL;
-			if (csid_res->is_dual_vfe) {
-				if (i == CAM_ISP_HW_SPLIT_LEFT) {
-					master_idx = hw_intf->hw_idx;
-					csid_acquire.sync_mode =
-						CAM_ISP_HW_SYNC_MASTER;
-				} else {
-					if (master_idx == -1) {
-						CAM_ERR(CAM_ISP,
-							"No Master found");
-						goto err;
-					}
-					csid_acquire.sync_mode =
-						CAM_ISP_HW_SYNC_SLAVE;
-					csid_acquire.master_idx = master_idx;
+		if (csid_res->is_dual_vfe) {
+			if (i == CAM_ISP_HW_SPLIT_LEFT) {
+				master_idx = hw_intf->hw_idx;
+				csid_acquire.sync_mode =
+					CAM_ISP_HW_SYNC_MASTER;
+			} else {
+				if (master_idx == -1) {
+					CAM_ERR(CAM_ISP,
+						"No Master found");
+					goto put_res;
 				}
+				csid_acquire.sync_mode =
+					CAM_ISP_HW_SYNC_SLAVE;
+				csid_acquire.master_idx = master_idx;
 			}
-
-			rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
-				&csid_acquire, sizeof(csid_acquire));
-			if (rc) {
-				CAM_ERR(CAM_ISP,
-					"Cannot acquire ife csid ipp resource");
-				goto err;
-			}
-
-			csid_res->hw_res[i] = csid_acquire.node_res;
-			CAM_DBG(CAM_ISP,
-				"acquired csid(%s)=%d ipp rsrc successfully",
-				(i == 0) ? "left" : "right",
-				hw_intf->hw_idx);
-
 		}
 
-		if (i == CAM_IFE_CSID_HW_NUM_MAX) {
+		rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+			&csid_acquire, sizeof(csid_acquire));
+		if (rc) {
 			CAM_ERR(CAM_ISP,
-				"Can not acquire ife csid ipp resource");
-			goto err;
+				"Cannot acquire ife csid ipp resource");
+			goto put_res;
 		}
 
-		csid_res->parent = cid_res;
-		cid_res->child[cid_res->num_children++] = csid_res;
+		csid_res->hw_res[i] = csid_acquire.node_res;
+		CAM_DBG(CAM_ISP,
+			"acquired csid(%s)=%d ipp rsrc successfully",
+			(i == 0) ? "left" : "right",
+			hw_intf->hw_idx);
 	}
+	cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res);
+
+	csid_res->parent = cid_res;
+	cid_res->child[cid_res->num_children++] = csid_res;
 
 	CAM_DBG(CAM_ISP, "acquire res %d", csid_acquire.res_id);
 
 	return 0;
-err:
+put_res:
+	cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &csid_res);
+end:
 	return rc;
 }
 
@@ -1099,111 +1151,88 @@
 	struct cam_ife_hw_mgr_ctx     *ife_ctx,
 	struct cam_isp_in_port_info   *in_port)
 {
-	int rc = -1;
-	int i, j;
+	int rc = -EINVAL;
+	int i;
 
 	struct cam_ife_hw_mgr               *ife_hw_mgr;
 	struct cam_ife_hw_mgr_res           *csid_res;
 	struct cam_ife_hw_mgr_res           *cid_res;
 	struct cam_hw_intf                  *hw_intf;
 	struct cam_isp_out_port_info        *out_port;
-	uint32_t                             cid_res_id;
 	struct cam_csid_hw_reserve_resource_args  csid_acquire;
+	enum cam_ife_pix_path_res_id         path_type;
 
 	ife_hw_mgr = ife_ctx->hw_mgr;
 
 	for (i = 0; i < in_port->num_out_res; i++) {
 		out_port = &in_port->data[i];
-		if (!cam_ife_hw_mgr_is_rdi_res(out_port->res_type))
+		path_type = cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
+			out_port->res_type);
+		if (path_type == CAM_IFE_PIX_PATH_RES_MAX)
 			continue;
 
-			/* get cid resource */
-			rc = cam_ife_mgr_acquire_cid_res(ife_ctx,
-				in_port, &cid_res_id,
-				cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
-				out_port->res_type));
-			if (rc) {
-				CAM_ERR(CAM_ISP,
-					"Acquire IFE CID resource Failed");
-				goto err;
+		/* get cid resource */
+		rc = cam_ife_mgr_acquire_cid_res(ife_ctx, in_port, &cid_res,
+			path_type);
+		if (rc) {
+			CAM_ERR(CAM_ISP, "Acquire IFE CID resource Failed");
+			goto end;
 		}
 
+		/* For each RDI we need CID + PATH resource */
 		rc = cam_ife_hw_mgr_get_res(&ife_ctx->free_res_list,
 			&csid_res);
 		if (rc) {
 			CAM_ERR(CAM_ISP, "No more free hw mgr resource");
-			goto err;
+			goto end;
 		}
-		cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res);
-
-		/*
-		 * no need to check since we are doing one to one mapping
-		 * between the csid rdi type and out port rdi type
-		 */
 
 		memset(&csid_acquire, 0, sizeof(csid_acquire));
-		csid_acquire.res_id =
-			cam_ife_hw_mgr_get_ife_csid_rdi_res_type(
-				out_port->res_type);
+		csid_acquire.res_id = path_type;
 
 		csid_acquire.res_type = CAM_ISP_RESOURCE_PIX_PATH;
-		csid_acquire.cid = cid_res_id;
+		csid_acquire.cid = cid_res->hw_res[0]->res_id;
 		csid_acquire.in_port = in_port;
 		csid_acquire.out_port = out_port;
 		csid_acquire.sync_mode = CAM_ISP_HW_SYNC_NONE;
+		csid_acquire.node_res = NULL;
 
-		list_for_each_entry(cid_res, &ife_ctx->res_list_ife_cid,
-			list) {
-			if (cid_res->res_id != cid_res_id)
-				continue;
+		hw_intf = cid_res->hw_res[0]->hw_intf;
+		rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
+			&csid_acquire, sizeof(csid_acquire));
+		if (rc) {
+			CAM_ERR(CAM_ISP,
+				"CSID Path reserve failed hw=%d rc=%d cid=%d",
+				hw_intf->hw_idx, rc,
+				cid_res->hw_res[0]->res_id);
 
-			for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
-				if (!cid_res->hw_res[j])
-					continue;
-
-				csid_acquire.node_res = NULL;
-
-				hw_intf = ife_hw_mgr->csid_devices[
-					cid_res->hw_res[j]->hw_intf->hw_idx];
-				rc = hw_intf->hw_ops.reserve(hw_intf->hw_priv,
-					&csid_acquire, sizeof(csid_acquire));
-				if (rc) {
-					CAM_DBG(CAM_ISP,
-					 "CSID Path reserve failed hw=%d rc=%d",
-					 hw_intf->hw_idx, rc);
-					continue;
-				}
-
-				/* RDI does not need Dual ISP. Break */
-				break;
-			}
-
-			if (j == CAM_ISP_HW_SPLIT_MAX &&
-				csid_acquire.node_res == NULL) {
-				CAM_ERR(CAM_ISP,
-					"acquire csid rdi rsrc failed, cid %d",
-					cid_res_id);
-				goto err;
-			}
-
-			csid_res->res_type = CAM_ISP_RESOURCE_PIX_PATH;
-			csid_res->res_id = csid_acquire.res_id;
-			csid_res->is_dual_vfe = 0;
-			csid_res->hw_res[0] = csid_acquire.node_res;
-			csid_res->hw_res[1] = NULL;
-			CAM_DBG(CAM_ISP, "acquire res %d",
-				csid_acquire.res_id);
-			csid_res->parent = cid_res;
-			cid_res->child[cid_res->num_children++] =
-				csid_res;
-
-			/* Done with cid_res_id. Break */
-			break;
+			goto put_res;
 		}
+
+		if (csid_acquire.node_res == NULL) {
+			CAM_ERR(CAM_ISP, "Acquire CSID RDI rsrc failed");
+
+			goto put_res;
+		}
+
+		csid_res->res_type = (enum cam_ife_hw_mgr_res_type)
+			CAM_ISP_RESOURCE_PIX_PATH;
+		csid_res->res_id = csid_acquire.res_id;
+		csid_res->is_dual_vfe = 0;
+		csid_res->hw_res[0] = csid_acquire.node_res;
+		csid_res->hw_res[1] = NULL;
+		CAM_DBG(CAM_ISP, "acquire res %d",
+			csid_acquire.res_id);
+		csid_res->parent = cid_res;
+		cid_res->child[cid_res->num_children++] =
+			csid_res;
+		cam_ife_hw_mgr_put_res(&ife_ctx->res_list_ife_csid, &csid_res);
 	}
 
 	return 0;
-err:
+put_res:
+	cam_ife_hw_mgr_put_res(&ife_ctx->free_res_list, &csid_res);
+end:
 	return rc;
 }
 
@@ -1511,7 +1540,7 @@
 	int                                    rc = -EINVAL;
 	uint32_t                               i;
 
-	CAM_DBG(CAM_ISP,
+	CAM_DBG(CAM_PERF,
 		"usage=%u left cam_bw_bps=%llu ext_bw_bps=%llu\n"
 		"right cam_bw_bps=%llu ext_bw_bps=%llu",
 		bw_config->usage_type,
@@ -1667,8 +1696,6 @@
 					"config done Success for req_id=%llu",
 					cfg->request_id);
 			}
-
-			rc = 0;
 		}
 	} else {
 		CAM_ERR(CAM_ISP, "No commands to config");
@@ -1870,6 +1897,24 @@
 	 */
 	if (i == ctx->num_base)
 		master_base_idx = ctx->base[0].idx;
+	CAM_DBG(CAM_ISP, "Stopping master CSID idx %d", master_base_idx);
+
+	/* Stop the master CSID path first */
+	cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
+		master_base_idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+
+	/* stop rest of the CSID paths  */
+	for (i = 0; i < ctx->num_base; i++) {
+		if (ctx->base[i].idx == master_base_idx)
+			continue;
+		CAM_DBG(CAM_ISP, "Stopping CSID idx %d i %d master %d",
+			ctx->base[i].idx, i, master_base_idx);
+
+		cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
+			ctx->base[i].idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+	}
+
+	CAM_DBG(CAM_ISP, "Stopping master CID idx %d", master_base_idx);
 
 	/* Stop the master CIDs first */
 	cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid,
@@ -1877,26 +1922,14 @@
 
 	/* stop rest of the CIDs  */
 	for (i = 0; i < ctx->num_base; i++) {
-		if (i == master_base_idx)
+		if (ctx->base[i].idx == master_base_idx)
 			continue;
+		CAM_DBG(CAM_ISP, "Stopping CID idx %d i %d master %d",
+			ctx->base[i].idx, i, master_base_idx);
 		cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid,
 			ctx->base[i].idx, csid_halt_type);
 	}
 
-	/* Stop the master CSID path first */
-	cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
-			master_base_idx, csid_halt_type);
-
-	/* stop rest of the CSID paths  */
-	for (i = 0; i < ctx->num_base; i++) {
-		if (i == master_base_idx)
-			continue;
-
-		cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
-			ctx->base[i].idx, csid_halt_type);
-	}
-
-
 	/* Deinit IFE CID */
 	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_cid, list) {
 		CAM_DBG(CAM_ISP, "%s: Going to DeInit IFE CID\n", __func__);
@@ -1918,7 +1951,8 @@
 	for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++)
 		cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]);
 
-	CAM_DBG(CAM_ISP, "Exit...ctx id:%d rc :%d", ctx->ctx_index, rc);
+	CAM_DBG(CAM_ISP,
+		"Stop success for ctx id:%d rc :%d", ctx->ctx_index, rc);
 
 	mutex_lock(&g_ife_hw_mgr.ctx_mutex);
 	if (!atomic_dec_return(&g_ife_hw_mgr.active_ctx_cnt)) {
@@ -2196,7 +2230,7 @@
 	}
 
 	/* Start IFE root node: do nothing */
-	CAM_DBG(CAM_ISP, "Exit...(success)");
+	CAM_DBG(CAM_ISP, "Start success for ctx id:%d", ctx->ctx_index);
 	return 0;
 err:
 	stop_hw_method.hw_stop_cmd = CAM_CSID_HALT_IMMEDIATELY;
@@ -2383,7 +2417,7 @@
 
 	ctx = prepare->ctxt_to_hw_map;
 
-	CAM_DBG(CAM_ISP,
+	CAM_DBG(CAM_PERF,
 		"usage=%u left_clk= %lu right_clk=%lu",
 		clock_config->usage_type,
 		clock_config->left_pix_hz,
@@ -2536,7 +2570,8 @@
 		return -EINVAL;
 	}
 
-	CAM_DBG(CAM_ISP, "enter");
+	CAM_DBG(CAM_REQ, "Enter for req_id %lld",
+		prepare->packet->header.request_id);
 
 	prepare_hw_data = (struct cam_isp_prepare_hw_update_data  *)
 		prepare->priv;
@@ -2664,6 +2699,52 @@
 	return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_INCLUDE);
 }
 
+static int cam_ife_mgr_sof_irq_debug(
+	struct cam_ife_hw_mgr_ctx *ctx,
+	uint32_t sof_irq_enable)
+{
+	int rc = 0;
+	uint32_t i = 0;
+	struct cam_ife_hw_mgr_res     *hw_mgr_res = NULL;
+	struct cam_hw_intf            *hw_intf = NULL;
+	struct cam_isp_resource_node  *rsrc_node = NULL;
+
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) {
+		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+			if (!hw_mgr_res->hw_res[i])
+				continue;
+
+			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+			if (hw_intf->hw_ops.process_cmd) {
+				rc |= hw_intf->hw_ops.process_cmd(
+					hw_intf->hw_priv,
+					CAM_IFE_CSID_SOF_IRQ_DEBUG,
+					&sof_irq_enable,
+					sizeof(sof_irq_enable));
+			}
+		}
+	}
+
+	list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+			if (!hw_mgr_res->hw_res[i])
+				continue;
+
+			rsrc_node = hw_mgr_res->hw_res[i];
+			if (rsrc_node->process_cmd && (rsrc_node->res_id ==
+				CAM_ISP_HW_VFE_IN_CAMIF)) {
+				rc |= hw_mgr_res->hw_res[i]->process_cmd(
+					hw_mgr_res->hw_res[i],
+					CAM_ISP_HW_CMD_SOF_IRQ_DEBUG,
+					&sof_irq_enable,
+					sizeof(sof_irq_enable));
+			}
+		}
+	}
+
+	return rc;
+}
+
 static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 {
 	int rc = 0;
@@ -2695,6 +2776,9 @@
 	case CAM_ISP_HW_MGR_CMD_RESUME_HW:
 		cam_ife_mgr_resume_hw(ctx);
 		break;
+	case CAM_ISP_HW_MGR_CMD_SOF_DEBUG:
+		cam_ife_mgr_sof_irq_debug(ctx, hw_cmd_args->u.sof_irq_enable);
+		break;
 	default:
 		CAM_ERR(CAM_ISP, "Invalid HW mgr command:0x%x",
 			hw_cmd_args->cmd_type);
@@ -4218,7 +4302,7 @@
 
 	/* Create Worker for ife_hw_mgr with 10 tasks */
 	rc = cam_req_mgr_workq_create("cam_ife_worker", 10,
-			&g_ife_hw_mgr.workq, CRM_WORKQ_USAGE_NON_IRQ);
+			&g_ife_hw_mgr.workq, CRM_WORKQ_USAGE_NON_IRQ, 0);
 	if (rc < 0) {
 		CAM_ERR(CAM_ISP, "Unable to create worker");
 		goto end;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
index e869e2b..abc6bb0 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c
@@ -70,6 +70,12 @@
 			hw_entry[num_ent].handle = kmd_buf_info->handle;
 			hw_entry[num_ent].len    = get_base.cmd.used_bytes;
 			hw_entry[num_ent].offset = kmd_buf_info->offset;
+			CAM_DBG(CAM_ISP,
+				"num_ent=%d handle=0x%x, len=%u, offset=%u",
+				num_ent,
+				hw_entry[num_ent].handle,
+				hw_entry[num_ent].len,
+				hw_entry[num_ent].offset);
 
 			kmd_buf_info->used_bytes += get_base.cmd.used_bytes;
 			kmd_buf_info->offset     += get_base.cmd.used_bytes;
@@ -184,6 +190,16 @@
 		return -EINVAL;
 	}
 
+	cmd_update.cmd_type = hw_cmd_type;
+	cmd_update.cmd.cmd_buf_addr = cmd_buf_addr;
+	cmd_update.cmd.size = kmd_buf_remain_size;
+	cmd_update.cmd.used_bytes = 0;
+	cmd_update.data = cmd_update_data;
+	CAM_DBG(CAM_ISP, "cmd_type %u cmd buffer 0x%pK, size %d",
+		cmd_update.cmd_type,
+		cmd_update.cmd.cmd_buf_addr,
+		cmd_update.cmd.size);
+
 	for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
 		if (!hw_mgr_res->hw_res[i])
 			continue;
@@ -193,14 +209,7 @@
 
 		res = hw_mgr_res->hw_res[i];
 		cmd_update.res = res;
-		cmd_update.cmd_type = hw_cmd_type;
-		cmd_update.cmd.cmd_buf_addr = cmd_buf_addr;
-		cmd_update.cmd.size = kmd_buf_remain_size;
-		cmd_update.data = cmd_update_data;
 
-		CAM_DBG(CAM_ISP, "cmd buffer 0x%pK, size %d",
-			cmd_update.cmd.cmd_buf_addr,
-			cmd_update.cmd.size);
 		rc = res->hw_intf->hw_ops.process_cmd(
 			res->hw_intf->hw_priv,
 			cmd_update.cmd_type, &cmd_update,
@@ -280,6 +289,12 @@
 				hw_entry[num_ent].handle =
 					cmd_desc[i].mem_handle;
 				hw_entry[num_ent].offset = cmd_desc[i].offset;
+				CAM_DBG(CAM_ISP,
+					"Meta_Left num_ent=%d handle=0x%x, len=%u, offset=%u",
+					num_ent,
+					hw_entry[num_ent].handle,
+					hw_entry[num_ent].len,
+					hw_entry[num_ent].offset);
 
 				if (cmd_meta_data ==
 					CAM_ISP_PACKET_META_DMI_LEFT)
@@ -295,6 +310,12 @@
 				hw_entry[num_ent].handle =
 					cmd_desc[i].mem_handle;
 				hw_entry[num_ent].offset = cmd_desc[i].offset;
+				CAM_DBG(CAM_ISP,
+					"Meta_Right num_ent=%d handle=0x%x, len=%u, offset=%u",
+					num_ent,
+					hw_entry[num_ent].handle,
+					hw_entry[num_ent].len,
+					hw_entry[num_ent].offset);
 
 				if (cmd_meta_data ==
 					CAM_ISP_PACKET_META_DMI_RIGHT)
@@ -308,7 +329,12 @@
 			hw_entry[num_ent].handle =
 				cmd_desc[i].mem_handle;
 			hw_entry[num_ent].offset = cmd_desc[i].offset;
-
+			CAM_DBG(CAM_ISP,
+				"Meta_Common num_ent=%d handle=0x%x, len=%u, offset=%u",
+				num_ent,
+				hw_entry[num_ent].handle,
+				hw_entry[num_ent].len,
+				hw_entry[num_ent].offset);
 			if (cmd_meta_data == CAM_ISP_PACKET_META_DMI_COMMON)
 				hw_entry[num_ent].flags = 0x1;
 
@@ -443,11 +469,12 @@
 
 	for (i = 0; i < prepare->packet->num_io_configs; i++) {
 		CAM_DBG(CAM_ISP, "======= io config idx %d ============", i);
-		CAM_DBG(CAM_ISP, "i %d resource_type:%d fence:%d",
-			i, io_cfg[i].resource_type, io_cfg[i].fence);
-		CAM_DBG(CAM_ISP, "format: %d", io_cfg[i].format);
-		CAM_DBG(CAM_ISP, "direction %d",
+		CAM_DBG(CAM_REQ,
+			"i %d req_id %llu resource_type:%d fence:%d direction %d",
+			i, prepare->packet->header.request_id,
+			io_cfg[i].resource_type, io_cfg[i].fence,
 			io_cfg[i].direction);
+		CAM_DBG(CAM_ISP, "format: %d", io_cfg[i].format);
 
 		if (io_cfg[i].direction == CAM_BUF_OUTPUT) {
 			res_id_out = io_cfg[i].resource_type & 0xFF;
@@ -647,6 +674,12 @@
 		prepare->hw_update_entries[num_ent].len = io_cfg_used_bytes;
 		prepare->hw_update_entries[num_ent].offset =
 			kmd_buf_info->offset;
+		CAM_DBG(CAM_ISP,
+			"num_ent=%d handle=0x%x, len=%u, offset=%u",
+			num_ent,
+			prepare->hw_update_entries[num_ent].handle,
+			prepare->hw_update_entries[num_ent].len,
+			prepare->hw_update_entries[num_ent].offset);
 		num_ent++;
 
 		kmd_buf_info->used_bytes += io_cfg_used_bytes;
@@ -741,6 +774,12 @@
 		prepare->hw_update_entries[num_ent].len = reg_update_size;
 		prepare->hw_update_entries[num_ent].offset =
 			kmd_buf_info->offset;
+		CAM_DBG(CAM_ISP,
+			"num_ent=%d handle=0x%x, len=%u, offset=%u",
+			num_ent,
+			prepare->hw_update_entries[num_ent].handle,
+			prepare->hw_update_entries[num_ent].len,
+			prepare->hw_update_entries[num_ent].offset);
 		num_ent++;
 
 		kmd_buf_info->used_bytes += reg_update_size;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c
index 3a89732..2c08e4d 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/cam_tasklet_util.c
@@ -70,41 +70,44 @@
 	void                              *ctx_priv;
 };
 
-/**
- * cam_tasklet_get_cmd()
- *
- * @brief:              Get free cmd from tasklet
- *
- * @tasklet:            Tasklet Info structure to get cmd from
- * @tasklet_cmd:        Return tasklet_cmd pointer if successful
- *
- * @return:             0: Success
- *                      Negative: Failure
- */
-static int cam_tasklet_get_cmd(
-	struct cam_tasklet_info        *tasklet,
-	struct cam_tasklet_queue_cmd  **tasklet_cmd)
+struct cam_irq_bh_api tasklet_bh_api = {
+	.bottom_half_enqueue_func = cam_tasklet_enqueue_cmd,
+	.get_bh_payload_func = cam_tasklet_get_cmd,
+	.put_bh_payload_func = cam_tasklet_put_cmd,
+};
+
+int cam_tasklet_get_cmd(
+	void                         *bottom_half,
+	void                        **bh_cmd)
 {
 	int           rc = 0;
 	unsigned long flags;
+	struct cam_tasklet_info        *tasklet = bottom_half;
+	struct cam_tasklet_queue_cmd   *tasklet_cmd = NULL;
 
-	*tasklet_cmd = NULL;
+	*bh_cmd = NULL;
+
+	if (tasklet == NULL) {
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "tasklet is NULL");
+		return -EINVAL;
+	}
 
 	if (!atomic_read(&tasklet->tasklet_active)) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "Tasklet is not active!\n");
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "Tasklet is not active");
 		rc = -EPIPE;
 		return rc;
 	}
 
 	spin_lock_irqsave(&tasklet->tasklet_lock, flags);
 	if (list_empty(&tasklet->free_cmd_list)) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP, "No more free tasklet cmd!\n");
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "No more free tasklet cmd");
 		rc = -ENODEV;
 		goto spin_unlock;
 	} else {
-		*tasklet_cmd = list_first_entry(&tasklet->free_cmd_list,
+		tasklet_cmd = list_first_entry(&tasklet->free_cmd_list,
 			struct cam_tasklet_queue_cmd, list);
-		list_del_init(&(*tasklet_cmd)->list);
+		list_del_init(&(tasklet_cmd)->list);
+		*bh_cmd = tasklet_cmd;
 	}
 
 spin_unlock:
@@ -112,25 +115,28 @@
 	return rc;
 }
 
-/**
- * cam_tasklet_put_cmd()
- *
- * @brief:              Put back cmd to free list
- *
- * @tasklet:            Tasklet Info structure to put cmd into
- * @tasklet_cmd:        tasklet_cmd pointer that needs to be put back
- *
- * @return:             Void
- */
-static void cam_tasklet_put_cmd(
-	struct cam_tasklet_info        *tasklet,
-	struct cam_tasklet_queue_cmd  **tasklet_cmd)
+void cam_tasklet_put_cmd(
+	void                         *bottom_half,
+	void                        **bh_cmd)
 {
 	unsigned long flags;
+	struct cam_tasklet_info        *tasklet = bottom_half;
+	struct cam_tasklet_queue_cmd   *tasklet_cmd = *bh_cmd;
+
+	if (tasklet == NULL) {
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "tasklet is NULL");
+		return;
+	}
+
+	if (tasklet_cmd == NULL) {
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "Invalid tasklet_cmd");
+		return;
+	}
 
 	spin_lock_irqsave(&tasklet->tasklet_lock, flags);
-	list_add_tail(&(*tasklet_cmd)->list,
-		&tasklet->free_cmd_list);
+	list_del_init(&tasklet_cmd->list);
+	list_add_tail(&tasklet_cmd->list, &tasklet->free_cmd_list);
+	*bh_cmd = NULL;
 	spin_unlock_irqrestore(&tasklet->tasklet_lock, flags);
 }
 
@@ -157,12 +163,6 @@
 
 	*tasklet_cmd = NULL;
 
-	if (!atomic_read(&tasklet->tasklet_active)) {
-		CAM_ERR(CAM_ISP, "Tasklet is not active!");
-		rc = -EPIPE;
-		return rc;
-	}
-
 	CAM_DBG(CAM_ISP, "Dequeue before lock.");
 	spin_lock_irqsave(&tasklet->tasklet_lock, flags);
 	if (list_empty(&tasklet->used_cmd_list)) {
@@ -181,38 +181,40 @@
 	return rc;
 }
 
-int cam_tasklet_enqueue_cmd(
+void cam_tasklet_enqueue_cmd(
 	void                              *bottom_half,
+	void                              *bh_cmd,
 	void                              *handler_priv,
 	void                              *evt_payload_priv,
 	CAM_IRQ_HANDLER_BOTTOM_HALF        bottom_half_handler)
 {
-	struct cam_tasklet_info       *tasklet = bottom_half;
-	struct cam_tasklet_queue_cmd  *tasklet_cmd = NULL;
 	unsigned long                  flags;
-	int                            rc;
+	struct cam_tasklet_queue_cmd  *tasklet_cmd = bh_cmd;
+	struct cam_tasklet_info       *tasklet = bottom_half;
 
 	if (!bottom_half) {
-		CAM_ERR(CAM_ISP, "NULL bottom half");
-		return -EINVAL;
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "NULL bottom half");
+		return;
 	}
 
-	rc = cam_tasklet_get_cmd(tasklet, &tasklet_cmd);
-
-	if (tasklet_cmd) {
-		CAM_DBG(CAM_ISP, "Enqueue tasklet cmd");
-		tasklet_cmd->bottom_half_handler = bottom_half_handler;
-		tasklet_cmd->payload = evt_payload_priv;
-		spin_lock_irqsave(&tasklet->tasklet_lock, flags);
-		list_add_tail(&tasklet_cmd->list,
-			&tasklet->used_cmd_list);
-		spin_unlock_irqrestore(&tasklet->tasklet_lock, flags);
-		tasklet_schedule(&tasklet->tasklet);
-	} else {
-		CAM_ERR(CAM_ISP, "tasklet cmd is NULL!");
+	if (!bh_cmd) {
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "NULL bh cmd");
+		return;
 	}
 
-	return rc;
+	if (!atomic_read(&tasklet->tasklet_active)) {
+		CAM_ERR_RATE_LIMIT(CAM_ISP, "Tasklet is not active\n");
+		return;
+	}
+
+	CAM_DBG(CAM_ISP, "Enqueue tasklet cmd");
+	tasklet_cmd->bottom_half_handler = bottom_half_handler;
+	tasklet_cmd->payload = evt_payload_priv;
+	spin_lock_irqsave(&tasklet->tasklet_lock, flags);
+	list_add_tail(&tasklet_cmd->list,
+		&tasklet->used_cmd_list);
+	spin_unlock_irqrestore(&tasklet->tasklet_lock, flags);
+	tasklet_schedule(&tasklet->tasklet);
 }
 
 int cam_tasklet_init(
@@ -244,7 +246,7 @@
 	}
 	tasklet_init(&tasklet->tasklet, cam_tasklet_action,
 		(unsigned long)tasklet);
-	cam_tasklet_stop(tasklet);
+	tasklet_disable(&tasklet->tasklet);
 
 	*tasklet_info = tasklet;
 
@@ -255,19 +257,18 @@
 {
 	struct cam_tasklet_info *tasklet = *tasklet_info;
 
-	atomic_set(&tasklet->tasklet_active, 0);
-	tasklet_kill(&tasklet->tasklet);
+	if (atomic_read(&tasklet->tasklet_active)) {
+		atomic_set(&tasklet->tasklet_active, 0);
+		tasklet_kill(&tasklet->tasklet);
+		tasklet_disable(&tasklet->tasklet);
+	}
 	kfree(tasklet);
 	*tasklet_info = NULL;
 }
 
-static void cam_tasklet_flush(void  *tasklet_info)
+static inline void cam_tasklet_flush(struct cam_tasklet_info *tasklet_info)
 {
-	unsigned long data;
-	struct cam_tasklet_info *tasklet = tasklet_info;
-
-	data = (unsigned long)tasklet;
-	cam_tasklet_action(data);
+	cam_tasklet_action((unsigned long) tasklet_info);
 }
 
 int cam_tasklet_start(void  *tasklet_info)
@@ -280,7 +281,6 @@
 			tasklet->index);
 		return -EBUSY;
 	}
-	atomic_set(&tasklet->tasklet_active, 1);
 
 	/* clean up the command queue first */
 	for (i = 0; i < CAM_TASKLETQ_SIZE; i++) {
@@ -289,6 +289,8 @@
 			&tasklet->free_cmd_list);
 	}
 
+	atomic_set(&tasklet->tasklet_active, 1);
+
 	tasklet_enable(&tasklet->tasklet);
 
 	return 0;
@@ -298,9 +300,10 @@
 {
 	struct cam_tasklet_info  *tasklet = tasklet_info;
 
-	cam_tasklet_flush(tasklet);
 	atomic_set(&tasklet->tasklet_active, 0);
+	tasklet_kill(&tasklet->tasklet);
 	tasklet_disable(&tasklet->tasklet);
+	cam_tasklet_flush(tasklet);
 }
 
 /*
@@ -323,7 +326,7 @@
 	while (!cam_tasklet_dequeue_cmd(tasklet_info, &tasklet_cmd)) {
 		tasklet_cmd->bottom_half_handler(tasklet_info->ctx_priv,
 			tasklet_cmd->payload);
-		cam_tasklet_put_cmd(tasklet_info, &tasklet_cmd);
+		cam_tasklet_put_cmd(tasklet_info, (void **)(&tasklet_cmd));
 	}
 }
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include/cam_tasklet_util.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include/cam_tasklet_util.h
index 0e4bf12..8bd93d8 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include/cam_tasklet_util.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/include/cam_tasklet_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
@@ -76,6 +76,7 @@
  * @brief:               Enqueue the tasklet_cmd to used list
  *
  * @bottom_half:         Tasklet info to enqueue onto
+ * @bh_cmd:              Tasklet cmd used to enqueue task
  * @handler_priv:        Private Handler data that will be passed to the
  *                       handler function
  * @evt_payload_priv:    Event payload that will be passed to the handler
@@ -83,13 +84,40 @@
  * @bottom_half_handler: Callback function that will be called by tasklet
  *                       for handling event
  *
- * @return:              0: Success
- *                       Negative: Failure
+ * @return:              Void
  */
-int cam_tasklet_enqueue_cmd(
+void cam_tasklet_enqueue_cmd(
 	void                              *bottom_half,
+	void                              *bh_cmd,
 	void                              *handler_priv,
 	void                              *evt_payload_priv,
 	CAM_IRQ_HANDLER_BOTTOM_HALF        bottom_half_handler);
 
+/**
+ * cam_tasklet_get_cmd()
+ *
+ * @brief:              Get free cmd from tasklet
+ *
+ * @bottom_half:        Tasklet Info structure to get cmd from
+ * @bh_cmd:             Return tasklet_cmd pointer if successful
+ *
+ * @return:             0: Success
+ *                      Negative: Failure
+ */
+int cam_tasklet_get_cmd(void *bottom_half, void **bh_cmd);
+
+/**
+ * cam_tasklet_put_cmd()
+ *
+ * @brief:              Put back cmd to free list
+ *
+ * @bottom_half:        Tasklet Info structure to put cmd into
+ * @bh_cmd:             tasklet_cmd pointer that needs to be put back
+ *
+ * @return:             Void
+ */
+void cam_tasklet_put_cmd(void *bottom_half, void **bh_cmd);
+
+extern struct cam_irq_bh_api tasklet_bh_api;
+
 #endif /* _CAM_TASKLET_UTIL_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
index feb79cc..e418fa9 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.c
@@ -13,6 +13,8 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
+#include <linux/ratelimit.h>
+
 #include "cam_io_util.h"
 #include "cam_irq_controller.h"
 #include "cam_debug_util.h"
@@ -42,7 +44,7 @@
 	CAM_IRQ_HANDLER_TOP_HALF           top_half_handler;
 	CAM_IRQ_HANDLER_BOTTOM_HALF        bottom_half_handler;
 	void                              *bottom_half;
-	CAM_IRQ_BOTTOM_HALF_ENQUEUE_FUNC   bottom_half_enqueue_func;
+	struct cam_irq_bh_api              irq_bh_api;
 	struct list_head                   list_node;
 	struct list_head                   th_list_node;
 	int                                index;
@@ -139,21 +141,21 @@
 
 	if (!register_info->num_registers || !register_info->irq_reg_set ||
 		!name || !mem_base) {
-		CAM_ERR(CAM_ISP, "Invalid parameters");
+		CAM_ERR(CAM_IRQ_CTRL, "Invalid parameters");
 		rc = -EINVAL;
 		return rc;
 	}
 
 	controller = kzalloc(sizeof(struct cam_irq_controller), GFP_KERNEL);
 	if (!controller) {
-		CAM_DBG(CAM_ISP, "Failed to allocate IRQ Controller");
+		CAM_DBG(CAM_IRQ_CTRL, "Failed to allocate IRQ Controller");
 		return -ENOMEM;
 	}
 
 	controller->irq_register_arr = kzalloc(register_info->num_registers *
 		sizeof(struct cam_irq_register_obj), GFP_KERNEL);
 	if (!controller->irq_register_arr) {
-		CAM_DBG(CAM_ISP, "Failed to allocate IRQ register Arr");
+		CAM_DBG(CAM_IRQ_CTRL, "Failed to allocate IRQ register Arr");
 		rc = -ENOMEM;
 		goto reg_alloc_error;
 	}
@@ -161,7 +163,7 @@
 	controller->irq_status_arr = kzalloc(register_info->num_registers *
 		sizeof(uint32_t), GFP_KERNEL);
 	if (!controller->irq_status_arr) {
-		CAM_DBG(CAM_ISP, "Failed to allocate IRQ status Arr");
+		CAM_DBG(CAM_IRQ_CTRL, "Failed to allocate IRQ status Arr");
 		rc = -ENOMEM;
 		goto status_alloc_error;
 	}
@@ -170,14 +172,16 @@
 		kzalloc(register_info->num_registers * sizeof(uint32_t),
 		GFP_KERNEL);
 	if (!controller->th_payload.evt_status_arr) {
-		CAM_DBG(CAM_ISP, "Failed to allocate BH payload bit mask Arr");
+		CAM_DBG(CAM_IRQ_CTRL,
+			"Failed to allocate BH payload bit mask Arr");
 		rc = -ENOMEM;
 		goto evt_mask_alloc_error;
 	}
 
 	controller->name = name;
 
-	CAM_DBG(CAM_ISP, "num_registers: %d", register_info->num_registers);
+	CAM_DBG(CAM_IRQ_CTRL, "num_registers: %d",
+		register_info->num_registers);
 	for (i = 0; i < register_info->num_registers; i++) {
 		controller->irq_register_arr[i].index = i;
 		controller->irq_register_arr[i].mask_reg_offset =
@@ -186,11 +190,11 @@
 			register_info->irq_reg_set[i].clear_reg_offset;
 		controller->irq_register_arr[i].status_reg_offset =
 			register_info->irq_reg_set[i].status_reg_offset;
-		CAM_DBG(CAM_ISP, "i %d mask_reg_offset: 0x%x", i,
+		CAM_DBG(CAM_IRQ_CTRL, "i %d mask_reg_offset: 0x%x", i,
 			controller->irq_register_arr[i].mask_reg_offset);
-		CAM_DBG(CAM_ISP, "i %d clear_reg_offset: 0x%x", i,
+		CAM_DBG(CAM_IRQ_CTRL, "i %d clear_reg_offset: 0x%x", i,
 			controller->irq_register_arr[i].clear_reg_offset);
-		CAM_DBG(CAM_ISP, "i %d status_reg_offset: 0x%x", i,
+		CAM_DBG(CAM_IRQ_CTRL, "i %d status_reg_offset: 0x%x", i,
 			controller->irq_register_arr[i].status_reg_offset);
 	}
 	controller->num_registers        = register_info->num_registers;
@@ -198,11 +202,12 @@
 	controller->global_clear_offset  = register_info->global_clear_offset;
 	controller->mem_base             = mem_base;
 
-	CAM_DBG(CAM_ISP, "global_clear_bitmask: 0x%x",
+	CAM_DBG(CAM_IRQ_CTRL, "global_clear_bitmask: 0x%x",
 		controller->global_clear_bitmask);
-	CAM_DBG(CAM_ISP, "global_clear_offset: 0x%x",
+	CAM_DBG(CAM_IRQ_CTRL, "global_clear_offset: 0x%x",
 		controller->global_clear_offset);
-	CAM_DBG(CAM_ISP, "mem_base: %pK", (void __iomem *)controller->mem_base);
+	CAM_DBG(CAM_IRQ_CTRL, "mem_base: %pK",
+		(void __iomem *)controller->mem_base);
 
 	INIT_LIST_HEAD(&controller->evt_handler_list_head);
 	for (i = 0; i < CAM_IRQ_PRIORITY_MAX; i++)
@@ -232,7 +237,7 @@
 	CAM_IRQ_HANDLER_TOP_HALF           top_half_handler,
 	CAM_IRQ_HANDLER_BOTTOM_HALF        bottom_half_handler,
 	void                              *bottom_half,
-	CAM_IRQ_BOTTOM_HALF_ENQUEUE_FUNC   bottom_half_enqueue_func)
+	struct cam_irq_bh_api             *irq_bh_api)
 {
 	struct cam_irq_controller  *controller  = irq_controller;
 	struct cam_irq_evt_handler *evt_handler = NULL;
@@ -243,43 +248,55 @@
 	bool                        need_lock;
 
 	if (!controller || !handler_priv || !evt_bit_mask_arr) {
-		CAM_ERR(CAM_ISP,
+		CAM_ERR(CAM_IRQ_CTRL,
 			"Inval params: ctlr=%pK hdl_priv=%pK bit_mask_arr=%pK",
 			controller, handler_priv, evt_bit_mask_arr);
 		return -EINVAL;
 	}
 
 	if (!top_half_handler) {
-		CAM_ERR(CAM_ISP, "Missing top half handler");
+		CAM_ERR(CAM_IRQ_CTRL, "Missing top half handler");
 		return -EINVAL;
 	}
 
 	if (bottom_half_handler &&
-		(!bottom_half || !bottom_half_enqueue_func)) {
-		CAM_ERR(CAM_ISP,
+		(!bottom_half || !irq_bh_api)) {
+		CAM_ERR(CAM_IRQ_CTRL,
 			"Invalid params: bh_handler=%pK bh=%pK bh_enq_f=%pK",
 			bottom_half_handler,
 			bottom_half,
-			bottom_half_enqueue_func);
+			irq_bh_api);
+		return -EINVAL;
+	}
+
+	if (irq_bh_api &&
+		(!irq_bh_api->bottom_half_enqueue_func ||
+		!irq_bh_api->get_bh_payload_func ||
+		!irq_bh_api->put_bh_payload_func)) {
+		CAM_ERR(CAM_IRQ_CTRL,
+			"Invalid: enqueue_func=%pK get_bh=%pK put_bh=%pK",
+			irq_bh_api->bottom_half_enqueue_func,
+			irq_bh_api->get_bh_payload_func,
+			irq_bh_api->put_bh_payload_func);
 		return -EINVAL;
 	}
 
 	if (priority >= CAM_IRQ_PRIORITY_MAX) {
-		CAM_ERR(CAM_ISP, "Invalid priority=%u, max=%u", priority,
+		CAM_ERR(CAM_IRQ_CTRL, "Invalid priority=%u, max=%u", priority,
 			CAM_IRQ_PRIORITY_MAX);
 		return -EINVAL;
 	}
 
 	evt_handler = kzalloc(sizeof(struct cam_irq_evt_handler), GFP_KERNEL);
 	if (!evt_handler) {
-		CAM_DBG(CAM_ISP, "Error allocating hlist_node");
+		CAM_DBG(CAM_IRQ_CTRL, "Error allocating hlist_node");
 		return -ENOMEM;
 	}
 
 	evt_handler->evt_bit_mask_arr = kzalloc(sizeof(uint32_t) *
 		controller->num_registers, GFP_KERNEL);
 	if (!evt_handler->evt_bit_mask_arr) {
-		CAM_DBG(CAM_ISP, "Error allocating hlist_node");
+		CAM_DBG(CAM_IRQ_CTRL, "Error allocating hlist_node");
 		rc = -ENOMEM;
 		goto free_evt_handler;
 	}
@@ -295,9 +312,11 @@
 	evt_handler->top_half_handler         = top_half_handler;
 	evt_handler->bottom_half_handler      = bottom_half_handler;
 	evt_handler->bottom_half              = bottom_half;
-	evt_handler->bottom_half_enqueue_func = bottom_half_enqueue_func;
 	evt_handler->index                    = controller->hdl_idx++;
 
+	if (irq_bh_api)
+		evt_handler->irq_bh_api       = *irq_bh_api;
+
 	/* Avoid rollover to negative values */
 	if (controller->hdl_idx > 0x3FFFFFFF)
 		controller->hdl_idx = 1;
@@ -358,7 +377,7 @@
 	list_for_each_entry_safe(evt_handler, evt_handler_temp,
 		&controller->evt_handler_list_head, list_node) {
 		if (evt_handler->index == handle) {
-			CAM_DBG(CAM_ISP, "enable item %d", handle);
+			CAM_DBG(CAM_IRQ_CTRL, "enable item %d", handle);
 			found = 1;
 			rc = 0;
 			break;
@@ -414,7 +433,7 @@
 	list_for_each_entry_safe(evt_handler, evt_handler_temp,
 		&controller->evt_handler_list_head, list_node) {
 		if (evt_handler->index == handle) {
-			CAM_DBG(CAM_ISP, "disable item %d", handle);
+			CAM_DBG(CAM_IRQ_CTRL, "disable item %d", handle);
 			found = 1;
 			rc = 0;
 			break;
@@ -435,13 +454,13 @@
 
 		irq_mask = cam_io_r_mb(controller->mem_base +
 			irq_register->mask_reg_offset);
-		CAM_DBG(CAM_ISP, "irq_mask 0x%x before disable 0x%x",
+		CAM_DBG(CAM_IRQ_CTRL, "irq_mask 0x%x before disable 0x%x",
 			irq_register->mask_reg_offset, irq_mask);
 		irq_mask &= ~(evt_handler->evt_bit_mask_arr[i]);
 
 		cam_io_w_mb(irq_mask, controller->mem_base +
 			irq_register->mask_reg_offset);
-		CAM_DBG(CAM_ISP, "irq_mask 0x%x after disable 0x%x",
+		CAM_DBG(CAM_IRQ_CTRL, "irq_mask 0x%x after disable 0x%x",
 			irq_register->mask_reg_offset, irq_mask);
 
 		/* Clear the IRQ bits of this handler */
@@ -483,7 +502,7 @@
 	list_for_each_entry_safe(evt_handler, evt_handler_temp,
 		&controller->evt_handler_list_head, list_node) {
 		if (evt_handler->index == handle) {
-			CAM_DBG(CAM_ISP, "unsubscribe item %d", handle);
+			CAM_DBG(CAM_IRQ_CTRL, "unsubscribe item %d", handle);
 			list_del_init(&evt_handler->list_node);
 			list_del_init(&evt_handler->th_list_node);
 			found = 1;
@@ -564,8 +583,10 @@
 	bool                            is_irq_match;
 	int                             rc = -EINVAL;
 	int                             i;
+	void                           *bh_cmd = NULL;
+	struct cam_irq_bh_api          *irq_bh_api = NULL;
 
-	CAM_DBG(CAM_ISP, "Enter");
+	CAM_DBG(CAM_IRQ_CTRL, "Enter");
 
 	if (list_empty(th_list_head))
 		return;
@@ -577,7 +598,7 @@
 		if (!is_irq_match)
 			continue;
 
-		CAM_DBG(CAM_ISP, "match found");
+		CAM_DBG(CAM_IRQ_CTRL, "match found");
 
 		cam_irq_th_payload_init(th_payload);
 		th_payload->handler_priv  = evt_handler->handler_priv;
@@ -588,6 +609,19 @@
 				evt_handler->evt_bit_mask_arr[i];
 		}
 
+		irq_bh_api = &evt_handler->irq_bh_api;
+		bh_cmd = NULL;
+
+		if (evt_handler->bottom_half_handler) {
+			rc = irq_bh_api->get_bh_payload_func(
+				evt_handler->bottom_half, &bh_cmd);
+			if (rc || !bh_cmd) {
+				CAM_ERR_RATE_LIMIT(CAM_ISP,
+					"Can't get bh payload");
+				continue;
+			}
+		}
+
 		/*
 		 * irq_status_arr[0] is dummy argument passed. the entire
 		 * status array is passed in th_payload.
@@ -597,20 +631,25 @@
 				controller->irq_status_arr[0],
 				(void *)th_payload);
 
-		if (!rc && evt_handler->bottom_half_handler) {
-			CAM_DBG(CAM_ISP, "Enqueuing bottom half for %s",
+		if (rc && bh_cmd) {
+			irq_bh_api->put_bh_payload_func(
+				evt_handler->bottom_half, &bh_cmd);
+			continue;
+		}
+
+		if (evt_handler->bottom_half_handler) {
+			CAM_DBG(CAM_IRQ_CTRL, "Enqueuing bottom half for %s",
 				controller->name);
-			if (evt_handler->bottom_half_enqueue_func) {
-				evt_handler->bottom_half_enqueue_func(
-					evt_handler->bottom_half,
-					evt_handler->handler_priv,
-					th_payload->evt_payload_priv,
-					evt_handler->bottom_half_handler);
-			}
+			irq_bh_api->bottom_half_enqueue_func(
+				evt_handler->bottom_half,
+				bh_cmd,
+				evt_handler->handler_priv,
+				th_payload->evt_payload_priv,
+				evt_handler->bottom_half_handler);
 		}
 	}
 
-	CAM_DBG(CAM_ISP, "Exit");
+	CAM_DBG(CAM_IRQ_CTRL, "Exit");
 }
 
 irqreturn_t cam_irq_controller_clear_and_mask(int irq_num, void *priv)
@@ -651,7 +690,7 @@
 	if (!controller)
 		return IRQ_NONE;
 
-	CAM_DBG(CAM_ISP, "locking controller %pK name %s lock %pK",
+	CAM_DBG(CAM_IRQ_CTRL, "locking controller %pK name %s lock %pK",
 		controller, controller->name, &controller->lock);
 	spin_lock(&controller->lock);
 	for (i = 0; i < controller->num_registers; i++) {
@@ -662,36 +701,36 @@
 		cam_io_w_mb(controller->irq_status_arr[i],
 			controller->mem_base +
 			controller->irq_register_arr[i].clear_reg_offset);
-		CAM_DBG(CAM_ISP, "Read irq status%d (0x%x) = 0x%x", i,
+		CAM_DBG(CAM_IRQ_CTRL, "Read irq status%d (0x%x) = 0x%x", i,
 			controller->irq_register_arr[i].status_reg_offset,
 			controller->irq_status_arr[i]);
 		for (j = 0; j < CAM_IRQ_PRIORITY_MAX; j++) {
 			if (irq_register->top_half_enable_mask[j] &
 				controller->irq_status_arr[i])
 				need_th_processing[j] = true;
-				CAM_DBG(CAM_ISP,
+				CAM_DBG(CAM_IRQ_CTRL,
 					"i %d j %d need_th_processing = %d",
 					i, j, need_th_processing[j]);
 		}
 	}
 
-	CAM_DBG(CAM_ISP, "Status Registers read Successful");
+	CAM_DBG(CAM_IRQ_CTRL, "Status Registers read Successful");
 
 	if (controller->global_clear_offset)
 		cam_io_w_mb(controller->global_clear_bitmask,
 			controller->mem_base + controller->global_clear_offset);
 
-	CAM_DBG(CAM_ISP, "Status Clear done");
+	CAM_DBG(CAM_IRQ_CTRL, "Status Clear done");
 
 	for (i = 0; i < CAM_IRQ_PRIORITY_MAX; i++) {
 		if (need_th_processing[i]) {
-			CAM_DBG(CAM_ISP, "Invoke TH processing");
+			CAM_DBG(CAM_IRQ_CTRL, "Invoke TH processing");
 			cam_irq_controller_th_processing(controller,
 				&controller->th_list_head[i]);
 		}
 	}
 	spin_unlock(&controller->lock);
-	CAM_DBG(CAM_ISP, "unlocked controller %pK name %s lock %pK",
+	CAM_DBG(CAM_IRQ_CTRL, "unlocked controller %pK name %s lock %pK",
 		controller, controller->name, &controller->lock);
 
 	return IRQ_HANDLED;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h
index e3071ac..c3c1e7c 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/hw_utils/irq_controller/cam_irq_controller.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
@@ -111,10 +111,22 @@
 typedef int (*CAM_IRQ_HANDLER_BOTTOM_HALF)(void *handler_priv,
 	void *evt_payload_priv);
 
-typedef int (*CAM_IRQ_BOTTOM_HALF_ENQUEUE_FUNC)(void *bottom_half,
-	void *handler_priv, void *evt_payload_priv,
+typedef void (*CAM_IRQ_BOTTOM_HALF_ENQUEUE_FUNC)(void *bottom_half,
+	void *bh_cmd, void *handler_priv, void *evt_payload_priv,
 	CAM_IRQ_HANDLER_BOTTOM_HALF);
 
+typedef int (*CAM_IRQ_GET_TASKLET_PAYLOAD_FUNC)(void *bottom_half,
+	void **bh_cmd);
+
+typedef void (*CAM_IRQ_PUT_TASKLET_PAYLOAD_FUNC)(void *bottom_half,
+	void **bh_cmd);
+
+struct cam_irq_bh_api {
+	CAM_IRQ_BOTTOM_HALF_ENQUEUE_FUNC bottom_half_enqueue_func;
+	CAM_IRQ_GET_TASKLET_PAYLOAD_FUNC get_bh_payload_func;
+	CAM_IRQ_PUT_TASKLET_PAYLOAD_FUNC put_bh_payload_func;
+};
+
 /*
  * cam_irq_controller_init()
  *
@@ -165,7 +177,7 @@
 	CAM_IRQ_HANDLER_TOP_HALF           top_half_handler,
 	CAM_IRQ_HANDLER_BOTTOM_HALF        bottom_half_handler,
 	void                              *bottom_half,
-	CAM_IRQ_BOTTOM_HALF_ENQUEUE_FUNC   bottom_half_enqueue_func);
+	struct cam_irq_bh_api             *irq_bh_api);
 
 /*
  * cam_irq_controller_unsubscribe_irq()
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 5410858..8f1911e 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
@@ -180,6 +180,7 @@
 	CAM_ISP_HW_MGR_CMD_IS_RDI_ONLY_CONTEXT,
 	CAM_ISP_HW_MGR_CMD_PAUSE_HW,
 	CAM_ISP_HW_MGR_CMD_RESUME_HW,
+	CAM_ISP_HW_MGR_CMD_SOF_DEBUG,
 	CAM_ISP_HW_MGR_CMD_MAX,
 };
 
@@ -195,6 +196,7 @@
 	uint32_t                            cmd_type;
 	union {
 		uint32_t                      is_rdi_only_context;
+		uint32_t                      sof_irq_enable;
 	} u;
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.c
index bdd59d2..70223f1 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.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
@@ -41,6 +41,7 @@
 		.name = CAM_CSID_DRV_NAME,
 		.owner = THIS_MODULE,
 		.of_match_table = cam_ife_csid170_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
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 3edae4a..e5fb03f 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
@@ -20,6 +20,7 @@
 #include "cam_soc_util.h"
 #include "cam_io_util.h"
 #include "cam_debug_util.h"
+#include "cam_cpas_api.h"
 
 /* Timeout value in msec */
 #define IFE_CSID_TIMEOUT                               1000
@@ -286,67 +287,49 @@
 }
 
 static int cam_ife_csid_cid_get(struct cam_ife_csid_hw *csid_hw,
-	struct cam_isp_resource_node **res, int32_t vc, uint32_t dt,
-	uint32_t res_type)
+	struct cam_isp_resource_node **res, int32_t vc, uint32_t dt)
 {
-	int  rc = 0;
 	struct cam_ife_csid_cid_data    *cid_data;
-	uint32_t  i = 0, j = 0;
+	uint32_t  i = 0;
 
+	*res = NULL;
+
+	/* Return already reserved CID if the VC/DT matches */
 	for (i = 0; i < CAM_IFE_CSID_CID_RES_MAX; i++) {
 		if (csid_hw->cid_res[i].res_state >=
 			CAM_ISP_RESOURCE_STATE_RESERVED) {
 			cid_data = (struct cam_ife_csid_cid_data *)
 				csid_hw->cid_res[i].res_priv;
-			if (res_type == CAM_ISP_IFE_IN_RES_TPG) {
-				if (cid_data->tpg_set) {
-					cid_data->cnt++;
-					*res = &csid_hw->cid_res[i];
-					break;
-				}
-			} else {
-				if (cid_data->vc == vc && cid_data->dt == dt) {
-					cid_data->cnt++;
-					*res = &csid_hw->cid_res[i];
-					break;
-				}
+			if (cid_data->vc == vc && cid_data->dt == dt) {
+				cid_data->cnt++;
+				*res = &csid_hw->cid_res[i];
+				return 0;
 			}
 		}
 	}
 
-	if (i == CAM_IFE_CSID_CID_RES_MAX) {
-		if (res_type == CAM_ISP_IFE_IN_RES_TPG) {
-			CAM_ERR(CAM_ISP, "CSID:%d TPG CID not available",
-				 csid_hw->hw_intf->hw_idx);
-			rc = -EINVAL;
-		}
-
-		for (j = 0; j < CAM_IFE_CSID_CID_RES_MAX; j++) {
-			if (csid_hw->cid_res[j].res_state ==
-				CAM_ISP_RESOURCE_STATE_AVAILABLE) {
-				cid_data = (struct cam_ife_csid_cid_data *)
-					csid_hw->cid_res[j].res_priv;
-				cid_data->vc  = vc;
-				cid_data->dt  = dt;
-				cid_data->cnt = 1;
-				csid_hw->cid_res[j].res_state =
-					CAM_ISP_RESOURCE_STATE_RESERVED;
-				*res = &csid_hw->cid_res[j];
-				CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated",
-					csid_hw->hw_intf->hw_idx,
-					csid_hw->cid_res[j].res_id);
-				break;
-			}
-		}
-
-		if (j == CAM_IFE_CSID_CID_RES_MAX) {
-			CAM_ERR(CAM_ISP, "CSID:%d Free cid is not available",
-				 csid_hw->hw_intf->hw_idx);
-			rc = -EINVAL;
+	for (i = 0; i < CAM_IFE_CSID_CID_RES_MAX; i++) {
+		if (csid_hw->cid_res[i].res_state ==
+			CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+			cid_data = (struct cam_ife_csid_cid_data *)
+				csid_hw->cid_res[i].res_priv;
+			cid_data->vc  = vc;
+			cid_data->dt  = dt;
+			cid_data->cnt = 1;
+			csid_hw->cid_res[i].res_state =
+				CAM_ISP_RESOURCE_STATE_RESERVED;
+			*res = &csid_hw->cid_res[i];
+			CAM_DBG(CAM_ISP, "CSID:%d CID %d allocated",
+				csid_hw->hw_intf->hw_idx,
+				csid_hw->cid_res[i].res_id);
+			return 0;
 		}
 	}
 
-	return rc;
+	CAM_ERR(CAM_ISP, "CSID:%d Free cid is not available",
+		 csid_hw->hw_intf->hw_idx);
+
+	return -EINVAL;
 }
 
 
@@ -547,6 +530,7 @@
 {
 	int rc = 0;
 	struct cam_ife_csid_cid_data       *cid_data;
+	uint32_t camera_hw_version;
 
 	CAM_DBG(CAM_ISP,
 		"CSID:%d res_sel:0x%x Lane type:%d lane_num:%d dt:%d vc:%d",
@@ -614,12 +598,40 @@
 		goto end;
 	}
 
-	if (cid_reserv->in_port->res_type == CAM_ISP_IFE_IN_RES_PHY_3 &&
-		csid_hw->hw_intf->hw_idx != 2) {
+	if (csid_hw->csi2_reserve_cnt == UINT_MAX) {
+		CAM_ERR(CAM_ISP,
+			"CSID%d reserve cnt reached max",
+			csid_hw->hw_intf->hw_idx);
 		rc = -EINVAL;
 		goto end;
 	}
 
+	rc = cam_cpas_get_cpas_hw_version(&camera_hw_version);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "Failed to get HW version rc:%d", rc);
+		goto end;
+	}
+	CAM_DBG(CAM_ISP, "HW version: %d", camera_hw_version);
+
+	switch (camera_hw_version) {
+	case CAM_CPAS_TITAN_NONE:
+	case CAM_CPAS_TITAN_MAX:
+		CAM_ERR(CAM_ISP, "Invalid HW version: %d", camera_hw_version);
+		break;
+	case CAM_CPAS_TITAN_170_V100:
+	case CAM_CPAS_TITAN_170_V110:
+	case CAM_CPAS_TITAN_170_V120:
+		if (cid_reserv->in_port->res_type == CAM_ISP_IFE_IN_RES_PHY_3 &&
+			csid_hw->hw_intf->hw_idx != 2) {
+			rc = -EINVAL;
+			goto end;
+		}
+		break;
+	default:
+		break;
+	}
+	CAM_DBG(CAM_ISP, "Reserve_cnt %u", csid_hw->csi2_reserve_cnt);
+
 	if (csid_hw->csi2_reserve_cnt) {
 		/* current configure res type should match requested res type */
 		if (csid_hw->res_type != cid_reserv->in_port->res_type) {
@@ -652,12 +664,53 @@
 		}
 	}
 
+	switch (cid_reserv->res_id) {
+	case CAM_IFE_PIX_PATH_RES_IPP:
+		if (csid_hw->ipp_res.res_state !=
+			CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+			CAM_DBG(CAM_ISP,
+				"CSID:%d IPP resource not available",
+				csid_hw->hw_intf->hw_idx);
+			rc = -EINVAL;
+			goto end;
+		}
+		break;
+	case CAM_IFE_PIX_PATH_RES_RDI_0:
+	case CAM_IFE_PIX_PATH_RES_RDI_1:
+	case CAM_IFE_PIX_PATH_RES_RDI_2:
+	case CAM_IFE_PIX_PATH_RES_RDI_3:
+		if (csid_hw->rdi_res[cid_reserv->res_id].res_state !=
+			CAM_ISP_RESOURCE_STATE_AVAILABLE) {
+			CAM_ERR(CAM_ISP,
+				"CSID:%d RDI:%d resource not available",
+				csid_hw->hw_intf->hw_idx,
+				cid_reserv->res_id);
+			rc = -EINVAL;
+			goto end;
+		}
+		break;
+	default:
+		CAM_ERR(CAM_ISP, "CSID%d: Invalid csid path",
+			csid_hw->hw_intf->hw_idx);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	rc = cam_ife_csid_cid_get(csid_hw,
+		&cid_reserv->node_res,
+		cid_reserv->in_port->vc,
+		cid_reserv->in_port->dt);
+	if (rc) {
+		CAM_ERR(CAM_ISP, "CSID:%d CID Reserve failed res_type %d",
+			csid_hw->hw_intf->hw_idx,
+			cid_reserv->in_port->res_type);
+		goto end;
+	}
+	cid_data = (struct cam_ife_csid_cid_data *)
+		cid_reserv->node_res->res_priv;
+
 	if (!csid_hw->csi2_reserve_cnt) {
 		csid_hw->res_type = cid_reserv->in_port->res_type;
-		/* Take the first CID resource*/
-		csid_hw->cid_res[0].res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
-		cid_data = (struct cam_ife_csid_cid_data *)
-				csid_hw->cid_res[0].res_priv;
 
 		csid_hw->csi2_rx_cfg.lane_cfg =
 			cid_reserv->in_port->lane_cfg;
@@ -699,71 +752,13 @@
 			csid_hw->csi2_rx_cfg.phy_sel =
 				(cid_reserv->in_port->res_type & 0xFF) - 1;
 		}
-
-		cid_data->vc = cid_reserv->in_port->vc;
-		cid_data->dt = cid_reserv->in_port->dt;
-		cid_data->cnt = 1;
-		cid_reserv->node_res = &csid_hw->cid_res[0];
-		csid_hw->csi2_reserve_cnt++;
-
-		CAM_DBG(CAM_ISP,
-			"CSID:%d CID :%d resource acquired successfully",
-			csid_hw->hw_intf->hw_idx,
-			cid_reserv->node_res->res_id);
-	} else {
-		switch (cid_reserv->res_id) {
-		case CAM_IFE_PIX_PATH_RES_IPP:
-			if (csid_hw->ipp_res.res_state !=
-				CAM_ISP_RESOURCE_STATE_AVAILABLE) {
-				CAM_DBG(CAM_ISP,
-					"CSID:%d IPP resource not available",
-					csid_hw->hw_intf->hw_idx);
-				rc = -EINVAL;
-				goto end;
-			}
-			break;
-		case CAM_IFE_PIX_PATH_RES_RDI_0:
-		case CAM_IFE_PIX_PATH_RES_RDI_1:
-		case CAM_IFE_PIX_PATH_RES_RDI_2:
-		case CAM_IFE_PIX_PATH_RES_RDI_3:
-			if (csid_hw->rdi_res[cid_reserv->res_id].res_state !=
-				CAM_ISP_RESOURCE_STATE_AVAILABLE) {
-				CAM_DBG(CAM_ISP,
-					"CSID:%d RDI:%d resource not available",
-					csid_hw->hw_intf->hw_idx,
-					cid_reserv->res_id);
-				rc = -EINVAL;
-				goto end;
-			}
-			break;
-		default:
-			CAM_ERR(CAM_ISP, "CSID%d: Invalid csid path",
-				csid_hw->hw_intf->hw_idx);
-			rc = -EINVAL;
-			goto end;
-		}
-
-		rc = cam_ife_csid_cid_get(csid_hw,
-			&cid_reserv->node_res,
-			cid_reserv->in_port->vc,
-			cid_reserv->in_port->dt,
-			cid_reserv->in_port->res_type);
-		/* if success then increment the reserve count */
-		if (!rc) {
-			if (csid_hw->csi2_reserve_cnt == UINT_MAX) {
-				CAM_ERR(CAM_ISP,
-					"CSID%d reserve cnt reached max",
-					csid_hw->hw_intf->hw_idx);
-				rc = -EINVAL;
-			} else {
-				csid_hw->csi2_reserve_cnt++;
-				CAM_DBG(CAM_ISP, "CSID:%d CID:%d acquired",
-					csid_hw->hw_intf->hw_idx,
-					cid_reserv->node_res->res_id);
-			}
-		}
 	}
 
+	csid_hw->csi2_reserve_cnt++;
+	CAM_DBG(CAM_ISP, "CSID:%d CID:%d acquired",
+		csid_hw->hw_intf->hw_idx,
+		cid_reserv->node_res->res_id);
+
 end:
 	return rc;
 }
@@ -1856,8 +1851,8 @@
 	soc_info = &csid_hw->hw_info->soc_info;
 	id = res->res_id;
 
-	if (res->res_id >= CAM_IFE_PIX_PATH_RES_MAX ||
-		!csid_reg->rdi_reg[res->res_id]) {
+	if ((res->res_id > CAM_IFE_PIX_PATH_RES_RDI_3) ||
+		(!csid_reg->rdi_reg[res->res_id])) {
 		CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID:%d Invalid res id%d",
 			csid_hw->hw_intf->hw_idx, res->res_id);
 		return -EINVAL;
@@ -2415,12 +2410,24 @@
 		return -EINVAL;
 	}
 	csid_stop = (struct cam_csid_hw_stop_args  *) stop_args;
+
+	if (!csid_stop->num_res) {
+		CAM_ERR(CAM_ISP, "CSID: Invalid args");
+		return -EINVAL;
+	}
+
 	csid_hw_info = (struct cam_hw_info  *)hw_priv;
 	csid_hw = (struct cam_ife_csid_hw   *)csid_hw_info->core_info;
+	CAM_DBG(CAM_ISP, "CSID:%d num_res %d",
+		csid_hw->hw_intf->hw_idx,
+		csid_stop->num_res);
 
 	/* Stop the resource first */
 	for (i = 0; i < csid_stop->num_res; i++) {
 		res = csid_stop->node_res[i];
+		CAM_DBG(CAM_ISP, "CSID:%d res_type %d res_id %d",
+			csid_hw->hw_intf->hw_idx,
+			res->res_type, res->res_id);
 		switch (res->res_type) {
 		case CAM_ISP_RESOURCE_CID:
 			if (csid_hw->res_type == CAM_ISP_IFE_IN_RES_TPG)
@@ -2469,6 +2476,61 @@
 	return -EINVAL;
 }
 
+static int cam_ife_csid_sof_irq_debug(
+	struct cam_ife_csid_hw *csid_hw, void *cmd_args)
+{
+	int i = 0;
+	uint32_t val = 0;
+	bool sof_irq_enable = false;
+	struct cam_ife_csid_reg_offset    *csid_reg;
+	struct cam_hw_soc_info            *soc_info;
+
+	csid_reg = csid_hw->csid_info->csid_reg;
+	soc_info = &csid_hw->hw_info->soc_info;
+
+	if (*((uint32_t *)cmd_args) == 1)
+		sof_irq_enable = true;
+
+	val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+			csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
+
+	if (val) {
+		if (sof_irq_enable)
+			val |= CSID_PATH_INFO_INPUT_SOF;
+		else
+			val &= ~CSID_PATH_INFO_INPUT_SOF;
+
+		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			csid_reg->ipp_reg->csid_ipp_irq_mask_addr);
+		val = 0;
+	}
+
+	for (i = 0; i < csid_reg->cmn_reg->no_rdis; i++) {
+		val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
+			csid_reg->rdi_reg[i]->csid_rdi_irq_mask_addr);
+		if (val) {
+			if (sof_irq_enable)
+				val |= CSID_PATH_INFO_INPUT_SOF;
+			else
+				val &= ~CSID_PATH_INFO_INPUT_SOF;
+
+			cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+				csid_reg->rdi_reg[i]->csid_rdi_irq_mask_addr);
+			val = 0;
+		}
+	}
+
+	if (sof_irq_enable)
+		csid_hw->csid_debug |= CSID_DEBUG_ENABLE_SOF_IRQ;
+	else
+		csid_hw->csid_debug &= ~CSID_DEBUG_ENABLE_SOF_IRQ;
+
+	CAM_INFO(CAM_ISP, "SOF freeze: CSID SOF irq %s",
+		(sof_irq_enable == true) ? "enabled" : "disabled");
+
+	return 0;
+}
+
 static int cam_ife_csid_process_cmd(void *hw_priv,
 	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
 {
@@ -2491,8 +2553,11 @@
 	case CAM_IFE_CSID_SET_CSID_DEBUG:
 		rc = cam_ife_csid_set_csid_debug(csid_hw, cmd_args);
 		break;
+	case CAM_IFE_CSID_SOF_IRQ_DEBUG:
+		rc = cam_ife_csid_sof_irq_debug(csid_hw, cmd_args);
+		break;
 	default:
-		CAM_ERR(CAM_ISP, "CSID:%d un supported cmd:%d",
+		CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d",
 			csid_hw->hw_intf->hw_idx, cmd_type);
 		rc = -EINVAL;
 		break;
@@ -2777,6 +2842,7 @@
 {
 	int rc = -EINVAL;
 	uint32_t i;
+	uint32_t num_paths;
 	struct cam_ife_csid_path_cfg         *path_data;
 	struct cam_ife_csid_cid_data         *cid_data;
 	struct cam_hw_info                   *csid_hw_info;
@@ -2828,8 +2894,10 @@
 	ife_csid_hw->hw_intf->hw_ops.write       = cam_ife_csid_write;
 	ife_csid_hw->hw_intf->hw_ops.process_cmd = cam_ife_csid_process_cmd;
 
-	/*Initialize the CID resoure */
-	for (i = 0; i < CAM_IFE_CSID_CID_RES_MAX; i++) {
+	num_paths = ife_csid_hw->csid_info->csid_reg->cmn_reg->no_pix +
+		ife_csid_hw->csid_info->csid_reg->cmn_reg->no_rdis;
+	/* Initialize the CID resource */
+	for (i = 0; i < num_paths; i++) {
 		ife_csid_hw->cid_res[i].res_type = CAM_ISP_RESOURCE_CID;
 		ife_csid_hw->cid_res[i].res_id = i;
 		ife_csid_hw->cid_res[i].res_state  =
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c
index 128c050..2556b65 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_dev.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_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
@@ -21,6 +21,8 @@
 static struct cam_hw_intf *cam_ife_csid_hw_list[CAM_IFE_CSID_HW_RES_MAX] = {
 	0, 0, 0, 0};
 
+static char csid_dev_name[8];
+
 int cam_ife_csid_probe(struct platform_device *pdev)
 {
 
@@ -63,6 +65,10 @@
 		goto free_dev;
 	}
 
+	memset(csid_dev_name, 0, sizeof(csid_dev_name));
+	snprintf(csid_dev_name, sizeof(csid_dev_name),
+		"csid%1u", csid_dev_idx);
+
 	csid_hw_intf->hw_idx = csid_dev_idx;
 	csid_hw_intf->hw_type = CAM_ISP_HW_TYPE_IFE_CSID;
 	csid_hw_intf->hw_priv = csid_hw_info;
@@ -70,7 +76,7 @@
 	csid_hw_info->core_info = csid_dev;
 	csid_hw_info->soc_info.pdev = pdev;
 	csid_hw_info->soc_info.dev = &pdev->dev;
-	csid_hw_info->soc_info.dev_name = pdev->name;
+	csid_hw_info->soc_info.dev_name = csid_dev_name;
 	csid_hw_info->soc_info.index = csid_dev_idx;
 
 	csid_hw_data = (struct cam_ife_csid_hw_info  *)match_dev->data;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c
index 36c6df0..6c39bd8 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_lite170.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
@@ -39,6 +39,7 @@
 		.name = CAM_CSID_LITE_DRV_NAME,
 		.owner = THIS_MODULE,
 		.of_match_table = cam_ife_csid_lite170_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c
index e11ff63..d3261f8 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -112,8 +112,6 @@
 		CAM_ERR(CAM_ISP, "CPAS unregistration failed rc=%d", rc);
 
 	rc = cam_soc_util_release_platform_resource(soc_info);
-	if (rc < 0)
-		return rc;
 
 	return rc;
 }
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 8911f99..bbd092f 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
@@ -153,6 +153,7 @@
 enum cam_ife_csid_cmd_type {
 	CAM_IFE_CSID_CMD_GET_TIME_STAMP,
 	CAM_IFE_CSID_SET_CSID_DEBUG,
+	CAM_IFE_CSID_SOF_IRQ_DEBUG,
 	CAM_IFE_CSID_CMD_MAX,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
index c56c49f..70e0467 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
@@ -95,6 +95,7 @@
 	CAM_ISP_HW_CMD_BW_CONTROL,
 	CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ,
 	CAM_ISP_HW_CMD_GET_REG_DUMP,
+	CAM_ISP_HW_CMD_SOF_IRQ_DEBUG,
 	CAM_ISP_HW_CMD_MAX,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
index fd38a96..f6becfb 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
@@ -560,7 +560,7 @@
 					cam_vfe_irq_top_half,
 					cam_ife_mgr_do_tasklet,
 					isp_res->tasklet_info,
-					cam_tasklet_enqueue_cmd);
+					&tasklet_bh_api);
 			if (isp_res->irq_handle < 1)
 				rc = -ENOMEM;
 		} else if (isp_res->rdi_only_ctx) {
@@ -573,7 +573,7 @@
 					cam_vfe_irq_top_half,
 					cam_ife_mgr_do_tasklet,
 					isp_res->tasklet_info,
-					cam_tasklet_enqueue_cmd);
+					&tasklet_bh_api);
 			if (isp_res->irq_handle < 1)
 				rc = -ENOMEM;
 		}
@@ -606,7 +606,7 @@
 				cam_vfe_irq_err_top_half,
 				cam_ife_mgr_do_tasklet,
 				core_info->tasklet_info,
-				cam_tasklet_enqueue_cmd);
+				&tasklet_bh_api);
 		if (core_info->irq_err_handle < 1) {
 			CAM_ERR(CAM_ISP, "Error handle subscribe failure");
 			rc = -ENOMEM;
@@ -639,10 +639,11 @@
 	if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_IN) {
 		cam_irq_controller_unsubscribe_irq(
 			core_info->vfe_irq_controller, isp_res->irq_handle);
+		isp_res->irq_handle = 0;
+
 		rc = core_info->vfe_top->hw_ops.stop(
 			core_info->vfe_top->top_priv, isp_res,
 			sizeof(struct cam_isp_resource_node));
-
 	} else if (isp_res->res_type == CAM_ISP_RESOURCE_VFE_OUT) {
 		rc = core_info->vfe_bus->hw_ops.stop(isp_res, NULL, 0);
 	} else {
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c
index 74627b8..66b647d 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_dev.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_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
@@ -21,6 +21,8 @@
 
 static struct cam_hw_intf *cam_vfe_hw_list[CAM_VFE_HW_NUM_MAX] = {0, 0, 0, 0};
 
+static char vfe_dev_name[8];
+
 int cam_vfe_probe(struct platform_device *pdev)
 {
 	struct cam_hw_info                *vfe_hw = NULL;
@@ -44,9 +46,14 @@
 		rc = -ENOMEM;
 		goto free_vfe_hw_intf;
 	}
+
+	memset(vfe_dev_name, 0, sizeof(vfe_dev_name));
+	snprintf(vfe_dev_name, sizeof(vfe_dev_name),
+		"vfe%1u", vfe_hw_intf->hw_idx);
+
 	vfe_hw->soc_info.pdev = pdev;
 	vfe_hw->soc_info.dev = &pdev->dev;
-	vfe_hw->soc_info.dev_name = pdev->name;
+	vfe_hw->soc_info.dev_name = vfe_dev_name;
 	vfe_hw_intf->hw_priv = vfe_hw;
 	vfe_hw_intf->hw_ops.get_hw_caps = cam_vfe_get_hw_caps;
 	vfe_hw_intf->hw_ops.init = cam_vfe_init_hw;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c
index 0af32ad..d002f84 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe170.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
@@ -32,6 +32,7 @@
 		.name = "cam_vfe170",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_vfe170_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.c
index 3c8abbf..ab692cf 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe170/cam_vfe_lite170.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
@@ -32,6 +32,7 @@
 		.name = "cam_vfe_lite170",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_vfe170_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
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 3c37b83..67b572e 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
@@ -1084,7 +1084,7 @@
 			bus_irq_reg_mask, wm_res,
 			wm_res->top_half_handler,
 			cam_ife_mgr_do_tasklet_buf_done,
-			wm_res->tasklet_info, cam_tasklet_enqueue_cmd);
+			wm_res->tasklet_info, &tasklet_bh_api);
 		if (wm_res->irq_handle < 0) {
 			CAM_ERR(CAM_ISP, "Subscribe IRQ failed for WM %d",
 				rsrc_data->index);
@@ -1132,7 +1132,8 @@
 
 	/* Disble WM */
 	/* Disable all register access, reply on global reset */
-	CAM_DBG(CAM_ISP, "irq_enabled %d", rsrc_data->irq_enabled);
+	CAM_DBG(CAM_ISP, "WM res %d irq_enabled %d",
+		rsrc_data->index, rsrc_data->irq_enabled);
 	/* Unsubscribe IRQ */
 	if (rsrc_data->irq_enabled)
 		rc = cam_irq_controller_unsubscribe_irq(
@@ -1565,7 +1566,7 @@
 			bus_irq_reg_mask, comp_grp,
 			comp_grp->top_half_handler,
 			cam_ife_mgr_do_tasklet_buf_done,
-			comp_grp->tasklet_info, cam_tasklet_enqueue_cmd);
+			comp_grp->tasklet_info, &tasklet_bh_api);
 		if (comp_grp->irq_handle < 0) {
 			CAM_ERR(CAM_ISP, "Subscribe IRQ failed for comp_grp %d",
 				rsrc_data->comp_grp_type);
@@ -2251,11 +2252,13 @@
 	struct cam_irq_th_payload                 *th_payload)
 {
 	struct cam_vfe_bus_ver2_priv          *bus_priv;
+	int rc = 0;
 
 	bus_priv     = th_payload->handler_priv;
 	CAM_DBG(CAM_ISP, "Enter");
-	return cam_irq_controller_handle_irq(evt_id,
+	rc = cam_irq_controller_handle_irq(evt_id,
 		bus_priv->common_data.bus_irq_controller);
+	return (rc == IRQ_HANDLED) ? 0 : -EINVAL;
 }
 
 static int cam_vfe_bus_error_irq_top_half(uint32_t evt_id,
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
index 8bc9bd2..b554fe4 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
@@ -39,6 +39,7 @@
 	uint32_t                           first_line;
 	uint32_t                           last_pixel;
 	uint32_t                           last_line;
+	bool                               enable_sof_irq_debug;
 };
 
 static int cam_vfe_camif_validate_pix_pattern(uint32_t pattern)
@@ -359,6 +360,23 @@
 	return rc;
 }
 
+static int cam_vfe_camif_sof_irq_debug(
+	struct cam_isp_resource_node *rsrc_node, void *cmd_args)
+{
+	struct cam_vfe_mux_camif_data *camif_priv;
+	uint32_t *enable_sof_irq = (uint32_t *)cmd_args;
+
+	camif_priv =
+		(struct cam_vfe_mux_camif_data *)rsrc_node->res_priv;
+
+	if (*enable_sof_irq == 1)
+		camif_priv->enable_sof_irq_debug = true;
+	else
+		camif_priv->enable_sof_irq_debug = false;
+
+	return 0;
+}
+
 static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node,
 	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
 {
@@ -377,6 +395,9 @@
 	case CAM_ISP_HW_CMD_GET_REG_DUMP:
 		rc = cam_vfe_camif_reg_dump(rsrc_node);
 		break;
+	case CAM_ISP_HW_CMD_SOF_IRQ_DEBUG:
+		rc = cam_vfe_camif_sof_irq_debug(rsrc_node, cmd_args);
+		break;
 	default:
 		CAM_ERR(CAM_ISP,
 			"unsupported process command:%d", cmd_type);
@@ -419,7 +440,11 @@
 	switch (payload->evt_id) {
 	case CAM_ISP_HW_EVENT_SOF:
 		if (irq_status0 & camif_priv->reg_data->sof_irq_mask) {
-			CAM_DBG(CAM_ISP, "Received SOF");
+			if (camif_priv->enable_sof_irq_debug)
+				CAM_ERR_RATE_LIMIT(CAM_ISP, "Received SOF");
+			else
+				CAM_DBG(CAM_ISP, "Received SOF");
+
 			ret = CAM_VFE_IRQ_STATUS_SUCCESS;
 		}
 		break;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
index be0ca18..47a0438 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
@@ -107,14 +107,11 @@
 	if (max_clk_rate == top_priv->hw_clk_rate)
 		return 0;
 
-	CAM_DBG(CAM_ISP, "VFE: Clock name=%s idx=%d clk=%lld",
+	CAM_DBG(CAM_ISP, "VFE: Clock name=%s idx=%d clk=%llu",
 		soc_info->clk_name[soc_info->src_clk_idx],
 		soc_info->src_clk_idx, max_clk_rate);
 
-	rc = cam_soc_util_set_clk_rate(
-		soc_info->clk[soc_info->src_clk_idx],
-		soc_info->clk_name[soc_info->src_clk_idx],
-		max_clk_rate);
+	rc = cam_soc_util_set_src_clk_rate(soc_info, max_clk_rate);
 
 	if (!rc)
 		top_priv->hw_clk_rate = max_clk_rate;
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c
index 60feeac..46cc08f 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/cam_jpeg_dev.c
@@ -138,6 +138,7 @@
 		.name = "cam_jpeg",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_jpeg_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index 97d076a..f0913b2 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -729,15 +729,59 @@
 	return rc;
 }
 
+static void cam_jpeg_mgr_stop_deinit_dev(struct cam_jpeg_hw_mgr *hw_mgr,
+	struct cam_jpeg_hw_cfg_req *p_cfg_req, uint32_t dev_type)
+{
+	int rc = 0;
+	struct cam_jpeg_set_irq_cb irq_cb;
+
+	/* stop reset Unregister CB and deinit */
+	irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb;
+	irq_cb.data = NULL;
+	irq_cb.b_set_cb = false;
+	if (hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) {
+		rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd(
+			hw_mgr->devices[dev_type][0]->hw_priv,
+			CAM_JPEG_CMD_SET_IRQ_CB,
+			&irq_cb, sizeof(irq_cb));
+		if (rc)
+			CAM_ERR(CAM_JPEG, "SET_IRQ_CB fail %d", rc);
+	} else {
+		CAM_ERR(CAM_JPEG, "process_cmd null %d", dev_type);
+	}
+
+	if (hw_mgr->devices[dev_type][0]->hw_ops.stop) {
+		rc = hw_mgr->devices[dev_type][0]->hw_ops.stop(
+			hw_mgr->devices[dev_type][0]->hw_priv,
+			NULL, 0);
+		if (rc)
+			CAM_ERR(CAM_JPEG, "stop fail %d", rc);
+	} else {
+		CAM_ERR(CAM_JPEG, "op stop null %d", dev_type);
+	}
+
+	if (hw_mgr->devices[dev_type][0]->hw_ops.deinit) {
+		rc = hw_mgr->devices[dev_type][0]->hw_ops.deinit(
+			hw_mgr->devices[dev_type][0]->hw_priv,
+			NULL, 0);
+		if (rc)
+			CAM_ERR(CAM_JPEG, "Failed to Deinit %d HW %d",
+				dev_type, rc);
+	} else {
+		CAM_ERR(CAM_JPEG, "op deinit null %d", dev_type);
+	}
+
+	hw_mgr->device_in_use[dev_type][0] = false;
+	hw_mgr->dev_hw_cfg_args[dev_type][0] = NULL;
+}
+
 static int cam_jpeg_mgr_flush(void *hw_mgr_priv,
 	struct cam_jpeg_hw_ctx_data *ctx_data)
 {
-	int rc = 0;
 	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
 	uint32_t dev_type;
 	struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL;
 	struct cam_jpeg_hw_cfg_req *cfg_req = NULL, *req_temp = NULL;
-	struct cam_jpeg_set_irq_cb irq_cb;
 
 	CAM_DBG(CAM_JPEG, "E: JPEG flush ctx");
 
@@ -753,75 +797,40 @@
 		p_cfg_req != NULL) {
 		if ((struct cam_jpeg_hw_ctx_data *)
 			p_cfg_req->hw_cfg_args.ctxt_to_hw_map == ctx_data) {
-			/* stop reset Unregister CB and deinit */
-			irq_cb.jpeg_hw_mgr_cb = cam_jpeg_hw_mgr_cb;
-			irq_cb.data = NULL;
-			irq_cb.b_set_cb = false;
-			if (hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) {
-				rc = hw_mgr->devices[dev_type][0]->
-					hw_ops.process_cmd(
-				hw_mgr->devices[dev_type][0]->hw_priv,
-				CAM_JPEG_CMD_SET_IRQ_CB,
-				&irq_cb, sizeof(irq_cb));
-			if (rc)
-				CAM_ERR(CAM_JPEG,
-					"CMD_SET_IRQ_CB failed %d", rc);
-
-			} else {
-				CAM_ERR(CAM_JPEG, "process_cmd null ");
-			}
-
-			if (hw_mgr->devices[dev_type][0]->hw_ops.stop) {
-				rc = hw_mgr->devices[dev_type][0]->hw_ops.stop(
-					hw_mgr->devices[dev_type][0]->hw_priv,
-					NULL, 0);
-				if (rc)
-					CAM_ERR(CAM_JPEG, "stop fail %d", rc);
-			} else {
-				CAM_ERR(CAM_JPEG, "op stop null ");
-			}
-
-			if (hw_mgr->devices[dev_type][0]->hw_ops.deinit) {
-				rc = hw_mgr->devices[dev_type][0]
-					->hw_ops.deinit(
-					hw_mgr->devices[dev_type][0]->hw_priv,
-					NULL, 0);
-				if (rc)
-					CAM_ERR(CAM_JPEG,
-						"Failed to Deinit %d HW",
-						dev_type);
-			} else {
-				CAM_ERR(CAM_JPEG, "op deinit null");
-			}
+			cam_jpeg_mgr_stop_deinit_dev(hw_mgr, p_cfg_req,
+				dev_type);
+			list_del_init(&p_cfg_req->list);
+			list_add_tail(&p_cfg_req->list,
+				&hw_mgr->free_req_list);
 		}
-
-		hw_mgr->device_in_use[dev_type][0] = false;
-		p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0];
-		hw_mgr->dev_hw_cfg_args[dev_type][0] = NULL;
 	}
 
 	list_for_each_entry_safe(cfg_req, req_temp,
 		&hw_mgr->hw_config_req_list, list) {
-		if ((cfg_req) && ((struct cam_jpeg_hw_ctx_data *)
-			cfg_req->hw_cfg_args.ctxt_to_hw_map != ctx_data))
+		if ((struct cam_jpeg_hw_ctx_data *)
+			cfg_req->hw_cfg_args.ctxt_to_hw_map != ctx_data)
 			continue;
 
 		list_del_init(&cfg_req->list);
+		list_add_tail(&cfg_req->list, &hw_mgr->free_req_list);
 	}
 
-	CAM_DBG(CAM_JPEG, "X: JPEG flush ctx with rc: %d", rc);
+	CAM_DBG(CAM_JPEG, "X: JPEG flush ctx");
 
-	return rc;
+	return 0;
 }
 
-
 static int cam_jpeg_mgr_flush_req(void *hw_mgr_priv,
 	struct cam_jpeg_hw_ctx_data *ctx_data,
 	struct cam_hw_flush_args *flush_args)
 {
 	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
-	struct cam_jpeg_hw_cfg_req *cfg_req, *req_temp;
-	int64_t request_id;
+	struct cam_jpeg_hw_cfg_req *cfg_req = NULL;
+	struct cam_jpeg_hw_cfg_req *req_temp = NULL;
+	int64_t request_id = 0;
+	uint32_t dev_type;
+	struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL;
+	bool b_req_found = false;
 
 	CAM_DBG(CAM_JPEG, "E: JPEG flush req");
 
@@ -833,21 +842,54 @@
 	if (flush_args->num_req_pending)
 		return 0;
 
-	request_id = *(int64_t *)flush_args->flush_req_active[0];
+	request_id = (int64_t)flush_args->flush_req_active[0];
+
+	if (!flush_args->num_req_active)
+		return 0;
+
+	if (request_id <= 0) {
+		CAM_ERR(CAM_JPEG, "Invalid red id %lld", request_id);
+		return -EINVAL;
+	}
+
+	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
+
+	p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0];
+	if (hw_mgr->device_in_use[dev_type][0] == true &&
+		p_cfg_req != NULL) {
+		if (((struct cam_jpeg_hw_ctx_data *)
+			p_cfg_req->hw_cfg_args.ctxt_to_hw_map == ctx_data) &&
+			(p_cfg_req->req_id == request_id)) {
+			cam_jpeg_mgr_stop_deinit_dev(hw_mgr, p_cfg_req,
+				dev_type);
+			list_del_init(&p_cfg_req->list);
+			list_add_tail(&p_cfg_req->list,
+				&hw_mgr->free_req_list);
+			b_req_found = true;
+		}
+	}
+
 	list_for_each_entry_safe(cfg_req, req_temp,
 		&hw_mgr->hw_config_req_list, list) {
-		if ((cfg_req) && (cfg_req->hw_cfg_args.ctxt_to_hw_map
-			!= ctx_data))
+		if ((struct cam_jpeg_hw_ctx_data *)
+			cfg_req->hw_cfg_args.ctxt_to_hw_map != ctx_data)
 			continue;
 
 		if (cfg_req->req_id != request_id)
 			continue;
 
 		list_del_init(&cfg_req->list);
+		list_add_tail(&cfg_req->list, &hw_mgr->free_req_list);
+		b_req_found = true;
+		break;
+	}
+
+	if (!b_req_found) {
+		CAM_ERR(CAM_JPEG, "req not found %lld", request_id);
+		return -EINVAL;
 	}
 
 	CAM_DBG(CAM_JPEG, "X: JPEG flush req");
-
 	return 0;
 }
 
@@ -887,7 +929,6 @@
 		break;
 	case CAM_FLUSH_TYPE_REQ:
 		rc = cam_jpeg_mgr_flush_req(hw_mgr_priv, ctx_data, flush_args);
-		CAM_ERR(CAM_JPEG, "Flush per request is not supported");
 		break;
 	default:
 		CAM_ERR(CAM_JPEG, "Invalid flush type: %d",
@@ -956,7 +997,6 @@
 	if (hw_mgr->cdm_info[dev_type][0].ref_cnt == 0) {
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		CAM_ERR(CAM_JPEG, "Error Unbalanced deinit");
-		kfree(ctx_data->cdm_cmd);
 		return -EFAULT;
 	}
 
@@ -978,10 +1018,13 @@
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		CAM_ERR(CAM_JPEG, "JPEG release ctx failed");
 		kfree(ctx_data->cdm_cmd);
+		ctx_data->cdm_cmd = NULL;
+
 		return -EINVAL;
 	}
 
 	kfree(ctx_data->cdm_cmd);
+	ctx_data->cdm_cmd = NULL;
 	CAM_DBG(CAM_JPEG, "handle %llu", ctx_data);
 
 	return rc;
@@ -989,7 +1032,7 @@
 
 static int cam_jpeg_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
 {
-	int rc;
+	int rc = 0;
 	int32_t ctx_id = 0;
 	struct cam_jpeg_hw_mgr *hw_mgr = hw_mgr_priv;
 	struct cam_jpeg_hw_ctx_data *ctx_data = NULL;
@@ -1171,7 +1214,7 @@
 		"jpeg_command_queue",
 		CAM_JPEG_WORKQ_NUM_TASK,
 		&g_jpeg_hw_mgr.work_process_frame,
-		CRM_WORKQ_USAGE_NON_IRQ);
+		CRM_WORKQ_USAGE_NON_IRQ, 0);
 	if (rc) {
 		CAM_ERR(CAM_JPEG, "unable to create a worker %d", rc);
 		goto work_process_frame_failed;
@@ -1181,7 +1224,7 @@
 		"jpeg_message_queue",
 		CAM_JPEG_WORKQ_NUM_TASK,
 		&g_jpeg_hw_mgr.work_process_irq_cb,
-		CRM_WORKQ_USAGE_IRQ);
+		CRM_WORKQ_USAGE_IRQ, 0);
 	if (rc) {
 		CAM_ERR(CAM_JPEG, "unable to create a worker %d", rc);
 		goto work_process_irq_cb_failed;
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c
index ef10406..fd4fdab 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_dev.c
@@ -220,6 +220,7 @@
 		.name = "cam-jpeg-dma",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_jpeg_dma_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
index 9fa691b..7fcc1ad 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
@@ -349,7 +349,7 @@
 	hw_info = core_info->jpeg_enc_hw_info;
 	mem_base = soc_info->reg_map[0].mem_base;
 
-	mutex_unlock(&core_info->core_mutex);
+	mutex_lock(&core_info->core_mutex);
 	spin_lock(&jpeg_enc_dev->hw_lock);
 	if (core_info->core_state == CAM_JPEG_ENC_CORE_ABORTING) {
 		CAM_ERR(CAM_JPEG, "alrady stopping");
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c
index d1eb526..d4daa6d 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_dev.c
@@ -218,6 +218,7 @@
 		.name = "cam-jpeg-enc",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_jpeg_enc_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_dev.c b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_dev.c
index 5be16ef..a4ee104 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_dev.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/cam_lrme_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
@@ -214,6 +214,7 @@
 		.name = "cam_lrme",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_lrme_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
index a60661e..0f34c9f 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
@@ -989,7 +989,8 @@
 	CAM_DBG(CAM_LRME, "Create submit workq for %s", buf);
 	rc = cam_req_mgr_workq_create(buf,
 		CAM_LRME_WORKQ_NUM_TASK,
-		&hw_device->work, CRM_WORKQ_USAGE_NON_IRQ);
+		&hw_device->work, CRM_WORKQ_USAGE_NON_IRQ,
+		0);
 	if (rc) {
 		CAM_ERR(CAM_LRME,
 			"Unable to create a worker, rc=%d", rc);
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
index 6f98354..595bb81 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
@@ -1118,7 +1118,7 @@
 
 	if (!data) {
 		CAM_ERR(CAM_LRME, "Invalid data in IRQ callback");
-		return -EINVAL;
+		return IRQ_NONE;
 	}
 
 	lrme_hw = (struct cam_hw_info *)data;
@@ -1179,7 +1179,7 @@
 		task = cam_req_mgr_workq_get_task(lrme_core->work);
 		if (!task) {
 			CAM_ERR(CAM_LRME, "no empty task available");
-			return -ENOMEM;
+			return IRQ_NONE;
 		}
 		work_data = (struct cam_lrme_hw_work_data *)task->payload;
 		work_data->top_irq_status = top_irq_status;
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c
index da42c84..ec42978 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_dev.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_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
@@ -28,8 +28,6 @@
 #include "cam_mem_mgr_api.h"
 #include "cam_smmu_api.h"
 
-#define CAM_LRME_HW_WORKQ_NUM_TASK 30
-
 static int cam_lrme_hw_dev_util_cdm_acquire(struct cam_lrme_core *lrme_core,
 	struct cam_hw_info *lrme_hw)
 {
@@ -122,7 +120,7 @@
 
 	rc = cam_req_mgr_workq_create("cam_lrme_hw_worker",
 		CAM_LRME_HW_WORKQ_NUM_TASK,
-		&lrme_core->work, CRM_WORKQ_USAGE_IRQ);
+		&lrme_core->work, CRM_WORKQ_USAGE_IRQ, 0);
 	if (rc) {
 		CAM_ERR(CAM_LRME, "Unable to create a workq, rc=%d", rc);
 		goto free_memory;
@@ -302,6 +300,7 @@
 		.name = "cam_lrme_hw",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_lrme_hw_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
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 93e4249..d192018 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
@@ -30,12 +30,12 @@
 {
 	*vaddr = (uintptr_t)ion_map_kernel(tbl.client, hdl);
 	if (IS_ERR_OR_NULL((void *)*vaddr)) {
-		CAM_ERR(CAM_CRM, "kernel map fail");
+		CAM_ERR(CAM_MEM, "kernel map fail");
 		return -ENOSPC;
 	}
 
 	if (ion_handle_get_size(tbl.client, hdl, len)) {
-		CAM_ERR(CAM_CRM, "kernel get len failed");
+		CAM_ERR(CAM_MEM, "kernel get len failed");
 		ion_unmap_kernel(tbl.client, hdl);
 		return -ENOSPC;
 	}
@@ -65,7 +65,7 @@
 
 	tbl.client = msm_ion_client_create("camera_global_pool");
 	if (IS_ERR_OR_NULL(tbl.client)) {
-		CAM_ERR(CAM_CRM, "fail to create client");
+		CAM_ERR(CAM_MEM, "fail to create client");
 		rc = -EINVAL;
 	}
 
@@ -88,7 +88,7 @@
 
 	rc = cam_mem_util_client_create();
 	if (rc < 0) {
-		CAM_ERR(CAM_CRM, "fail to create ion client");
+		CAM_ERR(CAM_MEM, "fail to create ion client");
 		goto client_fail;
 	}
 
@@ -175,7 +175,7 @@
 			iova_ptr,
 			len_ptr);
 	if (rc < 0)
-		CAM_ERR(CAM_CRM, "fail to get buf hdl :%d", buf_handle);
+		CAM_ERR(CAM_MEM, "fail to get buf hdl :%d", buf_handle);
 
 handle_mismatch:
 	mutex_unlock(&tbl.bufq[idx].q_lock);
@@ -209,7 +209,7 @@
 
 	ion_hdl = tbl.bufq[idx].i_hdl;
 	if (!ion_hdl) {
-		CAM_ERR(CAM_CRM, "Invalid ION handle");
+		CAM_ERR(CAM_MEM, "Invalid ION handle");
 		rc = -EINVAL;
 		goto exit_func;
 	}
@@ -264,7 +264,7 @@
 	rc = ion_handle_get_flags(tbl.client, tbl.bufq[idx].i_hdl,
 		&ion_flag);
 	if (rc) {
-		CAM_ERR(CAM_CRM, "cache get flags failed %d", rc);
+		CAM_ERR(CAM_MEM, "cache get flags failed %d", rc);
 		goto fail;
 	}
 
@@ -280,7 +280,7 @@
 			ion_cache_ops = ION_IOC_CLEAN_INV_CACHES;
 			break;
 		default:
-			CAM_ERR(CAM_CRM,
+			CAM_ERR(CAM_MEM,
 				"invalid cache ops :%d", cmd->mem_cache_ops);
 			rc = -EINVAL;
 			goto fail;
@@ -292,7 +292,7 @@
 				tbl.bufq[idx].len,
 				ion_cache_ops);
 		if (rc)
-			CAM_ERR(CAM_CRM, "cache operation failed %d", rc);
+			CAM_ERR(CAM_MEM, "cache operation failed %d", rc);
 	}
 fail:
 	mutex_unlock(&tbl.bufq[idx].q_lock);
@@ -310,7 +310,7 @@
 	int rc = 0;
 
 	if (!hdl || !buf) {
-		CAM_ERR(CAM_CRM, "Invalid params");
+		CAM_ERR(CAM_MEM, "Invalid params");
 		return -EINVAL;
 	}
 
@@ -320,7 +320,7 @@
 
 	*buf = ion_share_dma_buf(tbl.client, *hdl);
 	if (IS_ERR_OR_NULL(*buf)) {
-		CAM_ERR(CAM_CRM, "get dma buf fail");
+		CAM_ERR(CAM_MEM, "get dma buf fail");
 		rc = -EINVAL;
 		goto get_buf_fail;
 	}
@@ -343,7 +343,7 @@
 	int rc = 0;
 
 	if (!hdl || !fd) {
-		CAM_ERR(CAM_CRM, "Invalid params");
+		CAM_ERR(CAM_MEM, "Invalid params");
 		return -EINVAL;
 	}
 
@@ -353,7 +353,7 @@
 
 	*fd = ion_share_dma_buf_fd(tbl.client, *hdl);
 	if (*fd < 0) {
-		CAM_ERR(CAM_CRM, "get fd fail");
+		CAM_ERR(CAM_MEM, "get fd fail");
 		rc = -EINVAL;
 		goto get_fd_fail;
 	}
@@ -400,19 +400,19 @@
 static int cam_mem_util_check_flags(struct cam_mem_mgr_alloc_cmd *cmd)
 {
 	if (!cmd->flags) {
-		CAM_ERR(CAM_CRM, "Invalid flags");
+		CAM_ERR(CAM_MEM, "Invalid flags");
 		return -EINVAL;
 	}
 
 	if (cmd->num_hdl > CAM_MEM_MMU_MAX_HANDLE) {
-		CAM_ERR(CAM_CRM, "Num of mmu hdl exceeded maximum(%d)",
+		CAM_ERR(CAM_MEM, "Num of mmu hdl exceeded maximum(%d)",
 			CAM_MEM_MMU_MAX_HANDLE);
 		return -EINVAL;
 	}
 
 	if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE &&
 		cmd->flags & CAM_MEM_FLAG_KMD_ACCESS) {
-		CAM_ERR(CAM_CRM, "Kernel mapping in secure mode not allowed");
+		CAM_ERR(CAM_MEM, "Kernel mapping in secure mode not allowed");
 		return -EINVAL;
 	}
 
@@ -422,24 +422,24 @@
 static int cam_mem_util_check_map_flags(struct cam_mem_mgr_map_cmd *cmd)
 {
 	if (!cmd->flags) {
-		CAM_ERR(CAM_CRM, "Invalid flags");
+		CAM_ERR(CAM_MEM, "Invalid flags");
 		return -EINVAL;
 	}
 
 	if (cmd->num_hdl > CAM_MEM_MMU_MAX_HANDLE) {
-		CAM_ERR(CAM_CRM, "Num of mmu hdl exceeded maximum(%d)",
+		CAM_ERR(CAM_MEM, "Num of mmu hdl exceeded maximum(%d)",
 			CAM_MEM_MMU_MAX_HANDLE);
 		return -EINVAL;
 	}
 
 	if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE &&
 		cmd->flags & CAM_MEM_FLAG_KMD_ACCESS) {
-		CAM_ERR(CAM_CRM, "Kernel mapping in secure mode not allowed");
+		CAM_ERR(CAM_MEM, "Kernel mapping in secure mode not allowed");
 		return -EINVAL;
 	}
 
 	if (cmd->flags & CAM_MEM_FLAG_HW_SHARED_ACCESS) {
-		CAM_ERR(CAM_CRM,
+		CAM_ERR(CAM_MEM,
 			"Shared memory buffers are not allowed to be mapped");
 		return -EINVAL;
 	}
@@ -460,7 +460,7 @@
 	int dir = cam_mem_util_get_dma_dir(flags);
 
 	if (dir < 0) {
-		CAM_ERR(CAM_CRM, "fail to map DMA direction");
+		CAM_ERR(CAM_MEM, "fail to map DMA direction");
 		return dir;
 	}
 
@@ -474,7 +474,7 @@
 				len);
 
 			if (rc < 0) {
-				CAM_ERR(CAM_CRM,
+				CAM_ERR(CAM_MEM,
 					"Failed to securely map to smmu");
 				goto multi_map_fail;
 			}
@@ -489,7 +489,7 @@
 				region);
 
 			if (rc < 0) {
-				CAM_ERR(CAM_CRM, "Failed to map to smmu");
+				CAM_ERR(CAM_MEM, "Failed to map to smmu");
 				goto multi_map_fail;
 			}
 		}
@@ -519,14 +519,14 @@
 	size_t len;
 
 	if (!cmd) {
-		CAM_ERR(CAM_CRM, " Invalid argument");
+		CAM_ERR(CAM_MEM, " Invalid argument");
 		return -EINVAL;
 	}
 	len = cmd->len;
 
 	rc = cam_mem_util_check_flags(cmd);
 	if (rc) {
-		CAM_ERR(CAM_CRM, "Invalid flags: flags = %X", cmd->flags);
+		CAM_ERR(CAM_MEM, "Invalid flags: flags = %X", cmd->flags);
 		return rc;
 	}
 
@@ -534,12 +534,13 @@
 		&ion_hdl,
 		&ion_fd);
 	if (rc) {
-		CAM_ERR(CAM_CRM, "Ion allocation failed");
+		CAM_ERR(CAM_MEM, "Ion allocation failed");
 		return rc;
 	}
 
 	idx = cam_mem_get_slot();
 	if (idx < 0) {
+		CAM_ERR(CAM_MEM, "Failed to get slot");
 		rc = -ENOMEM;
 		goto slot_fail;
 	}
@@ -594,7 +595,7 @@
 	cmd->out.fd = tbl.bufq[idx].fd;
 	cmd->out.vaddr = 0;
 
-	CAM_DBG(CAM_CRM, "buf handle: %x, fd: %d, len: %zu",
+	CAM_DBG(CAM_MEM, "buf handle: %x, fd: %d, len: %zu",
 		cmd->out.buf_handle, cmd->out.fd,
 		tbl.bufq[idx].len);
 
@@ -616,7 +617,7 @@
 	size_t len = 0;
 
 	if (!cmd || (cmd->fd < 0)) {
-		CAM_ERR(CAM_CRM, "Invalid argument");
+		CAM_ERR(CAM_MEM, "Invalid argument");
 		return -EINVAL;
 	}
 
@@ -625,13 +626,13 @@
 
 	rc = cam_mem_util_check_map_flags(cmd);
 	if (rc) {
-		CAM_ERR(CAM_CRM, "Invalid flags: flags = %X", cmd->flags);
+		CAM_ERR(CAM_MEM, "Invalid flags: flags = %X", cmd->flags);
 		return rc;
 	}
 
 	ion_hdl = ion_import_dma_buf_fd(tbl.client, cmd->fd);
 	if (IS_ERR_OR_NULL((void *)(ion_hdl))) {
-		CAM_ERR(CAM_CRM, "Failed to import ion fd");
+		CAM_ERR(CAM_MEM, "Failed to import ion fd");
 		return -EINVAL;
 	}
 
@@ -702,7 +703,7 @@
 	int rc = -EINVAL;
 
 	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) {
-		CAM_ERR(CAM_CRM, "Incorrect index");
+		CAM_ERR(CAM_MEM, "Incorrect index");
 		return rc;
 	}
 
@@ -726,7 +727,7 @@
 				rc = cam_smmu_unmap_kernel_iova(mmu_hdls[i],
 					tbl.bufq[idx].dma_buf, region);
 			} else {
-				CAM_ERR(CAM_CRM,
+				CAM_ERR(CAM_MEM,
 					"invalid caller for unmapping : %d",
 					client);
 				rc = -EINVAL;
@@ -739,7 +740,7 @@
 	return rc;
 
 unmap_end:
-	CAM_ERR(CAM_CRM, "unmapping failed");
+	CAM_ERR(CAM_MEM, "unmapping failed");
 	return rc;
 }
 
@@ -762,11 +763,11 @@
 	mutex_lock(&tbl.m_lock);
 	for (i = 1; i < CAM_MEM_BUFQ_MAX; i++) {
 		if (!tbl.bufq[i].active) {
-			CAM_DBG(CAM_CRM,
+			CAM_DBG(CAM_MEM,
 				"Buffer inactive at idx=%d, continuing", i);
 			continue;
 		} else {
-			CAM_DBG(CAM_CRM,
+			CAM_DBG(CAM_MEM,
 			"Active buffer at idx=%d, possible leak needs unmapping",
 			i);
 			cam_mem_mgr_unmap_active_buf(i);
@@ -817,16 +818,16 @@
 	enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED;
 
 	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) {
-		CAM_ERR(CAM_CRM, "Incorrect index");
+		CAM_ERR(CAM_MEM, "Incorrect index");
 		return -EINVAL;
 	}
 
-	CAM_DBG(CAM_CRM, "Flags = %X idx %d", tbl.bufq[idx].flags, idx);
+	CAM_DBG(CAM_MEM, "Flags = %X idx %d", tbl.bufq[idx].flags, idx);
 
 	mutex_lock(&tbl.m_lock);
 	if ((!tbl.bufq[idx].active) &&
 		(tbl.bufq[idx].vaddr) == 0) {
-		CAM_WARN(CAM_CRM, "Buffer at idx=%d is already unmapped,",
+		CAM_WARN(CAM_MEM, "Buffer at idx=%d is already unmapped,",
 			idx);
 		mutex_unlock(&tbl.m_lock);
 		return 0;
@@ -858,7 +859,7 @@
 	memset(tbl.bufq[idx].hdls, 0,
 		sizeof(int32_t) * CAM_MEM_MMU_MAX_HANDLE);
 
-	CAM_DBG(CAM_CRM,
+	CAM_DBG(CAM_MEM,
 		"Ion handle at idx = %d freeing = %pK, fd = %d, imported %d dma_buf %pK",
 		idx, tbl.bufq[idx].i_hdl, tbl.bufq[idx].fd,
 		tbl.bufq[idx].is_imported,
@@ -889,28 +890,28 @@
 	int rc;
 
 	if (!cmd) {
-		CAM_ERR(CAM_CRM, "Invalid argument");
+		CAM_ERR(CAM_MEM, "Invalid argument");
 		return -EINVAL;
 	}
 
 	idx = CAM_MEM_MGR_GET_HDL_IDX(cmd->buf_handle);
 	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) {
-		CAM_ERR(CAM_CRM, "Incorrect index extracted from mem handle");
+		CAM_ERR(CAM_MEM, "Incorrect index extracted from mem handle");
 		return -EINVAL;
 	}
 
 	if (!tbl.bufq[idx].active) {
-		CAM_ERR(CAM_CRM, "Released buffer state should be active");
+		CAM_ERR(CAM_MEM, "Released buffer state should be active");
 		return -EINVAL;
 	}
 
 	if (tbl.bufq[idx].buf_handle != cmd->buf_handle) {
-		CAM_ERR(CAM_CRM,
+		CAM_ERR(CAM_MEM,
 			"Released buf handle not matching within table");
 		return -EINVAL;
 	}
 
-	CAM_DBG(CAM_CRM, "Releasing hdl = %u", cmd->buf_handle);
+	CAM_DBG(CAM_MEM, "Releasing hdl = %u", cmd->buf_handle);
 	rc = cam_mem_util_unmap(idx, CAM_SMMU_MAPPING_USER);
 
 	return rc;
@@ -936,14 +937,14 @@
 	enum cam_smmu_region_id region = CAM_SMMU_REGION_SHARED;
 
 	if (!inp || !out) {
-		CAM_ERR(CAM_CRM, "Invalid params");
+		CAM_ERR(CAM_MEM, "Invalid params");
 		return -EINVAL;
 	}
 
 	if (!(inp->flags & CAM_MEM_FLAG_HW_READ_WRITE ||
 		inp->flags & CAM_MEM_FLAG_HW_SHARED_ACCESS ||
 		inp->flags & CAM_MEM_FLAG_CACHE)) {
-		CAM_ERR(CAM_CRM, "Invalid flags for request mem");
+		CAM_ERR(CAM_MEM, "Invalid flags for request mem");
 		return -EINVAL;
 	}
 
@@ -963,20 +964,20 @@
 		&buf);
 
 	if (rc) {
-		CAM_ERR(CAM_CRM, "ION alloc failed for shared buffer");
+		CAM_ERR(CAM_MEM, "ION alloc failed for shared buffer");
 		goto ion_fail;
 	} else {
-		CAM_DBG(CAM_CRM, "Got dma_buf = %pK, hdl = %pK", buf, hdl);
+		CAM_DBG(CAM_MEM, "Got dma_buf = %pK, hdl = %pK", buf, hdl);
 	}
 
 	rc = cam_mem_util_map_cpu_va(hdl, &kvaddr, &request_len);
 	if (rc) {
-		CAM_ERR(CAM_CRM, "Failed to get kernel vaddr");
+		CAM_ERR(CAM_MEM, "Failed to get kernel vaddr");
 		goto map_fail;
 	}
 
 	if (!inp->smmu_hdl) {
-		CAM_ERR(CAM_CRM, "Invalid SMMU handle");
+		CAM_ERR(CAM_MEM, "Invalid SMMU handle");
 		rc = -EINVAL;
 		goto smmu_fail;
 	}
@@ -997,7 +998,7 @@
 		region);
 
 	if (rc < 0) {
-		CAM_ERR(CAM_CRM, "SMMU mapping failed");
+		CAM_ERR(CAM_MEM, "SMMU mapping failed");
 		goto smmu_fail;
 	}
 
@@ -1054,32 +1055,32 @@
 	int rc;
 
 	if (!inp) {
-		CAM_ERR(CAM_CRM, "Invalid argument");
+		CAM_ERR(CAM_MEM, "Invalid argument");
 		return -EINVAL;
 	}
 
 	idx = CAM_MEM_MGR_GET_HDL_IDX(inp->mem_handle);
 	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) {
-		CAM_ERR(CAM_CRM, "Incorrect index extracted from mem handle");
+		CAM_ERR(CAM_MEM, "Incorrect index extracted from mem handle");
 		return -EINVAL;
 	}
 
 	if (!tbl.bufq[idx].active) {
 		if (tbl.bufq[idx].vaddr == 0) {
-			CAM_ERR(CAM_CRM, "buffer is released already");
+			CAM_ERR(CAM_MEM, "buffer is released already");
 			return 0;
 		}
-		CAM_ERR(CAM_CRM, "Released buffer state should be active");
+		CAM_ERR(CAM_MEM, "Released buffer state should be active");
 		return -EINVAL;
 	}
 
 	if (tbl.bufq[idx].buf_handle != inp->mem_handle) {
-		CAM_ERR(CAM_CRM,
+		CAM_ERR(CAM_MEM,
 			"Released buf handle not matching within table");
 		return -EINVAL;
 	}
 
-	CAM_DBG(CAM_CRM, "Releasing hdl = %X", inp->mem_handle);
+	CAM_DBG(CAM_MEM, "Releasing hdl = %X", inp->mem_handle);
 	rc = cam_mem_util_unmap(idx, CAM_SMMU_MAPPING_KERNEL);
 
 	return rc;
@@ -1103,17 +1104,17 @@
 	int32_t num_hdl = 0;
 
 	if (!inp || !out) {
-		CAM_ERR(CAM_CRM, "Invalid param(s)");
+		CAM_ERR(CAM_MEM, "Invalid param(s)");
 		return -EINVAL;
 	}
 
 	if (!inp->smmu_hdl) {
-		CAM_ERR(CAM_CRM, "Invalid SMMU handle");
+		CAM_ERR(CAM_MEM, "Invalid SMMU handle");
 		return -EINVAL;
 	}
 
 	if (region != CAM_SMMU_REGION_SECHEAP) {
-		CAM_ERR(CAM_CRM, "Only secondary heap supported");
+		CAM_ERR(CAM_MEM, "Only secondary heap supported");
 		return -EINVAL;
 	}
 
@@ -1127,10 +1128,10 @@
 		&buf);
 
 	if (rc) {
-		CAM_ERR(CAM_CRM, "ION alloc failed for sec heap buffer");
+		CAM_ERR(CAM_MEM, "ION alloc failed for sec heap buffer");
 		goto ion_fail;
 	} else {
-		CAM_DBG(CAM_CRM, "Got dma_buf = %pK, hdl = %pK", buf, hdl);
+		CAM_DBG(CAM_MEM, "Got dma_buf = %pK, hdl = %pK", buf, hdl);
 	}
 
 	rc = cam_smmu_reserve_sec_heap(inp->smmu_hdl,
@@ -1139,7 +1140,7 @@
 		&request_len);
 
 	if (rc) {
-		CAM_ERR(CAM_CRM, "Reserving secondary heap failed");
+		CAM_ERR(CAM_MEM, "Reserving secondary heap failed");
 		goto smmu_fail;
 	}
 
@@ -1195,38 +1196,38 @@
 	int32_t smmu_hdl;
 
 	if (!inp) {
-		CAM_ERR(CAM_CRM, "Invalid argument");
+		CAM_ERR(CAM_MEM, "Invalid argument");
 		return -EINVAL;
 	}
 
 	if (inp->region != CAM_SMMU_REGION_SECHEAP) {
-		CAM_ERR(CAM_CRM, "Only secondary heap supported");
+		CAM_ERR(CAM_MEM, "Only secondary heap supported");
 		return -EINVAL;
 	}
 
 	idx = CAM_MEM_MGR_GET_HDL_IDX(inp->mem_handle);
 	if (idx >= CAM_MEM_BUFQ_MAX || idx <= 0) {
-		CAM_ERR(CAM_CRM, "Incorrect index extracted from mem handle");
+		CAM_ERR(CAM_MEM, "Incorrect index extracted from mem handle");
 		return -EINVAL;
 	}
 
 	if (!tbl.bufq[idx].active) {
 		if (tbl.bufq[idx].vaddr == 0) {
-			CAM_ERR(CAM_CRM, "buffer is released already");
+			CAM_ERR(CAM_MEM, "buffer is released already");
 			return 0;
 		}
-		CAM_ERR(CAM_CRM, "Released buffer state should be active");
+		CAM_ERR(CAM_MEM, "Released buffer state should be active");
 		return -EINVAL;
 	}
 
 	if (tbl.bufq[idx].buf_handle != inp->mem_handle) {
-		CAM_ERR(CAM_CRM,
+		CAM_ERR(CAM_MEM,
 			"Released buf handle not matching within table");
 		return -EINVAL;
 	}
 
 	if (tbl.bufq[idx].num_hdl != 1) {
-		CAM_ERR(CAM_CRM,
+		CAM_ERR(CAM_MEM,
 			"Sec heap region should have only one smmu hdl");
 		return -ENODEV;
 	}
@@ -1234,22 +1235,22 @@
 	memcpy(&smmu_hdl, tbl.bufq[idx].hdls,
 		sizeof(int32_t));
 	if (inp->smmu_hdl != smmu_hdl) {
-		CAM_ERR(CAM_CRM,
+		CAM_ERR(CAM_MEM,
 			"Passed SMMU handle doesn't match with internal hdl");
 		return -ENODEV;
 	}
 
 	rc = cam_smmu_release_sec_heap(inp->smmu_hdl);
 	if (rc) {
-		CAM_ERR(CAM_CRM,
+		CAM_ERR(CAM_MEM,
 			"Sec heap region release failed");
 		return -ENODEV;
 	}
 
-	CAM_DBG(CAM_CRM, "Releasing hdl = %X", inp->mem_handle);
+	CAM_DBG(CAM_MEM, "Releasing hdl = %X", inp->mem_handle);
 	rc = cam_mem_util_unmap(idx, CAM_SMMU_MAPPING_KERNEL);
 	if (rc)
-		CAM_ERR(CAM_CRM, "unmapping secondary heap failed");
+		CAM_ERR(CAM_MEM, "unmapping secondary heap failed");
 
 	return rc;
 }
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 4602d6c..346cd56 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
@@ -482,7 +482,8 @@
 			trace_cam_req_mgr_apply_request(link, &apply_req, dev);
 
 			apply_req.trigger_point = trigger;
-			CAM_DBG(CAM_CRM, "SEND: link_hdl: %x pd %d req_id %lld",
+			CAM_DBG(CAM_REQ,
+				"SEND: link_hdl: %x pd %d req_id %lld",
 				link->link_hdl, pd, apply_req.request_id);
 			if (dev->ops && dev->ops->apply_req) {
 				rc = dev->ops->apply_req(&apply_req);
@@ -566,7 +567,7 @@
 
 	if (!rc && traverse_data.result == link->pd_mask) {
 		CAM_DBG(CAM_CRM,
-			"APPLY: link_hdl= %x idx= %d, req_id= %lld :%lld :%lld",
+			"READY: link_hdl= %x idx= %d, req_id= %lld :%lld :%lld",
 			link->link_hdl, idx,
 			apply_data[2].req_id,
 			apply_data[1].req_id,
@@ -742,13 +743,13 @@
 	sync_link = link->sync_link;
 	req_id = slot->req_id;
 
-	CAM_DBG(CAM_CRM,
+	CAM_DBG(CAM_REQ,
 		"link_hdl %x req %lld sync_self_ref %lld sof_counter %lld frame_skip_flag %d sync_link_self_ref %lld",
 		link->link_hdl, req_id, link->sync_self_ref, link->sof_counter,
 		link->frame_skip_flag, link->sync_link->sync_self_ref);
 
 	if (sync_link->sync_link_sof_skip) {
-		CAM_DBG(CAM_CRM,
+		CAM_DBG(CAM_REQ,
 			"No req applied on corresponding SOF on sync link: %x",
 			sync_link->link_hdl);
 		sync_link->sync_link_sof_skip = false;
@@ -761,7 +762,7 @@
 		__cam_req_mgr_sof_cnt_initialize(link);
 	} else if ((link->frame_skip_flag) &&
 		(sync_link->sync_self_ref != -1)) {
-		CAM_DBG(CAM_CRM, "Link[%x] Req[%lld] Resetting values ",
+		CAM_DBG(CAM_REQ, "Link[%x] Req[%lld] Resetting values ",
 			link->link_hdl, req_id);
 		__cam_req_mgr_reset_sof_cnt(link);
 		__cam_req_mgr_sof_cnt_initialize(link);
@@ -771,8 +772,8 @@
 
 	rc = __cam_req_mgr_check_link_is_ready(link, slot->idx, true, true);
 	if (rc) {
-		CAM_DBG(CAM_CRM,
-			"Req: %lld [My link]not available link: %x, rc=%d",
+		CAM_DBG(CAM_REQ,
+			"Req: %lld [My link] not ready on link: %x, rc=%d",
 			req_id, link->link_hdl, rc);
 		link->sync_link_sof_skip = true;
 		goto failure;
@@ -794,8 +795,8 @@
 	}
 
 	if ((sync_slot_idx != -1) &&
-	((sync_link->req.in_q->slot[sync_slot_idx].status ==
-	CRM_SLOT_STATUS_REQ_APPLIED) || (rc == 0))) {
+		((sync_link->req.in_q->slot[sync_slot_idx].status ==
+		CRM_SLOT_STATUS_REQ_APPLIED) || (rc == 0))) {
 		rc = __cam_req_mgr_validate_sof_cnt(link, sync_link);
 		if (rc) {
 			CAM_DBG(CAM_CRM,
@@ -804,7 +805,7 @@
 			goto failure;
 		}
 
-		CAM_DBG(CAM_CRM,
+		CAM_DBG(CAM_REQ,
 			"Req: %lld ready to apply on link: %x [validation successful]",
 			req_id, link->link_hdl);
 		/*
@@ -819,7 +820,7 @@
 			CAM_WARN(CAM_CRM, "Unexpected return value rc: %d", rc);
 		}
 	} else {
-		CAM_DBG(CAM_CRM,
+		CAM_DBG(CAM_REQ,
 			"Req: %lld [Other link] not ready to apply on link: %x",
 			req_id, sync_link->link_hdl);
 		rc = -EPERM;
@@ -862,7 +863,7 @@
 	 * - if in applied_state, somthign wrong.
 	 * - if in no_req state, no new req
 	 */
-	CAM_DBG(CAM_CRM, "SOF Req[%lld] idx %d req_status %d link_hdl %x",
+	CAM_DBG(CAM_REQ, "SOF Req[%lld] idx %d req_status %d link_hdl %x",
 		in_q->slot[in_q->rd_idx].req_id, in_q->rd_idx,
 		in_q->slot[in_q->rd_idx].status, link->link_hdl);
 
@@ -1115,6 +1116,32 @@
 }
 
 /**
+ * __cam_req_mgr_notify_sof_freeze()
+ *
+ * @brief : Notify devices on link on detecting a SOF freeze
+ * @link  : link on which the sof freeze was detected
+ *
+ */
+static void __cam_req_mgr_notify_sof_freeze(
+	struct cam_req_mgr_core_link *link)
+{
+	int                                  i = 0;
+	struct cam_req_mgr_link_evt_data     evt_data;
+	struct cam_req_mgr_connected_device *dev = NULL;
+
+	for (i = 0; i < link->num_devs; i++) {
+		dev = &link->l_dev[i];
+		evt_data.evt_type = CAM_REQ_MGR_LINK_EVT_SOF_FREEZE;
+		evt_data.dev_hdl = dev->dev_hdl;
+		evt_data.link_hdl =  link->link_hdl;
+		evt_data.req_id = 0;
+		evt_data.u.error = CRM_KMD_ERR_FATAL;
+		if (dev->ops && dev->ops->process_evt)
+			dev->ops->process_evt(&evt_data);
+	}
+}
+
+/**
  * __cam_req_mgr_sof_freeze()
  *
  * @brief : Apoptosis - Handles case when connected devices are not responding
@@ -1138,6 +1165,7 @@
 	CAM_ERR(CAM_CRM, "SOF freeze for session %d link 0x%x",
 		session->session_hdl, link->link_hdl);
 
+	__cam_req_mgr_notify_sof_freeze(link);
 	memset(&msg, 0, sizeof(msg));
 
 	msg.session_hdl = session->session_hdl;
@@ -1453,7 +1481,7 @@
 	link = (struct cam_req_mgr_core_link *)priv;
 	task_data = (struct crm_task_payload *)data;
 	flush_info  = (struct cam_req_mgr_flush_info *)&task_data->u;
-	CAM_DBG(CAM_CRM, "link_hdl %x req_id %lld type %d",
+	CAM_DBG(CAM_REQ, "link_hdl %x req_id %lld type %d",
 		flush_info->link_hdl,
 		flush_info->req_id,
 		flush_info->flush_type);
@@ -1652,7 +1680,7 @@
 	trace_cam_req_mgr_add_req(link, idx, add_req, tbl, device);
 
 	if (slot->req_ready_map == tbl->dev_mask) {
-		CAM_DBG(CAM_CRM, "idx %d req_id %lld pd %d SLOT READY",
+		CAM_DBG(CAM_REQ, "idx %d req_id %lld pd %d SLOT READY",
 			idx, add_req->req_id, tbl->pd);
 		slot->state = CRM_REQ_STATE_READY;
 	}
@@ -1780,7 +1808,7 @@
 	task_data = (struct crm_task_payload *)data;
 	trigger_data = (struct cam_req_mgr_trigger_notify *)&task_data->u;
 
-	CAM_DBG(CAM_CRM, "link_hdl %x frame_id %lld, trigger %x\n",
+	CAM_DBG(CAM_REQ, "link_hdl %x frame_id %lld, trigger %x\n",
 		trigger_data->link_hdl,
 		trigger_data->frame_id,
 		trigger_data->trigger);
@@ -1823,6 +1851,30 @@
 	return rc;
 }
 
+/**
+ * __cam_req_mgr_dev_handle_to_name()
+ *
+ * @brief    : Finds device name based on the device handle
+ * @dev_hdl  : Device handle whose name is to be found
+ * @link     : Link on which the device is connected
+ * @return   : String containing the device name
+ *
+ */
+static const char *__cam_req_mgr_dev_handle_to_name(
+	int32_t dev_hdl, struct cam_req_mgr_core_link *link)
+{
+	struct cam_req_mgr_connected_device *dev = NULL;
+	int i = 0;
+
+	for (i = 0; i < link->num_devs; i++) {
+		dev = &link->l_dev[i];
+
+		if (dev_hdl == dev->dev_hdl)
+			return dev->dev_info.name;
+	}
+
+	return "Invalid dev_hdl";
+}
 
 /* Linked devices' Callback section */
 
@@ -1848,8 +1900,6 @@
 		return -EINVAL;
 	}
 
-	CAM_DBG(CAM_CRM, "E: dev %x dev req %lld",
-		add_req->dev_hdl, add_req->req_id);
 	link = (struct cam_req_mgr_core_link *)
 		cam_get_device_priv(add_req->link_hdl);
 
@@ -1858,9 +1908,13 @@
 		return -EINVAL;
 	}
 
+	CAM_DBG(CAM_REQ, "dev name %s dev_hdl %d dev req %lld",
+		__cam_req_mgr_dev_handle_to_name(add_req->dev_hdl, link),
+		add_req->dev_hdl, add_req->req_id);
+
 	mutex_lock(&link->lock);
 	spin_lock_bh(&link->link_state_spin_lock);
-	if (link->state != CAM_CRM_LINK_STATE_READY) {
+	if (link->state < CAM_CRM_LINK_STATE_READY) {
 		CAM_WARN(CAM_CRM, "invalid link state:%d", link->state);
 		rc = -EPERM;
 		spin_unlock_bh(&link->link_state_spin_lock);
@@ -1997,7 +2051,7 @@
 	}
 
 	spin_lock_bh(&link->link_state_spin_lock);
-	if (link->state != CAM_CRM_LINK_STATE_READY) {
+	if (link->state < CAM_CRM_LINK_STATE_READY) {
 		CAM_WARN(CAM_CRM, "invalid link state:%d", link->state);
 		spin_unlock_bh(&link->link_state_spin_lock);
 		rc = -EPERM;
@@ -2324,6 +2378,7 @@
 int cam_req_mgr_link(struct cam_req_mgr_link_info *link_info)
 {
 	int                                     rc = 0;
+	int                                     wq_flag = 0;
 	char                                    buf[128];
 	struct cam_create_dev_hdl               root_dev;
 	struct cam_req_mgr_core_session        *cam_session;
@@ -2394,8 +2449,9 @@
 	/* Create worker for current link */
 	snprintf(buf, sizeof(buf), "%x-%x",
 		link_info->session_hdl, link->link_hdl);
+	wq_flag = CAM_WORKQ_FLAG_HIGH_PRIORITY | CAM_WORKQ_FLAG_SERIAL;
 	rc = cam_req_mgr_workq_create(buf, CRM_WORKQ_NUM_TASKS,
-		&link->workq, CRM_WORKQ_USAGE_NON_IRQ);
+		&link->workq, CRM_WORKQ_USAGE_NON_IRQ, wq_flag);
 	if (rc < 0) {
 		CAM_ERR(CAM_CRM, "FATAL: unable to create worker");
 		__cam_req_mgr_destroy_link_info(link);
@@ -2497,7 +2553,7 @@
 		goto end;
 	}
 
-	CAM_DBG(CAM_CRM, "link %x req %lld, sync_mode %d",
+	CAM_DBG(CAM_CRM, "link 0x%x req %lld, sync_mode %d",
 		sched_req->link_hdl, sched_req->req_id, sched_req->sync_mode);
 
 	task_data.type = CRM_WORKQ_TASK_SCHED_REQ;
@@ -2514,8 +2570,8 @@
 
 	rc = cam_req_mgr_process_sched_req(link, &task_data);
 
-	CAM_DBG(CAM_CRM, "DONE dev %x req %lld sync_mode %d",
-		sched_req->link_hdl, sched_req->req_id, sched_req->sync_mode);
+	CAM_DBG(CAM_REQ, "Open req %lld on link 0x%x with sync_mode %d",
+		sched_req->req_id, sched_req->link_hdl, sched_req->sync_mode);
 end:
 	mutex_unlock(&g_crm_core_dev->crm_lock);
 	return rc;
@@ -2589,6 +2645,9 @@
 	link2->sync_link = link1;
 
 	cam_session->sync_mode = sync_info->sync_mode;
+	CAM_DBG(CAM_REQ,
+		"Sync config on link1 0x%x & link2 0x%x with sync_mode %d",
+		link1->link_hdl, link2->link_hdl, cam_session->sync_mode);
 
 done:
 	mutex_unlock(&cam_session->lock);
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c
index 9a93feb..543e332 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_dev.c
@@ -591,6 +591,7 @@
 	cam_v4l2_device_cleanup();
 	mutex_destroy(&g_dev.dev_lock);
 	g_dev.state = false;
+	g_dev.subdev_nodes_created = false;
 
 	return 0;
 }
@@ -680,6 +681,7 @@
 		.name = "cam_req_mgr",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_req_mgr_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
index 1ca6cc5..9929212 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_interface.h
@@ -177,13 +177,18 @@
 
 /**
  * enum cam_req_mgr_link_evt_type
- * @CAM_REQ_MGR_LINK_EVT_ERR:
- * @CAM_REQ_MGR_LINK_EVT_MAX:
+ * @CAM_REQ_MGR_LINK_EVT_ERR        : error on the link from any of the
+ *                                    connected devices
+ * @CAM_REQ_MGR_LINK_EVT_PAUSE      : to pause the link
+ * @CAM_REQ_MGR_LINK_EVT_RESUME     : resumes the link which was paused
+ * @CAM_REQ_MGR_LINK_EVT_SOF_FREEZE : request manager has detected an sof freeze
+ * @CAM_REQ_MGR_LINK_EVT_MAX        : invalid event type
  */
 enum cam_req_mgr_link_evt_type {
 	CAM_REQ_MGR_LINK_EVT_ERR,
 	CAM_REQ_MGR_LINK_EVT_PAUSE,
 	CAM_REQ_MGR_LINK_EVT_RESUME,
+	CAM_REQ_MGR_LINK_EVT_SOF_FREEZE,
 	CAM_REQ_MGR_LINK_EVT_MAX,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
index 066efd6..3798ef8 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
@@ -178,9 +178,10 @@
 }
 
 int cam_req_mgr_workq_create(char *name, int32_t num_tasks,
-	struct cam_req_mgr_core_workq **workq, enum crm_workq_context in_irq)
+	struct cam_req_mgr_core_workq **workq, enum crm_workq_context in_irq,
+	int flags)
 {
-	int32_t i;
+	int32_t i, wq_flags = 0, max_active_tasks = 0;
 	struct crm_workq_task  *task;
 	struct cam_req_mgr_core_workq *crm_workq = NULL;
 	char buf[128] = "crm_workq-";
@@ -192,10 +193,17 @@
 		if (crm_workq == NULL)
 			return -ENOMEM;
 
+		wq_flags |= WQ_UNBOUND;
+		if (flags & CAM_WORKQ_FLAG_HIGH_PRIORITY)
+			wq_flags |= WQ_HIGHPRI;
+
+		if (flags & CAM_WORKQ_FLAG_SERIAL)
+			max_active_tasks = 1;
+
 		strlcat(buf, name, sizeof(buf));
 		CAM_DBG(CAM_CRM, "create workque crm_workq-%s", name);
 		crm_workq->job = alloc_workqueue(buf,
-			WQ_HIGHPRI | WQ_UNBOUND, 0, NULL);
+			wq_flags, max_active_tasks, NULL);
 		if (!crm_workq->job) {
 			kfree(crm_workq);
 			return -ENOMEM;
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.h
index eb3b804..af76ae46 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.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
@@ -23,6 +23,15 @@
 
 #include "cam_req_mgr_core.h"
 
+/* Flag to create a high priority workq */
+#define CAM_WORKQ_FLAG_HIGH_PRIORITY             (1 << 0)
+
+/* This flag ensures only one task from a given
+ * workq will execute at any given point on any
+ * given CPU.
+ */
+#define CAM_WORKQ_FLAG_SERIAL                    (1 << 1)
+
 /* Task priorities, lower the number higher the priority*/
 enum crm_task_priority {
 	CRM_TASK_PRIORITY_0,
@@ -101,11 +110,14 @@
  * @num_task : Num_tasks to be allocated for workq
  * @workq    : Double pointer worker
  * @in_irq   : Set to one if workq might be used in irq context
+ * @flags    : Bitwise OR of Flags for workq behavior.
+ *             e.g. CAM_REQ_MGR_WORKQ_HIGH_PRIORITY | CAM_REQ_MGR_WORKQ_SERIAL
  * This function will allocate and create workqueue and pass
  * the workq pointer to caller.
  */
 int cam_req_mgr_workq_create(char *name, int32_t num_tasks,
-	struct cam_req_mgr_core_workq **workq, enum crm_workq_context in_irq);
+	struct cam_req_mgr_core_workq **workq, enum crm_workq_context in_irq,
+	int flags);
 
 /**
  * cam_req_mgr_workq_destroy()
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 a34d70c..ed0a26b 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
@@ -53,6 +53,8 @@
 
 free_power_settings:
 	kfree(power_info->power_setting);
+	power_info->power_setting = NULL;
+	power_info->power_setting_size = 0;
 	return rc;
 }
 
@@ -268,7 +270,10 @@
 			CAM_ERR(CAM_ACTUATOR,
 				"Failed to apply settings: %d",
 				rc);
-			return rc;
+		} else {
+			CAM_DBG(CAM_ACTUATOR,
+				"Success:request ID: %d",
+				i2c_set->request_id);
 		}
 	}
 
@@ -358,6 +363,28 @@
 	return 0;
 }
 
+static void cam_actuator_update_req_mgr(
+	struct cam_actuator_ctrl_t *a_ctrl,
+	struct cam_packet *csl_packet)
+{
+	struct cam_req_mgr_add_request add_req;
+
+	add_req.link_hdl = a_ctrl->bridge_intf.link_hdl;
+	add_req.req_id = csl_packet->header.request_id;
+	add_req.dev_hdl = a_ctrl->bridge_intf.device_hdl;
+	add_req.skip_before_applying = 0;
+
+	if (a_ctrl->bridge_intf.crm_cb &&
+		a_ctrl->bridge_intf.crm_cb->add_req) {
+		a_ctrl->bridge_intf.crm_cb->add_req(&add_req);
+		CAM_DBG(CAM_ACTUATOR, "Request Id: %lld added to CRM",
+			add_req.req_id);
+	} else {
+		CAM_ERR(CAM_ACTUATOR, "Can't add Request ID: %lld to CRM",
+			csl_packet->header.request_id);
+	}
+}
+
 int32_t cam_actuator_publish_dev_info(struct cam_req_mgr_device_info *info)
 {
 	if (!info) {
@@ -367,7 +394,7 @@
 
 	info->dev_id = CAM_REQ_MGR_DEVICE_ACTUATOR;
 	strlcpy(info->name, CAM_ACTUATOR_NAME, sizeof(info->name));
-	info->p_delay = 0;
+	info->p_delay = 1;
 	info->trigger = CAM_TRIGGER_POINT_SOF;
 
 	return 0;
@@ -390,7 +417,6 @@
 	struct i2c_data_settings  *i2c_data = NULL;
 	struct i2c_settings_array *i2c_reg_settings = NULL;
 	struct cam_cmd_buf_desc   *cmd_desc = NULL;
-	struct cam_req_mgr_add_request  add_req;
 	struct cam_actuator_soc_private *soc_private = NULL;
 	struct cam_sensor_power_ctrl_t  *power_info = NULL;
 
@@ -554,6 +580,7 @@
 				"Auto move lens parsing failed: %d", rc);
 			return rc;
 		}
+		cam_actuator_update_req_mgr(a_ctrl, csl_packet);
 		break;
 	case CAM_ACTUATOR_PACKET_MANUAL_MOVE_LENS:
 		if (a_ctrl->cam_act_state < CAM_ACTUATOR_CONFIG) {
@@ -563,11 +590,13 @@
 				a_ctrl->cam_act_state);
 			return rc;
 		}
+
+		a_ctrl->setting_apply_state = ACT_APPLY_SETTINGS_LATER;
 		i2c_data = &(a_ctrl->i2c_data);
 		i2c_reg_settings = &i2c_data->per_frame[
 			csl_packet->header.request_id % MAX_PER_FRAME_ARRAY];
 
-		i2c_data->init_settings.request_id =
+		 i2c_reg_settings->request_id =
 			csl_packet->header.request_id;
 		i2c_reg_settings->is_settings_valid = 1;
 		offset = (uint32_t *)&csl_packet->payload;
@@ -582,20 +611,19 @@
 				"Manual move lens parsing failed: %d", rc);
 			return rc;
 		}
-		break;
-	}
 
-	if ((csl_packet->header.op_code & 0xFFFFFF) !=
-		CAM_ACTUATOR_PACKET_OPCODE_INIT) {
-		add_req.link_hdl = a_ctrl->bridge_intf.link_hdl;
-		add_req.req_id = csl_packet->header.request_id;
-		add_req.dev_hdl = a_ctrl->bridge_intf.device_hdl;
-		add_req.skip_before_applying = 0;
-		if (a_ctrl->bridge_intf.crm_cb &&
-			a_ctrl->bridge_intf.crm_cb->add_req)
-			a_ctrl->bridge_intf.crm_cb->add_req(&add_req);
-		CAM_DBG(CAM_ACTUATOR, "Req Id: %lld added to Bridge",
-			add_req.req_id);
+		cam_actuator_update_req_mgr(a_ctrl, csl_packet);
+		break;
+	case CAM_PKT_NOP_OPCODE:
+		if (a_ctrl->cam_act_state < CAM_ACTUATOR_CONFIG) {
+			CAM_WARN(CAM_ACTUATOR,
+				"Received NOP packets in invalid state: %d",
+				a_ctrl->cam_act_state);
+			return -EINVAL;
+		}
+
+		cam_actuator_update_req_mgr(a_ctrl, csl_packet);
+		break;
 	}
 
 	return rc;
@@ -632,6 +660,8 @@
 	kfree(power_info->power_down_setting);
 	power_info->power_setting = NULL;
 	power_info->power_down_setting = NULL;
+	power_info->power_setting_size = 0;
+	power_info->power_down_setting_size = 0;
 
 	a_ctrl->cam_act_state = CAM_ACTUATOR_INIT;
 }
@@ -641,12 +671,19 @@
 {
 	int rc = 0;
 	struct cam_control *cmd = (struct cam_control *)arg;
+	struct cam_actuator_soc_private *soc_private = NULL;
+	struct cam_sensor_power_ctrl_t  *power_info = NULL;
 
 	if (!a_ctrl || !cmd) {
-		CAM_ERR(CAM_ACTUATOR, " Invalid Args");
+		CAM_ERR(CAM_ACTUATOR, "Invalid Args");
 		return -EINVAL;
 	}
 
+	soc_private =
+		(struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
+
+	power_info = &soc_private->power_info;
+
 	if (cmd->handle_type != CAM_HANDLE_USER_POINTER) {
 		CAM_ERR(CAM_ACTUATOR, "Invalid handle type: %d",
 			cmd->handle_type);
@@ -729,6 +766,12 @@
 		a_ctrl->bridge_intf.link_hdl = -1;
 		a_ctrl->bridge_intf.session_hdl = -1;
 		a_ctrl->cam_act_state = CAM_ACTUATOR_INIT;
+		kfree(power_info->power_setting);
+		kfree(power_info->power_down_setting);
+		power_info->power_setting = NULL;
+		power_info->power_down_setting = NULL;
+		power_info->power_down_setting_size = 0;
+		power_info->power_setting_size = 0;
 	}
 		break;
 	case CAM_QUERY_CAP: {
@@ -835,6 +878,11 @@
 		return -EINVAL;
 	}
 
+	if (a_ctrl->i2c_data.per_frame == NULL) {
+		CAM_ERR(CAM_ACTUATOR, "i2c frame data is NULL");
+		return -EINVAL;
+	}
+
 	for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
 		i2c_set = &(a_ctrl->i2c_data.per_frame[i]);
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
index 96fdfeb..7d23f90 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_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
@@ -252,6 +252,8 @@
 	a_ctrl->io_master_info.cci_client = NULL;
 	kfree(power_info->power_setting);
 	kfree(power_info->power_down_setting);
+	power_info->power_setting = NULL;
+	power_info->power_down_setting = NULL;
 	kfree(a_ctrl->soc_info.soc_private);
 	kfree(a_ctrl->i2c_data.per_frame);
 	a_ctrl->i2c_data.per_frame = NULL;
@@ -284,6 +286,8 @@
 	kfree(power_info->power_setting);
 	kfree(power_info->power_down_setting);
 	kfree(a_ctrl->soc_info.soc_private);
+	power_info->power_setting = NULL;
+	power_info->power_down_setting = NULL;
 	a_ctrl->soc_info.soc_private = NULL;
 	kfree(a_ctrl);
 	return rc;
@@ -393,6 +397,7 @@
 		.name = "qcom,actuator",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_actuator_driver_dt_match,
+		.suppress_bind_attrs = true,
 	},
 	.remove = cam_actuator_platform_remove,
 };
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c
index b47f4f3..058e352 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_core.c
@@ -1410,7 +1410,7 @@
 		else
 			rc = cam_cci_read(sd, c_ctrl);
 
-		if (!rc) {
+		if (rc) {
 			CAM_ERR(CAM_CCI, "failed to read rc:%d", rc);
 			goto ERROR;
 		}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c
index c8ca85d..ce7ac3f 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_dev.c
@@ -373,6 +373,7 @@
 		.name = CAMX_CCI_DEV_NAME,
 		.owner = THIS_MODULE,
 		.of_match_table = cam_cci_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
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 2688cd5..bc61df4 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
@@ -177,7 +177,7 @@
 
 	if (!csiphy_dev) {
 		CAM_ERR(CAM_CSIPHY, "Invalid Args");
-		return -EINVAL;
+		return IRQ_NONE;
 	}
 
 	soc_info = &csiphy_dev->soc_info;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c
index e2f061f..32bb34b 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_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
@@ -233,6 +233,7 @@
 		.name = CAMX_CSIPHY_DEV_NAME,
 		.owner = THIS_MODULE,
 		.of_match_table = cam_csiphy_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
index afe4239..9c85af3 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_dev.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
@@ -198,7 +198,6 @@
  * @csiphy_reg_ptr: Regulator structure
  * @csiphy_3p_clk_info: 3Phase clock information
  * @csiphy_3p_clk: 3Phase clocks structure
- * @csiphy_clk_index: Timer Src clk index
  * @csi_3phase: Is it a 3Phase mode
  * @ref_count: Reference count
  * @clk_lane: Clock lane
@@ -216,7 +215,6 @@
 	uint32_t csiphy_max_clk;
 	struct msm_cam_clk_info csiphy_3p_clk_info[2];
 	struct clk *csiphy_3p_clk[2];
-	uint32_t csiphy_clk_index;
 	unsigned char csi_3phase;
 	int32_t ref_count;
 	uint16_t lane_mask[MAX_CSIPHY];
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
index 6db5a97..28326ec 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -97,10 +97,8 @@
 		return rc;
 	}
 
-	rc = cam_soc_util_set_clk_rate(
-		soc_info->clk[csiphy_dev->csiphy_clk_index],
-		soc_info->clk_name[csiphy_dev->csiphy_clk_index],
-		soc_info->clk_rate[0][csiphy_dev->csiphy_clk_index]);
+	rc = cam_soc_util_set_src_clk_rate(soc_info,
+		soc_info->clk_rate[0][soc_info->src_clk_idx]);
 
 	if (rc < 0) {
 		CAM_ERR(CAM_CSIPHY, "csiphy_clk_set_rate failed rc: %d", rc);
@@ -208,16 +206,14 @@
 			continue;
 		}
 
-		if (!strcmp(soc_info->clk_name[i],
-			"csiphy_timer_src_clk")) {
-			csiphy_dev->csiphy_max_clk =
-			soc_info->clk_rate[0][clk_cnt];
-			csiphy_dev->csiphy_clk_index = clk_cnt;
-		}
 		CAM_DBG(CAM_CSIPHY, "clk_rate[%d] = %d", clk_cnt,
 			soc_info->clk_rate[0][clk_cnt]);
 		clk_cnt++;
 	}
+
+	csiphy_dev->csiphy_max_clk =
+		soc_info->clk_rate[0][soc_info->src_clk_idx];
+
 	rc = cam_soc_util_request_platform_resource(&csiphy_dev->soc_info,
 		cam_csiphy_irq, csiphy_dev);
 
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 7f94f8d..c8730ca 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
@@ -785,6 +785,8 @@
 		kfree(power_info->power_down_setting);
 		power_info->power_setting = NULL;
 		power_info->power_down_setting = NULL;
+		power_info->power_setting_size = 0;
+		power_info->power_down_setting_size = 0;
 		e_ctrl->cal_data.num_data = 0;
 		e_ctrl->cal_data.num_map = 0;
 		break;
@@ -838,6 +840,8 @@
 		kfree(power_info->power_down_setting);
 		power_info->power_setting = NULL;
 		power_info->power_down_setting = NULL;
+		power_info->power_setting_size = 0;
+		power_info->power_down_setting_size = 0;
 	}
 
 	e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
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 b8c32d4..cc34a70 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
@@ -508,6 +508,7 @@
 		.name = "qcom,eeprom",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_eeprom_dt_match,
+		.suppress_bind_attrs = true,
 	},
 	.probe = cam_eeprom_platform_driver_probe,
 	.remove = cam_eeprom_platform_driver_remove,
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c
index 5a6a401..afab016 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -135,7 +135,7 @@
 		return rc;
 	}
 
-	map = kzalloc((sizeof(*map) * data->num_map), GFP_KERNEL);
+	map = vzalloc((sizeof(*map) * data->num_map));
 	if (!map) {
 		rc = -ENOMEM;
 		return rc;
@@ -184,7 +184,7 @@
 		data->num_data += map[i].mem.valid_size;
 	}
 
-	data->mapdata = kzalloc(data->num_data, GFP_KERNEL);
+	data->mapdata = vzalloc(data->num_data);
 	if (!data->mapdata) {
 		rc = -ENOMEM;
 		goto ERROR;
@@ -192,7 +192,7 @@
 	return rc;
 
 ERROR:
-	kfree(data->map);
+	vfree(data->map);
 	memset(data, 0, sizeof(*data));
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
index 9b74826..4a9cfb0 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_core.c
@@ -151,7 +151,7 @@
 				else
 					curr = soc_private->torch_op_current[i];
 
-				CAM_DBG(CAM_FLASH,
+				CAM_DBG(CAM_PERF,
 					"Led_Current[%d] = %d", i, curr);
 				cam_res_mgr_led_trigger_event(
 					flash_ctrl->torch_trigger[i],
@@ -169,7 +169,7 @@
 				else
 					curr = soc_private->flash_op_current[i];
 
-				CAM_DBG(CAM_FLASH, "LED flash_current[%d]: %d",
+				CAM_DBG(CAM_PERF, "LED flash_current[%d]: %d",
 					i, curr);
 				cam_res_mgr_led_trigger_event(
 					flash_ctrl->flash_trigger[i],
@@ -191,25 +191,11 @@
 
 int cam_flash_off(struct cam_flash_ctrl *flash_ctrl)
 {
-	int i = 0;
-
 	if (!flash_ctrl) {
 		CAM_ERR(CAM_FLASH, "Flash control Null");
 		return -EINVAL;
 	}
 
-	for (i = 0; i < flash_ctrl->flash_num_sources; i++)
-		if (flash_ctrl->flash_trigger[i])
-			cam_res_mgr_led_trigger_event(
-				flash_ctrl->flash_trigger[i],
-				LED_OFF);
-
-	for (i = 0; i < flash_ctrl->torch_num_sources; i++)
-		if (flash_ctrl->torch_trigger[i])
-			cam_res_mgr_led_trigger_event(
-				flash_ctrl->torch_trigger[i],
-				LED_OFF);
-
 	if (flash_ctrl->switch_trigger)
 		cam_res_mgr_led_trigger_event(flash_ctrl->switch_trigger,
 			LED_SWITCH_OFF);
@@ -352,6 +338,10 @@
 		if (fctrl->nrt_info.cmn_attr.cmd_type ==
 			CAMERA_SENSOR_FLASH_CMD_TYPE_INIT_FIRE) {
 			flash_data = &fctrl->nrt_info;
+			CAM_DBG(CAM_REQ,
+				"FLASH_INIT_FIRE req_id: %u flash_opcode: %d",
+				req_id, flash_data->opcode);
+
 			if (flash_data->opcode ==
 				CAMERA_SENSOR_FLASH_OP_FIREHIGH) {
 				if (fctrl->flash_state !=
@@ -395,6 +385,10 @@
 		} else if (fctrl->nrt_info.cmn_attr.cmd_type ==
 			CAMERA_SENSOR_FLASH_CMD_TYPE_WIDGET) {
 			flash_data = &fctrl->nrt_info;
+			CAM_DBG(CAM_REQ,
+				"FLASH_WIDGET req_id: %u flash_opcode: %d",
+				req_id, flash_data->opcode);
+
 			if (flash_data->opcode ==
 				CAMERA_SENSOR_FLASH_OP_FIRELOW) {
 				rc = cam_flash_low(fctrl, flash_data);
@@ -425,6 +419,8 @@
 					goto nrt_del_req;
 				}
 			}
+			CAM_DBG(CAM_REQ, "FLASH_RER req_id: %u", req_id);
+
 			num_iterations = flash_data->num_iterations;
 			for (i = 0; i < num_iterations; i++) {
 				/* Turn On Torch */
@@ -459,6 +455,8 @@
 	} else {
 		frame_offset = req_id % MAX_PER_FRAME_ARRAY;
 		flash_data = &fctrl->per_frame[frame_offset];
+		CAM_DBG(CAM_REQ, "FLASH_RT req_id: %u flash_opcode: %d",
+			req_id, flash_data->opcode);
 
 		if ((flash_data->opcode == CAMERA_SENSOR_FLASH_OP_FIREHIGH) &&
 			(flash_data->cmn_attr.is_settings_valid) &&
@@ -496,8 +494,14 @@
 					"Flash off failed %d", rc);
 				goto apply_setting_err;
 			}
+		} else if (flash_data->opcode == CAM_PKT_NOP_OPCODE) {
+			flash_data->opcode = 0;
+			CAM_DBG(CAM_FLASH, "NOP Packet");
 		} else {
-			CAM_DBG(CAM_FLASH, "NOP opcode: req_id: %u", req_id);
+			rc = -EINVAL;
+			CAM_ERR(CAM_FLASH, "Invalid opcode: %d req_id: %llu",
+				flash_data->opcode, req_id);
+			goto apply_setting_err;
 		}
 	}
 
@@ -768,17 +772,20 @@
 		break;
 	}
 	case CAM_PKT_NOP_OPCODE: {
+		frm_offset = csl_packet->header.request_id %
+			MAX_PER_FRAME_ARRAY;
 		if ((fctrl->flash_state == CAM_FLASH_STATE_INIT) ||
 			(fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) {
 			CAM_WARN(CAM_FLASH,
 				"Rxed NOP packets without linking");
-			frm_offset = csl_packet->header.request_id %
-				MAX_PER_FRAME_ARRAY;
 			fctrl->per_frame[frm_offset].cmn_attr.is_settings_valid
 				= false;
 			return 0;
 		}
 
+		fctrl->per_frame[frm_offset].cmn_attr.is_settings_valid = false;
+		fctrl->per_frame[frm_offset].cmn_attr.request_id = 0;
+		fctrl->per_frame[frm_offset].opcode = CAM_PKT_NOP_OPCODE;
 		CAM_DBG(CAM_FLASH, "NOP Packet is Received: req_id: %u",
 			csl_packet->header.request_id);
 		goto update_req_mgr;
@@ -928,19 +935,15 @@
 	fctrl = (struct cam_flash_ctrl *) cam_get_device_priv(apply->dev_hdl);
 	if (!fctrl) {
 		CAM_ERR(CAM_FLASH, "Device data is NULL");
-		rc = -EINVAL;
-		goto free_resource;
+		return -EINVAL;
 	}
 
-	if (!(apply->report_if_bubble)) {
-		mutex_lock(&fctrl->flash_wq_mutex);
-		rc = cam_flash_apply_setting(fctrl, apply->request_id);
-		if (rc)
-			CAM_ERR(CAM_FLASH, "apply_setting failed with rc=%d",
-				rc);
-		mutex_unlock(&fctrl->flash_wq_mutex);
-	}
+	mutex_lock(&fctrl->flash_wq_mutex);
+	rc = cam_flash_apply_setting(fctrl, apply->request_id);
+	if (rc)
+		CAM_ERR(CAM_FLASH, "apply_setting failed with rc=%d",
+			rc);
+	mutex_unlock(&fctrl->flash_wq_mutex);
 
-free_resource:
 	return rc;
 }
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 f9411fc..d9b5f64 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
@@ -394,6 +394,7 @@
 		.name = "CAM-FLASH-DRIVER",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_flash_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h
index 92726a9..4adc1b2 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_flash/cam_flash_dev.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
@@ -78,10 +78,10 @@
  * @cmd_type           : Command buffer type
  */
 struct cam_flash_common_attr {
-	bool     is_settings_valid;
-	int32_t  request_id;
-	uint16_t count;
-	uint8_t  cmd_type;
+	bool      is_settings_valid;
+	uint64_t  request_id;
+	uint16_t  count;
+	uint8_t   cmd_type;
 };
 
 /**
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 dfcb9fc..c2d2e5f 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
@@ -55,6 +55,8 @@
 
 free_power_settings:
 	kfree(power_info->power_setting);
+	power_info->power_setting = NULL;
+	power_info->power_setting_size = 0;
 	return rc;
 }
 
@@ -637,10 +639,9 @@
 void cam_ois_shutdown(struct cam_ois_ctrl_t *o_ctrl)
 {
 	int rc = 0;
-	struct cam_ois_soc_private  *soc_private =
+	struct cam_ois_soc_private *soc_private =
 		(struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private;
-	struct cam_sensor_power_ctrl_t *power_info =
-		&soc_private->power_info;
+	struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info;
 
 	if (o_ctrl->cam_ois_state == CAM_OIS_INIT)
 		return;
@@ -665,6 +666,8 @@
 	kfree(power_info->power_down_setting);
 	power_info->power_setting = NULL;
 	power_info->power_down_setting = NULL;
+	power_info->power_down_setting_size = 0;
+	power_info->power_setting_size = 0;
 
 	o_ctrl->cam_ois_state = CAM_OIS_INIT;
 }
@@ -678,11 +681,13 @@
  */
 int cam_ois_driver_cmd(struct cam_ois_ctrl_t *o_ctrl, void *arg)
 {
-	int                            rc = 0;
-	struct cam_ois_query_cap_t     ois_cap = {0};
-	struct cam_control            *cmd = (struct cam_control *)arg;
+	int                              rc = 0;
+	struct cam_ois_query_cap_t       ois_cap = {0};
+	struct cam_control              *cmd = (struct cam_control *)arg;
+	struct cam_ois_soc_private      *soc_private = NULL;
+	struct cam_sensor_power_ctrl_t  *power_info = NULL;
 
-	if (!o_ctrl || !arg) {
+	if (!o_ctrl || !cmd) {
 		CAM_ERR(CAM_OIS, "Invalid arguments");
 		return -EINVAL;
 	}
@@ -693,6 +698,10 @@
 		return -EINVAL;
 	}
 
+	soc_private =
+		(struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private;
+	power_info = &soc_private->power_info;
+
 	mutex_lock(&(o_ctrl->ois_mutex));
 	switch (cmd->op_code) {
 	case CAM_QUERY_CAP:
@@ -763,6 +772,13 @@
 		o_ctrl->bridge_intf.link_hdl = -1;
 		o_ctrl->bridge_intf.session_hdl = -1;
 		o_ctrl->cam_ois_state = CAM_OIS_INIT;
+
+		kfree(power_info->power_setting);
+		kfree(power_info->power_down_setting);
+		power_info->power_setting = NULL;
+		power_info->power_down_setting = NULL;
+		power_info->power_down_setting_size = 0;
+		power_info->power_setting_size = 0;
 		break;
 	case CAM_STOP_DEV:
 		if (o_ctrl->cam_ois_state != CAM_OIS_START) {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c
index d742acf..5d16a4e 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_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
@@ -240,6 +240,8 @@
 
 	kfree(power_info->power_setting);
 	kfree(power_info->power_down_setting);
+	power_info->power_setting = NULL;
+	power_info->power_down_setting = NULL;
 	kfree(o_ctrl->soc_info.soc_private);
 	kfree(o_ctrl);
 
@@ -341,6 +343,8 @@
 
 	kfree(power_info->power_setting);
 	kfree(power_info->power_down_setting);
+	power_info->power_setting = NULL;
+	power_info->power_down_setting = NULL;
 	kfree(o_ctrl->soc_info.soc_private);
 	kfree(o_ctrl->io_master_info.cci_client);
 	kfree(o_ctrl);
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr.c
index bb3789b..d03faef 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_res_mgr/cam_res_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -718,6 +718,7 @@
 		.name = "cam_res_mgr",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_res_mgr_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
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 2133932..a2431be 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
@@ -17,7 +17,6 @@
 #include "cam_soc_util.h"
 #include "cam_trace.h"
 
-
 static void cam_sensor_update_req_mgr(
 	struct cam_sensor_ctrl_t *s_ctrl,
 	struct cam_packet *csl_packet)
@@ -500,8 +499,8 @@
 		&s_ctrl->sensordata->power_info;
 	int rc = 0;
 
-	s_ctrl->is_probe_succeed = 0;
-	if (s_ctrl->sensor_state == CAM_SENSOR_INIT)
+	if ((s_ctrl->sensor_state == CAM_SENSOR_INIT) &&
+		(s_ctrl->is_probe_succeed == 0))
 		return;
 
 	cam_sensor_release_resource(s_ctrl);
@@ -515,14 +514,15 @@
 	s_ctrl->bridge_intf.device_hdl = -1;
 	s_ctrl->bridge_intf.link_hdl = -1;
 	s_ctrl->bridge_intf.session_hdl = -1;
-
 	kfree(power_info->power_setting);
 	kfree(power_info->power_down_setting);
 	power_info->power_setting = NULL;
 	power_info->power_down_setting = NULL;
-
+	power_info->power_setting_size = 0;
+	power_info->power_down_setting_size = 0;
 	s_ctrl->streamon_count = 0;
 	s_ctrl->streamoff_count = 0;
+	s_ctrl->is_probe_succeed = 0;
 	s_ctrl->sensor_state = CAM_SENSOR_INIT;
 }
 
@@ -561,8 +561,6 @@
 {
 	int rc = 0;
 	struct cam_control *cmd = (struct cam_control *)arg;
-	struct cam_sensor_power_setting *pu = NULL;
-	struct cam_sensor_power_setting *pd = NULL;
 	struct cam_sensor_power_ctrl_t *power_info =
 		&s_ctrl->sensordata->power_info;
 	if (!s_ctrl || !arg) {
@@ -592,19 +590,15 @@
 			rc = cam_handle_mem_ptr(cmd->handle, s_ctrl);
 			if (rc < 0) {
 				CAM_ERR(CAM_SENSOR, "Get Buffer Handle Failed");
-				kfree(pu);
-				kfree(pd);
 				goto release_mutex;
 			}
 		} else {
 			CAM_ERR(CAM_SENSOR, "Invalid Command Type: %d",
 				 cmd->handle_type);
-			return -EINVAL;
+			rc = -EINVAL;
+			goto release_mutex;
 		}
 
-		pu = power_info->power_setting;
-		pd = power_info->power_down_setting;
-
 		/* Parse and fill vreg params for powerup settings */
 		rc = msm_camera_fill_vreg_params(
 			&s_ctrl->soc_info,
@@ -614,9 +608,7 @@
 			CAM_ERR(CAM_SENSOR,
 				"Fail in filling vreg params for PUP rc %d",
 				 rc);
-			kfree(pu);
-			kfree(pd);
-			goto release_mutex;
+			goto free_power_settings;
 		}
 
 		/* Parse and fill vreg params for powerdown settings*/
@@ -628,18 +620,14 @@
 			CAM_ERR(CAM_SENSOR,
 				"Fail in filling vreg params for PDOWN rc %d",
 				 rc);
-			kfree(pu);
-			kfree(pd);
-			goto release_mutex;
+			goto free_power_settings;
 		}
 
 		/* Power up and probe sensor */
 		rc = cam_sensor_power_up(s_ctrl);
 		if (rc < 0) {
 			CAM_ERR(CAM_SENSOR, "power up failed");
-			kfree(pu);
-			kfree(pd);
-			goto release_mutex;
+			goto free_power_settings;
 		}
 
 		/* Match sensor ID */
@@ -647,13 +635,11 @@
 		if (rc < 0) {
 			cam_sensor_power_down(s_ctrl);
 			msleep(20);
-			kfree(pu);
-			kfree(pd);
-			goto release_mutex;
+			goto free_power_settings;
 		}
 
 		CAM_INFO(CAM_SENSOR,
-			"Probe Succees,slot:%d,slave_addr:0x%x,sensor_id:0x%x",
+			"Probe success,slot:%d,slave_addr:0x%x,sensor_id:0x%x",
 			s_ctrl->soc_info.index,
 			s_ctrl->sensordata->slave_info.sensor_slave_addr,
 			s_ctrl->sensordata->slave_info.sensor_id);
@@ -661,9 +647,7 @@
 		rc = cam_sensor_power_down(s_ctrl);
 		if (rc < 0) {
 			CAM_ERR(CAM_SENSOR, "fail in Sensor Power Down");
-			kfree(pu);
-			kfree(pd);
-			goto release_mutex;
+			goto free_power_settings;
 		}
 		/*
 		 * Set probe succeeded flag to 1 so that no other camera shall
@@ -677,6 +661,15 @@
 		struct cam_sensor_acquire_dev sensor_acq_dev;
 		struct cam_create_dev_hdl bridge_params;
 
+		if ((s_ctrl->is_probe_succeed == 0) ||
+			(s_ctrl->sensor_state != CAM_SENSOR_INIT)) {
+			CAM_WARN(CAM_SENSOR,
+				"Not in right state to aquire %d",
+				s_ctrl->sensor_state);
+			rc = -EINVAL;
+			goto release_mutex;
+		}
+
 		if (s_ctrl->bridge_intf.device_hdl != -1) {
 			CAM_ERR(CAM_SENSOR, "Device is already acquired");
 			rc = -EINVAL;
@@ -885,6 +878,16 @@
 release_mutex:
 	mutex_unlock(&(s_ctrl->cam_sensor_mutex));
 	return rc;
+
+free_power_settings:
+	kfree(power_info->power_setting);
+	kfree(power_info->power_down_setting);
+	power_info->power_setting = NULL;
+	power_info->power_down_setting = NULL;
+	power_info->power_down_setting_size = 0;
+	power_info->power_setting_size = 0;
+	mutex_unlock(&(s_ctrl->cam_sensor_mutex));
+	return rc;
 }
 
 int cam_sensor_publish_dev_info(struct cam_req_mgr_device_info *info)
@@ -961,6 +964,16 @@
 		return -EINVAL;
 	}
 
+	if (s_ctrl->bob_pwm_switch) {
+		rc = cam_sensor_bob_pwm_mode_switch(soc_info,
+			s_ctrl->bob_reg_index, true);
+		if (rc) {
+			CAM_WARN(CAM_SENSOR,
+			"BoB PWM setup failed rc: %d", rc);
+			rc = 0;
+		}
+	}
+
 	rc = cam_sensor_core_power_up(power_info, soc_info);
 	if (rc < 0) {
 		CAM_ERR(CAM_SENSOR, "power up the core is failed:%d", rc);
@@ -998,6 +1011,16 @@
 		return rc;
 	}
 
+	if (s_ctrl->bob_pwm_switch) {
+		rc = cam_sensor_bob_pwm_mode_switch(soc_info,
+			s_ctrl->bob_reg_index, false);
+		if (rc) {
+			CAM_WARN(CAM_SENSOR,
+				"BoB PWM setup failed rc: %d", rc);
+			rc = 0;
+		}
+	}
+
 	camera_io_release(&(s_ctrl->io_master_info));
 
 	return rc;
@@ -1130,7 +1153,7 @@
 		CAM_ERR(CAM_SENSOR, "Device data is NULL");
 		return -EINVAL;
 	}
-	CAM_DBG(CAM_SENSOR, " Req Id: %lld", apply->request_id);
+	CAM_DBG(CAM_REQ, " Sensor update req id: %lld", apply->request_id);
 	trace_cam_apply_req("Sensor", apply->request_id);
 	rc = cam_sensor_apply_settings(s_ctrl, apply->request_id,
 		CAM_SENSOR_PACKET_OPCODE_SENSOR_UPDATE);
@@ -1154,6 +1177,11 @@
 		return -EINVAL;
 	}
 
+	if (s_ctrl->i2c_data.per_frame == NULL) {
+		CAM_ERR(CAM_SENSOR, "i2c frame data is NULL");
+		return -EINVAL;
+	}
+
 	for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
 		i2c_set = &(s_ctrl->i2c_data.per_frame[i]);
 
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c
index b60111a..6cf40f8 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_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
@@ -339,6 +339,7 @@
 		.name = "qcom,camera",
 		.owner = THIS_MODULE,
 		.of_match_table = cam_sensor_driver_dt_match,
+		.suppress_bind_attrs = true,
 	},
 	.remove = cam_sensor_platform_remove,
 };
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h
index cc6070c..34f8b8d 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_dev.h
@@ -92,6 +92,8 @@
  * @device_name: Sensor device structure
  * @streamon_count: Count to hold the number of times stream on called
  * @streamoff_count: Count to hold the number of times stream off called
+ * @bob_reg_index: Hold to BoB regulator index
+ * @bob_pwm_switch: Boolean flag to switch into PWM mode for BoB regulator
  */
 struct cam_sensor_ctrl_t {
 	struct platform_device *pdev;
@@ -113,6 +115,8 @@
 	char device_name[20];
 	uint32_t streamon_count;
 	uint32_t streamoff_count;
+	int bob_reg_index;
+	bool bob_pwm_switch;
 };
 
 #endif /* _CAM_SENSOR_DEV_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_soc.c
index 1c3ead0..e997419 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_soc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -104,6 +104,7 @@
 static int32_t cam_sensor_driver_get_dt_data(struct cam_sensor_ctrl_t *s_ctrl)
 {
 	int32_t rc = 0;
+	int i = 0;
 	struct cam_sensor_board_info *sensordata = NULL;
 	struct device_node *of_node = s_ctrl->of_node;
 	struct cam_hw_soc_info *soc_info = &s_ctrl->soc_info;
@@ -135,6 +136,33 @@
 		goto FREE_SENSOR_DATA;
 	}
 
+	/* Store the index of BoB regulator if it is available */
+	for (i = 0; i < soc_info->num_rgltr; i++) {
+		if (!strcmp(soc_info->rgltr_name[i],
+			"cam_bob")) {
+			CAM_DBG(CAM_SENSOR,
+				"i: %d cam_bob", i);
+			s_ctrl->bob_reg_index = i;
+			soc_info->rgltr[i] = devm_regulator_get(soc_info->dev,
+				soc_info->rgltr_name[i]);
+			if (IS_ERR_OR_NULL(soc_info->rgltr[i])) {
+				CAM_WARN(CAM_SENSOR,
+					"Regulator: %s get failed",
+					soc_info->rgltr_name[i]);
+				soc_info->rgltr[i] = NULL;
+			} else {
+				if (!of_property_read_bool(of_node,
+					"pwm-switch")) {
+					CAM_DBG(CAM_SENSOR,
+					"No BoB PWM switch param defined");
+					s_ctrl->bob_pwm_switch = false;
+				} else {
+					s_ctrl->bob_pwm_switch = true;
+				}
+			}
+		}
+	}
+
 	/* Read subdev info */
 	rc = cam_sensor_get_sub_module_index(of_node, sensordata);
 	if (rc < 0) {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c
index 1c6ab0b..9145a1e 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.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
@@ -245,9 +245,15 @@
 	enum camera_sensor_i2c_type data_type)
 {
 	int32_t rc = 0;
-	unsigned char buf[I2C_REG_MAX_BUF_SIZE];
+	unsigned char *buf = NULL;
 	uint8_t len = 0;
 
+	buf = kzalloc(I2C_REG_MAX_BUF_SIZE, GFP_KERNEL | GFP_DMA);
+	if (!buf) {
+		CAM_ERR(CAM_SENSOR, "Buffer memory allocation failed");
+		return -ENOMEM;
+	}
+
 	CAM_DBG(CAM_SENSOR, "reg addr = 0x%x data type: %d",
 			reg_setting->reg_addr, data_type);
 	if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) {
@@ -273,7 +279,8 @@
 		len = 4;
 	} else {
 		CAM_ERR(CAM_SENSOR, "Invalid I2C addr type");
-		return -EINVAL;
+		rc = -EINVAL;
+		goto deallocate_buffer;
 	}
 
 	CAM_DBG(CAM_SENSOR, "Data: 0x%x", reg_setting->reg_data);
@@ -307,12 +314,16 @@
 		len += 4;
 	} else {
 		CAM_ERR(CAM_SENSOR, "Invalid Data Type");
-		return -EINVAL;
+		rc = -EINVAL;
+		goto deallocate_buffer;
 	}
 
 	rc = cam_qup_i2c_txdata(client, buf, len);
 	if (rc < 0)
 		CAM_ERR(CAM_SENSOR, "failed rc: %d", rc);
+
+deallocate_buffer:
+	kfree(buf);
 	return rc;
 }
 
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 73a0cf7..46bda05 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
@@ -711,8 +711,10 @@
 		kzalloc(sizeof(struct cam_sensor_power_setting) *
 			MAX_POWER_CONFIG, GFP_KERNEL);
 	if (!power_info->power_down_setting) {
-		rc = -ENOMEM;
-		goto free_power_settings;
+		kfree(power_info->power_setting);
+		power_info->power_setting = NULL;
+		power_info->power_setting_size = 0;
+		return -ENOMEM;
 	}
 
 	while (tot_size < cmd_length) {
@@ -722,11 +724,18 @@
 				(struct cam_cmd_power *)ptr;
 
 			power_info->power_setting_size += pwr_cmd->count;
+			if (power_info->power_setting_size > MAX_POWER_CONFIG) {
+				CAM_ERR(CAM_SENSOR,
+					"Invalid: power up setting size %d",
+					power_info->power_setting_size);
+				rc = -EINVAL;
+				goto free_power_settings;
+			}
 			scr = ptr + sizeof(struct cam_cmd_power);
 			tot_size = tot_size + sizeof(struct cam_cmd_power);
 
 			if (pwr_cmd->count == 0)
-				CAM_WARN(CAM_SENSOR, "Un expected Command");
+				CAM_WARN(CAM_SENSOR, "pwr_up_size is zero");
 
 			for (i = 0; i < pwr_cmd->count; i++, pwr_up++) {
 				power_info->power_setting[pwr_up].seq_type =
@@ -746,7 +755,7 @@
 					CAM_ERR(CAM_SENSOR,
 						"Error: Cmd Buffer is wrong");
 					rc = -EINVAL;
-					goto free_power_down_settings;
+					goto free_power_settings;
 				}
 				CAM_DBG(CAM_SENSOR,
 				"Seq Type[%d]: %d Config_val: %ld", pwr_up,
@@ -814,9 +823,17 @@
 			scr = ptr + sizeof(struct cam_cmd_power);
 			tot_size = tot_size + sizeof(struct cam_cmd_power);
 			power_info->power_down_setting_size += pwr_cmd->count;
+			if (power_info->power_down_setting_size >
+				MAX_POWER_CONFIG) {
+				CAM_ERR(CAM_SENSOR,
+					"Invalid: power down setting size %d",
+					power_info->power_down_setting_size);
+				rc = -EINVAL;
+				goto free_power_settings;
+			}
 
 			if (pwr_cmd->count == 0)
-				CAM_ERR(CAM_SENSOR, "Invalid Command");
+				CAM_ERR(CAM_SENSOR, "pwr_down size is zero");
 
 			for (i = 0; i < pwr_cmd->count; i++, pwr_down++) {
 				pwr_settings =
@@ -840,7 +857,7 @@
 					CAM_ERR(CAM_SENSOR,
 						"Command Buffer is wrong");
 					rc = -EINVAL;
-					goto free_power_down_settings;
+					goto free_power_settings;
 				}
 				CAM_DBG(CAM_SENSOR,
 					"Seq Type[%d]: %d Config_val: %ld",
@@ -854,16 +871,19 @@
 			CAM_ERR(CAM_SENSOR,
 				"Error: Un expected Header Type: %d",
 				cmm_hdr->cmd_type);
+			rc = -EINVAL;
+			goto free_power_settings;
 		}
 	}
 
 	return rc;
-free_power_down_settings:
-	kfree(power_info->power_down_setting);
-	power_info->power_down_setting = NULL;
 free_power_settings:
+	kfree(power_info->power_down_setting);
 	kfree(power_info->power_setting);
+	power_info->power_down_setting = NULL;
 	power_info->power_setting = NULL;
+	power_info->power_down_setting_size = 0;
+	power_info->power_setting_size = 0;
 	return rc;
 }
 
@@ -1218,6 +1238,24 @@
 	return 0;
 }
 
+int cam_sensor_bob_pwm_mode_switch(struct cam_hw_soc_info *soc_info,
+	int bob_reg_idx, bool flag)
+{
+	int rc = 0;
+	uint32_t op_current =
+		(flag == true) ? soc_info->rgltr_op_mode[bob_reg_idx] : 0;
+
+	if (soc_info->rgltr[bob_reg_idx] != NULL) {
+		rc = regulator_set_load(soc_info->rgltr[bob_reg_idx],
+			op_current);
+		if (rc)
+			CAM_WARN(CAM_SENSOR,
+				"BoB PWM SetLoad failed rc: %d", rc);
+	}
+
+	return rc;
+}
+
 int msm_cam_sensor_handle_reg_gpio(int seq_type,
 	struct msm_camera_gpio_num_info *gpio_num_info, int val)
 {
@@ -1243,10 +1281,62 @@
 	return 0;
 }
 
+static int cam_config_mclk_reg(struct cam_sensor_power_ctrl_t *ctrl,
+	struct cam_hw_soc_info *soc_info, int32_t index)
+{
+	int32_t num_vreg = 0, j = 0, rc = 0, idx = 0;
+	struct cam_sensor_power_setting *ps = NULL;
+	struct cam_sensor_power_setting *pd = NULL;
+
+	num_vreg = soc_info->num_rgltr;
+
+	pd = &ctrl->power_down_setting[index];
+
+	for (j = 0; j < num_vreg; j++) {
+		if (!strcmp(soc_info->rgltr_name[j], "cam_clk")) {
+			ps = NULL;
+			for (idx = 0; idx < ctrl->power_setting_size; idx++) {
+				if (ctrl->power_setting[idx].seq_type ==
+					pd->seq_type) {
+					ps = &ctrl->power_setting[idx];
+					break;
+				}
+			}
+
+			if (ps != NULL) {
+				CAM_DBG(CAM_SENSOR, "Disable MCLK Regulator");
+				rc = cam_soc_util_regulator_disable(
+					soc_info->rgltr[j],
+					soc_info->rgltr_name[j],
+					soc_info->rgltr_min_volt[j],
+					soc_info->rgltr_max_volt[j],
+					soc_info->rgltr_op_mode[j],
+					soc_info->rgltr_delay[j]);
+
+				if (rc) {
+					CAM_ERR(CAM_SENSOR,
+						"MCLK REG DISALBE FAILED: %d",
+						rc);
+					return rc;
+				}
+
+				ps->data[0] =
+					soc_info->rgltr[j];
+
+				regulator_put(
+					soc_info->rgltr[j]);
+				soc_info->rgltr[j] = NULL;
+			}
+		}
+	}
+
+	return rc;
+}
+
 int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl,
 		struct cam_hw_soc_info *soc_info)
 {
-	int rc = 0, index = 0, no_gpio = 0, ret = 0, num_vreg, j = 0;
+	int rc = 0, index = 0, no_gpio = 0, ret = 0, num_vreg, j = 0, i = 0;
 	int32_t vreg_idx = -1;
 	struct cam_sensor_power_setting *power_setting = NULL;
 	struct msm_camera_gpio_num_info *gpio_num_info = NULL;
@@ -1343,6 +1433,7 @@
 							soc_info->rgltr_name[j],
 							rc);
 						soc_info->rgltr[j] = NULL;
+						goto power_up_failed;
 					}
 
 					rc =  cam_soc_util_regulator_enable(
@@ -1352,7 +1443,11 @@
 					soc_info->rgltr_max_volt[j],
 					soc_info->rgltr_op_mode[j],
 					soc_info->rgltr_delay[j]);
-
+					if (rc) {
+						CAM_ERR(CAM_SENSOR,
+							"Reg enable failed");
+						goto power_up_failed;
+					}
 					power_setting->data[0] =
 						soc_info->rgltr[j];
 				}
@@ -1433,6 +1528,7 @@
 						rc);
 
 					soc_info->rgltr[vreg_idx] = NULL;
+					goto power_up_failed;
 				}
 
 				rc =  cam_soc_util_regulator_enable(
@@ -1442,7 +1538,12 @@
 					soc_info->rgltr_max_volt[vreg_idx],
 					soc_info->rgltr_op_mode[vreg_idx],
 					soc_info->rgltr_delay[vreg_idx]);
-
+				if (rc) {
+					CAM_ERR(CAM_SENSOR,
+						"Reg Enable failed for %s",
+						soc_info->rgltr_name[vreg_idx]);
+					goto power_up_failed;
+				}
 				power_setting->data[0] =
 						soc_info->rgltr[vreg_idx];
 			}
@@ -1485,6 +1586,18 @@
 		CAM_DBG(CAM_SENSOR, "type %d",
 			power_setting->seq_type);
 		switch (power_setting->seq_type) {
+		case SENSOR_MCLK:
+			for (i = soc_info->num_clk - 1; i >= 0; i--) {
+				cam_soc_util_clk_disable(soc_info->clk[i],
+					soc_info->clk_name[i]);
+			}
+			ret = cam_config_mclk_reg(ctrl, soc_info, index);
+			if (ret < 0) {
+				CAM_ERR(CAM_SENSOR,
+					"config clk reg failed rc: %d", ret);
+				continue;
+			}
+			break;
 		case SENSOR_RESET:
 		case SENSOR_STANDBY:
 		case SENSOR_CUSTOM_GPIO1:
@@ -1517,11 +1630,21 @@
 					soc_info->rgltr_op_mode[vreg_idx],
 					soc_info->rgltr_delay[vreg_idx]);
 
+				if (rc) {
+					CAM_ERR(CAM_SENSOR,
+					"Fail to disalbe reg: %s",
+					soc_info->rgltr_name[vreg_idx]);
+					soc_info->rgltr[vreg_idx] = NULL;
+					msm_cam_sensor_handle_reg_gpio(
+						power_setting->seq_type,
+						gpio_num_info,
+						GPIOF_OUT_INIT_LOW);
+					continue;
+				}
 				power_setting->data[0] =
 						soc_info->rgltr[vreg_idx];
 
-				regulator_put(
-					soc_info->rgltr[vreg_idx]);
+				regulator_put(soc_info->rgltr[vreg_idx]);
 				soc_info->rgltr[vreg_idx] = NULL;
 			}
 			else
@@ -1547,8 +1670,8 @@
 
 	if (ctrl->cam_pinctrl_status) {
 		ret = pinctrl_select_state(
-				ctrl->pinctrl_info.pinctrl,
-				ctrl->pinctrl_info.gpio_state_suspend);
+			ctrl->pinctrl_info.pinctrl,
+			ctrl->pinctrl_info.gpio_state_suspend);
 		if (ret)
 			CAM_ERR(CAM_SENSOR, "cannot set pin to suspend state");
 		cam_res_mgr_shared_pinctrl_select_state(false);
@@ -1587,54 +1710,6 @@
 	return ps;
 }
 
-static int cam_config_mclk_reg(struct cam_sensor_power_ctrl_t *ctrl,
-	struct cam_hw_soc_info *soc_info, int32_t index)
-{
-	int32_t num_vreg = 0, j = 0, rc = 0, idx = 0;
-	struct cam_sensor_power_setting *ps = NULL;
-	struct cam_sensor_power_setting *pd = NULL;
-
-	num_vreg = soc_info->num_rgltr;
-
-	pd = &ctrl->power_down_setting[index];
-
-	for (j = 0; j < num_vreg; j++) {
-		if (!strcmp(soc_info->rgltr_name[j], "cam_clk")) {
-
-			ps = NULL;
-			for (idx = 0; idx <
-				ctrl->power_setting_size; idx++) {
-				if (ctrl->power_setting[idx].
-					seq_type == pd->seq_type) {
-					ps = &ctrl->power_setting[idx];
-					break;
-				}
-			}
-
-			if (ps != NULL) {
-				CAM_DBG(CAM_SENSOR, "Disable Regulator");
-
-				rc = cam_soc_util_regulator_disable(
-					soc_info->rgltr[j],
-					soc_info->rgltr_name[j],
-					soc_info->rgltr_min_volt[j],
-					soc_info->rgltr_max_volt[j],
-					soc_info->rgltr_op_mode[j],
-					soc_info->rgltr_delay[j]);
-
-				ps->data[0] =
-					soc_info->rgltr[j];
-
-				regulator_put(
-					soc_info->rgltr[j]);
-				soc_info->rgltr[j] = NULL;
-			}
-		}
-	}
-
-	return rc;
-}
-
 int msm_camera_power_down(struct cam_sensor_power_ctrl_t *ctrl,
 		struct cam_hw_soc_info *soc_info)
 {
@@ -1657,8 +1732,14 @@
 		return -EINVAL;
 	}
 
+	if (ctrl->power_down_setting_size > MAX_POWER_CONFIG) {
+		CAM_ERR(CAM_SENSOR, "Invalid: power setting size %d",
+			ctrl->power_setting_size);
+		return -EINVAL;
+	}
+
 	for (index = 0; index < ctrl->power_down_setting_size; index++) {
-		CAM_DBG(CAM_SENSOR, "index %d",  index);
+		CAM_DBG(CAM_SENSOR, "power_down_index %d",  index);
 		pd = &ctrl->power_down_setting[index];
 		if (!pd) {
 			CAM_ERR(CAM_SENSOR,
@@ -1668,21 +1749,20 @@
 		}
 
 		ps = NULL;
-		CAM_DBG(CAM_SENSOR, "type %d",  pd->seq_type);
+		CAM_DBG(CAM_SENSOR, "seq_type %d",  pd->seq_type);
 		switch (pd->seq_type) {
 		case SENSOR_MCLK:
-			ret = cam_config_mclk_reg(ctrl, soc_info, index);
-			if (ret < 0) {
-				CAM_ERR(CAM_SENSOR,
-					"config clk reg failed rc: %d", ret);
-				return ret;
-			}
-			//cam_soc_util_clk_disable_default(soc_info);
 			for (i = soc_info->num_clk - 1; i >= 0; i--) {
 				cam_soc_util_clk_disable(soc_info->clk[i],
 					soc_info->clk_name[i]);
 			}
 
+			ret = cam_config_mclk_reg(ctrl, soc_info, index);
+			if (ret < 0) {
+				CAM_ERR(CAM_SENSOR,
+					"config clk reg failed rc: %d", ret);
+				continue;
+			}
 			break;
 		case SENSOR_RESET:
 		case SENSOR_STANDBY:
@@ -1722,7 +1802,19 @@
 					soc_info->rgltr_max_volt[ps->seq_val],
 					soc_info->rgltr_op_mode[ps->seq_val],
 					soc_info->rgltr_delay[ps->seq_val]);
-
+					if (ret) {
+						CAM_ERR(CAM_SENSOR,
+						"Reg: %s disable failed",
+						soc_info->rgltr_name[
+							ps->seq_val]);
+						soc_info->rgltr[ps->seq_val] =
+							NULL;
+						msm_cam_sensor_handle_reg_gpio(
+							pd->seq_type,
+							gpio_num_info,
+							GPIOF_OUT_INIT_LOW);
+						continue;
+					}
 					ps->data[0] =
 						soc_info->rgltr[ps->seq_val];
 
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 c9ccc5c..6c0287e 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
@@ -58,4 +58,7 @@
 
 int32_t cam_sensor_update_power_settings(void *cmd_buf,
 	int cmd_length, struct cam_sensor_power_ctrl_t *power_info);
+
+int cam_sensor_bob_pwm_mode_switch(struct cam_hw_soc_info *soc_info,
+	int bob_reg_idx, bool flag);
 #endif /* _CAM_SENSOR_UTIL_H_ */
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 5cd3008..52da37f 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
@@ -3394,6 +3394,7 @@
 		.name = "msm_cam_smmu",
 		.owner = THIS_MODULE,
 		.of_match_table = msm_cam_smmu_dt_match,
+		.suppress_bind_attrs = true,
 	},
 };
 
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 517b7df..e5df874 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync.c
@@ -36,7 +36,8 @@
 	} while (bit);
 
 	spin_lock_bh(&sync_dev->row_spinlocks[idx]);
-	rc = cam_sync_init_object(sync_dev->sync_table, idx, name);
+	rc = cam_sync_init_row(sync_dev->sync_table, idx, name,
+		CAM_SYNC_TYPE_INDV);
 	if (rc) {
 		CAM_ERR(CAM_SYNC, "Error: Unable to init row at idx = %ld",
 			idx);
@@ -46,6 +47,7 @@
 	}
 
 	*sync_obj = idx;
+	CAM_DBG(CAM_SYNC, "sync_obj: %i", *sync_obj);
 	spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
 
 	return rc;
@@ -165,26 +167,30 @@
 	struct list_head sync_list;
 	struct cam_signalable_info *list_info = NULL;
 	struct cam_signalable_info *temp_list_info = NULL;
+	struct list_head parents_list;
 
 	/* Objects to be signaled will be added into this list */
 	INIT_LIST_HEAD(&sync_list);
 
 	if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0) {
-		CAM_ERR(CAM_SYNC, "Error: Out of range sync obj");
+		CAM_ERR(CAM_SYNC, "Error: Out of range sync obj (0 <= %d < %d)",
+			sync_obj, CAM_SYNC_MAX_OBJS);
 		return -EINVAL;
 	}
 	row = sync_dev->sync_table + sync_obj;
+	spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]);
 	if (row->state == CAM_SYNC_STATE_INVALID) {
+		spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
 		CAM_ERR(CAM_SYNC,
 			"Error: accessing an uninitialized sync obj = %d",
 			sync_obj);
 		return -EINVAL;
 	}
 
-	spin_lock_bh(&sync_dev->row_spinlocks[sync_obj]);
 	if (row->type == CAM_SYNC_TYPE_GROUP) {
 		spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
-		CAM_ERR(CAM_SYNC, "Error: Signaling a GROUP sync object = %d",
+		CAM_ERR(CAM_SYNC,
+			"Error: Signaling a GROUP sync object = %d",
 			sync_obj);
 		return -EINVAL;
 	}
@@ -216,20 +222,36 @@
 		return rc;
 	}
 
+	/* copy parent list to local and release child lock */
+	INIT_LIST_HEAD(&parents_list);
+	list_splice_init(&row->parents_list, &parents_list);
+	spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
+
+	if (list_empty(&parents_list))
+		goto dispatch_cb;
+
 	/*
 	 * Now iterate over all parents of this object and if they too need to
 	 * be signaled add them to the list
 	 */
 	list_for_each_entry(parent_info,
-		&row->parents_list,
+		&parents_list,
 		list) {
 		parent_row = sync_dev->sync_table + parent_info->sync_id;
 		spin_lock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]);
 		parent_row->remaining--;
 
-		parent_row->state = cam_sync_util_get_state(
-			parent_row->state,
+		rc = cam_sync_util_update_parent_state(
+			parent_row,
 			status);
+		if (rc) {
+			CAM_ERR(CAM_SYNC, "Invalid parent state %d",
+				parent_row->state);
+			spin_unlock_bh(
+				&sync_dev->row_spinlocks[parent_info->sync_id]);
+			kfree(parent_info);
+			continue;
+		}
 
 		if (!parent_row->remaining) {
 			rc = cam_sync_util_add_to_signalable_list
@@ -240,15 +262,13 @@
 				spin_unlock_bh(
 					&sync_dev->row_spinlocks[
 						parent_info->sync_id]);
-				spin_unlock_bh(
-					&sync_dev->row_spinlocks[sync_obj]);
-				return rc;
+				continue;
 			}
 		}
 		spin_unlock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]);
 	}
 
-	spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj]);
+dispatch_cb:
 
 	/*
 	 * Now dispatch the various sync objects collected so far, in our
@@ -333,10 +353,8 @@
 		return -EINVAL;
 	}
 
-	rc = cam_sync_util_validate_merge(sync_obj,
-		num_objs);
-	if (rc < 0) {
-		CAM_ERR(CAM_SYNC, "Validation failed, Merge not allowed");
+	if (num_objs <= 1) {
+		CAM_ERR(CAM_SYNC, "Single object merge is not allowed");
 		return -EINVAL;
 	}
 
@@ -348,7 +366,6 @@
 	} while (bit);
 
 	spin_lock_bh(&sync_dev->row_spinlocks[idx]);
-
 	rc = cam_sync_init_group_object(sync_dev->sync_table,
 		idx, sync_obj,
 		num_objs);
@@ -368,6 +385,7 @@
 
 int cam_sync_destroy(int32_t sync_obj)
 {
+	CAM_DBG(CAM_SYNC, "sync_obj: %i", sync_obj);
 	return cam_sync_deinit_object(sync_dev->sync_table, sync_obj);
 }
 
@@ -1048,6 +1066,7 @@
 	.driver = {
 		.name = "cam_sync",
 		.owner = THIS_MODULE,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
index ed69829..f391c8c 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.c
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.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
@@ -31,169 +31,123 @@
 	return rc;
 }
 
-int cam_sync_init_object(struct sync_table_row *table,
-	uint32_t idx,
-	const char *name)
+int cam_sync_init_row(struct sync_table_row *table,
+	uint32_t idx, const char *name, uint32_t type)
 {
 	struct sync_table_row *row = table + idx;
 
 	if (!table || idx <= 0 || idx >= CAM_SYNC_MAX_OBJS)
 		return -EINVAL;
 
+	memset(row, 0, sizeof(*row));
+
 	if (name)
 		strlcpy(row->name, name, SYNC_DEBUG_NAME_LEN);
 	INIT_LIST_HEAD(&row->parents_list);
 	INIT_LIST_HEAD(&row->children_list);
-	row->type = CAM_SYNC_TYPE_INDV;
+	row->type = type;
 	row->sync_id = idx;
 	row->state = CAM_SYNC_STATE_ACTIVE;
 	row->remaining = 0;
 	init_completion(&row->signaled);
 	INIT_LIST_HEAD(&row->callback_list);
 	INIT_LIST_HEAD(&row->user_payload_list);
-	CAM_DBG(CAM_SYNC, "Sync object Initialised: sync_id:%u row_state:%u ",
-		row->sync_id, row->state);
+	CAM_DBG(CAM_SYNC,
+		"row name:%s sync_id:%i [idx:%u] row_state:%u ",
+		row->name, row->sync_id, idx, row->state);
 
 	return 0;
 }
 
-uint32_t cam_sync_util_get_group_object_state(struct sync_table_row *table,
-	uint32_t *sync_objs,
-	uint32_t num_objs)
-{
-	int i;
-	struct sync_table_row *child_row = NULL;
-	int success_count = 0;
-	int active_count = 0;
-
-	if (!table || !sync_objs)
-		return CAM_SYNC_STATE_SIGNALED_ERROR;
-
-	/*
-	 * We need to arrive at the state of the merged object based on
-	 * counts of error, active and success states of all children objects
-	 */
-	for (i = 0; i < num_objs; i++) {
-		child_row = table + sync_objs[i];
-		switch (child_row->state) {
-		case CAM_SYNC_STATE_SIGNALED_ERROR:
-			return CAM_SYNC_STATE_SIGNALED_ERROR;
-		case CAM_SYNC_STATE_SIGNALED_SUCCESS:
-			success_count++;
-			break;
-		case CAM_SYNC_STATE_ACTIVE:
-			active_count++;
-			break;
-		default:
-			CAM_ERR(CAM_SYNC,
-				"Invalid state of child object during merge");
-			return CAM_SYNC_STATE_SIGNALED_ERROR;
-		}
-	}
-
-	if (active_count)
-		return CAM_SYNC_STATE_ACTIVE;
-
-	if (success_count == num_objs)
-		return CAM_SYNC_STATE_SIGNALED_SUCCESS;
-
-	return CAM_SYNC_STATE_SIGNALED_ERROR;
-}
-
-static int cam_sync_util_get_group_object_remaining_count(
-	struct sync_table_row *table,
-	uint32_t *sync_objs,
-	uint32_t num_objs)
-{
-	int i;
-	struct sync_table_row *child_row = NULL;
-	int remaining_count = 0;
-
-	if (!table || !sync_objs)
-		return -EINVAL;
-
-	for (i = 0; i < num_objs; i++) {
-		child_row = table + sync_objs[i];
-		if (child_row->state == CAM_SYNC_STATE_ACTIVE)
-			remaining_count++;
-	}
-
-	return remaining_count;
-}
-
 int cam_sync_init_group_object(struct sync_table_row *table,
 	uint32_t idx,
 	uint32_t *sync_objs,
 	uint32_t num_objs)
 {
-	int i;
-	int remaining;
+	int i, rc = 0;
 	struct sync_child_info *child_info;
 	struct sync_parent_info *parent_info;
 	struct sync_table_row *row = table + idx;
 	struct sync_table_row *child_row = NULL;
 
-	INIT_LIST_HEAD(&row->parents_list);
-
-	INIT_LIST_HEAD(&row->children_list);
+	cam_sync_init_row(table, idx, "merged_fence", CAM_SYNC_TYPE_GROUP);
 
 	/*
-	 * While traversing parents and children, we allocate in a loop and in
-	 * case allocation fails, we call the clean up function which frees up
-	 * all memory allocation thus far
+	 * While traversing for children, parent's row list is updated with
+	 * child info and each child's row is updated with parent info.
+	 * If any child state is ERROR or SUCCESS, it will not be added to list.
 	 */
 	for (i = 0; i < num_objs; i++) {
-		child_info = kzalloc(sizeof(*child_info), GFP_ATOMIC);
-
-		if (!child_info) {
-			cam_sync_util_cleanup_children_list(row,
-				SYNC_LIST_CLEAN_ALL, 0);
-			return -ENOMEM;
-		}
-
-		child_info->sync_id = sync_objs[i];
-		list_add_tail(&child_info->list, &row->children_list);
-	}
-
-	for (i = 0; i < num_objs; i++) {
-		/* This gets us the row corresponding to the sync object */
 		child_row = table + sync_objs[i];
 		spin_lock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
+
+		/* validate child */
+		if ((child_row->type == CAM_SYNC_TYPE_GROUP) ||
+			(child_row->state == CAM_SYNC_STATE_INVALID)) {
+			spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
+			CAM_ERR(CAM_SYNC,
+				"Invalid child fence:%i state:%u type:%u",
+				child_row->sync_id, child_row->state,
+				child_row->type);
+			rc = -EINVAL;
+			goto clean_children_info;
+		}
+
+		/* check for child's state */
+		if (child_row->state == CAM_SYNC_STATE_SIGNALED_ERROR) {
+			row->state = CAM_SYNC_STATE_SIGNALED_ERROR;
+			spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
+			continue;
+		}
+		if (child_row->state != CAM_SYNC_STATE_ACTIVE) {
+			spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
+			continue;
+		}
+
+		row->remaining++;
+
+		/* Add child info */
+		child_info = kzalloc(sizeof(*child_info), GFP_ATOMIC);
+		if (!child_info) {
+			spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
+			rc = -ENOMEM;
+			goto clean_children_info;
+		}
+		child_info->sync_id = sync_objs[i];
+		list_add_tail(&child_info->list, &row->children_list);
+
+		/* Add parent info */
 		parent_info = kzalloc(sizeof(*parent_info), GFP_ATOMIC);
 		if (!parent_info) {
-			cam_sync_util_cleanup_parents_list(child_row,
-				SYNC_LIST_CLEAN_ALL, 0);
-			cam_sync_util_cleanup_children_list(row,
-				SYNC_LIST_CLEAN_ALL, 0);
 			spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
-			return -ENOMEM;
+			rc = -ENOMEM;
+			goto clean_children_info;
 		}
 		parent_info->sync_id = idx;
 		list_add_tail(&parent_info->list, &child_row->parents_list);
 		spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
 	}
 
-	row->type = CAM_SYNC_TYPE_GROUP;
-	row->sync_id = idx;
-	row->state = cam_sync_util_get_group_object_state(table,
-		sync_objs, num_objs);
-	remaining = cam_sync_util_get_group_object_remaining_count(table,
-		sync_objs, num_objs);
-	if (remaining < 0) {
-		CAM_ERR(CAM_SYNC, "Failed getting remaining count");
-		return -ENODEV;
+	if (!row->remaining) {
+		if (row->state != CAM_SYNC_STATE_SIGNALED_ERROR)
+			row->state = CAM_SYNC_STATE_SIGNALED_SUCCESS;
+		complete_all(&row->signaled);
 	}
 
-	row->remaining = remaining;
-
-	init_completion(&row->signaled);
-	INIT_LIST_HEAD(&row->callback_list);
-	INIT_LIST_HEAD(&row->user_payload_list);
-
-	if (row->state != CAM_SYNC_STATE_ACTIVE)
-		complete_all(&row->signaled);
-
 	return 0;
+
+clean_children_info:
+	row->state = CAM_SYNC_STATE_INVALID;
+	for (i = i-1; i >= 0; i--) {
+		spin_lock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
+		child_row = table + sync_objs[i];
+		cam_sync_util_cleanup_parents_list(child_row,
+			SYNC_LIST_CLEAN_ONE, idx);
+		spin_unlock_bh(&sync_dev->row_spinlocks[sync_objs[i]]);
+	}
+
+	cam_sync_util_cleanup_children_list(row, SYNC_LIST_CLEAN_ALL, 0);
+	return rc;
 }
 
 int cam_sync_deinit_object(struct sync_table_row *table, uint32_t idx)
@@ -209,12 +163,16 @@
 	if (!table || idx <= 0 || idx >= CAM_SYNC_MAX_OBJS)
 		return -EINVAL;
 
+	CAM_DBG(CAM_SYNC,
+		"row name:%s sync_id:%i [idx:%u] row_state:%u",
+		row->name, row->sync_id, idx, row->state);
+
 	spin_lock_bh(&sync_dev->row_spinlocks[idx]);
 	if (row->state == CAM_SYNC_STATE_INVALID) {
+		spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
 		CAM_ERR(CAM_SYNC,
 			"Error: accessing an uninitialized sync obj: idx = %d",
 			idx);
-		spin_unlock_bh(&sync_dev->row_spinlocks[idx]);
 		return -EINVAL;
 	}
 	row->state = CAM_SYNC_STATE_INVALID;
@@ -252,9 +210,9 @@
 		spin_lock_bh(&sync_dev->row_spinlocks[child_info->sync_id]);
 
 		if (child_row->state == CAM_SYNC_STATE_INVALID) {
+			list_del_init(&child_info->list);
 			spin_unlock_bh(&sync_dev->row_spinlocks[
 				child_info->sync_id]);
-			list_del_init(&child_info->list);
 			kfree(child_info);
 			continue;
 		}
@@ -262,9 +220,8 @@
 		cam_sync_util_cleanup_parents_list(child_row,
 			SYNC_LIST_CLEAN_ONE, idx);
 
-		spin_unlock_bh(&sync_dev->row_spinlocks[child_info->sync_id]);
-
 		list_del_init(&child_info->list);
+		spin_unlock_bh(&sync_dev->row_spinlocks[child_info->sync_id]);
 		kfree(child_info);
 	}
 
@@ -277,9 +234,9 @@
 		spin_lock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]);
 
 		if (parent_row->state == CAM_SYNC_STATE_INVALID) {
+			list_del_init(&parent_info->list);
 			spin_unlock_bh(&sync_dev->row_spinlocks[
 				parent_info->sync_id]);
-			list_del_init(&parent_info->list);
 			kfree(parent_info);
 			continue;
 		}
@@ -287,9 +244,8 @@
 		cam_sync_util_cleanup_children_list(parent_row,
 			SYNC_LIST_CLEAN_ONE, idx);
 
-		spin_unlock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]);
-
 		list_del_init(&parent_info->list);
+		spin_unlock_bh(&sync_dev->row_spinlocks[parent_info->sync_id]);
 		kfree(parent_info);
 	}
 
@@ -356,32 +312,6 @@
 		sync_obj);
 }
 
-int cam_sync_util_validate_merge(uint32_t *sync_obj, uint32_t num_objs)
-{
-	int i;
-	struct sync_table_row *row = NULL;
-
-	if (num_objs <= 1) {
-		CAM_ERR(CAM_SYNC, "Single object merge is not allowed");
-		return -EINVAL;
-	}
-
-	for (i = 0; i < num_objs; i++) {
-		row = sync_dev->sync_table + sync_obj[i];
-		spin_lock_bh(&sync_dev->row_spinlocks[sync_obj[i]]);
-		if (row->type == CAM_SYNC_TYPE_GROUP ||
-			row->state == CAM_SYNC_STATE_INVALID) {
-			CAM_ERR(CAM_SYNC,
-				"Group obj %d can't be merged or obj UNINIT",
-				sync_obj[i]);
-			spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj[i]]);
-			return -EINVAL;
-		}
-		spin_unlock_bh(&sync_dev->row_spinlocks[sync_obj[i]]);
-	}
-	return 0;
-}
-
 int cam_sync_util_add_to_signalable_list(int32_t sync_obj,
 	uint32_t status,
 	struct list_head *sync_list)
@@ -402,34 +332,27 @@
 	return 0;
 }
 
-int cam_sync_util_get_state(int current_state,
+int cam_sync_util_update_parent_state(struct sync_table_row *parent_row,
 	int new_state)
 {
-	int result = CAM_SYNC_STATE_SIGNALED_ERROR;
+	int rc = 0;
 
-	if (new_state != CAM_SYNC_STATE_SIGNALED_SUCCESS &&
-		new_state != CAM_SYNC_STATE_SIGNALED_ERROR)
-		return CAM_SYNC_STATE_SIGNALED_ERROR;
-
-	switch (current_state) {
-	case CAM_SYNC_STATE_INVALID:
-		result =  CAM_SYNC_STATE_SIGNALED_ERROR;
-		break;
-
+	switch (parent_row->state) {
 	case CAM_SYNC_STATE_ACTIVE:
 	case CAM_SYNC_STATE_SIGNALED_SUCCESS:
-		if (new_state == CAM_SYNC_STATE_SIGNALED_ERROR)
-			result = CAM_SYNC_STATE_SIGNALED_ERROR;
-		else if (new_state == CAM_SYNC_STATE_SIGNALED_SUCCESS)
-			result = CAM_SYNC_STATE_SIGNALED_SUCCESS;
+		parent_row->state = new_state;
 		break;
 
 	case CAM_SYNC_STATE_SIGNALED_ERROR:
-		result = CAM_SYNC_STATE_SIGNALED_ERROR;
+		break;
+
+	case CAM_SYNC_STATE_INVALID:
+	default:
+		rc = -EINVAL;
 		break;
 	}
 
-	return result;
+	return rc;
 }
 
 void cam_sync_util_cleanup_children_list(struct sync_table_row *row,
diff --git a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.h b/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.h
index ae7d542..a9d6f86 100644
--- a/drivers/media/platform/msm/camera/cam_sync/cam_sync_util.h
+++ b/drivers/media/platform/msm/camera/cam_sync/cam_sync_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
@@ -41,12 +41,11 @@
  * @param idx   : Index of row to initialize
  * @param name  : Optional string representation of the sync object. Should be
  *                63 characters or less
- *
+ * @param type  : type of row to be initialized
  * @return Status of operation. Negative in case of error. Zero otherwise.
  */
-int cam_sync_init_object(struct sync_table_row *table,
-	uint32_t idx,
-	const char *name);
+int cam_sync_init_row(struct sync_table_row *table,
+	uint32_t idx, const char *name, uint32_t type);
 
 /**
  * @brief: Function to uninitialize a row in the sync table
@@ -104,16 +103,6 @@
 	int len);
 
 /**
- * @brief: Function to validate sync merge arguments
- *
- * @param sync_obj : Array of sync objects to merge
- * @param num_objs : Number of sync objects in the array
- *
- * @return Status of operation. Negative in case of error. Zero otherwise.
- */
-int cam_sync_util_validate_merge(uint32_t *sync_obj, uint32_t num_objs);
-
-/**
  * @brief: Function which adds sync object information to the signalable list
  *
  * @param sync_obj : Sync object to add
@@ -135,7 +124,7 @@
  *
  * @return Next state of the sync object
  */
-int cam_sync_util_get_state(int current_state,
+int cam_sync_util_update_parent_state(struct sync_table_row *parent_row,
 	int new_state);
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c
index 26f2ba1..4f32634 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundataion. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundataion. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -30,7 +30,7 @@
 		name = "CAM-CORE";
 		break;
 	case CAM_CRM:
-		name = "CAM_CRM";
+		name = "CAM-CRM";
 		break;
 	case CAM_CPAS:
 		name = "CAM-CPAS";
@@ -86,6 +86,18 @@
 	case CAM_OIS:
 		name = "CAM-OIS";
 		break;
+	case CAM_IRQ_CTRL:
+		name = "CAM-IRQ-CTRL";
+		break;
+	case CAM_MEM:
+		name = "CAM-MEM";
+		break;
+	case CAM_PERF:
+		name = "CAM-PERF";
+		break;
+	case CAM_REQ:
+		name = "CAM-REQ";
+		break;
 	default:
 		name = "CAM";
 		break;
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
index 4e97100..1ed7056 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_debug_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_debug_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
@@ -35,6 +35,16 @@
 #define CAM_CTXT       (1 << 19)
 #define CAM_OIS        (1 << 20)
 #define CAM_RES        (1 << 21)
+#define CAM_MEM        (1 << 22)
+
+/* CAM_IRQ_CTRL: For events in irq controller */
+#define CAM_IRQ_CTRL   (1 << 23)
+
+/* CAM_REQ: Tracks a request submitted to KMD */
+#define CAM_REQ        (1 << 24)
+
+/* CAM_PERF: Used for performance (clock, BW etc) logs */
+#define CAM_PERF       (1 << 25)
 
 #define STR_BUFFER_MAX_LENGTH  1024
 
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
index 30ab075..db2629d 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_packet_util.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
@@ -171,6 +171,24 @@
 			patch_desc[i].dst_buf_hdl, patch_desc[i].dst_offset,
 			patch_desc[i].src_buf_hdl, patch_desc[i].src_offset);
 
+		if (patch_desc[i].src_offset >= src_buf_size) {
+			CAM_ERR_RATE_LIMIT(CAM_UTIL,
+				"Inval src offset:0x%x src len:0x%x reqid:%lld",
+				patch_desc[i].src_offset,
+				(unsigned int)src_buf_size,
+				packet->header.request_id);
+			return -EINVAL;
+		}
+
+		if (patch_desc[i].dst_offset >= dst_buf_len) {
+			CAM_ERR_RATE_LIMIT(CAM_UTIL,
+				"Inval dst offset:0x%x dst len:0x%x reqid:%lld",
+				patch_desc[i].dst_offset,
+				(unsigned int)dst_buf_len,
+				packet->header.request_id);
+			return -EINVAL;
+		}
+
 		dst_cpu_addr = (uint32_t *)((uint8_t *)dst_cpu_addr +
 			patch_desc[i].dst_offset);
 		temp += patch_desc[i].src_offset;
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
index d0a13ab..a5456a9 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
@@ -72,6 +72,197 @@
 }
 #endif
 
+static char supported_clk_info[256];
+static char debugfs_dir_name[64];
+
+/**
+ * cam_soc_util_get_string_from_level()
+ *
+ * @brief:     Returns the string for a given clk level
+ *
+ * @level:     Clock level
+ *
+ * @return:    String corresponding to the clk level
+ */
+static const char *cam_soc_util_get_string_from_level(
+	enum cam_vote_level level)
+{
+	switch (level) {
+	case CAM_SUSPEND_VOTE:
+		return "";
+	case CAM_MINSVS_VOTE:
+		return "MINSVS[1]";
+	case CAM_LOWSVS_VOTE:
+		return "LOWSVS[2]";
+	case CAM_SVS_VOTE:
+		return "SVS[3]";
+	case CAM_SVSL1_VOTE:
+		return "SVSL1[4]";
+	case CAM_NOMINAL_VOTE:
+		return "NOM[5]";
+	case CAM_TURBO_VOTE:
+		return "TURBO[6]";
+	default:
+		return "";
+	}
+}
+
+/**
+ * cam_soc_util_get_supported_clk_levels()
+ *
+ * @brief:      Returns the string of all the supported clk levels for
+ *              the given device
+ *
+ * @soc_info:   Device soc information
+ *
+ * @return:     String containing all supported clk levels
+ */
+static const char *cam_soc_util_get_supported_clk_levels(
+	struct cam_hw_soc_info *soc_info)
+{
+	int i = 0;
+
+	memset(supported_clk_info, 0, sizeof(supported_clk_info));
+	strlcat(supported_clk_info, "Supported levels: ",
+		sizeof(supported_clk_info));
+
+	for (i = 0; i < CAM_MAX_VOTE; i++) {
+		if (soc_info->clk_level_valid[i] == true) {
+			strlcat(supported_clk_info,
+				cam_soc_util_get_string_from_level(i),
+				sizeof(supported_clk_info));
+			strlcat(supported_clk_info, " ",
+				sizeof(supported_clk_info));
+		}
+	}
+
+	strlcat(supported_clk_info, "\n", sizeof(supported_clk_info));
+	return supported_clk_info;
+}
+
+static int cam_soc_util_clk_lvl_options_open(struct inode *inode,
+	struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t cam_soc_util_clk_lvl_options_read(struct file *file,
+	char __user *clk_info, size_t size_t, loff_t *loff_t)
+{
+	struct cam_hw_soc_info *soc_info =
+		(struct cam_hw_soc_info *)file->private_data;
+	const char *display_string =
+		cam_soc_util_get_supported_clk_levels(soc_info);
+
+	return simple_read_from_buffer(clk_info, size_t, loff_t, display_string,
+		strlen(display_string));
+}
+
+static const struct file_operations cam_soc_util_clk_lvl_options = {
+	.open = cam_soc_util_clk_lvl_options_open,
+	.read = cam_soc_util_clk_lvl_options_read,
+};
+
+static int cam_soc_util_set_clk_lvl(void *data, u64 val)
+{
+	struct cam_hw_soc_info *soc_info = (struct cam_hw_soc_info *)data;
+
+	if (val <= CAM_SUSPEND_VOTE || val >= CAM_MAX_VOTE)
+		return 0;
+
+	if (soc_info->clk_level_valid[val] == true)
+		soc_info->clk_level_override = val;
+	else
+		soc_info->clk_level_override = 0;
+
+	return 0;
+}
+
+static int cam_soc_util_get_clk_lvl(void *data, u64 *val)
+{
+	struct cam_hw_soc_info *soc_info = (struct cam_hw_soc_info *)data;
+
+	*val = soc_info->clk_level_override;
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(cam_soc_util_clk_lvl_control,
+	cam_soc_util_get_clk_lvl, cam_soc_util_set_clk_lvl, "%08llu");
+
+/**
+ * cam_soc_util_create_clk_lvl_debugfs()
+ *
+ * @brief:      Creates debugfs files to view/control device clk rates
+ *
+ * @soc_info:   Device soc information
+ *
+ * @return:     Success or failure
+ */
+static int cam_soc_util_create_clk_lvl_debugfs(
+	struct cam_hw_soc_info *soc_info)
+{
+	struct dentry *dentry = NULL;
+
+	if (!soc_info) {
+		CAM_ERR(CAM_UTIL, "soc info is NULL");
+		return -EINVAL;
+	}
+
+	if (soc_info->dentry)
+		return 0;
+
+	memset(debugfs_dir_name, 0, sizeof(debugfs_dir_name));
+	strlcat(debugfs_dir_name, "clk_dir_", sizeof(debugfs_dir_name));
+	strlcat(debugfs_dir_name, soc_info->dev_name, sizeof(debugfs_dir_name));
+
+	dentry = soc_info->dentry;
+	dentry = debugfs_create_dir(debugfs_dir_name, NULL);
+	if (!dentry) {
+		CAM_ERR(CAM_UTIL, "failed to create debug directory");
+		return -ENOMEM;
+	}
+
+	if (!debugfs_create_file("clk_lvl_options", 0444,
+		dentry, soc_info, &cam_soc_util_clk_lvl_options)) {
+		CAM_ERR(CAM_UTIL, "failed to create clk_lvl_options");
+		goto err;
+	}
+
+	if (!debugfs_create_file("clk_lvl_control", 0644,
+		dentry, soc_info, &cam_soc_util_clk_lvl_control)) {
+		CAM_ERR(CAM_UTIL, "failed to create clk_lvl_control");
+		goto err;
+	}
+
+	CAM_DBG(CAM_UTIL, "clk lvl debugfs for %s successfully created",
+		soc_info->dev_name);
+
+	return 0;
+
+err:
+	debugfs_remove_recursive(dentry);
+	dentry = NULL;
+	return -ENOMEM;
+}
+
+/**
+ * cam_soc_util_remove_clk_lvl_debugfs()
+ *
+ * @brief:      Removes the debugfs files used to view/control
+ *              device clk rates
+ *
+ * @soc_info:   Device soc information
+ *
+ */
+static void cam_soc_util_remove_clk_lvl_debugfs(
+	struct cam_hw_soc_info *soc_info)
+{
+	debugfs_remove_recursive(soc_info->dentry);
+	soc_info->dentry = NULL;
+}
+
 int cam_soc_util_get_level_from_string(const char *string,
 	enum cam_vote_level *level)
 {
@@ -206,7 +397,18 @@
 	return clk_set_flags(soc_info->clk[clk_index], flags);
 }
 
-int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name,
+/**
+ * cam_soc_util_set_clk_rate()
+ *
+ * @brief:          Sets the given rate for the clk requested for
+ *
+ * @clk:            Clock structure information for which rate is to be set
+ * @clk_name:       Name of the clock for which rate is being set
+ * @clk_rate        Clock rate to be set
+ *
+ * @return:         Success or failure
+ */
+static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name,
 	int32_t clk_rate)
 {
 	int rc = 0;
@@ -250,6 +452,26 @@
 	return rc;
 }
 
+int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
+	int32_t clk_rate)
+{
+	int32_t src_clk_idx;
+	struct clk *clk = NULL;
+
+	if (!soc_info || (soc_info->src_clk_idx < 0))
+		return -EINVAL;
+
+	if (soc_info->clk_level_override && clk_rate)
+		clk_rate = soc_info->clk_level_override;
+
+	src_clk_idx = soc_info->src_clk_idx;
+	clk = soc_info->clk[src_clk_idx];
+
+	return cam_soc_util_set_clk_rate(clk,
+		soc_info->clk_name[src_clk_idx], clk_rate);
+
+}
+
 int cam_soc_util_clk_put(struct clk **clk)
 {
 	if (!(*clk)) {
@@ -456,6 +678,7 @@
 	int i, j, rc;
 	int32_t num_clk_level_strings;
 	const char *src_clk_str = NULL;
+	const char *clk_control_debugfs = NULL;
 	const char *clk_cntl_lvl_string = NULL;
 	enum cam_vote_level level;
 
@@ -569,8 +792,7 @@
 	if (rc || !src_clk_str) {
 		CAM_DBG(CAM_UTIL, "No src_clk_str found");
 		rc = 0;
-		/* Bottom loop is dependent on src_clk_str. So return here */
-		return rc;
+		goto end;
 	}
 
 	for (i = 0; i < soc_info->num_clk; i++) {
@@ -582,6 +804,18 @@
 		}
 	}
 
+	rc = of_property_read_string_index(of_node,
+		"clock-control-debugfs", 0, &clk_control_debugfs);
+	if (rc || !clk_control_debugfs) {
+		CAM_DBG(CAM_UTIL, "No clock_control_debugfs property found");
+		rc = 0;
+		goto end;
+	}
+
+	if (strcmp("true", clk_control_debugfs) == 0)
+		soc_info->clk_control_enable = true;
+
+end:
 	return rc;
 }
 
@@ -1269,6 +1503,9 @@
 		goto put_clk;
 	}
 
+	if (soc_info->clk_control_enable)
+		cam_soc_util_create_clk_lvl_debugfs(soc_info);
+
 	return rc;
 
 put_clk:
@@ -1353,6 +1590,9 @@
 	/* release for gpio */
 	cam_soc_util_request_gpio_table(soc_info, false);
 
+	if (soc_info->clk_control_enable)
+		cam_soc_util_remove_clk_lvl_debugfs(soc_info);
+
 	return 0;
 }
 
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
index 18fad8d..4c6ed4b 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
@@ -22,6 +22,7 @@
 #include <linux/spi/spi.h>
 #include <linux/regulator/consumer.h>
 #include <linux/clk/qcom.h>
+#include <linux/debugfs.h>
 
 #include "cam_io_util.h"
 
@@ -156,6 +157,9 @@
  * @clk_level_valid:        Indicates whether corresponding level is valid
  * @gpio_data:              Pointer to gpio info
  * @pinctrl_info:           Pointer to pinctrl info
+ * @dentry:                 Debugfs entry
+ * @clk_level_override:     Clk level set from debugfs
+ * @clk_control:            Enable/disable clk rate control through debugfs
  * @soc_private:            Soc private data
  */
 struct cam_hw_soc_info {
@@ -197,6 +201,10 @@
 	struct cam_soc_gpio_data       *gpio_data;
 	struct cam_soc_pinctrl_info     pinctrl_info;
 
+	struct dentry                  *dentry;
+	uint32_t                        clk_level_override;
+	bool                            clk_control_enable;
+
 	void                           *soc_private;
 };
 
@@ -370,17 +378,16 @@
 	 uint32_t clk_index, unsigned long flags);
 
 /**
- * cam_soc_util_set_clk_rate()
+ * cam_soc_util_set_src_clk_rate()
  *
- * @brief:              Set the rate on a given clock.
+ * @brief:              Set the rate on the source clock.
  *
- * @clk:                Clock that needs to be set
- * @clk_name:           Clocks name associated with clk
- * @clk_rate:           Clocks rate associated with clk
+ * @soc_info:           Device soc information
+ * @clk_rate:           Clock rate associated with the src clk
  *
  * @return:             success or failure
  */
-int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name,
+int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
 	int32_t clk_rate);
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_trace.h b/drivers/media/platform/msm/camera/cam_utils/cam_trace.h
index 90ec566..c7dc0b6 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_trace.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_trace.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
@@ -72,17 +72,19 @@
 );
 
 TRACE_EVENT(cam_icp_fw_dbg,
-	TP_PROTO(char *dbg_message),
-	TP_ARGS(dbg_message),
+	TP_PROTO(char *dbg_message, uint64_t timestamp),
+	TP_ARGS(dbg_message, timestamp),
 	TP_STRUCT__entry(
 		__string(dbg_message, dbg_message)
+		__field(uint64_t, timestamp)
 	),
 	TP_fast_assign(
 		__assign_str(dbg_message, dbg_message);
+		__entry->timestamp = timestamp;
 	),
 	TP_printk(
-		"%s: ",
-		__get_str(dbg_message)
+		"%llu %s: ",
+		 __entry->timestamp, __get_str(dbg_message)
 	)
 );
 
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 0b84327..3832d63 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
@@ -3847,7 +3847,7 @@
 
 int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg)
 {
-	int rc = 0, i;
+	int rc = 0, i, j, k;
 	struct msm_vfe_axi_stream *stream_info;
 	struct msm_vfe_axi_stream_update_cmd *update_cmd = arg;
 	struct msm_vfe_axi_stream_cfg_update_info *update_info = NULL;
@@ -3884,7 +3884,9 @@
 			update_cmd->update_type !=
 			UPDATE_STREAM_REMOVE_BUFQ &&
 			update_cmd->update_type !=
-			UPDATE_STREAM_SW_FRAME_DROP) {
+			UPDATE_STREAM_SW_FRAME_DROP &&
+			update_cmd->update_type !=
+			UPDATE_STREAM_REQUEST_FRAMES_VER2) {
 			pr_err("%s: Invalid stream state %d, update cmd %d\n",
 				__func__, stream_info->state,
 				stream_info->stream_id);
@@ -4126,8 +4128,16 @@
 			}
 			vfe_idx = msm_isp_get_vfe_idx_for_stream(
 				vfe_dev, stream_info);
-			msm_isp_stream_axi_cfg_update(vfe_dev, stream_info,
-				update_info);
+			for (j = 0; j < stream_info->num_planes; j++) {
+				stream_info->plane_cfg[vfe_idx][j] =
+					update_info->plane_cfg[j];
+				for (k = 0; k < stream_info->num_isp; k++) {
+					vfe_dev = stream_info->vfe_dev[k];
+					vfe_dev->hw_info->vfe_ops.axi_ops.
+						cfg_wm_reg(vfe_dev,
+						stream_info, j);
+				}
+			}
 		}
 		break;
 	}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
index 55a10ca..b5a6f44 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util_32.c
@@ -25,12 +25,16 @@
 	struct msm_vfe_axi_shared_data *axi_data,
 	struct msm_vfe32_axi_stream_request_cmd *stream_cfg_cmd)
 {
-	uint32_t i = stream_cfg_cmd->stream_src;
+	int i, rc = -1;
 
-	if (i >= VFE_AXI_SRC_MAX) {
-		pr_err("%s:%d invalid stream_src %d\n", __func__, __LINE__,
-			stream_cfg_cmd->stream_src);
-		return -EINVAL;
+	for (i = 0; i < MAX_NUM_STREAM; i++) {
+		if (axi_data->stream_info[i].state == AVAILABLE)
+			break;
+	}
+
+	if (i == MAX_NUM_STREAM) {
+		pr_err("%s: No free stream\n", __func__);
+		return rc;
 	}
 
 	if ((axi_data->stream_handle_cnt << 8) == 0)
@@ -1602,6 +1606,8 @@
 	vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev, 0xF);
 	msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
 	msm_isp_update_rdi_output_count(vfe_dev, stream_cfg_cmd);
+	/*Configure UB*/
+	vfe_dev->hw_info->vfe_ops.axi_ops.cfg_ub(vfe_dev);
 	if (camif_update == ENABLE_CAMIF) {
 		atomic_set(&vfe_dev->error_info.overflow_state,
 				NO_OVERFLOW);
@@ -1735,7 +1741,6 @@
 {
 	int rc = 0;
 	struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd = arg;
-	struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
 	enum msm_isp_camif_update_state camif_update;
 
 	rc = msm_isp_axi_check_stream_state(vfe_dev, stream_cfg_cmd);
@@ -1744,10 +1749,6 @@
 		return rc;
 	}
 
-	if (axi_data->num_active_stream == 0) {
-		/*Configure UB*/
-		vfe_dev->hw_info->vfe_ops.axi_ops.cfg_ub(vfe_dev);
-	}
 	camif_update = msm_isp_get_camif_update_state(vfe_dev, stream_cfg_cmd);
 
 	if (stream_cfg_cmd->cmd == START_STREAM) {
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 b589afa..e671122 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
@@ -410,8 +410,12 @@
 			pr_err("%s: Fetch engine config failed\n", __func__);
 			return -EINVAL;
 		}
-		for (i = 0; i < stream_info->num_planes; i++)
+		for (i = 0; i < stream_info->num_planes; i++) {
+			vfe_dev->hw_info->vfe_ops.axi_ops.enable_wm(
+				vfe_dev->vfe_base,
+				stream_info->wm[vfe_idx][i], 1);
 			wm_reload_mask |= (1 << stream_info->wm[vfe_idx][i]);
+		}
 		vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev,
 			VFE_SRC_MAX);
 		vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
index 7d37d7e..0811efb 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c
@@ -32,6 +32,8 @@
 #define MSM_JPEG_NAME "jpeg"
 #define DEV_NAME_LEN 10
 
+static char devname[DEV_NAME_LEN];
+
 static int msm_jpeg_open(struct inode *inode, struct file *filp)
 {
 	int rc = 0;
@@ -159,7 +161,6 @@
 	struct msm_jpeg_device *msm_jpeg_device_p;
 	const struct of_device_id *device_id;
 	const struct msm_jpeg_priv_data *priv_data;
-	char devname[DEV_NAME_LEN];
 
 	msm_jpeg_device_p = kzalloc(sizeof(struct msm_jpeg_device), GFP_ATOMIC);
 	if (!msm_jpeg_device_p) {
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 0cfddb3..276c76e 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
@@ -58,6 +58,7 @@
 #define MBPS                                      1000000
 #define SNPS_INTERPHY_OFFSET                      0x800
 #define SET_THE_BIT(x)                            (0x1 << x)
+#define SNPS_MAX_DATA_RATE_PER_LANE               2500000000ULL
 
 #undef CDBG
 #define CDBG(fmt, args...) pr_debug(fmt, ##args)
@@ -185,7 +186,15 @@
 	void __iomem *csiphybase;
 
 	csiphybase = csiphy_dev->base;
+
+	if (csiphy_params->data_rate >
+		SNPS_MAX_DATA_RATE_PER_LANE * num_lanes) {
+		pr_err("unsupported data rate\n");
+		return -EINVAL;
+	}
+
 	local_data_rate = csiphy_params->data_rate;
+
 	if (mode == TWO_LANE_PHY_A)
 		offset = 0x0;
 	else if (mode == TWO_LANE_PHY_B)
@@ -208,15 +217,6 @@
 		diff = diff_i;
 	}
 
-	if (i == (sizeof(snps_v100_freq_values)/
-		sizeof(snps_v100_freq_values[0]))) {
-		if (local_data_rate >
-			snps_v100_freq_values[--i].default_bit_rate) {
-			pr_err("unsupported data rate\n");
-			return -EINVAL;
-		}
-	}
-
 	csiphy_dev->snps_programmed_data_rate = csiphy_params->data_rate;
 
 	if (mode == TWO_LANE_PHY_A) {
@@ -1706,10 +1706,8 @@
 
 	CDBG("%s:%d called\n", __func__, __LINE__);
 	if (csiphy_dev->csiphy_state == CSIPHY_POWER_UP) {
-		pr_err("%s: csiphy invalid state %d\n", __func__,
+		pr_err("%s: csiphy current state %d\n", __func__,
 			csiphy_dev->csiphy_state);
-		rc = -EINVAL;
-		return rc;
 	}
 
 	CDBG("%s:%d called\n", __func__, __LINE__);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
index cd16236..f4305ea 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
@@ -788,11 +788,101 @@
 	.core = &msm_eeprom_subdev_core_ops,
 };
 
+static int msm_eeprom_get_dt_data(struct msm_eeprom_ctrl_t *e_ctrl)
+{
+	int rc = 0, i = 0;
+	struct msm_eeprom_board_info *eb_info;
+	struct msm_camera_power_ctrl_t *power_info =
+		&e_ctrl->eboard_info->power_info;
+	struct device_node *of_node = NULL;
+	struct msm_camera_gpio_conf *gconf = NULL;
+	int8_t gpio_array_size = 0;
+	uint16_t *gpio_array = NULL;
+
+	eb_info = e_ctrl->eboard_info;
+	if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE)
+		of_node = e_ctrl->i2c_client.
+			spi_client->spi_master->dev.of_node;
+	else if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE)
+		of_node = e_ctrl->pdev->dev.of_node;
+	else if (e_ctrl->eeprom_device_type == MSM_CAMERA_I2C_DEVICE)
+		of_node = e_ctrl->i2c_client.client->dev.of_node;
+
+	if (!of_node) {
+		pr_err("%s: %d of_node is NULL\n", __func__, __LINE__);
+		return -ENOMEM;
+	}
+	rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg,
+					     &power_info->num_vreg);
+	if (rc < 0)
+		return rc;
+
+	if (e_ctrl->userspace_probe == 0) {
+		rc = msm_camera_get_dt_power_setting_data(of_node,
+			power_info->cam_vreg, power_info->num_vreg,
+			power_info);
+		if (rc < 0)
+			goto ERROR1;
+	}
+
+	power_info->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf),
+					GFP_KERNEL);
+	if (!power_info->gpio_conf) {
+		rc = -ENOMEM;
+		goto ERROR2;
+	}
+	gconf = power_info->gpio_conf;
+	gpio_array_size = of_gpio_count(of_node);
+	CDBG("%s gpio count %d\n", __func__, gpio_array_size);
+
+	if (gpio_array_size > 0) {
+		gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t),
+			GFP_KERNEL);
+		if (!gpio_array)
+			goto ERROR3;
+		for (i = 0; i < gpio_array_size; i++) {
+			gpio_array[i] = of_get_gpio(of_node, i);
+			CDBG("%s gpio_array[%d] = %d\n", __func__, i,
+				gpio_array[i]);
+		}
+
+		rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf,
+			gpio_array, gpio_array_size);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR4;
+		}
+
+		rc = msm_camera_init_gpio_pin_tbl(of_node, gconf,
+			gpio_array, gpio_array_size);
+		if (rc < 0) {
+			pr_err("%s failed %d\n", __func__, __LINE__);
+			goto ERROR4;
+		}
+		kfree(gpio_array);
+	}
+
+	return rc;
+ERROR4:
+	kfree(gpio_array);
+ERROR3:
+	kfree(power_info->gpio_conf);
+ERROR2:
+	kfree(power_info->cam_vreg);
+ERROR1:
+	kfree(power_info->power_setting);
+	return rc;
+}
+
 static int msm_eeprom_i2c_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	int rc = 0;
+	uint32_t temp = 0;
 	struct msm_eeprom_ctrl_t *e_ctrl = NULL;
+	struct msm_eeprom_board_info *eb_info = NULL;
+	struct device_node *of_node = client->dev.of_node;
+	struct msm_camera_power_ctrl_t *power_info = NULL;
 
 	CDBG("%s E\n", __func__);
 
@@ -804,41 +894,122 @@
 	e_ctrl = kzalloc(sizeof(*e_ctrl), GFP_KERNEL);
 	if (!e_ctrl)
 		return -ENOMEM;
+
 	e_ctrl->eeprom_v4l2_subdev_ops = &msm_eeprom_subdev_ops;
 	e_ctrl->eeprom_mutex = &msm_eeprom_mutex;
-	CDBG("%s client = 0x%pK\n", __func__, client);
-	e_ctrl->eboard_info = (struct msm_eeprom_board_info *)(id->driver_data);
-	if (!e_ctrl->eboard_info) {
-		pr_err("%s:%d board info NULL\n", __func__, __LINE__);
-		rc = -EINVAL;
-		goto ectrl_free;
-	}
-	e_ctrl->i2c_client.client = client;
+
 	e_ctrl->cal_data.mapdata = NULL;
 	e_ctrl->cal_data.map = NULL;
 	e_ctrl->userspace_probe = 0;
-	e_ctrl->is_supported = 1;
-
+	e_ctrl->is_supported = 0;
+	if (!of_node) {
+		pr_err("%s dev.of_node NULL\n", __func__);
+		rc = -EINVAL;
+		goto ectrl_free;
+	}
 	/* Set device type as I2C */
 	e_ctrl->eeprom_device_type = MSM_CAMERA_I2C_DEVICE;
 	e_ctrl->i2c_client.i2c_func_tbl = &msm_eeprom_qup_func_tbl;
 
-	if (e_ctrl->eboard_info->i2c_slaveaddr != 0)
-		e_ctrl->i2c_client.client->addr =
-			e_ctrl->eboard_info->i2c_slaveaddr;
+	e_ctrl->eboard_info = kzalloc(sizeof(
+		struct msm_eeprom_board_info), GFP_KERNEL);
+	if (!e_ctrl->eboard_info) {
+		rc = -ENOMEM;
+		goto ectrl_free;
+	}
+	eb_info = e_ctrl->eboard_info;
+	power_info = &eb_info->power_info;
+	e_ctrl->i2c_client.client = client;
+	power_info->dev = &client->dev;
 
 	/*Get clocks information*/
 	rc = msm_camera_i2c_dev_get_clk_info(
 		&e_ctrl->i2c_client.client->dev,
-		&e_ctrl->eboard_info->power_info.clk_info,
-		&e_ctrl->eboard_info->power_info.clk_ptr,
-		&e_ctrl->eboard_info->power_info.clk_info_size);
+		&power_info->clk_info,
+		&power_info->clk_ptr,
+		&power_info->clk_info_size);
 	if (rc < 0) {
 		pr_err("failed: msm_camera_get_clk_info rc %d", rc);
-		goto ectrl_free;
+		goto board_free;
 	}
 
-	/*IMPLEMENT READING PART*/
+	rc = of_property_read_u32(of_node, "cell-index",
+		&e_ctrl->subdev_id);
+	CDBG("cell-index %d, rc %d\n", e_ctrl->subdev_id, rc);
+	if (rc < 0) {
+		pr_err("failed rc %d\n", rc);
+		goto board_free;
+	}
+
+	rc = of_property_read_string(of_node, "qcom,eeprom-name",
+		&eb_info->eeprom_name);
+	CDBG("%s qcom,eeprom-name %s, rc %d\n", __func__,
+		eb_info->eeprom_name, rc);
+	if (rc < 0) {
+		pr_err("%s failed %d\n", __func__, __LINE__);
+		e_ctrl->userspace_probe = 1;
+	}
+
+	rc = msm_eeprom_get_dt_data(e_ctrl);
+	if (rc < 0)
+		goto board_free;
+
+	if (e_ctrl->userspace_probe == 0) {
+		rc = of_property_read_u32(of_node, "qcom,slave-addr",
+			&temp);
+		if (rc < 0) {
+			pr_err("%s failed rc %d\n", __func__, rc);
+			goto board_free;
+		}
+
+		rc = of_property_read_u32(of_node, "qcom,i2c-freq-mode",
+			&e_ctrl->i2c_freq_mode);
+		CDBG("qcom,i2c_freq_mode %d, rc %d\n",
+			e_ctrl->i2c_freq_mode, rc);
+		if (rc < 0) {
+			pr_err("%s qcom,i2c-freq-mode read fail. Setting to 0 %d\n",
+				__func__, rc);
+			e_ctrl->i2c_freq_mode = 0;
+		}
+		if (e_ctrl->i2c_freq_mode >= I2C_MAX_MODES) {
+			pr_err("%s:%d invalid i2c_freq_mode = %d\n",
+				__func__, __LINE__, e_ctrl->i2c_freq_mode);
+			e_ctrl->i2c_freq_mode = 0;
+		}
+		eb_info->i2c_slaveaddr = temp;
+		CDBG("qcom,slave-addr = 0x%X\n", eb_info->i2c_slaveaddr);
+		eb_info->i2c_freq_mode = e_ctrl->i2c_freq_mode;
+
+		rc = msm_eeprom_parse_memory_map(of_node, &e_ctrl->cal_data);
+		if (rc < 0)
+			goto board_free;
+
+		rc = msm_camera_power_up(power_info, e_ctrl->eeprom_device_type,
+			&e_ctrl->i2c_client);
+		if (rc) {
+			pr_err("failed rc %d\n", rc);
+			goto memdata_free;
+		}
+
+		rc = read_eeprom_memory(e_ctrl, &e_ctrl->cal_data);
+		if (rc < 0) {
+			pr_err("%s read_eeprom_memory failed\n", __func__);
+			goto power_down;
+		}
+		CDBG("%s cal_data: %*ph\n", __func__,
+			e_ctrl->cal_data.num_data, e_ctrl->cal_data.mapdata);
+
+		e_ctrl->is_supported |= msm_eeprom_match_crc(&e_ctrl->cal_data);
+
+		rc = msm_camera_power_down(power_info,
+			e_ctrl->eeprom_device_type, &e_ctrl->i2c_client);
+		if (rc) {
+			pr_err("failed rc %d\n", rc);
+			goto memdata_free;
+		}
+	} else
+		e_ctrl->is_supported = 1;
+
 	/* Initialize sub device */
 	v4l2_i2c_subdev_init(&e_ctrl->msm_sd.sd,
 		e_ctrl->i2c_client.client,
@@ -846,12 +1017,23 @@
 	v4l2_set_subdevdata(&e_ctrl->msm_sd.sd, e_ctrl);
 	e_ctrl->msm_sd.sd.internal_ops = &msm_eeprom_internal_ops;
 	e_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	snprintf(e_ctrl->msm_sd.sd.name,
+		ARRAY_SIZE(e_ctrl->msm_sd.sd.name), "msm_eeprom");
 	media_entity_pads_init(&e_ctrl->msm_sd.sd.entity, 0, NULL);
 	e_ctrl->msm_sd.sd.entity.function = MSM_CAMERA_SUBDEV_EEPROM;
 	msm_sd_register(&e_ctrl->msm_sd);
-	CDBG("%s success result=%d X\n", __func__, rc);
+	e_ctrl->is_supported = (e_ctrl->is_supported << 1) | 1;
+	pr_err("%s success result=%d X\n", __func__, rc);
 	return rc;
 
+power_down:
+	msm_camera_power_down(power_info, e_ctrl->eeprom_device_type,
+		&e_ctrl->i2c_client);
+memdata_free:
+	kfree(e_ctrl->cal_data.mapdata);
+	kfree(e_ctrl->cal_data.map);
+board_free:
+	kfree(e_ctrl->eboard_info);
 ectrl_free:
 	kfree(e_ctrl);
 probe_failure:
@@ -961,91 +1143,6 @@
 	return 0;
 }
 
-static int msm_eeprom_get_dt_data(struct msm_eeprom_ctrl_t *e_ctrl)
-{
-	int rc = 0, i = 0;
-	struct msm_eeprom_board_info *eb_info;
-	struct msm_camera_power_ctrl_t *power_info =
-		&e_ctrl->eboard_info->power_info;
-	struct device_node *of_node = NULL;
-	struct msm_camera_gpio_conf *gconf = NULL;
-	int8_t gpio_array_size = 0;
-	uint16_t *gpio_array = NULL;
-
-	eb_info = e_ctrl->eboard_info;
-	if (e_ctrl->eeprom_device_type == MSM_CAMERA_SPI_DEVICE)
-		of_node = e_ctrl->i2c_client.
-			spi_client->spi_master->dev.of_node;
-	else if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE)
-		of_node = e_ctrl->pdev->dev.of_node;
-
-	if (!of_node) {
-		pr_err("%s: %d of_node is NULL\n", __func__, __LINE__);
-		return -ENOMEM;
-	}
-	rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg,
-					     &power_info->num_vreg);
-	if (rc < 0)
-		return rc;
-
-	if (e_ctrl->userspace_probe == 0) {
-		rc = msm_camera_get_dt_power_setting_data(of_node,
-			power_info->cam_vreg, power_info->num_vreg,
-			power_info);
-		if (rc < 0)
-			goto ERROR1;
-	}
-
-	power_info->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf),
-					GFP_KERNEL);
-	if (!power_info->gpio_conf) {
-		rc = -ENOMEM;
-		goto ERROR2;
-	}
-	gconf = power_info->gpio_conf;
-	gpio_array_size = of_gpio_count(of_node);
-	CDBG("%s gpio count %d\n", __func__, gpio_array_size);
-
-	if (gpio_array_size > 0) {
-		gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t),
-			GFP_KERNEL);
-		if (!gpio_array)
-			goto ERROR3;
-		for (i = 0; i < gpio_array_size; i++) {
-			gpio_array[i] = of_get_gpio(of_node, i);
-			CDBG("%s gpio_array[%d] = %d\n", __func__, i,
-				gpio_array[i]);
-		}
-
-		rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf,
-			gpio_array, gpio_array_size);
-		if (rc < 0) {
-			pr_err("%s failed %d\n", __func__, __LINE__);
-			goto ERROR4;
-		}
-
-		rc = msm_camera_init_gpio_pin_tbl(of_node, gconf,
-			gpio_array, gpio_array_size);
-		if (rc < 0) {
-			pr_err("%s failed %d\n", __func__, __LINE__);
-			goto ERROR4;
-		}
-		kfree(gpio_array);
-	}
-
-	return rc;
-ERROR4:
-	kfree(gpio_array);
-ERROR3:
-	kfree(power_info->gpio_conf);
-ERROR2:
-	kfree(power_info->cam_vreg);
-ERROR1:
-	kfree(power_info->power_setting);
-	return rc;
-}
-
-
 static int msm_eeprom_cmm_dts(struct msm_eeprom_board_info *eb_info,
 	struct device_node *of_node)
 {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
index 7832181..4bc13d0 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
@@ -513,7 +513,7 @@
 	int c, end;
 	struct msm_sensor_power_setting pd_tmp;
 
-	pr_err("Generating power_down_setting");
+	pr_err("Generating power_down_setting\n");
 
 #ifdef CONFIG_COMPAT
 	if (is_compat_task()) {
@@ -603,7 +603,7 @@
 
 	/* Print power setting */
 	for (i = 0; i < size_down; i++) {
-		CDBG("DOWN seq_type %d seq_val %d config_val %ld delay %d",
+		CDBG("DOWN seq_type %d seq_val %d config_val %ld delay %d\n",
 			pd[i].seq_type, pd[i].seq_val,
 			pd[i].config_val, pd[i].delay);
 	}
@@ -657,7 +657,7 @@
 
 	/* Print power setting */
 	for (i = 0; i < size; i++) {
-		CDBG("UP seq_type %d seq_val %d config_val %ld delay %d",
+		CDBG("UP seq_type %d seq_val %d config_val %ld delay %d\n",
 			pu[i].seq_type, pu[i].seq_val,
 			pu[i].config_val, pu[i].delay);
 	}
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
index ce50dcd..ca3b010 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -303,7 +303,7 @@
 	int ret = 0;
 
 	if (mgr->regulator_enable == on) {
-		SDEROT_ERR("Regulators already in selected mode on=%d\n", on);
+		SDEROT_DBG("Regulators already in selected mode on=%d\n", on);
 		return 0;
 	}
 
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
index 48ef46c..c0566a3 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
@@ -3733,6 +3733,7 @@
 		.name = SDE_ROTATOR_DRV_NAME,
 		.of_match_table = sde_rotator_dt_match,
 		.pm = &sde_rotator_pm_ops,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
index 84efd3d..eeca9f3 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -1496,7 +1496,7 @@
 			(fmt->bits[C0_G_Y] << 0);
 
 	/* alpha control */
-	if (fmt->bits[C3_ALPHA] || fmt->alpha_enable) {
+	if (fmt->alpha_enable || (!fmt->is_yuv && (fmt->unpack_count == 4))) {
 		dst_format |= BIT(8);
 		if (!fmt->alpha_enable) {
 			dst_format |= BIT(14);
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index 42bf1ba..5c82704 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -711,6 +711,10 @@
 	sysfs_remove_group(&pdev->dev.kobj, &msm_vidc_core_attr_group);
 	dev_set_drvdata(&pdev->dev, NULL);
 	mutex_destroy(&core->lock);
+
+	mutex_lock(&vidc_driver->lock);
+	list_del(&core->list);
+	mutex_unlock(&vidc_driver->lock);
 	kfree(core);
 	return rc;
 }
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index d77ea21..b878971 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -6724,6 +6724,7 @@
 	struct msm_vidc_buffer *temp;
 	bool found = false;
 	int i = 0;
+	u32 planes[VIDEO_MAX_PLANES] = {0};
 
 	mutex_lock(&inst->flush_lock);
 	mutex_lock(&inst->registeredbufs.lock);
@@ -6737,6 +6738,10 @@
 		}
 	}
 	if (found) {
+		/* save device_addr */
+		for (i = 0; i < mbuf->vvb.vb2_buf.num_planes; i++)
+			planes[i] = mbuf->smem[i].device_addr;
+
 		/* send RBR event to client */
 		msm_vidc_queue_rbr_event(inst,
 			mbuf->vvb.vb2_buf.planes[0].m.fd,
@@ -6755,6 +6760,7 @@
 		if (!mbuf->smem[0].refcount) {
 			list_del(&mbuf->list);
 			kref_put_mbuf(mbuf);
+			mbuf = NULL;
 		}
 	} else {
 		print_vidc_buffer(VIDC_ERR, "mbuf not found", inst, mbuf);
@@ -6772,8 +6778,8 @@
 	 */
 	found = false;
 	list_for_each_entry(temp, &inst->registeredbufs.list, list) {
-		if (msm_comm_compare_vb2_plane(inst, mbuf,
-				&temp->vvb.vb2_buf, 0)) {
+		if (msm_comm_compare_device_plane(temp, planes, 0)) {
+			mbuf = temp;
 			found = true;
 			break;
 		}
@@ -6793,9 +6799,11 @@
 		/* don't queue the buffer */
 		found = false;
 	}
-	/* clear DEFERRED flag, if any, as the buffer is going to be queued */
-	if (found)
+	/* clear required flags as the buffer is going to be queued */
+	if (found) {
 		mbuf->flags &= ~MSM_VIDC_FLAG_DEFERRED;
+		mbuf->flags &= ~MSM_VIDC_FLAG_RBR_PENDING;
+	}
 
 unlock:
 	mutex_unlock(&inst->registeredbufs.lock);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 07ae56f..0ee8208 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -189,6 +189,7 @@
 	wait_queue_head_t          listener_block_app_wq;
 	struct sglist_info sglistinfo_ptr[MAX_ION_FD];
 	uint32_t sglist_cnt;
+	int abort;
 };
 
 struct qseecom_registered_app_list {
@@ -1223,6 +1224,23 @@
 	return ret;
 }
 
+static void __qseecom_listener_abort_all(int abort)
+{
+	struct qseecom_registered_listener_list *entry = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&qseecom.registered_listener_list_lock, flags);
+	list_for_each_entry(entry,
+			&qseecom.registered_listener_list_head, list) {
+		pr_debug("set abort %d for listener %d\n",
+				abort, entry->svc.listener_id);
+		entry->abort = abort;
+	}
+	if (abort)
+		wake_up_interruptible_all(&qseecom.send_resp_wq);
+	spin_unlock_irqrestore(&qseecom.registered_listener_list_lock, flags);
+}
+
 static int qseecom_unregister_listener(struct qseecom_dev_handle *data)
 {
 	int ret = 0;
@@ -1256,6 +1274,7 @@
 	list_for_each_entry(ptr_svc, &qseecom.registered_listener_list_head,
 			list) {
 		if (ptr_svc->svc.listener_id == data->listener.id) {
+			ptr_svc->abort = 1;
 			wake_up_all(&ptr_svc->rcv_req_wq);
 			break;
 		}
@@ -1602,12 +1621,13 @@
 	return 0;
 }
 
-static int __qseecom_listener_has_sent_rsp(struct qseecom_dev_handle *data)
+static int __qseecom_listener_has_sent_rsp(struct qseecom_dev_handle *data,
+			struct qseecom_registered_listener_list *ptr_svc)
 {
 	int ret;
 
 	ret = (qseecom.send_resp_flag != 0);
-	return ret || data->abort;
+	return ret || data->abort || ptr_svc->abort;
 }
 
 static int __qseecom_reentrancy_listener_has_sent_rsp(
@@ -1617,56 +1637,7 @@
 	int ret;
 
 	ret = (ptr_svc->send_resp_flag != 0);
-	return ret || data->abort;
-}
-
-static int __qseecom_qseos_fail_return_resp_tz(struct qseecom_dev_handle *data,
-					struct qseecom_command_scm_resp *resp,
-			struct qseecom_client_listener_data_irsp *send_data_rsp,
-			struct qseecom_registered_listener_list *ptr_svc,
-							uint32_t lstnr) {
-	int ret = 0;
-
-	send_data_rsp->status = QSEOS_RESULT_FAILURE;
-	qseecom.send_resp_flag = 0;
-	send_data_rsp->qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND;
-	send_data_rsp->listener_id = lstnr;
-	if (ptr_svc)
-		pr_warn("listener_id:%x, lstnr: %x\n",
-					ptr_svc->svc.listener_id, lstnr);
-	if (ptr_svc && ptr_svc->ihandle) {
-		ret = msm_ion_do_cache_op(qseecom.ion_clnt, ptr_svc->ihandle,
-					ptr_svc->sb_virt, ptr_svc->sb_length,
-					ION_IOC_CLEAN_INV_CACHES);
-		if (ret) {
-			pr_err("cache operation failed %d\n", ret);
-			return ret;
-		}
-	}
-
-	if (lstnr == RPMB_SERVICE) {
-		ret = __qseecom_enable_clk(CLK_QSEE);
-		if (ret)
-			return ret;
-	}
-	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, send_data_rsp,
-				sizeof(send_data_rsp), resp, sizeof(*resp));
-	if (ret) {
-		pr_err("scm_call() failed with err: %d (app_id = %d)\n",
-						ret, data->client.app_id);
-		if (lstnr == RPMB_SERVICE)
-			__qseecom_disable_clk(CLK_QSEE);
-		return ret;
-	}
-	if ((resp->result != QSEOS_RESULT_SUCCESS) &&
-			(resp->result != QSEOS_RESULT_INCOMPLETE)) {
-		pr_err("fail:resp res= %d,app_id = %d,lstr = %d\n",
-				resp->result, data->client.app_id, lstnr);
-		ret = -EINVAL;
-	}
-	if (lstnr == RPMB_SERVICE)
-		__qseecom_disable_clk(CLK_QSEE);
-	return ret;
+	return ret || data->abort || ptr_svc->abort;
 }
 
 static void __qseecom_clean_listener_sglistinfo(
@@ -1717,23 +1688,33 @@
 
 		if (ptr_svc == NULL) {
 			pr_err("Listener Svc %d does not exist\n", lstnr);
-			__qseecom_qseos_fail_return_resp_tz(data, resp,
-					&send_data_rsp, ptr_svc, lstnr);
-			return -EINVAL;
+			rc = -EINVAL;
+			status = QSEOS_RESULT_FAILURE;
+			goto err_resp;
 		}
 
 		if (!ptr_svc->ihandle) {
 			pr_err("Client handle is not initialized\n");
-			__qseecom_qseos_fail_return_resp_tz(data, resp,
-					&send_data_rsp, ptr_svc, lstnr);
-			return -EINVAL;
+			rc = -EINVAL;
+			status = QSEOS_RESULT_FAILURE;
+			goto err_resp;
 		}
 
 		if (ptr_svc->svc.listener_id != lstnr) {
-			pr_warn("Service requested does not exist\n");
-			__qseecom_qseos_fail_return_resp_tz(data, resp,
-					&send_data_rsp, NULL, lstnr);
-			return -ERESTARTSYS;
+			pr_err("Service %d does not exist\n",
+						lstnr);
+			rc = -ERESTARTSYS;
+			ptr_svc = NULL;
+			status = QSEOS_RESULT_FAILURE;
+			goto err_resp;
+		}
+
+		if (ptr_svc->abort == 1) {
+			pr_err("Service %d abort %d\n",
+						lstnr, ptr_svc->abort);
+			rc = -ENODEV;
+			status = QSEOS_RESULT_FAILURE;
+			goto err_resp;
 		}
 		pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n");
 
@@ -1750,7 +1731,8 @@
 			 */
 			if (!qseecom.qsee_reentrancy_support &&
 				!wait_event_freezable(qseecom.send_resp_wq,
-				__qseecom_listener_has_sent_rsp(data))) {
+				__qseecom_listener_has_sent_rsp(
+						data, ptr_svc))) {
 				break;
 			}
 
@@ -1764,7 +1746,7 @@
 
 		/* restore signal mask */
 		sigprocmask(SIG_SETMASK, &old_sigset, NULL);
-		if (data->abort) {
+		if (data->abort || ptr_svc->abort) {
 			pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d",
 				data->client.app_id, lstnr, ret);
 			rc = -ENODEV;
@@ -1772,7 +1754,7 @@
 		} else {
 			status = QSEOS_RESULT_SUCCESS;
 		}
-
+err_resp:
 		qseecom.send_resp_flag = 0;
 		ptr_svc->send_resp_flag = 0;
 		table = ptr_svc->sglistinfo_ptr;
@@ -1832,6 +1814,8 @@
 				__qseecom_disable_clk(CLK_QSEE);
 			return ret;
 		}
+		pr_debug("resp status %d, res= %d, app_id = %d, lstr = %d\n",
+			status, resp->result, data->client.app_id, lstnr);
 		if ((resp->result != QSEOS_RESULT_SUCCESS) &&
 			(resp->result != QSEOS_RESULT_INCOMPLETE)) {
 			pr_err("fail:resp res= %d,app_id = %d,lstr = %d\n",
@@ -1985,7 +1969,7 @@
 	size_t cmd_len;
 	struct sglist_info *table = NULL;
 
-	while (ret == 0 && rc == 0 && resp->result == QSEOS_RESULT_INCOMPLETE) {
+	while (ret == 0 && resp->result == QSEOS_RESULT_INCOMPLETE) {
 		lstnr = resp->data;
 		/*
 		 * Wake up blocking lsitener service with the lstnr id
@@ -2006,17 +1990,33 @@
 
 		if (ptr_svc == NULL) {
 			pr_err("Listener Svc %d does not exist\n", lstnr);
-			return -EINVAL;
+			rc = -EINVAL;
+			status = QSEOS_RESULT_FAILURE;
+			goto err_resp;
 		}
 
 		if (!ptr_svc->ihandle) {
 			pr_err("Client handle is not initialized\n");
-			return -EINVAL;
+			rc = -EINVAL;
+			status = QSEOS_RESULT_FAILURE;
+			goto err_resp;
 		}
 
 		if (ptr_svc->svc.listener_id != lstnr) {
-			pr_warn("Service requested does not exist\n");
-			return -ERESTARTSYS;
+			pr_err("Service %d does not exist\n",
+						lstnr);
+			rc = -ERESTARTSYS;
+			ptr_svc = NULL;
+			status = QSEOS_RESULT_FAILURE;
+			goto err_resp;
+		}
+
+		if (ptr_svc->abort == 1) {
+			pr_err("Service %d abort %d\n",
+						lstnr, ptr_svc->abort);
+			rc = -ENODEV;
+			status = QSEOS_RESULT_FAILURE;
+			goto err_resp;
 		}
 		pr_debug("waking up rcv_req_wq and waiting for send_resp_wq\n");
 
@@ -2042,7 +2042,7 @@
 
 		/* restore signal mask */
 		sigprocmask(SIG_SETMASK, &old_sigset, NULL);
-		if (data->abort) {
+		if (data->abort || ptr_svc->abort) {
 			pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d",
 				data->client.app_id, lstnr, ret);
 			rc = -ENODEV;
@@ -2050,6 +2050,7 @@
 		} else {
 			status  = QSEOS_RESULT_SUCCESS;
 		}
+err_resp:
 		table = ptr_svc->sglistinfo_ptr;
 		if (qseecom.qsee_version < QSEE_VERSION_40) {
 			send_data_rsp.listener_id  = lstnr;
@@ -3813,7 +3814,7 @@
 	int ret;
 
 	ret = (svc->rcv_req_flag != 0);
-	return ret || data->abort;
+	return ret || data->abort || svc->abort;
 }
 
 static int qseecom_receive_req(struct qseecom_dev_handle *data)
@@ -3837,9 +3838,9 @@
 			return -ERESTARTSYS;
 		}
 
-		if (data->abort) {
+		if (data->abort || this_lstnr->abort) {
 			pr_err("Aborting Listener Service = %d\n",
-						(uint32_t)data->listener.id);
+					(uint32_t)data->listener.id);
 			return -ENODEV;
 		}
 		this_lstnr->rcv_req_flag = 0;
@@ -6154,7 +6155,7 @@
 }
 static int qseecom_is_es_activated(void __user *argp)
 {
-	struct qseecom_is_es_activated_req req;
+	struct qseecom_is_es_activated_req req = {0};
 	struct qseecom_command_scm_resp resp;
 	int ret;
 
@@ -6999,12 +7000,14 @@
 			break;
 		}
 		pr_debug("ioctl unregister_listener_req()\n");
+		__qseecom_listener_abort_all(1);
 		mutex_lock(&app_access_lock);
 		atomic_inc(&data->ioctl_count);
 		ret = qseecom_unregister_listener(data);
 		atomic_dec(&data->ioctl_count);
 		wake_up_all(&data->abort_wq);
 		mutex_unlock(&app_access_lock);
+		__qseecom_listener_abort_all(0);
 		if (ret)
 			pr_err("failed qseecom_unregister_listener: %d\n", ret);
 		break;
@@ -7671,9 +7674,11 @@
 			data->type, data->mode, data);
 		switch (data->type) {
 		case QSEECOM_LISTENER_SERVICE:
+			__qseecom_listener_abort_all(1);
 			mutex_lock(&app_access_lock);
 			ret = qseecom_unregister_listener(data);
 			mutex_unlock(&app_access_lock);
+			__qseecom_listener_abort_all(0);
 			break;
 		case QSEECOM_CLIENT_APP:
 			mutex_lock(&app_access_lock);
@@ -8792,11 +8797,11 @@
 		&qseecom.registered_kclient_list_head, list) {
 
 		/* Break the loop if client handle is NULL */
-		if (!kclient->handle)
-			goto exit_free_kclient;
-
-		if (list_empty(&kclient->list))
-			goto exit_free_kc_handle;
+		if (!kclient->handle) {
+			list_del(&kclient->list);
+			kzfree(kclient);
+			break;
+		}
 
 		list_del(&kclient->list);
 		mutex_lock(&app_access_lock);
@@ -8809,11 +8814,6 @@
 		}
 	}
 
-exit_free_kc_handle:
-	kzfree(kclient->handle);
-exit_free_kclient:
-	kzfree(kclient);
-
 	spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags);
 
 	if (qseecom.qseos_version > QSEEE_VERSION_00)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 7d24213..1119292 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -5239,19 +5239,50 @@
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 	struct sdhci_msm_host *msm_host = pltfm_host->priv;
 	struct sdhci_msm_pltfm_data *pdata = msm_host->pdata;
+	int nr_groups = msm_host->pdata->pm_qos_data.cpu_group_map.nr_groups;
+	int i;
 	int dead = (readl_relaxed(host->ioaddr + SDHCI_INT_STATUS) ==
 			0xffffffff);
 
-	pr_debug("%s: %s\n", dev_name(&pdev->dev), __func__);
+	pr_debug("%s: %s Enter\n", dev_name(&pdev->dev), __func__);
 	if (!gpio_is_valid(msm_host->pdata->status_gpio))
 		device_remove_file(&pdev->dev, &msm_host->polling);
+
+	device_remove_file(&pdev->dev, &msm_host->auto_cmd21_attr);
 	device_remove_file(&pdev->dev, &msm_host->msm_bus_vote.max_bus_bw);
 	pm_runtime_disable(&pdev->dev);
 
+	if (msm_host->pm_qos_group_enable) {
+		struct sdhci_msm_pm_qos_group *group;
+
+		for (i = 0; i < nr_groups; i++)
+			cancel_delayed_work_sync(
+					&msm_host->pm_qos[i].unvote_work);
+
+		device_remove_file(&msm_host->pdev->dev,
+			&msm_host->pm_qos_group_enable_attr);
+		device_remove_file(&msm_host->pdev->dev,
+			&msm_host->pm_qos_group_status_attr);
+
+		for (i = 0; i < nr_groups; i++) {
+			group = &msm_host->pm_qos[i];
+			pm_qos_remove_request(&group->req);
+		}
+	}
+
+	if (msm_host->pm_qos_irq.enabled) {
+		cancel_delayed_work_sync(&msm_host->pm_qos_irq.unvote_work);
+		device_remove_file(&pdev->dev,
+				&msm_host->pm_qos_irq.enable_attr);
+		device_remove_file(&pdev->dev,
+				&msm_host->pm_qos_irq.status_attr);
+		pm_qos_remove_request(&msm_host->pm_qos_irq.req);
+	}
+
 	if (msm_host->pm_qos_wq)
 		destroy_workqueue(msm_host->pm_qos_wq);
+
 	sdhci_remove_host(host, dead);
-	sdhci_pltfm_free(pdev);
 
 	sdhci_msm_vreg_init(&pdev->dev, msm_host->pdata, false);
 
@@ -5262,6 +5293,9 @@
 		sdhci_msm_bus_cancel_work_and_set_vote(host, 0);
 		sdhci_msm_bus_unregister(msm_host);
 	}
+
+	sdhci_pltfm_free(pdev);
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index bb2270b..c915ded 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -114,3 +114,5 @@
 source "drivers/net/wireless/cnss_genl/Kconfig"
 
 endif # WLAN
+
+source "drivers/net/wireless/qca402x/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 917a876..6cf62b66 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -32,3 +32,4 @@
 obj-$(CONFIG_CNSS_UTILS) += cnss_utils/
 obj-$(CONFIG_CNSS_GENL) += cnss_genl/
 obj-$(CONFIG_CNSS_CRYPTO) += cnss_crypto/
+obj-$(CONFIG_QCA402X) += qca402x/
diff --git a/drivers/net/wireless/cnss/Kconfig b/drivers/net/wireless/cnss/Kconfig
index 0b37af6..c18cea7 100644
--- a/drivers/net/wireless/cnss/Kconfig
+++ b/drivers/net/wireless/cnss/Kconfig
@@ -61,6 +61,19 @@
 	  Say N, if you are building a release kernel for production use.
 	  Only say Y, if you are building a kernel with debug support.
 
+config CLD_USB_CORE
+	tristate "Qualcomm Technologies Inc. Core wlan driver for QCA USB interface"
+	select WIRELESS_EXT
+	select WEXT_PRIV
+	select WEXT_CORE
+	select WEXT_SPY
+	select NL80211_TESTMODE
+	---help---
+	  This section contains the necessary modules needed to enable the
+	  core WLAN driver for Qualcomm Technologies Inc USB wlan chipset.
+	  Select Y to compile the driver in order to have WLAN functionality
+	  support.
+
 config CLD_HL_SDIO_CORE
 	tristate "Qualcomm Technologies Inc. Core wlan driver for QCA SDIO interface"
 	select WIRELESS_EXT
diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c
index 8797e68..b99a813 100644
--- a/drivers/net/wireless/cnss/cnss_pci.c
+++ b/drivers/net/wireless/cnss/cnss_pci.c
@@ -234,8 +234,11 @@
 	struct pci_dev *pdev;
 	const struct pci_device_id *id;
 	struct dma_iommu_mapping *smmu_mapping;
+	bool smmu_s1_bypass;
 	dma_addr_t smmu_iova_start;
 	size_t smmu_iova_len;
+	dma_addr_t smmu_iova_ipa_start;
+	size_t smmu_iova_ipa_len;
 	struct cnss_wlan_vreg_info vreg_info;
 	bool wlan_en_vreg_support;
 	struct cnss_wlan_gpio_info gpio_info;
@@ -1438,6 +1441,8 @@
 {
 	struct dma_iommu_mapping *mapping;
 	int atomic_ctx = 1;
+	int s1_bypass = 1;
+	int fast = 1;
 	int ret;
 
 	mapping = arm_iommu_create_mapping(&platform_bus_type,
@@ -1449,13 +1454,33 @@
 		goto map_fail;
 	}
 
-	ret = iommu_domain_set_attr(mapping->domain,
-				    DOMAIN_ATTR_ATOMIC,
-				    &atomic_ctx);
-	if (ret) {
-		pr_err("%s: set atomic_ctx attribute failed, err = %d\n",
-		       __func__, ret);
-		goto set_attr_fail;
+	if (penv->smmu_s1_bypass) {
+		ret = iommu_domain_set_attr(mapping->domain,
+					    DOMAIN_ATTR_S1_BYPASS,
+					    &s1_bypass);
+		if (ret) {
+			pr_err("%s: set s1 bypass attr failed, err = %d\n",
+			       __func__, ret);
+			goto set_attr_fail;
+		}
+	} else {
+		ret = iommu_domain_set_attr(mapping->domain,
+					    DOMAIN_ATTR_ATOMIC,
+					    &atomic_ctx);
+		if (ret) {
+			pr_err("%s: set atomic_ctx attr failed, err = %d\n",
+			       __func__, ret);
+			goto set_attr_fail;
+		}
+
+		ret = iommu_domain_set_attr(mapping->domain,
+					    DOMAIN_ATTR_FAST,
+					    &fast);
+		if (ret) {
+			pr_err("%s: set fast map attr failed, err = %d\n",
+			       __func__, ret);
+			goto set_attr_fail;
+		}
 	}
 
 	ret = arm_iommu_attach_device(dev, mapping);
@@ -1618,7 +1643,6 @@
 		if (ret) {
 			pr_err("%s: SMMU init failed, err = %d\n",
 			       __func__, ret);
-			goto smmu_init_fail;
 		}
 	}
 
@@ -1714,7 +1738,6 @@
 	dma_free_coherent(dev, EVICT_BIN_MAX_SIZE, cpu_addr, dma_handle);
 err_unknown:
 err_pcie_suspend:
-smmu_init_fail:
 	cnss_pcie_reset_platform_ops(dev);
 	return ret;
 }
@@ -2717,10 +2740,14 @@
 	cnss_configure_wlan_en_gpio(WLAN_EN_LOW);
 	cnss_wlan_vreg_set(vreg_info, VREG_OFF);
 	if (penv->pdev) {
-		pr_err("%d: Unregistering pci device\n", __LINE__);
-		pci_unregister_driver(&cnss_wlan_pci_driver);
-		penv->pdev = NULL;
-		penv->pci_register_again = true;
+		if (wdrv && wdrv->update_status)
+			wdrv->update_status(penv->pdev, CNSS_SSR_FAIL);
+		if (!penv->recovery_in_progress) {
+			pr_err("%d: Unregistering pci device\n", __LINE__);
+			pci_unregister_driver(&cnss_wlan_pci_driver);
+			penv->pdev = NULL;
+			penv->pci_register_again = true;
+		}
 	}
 
 err_wlan_vreg_on:
@@ -2867,6 +2894,55 @@
 	return msm_dump_data_register(MSM_DUMP_TABLE_APPS, &dump_entry);
 }
 
+struct dma_iommu_mapping *cnss_smmu_get_mapping(void)
+{
+	if (!penv) {
+		pr_err("Invalid penv: data %pK\n", penv);
+		return NULL;
+	}
+
+	return penv->smmu_mapping;
+}
+EXPORT_SYMBOL(cnss_smmu_get_mapping);
+
+int cnss_smmu_map(phys_addr_t paddr, uint32_t *iova_addr, size_t size)
+{
+	unsigned long iova;
+	size_t len;
+	int ret = 0;
+
+	if (!iova_addr) {
+		pr_err("iova_addr is NULL, paddr %pa, size %zu\n",
+		       &paddr, size);
+		return -EINVAL;
+	}
+
+	len = roundup(size + paddr - rounddown(paddr, PAGE_SIZE), PAGE_SIZE);
+	iova = roundup(penv->smmu_iova_ipa_start, PAGE_SIZE);
+
+	if (iova >= penv->smmu_iova_ipa_start + penv->smmu_iova_ipa_len) {
+		pr_err("No IOVA space to map, iova %lx, smmu_iova_ipa_start %pad, smmu_iova_ipa_len %zu\n",
+		       iova,
+		       &penv->smmu_iova_ipa_start,
+		       penv->smmu_iova_ipa_len);
+		return -ENOMEM;
+	}
+
+	ret = iommu_map(penv->smmu_mapping->domain, iova,
+			rounddown(paddr, PAGE_SIZE), len,
+			IOMMU_READ | IOMMU_WRITE);
+	if (ret) {
+		pr_err("PA to IOVA mapping failed, ret %d\n", ret);
+		return ret;
+	}
+
+	penv->smmu_iova_ipa_start = iova + len;
+	*iova_addr = (uint32_t)(iova + paddr - rounddown(paddr, PAGE_SIZE));
+
+	return 0;
+}
+EXPORT_SYMBOL(cnss_smmu_map);
+
 static int cnss_probe(struct platform_device *pdev)
 {
 	int ret = 0;
@@ -2877,6 +2953,7 @@
 	struct resource *res;
 	u32 ramdump_size = 0;
 	u32 smmu_iova_address[2];
+	u32 smmu_iova_ipa[2];
 
 	if (penv)
 		return -ENODEV;
@@ -3028,6 +3105,17 @@
 		penv->smmu_iova_len = smmu_iova_address[1];
 	}
 
+	if (of_property_read_u32_array(dev->of_node,
+				       "qcom,wlan-smmu-iova-ipa",
+				       smmu_iova_ipa, 2) == 0) {
+		penv->smmu_iova_ipa_start = smmu_iova_ipa[0];
+		penv->smmu_iova_ipa_len = smmu_iova_ipa[1];
+	}
+
+	if (of_property_read_bool(dev->of_node,
+				  "qcom,smmu-s1-bypass"))
+		penv->smmu_s1_bypass = true;
+
 	ret = pci_register_driver(&cnss_wlan_pci_driver);
 	if (ret)
 		goto err_pci_reg;
diff --git a/drivers/net/wireless/cnss2/Kconfig b/drivers/net/wireless/cnss2/Kconfig
index daa343e..209d315 100644
--- a/drivers/net/wireless/cnss2/Kconfig
+++ b/drivers/net/wireless/cnss2/Kconfig
@@ -16,6 +16,16 @@
 	  features, enabling kernel panic for certain cases to aid the
 	  debugging, and enabling any other debug mechanisms.
 
+config CNSS2_QMI
+	bool "CNSS2 Platform Driver QMI support"
+	depends on CNSS2
+	---help---
+	  CNSS2 platform driver uses QMI framework to communicate with WLAN
+	  firmware. It sends and receives boot handshake messages to WLAN
+	  firmware, which includes hardware and software capabilities and
+	  configurations. It also sends WLAN on/off control message to
+	  firmware over QMI channel.
+
 config CNSS_ASYNC
 	bool "Enable/disable CNSS platform driver asynchronous probe"
 	depends on CNSS2
@@ -38,3 +48,27 @@
 	  during system pm.
 	  This config flag controls the feature per target based. The feature
 	  requires CNSS driver support.
+
+config CNSS_QCA6290
+	bool "Enable CNSS QCA6290 chipset specific changes"
+	---help---
+	  This enables the changes from WLAN host driver that are specific to
+	  CNSS QCA6290 chipset.
+	  These changes are needed to support the new hardware architecture
+	  for CNSS QCA6290 chipset.
+
+config CNSS_QCA6390
+	bool "Enable CNSS QCA6390 chipset specific changes"
+	---help---
+	  This enables the changes from WLAN host driver that are specific to
+	  CNSS QCA6390 chipset.
+	  These changes are needed to support the new hardware architecture
+	  for CNSS QCA6390 chipset.
+
+config CNSS_EMULATION
+	bool "Enable specific changes for emulation hardware"
+	---help---
+	  This enables the changes from WLAN drivers that are specific to
+	  emulation hardware.
+	  These changes are needed for WLAN drivers to support and meet the
+	  requirement of emulation hardware.
diff --git a/drivers/net/wireless/cnss2/Makefile b/drivers/net/wireless/cnss2/Makefile
index 318076f..fe0f595 100644
--- a/drivers/net/wireless/cnss2/Makefile
+++ b/drivers/net/wireless/cnss2/Makefile
@@ -5,5 +5,4 @@
 cnss2-y += debug.o
 cnss2-y += pci.o
 cnss2-y += power.o
-cnss2-y += qmi.o
-cnss2-y += wlan_firmware_service_v01.o
+cnss2-$(CONFIG_CNSS2_QMI) += qmi.o wlan_firmware_service_v01.o
diff --git a/drivers/net/wireless/cnss2/bus.c b/drivers/net/wireless/cnss2/bus.c
index c35d661..6a8e67c 100644
--- a/drivers/net/wireless/cnss2/bus.c
+++ b/drivers/net/wireless/cnss2/bus.c
@@ -218,7 +218,7 @@
 
 	switch (plat_priv->bus_type) {
 	case CNSS_BUS_PCI:
-		return cnss_bus_call_driver_remove(plat_priv->bus_priv);
+		return cnss_pci_call_driver_remove(plat_priv->bus_priv);
 	default:
 		cnss_pr_err("Unsupported bus type: %d\n",
 			    plat_priv->bus_type);
diff --git a/drivers/net/wireless/cnss2/bus.h b/drivers/net/wireless/cnss2/bus.h
index 532438a..91356e9 100644
--- a/drivers/net/wireless/cnss2/bus.h
+++ b/drivers/net/wireless/cnss2/bus.h
@@ -24,6 +24,9 @@
 #define QCA6290_DEVICE_ID		0x1100
 #define QCA6290_EMULATION_VENDOR_ID	0x168C
 #define QCA6290_EMULATION_DEVICE_ID	0xABCD
+#define QCA6390_VENDOR_ID		0x17CB
+#define QCA6390_EMULATION_DEVICE_ID	0x0108
+#define QCA6390_DEVICE_ID		0x1101
 
 enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev);
 enum cnss_dev_bus_type cnss_get_bus_type(unsigned long device_id);
diff --git a/drivers/net/wireless/cnss2/debug.c b/drivers/net/wireless/cnss2/debug.c
index b1fbbd8..53a4620 100644
--- a/drivers/net/wireless/cnss2/debug.c
+++ b/drivers/net/wireless/cnss2/debug.c
@@ -147,6 +147,8 @@
 		return -ENODEV;
 
 	pci_priv = plat_priv->bus_priv;
+	if (!pci_priv)
+		return -ENODEV;
 
 	len = min(count, sizeof(buf) - 1);
 	if (copy_from_user(buf, user_buf, len))
@@ -304,10 +306,6 @@
 	if (kstrtou32(token, 0, &data_len))
 		return -EINVAL;
 
-	if (data_len == 0 ||
-	    data_len > QMI_WLFW_MAX_ATHDIAG_DATA_SIZE_V01)
-		return -EINVAL;
-
 	mutex_lock(&plat_priv->dev_lock);
 	kfree(plat_priv->diag_reg_read_buf);
 	plat_priv->diag_reg_read_buf = NULL;
diff --git a/drivers/net/wireless/cnss2/debug.h b/drivers/net/wireless/cnss2/debug.h
index f31fdfe..bf2e755 100644
--- a/drivers/net/wireless/cnss2/debug.h
+++ b/drivers/net/wireless/cnss2/debug.h
@@ -26,23 +26,23 @@
 	} while (0)
 
 #define cnss_pr_err(_fmt, ...) do {					\
-		pr_err("cnss: " _fmt, ##__VA_ARGS__);			\
-		cnss_ipc_log_string("ERR: " _fmt, ##__VA_ARGS__);	\
+		printk("%scnss: " _fmt, KERN_ERR, ##__VA_ARGS__);	\
+		cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\
 	} while (0)
 
 #define cnss_pr_warn(_fmt, ...) do {					\
-		pr_warn("cnss: " _fmt, ##__VA_ARGS__);			\
-		cnss_ipc_log_string("WRN: " _fmt, ##__VA_ARGS__);	\
+		printk("%scnss: " _fmt, KERN_WARNING, ##__VA_ARGS__);	\
+		cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\
 	} while (0)
 
 #define cnss_pr_info(_fmt, ...) do {					\
-		pr_info("cnss: " _fmt, ##__VA_ARGS__);			\
-		cnss_ipc_log_string("INF: " _fmt, ##__VA_ARGS__);	\
+		printk("%scnss: " _fmt, KERN_INFO, ##__VA_ARGS__);	\
+		cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\
 	} while (0)
 
 #define cnss_pr_dbg(_fmt, ...) do {					\
-		pr_debug("cnss: " _fmt, ##__VA_ARGS__);			\
-		cnss_ipc_log_string("DBG: " _fmt, ##__VA_ARGS__);	\
+		printk("%scnss: " _fmt, KERN_DEBUG, ##__VA_ARGS__);	\
+		cnss_ipc_log_string("%scnss: " _fmt, "", ##__VA_ARGS__);\
 	} while (0)
 
 #ifdef CONFIG_CNSS2_DEBUG
diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c
index 76ad51c..b2c0d09 100644
--- a/drivers/net/wireless/cnss2/main.c
+++ b/drivers/net/wireless/cnss2/main.c
@@ -248,8 +248,6 @@
 		     const char *host_version)
 {
 	struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
-	struct wlfw_wlan_cfg_req_msg_v01 req;
-	u32 i;
 	int ret = 0;
 
 	if (plat_priv->device_id == QCA6174_DEVICE_ID)
@@ -269,48 +267,7 @@
 	if (mode == CNSS_WALTEST || mode == CNSS_CCPM)
 		goto skip_cfg;
 
-	memset(&req, 0, sizeof(req));
-
-	req.host_version_valid = 1;
-	strlcpy(req.host_version, host_version,
-		QMI_WLFW_MAX_STR_LEN_V01 + 1);
-
-	req.tgt_cfg_valid = 1;
-	if (config->num_ce_tgt_cfg > QMI_WLFW_MAX_NUM_CE_V01)
-		req.tgt_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
-	else
-		req.tgt_cfg_len = config->num_ce_tgt_cfg;
-	for (i = 0; i < req.tgt_cfg_len; i++) {
-		req.tgt_cfg[i].pipe_num = config->ce_tgt_cfg[i].pipe_num;
-		req.tgt_cfg[i].pipe_dir = config->ce_tgt_cfg[i].pipe_dir;
-		req.tgt_cfg[i].nentries = config->ce_tgt_cfg[i].nentries;
-		req.tgt_cfg[i].nbytes_max = config->ce_tgt_cfg[i].nbytes_max;
-		req.tgt_cfg[i].flags = config->ce_tgt_cfg[i].flags;
-	}
-
-	req.svc_cfg_valid = 1;
-	if (config->num_ce_svc_pipe_cfg > QMI_WLFW_MAX_NUM_SVC_V01)
-		req.svc_cfg_len = QMI_WLFW_MAX_NUM_SVC_V01;
-	else
-		req.svc_cfg_len = config->num_ce_svc_pipe_cfg;
-	for (i = 0; i < req.svc_cfg_len; i++) {
-		req.svc_cfg[i].service_id = config->ce_svc_cfg[i].service_id;
-		req.svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir;
-		req.svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num;
-	}
-
-	req.shadow_reg_v2_valid = 1;
-	if (config->num_shadow_reg_v2_cfg >
-	    QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01)
-		req.shadow_reg_v2_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01;
-	else
-		req.shadow_reg_v2_len = config->num_shadow_reg_v2_cfg;
-
-	memcpy(req.shadow_reg_v2, config->shadow_reg_v2_cfg,
-	       sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01)
-	       * req.shadow_reg_v2_len);
-
-	ret = cnss_wlfw_wlan_cfg_send_sync(plat_priv, &req);
+	ret = cnss_wlfw_wlan_cfg_send_sync(plat_priv, config, host_version);
 	if (ret)
 		goto out;
 
@@ -331,7 +288,7 @@
 	if (qmi_bypass)
 		return 0;
 
-	return cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_OFF_V01);
+	return cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_OFF);
 }
 EXPORT_SYMBOL(cnss_wlan_disable);
 
@@ -350,13 +307,6 @@
 	if (plat_priv->device_id == QCA6174_DEVICE_ID)
 		return 0;
 
-	if (!output || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) {
-		cnss_pr_err("Invalid parameters for athdiag read: output %p, data_len %u\n",
-			    output, data_len);
-		ret = -EINVAL;
-		goto out;
-	}
-
 	if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
 		cnss_pr_err("Invalid state for athdiag read: 0x%lx\n",
 			    plat_priv->driver_state);
@@ -386,13 +336,6 @@
 	if (plat_priv->device_id == QCA6174_DEVICE_ID)
 		return 0;
 
-	if (!input || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) {
-		cnss_pr_err("Invalid parameters for athdiag write: input %p, data_len %u\n",
-			    input, data_len);
-		ret = -EINVAL;
-		goto out;
-	}
-
 	if (!test_bit(CNSS_FW_READY, &plat_priv->driver_state)) {
 		cnss_pr_err("Invalid state for athdiag write: 0x%lx\n",
 			    plat_priv->driver_state);
@@ -491,10 +434,10 @@
 
 	if (enable_waltest) {
 		ret = cnss_wlfw_wlan_mode_send_sync(plat_priv,
-						    QMI_WLFW_WALTEST_V01);
+						    CNSS_WALTEST);
 	} else if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state)) {
 		ret = cnss_wlfw_wlan_mode_send_sync(plat_priv,
-						    QMI_WLFW_CALIBRATION_V01);
+						    CNSS_CALIBRATION);
 	} else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
 		   test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
 		ret = cnss_bus_call_driver_probe(plat_priv);
@@ -625,6 +568,12 @@
 	return ret;
 }
 
+unsigned int cnss_get_boot_timeout(struct device *dev)
+{
+	return cnss_get_qmi_timeout();
+}
+EXPORT_SYMBOL(cnss_get_boot_timeout);
+
 int cnss_power_up(struct device *dev)
 {
 	int ret = 0;
@@ -647,7 +596,7 @@
 	if (plat_priv->device_id == QCA6174_DEVICE_ID)
 		goto out;
 
-	timeout = cnss_get_qmi_timeout();
+	timeout = cnss_get_boot_timeout(dev);
 
 	reinit_completion(&plat_priv->power_up_complete);
 	ret = wait_for_completion_timeout(&plat_priv->power_up_complete,
@@ -1101,7 +1050,7 @@
 static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv)
 {
 	plat_priv->cal_done = true;
-	cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_OFF_V01);
+	cnss_wlfw_wlan_mode_send_sync(plat_priv, CNSS_OFF);
 	cnss_bus_dev_shutdown(plat_priv);
 	clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
 
@@ -1435,6 +1384,8 @@
 		break;
 	case QCA6290_EMULATION_DEVICE_ID:
 	case QCA6290_DEVICE_ID:
+	case QCA6390_EMULATION_DEVICE_ID:
+	case QCA6390_DEVICE_ID:
 		ret = cnss_register_ramdump_v2(plat_priv);
 		break;
 	default:
@@ -1453,6 +1404,8 @@
 		break;
 	case QCA6290_EMULATION_DEVICE_ID:
 	case QCA6290_DEVICE_ID:
+	case QCA6390_EMULATION_DEVICE_ID:
+	case QCA6390_DEVICE_ID:
 		cnss_unregister_ramdump_v2(plat_priv);
 		break;
 	default:
@@ -1523,6 +1476,8 @@
 	switch (plat_priv->device_id) {
 	case QCA6290_EMULATION_DEVICE_ID:
 	case QCA6290_DEVICE_ID:
+	case QCA6390_EMULATION_DEVICE_ID:
+	case QCA6390_DEVICE_ID:
 		break;
 	default:
 		cnss_pr_err("Not supported for device ID 0x%lx\n",
@@ -1585,6 +1540,7 @@
 static const struct platform_device_id cnss_platform_id_table[] = {
 	{ .name = "qca6174", .driver_data = QCA6174_DEVICE_ID, },
 	{ .name = "qca6290", .driver_data = QCA6290_DEVICE_ID, },
+	{ .name = "qca6390", .driver_data = QCA6390_DEVICE_ID, },
 };
 
 static const struct of_device_id cnss_of_match_table[] = {
@@ -1594,6 +1550,9 @@
 	{
 		.compatible = "qcom,cnss-qca6290",
 		.data = (void *)&cnss_platform_id_table[1]},
+	{
+		.compatible = "qcom,cnss-qca6390",
+		.data = (void *)&cnss_platform_id_table[2]},
 	{ },
 };
 MODULE_DEVICE_TABLE(of, cnss_of_match_table);
diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h
index 509974a0..a2f346a 100644
--- a/drivers/net/wireless/cnss2/main.h
+++ b/drivers/net/wireless/cnss2/main.h
@@ -24,6 +24,8 @@
 #include "qmi.h"
 
 #define MAX_NO_OF_MAC_ADDR		4
+#define QMI_WLFW_MAX_TIMESTAMP_LEN	32
+#define QMI_WLFW_MAX_NUM_MEM_SEG	32
 
 #define CNSS_EVENT_SYNC   BIT(0)
 #define CNSS_EVENT_UNINTERRUPTIBLE BIT(1)
@@ -110,6 +112,33 @@
 	u32 type;
 };
 
+struct wlfw_rf_chip_info {
+	u32 chip_id;
+	u32 chip_family;
+};
+
+struct wlfw_rf_board_info {
+	u32 board_id;
+};
+
+struct wlfw_soc_info {
+	u32 soc_id;
+};
+
+struct wlfw_fw_version_info {
+	u32 fw_version;
+	char fw_build_timestamp[QMI_WLFW_MAX_TIMESTAMP_LEN + 1];
+};
+
+enum cnss_mem_type {
+	CNSS_MEM_TYPE_MSA,
+	CNSS_MEM_TYPE_DDR,
+	CNSS_MEM_BDF,
+	CNSS_MEM_M3,
+	CNSS_MEM_CAL_V01,
+	CNSS_MEM_DPD_V01,
+};
+
 enum cnss_fw_dump_type {
 	CNSS_FW_IMAGE,
 	CNSS_FW_RDDM,
@@ -202,12 +231,12 @@
 	struct qmi_handle *qmi_wlfw_clnt;
 	struct work_struct qmi_recv_msg_work;
 	struct notifier_block qmi_wlfw_clnt_nb;
-	struct wlfw_rf_chip_info_s_v01 chip_info;
-	struct wlfw_rf_board_info_s_v01 board_info;
-	struct wlfw_soc_info_s_v01 soc_info;
-	struct wlfw_fw_version_info_s_v01 fw_version_info;
+	struct wlfw_rf_chip_info chip_info;
+	struct wlfw_rf_board_info board_info;
+	struct wlfw_soc_info soc_info;
+	struct wlfw_fw_version_info fw_version_info;
 	u32 fw_mem_seg_len;
-	struct cnss_fw_mem fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG_V01];
+	struct cnss_fw_mem fw_mem[QMI_WLFW_MAX_NUM_MEM_SEG];
 	struct cnss_fw_mem m3_mem;
 	struct cnss_pin_connect_result pin_result;
 	struct dentry *root_dentry;
@@ -220,6 +249,7 @@
 	u32 diag_reg_read_len;
 	u8 *diag_reg_read_buf;
 	bool cal_done;
+	char firmware_name[13];
 };
 
 struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev);
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index e1704fb..161e68e 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -44,6 +44,7 @@
 
 #define MAX_M3_FILE_NAME_LENGTH		13
 #define DEFAULT_M3_FILE_NAME		"m3.bin"
+#define DEFAULT_FW_FILE_NAME		"amss.bin"
 
 #define WAKE_MSI_NAME			"WAKE"
 
@@ -432,7 +433,7 @@
 		goto power_off;
 	}
 
-	timeout = cnss_get_qmi_timeout();
+	timeout = cnss_get_boot_timeout(&pci_priv->pci_dev->dev);
 
 	ret = cnss_pci_start_mhi(pci_priv);
 	if (ret) {
@@ -569,6 +570,8 @@
 		break;
 	case QCA6290_EMULATION_DEVICE_ID:
 	case QCA6290_DEVICE_ID:
+	case QCA6390_EMULATION_DEVICE_ID:
+	case QCA6390_DEVICE_ID:
 		ret = cnss_qca6290_powerup(pci_priv);
 		break;
 	default:
@@ -595,6 +598,8 @@
 		break;
 	case QCA6290_EMULATION_DEVICE_ID:
 	case QCA6290_DEVICE_ID:
+	case QCA6390_EMULATION_DEVICE_ID:
+	case QCA6390_DEVICE_ID:
 		ret = cnss_qca6290_shutdown(pci_priv);
 		break;
 	default:
@@ -621,6 +626,8 @@
 		break;
 	case QCA6290_EMULATION_DEVICE_ID:
 	case QCA6290_DEVICE_ID:
+	case QCA6390_EMULATION_DEVICE_ID:
+	case QCA6390_DEVICE_ID:
 		cnss_qca6290_crash_shutdown(pci_priv);
 		break;
 	default:
@@ -647,6 +654,8 @@
 		break;
 	case QCA6290_EMULATION_DEVICE_ID:
 	case QCA6290_DEVICE_ID:
+	case QCA6390_EMULATION_DEVICE_ID:
+	case QCA6390_DEVICE_ID:
 		ret = cnss_qca6290_ramdump(pci_priv);
 		break;
 	default:
@@ -1705,7 +1714,7 @@
 	cnss_pr_dbg("Collect remote heap dump segment\n");
 
 	for (i = 0; i < plat_priv->fw_mem_seg_len; i++) {
-		if (fw_mem[i].type == QMI_WLFW_MEM_TYPE_DDR_V01) {
+		if (fw_mem[i].type == CNSS_MEM_TYPE_DDR) {
 			dump_seg->address = fw_mem[i].pa;
 			dump_seg->v_address = fw_mem[i].va;
 			dump_seg->size = fw_mem[i].size;
@@ -1838,6 +1847,8 @@
 	mhi_ctrl->bus = pci_dev->bus->number;
 	mhi_ctrl->slot = PCI_SLOT(pci_dev->devfn);
 
+	mhi_ctrl->fw_image = plat_priv->firmware_name;
+
 	mhi_ctrl->regs = pci_priv->bar;
 	cnss_pr_dbg("BAR starts at %pa\n",
 		    &pci_resource_start(pci_priv->pci_dev, PCI_BAR_NUM));
@@ -1863,6 +1874,9 @@
 	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->sbl_size = SZ_512K;
+	mhi_ctrl->seg_len = SZ_512K;
+	mhi_ctrl->fbc_download = true;
 
 	mhi_ctrl->log_buf = ipc_log_context_create(CNSS_IPC_LOG_PAGES,
 						   "cnss-mhi", 0);
@@ -1916,7 +1930,10 @@
 			return 0;
 		break;
 	case CNSS_MHI_TRIGGER_RDDM:
-		return 0;
+		if (test_bit(CNSS_MHI_POWER_ON, &pci_priv->mhi_state) &&
+		    !test_bit(CNSS_MHI_TRIGGER_RDDM, &pci_priv->mhi_state))
+			return 0;
+		break;
 	default:
 		cnss_pr_err("Unhandled MHI state: %s(%d)\n",
 			    cnss_mhi_state_to_str(mhi_state), mhi_state);
@@ -2109,6 +2126,8 @@
 	cnss_set_pci_priv(pci_dev, pci_priv);
 	plat_priv->device_id = pci_dev->device;
 	plat_priv->bus_priv = pci_priv;
+	snprintf(plat_priv->firmware_name, sizeof(plat_priv->firmware_name),
+		 DEFAULT_FW_FILE_NAME);
 
 	ret = cnss_register_subsys(plat_priv);
 	if (ret)
@@ -2163,6 +2182,8 @@
 		break;
 	case QCA6290_EMULATION_DEVICE_ID:
 	case QCA6290_DEVICE_ID:
+	case QCA6390_EMULATION_DEVICE_ID:
+	case QCA6390_DEVICE_ID:
 		ret = cnss_pci_enable_msi(pci_priv);
 		if (ret)
 			goto disable_bus;
@@ -2215,6 +2236,8 @@
 	switch (pci_dev->device) {
 	case QCA6290_EMULATION_DEVICE_ID:
 	case QCA6290_DEVICE_ID:
+	case QCA6390_EMULATION_DEVICE_ID:
+	case QCA6390_DEVICE_ID:
 		cnss_pci_unregister_mhi(pci_priv);
 		cnss_pci_disable_msi(pci_priv);
 		break;
@@ -2238,6 +2261,9 @@
 	{ QCA6290_EMULATION_VENDOR_ID, QCA6290_EMULATION_DEVICE_ID,
 	  PCI_ANY_ID, PCI_ANY_ID },
 	{ QCA6290_VENDOR_ID, QCA6290_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
+	{ QCA6390_VENDOR_ID, QCA6390_EMULATION_DEVICE_ID, PCI_ANY_ID,
+	  PCI_ANY_ID },
+	{ QCA6390_VENDOR_ID, QCA6390_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
 	{ 0 }
 };
 MODULE_DEVICE_TABLE(pci, cnss_pci_id_table);
diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c
index 222a131..2c375bb 100644
--- a/drivers/net/wireless/cnss2/qmi.c
+++ b/drivers/net/wireless/cnss2/qmi.c
@@ -23,8 +23,17 @@
 #define WLFW_SERVICE_INS_ID_V01		1
 #define WLFW_CLIENT_ID			0x4b4e454c
 #define MAX_BDF_FILE_NAME		11
-#define DEFAULT_BDF_FILE_NAME		"bdwlan.elf"
-#define BDF_FILE_NAME_PREFIX		"bdwlan.e"
+#define ELF_BDF_FILE_NAME		"bdwlan.elf"
+#define ELF_BDF_FILE_NAME_PREFIX	"bdwlan.e"
+#define BIN_BDF_FILE_NAME		"bdwlan.bin"
+#define BIN_BDF_FILE_NAME_PREFIX	"bdwlan.b"
+#define DUMMY_BDF_FILE_NAME		"bdwlan.dmy"
+
+enum cnss_bdf_type {
+	CNSS_BDF_BIN,
+	CNSS_BDF_ELF,
+	CNSS_BDF_DUMMY = 255,
+};
 
 #ifdef CONFIG_CNSS2_DEBUG
 static unsigned int qmi_timeout = 10000;
@@ -40,35 +49,30 @@
 module_param(daemon_support, bool, 0600);
 MODULE_PARM_DESC(daemon_support, "User space has cnss-daemon support or not");
 
-static bool bdf_bypass;
+static unsigned int bdf_type = CNSS_BDF_ELF;
 #ifdef CONFIG_CNSS2_DEBUG
-module_param(bdf_bypass, bool, 0600);
-MODULE_PARM_DESC(bdf_bypass, "If BDF is not found, send dummy BDF to FW");
+module_param(bdf_type, uint, 0600);
+MODULE_PARM_DESC(bdf_type, "Type of board data file to be downloaded");
 #endif
 
-enum cnss_bdf_type {
-	CNSS_BDF_BIN,
-	CNSS_BDF_ELF,
-};
-
-static char *cnss_qmi_mode_to_str(enum wlfw_driver_mode_enum_v01 mode)
+static char *cnss_qmi_mode_to_str(enum cnss_driver_mode mode)
 {
 	switch (mode) {
-	case QMI_WLFW_MISSION_V01:
+	case CNSS_MISSION:
 		return "MISSION";
-	case QMI_WLFW_FTM_V01:
+	case CNSS_FTM:
 		return "FTM";
-	case QMI_WLFW_EPPING_V01:
+	case CNSS_EPPING:
 		return "EPPING";
-	case QMI_WLFW_WALTEST_V01:
+	case CNSS_WALTEST:
 		return "WALTEST";
-	case QMI_WLFW_OFF_V01:
+	case CNSS_OFF:
 		return "OFF";
-	case QMI_WLFW_CCPM_V01:
+	case CNSS_CCPM:
 		return "CCPM";
-	case QMI_WLFW_QVIT_V01:
+	case CNSS_QVIT:
 		return "QVIT";
-	case QMI_WLFW_CALIBRATION_V01:
+	case CNSS_CALIBRATION:
 		return "CALIBRATION";
 	default:
 		return "UNKNOWN";
@@ -464,16 +468,23 @@
 		goto out;
 	}
 
-	if (resp.chip_info_valid)
-		plat_priv->chip_info = resp.chip_info;
+	if (resp.chip_info_valid) {
+		plat_priv->chip_info.chip_id = resp.chip_info.chip_id;
+		plat_priv->chip_info.chip_family = resp.chip_info.chip_family;
+	}
 	if (resp.board_info_valid)
-		plat_priv->board_info = resp.board_info;
+		plat_priv->board_info.board_id = resp.board_info.board_id;
 	else
 		plat_priv->board_info.board_id = 0xFF;
 	if (resp.soc_info_valid)
-		plat_priv->soc_info = resp.soc_info;
-	if (resp.fw_version_info_valid)
-		plat_priv->fw_version_info = resp.fw_version_info;
+		plat_priv->soc_info.soc_id = resp.soc_info.soc_id;
+	if (resp.fw_version_info_valid) {
+		plat_priv->fw_version_info.fw_version =
+			resp.fw_version_info.fw_version;
+		strlcpy(plat_priv->fw_version_info.fw_build_timestamp,
+			resp.fw_version_info.fw_build_timestamp,
+			QMI_WLFW_MAX_TIMESTAMP_LEN + 1);
+	}
 
 	cnss_pr_dbg("Target capability: chip_id: 0x%x, chip_family: 0x%x, board_id: 0x%x, soc_id: 0x%x, fw_version: 0x%x, fw_build_timestamp: %s",
 		    plat_priv->chip_info.chip_id,
@@ -508,24 +519,39 @@
 		goto out;
 	}
 
-	if (plat_priv->board_info.board_id == 0xFF)
-		snprintf(filename, sizeof(filename), DEFAULT_BDF_FILE_NAME);
-	else
-		snprintf(filename, sizeof(filename),
-			 BDF_FILE_NAME_PREFIX "%02x",
-			 plat_priv->board_info.board_id);
+	switch (bdf_type) {
+	case CNSS_BDF_ELF:
+		if (plat_priv->board_info.board_id == 0xFF)
+			snprintf(filename, sizeof(filename), ELF_BDF_FILE_NAME);
+		else
+			snprintf(filename, sizeof(filename),
+				 ELF_BDF_FILE_NAME_PREFIX "%02x",
+				 plat_priv->board_info.board_id);
+		break;
+	case CNSS_BDF_BIN:
+		if (plat_priv->board_info.board_id == 0xFF)
+			snprintf(filename, sizeof(filename), BIN_BDF_FILE_NAME);
+		else
+			snprintf(filename, sizeof(filename),
+				 BIN_BDF_FILE_NAME_PREFIX "%02x",
+				 plat_priv->board_info.board_id);
+		break;
+	case CNSS_BDF_DUMMY:
+		cnss_pr_dbg("CNSS_BDF_DUMMY is set, sending dummy BDF\n");
+		snprintf(filename, sizeof(filename), DUMMY_BDF_FILE_NAME);
+		temp = DUMMY_BDF_FILE_NAME;
+		remaining = MAX_BDF_FILE_NAME;
+		goto bypass_bdf;
+	default:
+		cnss_pr_err("Invalid BDF type: %d\n", bdf_type);
+		ret = -EINVAL;
+		goto err_req_fw;
+	}
 
 	ret = request_firmware(&fw_entry, filename, &plat_priv->plat_dev->dev);
 	if (ret) {
 		cnss_pr_err("Failed to load BDF: %s\n", filename);
-		if (bdf_bypass) {
-			cnss_pr_info("bdf_bypass is enabled, sending dummy BDF\n");
-			temp = filename;
-			remaining = MAX_BDF_FILE_NAME;
-			goto bypass_bdf;
-		} else {
-			goto err_req_fw;
-		}
+		goto err_req_fw;
 	}
 
 	temp = fw_entry->data;
@@ -554,7 +580,7 @@
 		req->data_valid = 1;
 		req->end_valid = 1;
 		req->bdf_type_valid = 1;
-		req->bdf_type = CNSS_BDF_ELF;
+		req->bdf_type = bdf_type;
 
 		if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) {
 			req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01;
@@ -587,7 +613,7 @@
 	}
 
 err_send:
-	if (!bdf_bypass)
+	if (bdf_type != CNSS_BDF_DUMMY)
 		release_firmware(fw_entry);
 err_req_fw:
 	kfree(req);
@@ -655,7 +681,7 @@
 }
 
 int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
-				  enum wlfw_driver_mode_enum_v01 mode)
+				  enum cnss_driver_mode mode)
 {
 	struct wlfw_wlan_mode_req_msg_v01 req;
 	struct wlfw_wlan_mode_resp_msg_v01 resp;
@@ -668,7 +694,7 @@
 	cnss_pr_dbg("Sending mode message, mode: %s(%d), state: 0x%lx\n",
 		    cnss_qmi_mode_to_str(mode), mode, plat_priv->driver_state);
 
-	if (mode == QMI_WLFW_OFF_V01 &&
+	if (mode == CNSS_OFF &&
 	    test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
 		cnss_pr_dbg("Recovery is in progress, ignore mode off request.\n");
 		return 0;
@@ -693,7 +719,7 @@
 				sizeof(req), &resp_desc, &resp, sizeof(resp),
 				QMI_WLFW_TIMEOUT_MS);
 	if (ret < 0) {
-		if (mode == QMI_WLFW_OFF_V01 && ret == -ENETRESET) {
+		if (mode == CNSS_OFF && ret == -ENETRESET) {
 			cnss_pr_dbg("WLFW service is disconnected while sending mode off request.\n");
 			return 0;
 		}
@@ -712,17 +738,19 @@
 
 	return 0;
 out:
-	if (mode != QMI_WLFW_OFF_V01)
+	if (mode != CNSS_OFF)
 		CNSS_ASSERT(0);
 	return ret;
 }
 
 int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
-				 struct wlfw_wlan_cfg_req_msg_v01 *data)
+				 struct cnss_wlan_enable_cfg *config,
+				 const char *host_version)
 {
 	struct wlfw_wlan_cfg_req_msg_v01 req;
 	struct wlfw_wlan_cfg_resp_msg_v01 resp;
 	struct msg_desc req_desc, resp_desc;
+	u32 i;
 	int ret = 0;
 
 	cnss_pr_dbg("Sending WLAN config message, state: 0x%lx\n",
@@ -734,7 +762,44 @@
 	memset(&req, 0, sizeof(req));
 	memset(&resp, 0, sizeof(resp));
 
-	memcpy(&req, data, sizeof(req));
+	req.host_version_valid = 1;
+	strlcpy(req.host_version, host_version,
+		QMI_WLFW_MAX_STR_LEN_V01 + 1);
+
+	req.tgt_cfg_valid = 1;
+	if (config->num_ce_tgt_cfg > QMI_WLFW_MAX_NUM_CE_V01)
+		req.tgt_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
+	else
+		req.tgt_cfg_len = config->num_ce_tgt_cfg;
+	for (i = 0; i < req.tgt_cfg_len; i++) {
+		req.tgt_cfg[i].pipe_num = config->ce_tgt_cfg[i].pipe_num;
+		req.tgt_cfg[i].pipe_dir = config->ce_tgt_cfg[i].pipe_dir;
+		req.tgt_cfg[i].nentries = config->ce_tgt_cfg[i].nentries;
+		req.tgt_cfg[i].nbytes_max = config->ce_tgt_cfg[i].nbytes_max;
+		req.tgt_cfg[i].flags = config->ce_tgt_cfg[i].flags;
+	}
+
+	req.svc_cfg_valid = 1;
+	if (config->num_ce_svc_pipe_cfg > QMI_WLFW_MAX_NUM_SVC_V01)
+		req.svc_cfg_len = QMI_WLFW_MAX_NUM_SVC_V01;
+	else
+		req.svc_cfg_len = config->num_ce_svc_pipe_cfg;
+	for (i = 0; i < req.svc_cfg_len; i++) {
+		req.svc_cfg[i].service_id = config->ce_svc_cfg[i].service_id;
+		req.svc_cfg[i].pipe_dir = config->ce_svc_cfg[i].pipe_dir;
+		req.svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num;
+	}
+
+	req.shadow_reg_v2_valid = 1;
+	if (config->num_shadow_reg_v2_cfg >
+	    QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01)
+		req.shadow_reg_v2_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01;
+	else
+		req.shadow_reg_v2_len = config->num_shadow_reg_v2_cfg;
+
+	memcpy(req.shadow_reg_v2, config->shadow_reg_v2_cfg,
+	       sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01)
+	       * req.shadow_reg_v2_len);
 
 	req_desc.max_msg_len = WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN;
 	req_desc.msg_id = QMI_WLFW_WLAN_CFG_REQ_V01;
@@ -781,6 +846,12 @@
 	if (!plat_priv->qmi_wlfw_clnt)
 		return -EINVAL;
 
+	if (!data || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) {
+		cnss_pr_err("Invalid parameters for athdiag read: data %p, data_len %u\n",
+			    data, data_len);
+		return -EINVAL;
+	}
+
 	cnss_pr_dbg("athdiag read: state 0x%lx, offset %x, mem_type %x, data_len %u\n",
 		    plat_priv->driver_state, offset, mem_type, data_len);
 
@@ -847,6 +918,12 @@
 	if (!plat_priv->qmi_wlfw_clnt)
 		return -EINVAL;
 
+	if (!data || data_len == 0 || data_len > QMI_WLFW_MAX_DATA_SIZE_V01) {
+		cnss_pr_err("Invalid parameters for athdiag write: data %p, data_len %u\n",
+			    data, data_len);
+		return -EINVAL;
+	}
+
 	cnss_pr_dbg("athdiag write: state 0x%lx, offset %x, mem_type %x, data_len %u, data %p\n",
 		    plat_priv->driver_state, offset, mem_type, data_len, data);
 
@@ -990,7 +1067,6 @@
 
 	return QMI_WLFW_TIMEOUT_MS;
 }
-EXPORT_SYMBOL(cnss_get_qmi_timeout);
 
 int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv)
 {
diff --git a/drivers/net/wireless/cnss2/qmi.h b/drivers/net/wireless/cnss2/qmi.h
index 70d8d40..a48263e 100644
--- a/drivers/net/wireless/cnss2/qmi.h
+++ b/drivers/net/wireless/cnss2/qmi.h
@@ -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
@@ -13,12 +13,14 @@
 #ifndef _CNSS_QMI_H
 #define _CNSS_QMI_H
 
-#include "wlan_firmware_service_v01.h"
-
 struct cnss_plat_data;
 
+#ifdef CONFIG_CNSS2_QMI
+#include "wlan_firmware_service_v01.h"
+
 int cnss_qmi_init(struct cnss_plat_data *plat_priv);
 void cnss_qmi_deinit(struct cnss_plat_data *plat_priv);
+unsigned int cnss_get_qmi_timeout(void);
 int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv);
@@ -26,9 +28,10 @@
 int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv);
 int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
-				  enum wlfw_driver_mode_enum_v01 mode);
+				  enum cnss_driver_mode mode);
 int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
-				 struct wlfw_wlan_cfg_req_msg_v01 *data);
+				 struct cnss_wlan_enable_cfg *config,
+				 const char *host_version);
 int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv,
 				     u32 offset, u32 mem_type,
 				     u32 data_len, u8 *data);
@@ -37,5 +40,91 @@
 				      u32 data_len, u8 *data);
 int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv,
 			    u8 fw_log_mode);
+#else
+#define QMI_WLFW_TIMEOUT_MS		10000
+
+static inline int cnss_qmi_init(struct cnss_plat_data *plat_priv)
+{
+	return 0;
+}
+
+static inline void cnss_qmi_deinit(struct cnss_plat_data *plat_priv)
+{
+}
+
+static inline unsigned int cnss_get_qmi_timeout(void)
+{
+	return QMI_WLFW_TIMEOUT_MS;
+}
+
+static inline int cnss_wlfw_server_arrive(struct cnss_plat_data *plat_priv)
+{
+	return 0;
+}
+
+static inline int cnss_wlfw_server_exit(struct cnss_plat_data *plat_priv)
+{
+	return 0;
+}
+
+static inline
+int cnss_wlfw_respond_mem_send_sync(struct cnss_plat_data *plat_priv)
+{
+	return 0;
+}
+
+static inline int cnss_wlfw_tgt_cap_send_sync(struct cnss_plat_data *plat_priv)
+{
+	return 0;
+}
+
+static inline int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv)
+{
+	return 0;
+}
+
+static inline int cnss_wlfw_m3_dnld_send_sync(struct cnss_plat_data *plat_priv)
+{
+	return 0;
+}
+
+static inline
+int cnss_wlfw_wlan_mode_send_sync(struct cnss_plat_data *plat_priv,
+				  enum cnss_driver_mode mode)
+{
+	return 0;
+}
+
+static inline
+int cnss_wlfw_wlan_cfg_send_sync(struct cnss_plat_data *plat_priv,
+				 struct cnss_wlan_enable_cfg *config,
+				 const char *host_version)
+{
+	return 0;
+}
+
+static inline
+int cnss_wlfw_athdiag_read_send_sync(struct cnss_plat_data *plat_priv,
+				     u32 offset, u32 mem_type,
+				     u32 data_len, u8 *data)
+{
+	return 0;
+}
+
+static inline
+int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv,
+				      u32 offset, u32 mem_type,
+				      u32 data_len, u8 *data)
+{
+	return 0;
+}
+
+static inline
+int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv,
+			    u8 fw_log_mode)
+{
+	return 0;
+}
+#endif /* CONFIG_CNSS2_QMI */
 
 #endif /* _CNSS_QMI_H */
diff --git a/drivers/net/wireless/qca402x/Kconfig b/drivers/net/wireless/qca402x/Kconfig
new file mode 100644
index 0000000..bae2a49
--- /dev/null
+++ b/drivers/net/wireless/qca402x/Kconfig
@@ -0,0 +1,10 @@
+config QCA402X
+	tristate "Qualcomm QCA402X wireless support"
+	default n
+	---help---
+	Software for Qualcomm QCA402x including HIF and HTCA.
+
+	Say Y here if support for Qualcomm's QCA402x wireless SoC
+	via host-target communication protocol is required.
+	Say N to disable completely if support for that device is
+	not needed or if not sure.
diff --git a/drivers/net/wireless/qca402x/Makefile b/drivers/net/wireless/qca402x/Makefile
new file mode 100644
index 0000000..c052f73
--- /dev/null
+++ b/drivers/net/wireless/qca402x/Makefile
@@ -0,0 +1,9 @@
+obj-$(CONFIG_QCA402X) += htca_mbox/htca_mbox.o
+obj-$(CONFIG_QCA402X) += htca_mbox/htca_mbox_compl.o
+obj-$(CONFIG_QCA402X) += htca_mbox/htca_mbox_events.o
+obj-$(CONFIG_QCA402X) += htca_mbox/htca_mbox_intr.o
+obj-$(CONFIG_QCA402X) += htca_mbox/htca_mbox_recv.o
+obj-$(CONFIG_QCA402X) += htca_mbox/htca_mbox_send.o
+obj-$(CONFIG_QCA402X) += htca_mbox/htca_mbox_task.o
+obj-$(CONFIG_QCA402X) += htca_mbox/htca_mbox_utils.o
+obj-$(CONFIG_QCA402X) += hif_sdio/hif.o
diff --git a/drivers/net/wireless/qca402x/README.txt b/drivers/net/wireless/qca402x/README.txt
new file mode 100644
index 0000000..50873a8
--- /dev/null
+++ b/drivers/net/wireless/qca402x/README.txt
@@ -0,0 +1,52 @@
+This directory contains support to communicate beteween an APQ8053 Host
+and Qualcomm's QCA402x wireless SoC.
+
+QCA4020 SoC supports
+    802.11 (i.e. WiFi/WLAN)
+    802.15.4 (i.e. Zigbee, Thread)
+    BT LE
+
+Contents of this directory may eventually include:
+	cfg80211 support
+	SoftMAC wireless driver
+	Perhaps a mac80211 driver
+	Zigbee APIs
+	Thread APIs
+	BT APIs
+
+For now, all that is present are the bottommost layers of a communication stack:
+
+	HTCA - Host/Target Communications protocol
+		htca_mbox
+		    Quartz SDIO/SPI address space
+		    Quartz mailboxes and associated SDIO/SPI registers
+		    Quartz mbox credit-based flow control
+		htca_uart (TBD)
+
+	HIF - a shim layer which abstracts the underlying Master/Host-side
+		interconnect controller (e.g. SDIO controller) to provide
+		an interconnect-independent API for use by HTCA.
+		hif_sdio
+			Host Interface layer for SDIO Master controllers
+		hif_spi (TBD)
+			Host Interface layer for SPI Master controllers
+		hif_uart (TBD)
+			Host Interface layer for UART-based controllers
+
+	qrtzdev-a simple driver used for HTCA TESTING.
+
+Note: The initial implementation supports HTCA Protocol Version 1 over SDIO.
+It is based on previous HTCA implementations for Atheros SoCs, but uses a
+revised design which appropriately leverages kernel threads.
+
+This implementation is likely to evolve with increasing focus on performance,
+especially for use cases of current interest such as streaming video from
+Host over SDIO to WLAN; however this evolution may differ from the existing
+implementation of HTCA Protocol Version 2 used by earlier Atheros SoC's.
+
+However there are several issues with this code:
+  it is based on HTCA v2 protocol which adds complexity
+  it is based on a non-threaded design, originally for a non-threaded RTOS
+TBD: Ideally, these two implementations ought to be merged so that the resulting
+implementation is based on a proper threaded design and supports both HTCA
+protocol v1 and v2.
diff --git a/drivers/net/wireless/qca402x/hif_sdio/hif.c b/drivers/net/wireless/qca402x/hif_sdio/hif.c
new file mode 100644
index 0000000..56d3b95
--- /dev/null
+++ b/drivers/net/wireless/qca402x/hif_sdio/hif.c
@@ -0,0 +1,1230 @@
+/* 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 was originally distributed by Qualcomm Atheros, Inc.
+ * before Copyright ownership was assigned to the Linux Foundation.
+ */
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sd.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/sdio_ids.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "hif_internal.h"
+#include "hif.h"
+
+#if defined(DEBUG)
+#define hifdebug(fmt, a...)\
+	pr_err("hif %s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define hifdebug(args...)
+#endif
+
+#define MAX_HIF_DEVICES 2
+#define ENABLE_SDIO_TIMEOUT 100 /* ms */
+
+static unsigned int hif_mmcbuswidth;
+EXPORT_SYMBOL(hif_mmcbuswidth);
+module_param(hif_mmcbuswidth, uint, 0644);
+MODULE_PARM_DESC(hif_mmcbuswidth, "Set MMC driver Bus Width: 1-1Bit, 4-4Bit, 8-8Bit");
+
+static unsigned int hif_mmcclock;
+EXPORT_SYMBOL(hif_mmcclock);
+module_param(hif_mmcclock, uint, 0644);
+MODULE_PARM_DESC(hif_mmcclock, "Set MMC driver Clock value");
+
+static unsigned int hif_writecccr1;
+module_param(hif_writecccr1, uint, 0644);
+static unsigned int hif_writecccr1value;
+module_param(hif_writecccr1value, uint, 0644);
+
+static unsigned int hif_writecccr2;
+module_param(hif_writecccr2, uint, 0644);
+static unsigned int hif_writecccr2value;
+module_param(hif_writecccr2value, uint, 0644);
+
+static unsigned int hif_writecccr3;
+module_param(hif_writecccr3, uint, 0644);
+static unsigned int hif_writecccr3value;
+module_param(hif_writecccr3value, uint, 0644);
+
+static unsigned int hif_writecccr4;
+module_param(hif_writecccr4, uint, 0644);
+
+static unsigned int hif_writecccr4value;
+module_param(hif_writecccr4value, uint, 0644);
+
+static int hif_device_inserted(struct sdio_func *func,
+			       const struct sdio_device_id *id);
+static void hif_device_removed(struct sdio_func *func);
+static void *add_hif_device(struct sdio_func *func);
+static struct hif_device *get_hif_device(struct sdio_func *func);
+static void del_hif_device(struct hif_device *device);
+static int func0_CMD52_write_byte(struct mmc_card *card, unsigned int address,
+				  unsigned char byte);
+static int func0_CMD52_read_byte(struct mmc_card *card, unsigned int address,
+				 unsigned char *byte);
+static void hif_stop_hif_task(struct hif_device *device);
+static struct bus_request *hif_allocate_bus_request(void *device);
+static void hif_free_bus_request(struct hif_device *device,
+				 struct bus_request *busrequest);
+static void hif_add_to_req_list(struct hif_device *device,
+				struct bus_request *busrequest);
+
+static int hif_reset_sdio_on_unload;
+module_param(hif_reset_sdio_on_unload, int, 0644);
+
+static u32 hif_forcedriverstrength = 1; /* force driver strength to type D */
+
+static const struct sdio_device_id hif_sdio_id_table[] = {
+	{SDIO_DEVICE(SDIO_ANY_ID,
+	SDIO_ANY_ID)}, /* QCA402x IDs are hardwired to 0 */
+	{/* null */},
+};
+
+MODULE_DEVICE_TABLE(sdio, hif_sdio_id_table);
+
+static struct sdio_driver hif_sdio_driver = {
+	.name = "hif_sdio",
+	.id_table = hif_sdio_id_table,
+	.probe = hif_device_inserted,
+	.remove = hif_device_removed,
+};
+
+/* make sure we unregister only when registered. */
+/* TBD: synchronization needed.... */
+/* device->completion_task, registered, ... */
+static int registered;
+
+static struct cbs_from_os hif_callbacks;
+
+static struct hif_device *hif_devices[MAX_HIF_DEVICES];
+
+static int hif_disable_func(struct hif_device *device, struct sdio_func *func);
+static int hif_enable_func(struct hif_device *device, struct sdio_func *func);
+
+static int hif_sdio_register_driver(struct cbs_from_os *callbacks)
+{
+	/* store the callback handlers */
+	hif_callbacks = *callbacks; /* structure copy */
+
+	/* Register with bus driver core */
+	registered++;
+
+	return sdio_register_driver(&hif_sdio_driver);
+}
+
+static void hif_sdio_unregister_driver(void)
+{
+	sdio_unregister_driver(&hif_sdio_driver);
+	registered--;
+}
+
+int hif_init(struct cbs_from_os *callbacks)
+{
+	int status;
+
+	hifdebug("Enter\n");
+	if (!callbacks)
+		return HIF_ERROR;
+
+	hifdebug("calling hif_sdio_register_driver\n");
+	status = hif_sdio_register_driver(callbacks);
+	hifdebug("hif_sdio_register_driver returns %d\n", status);
+	if (status != 0)
+		return HIF_ERROR;
+
+	return HIF_OK;
+}
+
+static int __hif_read_write(struct hif_device *device, u32 address,
+			    u8 *buffer, u32 length,
+			    u32 request, void *context)
+{
+	u8 opcode;
+	int status = HIF_OK;
+	int ret = 0;
+	u8 temp[4];
+
+	if (!device || !device->func)
+		return HIF_ERROR;
+
+	if (!buffer)
+		return HIF_EINVAL;
+
+	if (length == 0)
+		return HIF_EINVAL;
+
+	do {
+		if (!(request & HIF_EXTENDED_IO)) {
+			status = HIF_EINVAL;
+			break;
+		}
+
+		if (request & HIF_BLOCK_BASIS) {
+			if (WARN_ON(length & (HIF_MBOX_BLOCK_SIZE - 1)))
+				return HIF_EINVAL;
+		} else if (request & HIF_BYTE_BASIS) {
+		} else {
+			status = HIF_EINVAL;
+			break;
+		}
+
+		if (request & HIF_FIXED_ADDRESS) {
+			opcode = CMD53_FIXED_ADDRESS;
+		} else if (request & HIF_INCREMENTAL_ADDRESS) {
+			opcode = CMD53_INCR_ADDRESS;
+		} else {
+			status = HIF_EINVAL;
+			break;
+		}
+
+		if (request & HIF_WRITE) {
+			if (opcode == CMD53_FIXED_ADDRESS) {
+				/* TBD: Why special handling? */
+				if (length == 1) {
+					memset(temp, *buffer, 4);
+					ret = sdio_writesb(device->func,
+							   address, temp, 4);
+				} else {
+					ret =
+					    sdio_writesb(device->func, address,
+							 buffer, length);
+				}
+			} else {
+				ret = sdio_memcpy_toio(device->func, address,
+						       buffer, length);
+			}
+		} else if (request & HIF_READ) {
+			if (opcode == CMD53_FIXED_ADDRESS) {
+				if (length ==
+				    1) { /* TBD: Why special handling? */
+					memset(temp, 0, 4);
+					ret = sdio_readsb(device->func, temp,
+							  address, 4);
+					buffer[0] = temp[0];
+				} else {
+					ret = sdio_readsb(device->func, buffer,
+							  address, length);
+				}
+			} else {
+				ret = sdio_memcpy_fromio(device->func, buffer,
+							 address, length);
+			}
+		} else {
+			status = HIF_EINVAL; /* Neither read nor write */
+			break;
+		}
+
+		if (ret) {
+			hifdebug("SDIO op returns %d\n", ret);
+			status = HIF_ERROR;
+		}
+	} while (false);
+
+	return status;
+}
+
+/* Add busrequest to tail of sdio_request request list */
+static void hif_add_to_req_list(struct hif_device *device,
+				struct bus_request *busrequest)
+{
+	unsigned long flags;
+
+	busrequest->next = NULL;
+
+	spin_lock_irqsave(&device->req_qlock, flags);
+	if (device->req_qhead)
+		device->req_qtail->next = (void *)busrequest;
+	else
+		device->req_qhead = busrequest;
+	device->req_qtail = busrequest;
+	spin_unlock_irqrestore(&device->req_qlock, flags);
+}
+
+int hif_sync_read(void *hif_device, u32 address, u8 *buffer,
+		  u32 length, u32 request, void *context)
+{
+	int status;
+	struct hif_device *device = (struct hif_device *)hif_device;
+
+	if (!device || !device->func)
+		return HIF_ERROR;
+
+	sdio_claim_host(device->func);
+	status = __hif_read_write(device, address, buffer, length,
+				  request & ~HIF_SYNCHRONOUS, NULL);
+	sdio_release_host(device->func);
+	return status;
+}
+
+/* Queue a read/write request and optionally wait for it to complete. */
+int hif_read_write(void *hif_device, u32 address, void *buffer,
+		   u32 length, u32 req_type, void *context)
+{
+	struct bus_request *busrequest;
+	int status;
+	struct hif_device *device = (struct hif_device *)hif_device;
+
+	if (!device || !device->func)
+		return HIF_ERROR;
+
+	if (!(req_type & HIF_ASYNCHRONOUS) && !(req_type & HIF_SYNCHRONOUS))
+		return HIF_EINVAL;
+
+	/* Serialize all requests through the reqlist and HIFtask */
+	busrequest = hif_allocate_bus_request(device);
+	if (!busrequest)
+		return HIF_ERROR;
+
+	/* TBD: caller may pass buffers ON THE STACK, especially 4 Byte buffers.
+	 * If this is a problem on some platforms/drivers, this is one
+	 * reasonable
+	 * place to handle it. If poentially using DMA
+	 * reject large buffers on stack
+	 * copy 4B buffers allow register writes (no DMA)
+	 */
+
+	busrequest->address = address;
+	busrequest->buffer = buffer;
+	busrequest->length = length;
+	busrequest->req_type = req_type;
+	busrequest->context = context;
+
+	hif_add_to_req_list(device, busrequest);
+	device->hif_task_work = 1;
+	wake_up(&device->hif_wait); /* Notify HIF task */
+
+	if (req_type & HIF_ASYNCHRONOUS)
+		return HIF_PENDING;
+
+	/* Synchronous request -- wait for completion. */
+	wait_for_completion(&busrequest->comp_req);
+	status = busrequest->status;
+	hif_free_bus_request(device, busrequest);
+	return status;
+}
+
+/* add_to_completion_list() - Queue a completed request
+ * @device:    context to the hif device.
+ * @comple: SDIO bus access request.
+ *
+ * This function adds an sdio bus access request to the
+ * completion list.
+ *
+ * Return: No return.
+ */
+static void add_to_completion_list(struct hif_device *device,
+				   struct bus_request *comple)
+{
+	unsigned long flags;
+
+	comple->next = NULL;
+
+	spin_lock_irqsave(&device->compl_qlock, flags);
+	if (device->compl_qhead)
+		device->compl_qtail->next = (void *)comple;
+	else
+		device->compl_qhead = comple;
+
+	device->compl_qtail = comple;
+	spin_unlock_irqrestore(&device->compl_qlock, flags);
+}
+
+/* process_completion_list() - Remove completed requests from
+ * the completion list, and invoke the corresponding callbacks.
+ *
+ * @device:  HIF device handle.
+ *
+ * Function to clean the completion list.
+ *
+ * Return: No
+ */
+static void process_completion_list(struct hif_device *device)
+{
+	unsigned long flags;
+	struct bus_request *next_comple;
+	struct bus_request *request;
+
+	/* Pull the entire chain of completions from the list */
+	spin_lock_irqsave(&device->compl_qlock, flags);
+	request = device->compl_qhead;
+	device->compl_qhead = NULL;
+	device->compl_qtail = NULL;
+	spin_unlock_irqrestore(&device->compl_qlock, flags);
+
+	while (request) {
+		int status;
+		void *context;
+
+		hifdebug("HIF top of loop\n");
+		next_comple = (struct bus_request *)request->next;
+
+		status = request->status;
+		context = request->context;
+		hif_free_bus_request(device, request);
+		device->cbs_from_hif.rw_completion_hdl(context, status);
+
+		request = next_comple;
+	}
+}
+
+/* completion_task() - Thread to process request completions
+ *
+ * @param:   context to the hif device.
+ *
+ * Completed asynchronous requests are added to a completion
+ * queue where they are processed by this task. This serves
+ * multiple purposes:
+ * -minimizes processing by the HIFTask, which allows
+ *	that task to keep SDIO busy
+ * -allows request processing to be parallelized on
+ *	multiprocessor systems
+ * -provides a suspendable context for use by the
+ *	caller's callback function, though this should
+ *	not be abused since it will cause requests to
+ *	sit on the completion queue (which makes us
+ *	more likely to exhaust free requests).
+ *
+ * Return: 0 thread exits
+ */
+static int completion_task(void *param)
+{
+	struct hif_device *device;
+
+	device = (struct hif_device *)param;
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	for (;;) {
+		hifdebug("HIF top of loop\n");
+		wait_event_interruptible(device->completion_wait,
+					 device->completion_work);
+		if (!device->completion_work)
+			break;
+
+		if (device->completion_shutdown)
+			break;
+
+		device->completion_work = 0;
+		process_completion_list(device);
+	}
+
+	/* Process any remaining completions.
+	 * This task should not be shut down
+	 * until after all requests are stopped.
+	 */
+	process_completion_list(device);
+
+	complete_and_exit(&device->completion_exit, 0);
+	return 0;
+}
+
+/* hif_request_complete() - Completion processing after a request
+ * is processed.
+ *
+ * @device:    device handle.
+ * @request:   SIDO bus access request.
+ *
+ * All completed requests are queued onto a completion list
+ * which is processed by complete_task.
+ *
+ * Return: None.
+ */
+static inline void hif_request_complete(struct hif_device *device,
+					struct bus_request *request)
+{
+	add_to_completion_list(device, request);
+	device->completion_work = 1;
+	wake_up(&device->completion_wait);
+}
+
+/* hif_stop_completion_thread() - Destroy the completion task
+ * @device: device handle.
+ *
+ * This function will destroy the completion thread.
+ *
+ * Return: None.
+ */
+static inline void hif_stop_completion_thread(struct hif_device *device)
+{
+	if (device->completion_task) {
+		init_completion(&device->completion_exit);
+		device->completion_shutdown = 1;
+
+		device->completion_work = 1;
+		wake_up(&device->completion_wait);
+		wait_for_completion(&device->completion_exit);
+		device->completion_task = NULL;
+	}
+}
+
+/* This task tries to keep the SDIO bus as busy as it
+ * can. It pulls both requests off the request queue and
+ * it uses the underlying sdio API to make them happen.
+ *
+ * Requests may be one of
+ * synchronous (a thread is suspended until it completes)
+ * asynchronous (a completion callback will be invoked)
+ * and one of
+ * reads (from Target SDIO space into Host RAM)
+ * writes (from Host RAM into Target SDIO space)
+ * and it is to one of
+ * Target's mailbox space
+ * Target's register space
+ * and lots of other choices.
+ */
+static int hif_task(void *param)
+{
+	struct hif_device *device;
+	struct bus_request *request;
+	int status;
+	unsigned long flags;
+
+	set_user_nice(current, -3);
+	device = (struct hif_device *)param;
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	for (;;) {
+		hifdebug("top of loop\n");
+		/* wait for work */
+		wait_event_interruptible(device->hif_wait,
+					 device->hif_task_work);
+		if (!device->hif_task_work)
+			/* interrupted, exit */
+			break;
+
+		if (device->hif_shutdown)
+			break;
+
+		device->hif_task_work = 0;
+
+		/* We want to hold the host over multiple cmds if possible;
+		 * but holding the host blocks card interrupts.
+		 */
+		sdio_claim_host(device->func);
+
+		for (;;) {
+			hifdebug("pull next request\n");
+			/* Pull the next request to work on */
+			spin_lock_irqsave(&device->req_qlock, flags);
+			request = device->req_qhead;
+			if (!request) {
+				spin_unlock_irqrestore(&device->req_qlock,
+						       flags);
+				break;
+			}
+
+			/* Remove request from queue */
+			device->req_qhead = (struct bus_request *)request->next;
+			/* Note: No need to clean up req_qtail */
+
+			spin_unlock_irqrestore(&device->req_qlock, flags);
+
+			/* call __hif_read_write to do the work */
+			hifdebug("before HIFRW: address=0x%08x buffer=0x%pK\n",
+				 request->address, request->buffer);
+			hifdebug("before HIFRW: length=%d req_type=0x%08x\n",
+				 request->length, request->req_type);
+
+			if (request->req_type & HIF_WRITE) {
+				int i;
+				int dbgcount;
+
+				if (request->length <= 16)
+					dbgcount = request->length;
+				else
+					dbgcount = 16;
+
+				for (i = 0; i < dbgcount; i++)
+					hifdebug("|0x%02x", request->buffer[i]);
+				hifdebug("\n");
+			}
+			status = __hif_read_write(
+			    device, request->address, request->buffer,
+			    request->length,
+			    request->req_type & ~HIF_SYNCHRONOUS, NULL);
+			hifdebug("after HIFRW: address=0x%08x buffer=0x%pK\n",
+				 request->address, request->buffer);
+			hifdebug("after HIFRW: length=%d req_type=0x%08x\n",
+				 request->length, request->req_type);
+
+			if (request->req_type & HIF_READ) {
+				int i;
+				int dbgcount;
+
+				if (request->length <= 16)
+					dbgcount = request->length;
+				else
+					dbgcount = 16;
+
+				for (i = 0; i < dbgcount; i++)
+					hifdebug("|0x%02x", request->buffer[i]);
+				hifdebug("\n");
+			}
+
+			/* When we return, the read/write is done */
+			request->status = status;
+
+			if (request->req_type & HIF_ASYNCHRONOUS)
+				hif_request_complete(device, request);
+			else
+				/* notify thread that's waiting on this request
+				 */
+				complete(&request->comp_req);
+		}
+		sdio_release_host(device->func);
+	}
+
+	complete_and_exit(&device->hif_exit, 0);
+	return 0;
+}
+
+int hif_configure_device(void *hif_device,
+			 enum hif_device_config_opcode opcode,
+			 void *config, u32 config_len)
+{
+	int status = HIF_OK;
+	struct hif_device *device = (struct hif_device *)hif_device;
+
+	switch (opcode) {
+	case HIF_DEVICE_GET_MBOX_BLOCK_SIZE:
+		((u32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE;
+		((u32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE;
+		((u32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE;
+		((u32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE;
+		break;
+
+	case HIF_DEVICE_SET_CONTEXT:
+		device->context = config;
+		break;
+
+	case HIF_DEVICE_GET_CONTEXT:
+		if (!config)
+			return HIF_ERROR;
+		*(void **)config = device->context;
+		break;
+
+	default:
+		status = HIF_ERROR;
+	}
+
+	return status;
+}
+
+void hif_shutdown_device(void *device)
+{
+	if (!device) {
+		int i;
+		/* since we are unloading the driver, reset all cards
+		 * in case the SDIO card is externally powered and we
+		 * are unloading the SDIO stack.  This avoids the problem
+		 * when the SDIO stack is reloaded and attempts are made
+		 * to re-enumerate a card that is already enumerated.
+		 */
+
+		/* Unregister with bus driver core */
+		if (registered) {
+			registered = 0;
+			hif_sdio_unregister_driver();
+			WARN_ON(1);
+			return;
+		}
+
+		for (i = 0; i < MAX_HIF_DEVICES; ++i) {
+			if (hif_devices[i] && !hif_devices[i]->func) {
+				del_hif_device(hif_devices[i]);
+				hif_devices[i] = NULL;
+			}
+		}
+	}
+}
+
+static void hif_irq_handler(struct sdio_func *func)
+{
+	int status;
+	struct hif_device *device;
+
+	device = get_hif_device(func);
+	device->irq_handling = 1;
+	/* release the host during ints so we can pick it back up when we
+	 * process cmds
+	 */
+	sdio_release_host(device->func);
+	status = device->cbs_from_hif.dsr_hdl(device->cbs_from_hif.context);
+	sdio_claim_host(device->func);
+	device->irq_handling = 0;
+}
+
+static void hif_force_driver_strength(struct sdio_func *func)
+{
+	unsigned int addr = SDIO_CCCR_DRIVE_STRENGTH;
+	unsigned char value = 0;
+
+	if (func0_CMD52_read_byte(func->card, addr, &value))
+		goto cmd_fail;
+
+	value = (value & (~(SDIO_DRIVE_DTSx_MASK << SDIO_DRIVE_DTSx_SHIFT))) |
+			SDIO_DTSx_SET_TYPE_D;
+	if (func0_CMD52_write_byte(func->card, addr, value))
+		goto cmd_fail;
+
+	addr = CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR;
+	value = 0;
+	if (func0_CMD52_read_byte(func->card, addr, &value))
+		goto cmd_fail;
+
+	value = (value & (~CCCR_SDIO_DRIVER_STRENGTH_ENABLE_MASK)) |
+			CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A |
+			CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C |
+			CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D;
+	if (func0_CMD52_write_byte(func->card, addr, value))
+		goto cmd_fail;
+	return;
+cmd_fail:
+	hifdebug("set fail\n");
+}
+
+static int hif_set_mmc_buswidth(struct sdio_func *func,
+				struct hif_device *device)
+{
+	int ret = -1;
+
+	if (hif_mmcbuswidth == 1) {
+		ret = func0_CMD52_write_byte(func->card, SDIO_CCCR_IF,
+					     SDIO_BUS_CD_DISABLE |
+					     SDIO_BUS_WIDTH_1BIT);
+		if (ret)
+			return ret;
+		device->host->ios.bus_width = MMC_BUS_WIDTH_1;
+		device->host->ops->set_ios(device->host, &device->host->ios);
+	} else if (hif_mmcbuswidth == 4 &&
+		   (device->host->caps & MMC_CAP_4_BIT_DATA)) {
+		ret = func0_CMD52_write_byte(func->card, SDIO_CCCR_IF,
+					     SDIO_BUS_CD_DISABLE |
+					     SDIO_BUS_WIDTH_4BIT);
+		if (ret)
+			return ret;
+		device->host->ios.bus_width = MMC_BUS_WIDTH_4;
+		device->host->ops->set_ios(device->host, &device->host->ios);
+	}
+#ifdef SDIO_BUS_WIDTH_8BIT
+	else if (hif_mmcbuswidth == 8 &&
+		 (device->host->caps & MMC_CAP_8_BIT_DATA)) {
+		ret = func0_CMD52_write_byte(func->card, SDIO_CCCR_IF,
+					     SDIO_BUS_CD_DISABLE |
+					     SDIO_BUS_WIDTH_8BIT);
+		if (ret)
+			return ret;
+		device->host->ios.bus_width = MMC_BUS_WIDTH_8;
+		device->host->ops->set_ios(device->host, &device->host->ios);
+	}
+#endif /* SDIO_BUS_WIDTH_8BIT */
+	return ret;
+}
+
+static int hif_device_inserted(struct sdio_func *func,
+			       const struct sdio_device_id *id)
+{
+	int i;
+	int ret = -1;
+	struct hif_device *device = NULL;
+	int count;
+
+	hifdebug("Enter\n");
+
+	/* dma_mask should be populated here.
+	 * Use the parent device's setting.
+	 */
+	func->dev.dma_mask = mmc_dev(func->card->host)->dma_mask;
+
+	if (!add_hif_device(func))
+		return ret;
+	device = get_hif_device(func);
+
+	for (i = 0; i < MAX_HIF_DEVICES; ++i) {
+		if (!hif_devices[i]) {
+			hif_devices[i] = device;
+			break;
+		}
+	}
+	if (WARN_ON(i >= MAX_HIF_DEVICES))
+		return ret;
+
+	device->id = id;
+	device->host = func->card->host;
+	device->is_enabled = false;
+
+	{
+		u32 clock, clock_set = SDIO_CLOCK_FREQUENCY_DEFAULT;
+
+		sdio_claim_host(func);
+
+		/* force driver strength to type D */
+		if (hif_forcedriverstrength == 1)
+			hif_force_driver_strength(func);
+
+		if (hif_writecccr1)
+			(void)func0_CMD52_write_byte(func->card, hif_writecccr1,
+						     hif_writecccr1value);
+		if (hif_writecccr2)
+			(void)func0_CMD52_write_byte(func->card, hif_writecccr2,
+						     hif_writecccr2value);
+		if (hif_writecccr3)
+			(void)func0_CMD52_write_byte(func->card, hif_writecccr3,
+						     hif_writecccr3value);
+		if (hif_writecccr4)
+			(void)func0_CMD52_write_byte(func->card, hif_writecccr4,
+						     hif_writecccr4value);
+		/* Set MMC Clock */
+		if (hif_mmcclock > 0)
+			clock_set = hif_mmcclock;
+		if (mmc_card_hs(func->card))
+			clock = 50000000;
+		else
+			clock = func->card->cis.max_dtr;
+		if (clock > device->host->f_max)
+			clock = device->host->f_max;
+		hifdebug("clock is %d", clock);
+
+		/* only when hif_mmcclock module parameter is specified,
+		 * set the clock explicitly
+		 */
+		if (hif_mmcclock > 0) {
+			device->host->ios.clock = clock_set;
+			device->host->ops->set_ios(device->host,
+						   &device->host->ios);
+		}
+		/* Set MMC Bus Width: 1-1Bit, 4-4Bit, 8-8Bit */
+		if (hif_mmcbuswidth > 0)
+			ret = hif_set_mmc_buswidth(func, device);
+
+		sdio_release_host(func);
+	}
+
+	spin_lock_init(&device->req_free_qlock);
+	spin_lock_init(&device->req_qlock);
+
+	/* Initialize the bus requests to be used later */
+	memset(device->bus_request, 0, sizeof(device->bus_request));
+	for (count = 0; count < BUS_REQUEST_MAX_NUM; count++) {
+		init_completion(&device->bus_request[count].comp_req);
+		hif_free_bus_request(device, &device->bus_request[count]);
+	}
+	init_waitqueue_head(&device->hif_wait);
+	spin_lock_init(&device->compl_qlock);
+	init_waitqueue_head(&device->completion_wait);
+
+	ret = hif_enable_func(device, func);
+	if ((ret == HIF_OK) || (ret == HIF_PENDING)) {
+		hifdebug("Function is ENABLED");
+		return 0;
+	}
+
+	for (i = 0; i < MAX_HIF_DEVICES; i++) {
+		if (hif_devices[i] == device) {
+			hif_devices[i] = NULL;
+			break;
+		}
+	}
+	sdio_set_drvdata(func, NULL);
+	del_hif_device(device);
+	return ret;
+}
+
+void hif_un_mask_interrupt(void *hif_device)
+{
+	struct hif_device *device = (struct hif_device *)hif_device;
+
+	if (!device || !device->func)
+		return;
+
+	/* Unmask our function IRQ */
+	sdio_claim_host(device->func);
+	device->func->card->host->ops->enable_sdio_irq(device->func->card->host,
+						       1);
+	device->is_intr_enb = true;
+	sdio_release_host(device->func);
+}
+
+void hif_mask_interrupt(void *hif_device)
+{
+	struct hif_device *device = (struct hif_device *)hif_device;
+
+	if (!device || !device->func)
+		return;
+
+	/* Mask our function IRQ */
+	sdio_claim_host(device->func);
+	device->func->card->host->ops->enable_sdio_irq(device->func->card->host,
+						       0);
+	device->is_intr_enb = false;
+	sdio_release_host(device->func);
+}
+
+static struct bus_request *hif_allocate_bus_request(void *hif_device)
+{
+	struct bus_request *busrequest;
+	unsigned long flag;
+	struct hif_device *device = (struct hif_device *)hif_device;
+
+	spin_lock_irqsave(&device->req_free_qlock, flag);
+	/* Remove first in list */
+	busrequest = device->bus_req_free_qhead;
+	if (busrequest)
+		device->bus_req_free_qhead =
+			(struct bus_request *)busrequest->next;
+	spin_unlock_irqrestore(&device->req_free_qlock, flag);
+
+	return busrequest;
+}
+
+static void hif_free_bus_request(struct hif_device *device,
+				 struct bus_request *busrequest)
+{
+	unsigned long flag;
+
+	if (!busrequest)
+		return;
+
+	busrequest->next = NULL;
+
+	/* Insert first in list */
+	spin_lock_irqsave(&device->req_free_qlock, flag);
+	busrequest->next = (struct bus_request *)device->bus_req_free_qhead;
+	device->bus_req_free_qhead = busrequest;
+	spin_unlock_irqrestore(&device->req_free_qlock, flag);
+}
+
+static int hif_disable_func(struct hif_device *device, struct sdio_func *func)
+{
+	int ret;
+	int status = HIF_OK;
+
+	device = get_hif_device(func);
+
+	hif_stop_completion_thread(device);
+	hif_stop_hif_task(device);
+
+	/* Disable the card */
+	sdio_claim_host(device->func);
+	ret = sdio_disable_func(device->func);
+	if (ret)
+		status = HIF_ERROR;
+
+	if (hif_reset_sdio_on_unload && (status == HIF_OK)) {
+		/* Reset the SDIO interface.  This is useful in
+		 * automated testing where the card does not need
+		 * to be removed at the end of the test.  It is
+		 * expected that the user will also unload/reload
+		 * the host controller driver to force the bus driver
+		 * to re-enumerate the slot.
+		 */
+
+		/* NOTE : sdio_f0_writeb() cannot be used here, that API only
+		 * allows access to undefined registers in the range of:
+		 * 0xF0-0xFF
+		 */
+
+		ret = func0_CMD52_write_byte(device->func->card,
+					     SDIO_CCCR_ABORT, (1 << 3));
+		if (ret)
+			status = HIF_ERROR;
+	}
+
+	sdio_release_host(device->func);
+
+	if (status == HIF_OK)
+		device->is_enabled = false;
+	return status;
+}
+
+static int hif_enable_func(struct hif_device *device, struct sdio_func *func)
+{
+	int ret = HIF_OK;
+
+	device = get_hif_device(func);
+
+	if (!device)
+		return HIF_EINVAL;
+
+	if (!device->is_enabled) {
+		/* enable the SDIO function */
+		sdio_claim_host(func);
+
+		/* give us some time to enable, in ms */
+		func->enable_timeout = ENABLE_SDIO_TIMEOUT;
+		ret = sdio_enable_func(func);
+		if (ret) {
+			sdio_release_host(func);
+			return HIF_ERROR;
+		}
+		ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
+
+		sdio_release_host(func);
+		if (ret)
+			return HIF_ERROR;
+		device->is_enabled = true;
+
+		if (!device->completion_task) {
+			device->compl_qhead = NULL;
+			device->compl_qtail = NULL;
+			device->completion_shutdown = 0;
+			device->completion_task = kthread_create(
+			    completion_task, (void *)device, "HIFCompl");
+			if (IS_ERR(device->completion_task)) {
+				device->completion_shutdown = 1;
+				return HIF_ERROR;
+			}
+			wake_up_process(device->completion_task);
+		}
+
+		/* create HIF I/O thread */
+		if (!device->hif_task) {
+			device->hif_shutdown = 0;
+			device->hif_task =
+			    kthread_create(hif_task, (void *)device, "HIF");
+			if (IS_ERR(device->hif_task)) {
+				device->hif_shutdown = 1;
+				return HIF_ERROR;
+			}
+			wake_up_process(device->hif_task);
+		}
+	}
+
+	if (!device->claimed_context) {
+		ret = hif_callbacks.dev_inserted_hdl(hif_callbacks.context,
+						     device);
+		if (ret != HIF_OK) {
+			/* Disable the SDIO func & Reset the sdio
+			 * for automated tests to move ahead, where
+			 * the card does not need to be removed at
+			 * the end of the test.
+			 */
+			hif_disable_func(device, func);
+		}
+		(void)sdio_claim_irq(func, hif_irq_handler);
+	}
+
+	return ret;
+}
+
+static void hif_device_removed(struct sdio_func *func)
+{
+	int i;
+	int status = HIF_OK;
+	struct hif_device *device;
+
+	device = get_hif_device(func);
+	if (!device)
+		return;
+
+	for (i = 0; i < MAX_HIF_DEVICES; ++i) {
+		if (hif_devices[i] == device)
+			hif_devices[i] = NULL;
+	}
+
+	if (device->claimed_context) {
+		status = hif_callbacks.dev_removed_hdl(
+		    device->claimed_context, device);
+	}
+
+	/* TBD: Release IRQ (opposite of sdio_claim_irq) */
+	hif_mask_interrupt(device);
+
+	if (device->is_enabled)
+		status = hif_disable_func(device, func);
+
+	del_hif_device(device);
+}
+
+static void *add_hif_device(struct sdio_func *func)
+{
+	struct hif_device *hifdevice = NULL;
+
+	if (!func)
+		return NULL;
+
+	hifdevice = kmalloc(sizeof(*hifdevice), GFP_KERNEL);
+	if (!hifdevice)
+		return NULL;
+
+	memset(hifdevice, 0, sizeof(*hifdevice));
+	hifdevice->func = func;
+	sdio_set_drvdata(func, hifdevice);
+
+	return (void *)hifdevice;
+}
+
+static struct hif_device *get_hif_device(struct sdio_func *func)
+{
+	return (struct hif_device *)sdio_get_drvdata(func);
+}
+
+static void del_hif_device(struct hif_device *device)
+{
+	if (!device)
+		return;
+	kfree(device);
+}
+
+void hif_claim_device(void *hif_device, void *context)
+{
+	struct hif_device *device = (struct hif_device *)hif_device;
+
+	device->claimed_context = context;
+}
+
+void hif_release_device(void *hif_device)
+{
+	struct hif_device *device = (struct hif_device *)hif_device;
+
+	device->claimed_context = NULL;
+}
+
+int hif_attach(void *hif_device, struct cbs_from_hif *callbacks)
+{
+	struct hif_device *device = (struct hif_device *)hif_device;
+
+	if (device->cbs_from_hif.context) {
+		/* already in use! */
+		return HIF_ERROR;
+	}
+	device->cbs_from_hif = *callbacks;
+	return HIF_OK;
+}
+
+static void hif_stop_hif_task(struct hif_device *device)
+{
+	if (device->hif_task) {
+		init_completion(&device->hif_exit);
+		device->hif_shutdown = 1;
+		device->hif_task_work = 1;
+		wake_up(&device->hif_wait);
+		wait_for_completion(&device->hif_exit);
+		device->hif_task = NULL;
+	}
+}
+
+/* hif_reset_target() - Reset target device
+ * @struct hif_device: pointer to struct hif_device structure
+ *
+ * Reset the target by invoking power off and power on
+ * sequence to bring back target into active state.
+ * This API shall be called only when driver load/unload
+ * is in progress.
+ *
+ * Return: 0 on success, error for failure case.
+ */
+static int hif_reset_target(struct hif_device *hif_device)
+{
+	int ret;
+
+	if (!hif_device || !hif_device->func || !hif_device->func->card)
+		return -ENODEV;
+	/* Disable sdio func->pull down WLAN_EN-->pull down DAT_2 line */
+	ret = mmc_power_save_host(hif_device->func->card->host);
+	if (ret)
+		goto done;
+
+	/* pull up DAT_2 line->pull up WLAN_EN-->Enable sdio func */
+	ret = mmc_power_restore_host(hif_device->func->card->host);
+
+done:
+	return ret;
+}
+
+void hif_detach(void *hif_device)
+{
+	struct hif_device *device = (struct hif_device *)hif_device;
+
+	hif_stop_hif_task(device);
+	if (device->ctrl_response_timeout) {
+		/* Reset the target by invoking power off and power on sequence
+		 * to the card to bring back into active state.
+		 */
+		if (hif_reset_target(device))
+			panic("BUG");
+		device->ctrl_response_timeout = false;
+	}
+
+	memset(&device->cbs_from_hif, 0, sizeof(device->cbs_from_hif));
+}
+
+#define SDIO_SET_CMD52_ARG(arg, rw, func, raw, address, writedata) \
+	((arg) = ((((rw) & 1) << 31) | (((func) & 0x7) << 28) | \
+		 (((raw) & 1) << 27) | (1 << 26) | \
+		 (((address) & 0x1FFFF) << 9) | (1 << 8) | \
+		 ((writedata) & 0xFF)))
+
+#define SDIO_SET_CMD52_READ_ARG(arg, func, address) \
+	SDIO_SET_CMD52_ARG(arg, 0, (func), 0, address, 0x00)
+#define SDIO_SET_CMD52_WRITE_ARG(arg, func, address, value) \
+	SDIO_SET_CMD52_ARG(arg, 1, (func), 0, address, value)
+
+static int func0_CMD52_write_byte(struct mmc_card *card, unsigned int address,
+				  unsigned char byte)
+{
+	struct mmc_command ioCmd;
+	unsigned long arg;
+	int status;
+
+	memset(&ioCmd, 0, sizeof(ioCmd));
+	SDIO_SET_CMD52_WRITE_ARG(arg, 0, address, byte);
+	ioCmd.opcode = SD_IO_RW_DIRECT;
+	ioCmd.arg = arg;
+	ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
+	status = mmc_wait_for_cmd(card->host, &ioCmd, 0);
+
+	return status;
+}
+
+static int func0_CMD52_read_byte(struct mmc_card *card, unsigned int address,
+				 unsigned char *byte)
+{
+	struct mmc_command ioCmd;
+	unsigned long arg;
+	s32 err;
+
+	memset(&ioCmd, 0, sizeof(ioCmd));
+	SDIO_SET_CMD52_READ_ARG(arg, 0, address);
+	ioCmd.opcode = SD_IO_RW_DIRECT;
+	ioCmd.arg = arg;
+	ioCmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
+
+	err = mmc_wait_for_cmd(card->host, &ioCmd, 0);
+
+	if ((!err) && (byte))
+		*byte = ioCmd.resp[0] & 0xFF;
+
+	return err;
+}
+
+void hif_set_handle(void *hif_handle, void *handle)
+{
+	struct hif_device *device = (struct hif_device *)hif_handle;
+
+	device->caller_handle = handle;
+}
+
+size_t hif_get_device_size(void)
+{
+	return sizeof(struct hif_device);
+}
diff --git a/drivers/net/wireless/qca402x/hif_sdio/hif.h b/drivers/net/wireless/qca402x/hif_sdio/hif.h
new file mode 100644
index 0000000..924d2e4
--- /dev/null
+++ b/drivers/net/wireless/qca402x/hif_sdio/hif.h
@@ -0,0 +1,335 @@
+/* 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 was originally distributed by Qualcomm Atheros, Inc.
+ * before Copyright ownership was assigned to the Linux Foundation.
+ */
+
+#ifndef _HIF_H_
+#define _HIF_H_
+
+#define DEBUG
+#undef DEBUG
+
+#define HIF_OK 0
+#define HIF_PENDING 1
+#define HIF_ERROR 2
+#define HIF_EINVAL 3
+
+/* direction - Direction of transfer (HIF_READ/HIF_WRITE). */
+#define HIF_READ 0x00000001
+#define HIF_WRITE 0x00000002
+#define HIF_DIR_MASK (HIF_READ | HIF_WRITE)
+
+/* type - An interface may support different kind of read/write commands.
+ * For example: SDIO supports CMD52/CMD53s. In case of MSIO it
+ * translates to using different kinds of TPCs. The command type
+ * is thus divided into a basic and an extended command and can
+ * be specified using HIF_BASIC_IO/HIF_EXTENDED_IO.
+ */
+#define HIF_BASIC_IO 0x00000004
+#define HIF_EXTENDED_IO 0x00000008
+#define HIF_TYPE_MASK (HIF_BASIC_IO | HIF_EXTENDED_IO)
+
+/* emode - This indicates the whether the command is to be executed in a
+ * blocking or non-blocking fashion (HIF_SYNCHRONOUS/
+ * HIF_ASYNCHRONOUS). The read/write data paths in HTCA have been
+ * implemented using the asynchronous mode allowing the the bus
+ * driver to indicate the completion of operation through the
+ * registered callback routine. The requirement primarily comes
+ * from the contexts these operations get called from (a driver's
+ * transmit context or the ISR context in case of receive).
+ * Support for both of these modes is essential.
+ */
+#define HIF_SYNCHRONOUS 0x00000010
+#define HIF_ASYNCHRONOUS 0x00000020
+#define HIF_EMODE_MASK (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS)
+
+/* dmode - An interface may support different kinds of commands based on
+ * the tradeoff between the amount of data it can carry and the
+ * setup time. Byte and Block modes are supported (HIF_BYTE_BASIS/
+ * HIF_BLOCK_BASIS). In case of latter, the data is rounded off
+ * to the nearest block size by padding. The size of the block is
+ * configurable at compile time using the HIF_BLOCK_SIZE and is
+ * negotiated with the target during initialization after the
+ * AR6000 interrupts are enabled.
+ */
+#define HIF_BYTE_BASIS 0x00000040
+#define HIF_BLOCK_BASIS 0x00000080
+#define HIF_DMODE_MASK (HIF_BYTE_BASIS | HIF_BLOCK_BASIS)
+
+/* amode - This indicates if the address has to be incremented on AR6000
+ * after every read/write operation (HIF?FIXED_ADDRESS/
+ * HIF_INCREMENTAL_ADDRESS).
+ */
+#define HIF_FIXED_ADDRESS 0x00000100
+#define HIF_INCREMENTAL_ADDRESS 0x00000200
+#define HIF_AMODE_MASK (HIF_FIXED_ADDRESS | HIF_INCREMENTAL_ADDRESS)
+
+#define HIF_WR_ASYNC_BYTE_FIX \
+	(HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | \
+	 HIF_FIXED_ADDRESS)
+#define HIF_WR_ASYNC_BYTE_INC \
+	(HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | \
+	 HIF_INCREMENTAL_ADDRESS)
+#define HIF_WR_ASYNC_BLOCK_INC \
+	(HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | \
+	 HIF_INCREMENTAL_ADDRESS)
+#define HIF_WR_SYNC_BYTE_FIX \
+	(HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | \
+	 HIF_FIXED_ADDRESS)
+#define HIF_WR_SYNC_BYTE_INC \
+	(HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | \
+	 HIF_INCREMENTAL_ADDRESS)
+#define HIF_WR_SYNC_BLOCK_INC \
+	(HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | \
+	 HIF_INCREMENTAL_ADDRESS)
+#define HIF_WR_ASYNC_BLOCK_FIX \
+	(HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | \
+	 HIF_FIXED_ADDRESS)
+#define HIF_WR_SYNC_BLOCK_FIX \
+	(HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | \
+	 HIF_FIXED_ADDRESS)
+#define HIF_RD_SYNC_BYTE_INC \
+	(HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | \
+	 HIF_INCREMENTAL_ADDRESS)
+#define HIF_RD_SYNC_BYTE_FIX \
+	(HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | \
+	 HIF_FIXED_ADDRESS)
+#define HIF_RD_ASYNC_BYTE_FIX \
+	(HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | \
+	 HIF_FIXED_ADDRESS)
+#define HIF_RD_ASYNC_BLOCK_FIX \
+	(HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | \
+	 HIF_FIXED_ADDRESS)
+#define HIF_RD_ASYNC_BYTE_INC \
+	(HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | \
+	 HIF_INCREMENTAL_ADDRESS)
+#define HIF_RD_ASYNC_BLOCK_INC \
+	(HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | \
+	 HIF_INCREMENTAL_ADDRESS)
+#define HIF_RD_SYNC_BLOCK_INC \
+	(HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | \
+	 HIF_INCREMENTAL_ADDRESS)
+#define HIF_RD_SYNC_BLOCK_FIX \
+	(HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | \
+	 HIF_FIXED_ADDRESS)
+
+enum hif_device_config_opcode {
+	HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
+	HIF_DEVICE_SET_CONTEXT,
+	HIF_DEVICE_GET_CONTEXT,
+};
+
+/* HIF CONFIGURE definitions:
+ *
+ * HIF_DEVICE_GET_MBOX_BLOCK_SIZE
+ * input : none
+ * output : array of 4 u32s
+ * notes: block size is returned for each mailbox (4)
+ *
+ * HIF_DEVICE_SET_CONTEXT
+ * input : arbitrary pointer-sized value
+ * output: none
+ * notes: stores an arbitrary value which can be retrieved later
+ *
+ * HIF_DEVICE_GET_CONTEXT
+ * input: none
+ * output : arbitrary pointer-sized value
+ * notes: retrieves an arbitrary value which was set earlier
+ */
+struct cbs_from_hif {
+	void *context; /* context to pass to the dsrhandler
+			* note : rw_completion_hdl is provided the context
+			* passed to hif_read_write
+			*/
+	int (*rw_completion_hdl)(void *rw_context, int status);
+	int (*dsr_hdl)(void *context);
+};
+
+struct cbs_from_os {
+	void *context; /* context to pass for all callbacks except
+			* dev_removed_hdl the dev_removed_hdl is only called if
+			* the device is claimed
+			*/
+	int (*dev_inserted_hdl)(void *context, void *hif_handle);
+	int (*dev_removed_hdl)(void *claimed_context, void *hif_handle);
+	int (*dev_suspend_hdl)(void *context);
+	int (*dev_resume_hdl)(void *context);
+	int (*dev_wakeup_hdl)(void *context);
+#if defined(DEVICE_POWER_CHANGE)
+	int (*dev_pwr_change_hdl)(void *context,
+				  HIF_DEVICE_POWER_CHANGE_TYPE config);
+#endif /* DEVICE_POWER_CHANGE */
+};
+
+/* other interrupts (non-Recv) are pending, host
+ * needs to read the register table to figure out what
+ */
+#define HIF_OTHER_EVENTS BIT(0)
+
+#define HIF_RECV_MSG_AVAIL BIT(1) /* pending recv packet */
+
+struct hif_pending_events_info {
+	u32 events;
+	u32 look_ahead;
+	u32 available_recv_bytes;
+};
+
+/* function to get pending events , some HIF modules use special mechanisms
+ * to detect packet available and other interrupts
+ */
+typedef int (*HIF_PENDING_EVENTS_FUNC)(void *device,
+				       struct hif_pending_events_info *p_events,
+				       void *async_context);
+
+#define HIF_MASK_RECV TRUE
+#define HIF_UNMASK_RECV FALSE
+/* function to mask recv events */
+typedef int (*HIF_MASK_UNMASK_RECV_EVENT)(void *device, bool mask,
+					  void *async_context);
+
+#ifdef HIF_MBOX_SLEEP_WAR
+/* This API is used to update the target sleep state */
+void hif_set_mbox_sleep(void *device, bool sleep, bool wait,
+			bool cache);
+#endif
+/* This API is used to perform any global initialization of the HIF layer
+ * and to set OS driver callbacks (i.e. insertion/removal) to the HIF layer
+ */
+int hif_init(struct cbs_from_os *callbacks);
+
+/* This API claims the HIF device and provides a context for handling removal.
+ * The device removal callback is only called when the OS claims
+ * a device.  The claimed context must be non-NULL
+ */
+void hif_claim_device(void *device, void *claimed_context);
+
+/* release the claimed device */
+void hif_release_device(void *device);
+
+/* This API allows the calling layer to attach callbacks from HIF */
+int hif_attach(void *device, struct cbs_from_hif *callbacks);
+
+/* This API allows the calling layer to detach callbacks from HIF */
+void hif_detach(void *device);
+
+void hif_set_handle(void *hif_handle, void *handle);
+
+int hif_sync_read(void *device, u32 address, u8 *buffer,
+		  u32 length, u32 request, void *context);
+
+size_t hif_get_device_size(void);
+
+/* This API is used to provide the read/write interface over the specific bus
+ * interface.
+ * address - Starting address in the AR6000's address space. For mailbox
+ * writes, it refers to the start of the mbox boundary. It should
+ * be ensured that the last byte falls on the mailbox's EOM. For
+ * mailbox reads, it refers to the end of the mbox boundary.
+ * buffer - Pointer to the buffer containg the data to be transmitted or
+ * received.
+ * length - Amount of data to be transmitted or received.
+ * request - Characterizes the attributes of the command.
+ */
+int hif_read_write(void *device, u32 address, void *buffer,
+		   u32 length, u32 request, void *context);
+
+/* This can be initiated from the unload driver context when the OS has no more
+ * use for
+ * the device.
+ */
+void hif_shutdown_device(void *device);
+void hif_surprise_removed(void *device);
+
+void hif_mask_interrupt(void *device);
+
+void hif_un_mask_interrupt(void *device);
+
+int hif_configure_device(void *device,
+			 enum hif_device_config_opcode opcode,
+			 void *config, u32 config_len);
+
+/* This API wait for the remaining MBOX messages to be drained
+ * This should be moved to HTCA AR6K layer
+ */
+int hif_wait_for_pending_recv(void *device);
+
+/* BMI and Diag window abstraction
+ */
+
+#define HIF_BMI_EXCHANGE_NO_TIMEOUT ((u32)(0))
+
+#define DIAG_TRANSFER_LIMIT 2048U /* maximum number of bytes that can be handled
+				   * atomically by DiagRead/DiagWrite
+				   */
+
+#ifdef FEATURE_RUNTIME_PM
+/* Runtime power management API of HIF to control
+ * runtime pm. During Runtime Suspend the get API
+ * return -EAGAIN. The caller can queue the cmd or return.
+ * The put API decrements the usage count.
+ * The get API increments the usage count.
+ * The API's are exposed to HTT and WMI Services only.
+ */
+int hif_pm_runtime_get(void *device);
+int hif_pm_runtime_put(void *device);
+void *hif_runtime_pm_prevent_suspend_init(const char *name);
+void hif_runtime_pm_prevent_suspend_deinit(void *data);
+int hif_pm_runtime_prevent_suspend(void *ol_sc, void *data);
+int hif_pm_runtime_allow_suspend(void *ol_sc, void *data);
+int hif_pm_runtime_prevent_suspend_timeout(void *ol_sc, void *data,
+					   unsigned int delay);
+void hif_request_runtime_pm_resume(void *ol_sc);
+#else
+static inline int hif_pm_runtime_get(void *device)
+{
+	return 0;
+}
+
+static inline int hif_pm_runtime_put(void *device)
+{
+	return 0;
+}
+
+static inline int hif_pm_runtime_prevent_suspend(void *ol_sc, void *context)
+{
+	return 0;
+}
+
+static inline int hif_pm_runtime_allow_suspend(void *ol_sc, void *context)
+{
+	return 0;
+}
+
+static inline int hif_pm_runtime_prevent_suspend_timeout(void *ol_sc,
+							 void *context,
+							 unsigned int msec)
+{
+	return 0;
+}
+
+static inline void *hif_runtime_pm_prevent_suspend_init(const char *name)
+{
+	return NULL;
+}
+
+static inline void hif_runtime_pm_prevent_suspend_deinit(void *context)
+{
+}
+
+static inline void hif_request_runtime_pm_resume(void *ol_sc)
+{
+}
+#endif
+
+#endif /* _HIF_H_ */
diff --git a/drivers/net/wireless/qca402x/hif_sdio/hif_internal.h b/drivers/net/wireless/qca402x/hif_sdio/hif_internal.h
new file mode 100644
index 0000000..8b4c11e
--- /dev/null
+++ b/drivers/net/wireless/qca402x/hif_sdio/hif_internal.h
@@ -0,0 +1,117 @@
+/* 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 was originally distributed by Qualcomm Atheros, Inc.
+ * before Copyright ownership was assigned to the Linux Foundation.
+ */
+
+#ifndef _HIF_INTERNAL_H_
+#define _HIF_INTERNAL_H_
+
+#include "hif.h"
+#include "hif_sdio_common.h"
+
+/* Make this large enough to avoid ever failing due to lack of bus requests.
+ * A number that accounts for the total number of credits on the Target plus
+ * outstanding register requests is good.
+ *
+ * FUTURE: could dyanamically allocate busrequest structs as needed.
+ * FUTURE: would be nice for HIF to use HTCA's htca_request. Seems
+ * wasteful to use multiple structures -- one for HTCA and another
+ * for HIF -- and to copy info from one to the other. Maybe should
+ * semi-merge these layers?
+ */
+#define BUS_REQUEST_MAX_NUM 128
+
+#define SDIO_CLOCK_FREQUENCY_DEFAULT 25000000 /* TBD: Can support 50000000
+					       * on real HW?
+					       */
+#define SDWLAN_ENABLE_DISABLE_TIMEOUT 20
+#define FLAGS_CARD_ENAB 0x02
+#define FLAGS_CARD_IRQ_UNMSK 0x04
+
+/* The block size is an attribute of the SDIO function which is
+ * shared by all four mailboxes. We cannot support per-mailbox
+ * block sizes over SDIO.
+ */
+#define HIF_MBOX_BLOCK_SIZE HIF_DEFAULT_IO_BLOCK_SIZE
+#define HIF_MBOX0_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE
+#define HIF_MBOX1_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE
+#define HIF_MBOX2_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE
+#define HIF_MBOX3_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE
+
+struct bus_request {
+	/*struct bus_request*/ void *next; /* link list of available requests */
+	struct completion comp_req;
+	u32 address; /* request data */
+	u8 *buffer;
+	u32 length;
+	u32 req_type;
+	void *context;
+	int status;
+};
+
+struct hif_device {
+	struct sdio_func *func;
+
+	/* Main HIF task */
+	struct task_struct *hif_task; /* task to handle SDIO requests */
+	wait_queue_head_t hif_wait;
+	int hif_task_work;	    /* Signals HIFtask that there is work */
+	int hif_shutdown;	    /* signals HIFtask to stop */
+	struct completion hif_exit; /* HIFtask completion */
+
+	/* HIF Completion task */
+	/* task to handle SDIO completions */
+	struct task_struct *completion_task;
+	wait_queue_head_t completion_wait;
+	int completion_work;
+	int completion_shutdown;
+	struct completion completion_exit;
+
+	/* pending request queue */
+	spinlock_t req_qlock;
+	struct bus_request *req_qhead; /* head of request queue */
+	struct bus_request *req_qtail; /* tail of request queue */
+
+	/* completed request queue */
+	spinlock_t compl_qlock;
+	struct bus_request *compl_qhead;
+	struct bus_request *compl_qtail;
+
+	/* request free list */
+	spinlock_t req_free_qlock;
+	struct bus_request *bus_req_free_qhead; /* free queue */
+
+	/* Space for requests, initially queued to busRequestFreeQueue */
+	struct bus_request bus_request[BUS_REQUEST_MAX_NUM];
+
+	void *claimed_context;
+	struct cbs_from_hif
+	    cbs_from_hif; /* Callbacks made from HIF to caller */
+	bool is_enabled;  /* device is currently enabled? */
+	bool is_intr_enb; /* interrupts are currently unmasked at
+			   * Host - dbg only
+			   */
+	int irq_handling; /* currently processing interrupts */
+	const struct sdio_device_id *id;
+	struct mmc_host *host;
+	void *context;
+	bool ctrl_response_timeout;
+	/* for debug; links hif device back to caller (e.g.HTCA target) */
+	void *caller_handle;
+};
+
+#define CMD53_FIXED_ADDRESS 1
+#define CMD53_INCR_ADDRESS 2
+
+#endif /* _HIF_INTERNAL_H_ */
diff --git a/drivers/net/wireless/qca402x/hif_sdio/hif_sdio_common.h b/drivers/net/wireless/qca402x/hif_sdio/hif_sdio_common.h
new file mode 100644
index 0000000..c325c06
--- /dev/null
+++ b/drivers/net/wireless/qca402x/hif_sdio/hif_sdio_common.h
@@ -0,0 +1,43 @@
+/* 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 was originally distributed by Qualcomm Atheros, Inc.
+ * before Copyright ownership was assigned to the Linux Foundation.
+ */
+
+#ifndef _HIF_SDIO_COMMON_H_
+#define _HIF_SDIO_COMMON_H_
+
+/* The purpose of these blocks is to amortize SDIO command setup time
+ * across multiple bytes of data. In byte mode, we must issue a command
+ * for each byte. In block mode, we issue a command (8B?) for each
+ * BLOCK_SIZE bytes.
+ *
+ * Every mailbox read/write must be padded to this block size. If the
+ * value is too large, we spend more time sending padding bytes over
+ * SDIO. If the value is too small we see less benefit from amortizing
+ * the cost of a command across data bytes.
+ */
+#define HIF_DEFAULT_IO_BLOCK_SIZE 256
+
+#define FIFO_TIMEOUT_AND_CHIP_CONTROL 0x00000868
+#define FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF 0xFFFEFFFF
+#define FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_ON 0x10000
+
+/* Vendor Specific Driver Strength Settings */
+#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_ADDR 0xf2
+#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_MASK 0x0e
+#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_A 0x02
+#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_C 0x04
+#define CCCR_SDIO_DRIVER_STRENGTH_ENABLE_D 0x08
+
+#endif /* _HIF_SDIO_COMMON_H_ */
diff --git a/drivers/net/wireless/qca402x/htca_mbox/htca.h b/drivers/net/wireless/qca402x/htca_mbox/htca.h
new file mode 100644
index 0000000..ce2e0eb
--- /dev/null
+++ b/drivers/net/wireless/qca402x/htca_mbox/htca.h
@@ -0,0 +1,132 @@
+/* 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.
+ */
+
+/* Host-Target Communication API */
+
+#ifndef _HTCA_H_
+#define _HTCA_H_
+
+#define DEBUG
+#undef DEBUG
+
+/* The HTCA API is independent of the underlying interconnect and
+ * independent of the protocols used across that interconnect.
+ */
+
+#define HTCA_OK 0        /* Success */
+#define HTCA_ERROR 1     /* generic error */
+#define HTCA_EINVAL 2    /* Invalid parameter */
+#define HTCA_ECANCELED 3 /* Operation canceled */
+#define HTCA_EPROTO 4    /* Protocol error */
+#define HTCA_ENOMEM 5    /* Memory exhausted */
+
+/* Note: An Endpoint ID is always Interconnect-relative. So we
+ * are likely to see the same Endpoint ID with different Targets
+ * on a multi-Target system.
+ */
+#define HTCA_EP_UNUSED (0xff)
+
+#define HTCA_EVENT_UNUSED 0
+
+/* Start global events */
+#define HTCA_EVENT_GLOBAL_START 1
+#define HTCA_EVENT_TARGET_AVAILABLE 1
+#define HTCA_EVENT_TARGET_UNAVAILABLE 2
+#define HTCA_EVENT_GLOBAL_END 2
+#define HTCA_EVENT_GLOBAL_COUNT                                                \
+		(HTCA_EVENT_GLOBAL_END - HTCA_EVENT_GLOBAL_START + 1)
+/* End global events */
+
+/* Start endpoint-specific events */
+#define HTCA_EVENT_EP_START 3
+#define HTCA_EVENT_BUFFER_RECEIVED 3
+#define HTCA_EVENT_BUFFER_SENT 4
+#define HTCA_EVENT_DATA_AVAILABLE 5
+#define HTCA_EVENT_EP_END 5
+#define HTCA_EVENT_EP_COUNT (HTCA_EVENT_EP_END - HTCA_EVENT_EP_START + 1)
+/* End endpoint-specific events */
+
+/* Maximum size of an HTC header across relevant implementations
+ * (e.g. across interconnect types and platforms and OSes of interest).
+ *
+ * Callers of HTC must leave HTCA_HEADER_LEN_MAX bytes
+ * reserved BEFORE the start of a buffer passed to HTCA htca_buffer_send
+ * AT the start of a buffer passed to HTCBufferReceive
+ * for use by HTC itself.
+ *
+ * FUTURE: Investigate ways to remove the need for callers to accommodate
+ * for HTC headers.* Doesn't seem that hard to do....just tack on the
+ * length in a separate buffer and send buffer pairs to HIF. When extracting,
+ * first pull header then pull payload into paired buffers.
+ */
+
+#define HTCA_HEADER_LEN_MAX 2
+
+struct htca_event_info {
+	u8 *buffer;
+	void *cookie;
+	u32 buffer_length;
+	u32 actual_length;
+	int status;
+};
+
+typedef void (*htca_event_handler)(void *target,
+				   u8 ep,
+				   u8 event_id,
+				   struct htca_event_info *event_info,
+				   void *context);
+
+int htca_init(void);
+
+void htca_shutdown(void);
+
+int htca_start(void *target);
+
+void htca_stop(void *target);
+
+int htca_event_reg(void *target,
+		   u8 end_point_id,
+		   u8 event_id,
+		   htca_event_handler event_handler, void *context);
+
+/* Notes:
+ * buffer should be multiple of blocksize.
+ * buffer should be large enough for header+largest message, rounded up to
+ * blocksize.
+ * buffer passed in should be start of the buffer -- where header will go.
+ * length should be full length, including header.
+ * On completion, buffer points to start of payload (AFTER header).
+ * On completion, actual_length is the length of payload. Does not include
+ * header nor padding. On completion, buffer_length matches the length that
+ * was passed in here.
+ */
+int htca_buffer_receive(void *target,
+			u8 end_point_id, u8 *buffer,
+			u32 length, void *cookie);
+
+/* Notes:
+ * buffer should be multiple of blocksize.
+ * buffer passed in should be start of payload; header will be tacked on BEFORE
+ * this.
+ * extra bytes will be sent, padding the message to blocksize.
+ * length should be the number of payload bytes to be sent.
+ * The actual number of bytes that go over SDIO is length+header, rounded up to
+ * blocksize.
+ * On completion, buffer points to start of payload (AFTER header).
+ * On completion, actual_length is the length of payload. Does not include
+ * header nor padding. On completion buffer_length is irrelevant.
+ */
+int htca_buffer_send(void *target,
+		     u8 end_point_id,
+		     u8 *buffer, u32 length, void *cookie);
+
+#endif /* _HTCA_H_ */
diff --git a/drivers/net/wireless/qca402x/htca_mbox/htca_mbox.c b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox.c
new file mode 100644
index 0000000..fbf3549
--- /dev/null
+++ b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox.c
@@ -0,0 +1,497 @@
+/* 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.
+ */
+
+/* Implementation of Host Target Communication
+ * API v1 and HTCA Protocol v1
+ * over Qualcomm QCA mailbox-based SDIO/SPI interconnects.
+ */
+
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "../hif_sdio/hif.h"
+#include "htca.h"
+#include "htca_mbox_internal.h"
+
+struct htca_target *htca_target_list[HTCA_NUM_DEVICES_MAX];
+
+/* Single thread module initialization, module shutdown,
+ * target start and target stop.
+ */
+static DEFINE_MUTEX(htca_startup_mutex);
+static bool htca_initialized;
+
+/* Initialize the HTCA software module.
+ * Typically invoked exactly once.
+ */
+int htca_init(void)
+{
+	struct cbs_from_os callbacks;
+
+	if (mutex_lock_interruptible(&htca_startup_mutex))
+		return HTCA_ERROR; /* interrupted */
+
+	if (htca_initialized) {
+		mutex_unlock(&htca_startup_mutex);
+		return HTCA_OK; /* Already initialized */
+	}
+
+	htca_initialized = true;
+
+	htca_event_table_init();
+
+	memset(&callbacks, 0, sizeof(callbacks));
+	callbacks.dev_inserted_hdl = htca_target_inserted_handler;
+	callbacks.dev_removed_hdl = htca_target_removed_handler;
+	hif_init(&callbacks);
+
+	mutex_unlock(&htca_startup_mutex);
+
+	return HTCA_OK;
+}
+
+/* Shutdown the entire module and free all module data.
+ * Inverse of htca_init.
+ *
+ * May be invoked only after all Targets are stopped.
+ */
+void htca_shutdown(void)
+{
+	int i;
+
+	if (mutex_lock_interruptible(&htca_startup_mutex))
+		return; /* interrupted */
+
+	if (!htca_initialized) {
+		mutex_unlock(&htca_startup_mutex);
+		return; /* Not initialized, so nothing to shut down */
+	}
+
+	for (i = 0; i < HTCA_NUM_DEVICES_MAX; i++) {
+		if (htca_target_instance(i)) {
+			/* One or more Targets are still active --
+			 * cannot shutdown software.
+			 */
+			mutex_unlock(&htca_startup_mutex);
+			WARN_ON(1);
+			return;
+		}
+	}
+
+	hif_shutdown_device(NULL); /* Tell HIF that we're all done */
+	htca_initialized = false;
+
+	mutex_unlock(&htca_startup_mutex);
+}
+
+/* Start a Target. This typically happens once per Target after
+ * the module has been initialized and a Target is powered on.
+ *
+ * When a Target starts, it posts a single credit to each mailbox
+ * and it enters "HTCA configuration". During configuration
+ * negotiation, block sizes for each HTCA endpoint are established
+ * that both Host and Target agree. Once this is complete, the
+ * Target starts normal operation so it can send/receive.
+ */
+int htca_start(void *tar)
+{
+	int status;
+	u32 address;
+	struct htca_target *target = (struct htca_target *)tar;
+
+	mutex_lock(&htca_startup_mutex);
+
+	if (!htca_initialized) {
+		mutex_unlock(&htca_startup_mutex);
+		return HTCA_ERROR;
+	}
+
+	init_waitqueue_head(&target->target_init_wait);
+
+	/* Unmask Host controller interrupts associated with this Target */
+	hif_un_mask_interrupt(target->hif_handle);
+
+	/* Enable all interrupts of interest on the Target. */
+
+	target->enb.int_status_enb = INT_STATUS_ENABLE_ERROR_SET(0x01) |
+				     INT_STATUS_ENABLE_CPU_SET(0x01) |
+				     INT_STATUS_ENABLE_COUNTER_SET(0x01) |
+				     INT_STATUS_ENABLE_MBOX_DATA_SET(0x0F);
+
+	target->enb.cpu_int_status_enb = CPU_INT_STATUS_ENABLE_BIT_SET(0x00);
+
+	target->enb.err_status_enb =
+	    ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(0x01) |
+	    ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(0x01);
+
+	target->enb.counter_int_status_enb =
+	    COUNTER_INT_STATUS_ENABLE_BIT_SET(0xFF);
+
+	/* Commit interrupt register values to Target HW. */
+	address = get_reg_addr(INTR_ENB_REG, ENDPOINT_UNUSED);
+	status =
+	    hif_read_write(target->hif_handle, address, &target->enb,
+			   sizeof(target->enb), HIF_WR_SYNC_BYTE_INC, NULL);
+	if (status != HIF_OK) {
+		_htca_stop(target);
+		mutex_unlock(&htca_startup_mutex);
+		return HTCA_ERROR;
+	}
+
+	/* At this point, we're waiting for the Target to post
+	 * 1 credit to each mailbox. This allows us to begin
+	 * configuration negotiation. We should see an interrupt
+	 * as soon as the first credit is posted. The remaining
+	 * credits should be posted almost immediately after.
+	 */
+
+	/* Wait indefinitely until configuration negotiation with
+	 * the Target completes and the Target tells us it is ready to go.
+	 */
+	if (!target->ready) {
+		/* NB: Retain the htca_statup_mutex during this wait.
+		 * This serializes startup but should be OK.
+		 */
+
+		wait_event_interruptible(target->target_init_wait,
+					 target->ready);
+
+		if (target->ready) {
+			status = HTCA_OK;
+		} else {
+			status = HTCA_ERROR;
+			_htca_stop(target);
+		}
+	}
+
+	mutex_unlock(&htca_startup_mutex);
+	return status;
+}
+
+void _htca_stop(struct htca_target *target)
+{
+	uint ep;
+	struct htca_endpoint *end_point;
+	u32 address;
+
+	/* Note: htca_startup_mutex must be held on entry */
+	if (!htca_initialized)
+		return;
+
+	htca_work_task_stop(target);
+
+	/* Disable interrupts at source, on Target */
+	target->enb.int_status_enb = 0;
+	target->enb.cpu_int_status_enb = 0;
+	target->enb.err_status_enb = 0;
+	target->enb.counter_int_status_enb = 0;
+
+	address = get_reg_addr(INTR_ENB_REG, ENDPOINT_UNUSED);
+
+	/* Try to disable all interrupts on the Target. */
+	(void)hif_read_write(target->hif_handle, address, &target->enb,
+			     sizeof(target->enb), HIF_WR_SYNC_BYTE_INC, NULL);
+
+	/* Disable Host controller interrupts */
+	hif_mask_interrupt(target->hif_handle);
+
+	/* Flush all the queues and return the buffers to their owner */
+	for (ep = 0; ep < HTCA_NUM_MBOX; ep++) {
+		unsigned long flags;
+
+		end_point = &target->end_point[ep];
+
+		spin_lock_irqsave(&end_point->tx_credit_lock, flags);
+		end_point->tx_credits_available = 0;
+		spin_unlock_irqrestore(&end_point->tx_credit_lock, flags);
+
+		end_point->enabled = false;
+
+		/* Flush the Pending Receive Queue */
+		htca_mbox_queue_flush(end_point, &end_point->recv_pending_queue,
+				      &end_point->recv_free_queue,
+				      HTCA_EVENT_BUFFER_RECEIVED);
+
+		/* Flush the Pending Send Queue */
+		htca_mbox_queue_flush(end_point, &end_point->send_pending_queue,
+				      &end_point->send_free_queue,
+				      HTCA_EVENT_BUFFER_SENT);
+	}
+
+	target->ready = false;
+
+	hif_detach(target->hif_handle);
+
+	/* Remove this Target from the global list */
+	htca_target_instance_remove(target);
+
+	/* Free target memory */
+	kfree(target);
+}
+
+void htca_stop(void *tar)
+{
+	struct htca_target *target = (struct htca_target *)tar;
+
+	htca_work_task_stop(target);
+	htca_compl_task_stop(target);
+
+	mutex_lock(&htca_startup_mutex);
+	_htca_stop(target);
+	mutex_unlock(&htca_startup_mutex);
+}
+
+/* Provides an interface for the caller to register for
+ * various events supported by the HTCA module.
+ */
+int htca_event_reg(void *tar,
+		   u8 end_point_id,
+		   u8 event_id,
+		   htca_event_handler event_handler, void *param)
+{
+	int status;
+	struct htca_endpoint *end_point;
+	struct htca_event_info event_info;
+	struct htca_target *target = (struct htca_target *)tar;
+
+	/* Register a new handler BEFORE dispatching events.
+	 * UNregister a handler AFTER dispatching events.
+	 */
+	if (event_handler) {
+		/* Register a new event handler */
+
+		status = htca_add_to_event_table(target, end_point_id, event_id,
+						 event_handler, param);
+		if (status != HTCA_OK)
+			return status; /* Fail to register handler */
+	}
+
+	/* Handle events associated with this handler */
+	switch (event_id) {
+	case HTCA_EVENT_TARGET_AVAILABLE:
+		if (event_handler) {
+			struct htca_target *targ;
+			int i;
+
+			/* Dispatch a Target Available event for all Targets
+			 * that are already present.
+			 */
+			for (i = 0; i < HTCA_NUM_DEVICES_MAX; i++) {
+				targ = htca_target_list[i];
+				if (targ) {
+					size_t size = hif_get_device_size();
+
+					htca_frame_event(&event_info,
+							 (u8 *)targ->hif_handle,
+							 size, size,
+							 HTCA_OK, NULL);
+
+					htca_dispatch_event(
+					    targ, ENDPOINT_UNUSED,
+					    HTCA_EVENT_TARGET_AVAILABLE,
+					    &event_info);
+				}
+			}
+		}
+		break;
+
+	case HTCA_EVENT_TARGET_UNAVAILABLE:
+		break;
+
+	case HTCA_EVENT_BUFFER_RECEIVED:
+		if (!event_handler) {
+			/* Flush the Pending Recv queue before unregistering
+			 * the event handler.
+			 */
+			end_point = &target->end_point[end_point_id];
+			htca_mbox_queue_flush(end_point,
+					      &end_point->recv_pending_queue,
+					      &end_point->recv_free_queue,
+					      HTCA_EVENT_BUFFER_RECEIVED);
+		}
+		break;
+
+	case HTCA_EVENT_BUFFER_SENT:
+		if (!event_handler) {
+			/* Flush the Pending Send queue before unregistering
+			 * the event handler.
+			 */
+			end_point = &target->end_point[end_point_id];
+			htca_mbox_queue_flush(end_point,
+					      &end_point->send_pending_queue,
+					      &end_point->send_free_queue,
+					      HTCA_EVENT_BUFFER_SENT);
+		}
+		break;
+
+	case HTCA_EVENT_DATA_AVAILABLE:
+		/* We could dispatch a data available event. Instead,
+		 * we require users to register this event handler
+		 * before posting receive buffers.
+		 */
+		break;
+
+	default:
+		return HTCA_EINVAL; /* unknown event? */
+	}
+
+	if (!event_handler) {
+		/* Unregister an event handler */
+		status = htca_remove_from_event_table(target,
+						      end_point_id, event_id);
+		if (status != HTCA_OK)
+			return status;
+	}
+
+	return HTCA_OK;
+}
+
+/* Enqueue to the endpoint's recv_pending_queue an empty buffer
+ * which will receive data from the Target.
+ */
+int htca_buffer_receive(void *tar,
+			u8 end_point_id, u8 *buffer,
+			u32 length, void *cookie)
+{
+	struct htca_endpoint *end_point;
+	struct htca_mbox_request *mbox_request;
+	struct htca_event_table_element *ev;
+	unsigned long flags;
+	struct htca_target *target = (struct htca_target *)tar;
+
+	end_point = &target->end_point[end_point_id];
+
+	if (!end_point->enabled)
+		return HTCA_ERROR;
+
+	/* Length must be a multiple of block_size.
+	 * (Ideally, length should match the largest message that can be sent
+	 * over this endpoint, including HTCA header, rounded up to blocksize.)
+	 */
+	if (length % end_point->block_size)
+		return HTCA_EINVAL;
+
+	if (length > HTCA_MESSAGE_SIZE_MAX)
+		return HTCA_EINVAL;
+
+	if (length < HTCA_HEADER_LEN_MAX)
+		return HTCA_EINVAL;
+
+	ev = htca_event_id_to_event(target, end_point_id,
+				    HTCA_EVENT_BUFFER_RECEIVED);
+	if (!ev->handler) {
+		/* In order to use this API, caller must
+		 * register an event handler for HTCA_EVENT_BUFFER_RECEIVED.
+		 */
+		return HTCA_ERROR;
+	}
+
+	spin_lock_irqsave(&end_point->mbox_queue_lock, flags);
+	mbox_request = (struct htca_mbox_request *)htca_request_deq_head(
+	    &end_point->recv_free_queue);
+	spin_unlock_irqrestore(&end_point->mbox_queue_lock, flags);
+	if (!mbox_request)
+		return HTCA_ENOMEM;
+
+	if (WARN_ON(mbox_request->req.target != target))
+		return HTCA_ERROR;
+
+	mbox_request->buffer = buffer;
+	/* includes space for HTCA header */
+	mbox_request->buffer_length = length;
+	/* filled in after message is received */
+	mbox_request->actual_length = 0;
+	mbox_request->end_point = end_point;
+	mbox_request->cookie = cookie;
+
+	spin_lock_irqsave(&end_point->mbox_queue_lock, flags);
+	htca_request_enq_tail(&end_point->recv_pending_queue,
+			      (struct htca_request *)mbox_request);
+	spin_unlock_irqrestore(&end_point->mbox_queue_lock, flags);
+
+	/* Alert the work_task that there may be work to do */
+	htca_work_task_poke(target);
+
+	return HTCA_OK;
+}
+
+/* Enqueue a buffer to be sent to the Target.
+ *
+ * Supplied buffer must be preceded by HTCA_HEADER_LEN_MAX bytes for the
+ * HTCA header (of which HTCA_HEADER_LEN bytes are actually used, and the
+ * remaining are padding).
+ *
+ * Must be followed with sufficient space for block-size padding.
+ *
+ * Example:
+ * To send a 10B message over an endpoint that uses 64B blocks, caller
+ * specifies length=10. HTCA adds HTCA_HEADER_LEN_MAX bytes just before
+ * buffer, consisting of HTCA_HEADER_LEN header bytes followed by
+ * HTCA_HEADER_LEN_MAX-HTCA_HEADER_LEN pad bytes. HTC sends blockSize
+ * bytes starting at buffer-HTCA_HEADER_LEN_MAX.
+ */
+int htca_buffer_send(void *tar,
+		     u8 end_point_id,
+		     u8 *buffer, u32 length, void *cookie)
+{
+	struct htca_endpoint *end_point;
+	struct htca_mbox_request *mbox_request;
+	struct htca_event_table_element *ev;
+	unsigned long flags;
+	struct htca_target *target = (struct htca_target *)tar;
+
+	end_point = &target->end_point[end_point_id];
+
+	if (!end_point->enabled)
+		return HTCA_ERROR;
+
+	if (length + HTCA_HEADER_LEN_MAX > HTCA_MESSAGE_SIZE_MAX)
+		return HTCA_EINVAL;
+
+	ev = htca_event_id_to_event(target, end_point_id,
+				    HTCA_EVENT_BUFFER_SENT);
+	if (!ev->handler) {
+		/* In order to use this API, caller must
+		 * register an event handler for HTCA_EVENT_BUFFER_SENT.
+		 */
+		return HTCA_ERROR;
+	}
+
+	spin_lock_irqsave(&end_point->mbox_queue_lock, flags);
+	mbox_request = (struct htca_mbox_request *)htca_request_deq_head(
+	    &end_point->send_free_queue);
+	spin_unlock_irqrestore(&end_point->mbox_queue_lock, flags);
+	if (!mbox_request)
+		return HTCA_ENOMEM;
+
+	/* Buffer will be adjusted by HTCA_HEADER_LEN later, in
+	 * htca_send_request_to_hif.
+	 */
+	mbox_request->buffer = buffer;
+	mbox_request->buffer_length = length;
+	mbox_request->actual_length = length;
+	mbox_request->end_point = end_point;
+	mbox_request->cookie = cookie;
+
+	spin_lock_irqsave(&end_point->mbox_queue_lock, flags);
+	htca_request_enq_tail(&end_point->send_pending_queue,
+			      (struct htca_request *)mbox_request);
+	spin_unlock_irqrestore(&end_point->mbox_queue_lock, flags);
+
+	/* Alert the work_task that there may be work to do */
+	htca_work_task_poke(target);
+
+	return HTCA_OK;
+}
diff --git a/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_compl.c b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_compl.c
new file mode 100644
index 0000000..c7f8e953
--- /dev/null
+++ b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_compl.c
@@ -0,0 +1,503 @@
+/* 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/completion.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/spinlock_types.h>
+#include <linux/wait.h>
+
+#include "../hif_sdio/hif.h"
+#include "htca.h"
+#include "htca_mbox_internal.h"
+
+/* Host Target Communications Completion Management */
+
+/* Top-level callback handler, registered with HIF to be invoked
+ * whenever a read/write HIF operation completes. Executed in the
+ * context of an HIF task, so we don't want to take much time
+ * here. Pass processing to HTCA's compl_task.
+ *
+ * Used for both reg_requests and mbox_requests.
+ */
+int htca_rw_completion_handler(void *context, int status)
+{
+	struct htca_request *req;
+	struct htca_target *target;
+	unsigned long flags;
+
+	req = (struct htca_request *)context;
+	if (!context) {
+		/* No completion required for this request.
+		 * (e.g. Fire-and-forget register write.)
+		 */
+		return HTCA_OK;
+	}
+
+	target = req->target;
+	req->status = status;
+
+	/* Enqueue this completed request on the
+	 * Target completion queue.
+	 */
+	spin_lock_irqsave(&target->compl_queue_lock, flags);
+	htca_request_enq_tail(&target->compl_queue, (struct htca_request *)req);
+	spin_unlock_irqrestore(&target->compl_queue_lock, flags);
+
+	/* Notify the completion task that it has work */
+	htca_compl_task_poke(target);
+
+	return HTCA_OK;
+}
+
+/* Request-specific callback invoked by the HTCA Completion Task
+ * when a Mbox Send Request completes. Note: Used for Mbox Send
+ * requests; not used for Reg requests.
+ *
+ * Simply dispatch a BUFFER_SENT event to the originator of the request.
+ */
+void htca_send_compl(struct htca_request *req, int status)
+{
+	struct htca_target *target;
+	u8 end_point_id;
+	struct htca_event_info event_info;
+	struct htca_endpoint *end_point;
+	struct htca_mbox_request *mbox_request =
+			(struct htca_mbox_request *)req;
+	unsigned long flags;
+
+	end_point = mbox_request->end_point;
+	target = end_point->target;
+	end_point_id = get_endpoint_id(end_point);
+
+	/* Strip off the HTCA header that was added earlier */
+	mbox_request->buffer += HTCA_HEADER_LEN_MAX;
+
+	/* Prepare event frame to notify caller */
+	htca_frame_event(&event_info, mbox_request->buffer,
+			 mbox_request->buffer_length,
+			 mbox_request->actual_length,
+			 (status == HIF_OK) ? HTCA_OK : HTCA_ECANCELED,
+			 mbox_request->cookie);
+
+	/* Recycle the request */
+	spin_lock_irqsave(&end_point->mbox_queue_lock, flags);
+	htca_request_enq_tail(&end_point->send_free_queue,
+			      (struct htca_request *)mbox_request);
+	spin_unlock_irqrestore(&end_point->mbox_queue_lock, flags);
+	/* Regardless of success/failure, notify caller that HTCA is done
+	 * with his buffer.
+	 */
+	htca_dispatch_event(target, end_point_id, HTCA_EVENT_BUFFER_SENT,
+			    &event_info);
+}
+
+/* Request-specific callback invoked by the HTCA Completion Task
+ * when a Mbox Recv Request completes. Note: Used for Mbox Recv
+ * requests; not used for Reg requests.
+ *
+ * Simply dispatch a BUFFER_RECEIVED event to the originator
+ * of the request.
+ */
+void htca_recv_compl(struct htca_request *req, int status)
+{
+	struct htca_target *target;
+	struct htca_event_info event_info;
+	u8 end_point_id;
+	struct htca_endpoint *end_point;
+	struct htca_mbox_request *mbox_request =
+	    (struct htca_mbox_request *)req;
+	unsigned long flags;
+
+	end_point = mbox_request->end_point;
+	target = end_point->target;
+	end_point_id = get_endpoint_id(end_point);
+
+	/* Signaling:
+	 * Now that we have consumed recv data, clar rx_frame_length so that
+	 * htca_manage_pending_recvs will not try to re-read the same data.
+	 *
+	 * Set need_register_refresh so we can determine whether or not there
+	 * is additional data waiting to be read.
+	 *
+	 * Clear our endpoint from the pending_recv_mask so
+	 * htca_manage_pending_recvs
+	 * is free to issue another read.
+	 *
+	 * Finally, poke the work_task.
+	 */
+	end_point->rx_frame_length = 0;
+	target->need_register_refresh = 1;
+	spin_lock_irqsave(&target->pending_op_lock, flags);
+	target->pending_recv_mask &= ~(1 << end_point_id);
+	spin_unlock_irqrestore(&target->pending_op_lock, flags);
+	htca_work_task_poke(target);
+
+	if (status == HIF_OK) {
+		u32 check_length;
+		/* Length coming from Target is always LittleEndian */
+		check_length = ((mbox_request->buffer[0] << 0) |
+				(mbox_request->buffer[1] << 8));
+		WARN_ON(mbox_request->actual_length != check_length);
+	}
+
+	/* Strip off header */
+	mbox_request->buffer += HTCA_HEADER_LEN_MAX;
+
+	htca_frame_event(&event_info, mbox_request->buffer,
+			 mbox_request->buffer_length,
+			 mbox_request->actual_length,
+			 (status == HIF_OK) ? HTCA_OK : HTCA_ECANCELED,
+			 mbox_request->cookie);
+
+	/* Recycle the request */
+	spin_lock_irqsave(&end_point->mbox_queue_lock, flags);
+	htca_request_enq_tail(&end_point->recv_free_queue,
+			      (struct htca_request *)mbox_request);
+	spin_unlock_irqrestore(&end_point->mbox_queue_lock, flags);
+
+	htca_dispatch_event(target, end_point_id, HTCA_EVENT_BUFFER_RECEIVED,
+			    &event_info);
+}
+
+/* Request-specific callback invoked when a register read/write
+ * request completes. reg_request structures are not used for
+ * register WRITE requests so there's not much to do for writes.
+ *
+ * Note: For Mbox Request completions see htca_send_compl
+ * and htca_recv_compl.
+ */
+
+/* Request-specific callback invoked by the HTCA Completion Task
+ * when a Reg Request completes. Note: Used for Reg requests;
+ * not used for Mbox requests.
+ */
+void htca_reg_compl(struct htca_request *req, int status)
+{
+	struct htca_target *target;
+	struct htca_reg_request *reg_request = (struct htca_reg_request *)req;
+	unsigned long flags;
+
+	if (WARN_ON(!reg_request))
+		return;
+
+	htcadebug("purpose=0x%x\n", reg_request->purpose);
+
+	/* Process async register read/write completion */
+
+	target = reg_request->req.target;
+	if (status != HIF_OK) {
+		/* Recycle the request */
+		reg_request->purpose = UNUSED_PURPOSE;
+		spin_lock_irqsave(&target->reg_queue_lock, flags);
+		htca_request_enq_tail(&target->reg_free_queue,
+				      (struct htca_request *)reg_request);
+		spin_unlock_irqrestore(&target->reg_queue_lock, flags);
+
+		/* A register read/write accepted by HIF
+		 * should never fail.
+		 */
+		WARN_ON(1);
+		return;
+	}
+
+	switch (reg_request->purpose) {
+	case INTR_REFRESH:
+		/* Target register state, including interrupt
+		 * registers, has been fetched.
+		 */
+		htca_register_refresh_compl(target, reg_request);
+		break;
+
+	case CREDIT_REFRESH:
+		htca_credit_refresh_compl(target, reg_request);
+		break;
+
+	case UPDATE_TARG_INTRS:
+	case UPDATE_TARG_AND_ENABLE_HOST_INTRS:
+		htca_update_intr_enbs_compl(target, reg_request);
+		break;
+
+	default:
+		WARN_ON(1); /* unhandled request type */
+		break;
+	}
+
+	/* Recycle this register read/write request */
+	reg_request->purpose = UNUSED_PURPOSE;
+	spin_lock_irqsave(&target->reg_queue_lock, flags);
+	htca_request_enq_tail(&target->reg_free_queue,
+			      (struct htca_request *)reg_request);
+	spin_unlock_irqrestore(&target->reg_queue_lock, flags);
+}
+
+/* After a Register Refresh, uppdate tx_credits_to_reap for each end_point.  */
+static void htca_update_tx_credits_to_reap(struct htca_target *target,
+					   struct htca_reg_request *reg_request)
+{
+	struct htca_endpoint *end_point;
+	int ep;
+
+	for (ep = 0; ep < HTCA_NUM_MBOX; ep++) {
+		end_point = &target->end_point[ep];
+
+		if (reg_request->u.reg_table.status.counter_int_status &
+		    (0x10 << ep)) {
+			end_point->tx_credits_to_reap = true;
+		} else {
+			end_point->tx_credits_to_reap = false;
+		}
+	}
+}
+
+/* After a Register Refresh, uppdate rx_frame_length for each end_point.  */
+static void htca_update_rx_frame_lengths(struct htca_target *target,
+					 struct htca_reg_request *reg_request)
+{
+	struct htca_endpoint *end_point;
+	u32 rx_lookahead;
+	u32 frame_length;
+	int ep;
+
+	htcadebug("Enter\n");
+	for (ep = 0; ep < HTCA_NUM_MBOX; ep++) {
+		end_point = &target->end_point[ep];
+
+		if (end_point->rx_frame_length != 0) {
+			/* NB: Will be cleared in htca_recv_compl after
+			 * frame is read
+			 */
+			continue;
+		}
+
+		if (!(reg_request->u.reg_table.rx_lookahead_valid &
+		      (1 << ep))) {
+			continue;
+		}
+
+		/* The length of the incoming message is contained
+		 * in the first two (HTCA_HEADER_LEN) bytes in
+		 * LittleEndian order.
+		 *
+		 * This length does NOT include the HTCA header nor block
+		 * padding.
+		 */
+		rx_lookahead = reg_request->u.reg_table.rx_lookahead[ep];
+		frame_length = rx_lookahead & 0x0000ffff;
+
+		end_point->rx_frame_length = frame_length;
+		htcadebug("ep#%d : %d\n", ep,
+			  frame_length);
+	}
+}
+
+static unsigned int htca_debug_no_pending; /* debug only */
+
+/* Completion for a register refresh.
+ *
+ * Update rxFrameLengths and tx_credits_to_reap info for
+ * each endpoint. Then handle all pending interrupts (o
+ * if interrupts are currently masked at the Host, handle
+ * all interrupts that would be pending if interrupts
+ * were enabled).
+ *
+ * Called in the context of HIF's completion task whenever
+ * results from a register refresh are received.
+ */
+void htca_register_refresh_compl(struct htca_target *target,
+				 struct htca_reg_request *req)
+{
+	u8 host_int_status;
+	u8 pnd_enb_intrs; /* pending and enabled interrupts */
+	u8 pending_int;
+	u8 enabled_int;
+	unsigned long flags;
+
+	htcadebug("Enter\n");
+
+	if (WARN_ON(target->pending_register_refresh == 0))
+		return;
+
+	spin_lock_irqsave(&target->pending_op_lock, flags);
+	target->pending_register_refresh--;
+	spin_unlock_irqrestore(&target->pending_op_lock, flags);
+
+	htcadebug(
+	    "REGDUMP: hostis=0x%02x cpuis=0x%02x erris=0x%02x cntris=0x%02x\n",
+	    req->u.reg_table.status.host_int_status,
+	    req->u.reg_table.status.cpu_int_status,
+	    req->u.reg_table.status.err_int_status,
+	    req->u.reg_table.status.counter_int_status);
+	htcadebug(
+	    "mbox_frame=0x%02x lav=0x%02x la0=0x%08x la1=0x%08x la2=0x%08x la3=0x%08x\n",
+	    req->u.reg_table.mbox_frame, req->u.reg_table.rx_lookahead_valid,
+	    req->u.reg_table.rx_lookahead[0], req->u.reg_table.rx_lookahead[1],
+	    req->u.reg_table.rx_lookahead[2], req->u.reg_table.rx_lookahead[3]);
+
+	/* Update rxFrameLengths */
+	htca_update_rx_frame_lengths(target, req);
+
+	/* Update tx_credits_to_reap */
+	htca_update_tx_credits_to_reap(target, req);
+
+	/* Process pending Target interrupts. */
+
+	/* Restrict attention to pending interrupts of interest */
+	host_int_status = req->u.reg_table.status.host_int_status;
+
+	/* Unexpected and unhandled */
+	if (WARN_ON(host_int_status & HOST_INT_STATUS_DRAGON_INT_MASK))
+		return;
+
+	/* Form software's idea of pending and enabled interrupts.
+	 * Start with ERRORs and CPU interrupts.
+	 */
+	pnd_enb_intrs = host_int_status &
+			(HOST_INT_STATUS_ERROR_MASK | HOST_INT_STATUS_CPU_MASK);
+
+	/* Software may have intended to enable/disable credit
+	 * counter interrupts; but we commit these updates to
+	 * Target hardware lazily, just before re-enabling
+	 * interrupts. So registers that we have now may not
+	 * reflect the intended state of interrupt enables.
+	 */
+
+	/* Based on software credit enable bits, update pnd_enb_intrs
+	 * (which is like a software copy of host_int_status) as if
+	 * all desired interrupt enables had been committed to HW.
+	 */
+	pending_int = req->u.reg_table.status.counter_int_status;
+	enabled_int = target->enb.counter_int_status_enb;
+	if (pending_int & enabled_int)
+		pnd_enb_intrs |= HOST_INT_STATUS_COUNTER_MASK;
+
+	/* Based on software recv data enable bits, update
+	 * pnd_enb_intrs AS IF all the interrupt enables had
+	 * been committed to HW.
+	 */
+	pending_int = host_int_status;
+	enabled_int = target->enb.int_status_enb;
+	pnd_enb_intrs |= (pending_int & enabled_int);
+
+	if (!pnd_enb_intrs) {
+		/* No enabled interrupts are pending. */
+		htca_debug_no_pending++;
+	}
+
+	/* Invoke specific handlers for each enabled and pending interrupt.
+	 * The goal of each service routine is to clear interrupts at the
+	 * source (on the Target).
+	 *
+	 * We deal with four types of interrupts in the HOST_INT_STATUS
+	 * summary register:
+	 * errors
+	 * This remains set until bits in ERROR_INT_STATUS are cleared
+	 *
+	 * CPU
+	 * This remains set until bits in CPU_INT_STATUS are cleared
+	 *
+	 * rx data available
+	 * These remain set as long as rx data is available. HW clears
+	 * the rx data available enable bits when receive buffers
+	 * are exhausted. If we exhaust Host-side received buffers, we
+	 * mask the rx data available interrupt.
+	 *
+	 * tx credits available
+	 * This remains set until all bits in COUNTER_INT_STATUS are
+	 * cleared by HW after Host SW reaps all credits on a mailbox.
+	 * If credits on an endpoint are sufficient, we mask the
+	 * corresponding COUNTER_INT_STATUS bit. We avoid "dribbling"
+	 * one credit at a time and instead reap them en masse.
+	 *
+	 * The HOST_INT_STATUS register is read-only these bits are cleared
+	 * by HW when the underlying condition is cleared.
+	 */
+
+	if (HOST_INT_STATUS_ERROR_GET(pnd_enb_intrs))
+		htca_service_error_interrupt(target, req);
+
+	if (HOST_INT_STATUS_CPU_GET(pnd_enb_intrs))
+		htca_service_cpu_interrupt(target, req);
+
+	if (HOST_INT_STATUS_COUNTER_GET(pnd_enb_intrs))
+		htca_service_credit_counter_interrupt(target, req);
+
+	/* Always needed in order to at least unmask Host interrupts */
+	htca_work_task_poke(target);
+}
+
+/* Complete an update of interrupt enables. */
+void htca_update_intr_enbs_compl(struct htca_target *target,
+				 struct htca_reg_request *req)
+{
+	htcadebug("Enter\n");
+	if (req->purpose == UPDATE_TARG_AND_ENABLE_HOST_INTRS) {
+		/* NB: non-intuitive, but correct */
+
+		/* While waiting for rxdata and txcred
+		 * interrupts to be disabled at the Target,
+		 * we temporarily masked interrupts at
+		 * the Host. It is now safe to allow
+		 * interrupts (esp. ERROR and CPU) at
+		 * the Host.
+		 */
+		htcadebug("Unmasking\n");
+		hif_un_mask_interrupt(target->hif_handle);
+	}
+}
+
+/* Called to complete htca_credit_refresh_start.
+ *
+ * Ends a credit refresh cycle. Called after decrementing a
+ * credit counter register (many times in a row). HW atomically
+ * decrements the counter and returns the OLD value but HW will
+ * never reduce it below 0.
+ *
+ * Called in the context of the work_task when the credit counter
+ * decrement operation completes synchronously. Called in the
+ * context of the compl_task when the credit counter decrement
+ * operation completes asynchronously.
+ */
+void htca_credit_refresh_compl(struct htca_target *target,
+			       struct htca_reg_request *reg_request)
+{
+	struct htca_endpoint *end_point;
+	unsigned long flags;
+	int reaped;
+	int i;
+
+	/* A non-zero value indicates 1 credit reaped.
+	 * Typically, we will find monotonically descending
+	 * values that reach 0 with the remaining values
+	 * all zero. But we must scan the entire results
+	 * to handle the case where the Target just happened
+	 * to increment credits simultaneously with our
+	 * series of credit decrement operations.
+	 */
+	htcadebug("ep=%d\n", reg_request->epid);
+	end_point = &target->end_point[reg_request->epid];
+	reaped = 0;
+	for (i = 0; i < HTCA_TX_CREDITS_REAP_MAX; i++) {
+		htcadebug("|R0x%02x", reg_request->u.credit_dec_results[i]);
+		if (reg_request->u.credit_dec_results[i])
+			reaped++;
+	}
+
+	htcadebug("\nreaped %d credits on ep=%d\n", reaped, reg_request->epid);
+
+	spin_lock_irqsave(&end_point->tx_credit_lock, flags);
+	end_point->tx_credits_available += reaped;
+	end_point->tx_credit_refresh_in_progress = false;
+	spin_unlock_irqrestore(&end_point->tx_credit_lock, flags);
+
+	htca_work_task_poke(target);
+}
diff --git a/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_events.c b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_events.c
new file mode 100644
index 0000000..d034277
--- /dev/null
+++ b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_events.c
@@ -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 <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/spinlock_types.h>
+#include <linux/wait.h>
+
+#include "../hif_sdio/hif.h"
+#include "htca.h"
+#include "htca_mbox_internal.h"
+
+/* Host Target Communications Event Management */
+
+/* Protect all event tables -- global as well as per-endpoint. */
+static spinlock_t event_lock; /* protects all event tables */
+
+/* Mapping table for global events -- avail/unavail */
+static struct htca_event_table_element
+	global_event_table[HTCA_EVENT_GLOBAL_COUNT];
+
+struct htca_event_table_element *
+htca_event_id_to_event(struct htca_target *target,
+		       u8 end_point_id,
+		       u8 event_id)
+{
+	struct htca_event_table_element *ev = NULL;
+
+	/* is ep event */
+	if ((event_id >= HTCA_EVENT_EP_START) &&
+	    (event_id <= HTCA_EVENT_EP_END)) {
+		struct htca_endpoint *end_point;
+		int ep_evid;
+
+		ep_evid = event_id - HTCA_EVENT_EP_START;
+		end_point = &target->end_point[end_point_id];
+		ev = &end_point->endpoint_event_tbl[ep_evid];
+	/* is global event */
+	} else if ((event_id >= HTCA_EVENT_GLOBAL_START) &&
+		   (event_id <= HTCA_EVENT_GLOBAL_END)) {
+		int global_evid;
+
+		global_evid = event_id - HTCA_EVENT_GLOBAL_START;
+		ev = &global_event_table[global_evid];
+	} else {
+		WARN_ON(1); /* unknown event */
+	}
+
+	return ev;
+}
+
+void htca_dispatch_event(struct htca_target *target,
+			 u8 end_point_id,
+			 u8 event_id,
+			 struct htca_event_info *event_info)
+{
+	struct htca_event_table_element *ev;
+
+	ev = htca_event_id_to_event(target, end_point_id, event_id);
+	if (!ev) {
+		panic("BUG");
+		return;
+	}
+	if (ev->handler) {
+		htca_event_handler handler;
+		void *param;
+		unsigned long flags;
+
+		spin_lock_irqsave(&event_lock, flags);
+		handler = ev->handler;
+		param = ev->param;
+		spin_unlock_irqrestore(&event_lock, flags);
+
+		handler((void *)target, end_point_id, event_id,
+			event_info, param);
+	}
+}
+
+int htca_add_to_event_table(struct htca_target *target,
+			    u8 end_point_id,
+			    u8 event_id,
+			    htca_event_handler handler, void *param) {
+	struct htca_event_table_element *ev;
+	unsigned long flags;
+
+	ev = htca_event_id_to_event(target, end_point_id, event_id);
+	if (!ev)
+		return HTCA_ERROR;
+
+	spin_lock_irqsave(&event_lock, flags);
+	ev->handler = handler;
+	ev->param = param;
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return HTCA_OK;
+}
+
+int htca_remove_from_event_table(struct htca_target *target,
+				 u8 end_point_id,
+				 u8 event_id) {
+	struct htca_event_table_element *ev;
+	unsigned long flags;
+
+	ev = htca_event_id_to_event(target, end_point_id, event_id);
+	if (!ev)
+		return HTCA_ERROR;
+
+	spin_lock_irqsave(&event_lock, flags);
+	/* Clear event handler info */
+	memset(ev, 0, sizeof(*ev));
+	spin_unlock_irqrestore(&event_lock, flags);
+
+	return HTCA_OK;
+}
+
+/* Called once during module initialization */
+void htca_event_table_init(void)
+{
+	spin_lock_init(&event_lock);
+}
diff --git a/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_internal.h b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_internal.h
new file mode 100644
index 0000000..b1c7c6b
--- /dev/null
+++ b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_internal.h
@@ -0,0 +1,581 @@
+/* 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 _HTCA_INTERNAL_H_
+#define _HTCA_INTERNAL_H_
+
+#include "mbox_host_reg.h"
+
+#if defined(DEBUG)
+#define htcadebug(fmt, a...) \
+	pr_err("htca %s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define htcadebug(args...)
+#endif
+
+/* HTCA internal specific declarations and prototypes */
+
+/* Target-side SDIO/SPI (mbox) controller supplies 4 mailboxes */
+#define HTCA_NUM_MBOX 4
+
+/* Software supports at most this many Target devices */
+#define HTCA_NUM_DEVICES_MAX 2
+
+/* Maximum supported mailbox message size.
+ *
+ * Quartz' SDIO/SPI mailbox alias spaces are 2KB each; so changes
+ * would be required to exceed that. WLAN restricts packets to
+ * under 1500B.
+ */
+#define HTCA_MESSAGE_SIZE_MAX 2048
+
+#define HTCA_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */
+
+/* The maximum number of credits that we will reap
+ * from the Target at one time.
+ */
+#define HTCA_TX_CREDITS_REAP_MAX 8
+
+/* Mailbox address in SDIO address space */
+#define MBOX_BASE_ADDR 0x800 /* Start of MBOX alias spaces */
+#define MBOX_WIDTH 0x800     /* Width of each mailbox alias space */
+
+#define MBOX_START_ADDR(mbox) (MBOX_BASE_ADDR + ((mbox) * (MBOX_WIDTH)))
+
+/* The byte just before this causes an EndOfMessage interrupt to be generated */
+#define MBOX_END_ADDR(mbox) (MBOX_START_ADDR(mbox) + MBOX_WIDTH)
+
+/* extended MBOX address for larger MBOX writes to MBOX 0 (not used) */
+#define MBOX0_EXTENDED_BASE_ADDR 0x2800
+#define MBOX0_EXTENDED_WIDTH (6 * 1024)
+
+/* HTCA message header */
+struct HTCA_header {
+	u16 total_msg_length;
+} __packed;
+
+#define HTCA_HEADER_LEN sizeof(struct HTCA_header)
+
+/* Populate an htca_event_info structure to be passed to
+ * a user's event handler.
+ */
+static inline void htca_frame_event(struct htca_event_info *event_info,
+				    u8 *buffer, size_t buffer_length,
+				    size_t actual_length, u32 status,
+				    void *cookie)
+{
+	if (event_info) {
+		event_info->buffer = buffer;
+		event_info->buffer_length = buffer_length;
+		event_info->actual_length = actual_length;
+		event_info->status = status;
+		event_info->cookie = cookie;
+	}
+}
+
+/* Global and endpoint-specific event tables use these to
+ * map an event ID --> handler + param.
+ */
+struct htca_event_table_element {
+	htca_event_handler handler;
+	void *param;
+};
+
+/* This layout MUST MATCH Target hardware layout! */
+struct htca_intr_status {
+	u8 host_int_status;
+	u8 cpu_int_status;
+	u8 err_int_status;
+	u8 counter_int_status;
+} __packed;
+
+/* This layout MUST MATCH Target hardware layout! */
+struct htca_intr_enables {
+	u8 int_status_enb;
+	u8 cpu_int_status_enb;
+	u8 err_status_enb;
+	u8 counter_int_status_enb;
+} __packed;
+
+/* The Register table contains Target SDIO/SPI interrupt/rxstatus
+ * registers used by HTCA. Rather than read particular registers,
+ * we use a bulk "register refresh" to read all at once.
+ *
+ * This layout MUST MATCH Target hardware layout!
+ */
+struct htca_register_table {
+	struct htca_intr_status status;
+
+	u8 mbox_frame;
+	u8 rx_lookahead_valid;
+	u8 hole[2];
+
+	/* Four lookahead bytes for each mailbox */
+	u32 rx_lookahead[HTCA_NUM_MBOX];
+} __packed;
+
+/* Two types of requests/responses are supported:
+ * "mbox requests" are messages or data which
+ * are sent to a Target mailbox
+ * "register requests" are to read/write Target registers
+ *
+ * Mbox requests are managed with a per-endpoint
+ * pending list and free list.
+ *
+ * Register requests are managed with a per-Target
+ * pending list and free list.
+ *
+ * A generic HTCA request -- one which is either an
+ * htca_mbox_request or an htca_reg_request is represented
+ * by an htca_request.
+ */
+
+/* Number of mbox_requests and reg_requests allocated initially.  */
+#define HTCA_MBOX_REQUEST_COUNT 16		   /* per mailbox */
+#define HTCA_REG_REQUEST_COUNT (4 * HTCA_NUM_MBOX) /* per target */
+
+/* An htca_request is at the start of a mbox_request structure
+ * and at the start of a reg_request structure.
+ *
+ * Specific request types may be cast to a generic htca_request
+ * (e.g. in order to invoke the completion callback function)
+ */
+struct htca_request {
+	/*struct htca_request*/ void *next; /* linkage */
+	struct htca_target *target;
+	void (*completion_cb)(struct htca_request *req, int status);
+	int status; /* completion status from HIF */
+};
+
+struct htca_endpoint; /* forward reference */
+
+/* Mailbox request -- a message or bulk data */
+struct htca_mbox_request {
+	struct htca_request req; /* Must be first -- (cast to htca_request) */
+
+	/* Caller-supplied cookie associated with this request */
+	void *cookie;
+
+	/* Pointer to the start of the buffer. In the transmit
+	 * direction this points to the start of the payload. In the
+	 * receive direction, however, the buffer when queued up
+	 * points to the start of the HTCA header but when returned
+	 * to the caller points to the start of the payload
+	 *
+	 * Note: buffer is set to NULL whenever this request is free.
+	 */
+	u8 *buffer;
+
+	/* length, in bytes, of the buffer */
+	u32 buffer_length;
+
+	/* length, in bytes, of the payload within the buffer */
+	u32 actual_length;
+
+	struct htca_endpoint *end_point;
+};
+
+/* Round up a value (e.g. length) to a power of 2 (e.g. block size).  */
+static inline u32 htca_round_up(u32 value, u32 pwrof2)
+{
+	return (((value) + (pwrof2) - 1) & ~((pwrof2) - 1));
+}
+
+/* Indicates reasons that we might access Target register space */
+enum htca_req_purpose {
+	UNUSED_PURPOSE,
+	INTR_REFRESH,	/* Fetch latest interrupt/status registers */
+	CREDIT_REFRESH, /* Reap credits */
+	UPDATE_TARG_INTRS,
+	UPDATE_TARG_AND_ENABLE_HOST_INTRS,
+};
+
+/* Register read request -- used to read registers from SDIO/SPI space.
+ * Register writes are fire and forget; no completion is needed.
+ *
+ */
+struct htca_reg_request {
+	struct htca_request req; /* Must be first -- (cast to htca_request) */
+	u8 *buffer;	 /* register value(s) */
+	u32 length;
+
+	/* Indicates the purpose this request was made */
+	enum htca_req_purpose purpose;
+
+	/* Which endpoint this read is for.
+	 * Used when processing a completed credit refresh request.
+	 */
+	u8 epid; /* which endpoint ID [0..3] */
+
+	/* A read to Target register space returns
+	 * one specific Target register value OR
+	 * all values in the register_table OR
+	 * a special repeated read-and-dec from a credit register
+	 *
+	 * FUTURE: We could separate these into separate request
+	 * types in order to perhaps save a bit of space....
+	 * eliminate the union.
+	 */
+	union {
+		struct htca_intr_enables enb;
+		struct htca_register_table reg_table;
+		u8 credit_dec_results[HTCA_TX_CREDITS_REAP_MAX];
+	} u;
+};
+
+struct htca_request_queue {
+	struct htca_request *head;
+	struct htca_request *tail;
+};
+
+#define HTCA_IS_QUEUE_EMPTY(q) (!((q)->head))
+
+/* List of Target registers in SDIO/SPI space which can be accessed by Host */
+enum target_registers {
+	UNUSED_REG = 0,
+	INTR_ENB_REG = INT_STATUS_ENABLE_ADDRESS,
+	ALL_STATUS_REG = HOST_INT_STATUS_ADDRESS,
+	ERROR_INT_STATUS_REG = ERROR_INT_STATUS_ADDRESS,
+	CPU_INT_STATUS_REG = CPU_INT_STATUS_ADDRESS,
+	TX_CREDIT_COUNTER_DECREMENT_REG = COUNT_DEC_ADDRESS,
+	INT_TARGET_REG = INT_TARGET_ADDRESS,
+};
+
+static inline u32 get_reg_addr(enum target_registers which,
+			       u8 epid)
+{
+	return (((which) == TX_CREDIT_COUNTER_DECREMENT_REG)
+	     ? (COUNT_DEC_ADDRESS + (HTCA_NUM_MBOX + (epid)) * 4)
+	     : (which));
+}
+
+/* FUTURE: See if we can use lock-free operations
+ * to manage credits and linked lists.
+ * FUTURE: Use standard Linux queue ops; ESPECIALLY
+ * if they support lock-free operation.
+ */
+
+/* One of these per endpoint */
+struct htca_endpoint {
+	/* Enabled or Disabled */
+	bool enabled;
+
+	/* If data is available, rxLengthPending
+	 * indicates the length of the incoming message.
+	 */
+	u32 rx_frame_length; /* incoming frame length on this endpoint */
+	/* includes HTCA header */
+	/* Modified only by compl_task */
+
+	bool rx_data_alerted; /* Caller was sent a BUFFER_AVAILABLE event */
+	/* and has not supplied a new recv buffer */
+	/* since that warning was sent.  */
+	/* Modified only by work_task */
+
+	bool tx_credits_to_reap; /* At least one credit available at the */
+	/* Target waiting to be reaped. */
+	/* Modified only by compl_task */
+
+	/* Guards tx_credits_available and tx_credit_refresh_in_progress */
+	spinlock_t tx_credit_lock;
+
+	/* The number of credits that we have already reaped
+	 * from the Target. (i.e. we have decremented the Target's
+	 * count register so that we have ability to send future
+	 * messages). We have the ability to send tx_credits_available
+	 * messages without blocking.
+	 *
+	 * The size of a message is endpoint-dependent and always
+	 * a multiple of the device's block_size.
+	 */
+	u32 tx_credits_available;
+
+	/* Maximum message size */
+	u32 max_msg_sz;
+
+	/* Indicates that we are in the midst of a credit refresh cycle */
+	bool tx_credit_refresh_in_progress;
+
+	/* Free/Pending Send/Recv queues are used for mbox requests.
+	 * An mbox Send request cannot be given to HIF until we have
+	 * a tx credit. An mbox Recv request cannot be given to HIF
+	 * until we have a pending rx msg.
+	 *
+	 * The HIF layer maintains its own queue of requests, which
+	 * it uses to serialize access to SDIO. Its queue contains
+	 * a mixture of sends/recvs and mbox/reg requests. HIF is
+	 * "beyond" flow control so once a requets is given to HIF
+	 * it is guaranteed to complete (after all previous requests
+	 * complete).
+	 */
+
+	/* Guards Free/Pending send/recv queues */
+	spinlock_t mbox_queue_lock;
+	struct htca_request_queue send_free_queue;
+	struct htca_request_queue send_pending_queue;
+	struct htca_request_queue recv_free_queue;
+	struct htca_request_queue recv_pending_queue;
+
+	/* Inverse reference to the target */
+	struct htca_target *target;
+
+	/* Block size configured for the endpoint -- common across all endpoints
+	 */
+	u32 block_size;
+
+	/* Mapping table for per-endpoint events */
+	struct htca_event_table_element endpoint_event_tbl[HTCA_EVENT_EP_COUNT];
+
+	/* Location of the endpoint's mailbox space */
+	u32 mbox_start_addr;
+	u32 mbox_end_addr;
+};
+
+#define ENDPOINT_UNUSED 0
+
+/* Target interrupt states. */
+enum intr_state_e {
+	/* rxdata and txcred interrupts enabled.
+	 * Only the DSR context can switch us to
+	 * polled state.
+	 */
+	HTCA_INTERRUPT,
+
+	/* rxdata and txcred interrupts are disabled.
+	 * We are polling (via RegisterRefresh).
+	 * Only the work_task can switch us to
+	 * interrupt state.
+	 */
+	HTCA_POLL,
+};
+
+/* One of these per connected QCA402X device. */
+struct htca_target {
+	/* Target device is initialized and ready to go?
+	 * This has little o do with Host state;
+	 * it reflects readiness of the Target.
+	 */
+	bool ready;
+
+	/* Handle passed to HIF layer for SDIO/SPI Host controller access */
+	void *hif_handle; /* hif_device */
+
+	/* Per-endpoint info */
+	struct htca_endpoint end_point[HTCA_NUM_MBOX];
+
+	/* Used during startup while the Host waits for the
+	 * Target to initialize.
+	 */
+	wait_queue_head_t target_init_wait;
+
+	/* Free queue for htca_reg_requests.
+	 *
+	 * We don't need a regPendingQueue because reads/writes to
+	 * Target register space are not flow controlled by the Target.
+	 * There is no need to wait for credits in order to hand off a
+	 * register read/write to HIF.
+	 *
+	 * The register read/write may end up queued in a HIF queue
+	 * behind both register and mbox reads/writes that were
+	 * handed to HIF earlier. But they will never be queued
+	 * by HTCA.
+	 */
+	spinlock_t reg_queue_lock;
+	struct htca_request_queue reg_free_queue;
+
+	/* comp task synchronization */
+	struct mutex task_mutex;
+
+	struct task_struct *work_task;
+	struct task_struct *compl_task;
+
+	/* work_task synchronization */
+	wait_queue_head_t work_task_wait; /* wait for work to do */
+	bool work_task_has_work;	  /* work available? */
+	bool work_task_shutdown;	  /* requested stop? */
+	struct completion work_task_completion;
+
+	/* compl_task synchronization */
+	wait_queue_head_t compl_task_wait; /* wait for work to do */
+	bool compl_task_has_work;	   /* work available? */
+	bool compl_task_shutdown;	   /* requested stop? */
+	struct completion compl_cask_completion;
+
+	/* Queue of completed mailbox and register requests */
+	spinlock_t compl_queue_lock;
+	struct htca_request_queue compl_queue;
+
+	/* Software's shadow copy of interrupt enables.
+	 * Only the work_task changes intr_enable bits,
+	 * so no locking necessary.
+	 *
+	 * Committed to Target HW when
+	 * we convert from polling to interrupts or
+	 * we are using interrupts and enables have changed
+	 */
+	struct htca_intr_enables enb;
+	struct htca_intr_enables last_committed_enb;
+
+	enum intr_state_e intr_state;
+	int need_start_polling;
+
+	/* Set after we read data from a mailbox (to
+	 * update lookahead and mailbox status bits).
+	 * used only by work_task even though refreshes
+	 * may be started in other contexts.
+	 */
+	int need_register_refresh;
+
+	/* Guards pending_register_refresh and pending_recv_mask */
+	spinlock_t pending_op_lock;
+
+	/* Incremented when a RegisterRefresh is started;
+	 * Decremented when it completes.
+	 */
+	int pending_register_refresh;
+
+	/* Non-zero if a recv operation has been started
+	 * but not yet completed. 1 bit for each ep.
+	 */
+	int pending_recv_mask;
+};
+
+/* Convert an endpoint POINTER into an endpoint ID [0..3] */
+static inline u32 get_endpoint_id(struct htca_endpoint *ep)
+{
+	return (u32)(ep - ep->target->end_point);
+}
+
+void htca_receive_frame(struct htca_endpoint *end_point);
+
+u32 htca_get_frame_length(struct htca_endpoint *end_point);
+
+void htca_send_frame(struct htca_endpoint *end_point);
+
+void htca_send_blk_size(struct htca_endpoint *end_point);
+
+int htca_rw_completion_handler(void *req, int status);
+
+void htca_send_compl(struct htca_request *req, int status);
+
+void htca_recv_compl(struct htca_request *req, int status);
+
+void htca_reg_compl(struct htca_request *req, int status);
+
+int htca_target_inserted_handler(void *context,
+				 void *hif_handle);
+
+int htca_target_removed_handler(void *context, void *hif_handle);
+
+int htca_dsr_handler(void *target_ctxt);
+
+void htca_service_cpu_interrupt(struct htca_target *target,
+				struct htca_reg_request *req);
+
+void htca_service_error_interrupt(struct htca_target *target,
+				  struct htca_reg_request *req);
+
+void htca_service_credit_counter_interrupt(struct htca_target *target,
+					   struct htca_reg_request *req);
+
+void htca_enable_credit_counter_interrupt(struct htca_target *target,
+					  u8 end_point_id);
+
+void htca_disable_credit_counter_interrupt(struct htca_target *target,
+					   u8 end_point_id);
+
+int htca_add_to_mbox_queue(struct htca_mbox_request *queue,
+			   u8 *buffer,
+			   u32 buffer_length,
+			   u32 actual_length, void *cookie);
+
+struct htca_mbox_request *
+htca_remove_from_mbox_queue(struct htca_mbox_request *queue);
+
+void htca_mbox_queue_flush(struct htca_endpoint *end_point,
+			   struct htca_request_queue *pending_queue,
+			   struct htca_request_queue *free_queue,
+			   u8 event_id);
+
+int htca_add_to_event_table(struct htca_target *target,
+			    u8 end_point_id,
+			    u8 event_id,
+			    htca_event_handler handler,
+			    void *param);
+
+int htca_remove_from_event_table(struct htca_target *target,
+				 u8 end_point_id,
+				 u8 event_id);
+
+void htca_dispatch_event(struct htca_target *target,
+			 u8 end_point_id,
+			 u8 event_id,
+			 struct htca_event_info *event_info);
+
+struct htca_target *htca_target_instance(int i);
+
+void htca_target_instance_add(struct htca_target *target);
+
+void htca_target_instance_remove(struct htca_target *target);
+
+u8 htca_get_bit_num_set(u32 data);
+
+void htca_register_refresh(struct htca_target *target);
+
+void free_request(struct htca_request *req,
+		  struct htca_request_queue *queue);
+
+extern struct htca_target *htca_target_list[HTCA_NUM_DEVICES_MAX];
+
+int htca_work_task_start(struct htca_target *target);
+int htca_compl_task_start(struct htca_target *target);
+void htca_work_task_stop(struct htca_target *target);
+void htca_compl_task_stop(struct htca_target *target);
+void htca_work_task_poke(struct htca_target *target);
+void htca_compl_task_poke(struct htca_target *target);
+
+void htca_event_table_init(void);
+struct htca_event_table_element *
+htca_event_id_to_event(struct htca_target *target,
+		       u8 end_point_id,
+		       u8 event_id);
+
+void htca_request_enq_tail(struct htca_request_queue *queue,
+			   struct htca_request *req);
+struct htca_request *htca_request_deq_head(struct htca_request_queue *queue);
+
+void htca_register_refresh_start(struct htca_target *target);
+void htca_register_refresh_compl(struct htca_target *target,
+				 struct htca_reg_request *req);
+
+int htca_credit_refresh_start(struct htca_endpoint *end_point);
+void htca_credit_refresh_compl(struct htca_target *target,
+			       struct htca_reg_request *req);
+
+void htca_update_intr_enbs(struct htca_target *target,
+			   int enable_host_intrs);
+void htca_update_intr_enbs_compl(struct htca_target *target,
+				 struct htca_reg_request *req);
+
+bool htca_negotiate_config(struct htca_target *target);
+
+int htca_recv_request_to_hif(struct htca_endpoint *end_point,
+			     struct htca_mbox_request *mbox_request);
+int htca_send_request_to_hif(struct htca_endpoint *endpoint,
+			     struct htca_mbox_request *mbox_request);
+
+int htca_manage_pending_sends(struct htca_target *target, int epid);
+int htca_manage_pending_recvs(struct htca_target *target, int epid);
+
+void _htca_stop(struct htca_target *target);
+
+#endif /* _HTCA_INTERNAL_H_ */
diff --git a/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_intr.c b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_intr.c
new file mode 100644
index 0000000..0486f59
--- /dev/null
+++ b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_intr.c
@@ -0,0 +1,627 @@
+/* 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/completion.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/spinlock_types.h>
+#include <linux/wait.h>
+
+#include "../hif_sdio/hif.h"
+#include "htca.h"
+#include "htca_mbox_internal.h"
+
+/* Host Target Communications Interrupt Management */
+
+/* Interrupt Management
+ * When an interrupt occurs at the Host, it is to tell us about
+ * a high-priority error interrupt
+ * a CPU interrupt (TBD)
+ * rx data available
+ * tx credits available
+ *
+ * From an interrupt management perspective, rxdata and txcred
+ * interrupts are grouped together. When either of these occurs,
+ * we enter a mode where we repeatedly refresh register state
+ * and act on all interrupt information in the refreshed registers.
+ * We are basically polling with rxdata and txcred interrupts
+ * masked. Eventually, we refresh registers and find no rxdata
+ * and no txcred interrupts pending. At this point, we unmask
+ * those types of interrupts.
+ *
+ * Unmasking is selective: We unmask only the interrupts that
+ * we want to receive which include
+ * -rxdata interrupts for endpoints that have received
+ * buffers on the recv pending queue
+ * -txcred interrupts for endpoints with a very low
+ * count of creditsAvailable
+ * Other rxdata and txcred interrupts are masked. These include:
+ * -rxdata interrupts for endpoint that lack recv buffers
+ * -txcred interrupts for endpoint with lots of credits
+ *
+ * Very little activity takes place in the context of the
+ * interrupt function (Delayed Service Routine). We mask
+ * interrupts at the Host, send a command to disable all
+ * rxdata/txcred interrupts and finally start a register
+ * refresh. When the register refresh completes, we unmask
+ * interrupts on the Host and poke the work_task which now
+ * has valid register state to examine.
+ *
+ * The work_task repeatedly
+ * handles outstanding rx and tx service
+ * starts another register refresh
+ * Every time a register refresh completes, it pokes the
+ * work_task. This cycle continues until the work_task finds
+ * nothing to do after a register refresh. At this point,
+ * it unmasks rxdata/txcred interrupts at the Target (again,
+ * selectively).
+ *
+ * While in the work_task polling cycle, we maintain a notion
+ * of interrupt enables in software rather than commit these
+ * to Target HW.
+ *
+ *
+ * Credit State Machine:
+ * Credits are
+ * -Added by the Target whenever a Target-side receive
+ * buffer is added to a mailbox
+ * -Never rescinded by the Target
+ * -Reaped by this software after a credit refresh cycle
+ * which is initiated
+ * -as a result of a credit counter interrupt
+ * -after a send completes and the number of credits
+ * are below an acceptable threshold
+ * -used by this software when it sends a message HIF to
+ * be sent to the Target
+ *
+ * The process of "reaping" credits involves first issuing
+ * a sequence of reads to the COUNTER_DEC register. (This is
+ * known as the start of a credit refresh.) We issue a large
+ * number of reads in order to reap as many credits at once
+ * as we can. When these reads complete, we determine how
+ * many credits were available and increase software's notion
+ * of tx_credits_available accordingly.
+ *
+ * Note: All Target reads/writes issued from the interrupt path
+ * should be asynchronous. HIF adds such a request to a queue
+ * and immediately returns.
+ *
+ * TBD: It might be helpful for HIF to support a "priority
+ * queue" -- requests that should be issued prior to anything
+ * in its normal queue. Even with this, a request might have
+ * to wait for a while as the current, read/write request
+ * completes on SDIO and then wait for all prior priority
+ * requests to finish. So probably not worth the additional
+ * complexity.
+ */
+
+/* Maximum message sizes for each endpoint.
+ * Must be a multiple of the block size.
+ * Must be no greater than HTCA_MESSAGE_SIZE_MAX.
+ *
+ * TBD: These should be tunable. Example anticipated usage:
+ * ep0: Host-side networking control messages
+ * ep1: Host-side networking data messages
+ * ep2: OEM control messages
+ * ep3: OEM data messages
+ */
+static u32 htca_msg_size[HTCA_NUM_MBOX] = {256, 3 * 512, 512, 2048};
+
+/* Commit the shadow interrupt enables in software to
+ * Target Hardware. This is where the "lazy commit"
+ * occurs. Always called in the context of work_task.
+ *
+ * When the host's intr_state is POLL:
+ * -All credit count interrupts and all rx data interrupts
+ * are disabled at the Target.
+ *
+ * When the host's intr_state is INTERRUPT:
+ * -We commit the shadow copy of interrupt enables.
+ * -A mailbox with low credit count will have the credit
+ * interrupt enabled. A mailbox with high credit count
+ * will have the credit interrupt disabled.
+ * -A mailbox with no available receive buffers will have
+ * the mailbox data interrupt disabled. A mailbox with
+ * at least one receive buffer will have the mailbox
+ * data interrupt enabled.
+ */
+void htca_update_intr_enbs(struct htca_target *target,
+			   int enable_host_intrs)
+{
+	int status;
+	struct htca_reg_request *reg_request;
+	struct htca_intr_enables *enbregs;
+	unsigned long flags;
+	u32 address;
+
+	htcadebug("Enter: enable_host_intrs=%d\n",
+		  enable_host_intrs);
+	htcadebug("ints: 0x%02x  --> 0x%02x\n",
+		  target->last_committed_enb.int_status_enb,
+		  target->enb.int_status_enb);
+	htcadebug("cpu: 0x%02x	--> 0x%02x\n",
+		  target->last_committed_enb.cpu_int_status_enb,
+		  target->enb.cpu_int_status_enb);
+	htcadebug("error: 0x%02x  --> 0x%02x\n",
+		  target->last_committed_enb.err_status_enb,
+		  target->enb.err_status_enb);
+	htcadebug("counters: 0x%02x  --> 0x%02x\n",
+		  target->last_committed_enb.counter_int_status_enb,
+		  target->enb.counter_int_status_enb);
+	if ((target->enb.int_status_enb ==
+			target->last_committed_enb.int_status_enb) &&
+		(target->enb.counter_int_status_enb ==
+			target->last_committed_enb.counter_int_status_enb) &&
+		(target->enb.cpu_int_status_enb ==
+			target->last_committed_enb.cpu_int_status_enb) &&
+		(target->enb.err_status_enb ==
+			target->last_committed_enb.err_status_enb)) {
+		/* No changes to Target-side interrupt enables are required.
+		 * But we must still need to enable Host-side interrupts.
+		 */
+		if (enable_host_intrs) {
+			htcadebug("Unmasking - no change to Target enables\n");
+			hif_un_mask_interrupt(target->hif_handle);
+		}
+		return;
+	}
+
+	spin_lock_irqsave(&target->reg_queue_lock, flags);
+	reg_request = (struct htca_reg_request *)htca_request_deq_head(
+	    &target->reg_free_queue);
+	spin_unlock_irqrestore(&target->reg_queue_lock, flags);
+	if (!reg_request) {
+		WARN_ON(1);
+		return;
+	}
+	if (WARN_ON(reg_request->purpose != UNUSED_PURPOSE))
+		return;
+
+	reg_request->buffer = NULL;
+	reg_request->length = 0;
+	reg_request->epid = 0; /* unused */
+	enbregs = &reg_request->u.enb;
+
+	if (target->intr_state == HTCA_INTERRUPT) {
+		enbregs->int_status_enb = target->enb.int_status_enb;
+		enbregs->counter_int_status_enb =
+		    target->enb.counter_int_status_enb;
+	} else {
+		enbregs->int_status_enb = (target->enb.int_status_enb &
+					   ~HOST_INT_STATUS_MBOX_DATA_MASK);
+		enbregs->counter_int_status_enb = 0;
+	}
+
+	enbregs->cpu_int_status_enb = target->enb.cpu_int_status_enb;
+	enbregs->err_status_enb = target->enb.err_status_enb;
+
+	target->last_committed_enb = *enbregs; /* structure copy */
+
+	if (enable_host_intrs)
+		reg_request->purpose = UPDATE_TARG_AND_ENABLE_HOST_INTRS;
+	else
+		reg_request->purpose = UPDATE_TARG_INTRS;
+
+	address = get_reg_addr(INTR_ENB_REG, ENDPOINT_UNUSED);
+
+	status = hif_read_write(target->hif_handle, address, enbregs,
+				sizeof(*enbregs), HIF_WR_ASYNC_BYTE_INC,
+				reg_request);
+	if (status == HIF_OK && reg_request->req.completion_cb) {
+		reg_request->req.completion_cb(
+		    (struct htca_request *)reg_request, HIF_OK);
+		/* htca_update_intr_enbs_compl */
+	} else if (status == HIF_PENDING) {
+		/* Will complete later */
+	} else { /* HIF error */
+		WARN_ON(1);
+	}
+}
+
+/* Delayed Service Routine, invoked from HIF in thread context
+ * (from sdio's irqhandler) in order to handle interrupts
+ * caused by the Target.
+ *
+ * This serves as a top-level interrupt dispatcher for HTCA.
+ */
+int htca_dsr_handler(void *htca_handle)
+{
+	struct htca_target *target = (struct htca_target *)htca_handle;
+
+	htcadebug("Enter\n");
+	if (target->ready) {
+		/* Transition state to polling mode.
+		 * Temporarily disable intrs at Host
+		 * until interrupts are stopped in
+		 * Target HW.
+		 */
+		htcadebug("Masking interrupts\n");
+		hif_mask_interrupt(target->hif_handle);
+		target->need_start_polling = 1;
+
+		/* Kick off a register refresh so we
+		 * use updated registers in order to
+		 * figure out what needs to be serviced.
+		 *
+		 * RegisterRefresh completion wakes the
+		 * work_task which re-enables Host-side
+		 * interrupts.
+		 */
+		htca_register_refresh_start(target);
+	} else { /* startup time */
+		 /* Assumption is that we are receiving an interrupt
+		  * because the Target made a TX Credit available
+		  * on each endpoint (for configuration negotiation).
+		  */
+
+		hif_mask_interrupt(target->hif_handle);
+		if (htca_negotiate_config(target)) {
+			/* All endpoints are configured.
+			 * Target is now ready for normal operation.
+			 */
+			/* TBDXXX - Fix Quartz-side and remove this */
+			{
+				/* HACK: Signal Target to read mbox Cfg info.
+				 * TBD: Target should use EOM rather than an
+				 * an explicit Target Interrupt for this.
+				 */
+				u8 my_targ_int;
+				u32 address;
+				int status;
+
+				/* Set HTCA_INT_TARGET_INIT_HOST_REQ */
+				my_targ_int = 1;
+
+				address =
+				    get_reg_addr(
+					INT_TARGET_REG, ENDPOINT_UNUSED);
+				status = hif_read_write(
+				    target->hif_handle, address, &my_targ_int,
+				    sizeof(my_targ_int), HIF_WR_SYNC_BYTE_INC,
+				    NULL);
+				if (WARN_ON(status != HIF_OK))
+					return status;
+			}
+			target->ready = true;
+			htcadebug("HTCA TARGET IS READY\n");
+			wake_up(&target->target_init_wait);
+		}
+		hif_un_mask_interrupt(target->hif_handle);
+	}
+	return HTCA_OK;
+}
+
+/* Handler for CPU interrupts that are explicitly
+ * initiated by Target firmware. Not used by system firmware today.
+ */
+void htca_service_cpu_interrupt(struct htca_target *target,
+				struct htca_reg_request *req)
+{
+	int status;
+	u32 address;
+	u8 cpu_int_status;
+
+	htcadebug("Enter\n");
+	cpu_int_status = req->u.reg_table.status.cpu_int_status &
+			 target->enb.cpu_int_status_enb;
+
+	/* Clear pending interrupts on Target -- Write 1 to Clear */
+	address = get_reg_addr(CPU_INT_STATUS_REG, ENDPOINT_UNUSED);
+
+	status =
+	    hif_read_write(target->hif_handle, address, &cpu_int_status,
+			   sizeof(cpu_int_status), HIF_WR_SYNC_BYTE_INC, NULL);
+
+	WARN_ON(status != HIF_OK);
+
+	/* Handle cpu_int_status actions here. None are currently used */
+}
+
+/* Handler for error interrupts on Target.
+ * If everything is working properly we hope never to see these.
+ */
+void htca_service_error_interrupt(struct htca_target *target,
+				  struct htca_reg_request *req)
+{
+	int status = HIF_ERROR;
+	u32 address;
+	u8 err_int_status;
+	struct htca_endpoint *end_point;
+
+	htcadebug("Enter\n");
+	err_int_status =
+	    req->u.reg_table.status.err_int_status & target->enb.err_status_enb;
+
+	end_point = &target->end_point[req->epid];
+	htcadebug("epid=%d txCreditsAvailable=%d\n",
+		  (int)req->epid, end_point->tx_credits_available);
+	htcadebug("statusregs host=0x%02x cpu=0x%02x err=0x%02x cnt=0x%02x\n",
+		  req->u.reg_table.status.host_int_status,
+		  req->u.reg_table.status.cpu_int_status,
+		  req->u.reg_table.status.err_int_status,
+		  req->u.reg_table.status.counter_int_status);
+
+	/* Clear pending interrupts on Target -- Write 1 to Clear */
+	address = get_reg_addr(ERROR_INT_STATUS_REG, ENDPOINT_UNUSED);
+	status =
+	    hif_read_write(target->hif_handle, address, &err_int_status,
+			   sizeof(err_int_status), HIF_WR_SYNC_BYTE_INC, NULL);
+
+	if (WARN_ON(status != HIF_OK))
+		return;
+
+	if (ERROR_INT_STATUS_WAKEUP_GET(err_int_status)) {
+		/* Wakeup */
+		htcadebug("statusregs host=0x%x\n",
+			  ERROR_INT_STATUS_WAKEUP_GET(err_int_status));
+		/* Nothing needed here */
+	}
+
+	if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(err_int_status)) {
+		/* TBD: Rx Underflow */
+		/* Host posted a read to an empty mailbox? */
+		/* Target DMA was not able to keep pace with Host reads? */
+		if (WARN_ON(2)) /* TBD */
+			return;
+	}
+
+	if (ERROR_INT_STATUS_TX_OVERFLOW_GET(err_int_status)) {
+		/* TBD: Tx Overflow */
+		/* Host posted a write to a mailbox with no credits? */
+		/* Target DMA was not able to keep pace with Host writes? */
+		if (WARN_ON(1)) /* TBD */
+			return;
+	}
+}
+
+/* Handler for Credit Counter interrupts from Target.
+ *
+ * This occurs when the number of credits available on a mailbox
+ * increases from 0 to non-zero. (i.e. when Target firmware queues a
+ * DMA Receive buffer to an endpoint that previously had no buffers.)
+ *
+ * This interrupt is masked when we have a sufficient number of
+ * credits available. It is unmasked only when we have reaped all
+ * available credits and are still below a desired threshold.
+ */
+void htca_service_credit_counter_interrupt(struct htca_target *target,
+					   struct htca_reg_request *req)
+{
+	struct htca_endpoint *end_point;
+	u8 counter_int_status;
+	u8 eps_with_credits;
+	int ep;
+
+	htcadebug("Enter\n");
+	counter_int_status = req->u.reg_table.status.counter_int_status;
+
+	/* Service the credit counter interrupt.
+	 * COUNTER bits [4..7] are used for credits on endpoints [0..3].
+	 */
+	eps_with_credits =
+	    counter_int_status & target->enb.counter_int_status_enb;
+	htcadebug("eps_with_credits=0x%02x\n", eps_with_credits);
+	htcadebug("counter_int_status=0x%02x\n", counter_int_status);
+	htcadebug("counter_int_status_enb=0x%02x\n",
+		  target->enb.counter_int_status_enb);
+
+	for (ep = 0; ep < HTCA_NUM_MBOX; ep++) {
+		if (!(eps_with_credits & (0x10 << ep)))
+			continue;
+
+		end_point = &target->end_point[ep];
+
+		/* We need credits on this endpoint AND
+		 * the target tells us that there are some.
+		 * Start a credit refresh cycle on this
+		 * endpoint.
+		 */
+		(void)htca_credit_refresh_start(end_point);
+	}
+}
+
+/* Callback registered with HIF to be invoked when Target
+ * presence is first detected.
+ *
+ * Allocate memory for Target, endpoints, requests, etc.
+ */
+int htca_target_inserted_handler(void *unused_context,
+				 void *hif_handle)
+{
+	struct htca_target *target;
+	struct htca_endpoint *end_point;
+	int ep;
+	struct htca_event_info event_info;
+	struct htca_request_queue *send_free_queue, *recv_free_queue;
+	struct htca_request_queue *reg_queue;
+	u32 block_size[HTCA_NUM_MBOX];
+	struct cbs_from_hif htca_callbacks; /* Callbacks from HIF to HTCA */
+	int status = HTCA_OK;
+	int i;
+
+	htcadebug("Enter\n");
+
+	target = kzalloc(sizeof(*target), GFP_KERNEL);
+	/* target->ready = false; */
+
+	/* Give a handle to HIF for this target */
+	target->hif_handle = hif_handle;
+	hif_set_handle(hif_handle, (void *)target);
+
+	/* Register htca_callbacks from HIF */
+	memset(&htca_callbacks, 0, sizeof(htca_callbacks));
+	htca_callbacks.rw_completion_hdl = htca_rw_completion_handler;
+	htca_callbacks.dsr_hdl = htca_dsr_handler;
+	htca_callbacks.context = target;
+	(void)hif_attach(hif_handle, &htca_callbacks);
+
+	/* Get block sizes and start addresses for each mailbox */
+	hif_configure_device(hif_handle,
+			     HIF_DEVICE_GET_MBOX_BLOCK_SIZE, &block_size,
+			     sizeof(block_size));
+
+	/* Initial software copies of interrupt enables */
+	target->enb.int_status_enb =
+	    INT_STATUS_ENABLE_ERROR_MASK | INT_STATUS_ENABLE_CPU_MASK |
+	    INT_STATUS_ENABLE_COUNTER_MASK | INT_STATUS_ENABLE_MBOX_DATA_MASK;
+
+	/* All 8 CPU interrupts enabled */
+	target->enb.cpu_int_status_enb = CPU_INT_STATUS_ENABLE_BIT_MASK;
+
+	target->enb.err_status_enb = ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK |
+				     ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK;
+
+	/* credit counters in upper bits */
+	target->enb.counter_int_status_enb = COUNTER_INT_STATUS_ENABLE_BIT_MASK;
+
+	spin_lock_init(&target->reg_queue_lock);
+	spin_lock_init(&target->compl_queue_lock);
+	spin_lock_init(&target->pending_op_lock);
+	mutex_init(&target->task_mutex);
+
+	status = htca_work_task_start(target);
+	if (status != HTCA_OK)
+		goto done;
+
+	status = htca_compl_task_start(target);
+	if (status != HTCA_OK)
+		goto done;
+
+	/* Initialize the register request free list */
+	reg_queue = &target->reg_free_queue;
+	for (i = 0; i < HTCA_REG_REQUEST_COUNT; i++) {
+		struct htca_reg_request *reg_request;
+
+		/* Add a reg_request to the Reg Free Queue */
+		reg_request = kzalloc(sizeof(*reg_request), GFP_DMA);
+		reg_request->req.target = target;
+		reg_request->req.completion_cb = htca_reg_compl;
+
+		/* no lock required -- startup */
+		htca_request_enq_tail(reg_queue,
+				      (struct htca_request *)reg_request);
+	}
+
+	/* Initialize endpoints, mbox queues and event tables */
+	for (ep = 0; ep < HTCA_NUM_MBOX; ep++) {
+		end_point = &target->end_point[ep];
+
+		spin_lock_init(&end_point->tx_credit_lock);
+		spin_lock_init(&end_point->mbox_queue_lock);
+
+		end_point->tx_credits_available = 0;
+		end_point->max_msg_sz = htca_msg_size[ep];
+		end_point->rx_frame_length = 0;
+		end_point->tx_credits_to_reap = false;
+		end_point->target = target;
+		end_point->enabled = false;
+		end_point->block_size = block_size[ep];
+		end_point->mbox_start_addr = MBOX_START_ADDR(ep);
+		end_point->mbox_end_addr = MBOX_END_ADDR(ep);
+
+		/* Initialize per-endpoint queues */
+		end_point->send_pending_queue.head = NULL;
+		end_point->send_pending_queue.tail = NULL;
+		end_point->recv_pending_queue.head = NULL;
+		end_point->recv_pending_queue.tail = NULL;
+
+		send_free_queue = &end_point->send_free_queue;
+		recv_free_queue = &end_point->recv_free_queue;
+		for (i = 0; i < HTCA_MBOX_REQUEST_COUNT; i++) {
+			struct htca_mbox_request *mbox_request;
+
+			/* Add an mbox_request to the mbox SEND Free Queue */
+			mbox_request = kzalloc(sizeof(*mbox_request),
+					       GFP_KERNEL);
+			mbox_request->req.target = target;
+			mbox_request->req.completion_cb = htca_send_compl;
+			mbox_request->end_point = end_point;
+			htca_request_enq_tail(
+			    send_free_queue,
+			    (struct htca_request *)mbox_request);
+
+			/* Add an mbox_request to the mbox RECV Free Queue */
+			mbox_request = kzalloc(sizeof(*mbox_request),
+					       GFP_KERNEL);
+			mbox_request->req.target = target;
+			mbox_request->req.completion_cb = htca_recv_compl;
+			mbox_request->end_point = end_point;
+			htca_request_enq_tail(
+			    recv_free_queue,
+			    (struct htca_request *)mbox_request);
+		}
+	}
+
+	/* Target and endpoint structures are now completely initialized.
+	 * Add the target instance to the global list of targets.
+	 */
+	htca_target_instance_add(target);
+
+	/* Frame a TARGET_AVAILABLE event and send it to
+	 * the caller. Return the hif_device handle as a
+	 * parameter with the event.
+	 */
+	htca_frame_event(&event_info, (u8 *)hif_handle,
+			 hif_get_device_size(),
+			 hif_get_device_size(), HTCA_OK, NULL);
+	htca_dispatch_event(target, ENDPOINT_UNUSED,
+			    HTCA_EVENT_TARGET_AVAILABLE, &event_info);
+
+done:
+	return status;
+}
+
+/* Callback registered with HIF to be invoked when Target
+ * is removed
+ *
+ * Also see htca_stop
+ * Stop tasks
+ * Free memory for Target, endpoints, requests, etc.
+ *
+ * TBD: Not yet supported
+ */
+int htca_target_removed_handler(void *unused_context,
+				void *htca_handle)
+{
+	struct htca_target *target = (struct htca_target *)htca_handle;
+	struct htca_event_info event_info;
+	struct htca_endpoint *end_point;
+	int ep;
+
+	htcadebug("Enter\n");
+	/* Disable each of the endpoints to stop accepting requests. */
+	for (ep = 0; ep < HTCA_NUM_MBOX; ep++) {
+		end_point = &target->end_point[ep];
+		end_point->enabled = false;
+	}
+
+	if (target) {
+		/* Frame a TARGET_UNAVAILABLE event and send it to the host */
+		htca_frame_event(&event_info, NULL, 0, 0, HTCA_OK, NULL);
+		htca_dispatch_event(target, ENDPOINT_UNUSED,
+				    HTCA_EVENT_TARGET_UNAVAILABLE, &event_info);
+	}
+
+	/* TBD: call htca_stop? */
+	/* TBD: Must be sure that nothing is going on before we free. */
+	if (WARN_ON(1)) /* TBD */
+		return HTCA_ERROR;
+
+	/* Free everything allocated earlier, including target
+	 * structure and all request structures.
+	 */
+	/* TBD: kfree .... */
+
+	return HTCA_OK;
+}
diff --git a/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_recv.c b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_recv.c
new file mode 100644
index 0000000..0d4eae8
--- /dev/null
+++ b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_recv.c
@@ -0,0 +1,205 @@
+/* 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/completion.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/spinlock_types.h>
+#include <linux/wait.h>
+
+#include "../hif_sdio/hif.h"
+#include "htca.h"
+#include "htca_mbox_internal.h"
+
+/* If there is data available to read on the specified mailbox,
+ * pull a Mailbox Recv Request off of the PendingRecv queue
+ * and request HIF to pull data from the mailbox into the
+ * request's recv buffer.
+ *
+ * If we are not aware of data waiting on the endpoint, simply
+ * return. Note that our awareness is based on slightly stale
+ * data from Quartz registers. Upper layers insure that we are
+ * called shortly after data becomes available on an endpoint.
+ *
+ * If we exhaust receive buffers, disable the mailbox's interrupt
+ * until additional buffers are available.
+ *
+ * Returns 0 if no request was sent to HIF
+ * returns 1 if at least one request was sent to HIF
+ */
+int htca_manage_pending_recvs(struct htca_target *target, int epid)
+{
+	struct htca_endpoint *end_point;
+	struct htca_request_queue *recv_queue;
+	struct htca_mbox_request *mbox_request;
+	u32 rx_frame_length;
+	unsigned long flags;
+	int work_done = 0;
+
+	if (target->pending_recv_mask & (1 << epid)) {
+		/* Receive operation is already in progress on this endpoint */
+		return 0;
+	}
+
+	end_point = &target->end_point[epid];
+
+	/* Hand off requests as long as we have both
+	 * something to recv into
+	 * data waiting to be read on the mailbox
+	 */
+
+	/* rx_frame_length of 0 --> nothing waiting; otherwise, it's
+	 * the length of data waiting to be read, NOT including
+	 * HTCA header nor block padding.
+	 */
+	rx_frame_length = end_point->rx_frame_length;
+
+	recv_queue = &end_point->recv_pending_queue;
+	if (HTCA_IS_QUEUE_EMPTY(recv_queue)) {
+		htcadebug("no recv buff for ep#%d\n", epid);
+		/* Not interested in rxdata interrupts
+		 * since we have no recv buffers.
+		 */
+		target->enb.int_status_enb &= ~(1 << epid);
+
+		if (rx_frame_length) {
+			struct htca_event_info event_info;
+
+			htcadebug("frame waiting (%d): %d\n",
+				  epid, rx_frame_length);
+			/* No buffer ready to receive but data
+			 * is ready. Alert the caller with a
+			 * DATA_AVAILABLE event.
+			 */
+			if (!end_point->rx_data_alerted) {
+				end_point->rx_data_alerted = true;
+
+				htca_frame_event(&event_info, NULL,
+						 rx_frame_length,
+						 0, HTCA_OK, NULL);
+
+				htca_dispatch_event(target, epid,
+						    HTCA_EVENT_DATA_AVAILABLE,
+						    &event_info);
+			}
+		}
+		return 0;
+	}
+
+	/* We have recv buffers available, so we are
+	 * interested in rxdata interrupts.
+	 */
+	target->enb.int_status_enb |= (1 << epid);
+	end_point->rx_data_alerted = false;
+
+	if (rx_frame_length == 0) {
+		htcadebug(
+		    "htca_manage_pending_recvs: buffer available (%d), but no data to recv\n",
+		    epid);
+		/* We have a buffer but there's nothing
+		 * available on the Target to read.
+		 */
+		return 0;
+	}
+
+	/* There is rxdata waiting and a buffer to read it into */
+
+	/* Pull the request buffer off the Pending Recv Queue */
+	spin_lock_irqsave(&end_point->mbox_queue_lock, flags);
+	mbox_request =
+	    (struct htca_mbox_request *)htca_request_deq_head(recv_queue);
+
+	spin_unlock_irqrestore(&end_point->mbox_queue_lock, flags);
+
+	if (!mbox_request)
+		goto done;
+
+	htcadebug("ep#%d receiving frame: %d bytes\n", epid, rx_frame_length);
+
+	spin_lock_irqsave(&target->pending_op_lock, flags);
+	target->pending_recv_mask |= (1 << epid);
+	spin_unlock_irqrestore(&target->pending_op_lock, flags);
+
+	/* Hand off this Mbox Recv request to HIF */
+	mbox_request->actual_length = rx_frame_length;
+	if (htca_recv_request_to_hif(end_point, mbox_request) == HTCA_ERROR) {
+		struct htca_event_info event_info;
+
+		/* TBD: Could requeue this at the HEAD of the
+		 * pending recv queue. Try again later?
+		 */
+
+		/* Frame an event to send to caller */
+		htca_frame_event(&event_info, mbox_request->buffer,
+				 mbox_request->buffer_length,
+				 mbox_request->actual_length, HTCA_ECANCELED,
+				 mbox_request->cookie);
+
+		/* Free the Mailbox request */
+		spin_lock_irqsave(&end_point->mbox_queue_lock, flags);
+		htca_request_enq_tail(&end_point->recv_free_queue,
+				      (struct htca_request *)mbox_request);
+		spin_unlock_irqrestore(&end_point->mbox_queue_lock, flags);
+
+		spin_lock_irqsave(&target->pending_op_lock, flags);
+		target->pending_recv_mask &= ~(1 << epid);
+		spin_unlock_irqrestore(&target->pending_op_lock, flags);
+
+		htca_dispatch_event(target, epid, HTCA_EVENT_BUFFER_RECEIVED,
+				    &event_info);
+		goto done;
+	} else {
+		work_done = 1;
+	}
+
+done:
+	return work_done;
+}
+
+int htca_recv_request_to_hif(struct htca_endpoint *end_point,
+			     struct htca_mbox_request *mbox_request)
+{
+	int status;
+	struct htca_target *target;
+	u32 padded_length;
+	u32 mbox_address;
+	u32 req_type;
+
+	target = end_point->target;
+
+	/* Adjust length for power-of-2 block size */
+	padded_length =
+	    htca_round_up(mbox_request->actual_length + HTCA_HEADER_LEN_MAX,
+			  end_point->block_size);
+
+	req_type = (end_point->block_size > 1) ? HIF_RD_ASYNC_BLOCK_INC
+					       : HIF_RD_ASYNC_BYTE_INC;
+
+	mbox_address = end_point->mbox_start_addr;
+
+	status = hif_read_write(target->hif_handle, mbox_address,
+				&mbox_request->buffer
+				[HTCA_HEADER_LEN_MAX - HTCA_HEADER_LEN],
+				padded_length, req_type, mbox_request);
+
+	if (status == HIF_OK && mbox_request->req.completion_cb) {
+		mbox_request->req.completion_cb(
+		    (struct htca_request *)mbox_request, HTCA_OK);
+		/* htca_recv_compl */
+	} else if (status == HIF_PENDING) {
+		/* Will complete later */
+	} else { /* HIF error */
+		return HTCA_ERROR;
+	}
+
+	return HTCA_OK;
+}
diff --git a/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_send.c b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_send.c
new file mode 100644
index 0000000..ebccf72
--- /dev/null
+++ b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_send.c
@@ -0,0 +1,392 @@
+/* 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/completion.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/spinlock_types.h>
+#include <linux/wait.h>
+
+#include "../hif_sdio/hif.h"
+#include "htca.h"
+#include "htca_mbox_internal.h"
+
+/* Decide when an endpoint is low on tx credits and we should
+ * initiate a credit refresh. If this is set very low, we may
+ * exhaust credits entirely and pause while we wait for credits
+ * to be reaped from the Target. If set very high we may end
+ * up spending excessive time trying to reap when nothing is
+ * available.
+ *
+ * TBD: We could make this something like a percentage of the
+ * most credits we've ever seen on this endpoint. Or make it
+ * a value that automatically adjusts -- increase by one whenever
+ * we exhaust credits; decrease by one whenever a CREDIT_REFRESH
+ * fails to reap any credits.
+ * For now, wait until credits are completely exhausted; then
+ * initiate a credit refresh cycle.
+ */
+#define HTCA_EP_CREDITS_ARE_LOW(_endp) ((_endp)->tx_credits_available == 0)
+
+/* Pull as many Mailbox Send Requests off of the PendingSend queue
+ * as we can (must have a credit for each send) and hand off the
+ * request to HIF.
+ *
+ * This function returns when we exhaust Send Requests OR when we
+ * exhaust credits.
+ *
+ * If we are low on credits, it starts a credit refresh cycle.
+ *
+ * Returns 0 if nothing was send to HIF
+ * returns 1 if at least one request was sent to HIF
+ */
+int htca_manage_pending_sends(struct htca_target *target, int epid)
+{
+	struct htca_endpoint *end_point;
+	struct htca_request_queue *send_queue;
+	struct htca_mbox_request *mbox_request;
+	unsigned long flags;
+	u8 tx_credits_available;
+	int work_done = 0;
+
+	end_point = &target->end_point[epid];
+	send_queue = &end_point->send_pending_queue;
+
+	/* Transmit messages as long as we have both something to send
+	 * tx credits that permit us to send
+	 */
+	while (!HTCA_IS_QUEUE_EMPTY(send_queue)) {
+		spin_lock_irqsave(&end_point->tx_credit_lock, flags);
+		tx_credits_available = end_point->tx_credits_available;
+		if (tx_credits_available)
+			end_point->tx_credits_available--;
+		spin_unlock_irqrestore(&end_point->tx_credit_lock, flags);
+		htcadebug("(ep=%d) tx_credits_available=%d\n",
+			  epid, tx_credits_available);
+		if (!tx_credits_available) {
+			/* We exhausted tx credits */
+			break;
+		}
+
+		/* Get the request buffer from the Pending Send Queue */
+		spin_lock_irqsave(&end_point->mbox_queue_lock, flags);
+		mbox_request =
+		    (struct htca_mbox_request *)htca_request_deq_head(
+			send_queue);
+
+		spin_unlock_irqrestore(&end_point->mbox_queue_lock, flags);
+
+		if (!mbox_request)
+			break;
+
+		/* Hand off this Mbox Send request to HIF */
+		if (htca_send_request_to_hif(end_point, mbox_request) ==
+		    HTCA_ERROR) {
+			struct htca_event_info event_info;
+
+			/* TBD: Could requeue this at the HEAD of the
+			 * pending send queue. Try again later?
+			 */
+
+			/* Restore tx credit, since it was not used */
+			spin_lock_irqsave(&end_point->tx_credit_lock, flags);
+			end_point->tx_credits_available++;
+			spin_unlock_irqrestore(&end_point->tx_credit_lock,
+					       flags);
+
+			/* Frame an event to send to caller */
+			htca_frame_event(&event_info, mbox_request->buffer,
+					 mbox_request->buffer_length,
+					 mbox_request->actual_length,
+					 HTCA_ECANCELED,
+					 mbox_request->cookie);
+
+			/* Free the Mailbox request */
+			spin_lock_irqsave(&end_point->mbox_queue_lock, flags);
+			htca_request_enq_tail(
+			    &end_point->send_free_queue,
+			    (struct htca_request *)mbox_request);
+			spin_unlock_irqrestore(&end_point->mbox_queue_lock,
+					       flags);
+
+			htca_dispatch_event(
+			    target, epid, HTCA_EVENT_BUFFER_SENT, &event_info);
+			goto done;
+		}
+		work_done = 1;
+	}
+
+	htcadebug("ep=%d credsAvail=%d toReap=%d\n",
+		  epid, end_point->tx_credits_available,
+		  end_point->tx_credits_to_reap);
+	if (HTCA_EP_CREDITS_ARE_LOW(end_point)) {
+		target->enb.counter_int_status_enb |= (0x10 << epid);
+		if (end_point->tx_credits_to_reap)
+			htca_credit_refresh_start(end_point);
+	} else {
+		target->enb.counter_int_status_enb &= ~(0x10 << epid);
+	}
+
+done:
+	return work_done;
+}
+
+/* Send one send request to HIF.
+ *
+ * Called from the HTCA task while processing requests from
+ * an endpoint's pendingSendQueue.
+ *
+ * Note: May consider calling this in the context of a process
+ * submitting a new Send Request (i.e. when nothing else is
+ * pending and credits are available). This would save the
+ * cost of context switching to the HTCA Work Task; but it would
+ * require additional synchronization and would add some
+ * complexity. For the high throughput case this optimization
+ * would not help since we are likely to have requests
+ * pending which must be submitted to HIF in the order received.
+ */
+int htca_send_request_to_hif(struct htca_endpoint *end_point,
+			     struct htca_mbox_request *mbox_request)
+{
+	int status;
+	struct htca_target *target;
+	u32 padded_length;
+	u32 mbox_address;
+	u32 req_type;
+
+	target = end_point->target;
+
+	/* Adjust length for power-of-2 block size */
+	padded_length =
+	    htca_round_up(mbox_request->actual_length + HTCA_HEADER_LEN_MAX,
+			  end_point->block_size);
+
+	/* Prepend the message's actual length to the  outgoing message.
+	 * Caller is REQUIRED to leave HTCA_HEADER_LEN_MAX bytes before
+	 * the message for this purpose (of which the first HTCA_HEADER_LEN
+	 * bytes are actually used).
+	 *
+	 * TBD: We may enhance HIF so that a single write request
+	 * may have TWO consecutive components: one for the HTCA header
+	 * and another for the payload. This would remove the burden
+	 * on callers to reserve space in their buffer for HTCA.
+	 *
+	 * TBD: Since the messaging layer sitting on top of HTCA may
+	 * have this same issue it may make sense to allow a Send
+	 * to pass in a "header buffer" along with a "payload buffer".
+	 * So two buffers (or more generally, a list of buffers)
+	 * rather than one on each call.  These buffers would be
+	 * guaranteed to be sent to HIF as a group and they would
+	 * be sent over SDIO back to back.
+	 */
+	mbox_request->buffer -= HTCA_HEADER_LEN_MAX;
+
+	if (HTCA_HEADER_LEN_MAX > HTCA_HEADER_LEN) {
+		/* Sanity: clear padding bytes, if used */
+		memset(&mbox_request->buffer[HTCA_HEADER_LEN], 0,
+		       HTCA_HEADER_LEN_MAX - HTCA_HEADER_LEN);
+	}
+	/* Target receives length in LittleEndian byte order
+	 * regardeless of Host endianness.
+	 */
+	mbox_request->buffer[0] = mbox_request->actual_length & 0xff;
+	mbox_request->buffer[1] = (mbox_request->actual_length >> 8) & 0xff;
+
+	req_type = (end_point->block_size > 1) ? HIF_WR_ASYNC_BLOCK_INC
+					       : HIF_WR_ASYNC_BYTE_INC;
+
+	/* Arrange for last byte of the message to generate an
+	 * EndOfMessage interrupt to the Target.
+	 */
+	mbox_address = end_point->mbox_end_addr - padded_length;
+
+	/* Send the request to HIF */
+	status = hif_read_write(target->hif_handle, mbox_address,
+				mbox_request->buffer, padded_length, req_type,
+				mbox_request);
+
+	if (status == HIF_OK && mbox_request->req.completion_cb) {
+		mbox_request->req.completion_cb(
+		    (struct htca_request *)mbox_request, HTCA_OK);
+		/* htcaSendCompletionCB */
+	} else if (status == HIF_PENDING) {
+		/* Will complete later */
+	} else { /* HIF error */
+		/* Restore mbox_request buffer */
+		mbox_request->buffer += HTCA_HEADER_LEN_MAX;
+		return HTCA_ERROR;
+	}
+
+	return HTCA_OK;
+}
+
+/* Start a credit refresh cycle. Credits will appear in
+ * end_point->tx_credits_available when this refresh completes.
+ *
+ * Called in the context of the work_task when we are unable
+ * to send any more requests because credits are exhausted.
+ * Also called from HIF completion's context when a credit
+ * interrupt occurs.
+ *
+ * TBD: Consider HTCA v2 features: Quartz FW can send
+ * in-band TX Credit hint
+ * RX Length hint
+ * interrupt status registers
+ * as opportunistic trailer(s) on an RX message.
+ * This increases code complexity but may reduce overhead
+ * since we may reduce the number of explicit SDIO register
+ * read operations which are relatively expensive "byte basis"
+ * operations.
+ */
+int htca_credit_refresh_start(struct htca_endpoint *end_point)
+{
+	u8 end_point_id;
+	int status;
+	struct htca_target *target;
+	struct htca_reg_request *reg_request;
+	unsigned long flags;
+	bool already_in_progress;
+	u32 address;
+
+	htcadebug("Enter\n");
+
+	spin_lock_irqsave(&end_point->tx_credit_lock, flags);
+	already_in_progress = end_point->tx_credit_refresh_in_progress;
+	end_point->tx_credit_refresh_in_progress = true;
+	spin_unlock_irqrestore(&end_point->tx_credit_lock, flags);
+
+	if (already_in_progress)
+		return 0;
+
+	target = end_point->target;
+	end_point_id = get_endpoint_id(end_point);
+	htcadebug("on endpoint %d\n", end_point_id);
+
+	spin_lock_irqsave(&target->reg_queue_lock, flags);
+	reg_request = (struct htca_reg_request *)htca_request_deq_head(
+	    &target->reg_free_queue);
+	spin_unlock_irqrestore(&target->reg_queue_lock, flags);
+
+	if (!reg_request) {
+		WARN_ON(1);
+		return 1;
+	}
+
+	if (WARN_ON(reg_request->purpose != UNUSED_PURPOSE))
+		return 1;
+
+	reg_request->buffer = NULL;
+	reg_request->length = 0;
+	reg_request->purpose = CREDIT_REFRESH;
+	reg_request->epid = end_point_id;
+
+	address = get_reg_addr(TX_CREDIT_COUNTER_DECREMENT_REG, end_point_id);
+
+	/* Note: reading many times FROM a FIXed register address, the
+	 * "atomic decrement address". The function htca_credit_refresh_compl
+	 * examines the results upon completion.
+	 */
+	status = hif_read_write(
+	    target->hif_handle, address, reg_request->u.credit_dec_results,
+	    HTCA_TX_CREDITS_REAP_MAX, HIF_RD_ASYNC_BYTE_FIX, reg_request);
+	if (status == HIF_OK && reg_request->req.completion_cb) {
+		reg_request->req.completion_cb(
+		    (struct htca_request *)reg_request, HIF_OK);
+		/* htca_credit_refresh_compl */
+	} else if (status == HIF_PENDING) {
+		/* Will complete later */
+	} else { /* HIF error */
+		WARN_ON(1);
+	}
+	return 1;
+}
+
+/* Used during Configuration Negotiation at startup
+ * to configure max message sizes for each endpoint.
+ *
+ * Returns true if all endpoints have been configured,
+ * by this pass and/or all earlier calls. (Typically
+ * there should be only a single call which enables
+ * all endpoints at once.)
+ *
+ * Returns false if at least one endpoint has not
+ * yet been configured.
+ */
+bool htca_negotiate_config(struct htca_target *target)
+{
+	int status;
+	struct htca_endpoint *end_point;
+	u32 address;
+	int enb_count = 0;
+	int ep;
+
+	htcadebug("Enter\n");
+
+	/* The Target should have posted 1 credit to
+	 * each endpoint by the time we reach here.
+	 */
+	for (ep = 0; ep < HTCA_NUM_MBOX; ep++) {
+		end_point = &target->end_point[ep];
+		if (end_point->enabled) {
+			/* This endpoint was already enabled */
+			enb_count++;
+			continue;
+		}
+		htcadebug("try epid=%d\n", ep);
+
+		address = get_reg_addr(TX_CREDIT_COUNTER_DECREMENT_REG, ep);
+		end_point->tx_credits_available = 0;
+		status =
+		    hif_read_write(target->hif_handle, address,
+				   (u8 *)&end_point->tx_credits_available,
+				   1, HIF_RD_SYNC_BYTE_FIX, NULL);
+		if (status != HIF_OK) {
+			htcadebug("DBG: address=0x%08x status=%d\n", address,
+				  status);
+		}
+		if (WARN_ON(status != HIF_OK))
+			return false;
+
+		if (!end_point->tx_credits_available) {
+			/* not yet ready -- no credit posted.  Odd case. */
+			continue;
+		}
+		if (WARN_ON(end_point->tx_credits_available != 1))
+			return false;
+
+		end_point->tx_credits_available--;
+
+		/* TBD: Tacitly assumes LittleEndian Host.
+		 * This -- rather than an explicit Host interrupt -- is
+		 * what should trigger Target to fetch blocksize.
+		 */
+		htcadebug("good to go epid=%d\n", ep);
+
+		/* "Negotiate" the message size for this endpoint by writing
+		 * the maximum message size (and trigger EOM).
+		 */
+		address =
+		    end_point->mbox_end_addr - sizeof(end_point->max_msg_sz);
+		status = hif_read_write(target->hif_handle, address,
+					(u8 *)&end_point->max_msg_sz,
+					sizeof(end_point->max_msg_sz),
+					HIF_WR_SYNC_BYTE_INC, NULL);
+		if (WARN_ON(status != HIF_OK))
+			return false;
+
+		end_point->enabled = true;
+		enb_count++;
+	}
+
+	htcadebug("enb_count=%d\n", enb_count);
+	return (enb_count == HTCA_NUM_MBOX);
+}
diff --git a/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_task.c b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_task.c
new file mode 100644
index 0000000..6598cba
--- /dev/null
+++ b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_task.c
@@ -0,0 +1,340 @@
+/* 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.
+ */
+
+/* Implementation of Host Target Communication tasks,
+ * WorkTask and compl_task, which are used to manage
+ * the Mbox Pending Queues.
+ *
+ * A mailbox Send request is queued in arrival order on
+ * a per-mailbox Send queue until a credit is available
+ * from the Target. Requests in this queue are
+ * waiting for the Target to provide tx credits (i.e. recv
+ * buffers on the Target-side).
+ *
+ * A mailbox Recv request is queued in arrival order on
+ * a per-mailbox Recv queue until a message is available
+ * to be read. So requests in this queue are waiting for
+ * the Target to provide rx data.
+ *
+ * htca_work_task dequeues requests from the SendPendingQueue
+ * (once credits are available) and dequeues requests from
+ * the RecvPendingQueue (once rx data is available) and
+ * hands them to HIF for processing.
+ *
+ * htca_compl_task handles completion processing after
+ * HIF completes a request.
+ *
+ * The main purpose of these tasks is to provide a
+ * suitable suspendable context for processing requests
+ * and completions.
+ */
+
+#include <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/spinlock_types.h>
+#include <linux/wait.h>
+
+#include "../hif_sdio/hif.h"
+#include "htca.h"
+#include "htca_mbox_internal.h"
+
+/* Wakeup the htca_work_task.
+ *
+ * Invoked whenever send/recv state changes:
+ * new Send buffer added to the send_pending_queue
+ * new Recv buffer added to the recv_pending_queue
+ * tx credits are reaped
+ * rx data available recognized
+ */
+void htca_work_task_poke(struct htca_target *target)
+{
+	target->work_task_has_work = true;
+	wake_up_interruptible_sync(&target->work_task_wait);
+}
+
+/* Body of the htca_work_task, which hands Send and
+ * Receive requests to HIF.
+ */
+static int htca_work_task_core(struct htca_target *target)
+{
+	int ep;
+	int work_done = 0;
+
+	/* TBD: We might consider alternative ordering policies, here,
+	 * between Sends and Recvs and among mailboxes. The current
+	 * algorithm is simple.
+	 */
+
+	/* Process sends/recvs */
+	for (ep = 0; ep < HTCA_NUM_MBOX; ep++) {
+		htcadebug("Call (%d)\n", ep);
+		work_done += htca_manage_pending_sends(target, ep);
+		htcadebug("Call (%d)\n", ep);
+		work_done += htca_manage_pending_recvs(target, ep);
+	}
+
+	return work_done;
+}
+
+/* Only this work_task is permitted to update
+ * interrupt enables. That restriction eliminates
+ * complex race conditions.
+ */
+static int htca_work_task(void *param)
+{
+	struct htca_target *target = (struct htca_target *)param;
+
+	/* set_user_nice(current, -3); */
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	for (;;) {
+		htcadebug("top of loop. intr_state=%d\n", target->intr_state);
+		/* Wait for htca_work_task_poke */
+		wait_event_interruptible(target->work_task_wait,
+					 target->work_task_has_work);
+
+		if (target->work_task_shutdown)
+			break; /* htcaTaskStop invoked */
+
+		if (!target->work_task_has_work)
+			break; /* exit, if this task was interrupted */
+
+		/* reset before we start work */
+		target->work_task_has_work = false;
+		barrier();
+
+		if (target->need_start_polling) {
+			/* reset for next time */
+			target->need_start_polling = 0;
+			target->intr_state = HTCA_POLL;
+			htca_update_intr_enbs(target, 1);
+		}
+
+		while (htca_work_task_core(target))
+			;
+
+		if (target->pending_recv_mask ||
+		    target->pending_register_refresh) {
+			continue;
+		}
+
+		/* When a Recv completes, it sets need_register_refresh=1
+		 * and pokes the work_task.
+		 *
+		 * We won't actually initiate a register refresh until
+		 * pending recvs on ALL eps have completed. This may
+		 * increase latency slightly but it increases efficiency
+		 * and reduces chatter which should improve throughput.
+		 * Note that even though we don't initiate the register
+		 * refresh immediately, SDIO is still 100% busy doing
+		 * useful work. The refresh is issued shortly after.
+		 */
+		if (target->need_register_refresh) {
+			/* Continue to poll. When the RegsiterRefresh
+			 * completes, the WorkTask will be poked.
+			 */
+			target->need_register_refresh = 0;
+			htca_register_refresh_start(target);
+			continue;
+		}
+
+		/* If more work has arrived since we last checked,
+		 * make another pass.
+		 */
+		if (target->work_task_has_work)
+			continue;
+
+		/* As long as we are constantly refreshing register
+		 * state and reprocessing, there is no need to
+		 * enable interrupts. We are essentially POLLING for
+		 * interrupts anyway. But if
+		 * -we were in POLL mode and
+		 * -we have processed all outstanding sends/recvs and
+		 * -there are no PENDING recv operations and
+		 * -there is no pending register refresh (so
+		 * no recv operations have completed since the
+		 * last time we refreshed register state)
+		 * then we switch to INTERRUPT mode and re-enable
+		 * Target-side interrupts.
+		 *
+		 * We'll sleep until poked:
+		 * -DSR handler receives an interrupt
+		 * -application enqueues a new send/recv buffer
+		 * We must also UPDATE interrupt enables even if we
+		 * were already in INTERRUPT mode, since some bits
+		 * may have changed.
+		 */
+		if (target->intr_state == HTCA_POLL) {
+			target->intr_state = HTCA_INTERRUPT;
+			htca_update_intr_enbs(target, 0);
+		}
+	}
+	complete_and_exit(&target->work_task_completion, 0);
+
+	return 0;
+}
+
+int htca_work_task_start(struct htca_target *target)
+{
+	int status = HTCA_ERROR;
+
+	if (mutex_lock_interruptible(&target->task_mutex))
+		return HTCA_ERROR; /* interrupted */
+
+	if (target->work_task)
+		goto done; /* already started */
+
+	target->work_task = kthread_create(htca_work_task, target, "htcaWork");
+	if (!target->work_task)
+		goto done; /* Failed to create task */
+
+	target->work_task_shutdown = false;
+	init_waitqueue_head(&target->work_task_wait);
+	init_completion(&target->work_task_completion);
+	wake_up_process(target->work_task);
+	status = HTCA_OK;
+
+done:
+	mutex_unlock(&target->task_mutex);
+	return status;
+}
+
+void htca_work_task_stop(struct htca_target *target)
+{
+	if (mutex_lock_interruptible(&target->task_mutex))
+		return; /* interrupted */
+
+	if (!target->work_task)
+		goto done;
+
+	target->work_task_shutdown = true;
+	htca_work_task_poke(target);
+	wait_for_completion(&target->work_task_completion);
+	target->work_task = NULL;
+
+done:
+	mutex_unlock(&target->task_mutex);
+}
+
+/* Wakeup the compl_task.
+ * Invoked after adding a new completion to the compl_queue.
+ */
+void htca_compl_task_poke(struct htca_target *target)
+{
+	target->compl_task_has_work = true;
+	wake_up_interruptible_sync(&target->compl_task_wait);
+}
+
+static int htca_manage_compl(struct htca_target *target)
+{
+	struct htca_request *req;
+	unsigned long flags;
+
+	/* Pop a request from the completion queue */
+	spin_lock_irqsave(&target->compl_queue_lock, flags);
+	req = htca_request_deq_head(&target->compl_queue);
+	spin_unlock_irqrestore(&target->compl_queue_lock, flags);
+
+	if (!req)
+		return 0; /* nothing to do */
+
+	/* Invoke request's corresponding completion function */
+	if (req->completion_cb)
+		req->completion_cb(req, req->status);
+
+	return 1;
+}
+
+static int htca_compl_task(void *param)
+{
+	struct htca_target *target = (struct htca_target *)param;
+
+	/* set_user_nice(current, -3); */
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	for (;;) {
+		/* Wait for htca_compl_task_poke */
+		wait_event_interruptible(target->compl_task_wait,
+					 target->compl_task_has_work);
+		if (target->compl_task_shutdown)
+			break; /* htcaTaskStop invoked */
+
+		if (!target->compl_task_has_work)
+			break; /* exit, if this task was interrupted */
+
+		/* reset before we start work */
+		target->compl_task_has_work = false;
+		barrier();
+
+		/* TBD: We could try to prioritize completions rather than
+		 * handle them strictly in order. Could use separate queues for
+		 * register completions and mailbox completion on each endpoint.
+		 * In general, completion processing is expected to be short
+		 * so this probably isn't worth the additional complexity.
+		 */
+		{
+			int did_work;
+
+			do {
+				did_work = htca_manage_compl(target);
+			} while (did_work);
+		}
+	}
+	complete_and_exit(&target->compl_cask_completion, 0);
+
+	return 0;
+}
+
+int htca_compl_task_start(struct htca_target *target)
+{
+	int status = HTCA_ERROR;
+
+	if (mutex_lock_interruptible(&target->task_mutex))
+		return HTCA_ERROR; /* interrupted */
+
+	if (target->compl_task)
+		goto done; /* already started */
+
+	target->compl_task =
+	    kthread_create(htca_compl_task, target, "htcaCompl");
+	if (!target->compl_task)
+		goto done; /* Failed to create task */
+
+	target->compl_task_shutdown = false;
+	init_waitqueue_head(&target->compl_task_wait);
+	init_completion(&target->compl_cask_completion);
+	wake_up_process(target->compl_task);
+	status = HTCA_OK;
+
+done:
+	mutex_unlock(&target->task_mutex);
+	return status;
+}
+
+void htca_compl_task_stop(struct htca_target *target)
+{
+	if (mutex_lock_interruptible(&target->task_mutex))
+		return; /* interrupted */
+
+	if (!target->compl_task)
+		goto done;
+
+	target->compl_task_shutdown = true;
+	htca_compl_task_poke(target);
+	wait_for_completion(&target->compl_cask_completion);
+	target->compl_task = NULL;
+
+done:
+	mutex_unlock(&target->task_mutex);
+}
diff --git a/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_utils.c b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_utils.c
new file mode 100644
index 0000000..4cf137c
--- /dev/null
+++ b/drivers/net/wireless/qca402x/htca_mbox/htca_mbox_utils.c
@@ -0,0 +1,182 @@
+/* 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/completion.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/spinlock_types.h>
+#include <linux/wait.h>
+
+#include "../hif_sdio/hif.h"
+#include "htca.h"
+#include "htca_mbox_internal.h"
+
+/* HTCA utility routines  */
+
+/* Invoked when shutting down */
+void htca_mbox_queue_flush(struct htca_endpoint *end_point,
+			   struct htca_request_queue *pending_queue,
+			   struct htca_request_queue *free_queue,
+			   u8 event_id)
+{
+	struct htca_event_info event_info;
+	u8 end_point_id;
+	struct htca_target *target;
+	struct htca_mbox_request *mbox_request;
+	unsigned long flags;
+
+	target = end_point->target;
+	end_point_id = get_endpoint_id(end_point);
+
+	spin_lock_irqsave(&end_point->mbox_queue_lock, flags);
+	for (;;) {
+		mbox_request =
+		    (struct htca_mbox_request *)htca_request_deq_head(
+			pending_queue);
+		spin_unlock_irqrestore(&end_point->mbox_queue_lock, flags);
+
+		if (!mbox_request)
+			break;
+
+		htca_frame_event(&event_info, mbox_request->buffer,
+				 mbox_request->buffer_length, 0, HTCA_ECANCELED,
+				 mbox_request->cookie);
+
+		htca_dispatch_event(target, end_point_id, event_id,
+				    &event_info);
+
+		/* Recycle the request */
+		spin_lock_irqsave(&end_point->mbox_queue_lock, flags);
+		htca_request_enq_tail(free_queue,
+				      (struct htca_request *)mbox_request);
+	}
+	spin_unlock_irqrestore(&end_point->mbox_queue_lock, flags);
+}
+
+struct htca_target *htca_target_instance(int i)
+{
+	return htca_target_list[i];
+}
+
+void htca_target_instance_add(struct htca_target *target)
+{
+	int i;
+
+	for (i = 0; i < HTCA_NUM_DEVICES_MAX; i++) {
+		if (!htca_target_list[i]) {
+			htca_target_list[i] = target;
+			break;
+		}
+	}
+	WARN_ON(i >= HTCA_NUM_DEVICES_MAX);
+}
+
+void htca_target_instance_remove(struct htca_target *target)
+{
+	int i;
+
+	for (i = 0; i < HTCA_NUM_DEVICES_MAX; i++) {
+		if (htca_target_list[i] == target) {
+			htca_target_list[i] = NULL;
+			break;
+		}
+	}
+	WARN_ON(i >= HTCA_NUM_DEVICES_MAX);
+}
+
+/* Add a request to the tail of a queue.
+ * Caller must handle any locking required.
+ * TBD: Use Linux queue support
+ */
+void htca_request_enq_tail(struct htca_request_queue *queue,
+			   struct htca_request *req)
+{
+	req->next = NULL;
+
+	if (queue->tail)
+		queue->tail->next = (void *)req;
+	else
+		queue->head = req;
+
+	queue->tail = req;
+}
+
+/* Remove a request from the start of a queue.
+ * Caller must handle any locking required.
+ * TBD: Use Linux queue support
+ * TBD: If cannot allocate from FREE queue, caller may add more elements.
+ */
+struct htca_request *htca_request_deq_head(struct htca_request_queue *queue)
+{
+	struct htca_request *req;
+
+	req = queue->head;
+	if (!req)
+		return NULL;
+
+	queue->head = req->next;
+	if (!queue->head)
+		queue->tail = NULL;
+	req->next = NULL;
+
+	return req;
+}
+
+/* Start a Register Refresh cycle.
+ *
+ * Submits a request to fetch ALL relevant registers from Target.
+ * When this completes, we'll take actions based on the new
+ * register values.
+ */
+void htca_register_refresh_start(struct htca_target *target)
+{
+	int status;
+	struct htca_reg_request *reg_request;
+	u32 address;
+	unsigned long flags;
+
+	htcadebug("Enter\n");
+	spin_lock_irqsave(&target->reg_queue_lock, flags);
+	reg_request = (struct htca_reg_request *)htca_request_deq_head(
+	    &target->reg_free_queue);
+	spin_unlock_irqrestore(&target->reg_queue_lock, flags);
+	if (!reg_request) {
+		WARN_ON(1);
+		return;
+	}
+	if (WARN_ON(reg_request->purpose != UNUSED_PURPOSE))
+		return;
+
+	spin_lock_irqsave(&target->pending_op_lock, flags);
+	target->pending_register_refresh++;
+	spin_unlock_irqrestore(&target->pending_op_lock, flags);
+
+	reg_request->buffer = (u8 *)&reg_request->u.reg_table;
+	reg_request->length = sizeof(reg_request->u.reg_table);
+	reg_request->purpose = INTR_REFRESH;
+	reg_request->epid = 0; /* not used */
+
+	address = get_reg_addr(ALL_STATUS_REG, ENDPOINT_UNUSED);
+	status = hif_read_write(target->hif_handle, address,
+				&reg_request->u.reg_table,
+				sizeof(reg_request->u.reg_table),
+				HIF_RD_ASYNC_BYTE_INC, reg_request);
+	if (status == HIF_OK && reg_request->req.completion_cb) {
+		reg_request->req.completion_cb(
+		    (struct htca_request *)reg_request, HIF_OK);
+		/* htca_register_refresh_compl */
+	} else if (status == HIF_PENDING) {
+		/* Will complete later */
+	} else { /* HIF error */
+		WARN_ON(1);
+	}
+}
diff --git a/drivers/net/wireless/qca402x/htca_mbox/mbox_host_reg.h b/drivers/net/wireless/qca402x/htca_mbox/mbox_host_reg.h
new file mode 100644
index 0000000..81ce632
--- /dev/null
+++ b/drivers/net/wireless/qca402x/htca_mbox/mbox_host_reg.h
@@ -0,0 +1,412 @@
+/* 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 _MBOX_HOST_REG_REG_H_
+#define _MBOX_HOST_REG_REG_H_
+
+/* TBD: REMOVE things that are not needed, especially Diag Window */
+
+#define HOST_INT_STATUS_ADDRESS 0x00000400
+#define HOST_INT_STATUS_OFFSET 0x00000400
+#define HOST_INT_STATUS_ERROR_MSB 7
+#define HOST_INT_STATUS_ERROR_LSB 7
+#define HOST_INT_STATUS_ERROR_MASK 0x00000080
+#define HOST_INT_STATUS_ERROR_GET(x) \
+	(((x) & HOST_INT_STATUS_ERROR_MASK) >> HOST_INT_STATUS_ERROR_LSB)
+#define HOST_INT_STATUS_ERROR_SET(x) \
+	(((x) << HOST_INT_STATUS_ERROR_LSB) & HOST_INT_STATUS_ERROR_MASK)
+#define HOST_INT_STATUS_CPU_MSB 6
+#define HOST_INT_STATUS_CPU_LSB 6
+#define HOST_INT_STATUS_CPU_MASK 0x00000040
+#define HOST_INT_STATUS_CPU_GET(x) \
+	(((x) & HOST_INT_STATUS_CPU_MASK) >> HOST_INT_STATUS_CPU_LSB)
+#define HOST_INT_STATUS_CPU_SET(x) \
+	(((x) << HOST_INT_STATUS_CPU_LSB) & HOST_INT_STATUS_CPU_MASK)
+#define HOST_INT_STATUS_DRAGON_INT_MSB 5
+#define HOST_INT_STATUS_DRAGON_INT_LSB 5
+#define HOST_INT_STATUS_DRAGON_INT_MASK 0x00000020
+#define HOST_INT_STATUS_DRAGON_INT_GET(x) \
+	(((x) & HOST_INT_STATUS_DRAGON_INT_MASK) >> \
+	 HOST_INT_STATUS_DRAGON_INT_LSB)
+#define HOST_INT_STATUS_DRAGON_INT_SET(x) \
+	(((x) << HOST_INT_STATUS_DRAGON_INT_LSB) & \
+	 HOST_INT_STATUS_DRAGON_INT_MASK)
+#define HOST_INT_STATUS_COUNTER_MSB 4
+#define HOST_INT_STATUS_COUNTER_LSB 4
+#define HOST_INT_STATUS_COUNTER_MASK 0x00000010
+#define HOST_INT_STATUS_COUNTER_GET(x) \
+	(((x) & HOST_INT_STATUS_COUNTER_MASK) >> HOST_INT_STATUS_COUNTER_LSB)
+#define HOST_INT_STATUS_COUNTER_SET(x) \
+	(((x) << HOST_INT_STATUS_COUNTER_LSB) & HOST_INT_STATUS_COUNTER_MASK)
+#define HOST_INT_STATUS_MBOX_DATA_MSB 3
+#define HOST_INT_STATUS_MBOX_DATA_LSB 0
+#define HOST_INT_STATUS_MBOX_DATA_MASK 0x0000000f
+#define HOST_INT_STATUS_MBOX_DATA_GET(x) \
+	(((x) & HOST_INT_STATUS_MBOX_DATA_MASK) >> \
+						HOST_INT_STATUS_MBOX_DATA_LSB)
+#define HOST_INT_STATUS_MBOX_DATA_SET(x) \
+	(((x) << HOST_INT_STATUS_MBOX_DATA_LSB) & \
+	 HOST_INT_STATUS_MBOX_DATA_MASK)
+
+#define CPU_INT_STATUS_ADDRESS 0x00000401
+#define CPU_INT_STATUS_OFFSET 0x00000401
+#define CPU_INT_STATUS_BIT_MSB 7
+#define CPU_INT_STATUS_BIT_LSB 0
+#define CPU_INT_STATUS_BIT_MASK 0x000000ff
+#define CPU_INT_STATUS_BIT_GET(x) \
+	(((x) & CPU_INT_STATUS_BIT_MASK) >> CPU_INT_STATUS_BIT_LSB)
+#define CPU_INT_STATUS_BIT_SET(x) \
+	(((x) << CPU_INT_STATUS_BIT_LSB) & CPU_INT_STATUS_BIT_MASK)
+
+#define ERROR_INT_STATUS_ADDRESS 0x00000402
+#define ERROR_INT_STATUS_OFFSET 0x00000402
+#define ERROR_INT_STATUS_SPI_MSB 3
+#define ERROR_INT_STATUS_SPI_LSB 3
+#define ERROR_INT_STATUS_SPI_MASK 0x00000008
+#define ERROR_INT_STATUS_SPI_GET(x) \
+	(((x) & ERROR_INT_STATUS_SPI_MASK) >> ERROR_INT_STATUS_SPI_LSB)
+#define ERROR_INT_STATUS_SPI_SET(x) \
+	(((x) << ERROR_INT_STATUS_SPI_LSB) & ERROR_INT_STATUS_SPI_MASK)
+#define ERROR_INT_STATUS_WAKEUP_MSB 2
+#define ERROR_INT_STATUS_WAKEUP_LSB 2
+#define ERROR_INT_STATUS_WAKEUP_MASK 0x00000004
+#define ERROR_INT_STATUS_WAKEUP_GET(x) \
+	(((x) & ERROR_INT_STATUS_WAKEUP_MASK) >> ERROR_INT_STATUS_WAKEUP_LSB)
+#define ERROR_INT_STATUS_WAKEUP_SET(x) \
+	(((x) << ERROR_INT_STATUS_WAKEUP_LSB) & ERROR_INT_STATUS_WAKEUP_MASK)
+#define ERROR_INT_STATUS_RX_UNDERFLOW_MSB 1
+#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB 1
+#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00000002
+#define ERROR_INT_STATUS_RX_UNDERFLOW_GET(x) \
+	(((x) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) >> \
+	 ERROR_INT_STATUS_RX_UNDERFLOW_LSB)
+#define ERROR_INT_STATUS_RX_UNDERFLOW_SET(x) \
+	(((x) << ERROR_INT_STATUS_RX_UNDERFLOW_LSB) & \
+	 ERROR_INT_STATUS_RX_UNDERFLOW_MASK)
+#define ERROR_INT_STATUS_TX_OVERFLOW_MSB 0
+#define ERROR_INT_STATUS_TX_OVERFLOW_LSB 0
+#define ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00000001
+#define ERROR_INT_STATUS_TX_OVERFLOW_GET(x) \
+	(((x) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) >> \
+	 ERROR_INT_STATUS_TX_OVERFLOW_LSB)
+#define ERROR_INT_STATUS_TX_OVERFLOW_SET(x) \
+	(((x) << ERROR_INT_STATUS_TX_OVERFLOW_LSB) & \
+	 ERROR_INT_STATUS_TX_OVERFLOW_MASK)
+
+#define COUNTER_INT_STATUS_ADDRESS 0x00000403
+#define COUNTER_INT_STATUS_OFFSET 0x00000403
+#define COUNTER_INT_STATUS_COUNTER_MSB 7
+#define COUNTER_INT_STATUS_COUNTER_LSB 0
+#define COUNTER_INT_STATUS_COUNTER_MASK 0x000000ff
+#define COUNTER_INT_STATUS_COUNTER_GET(x) \
+	(((x) & COUNTER_INT_STATUS_COUNTER_MASK) >> \
+	 COUNTER_INT_STATUS_COUNTER_LSB)
+#define COUNTER_INT_STATUS_COUNTER_SET(x) \
+	(((x) << COUNTER_INT_STATUS_COUNTER_LSB) & \
+	 COUNTER_INT_STATUS_COUNTER_MASK)
+
+#define MBOX_FRAME_ADDRESS 0x00000404
+#define MBOX_FRAME_OFFSET 0x00000404
+#define MBOX_FRAME_RX_EOM_MSB 7
+#define MBOX_FRAME_RX_EOM_LSB 4
+#define MBOX_FRAME_RX_EOM_MASK 0x000000f0
+#define MBOX_FRAME_RX_EOM_GET(x) \
+	(((x) & MBOX_FRAME_RX_EOM_MASK) >> MBOX_FRAME_RX_EOM_LSB)
+#define MBOX_FRAME_RX_EOM_SET(x) \
+	(((x) << MBOX_FRAME_RX_EOM_LSB) & MBOX_FRAME_RX_EOM_MASK)
+#define MBOX_FRAME_RX_SOM_MSB 3
+#define MBOX_FRAME_RX_SOM_LSB 0
+#define MBOX_FRAME_RX_SOM_MASK 0x0000000f
+#define MBOX_FRAME_RX_SOM_GET(x) \
+	(((x) & MBOX_FRAME_RX_SOM_MASK) >> MBOX_FRAME_RX_SOM_LSB)
+#define MBOX_FRAME_RX_SOM_SET(x) \
+	(((x) << MBOX_FRAME_RX_SOM_LSB) & MBOX_FRAME_RX_SOM_MASK)
+
+#define RX_LOOKAHEAD_VALID_ADDRESS 0x00000405
+#define RX_LOOKAHEAD_VALID_OFFSET 0x00000405
+#define RX_LOOKAHEAD_VALID_MBOX_MSB 3
+#define RX_LOOKAHEAD_VALID_MBOX_LSB 0
+#define RX_LOOKAHEAD_VALID_MBOX_MASK 0x0000000f
+#define RX_LOOKAHEAD_VALID_MBOX_GET(x) \
+	(((x) & RX_LOOKAHEAD_VALID_MBOX_MASK) >> RX_LOOKAHEAD_VALID_MBOX_LSB)
+#define RX_LOOKAHEAD_VALID_MBOX_SET(x) \
+	(((x) << RX_LOOKAHEAD_VALID_MBOX_LSB) & RX_LOOKAHEAD_VALID_MBOX_MASK)
+
+#define RX_LOOKAHEAD0_ADDRESS 0x00000408
+#define RX_LOOKAHEAD0_OFFSET 0x00000408
+#define RX_LOOKAHEAD0_DATA_MSB 7
+#define RX_LOOKAHEAD0_DATA_LSB 0
+#define RX_LOOKAHEAD0_DATA_MASK 0x000000ff
+#define RX_LOOKAHEAD0_DATA_GET(x) \
+	(((x) & RX_LOOKAHEAD0_DATA_MASK) >> RX_LOOKAHEAD0_DATA_LSB)
+#define RX_LOOKAHEAD0_DATA_SET(x) \
+	(((x) << RX_LOOKAHEAD0_DATA_LSB) & RX_LOOKAHEAD0_DATA_MASK)
+
+#define RX_LOOKAHEAD1_ADDRESS 0x0000040c
+#define RX_LOOKAHEAD1_OFFSET 0x0000040c
+#define RX_LOOKAHEAD1_DATA_MSB 7
+#define RX_LOOKAHEAD1_DATA_LSB 0
+#define RX_LOOKAHEAD1_DATA_MASK 0x000000ff
+#define RX_LOOKAHEAD1_DATA_GET(x) \
+	(((x) & RX_LOOKAHEAD1_DATA_MASK) >> RX_LOOKAHEAD1_DATA_LSB)
+#define RX_LOOKAHEAD1_DATA_SET(x) \
+	(((x) << RX_LOOKAHEAD1_DATA_LSB) & RX_LOOKAHEAD1_DATA_MASK)
+
+#define RX_LOOKAHEAD2_ADDRESS 0x00000410
+#define RX_LOOKAHEAD2_OFFSET 0x00000410
+#define RX_LOOKAHEAD2_DATA_MSB 7
+#define RX_LOOKAHEAD2_DATA_LSB 0
+#define RX_LOOKAHEAD2_DATA_MASK 0x000000ff
+#define RX_LOOKAHEAD2_DATA_GET(x) \
+	(((x) & RX_LOOKAHEAD2_DATA_MASK) >> RX_LOOKAHEAD2_DATA_LSB)
+#define RX_LOOKAHEAD2_DATA_SET(x) \
+	(((x) << RX_LOOKAHEAD2_DATA_LSB) & RX_LOOKAHEAD2_DATA_MASK)
+
+#define RX_LOOKAHEAD3_ADDRESS 0x00000414
+#define RX_LOOKAHEAD3_OFFSET 0x00000414
+#define RX_LOOKAHEAD3_DATA_MSB 7
+#define RX_LOOKAHEAD3_DATA_LSB 0
+#define RX_LOOKAHEAD3_DATA_MASK 0x000000ff
+#define RX_LOOKAHEAD3_DATA_GET(x) \
+	(((x) & RX_LOOKAHEAD3_DATA_MASK) >> RX_LOOKAHEAD3_DATA_LSB)
+#define RX_LOOKAHEAD3_DATA_SET(x) \
+	(((x) << RX_LOOKAHEAD3_DATA_LSB) & RX_LOOKAHEAD3_DATA_MASK)
+
+#define INT_STATUS_ENABLE_ADDRESS 0x00000418
+#define INT_STATUS_ENABLE_OFFSET 0x00000418
+#define INT_STATUS_ENABLE_ERROR_MSB 7
+#define INT_STATUS_ENABLE_ERROR_LSB 7
+#define INT_STATUS_ENABLE_ERROR_MASK 0x00000080
+#define INT_STATUS_ENABLE_ERROR_GET(x) \
+	(((x) & INT_STATUS_ENABLE_ERROR_MASK) >> INT_STATUS_ENABLE_ERROR_LSB)
+#define INT_STATUS_ENABLE_ERROR_SET(x) \
+	(((x) << INT_STATUS_ENABLE_ERROR_LSB) & INT_STATUS_ENABLE_ERROR_MASK)
+#define INT_STATUS_ENABLE_CPU_MSB 6
+#define INT_STATUS_ENABLE_CPU_LSB 6
+#define INT_STATUS_ENABLE_CPU_MASK 0x00000040
+#define INT_STATUS_ENABLE_CPU_GET(x) \
+	(((x) & INT_STATUS_ENABLE_CPU_MASK) >> INT_STATUS_ENABLE_CPU_LSB)
+#define INT_STATUS_ENABLE_CPU_SET(x) \
+	(((x) << INT_STATUS_ENABLE_CPU_LSB) & INT_STATUS_ENABLE_CPU_MASK)
+#define INT_STATUS_ENABLE_DRAGON_INT_MSB 5
+#define INT_STATUS_ENABLE_DRAGON_INT_LSB 5
+#define INT_STATUS_ENABLE_DRAGON_INT_MASK 0x00000020
+#define INT_STATUS_ENABLE_DRAGON_INT_GET(x) \
+	(((x) & INT_STATUS_ENABLE_DRAGON_INT_MASK) >> \
+	 INT_STATUS_ENABLE_DRAGON_INT_LSB)
+#define INT_STATUS_ENABLE_DRAGON_INT_SET(x) \
+	(((x) << INT_STATUS_ENABLE_DRAGON_INT_LSB) & \
+	 INT_STATUS_ENABLE_DRAGON_INT_MASK)
+#define INT_STATUS_ENABLE_COUNTER_MSB 4
+#define INT_STATUS_ENABLE_COUNTER_LSB 4
+#define INT_STATUS_ENABLE_COUNTER_MASK 0x00000010
+#define INT_STATUS_ENABLE_COUNTER_GET(x) \
+	(((x) & INT_STATUS_ENABLE_COUNTER_MASK) >> \
+						INT_STATUS_ENABLE_COUNTER_LSB)
+#define INT_STATUS_ENABLE_COUNTER_SET(x) \
+	(((x) << INT_STATUS_ENABLE_COUNTER_LSB) & \
+	 INT_STATUS_ENABLE_COUNTER_MASK)
+#define INT_STATUS_ENABLE_MBOX_DATA_MSB 3
+#define INT_STATUS_ENABLE_MBOX_DATA_LSB 0
+#define INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f
+#define INT_STATUS_ENABLE_MBOX_DATA_GET(x) \
+	(((x) & INT_STATUS_ENABLE_MBOX_DATA_MASK) >> \
+	 INT_STATUS_ENABLE_MBOX_DATA_LSB)
+#define INT_STATUS_ENABLE_MBOX_DATA_SET(x) \
+	(((x) << INT_STATUS_ENABLE_MBOX_DATA_LSB) & \
+	 INT_STATUS_ENABLE_MBOX_DATA_MASK)
+
+#define CPU_INT_STATUS_ENABLE_ADDRESS 0x00000419
+#define CPU_INT_STATUS_ENABLE_OFFSET 0x00000419
+#define CPU_INT_STATUS_ENABLE_BIT_MSB 7
+#define CPU_INT_STATUS_ENABLE_BIT_LSB 0
+#define CPU_INT_STATUS_ENABLE_BIT_MASK 0x000000ff
+#define CPU_INT_STATUS_ENABLE_BIT_GET(x) \
+	(((x) & CPU_INT_STATUS_ENABLE_BIT_MASK) >> \
+						CPU_INT_STATUS_ENABLE_BIT_LSB)
+#define CPU_INT_STATUS_ENABLE_BIT_SET(x) \
+	(((x) << CPU_INT_STATUS_ENABLE_BIT_LSB) & \
+	 CPU_INT_STATUS_ENABLE_BIT_MASK)
+
+#define ERROR_STATUS_ENABLE_ADDRESS 0x0000041a
+#define ERROR_STATUS_ENABLE_OFFSET 0x0000041a
+#define ERROR_STATUS_ENABLE_WAKEUP_MSB 2
+#define ERROR_STATUS_ENABLE_WAKEUP_LSB 2
+#define ERROR_STATUS_ENABLE_WAKEUP_MASK 0x00000004
+#define ERROR_STATUS_ENABLE_WAKEUP_GET(x) \
+	(((x) & ERROR_STATUS_ENABLE_WAKEUP_MASK) >> \
+	 ERROR_STATUS_ENABLE_WAKEUP_LSB)
+#define ERROR_STATUS_ENABLE_WAKEUP_SET(x) \
+	(((x) << ERROR_STATUS_ENABLE_WAKEUP_LSB) & \
+	 ERROR_STATUS_ENABLE_WAKEUP_MASK)
+#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MSB 1
+#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 1
+#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00000002
+#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_GET(x) \
+	(((x) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) >> \
+	 ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB)
+#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(x) \
+	(((x) << ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) & \
+	 ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK)
+#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MSB 0
+#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 0
+#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00000001
+#define ERROR_STATUS_ENABLE_TX_OVERFLOW_GET(x) \
+	(((x) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) >> \
+	 ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB)
+#define ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(x) \
+	(((x) << ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) & \
+	 ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK)
+
+#define COUNTER_INT_STATUS_ENABLE_ADDRESS 0x0000041b
+#define COUNTER_INT_STATUS_ENABLE_OFFSET 0x0000041b
+#define COUNTER_INT_STATUS_ENABLE_BIT_MSB 7
+#define COUNTER_INT_STATUS_ENABLE_BIT_LSB 0
+#define COUNTER_INT_STATUS_ENABLE_BIT_MASK 0x000000ff
+#define COUNTER_INT_STATUS_ENABLE_BIT_GET(x) \
+	(((x) & COUNTER_INT_STATUS_ENABLE_BIT_MASK) >> \
+	 COUNTER_INT_STATUS_ENABLE_BIT_LSB)
+#define COUNTER_INT_STATUS_ENABLE_BIT_SET(x) \
+	(((x) << COUNTER_INT_STATUS_ENABLE_BIT_LSB) & \
+	 COUNTER_INT_STATUS_ENABLE_BIT_MASK)
+
+#define COUNT_ADDRESS 0x00000420
+#define COUNT_OFFSET 0x00000420
+#define COUNT_VALUE_MSB 7
+#define COUNT_VALUE_LSB 0
+#define COUNT_VALUE_MASK 0x000000ff
+#define COUNT_VALUE_GET(x) (((x) & COUNT_VALUE_MASK) >> COUNT_VALUE_LSB)
+#define COUNT_VALUE_SET(x) (((x) << COUNT_VALUE_LSB) & COUNT_VALUE_MASK)
+
+#define COUNT_DEC_ADDRESS 0x00000440
+#define COUNT_DEC_OFFSET 0x00000440
+#define COUNT_DEC_VALUE_MSB 7
+#define COUNT_DEC_VALUE_LSB 0
+#define COUNT_DEC_VALUE_MASK 0x000000ff
+#define COUNT_DEC_VALUE_GET(x) \
+	(((x) & COUNT_DEC_VALUE_MASK) >> COUNT_DEC_VALUE_LSB)
+#define COUNT_DEC_VALUE_SET(x) \
+	(((x) << COUNT_DEC_VALUE_LSB) & COUNT_DEC_VALUE_MASK)
+
+#define SCRATCH_ADDRESS 0x00000460
+#define SCRATCH_OFFSET 0x00000460
+#define SCRATCH_VALUE_MSB 7
+#define SCRATCH_VALUE_LSB 0
+#define SCRATCH_VALUE_MASK 0x000000ff
+#define SCRATCH_VALUE_GET(x) (((x) & SCRATCH_VALUE_MASK) >> SCRATCH_VALUE_LSB)
+#define SCRATCH_VALUE_SET(x) (((x) << SCRATCH_VALUE_LSB) & SCRATCH_VALUE_MASK)
+
+#define FIFO_TIMEOUT_ADDRESS 0x00000468
+#define FIFO_TIMEOUT_OFFSET 0x00000468
+#define FIFO_TIMEOUT_VALUE_MSB 7
+#define FIFO_TIMEOUT_VALUE_LSB 0
+#define FIFO_TIMEOUT_VALUE_MASK 0x000000ff
+#define FIFO_TIMEOUT_VALUE_GET(x) \
+	(((x) & FIFO_TIMEOUT_VALUE_MASK) >> FIFO_TIMEOUT_VALUE_LSB)
+#define FIFO_TIMEOUT_VALUE_SET(x) \
+	(((x) << FIFO_TIMEOUT_VALUE_LSB) & FIFO_TIMEOUT_VALUE_MASK)
+
+#define FIFO_TIMEOUT_ENABLE_ADDRESS 0x00000469
+#define FIFO_TIMEOUT_ENABLE_OFFSET 0x00000469
+#define FIFO_TIMEOUT_ENABLE_SET_MSB 0
+#define FIFO_TIMEOUT_ENABLE_SET_LSB 0
+#define FIFO_TIMEOUT_ENABLE_SET_MASK 0x00000001
+#define FIFO_TIMEOUT_ENABLE_SET_GET(x) \
+	(((x) & FIFO_TIMEOUT_ENABLE_SET_MASK) >> FIFO_TIMEOUT_ENABLE_SET_LSB)
+#define FIFO_TIMEOUT_ENABLE_SET_SET(x) \
+	(((x) << FIFO_TIMEOUT_ENABLE_SET_LSB) & FIFO_TIMEOUT_ENABLE_SET_MASK)
+
+#define INT_WLAN_ADDRESS 0x00000472
+#define INT_TARGET_ADDRESS INT_WLAN_ADDRESS
+#define INT_WLAN_OFFSET 0x00000472
+#define INT_WLAN_VECTOR_MSB 7
+#define INT_WLAN_VECTOR_LSB 0
+#define INT_WLAN_VECTOR_MASK 0x000000ff
+#define INT_WLAN_VECTOR_GET(x) \
+	(((x) & INT_WLAN_VECTOR_MASK) >> INT_WLAN_VECTOR_LSB)
+#define INT_WLAN_VECTOR_SET(x) \
+	(((x) << INT_WLAN_VECTOR_LSB) & INT_WLAN_VECTOR_MASK)
+
+#define SPI_CONFIG_ADDRESS 0x00000480
+#define SPI_CONFIG_OFFSET 0x00000480
+#define SPI_CONFIG_SPI_RESET_MSB 4
+#define SPI_CONFIG_SPI_RESET_LSB 4
+#define SPI_CONFIG_SPI_RESET_MASK 0x00000010
+#define SPI_CONFIG_SPI_RESET_GET(x) \
+	(((x) & SPI_CONFIG_SPI_RESET_MASK) >> SPI_CONFIG_SPI_RESET_LSB)
+#define SPI_CONFIG_SPI_RESET_SET(x) \
+	(((x) << SPI_CONFIG_SPI_RESET_LSB) & SPI_CONFIG_SPI_RESET_MASK)
+#define SPI_CONFIG_INTERRUPT_ENABLE_MSB 3
+#define SPI_CONFIG_INTERRUPT_ENABLE_LSB 3
+#define SPI_CONFIG_INTERRUPT_ENABLE_MASK 0x00000008
+#define SPI_CONFIG_INTERRUPT_ENABLE_GET(x) \
+	(((x) & SPI_CONFIG_INTERRUPT_ENABLE_MASK) >> \
+	 SPI_CONFIG_INTERRUPT_ENABLE_LSB)
+#define SPI_CONFIG_INTERRUPT_ENABLE_SET(x) \
+	(((x) << SPI_CONFIG_INTERRUPT_ENABLE_LSB) & \
+	 SPI_CONFIG_INTERRUPT_ENABLE_MASK)
+#define SPI_CONFIG_TEST_MODE_MSB 2
+#define SPI_CONFIG_TEST_MODE_LSB 2
+#define SPI_CONFIG_TEST_MODE_MASK 0x00000004
+#define SPI_CONFIG_TEST_MODE_GET(x) \
+	(((x) & SPI_CONFIG_TEST_MODE_MASK) >> SPI_CONFIG_TEST_MODE_LSB)
+#define SPI_CONFIG_TEST_MODE_SET(x) \
+	(((x) << SPI_CONFIG_TEST_MODE_LSB) & SPI_CONFIG_TEST_MODE_MASK)
+#define SPI_CONFIG_DATA_SIZE_MSB 1
+#define SPI_CONFIG_DATA_SIZE_LSB 0
+#define SPI_CONFIG_DATA_SIZE_MASK 0x00000003
+#define SPI_CONFIG_DATA_SIZE_GET(x) \
+	(((x) & SPI_CONFIG_DATA_SIZE_MASK) >> SPI_CONFIG_DATA_SIZE_LSB)
+#define SPI_CONFIG_DATA_SIZE_SET(x) \
+	(((x) << SPI_CONFIG_DATA_SIZE_LSB) & SPI_CONFIG_DATA_SIZE_MASK)
+
+#define SPI_STATUS_ADDRESS 0x00000481
+#define SPI_STATUS_OFFSET 0x00000481
+#define SPI_STATUS_ADDR_ERR_MSB 3
+#define SPI_STATUS_ADDR_ERR_LSB 3
+#define SPI_STATUS_ADDR_ERR_MASK 0x00000008
+#define SPI_STATUS_ADDR_ERR_GET(x) \
+	(((x) & SPI_STATUS_ADDR_ERR_MASK) >> SPI_STATUS_ADDR_ERR_LSB)
+#define SPI_STATUS_ADDR_ERR_SET(x) \
+	(((x) << SPI_STATUS_ADDR_ERR_LSB) & SPI_STATUS_ADDR_ERR_MASK)
+#define SPI_STATUS_RD_ERR_MSB 2
+#define SPI_STATUS_RD_ERR_LSB 2
+#define SPI_STATUS_RD_ERR_MASK 0x00000004
+#define SPI_STATUS_RD_ERR_GET(x) \
+	(((x) & SPI_STATUS_RD_ERR_MASK) >> SPI_STATUS_RD_ERR_LSB)
+#define SPI_STATUS_RD_ERR_SET(x) \
+	(((x) << SPI_STATUS_RD_ERR_LSB) & SPI_STATUS_RD_ERR_MASK)
+#define SPI_STATUS_WR_ERR_MSB 1
+#define SPI_STATUS_WR_ERR_LSB 1
+#define SPI_STATUS_WR_ERR_MASK 0x00000002
+#define SPI_STATUS_WR_ERR_GET(x) \
+	(((x) & SPI_STATUS_WR_ERR_MASK) >> SPI_STATUS_WR_ERR_LSB)
+#define SPI_STATUS_WR_ERR_SET(x) \
+	(((x) << SPI_STATUS_WR_ERR_LSB) & SPI_STATUS_WR_ERR_MASK)
+#define SPI_STATUS_READY_MSB 0
+#define SPI_STATUS_READY_LSB 0
+#define SPI_STATUS_READY_MASK 0x00000001
+#define SPI_STATUS_READY_GET(x) \
+	(((x) & SPI_STATUS_READY_MASK) >> SPI_STATUS_READY_LSB)
+#define SPI_STATUS_READY_SET(x) \
+	(((x) << SPI_STATUS_READY_LSB) & SPI_STATUS_READY_MASK)
+#define INT_WLAN_ADDRESS 0x00000472
+#define INT_WLAN_OFFSET 0x00000472
+#define INT_WLAN_VECTOR_MSB 7
+#define INT_WLAN_VECTOR_LSB 0
+#define INT_WLAN_VECTOR_MASK 0x000000ff
+#define INT_WLAN_VECTOR_GET(x) \
+	(((x) & INT_WLAN_VECTOR_MASK) >> INT_WLAN_VECTOR_LSB)
+#define INT_WLAN_VECTOR_SET(x) \
+	(((x) << INT_WLAN_VECTOR_LSB) & INT_WLAN_VECTOR_MASK)
+
+#endif /* _MBOX_HOST_REG_H_ */
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index 2c29538..c38f1be 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -23,7 +23,7 @@
 #include "gsi_emulation.h"
 
 #define GSI_CMD_TIMEOUT (5*HZ)
-#define GSI_STOP_CMD_TIMEOUT_MS 20
+#define GSI_STOP_CMD_TIMEOUT_MS 50
 #define GSI_MAX_CH_LOW_WEIGHT 15
 
 #define GSI_RESET_WA_MIN_SLEEP 1000
@@ -2788,27 +2788,21 @@
 		return -GSI_STATUS_UNSUPPORTED_OP;
 	}
 
+	spin_lock_irqsave(&gsi_ctx->slock, flags);
 	if (curr == GSI_CHAN_MODE_CALLBACK &&
 			mode == GSI_CHAN_MODE_POLL) {
-		spin_lock_irqsave(&gsi_ctx->slock, flags);
 		__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, 0);
-		spin_unlock_irqrestore(&gsi_ctx->slock, flags);
-		spin_lock_irqsave(&ctx->ring.slock, flags);
 		atomic_set(&ctx->poll_mode, mode);
-		spin_unlock_irqrestore(&ctx->ring.slock, flags);
 		ctx->stats.callback_to_poll++;
 	}
 
 	if (curr == GSI_CHAN_MODE_POLL &&
 			mode == GSI_CHAN_MODE_CALLBACK) {
-		spin_lock_irqsave(&ctx->ring.slock, flags);
 		atomic_set(&ctx->poll_mode, mode);
-		spin_unlock_irqrestore(&ctx->ring.slock, flags);
-		spin_lock_irqsave(&gsi_ctx->slock, flags);
 		__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, ~0);
-		spin_unlock_irqrestore(&gsi_ctx->slock, flags);
 		ctx->stats.poll_to_callback++;
 	}
+	spin_unlock_irqrestore(&gsi_ctx->slock, flags);
 
 	return GSI_STATUS_SUCCESS;
 }
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
index 8b998fe..704308f 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
@@ -2952,6 +2952,7 @@
 	int i;
 	unsigned long flags;
 	int res;
+	struct ipa3_usb_pm_context *pm_ctx;
 
 	pr_debug("entry\n");
 	ipa3_usb_ctx = kzalloc(sizeof(struct ipa3_usb_context), GFP_KERNEL);
@@ -2971,19 +2972,13 @@
 	ipa3_usb_ctx->dl_data_pending = false;
 	mutex_init(&ipa3_usb_ctx->general_mutex);
 
-	if (ipa_pm_is_used()) {
-		struct ipa3_usb_pm_context *pm_ctx;
-
-		pm_ctx =
-			&ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].pm_ctx;
-		pm_ctx->hdl = ~0;
-		pm_ctx->remote_wakeup_work =
-			&ipa3_usb_notify_remote_wakeup_work;
-		pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_DPL].pm_ctx;
-		pm_ctx->hdl = ~0;
-		pm_ctx->remote_wakeup_work =
-			&ipa3_usb_dpl_notify_remote_wakeup_work;
-	}
+	/* init PM related members */
+	pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].pm_ctx;
+	pm_ctx->hdl = ~0;
+	pm_ctx->remote_wakeup_work = &ipa3_usb_notify_remote_wakeup_work;
+	pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_DPL].pm_ctx;
+	pm_ctx->hdl = ~0;
+	pm_ctx->remote_wakeup_work = &ipa3_usb_dpl_notify_remote_wakeup_work;
 
 	for (i = 0; i < IPA_USB_TRANSPORT_MAX; i++) {
 		ipa3_usb_ctx->ttype_ctx[i].rm_ctx.prod_valid = false;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index 10468f3..6f9afa6 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -3938,11 +3938,8 @@
 	}
 
 	ipa_ctx->logbuf = ipc_log_context_create(IPA_IPC_LOG_PAGES, "ipa", 0);
-	if (ipa_ctx->logbuf == NULL) {
-		IPAERR("failed to get logbuf\n");
-		result = -ENOMEM;
-		goto fail_logbuf;
-	}
+	if (ipa_ctx->logbuf == NULL)
+		IPADBG("failed to create IPC log, continue...\n");
 
 	ipa_ctx->pdev = ipa_dev;
 	ipa_ctx->uc_pdev = ipa_dev;
@@ -4488,7 +4485,6 @@
 	kfree(ipa_ctx->ctrl);
 fail_mem_ctrl:
 	ipc_log_context_destroy(ipa_ctx->logbuf);
-fail_logbuf:
 	kfree(ipa_ctx);
 	ipa_ctx = NULL;
 fail_mem_ctx:
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
index c2f7aae..0224f98 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
@@ -91,6 +91,7 @@
 	__stringify(IPA_PER_CLIENT_STATS_DISCONNECT_EVENT),
 	__stringify(ADD_BRIDGE_VLAN_MAPPING),
 	__stringify(DEL_BRIDGE_VLAN_MAPPING),
+	__stringify(WLAN_FWR_SSR_BEFORE_SHUTDOWN),
 };
 
 const char *ipa_hdr_l2_type_name[] = {
@@ -1903,7 +1904,7 @@
 				ipc_log_context_create(IPA_IPC_LOG_PAGES,
 				"ipa_low", 0);
 			if (ipa_ipc_low_buff == NULL)
-				IPAERR("failed to get logbuf_low\n");
+				IPADBG("failed to get logbuf_low\n");
 		}
 		ipa_ctx->logbuf_low = ipa_ipc_low_buff;
 	} else {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 2b94f0e..8a773e4 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -5018,7 +5018,7 @@
 
 	ipa3_ctx->logbuf = ipc_log_context_create(IPA_IPC_LOG_PAGES, "ipa", 0);
 	if (ipa3_ctx->logbuf == NULL)
-		IPAERR("failed to create IPC log, continue...\n");
+		IPADBG("failed to create IPC log, continue...\n");
 
 	/* ipa3_ctx->pdev and ipa3_ctx->uc_pdev will be set in the smmu probes*/
 	ipa3_ctx->master_pdev = ipa_pdev;
@@ -5041,6 +5041,7 @@
 	ipa3_ctx->apply_rg10_wa = resource_p->apply_rg10_wa;
 	ipa3_ctx->gsi_ch20_wa = resource_p->gsi_ch20_wa;
 	ipa3_ctx->use_ipa_pm = resource_p->use_ipa_pm;
+	ipa3_ctx->wdi_over_pcie = resource_p->wdi_over_pcie;
 	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];
@@ -5872,6 +5873,12 @@
 		return result;
 	}
 
+	ipa_drv_res->wdi_over_pcie =
+		of_property_read_bool(pdev->dev.of_node,
+		"qcom,wlan-ce-db-over-pcie");
+	IPADBG("Is wdi_over_pcie ? (%s)\n",
+		ipa_drv_res->wdi_over_pcie ? "Yes":"No");
+
 	/*
 	 * If we're on emulator, get its interrupt controller's mem
 	 * start and size
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
index 5bcd49e..cfac126 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
@@ -63,7 +63,15 @@
 	IPADBG("Enabling data path\n");
 	if (IPA_CLIENT_IS_CONS(ep->client)) {
 		memset(&holb_cfg, 0, sizeof(holb_cfg));
-		holb_cfg.en = IPA_HOLB_TMR_DIS;
+		/*
+		 * Set HOLB on USB DPL CONS to avoid IPA stall
+		 * if DPL client is not pulling the data
+		 * on other end from IPA hw.
+		 */
+		if (ep->client == IPA_CLIENT_USB_DPL_CONS)
+			holb_cfg.en = IPA_HOLB_TMR_EN;
+		else
+			holb_cfg.en = IPA_HOLB_TMR_DIS;
 		holb_cfg.tmr_val = 0;
 		res = ipa3_cfg_ep_holb(clnt_hdl, &holb_cfg);
 	}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index 10abdcf..0925e8c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -75,6 +75,7 @@
 	__stringify(IPA_PER_CLIENT_STATS_DISCONNECT_EVENT),
 	__stringify(ADD_BRIDGE_VLAN_MAPPING),
 	__stringify(DEL_BRIDGE_VLAN_MAPPING),
+	__stringify(WLAN_FWR_SSR_BEFORE_SHUTDOWN),
 };
 
 const char *ipa3_hdr_l2_type_name[] = {
@@ -2089,7 +2090,7 @@
 					"ipa_low", 0);
 		}
 			if (ipa_ipc_low_buff == NULL)
-				IPAERR("failed to get logbuf_low\n");
+				IPADBG("failed to get logbuf_low\n");
 		ipa3_ctx->logbuf_low = ipa_ipc_low_buff;
 	} else {
 		ipa3_ctx->logbuf_low = NULL;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c
index 547c9da..5e398cc 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hw_stats.c
@@ -231,6 +231,9 @@
 
 	IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size);
 
+	if (offset.size == 0)
+		return 0;
+
 	mem.size = offset.size;
 	mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
 		mem.size,
@@ -541,6 +544,9 @@
 
 	IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size);
 
+	if (offset.size == 0)
+		return 0;
+
 	mem.size = offset.size;
 	mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
 		mem.size,
@@ -1099,6 +1105,11 @@
 
 	IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size);
 
+	if (offset.size == 0) {
+		ret = 0;
+		goto free_offset;
+	}
+
 	mem.size = offset.size;
 	mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
 		mem.size,
@@ -1368,6 +1379,9 @@
 
 	IPADBG_LOW("offset = %d size = %d\n", offset.offset, offset.size);
 
+	if (offset.size == 0)
+		return 0;
+
 	mem.size = offset.size;
 	mem.base = dma_alloc_coherent(ipa3_ctx->pdev,
 		mem.size,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index c860bd0..43f4c74 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1604,6 +1604,7 @@
 	struct mutex ipa_cne_evt_lock;
 	bool use_ipa_pm;
 	bool vlan_mode_iface[IPA_VLAN_IF_MAX];
+	bool wdi_over_pcie;
 };
 
 struct ipa3_plat_drv_res {
@@ -1638,6 +1639,7 @@
 	struct ipa_tz_unlock_reg_info *ipa_tz_unlock_reg;
 	bool use_ipa_pm;
 	struct ipa_pm_init_params pm_init;
+	bool wdi_over_pcie;
 };
 
 /**
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 f4068bf..2401166 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_ntn.c
@@ -508,6 +508,8 @@
 		result = -EFAULT;
 		goto fail_smmu_map_dl;
 	}
+
+	IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
 	IPADBG("client %d (ep: %d) connected\n", in->dl.client,
 		ipa_ep_idx_dl);
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
index 13d2511..3cbc0c6 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
@@ -756,16 +756,21 @@
 		return -EINVAL;
 	}
 
-	if (IPA_CLIENT_IS_CONS(in->sys.client)) {
-		if (in->u.dl.comp_ring_base_pa % IPA_WDI_RING_ALIGNMENT ||
-			in->u.dl.ce_ring_base_pa % IPA_WDI_RING_ALIGNMENT) {
-			IPAERR("alignment failure on TX\n");
-			return -EINVAL;
-		}
-	} else {
-		if (in->u.ul.rdy_ring_base_pa % IPA_WDI_RING_ALIGNMENT) {
-			IPAERR("alignment failure on RX\n");
-			return -EINVAL;
+	if (!in->smmu_enabled) {
+		if (IPA_CLIENT_IS_CONS(in->sys.client)) {
+			if (in->u.dl.comp_ring_base_pa %
+				IPA_WDI_RING_ALIGNMENT ||
+				in->u.dl.ce_ring_base_pa %
+				IPA_WDI_RING_ALIGNMENT) {
+				IPAERR("alignment failure on TX\n");
+					return -EINVAL;
+			}
+		} else {
+			if (in->u.ul.rdy_ring_base_pa %
+				IPA_WDI_RING_ALIGNMENT) {
+				IPAERR("alignment failure on RX\n");
+				return -EINVAL;
+			}
 		}
 	}
 
@@ -795,43 +800,73 @@
 			cmd.size = sizeof(*tx_2);
 		else
 			cmd.size = sizeof(*tx);
-		IPADBG("comp_ring_base_pa=0x%pa\n",
-				&in->u.dl.comp_ring_base_pa);
-		IPADBG("comp_ring_size=%d\n", in->u.dl.comp_ring_size);
-		IPADBG("ce_ring_base_pa=0x%pa\n", &in->u.dl.ce_ring_base_pa);
-		IPADBG("ce_ring_size=%d\n", in->u.dl.ce_ring_size);
-		IPADBG("ce_ring_doorbell_pa=0x%pa\n",
-				&in->u.dl.ce_door_bell_pa);
-		IPADBG("num_tx_buffers=%d\n", in->u.dl.num_tx_buffers);
+		if (in->smmu_enabled) {
+			IPADBG("comp_ring_size=%d\n",
+				in->u.dl_smmu.comp_ring_size);
+			IPADBG("ce_ring_size=%d\n", in->u.dl_smmu.ce_ring_size);
+			IPADBG("ce_ring_doorbell_pa=0x%pa\n",
+					&in->u.dl_smmu.ce_door_bell_pa);
+			IPADBG("num_tx_buffers=%d\n",
+				in->u.dl_smmu.num_tx_buffers);
+		} else {
+			IPADBG("comp_ring_base_pa=0x%pa\n",
+					&in->u.dl.comp_ring_base_pa);
+			IPADBG("comp_ring_size=%d\n", in->u.dl.comp_ring_size);
+			IPADBG("ce_ring_base_pa=0x%pa\n",
+				&in->u.dl.ce_ring_base_pa);
+			IPADBG("ce_ring_size=%d\n", in->u.dl.ce_ring_size);
+			IPADBG("ce_ring_doorbell_pa=0x%pa\n",
+					&in->u.dl.ce_door_bell_pa);
+			IPADBG("num_tx_buffers=%d\n", in->u.dl.num_tx_buffers);
+		}
 	} else {
 		if (ipa3_ctx->ipa_wdi2)
 			cmd.size = sizeof(*rx_2);
 		else
 			cmd.size = sizeof(*rx);
-		IPADBG("rx_ring_base_pa=0x%pa\n",
-			&in->u.ul.rdy_ring_base_pa);
-		IPADBG("rx_ring_size=%d\n",
-			in->u.ul.rdy_ring_size);
-		IPADBG("rx_ring_rp_pa=0x%pa\n",
-			&in->u.ul.rdy_ring_rp_pa);
-		IPADBG("rx_comp_ring_base_pa=0x%pa\n",
-			&in->u.ul.rdy_comp_ring_base_pa);
-		IPADBG("rx_comp_ring_size=%d\n",
-			in->u.ul.rdy_comp_ring_size);
-		IPADBG("rx_comp_ring_wp_pa=0x%pa\n",
-			&in->u.ul.rdy_comp_ring_wp_pa);
-		ipa3_ctx->uc_ctx.rdy_ring_base_pa =
-			in->u.ul.rdy_ring_base_pa;
-		ipa3_ctx->uc_ctx.rdy_ring_rp_pa =
-			in->u.ul.rdy_ring_rp_pa;
-		ipa3_ctx->uc_ctx.rdy_ring_size =
-			in->u.ul.rdy_ring_size;
-		ipa3_ctx->uc_ctx.rdy_comp_ring_base_pa =
-			in->u.ul.rdy_comp_ring_base_pa;
-		ipa3_ctx->uc_ctx.rdy_comp_ring_wp_pa =
-			in->u.ul.rdy_comp_ring_wp_pa;
-		ipa3_ctx->uc_ctx.rdy_comp_ring_size =
-			in->u.ul.rdy_comp_ring_size;
+		if (in->smmu_enabled) {
+			IPADBG("rx_ring_size=%d\n",
+				in->u.ul_smmu.rdy_ring_size);
+			IPADBG("rx_ring_rp_pa=0x%pa\n",
+				&in->u.ul_smmu.rdy_ring_rp_pa);
+			IPADBG("rx_comp_ring_size=%d\n",
+				in->u.ul_smmu.rdy_comp_ring_size);
+			IPADBG("rx_comp_ring_wp_pa=0x%pa\n",
+				&in->u.ul_smmu.rdy_comp_ring_wp_pa);
+			ipa3_ctx->uc_ctx.rdy_ring_rp_pa =
+				in->u.ul_smmu.rdy_ring_rp_pa;
+			ipa3_ctx->uc_ctx.rdy_ring_size =
+				in->u.ul_smmu.rdy_ring_size;
+			ipa3_ctx->uc_ctx.rdy_comp_ring_wp_pa =
+				in->u.ul_smmu.rdy_comp_ring_wp_pa;
+			ipa3_ctx->uc_ctx.rdy_comp_ring_size =
+				in->u.ul_smmu.rdy_comp_ring_size;
+		} else {
+			IPADBG("rx_ring_base_pa=0x%pa\n",
+				&in->u.ul.rdy_ring_base_pa);
+			IPADBG("rx_ring_size=%d\n",
+				in->u.ul.rdy_ring_size);
+			IPADBG("rx_ring_rp_pa=0x%pa\n",
+				&in->u.ul.rdy_ring_rp_pa);
+			IPADBG("rx_comp_ring_base_pa=0x%pa\n",
+				&in->u.ul.rdy_comp_ring_base_pa);
+			IPADBG("rx_comp_ring_size=%d\n",
+				in->u.ul.rdy_comp_ring_size);
+			IPADBG("rx_comp_ring_wp_pa=0x%pa\n",
+				&in->u.ul.rdy_comp_ring_wp_pa);
+			ipa3_ctx->uc_ctx.rdy_ring_base_pa =
+				in->u.ul.rdy_ring_base_pa;
+			ipa3_ctx->uc_ctx.rdy_ring_rp_pa =
+				in->u.ul.rdy_ring_rp_pa;
+			ipa3_ctx->uc_ctx.rdy_ring_size =
+				in->u.ul.rdy_ring_size;
+			ipa3_ctx->uc_ctx.rdy_comp_ring_base_pa =
+				in->u.ul.rdy_comp_ring_base_pa;
+			ipa3_ctx->uc_ctx.rdy_comp_ring_wp_pa =
+				in->u.ul.rdy_comp_ring_wp_pa;
+			ipa3_ctx->uc_ctx.rdy_comp_ring_size =
+				in->u.ul.rdy_comp_ring_size;
+		}
 	}
 
 	cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
@@ -945,10 +980,11 @@
 			tx->comp_ring_size = len;
 			len = in->smmu_enabled ? in->u.dl_smmu.ce_ring_size :
 				in->u.dl.ce_ring_size;
-			IPADBG("TX CE ring smmu_en=%d ring_size=%d %d\n",
+			IPADBG("TX CE ring smmu_en=%d ring_size=%d %d 0x%lx\n",
 					in->smmu_enabled,
 					in->u.dl_smmu.ce_ring_size,
-					in->u.dl.ce_ring_size);
+					in->u.dl.ce_ring_size,
+					va);
 			if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
 						in->smmu_enabled,
 						in->u.dl.ce_ring_base_pa,
@@ -975,8 +1011,19 @@
 				result = -ENOMEM;
 				goto uc_timeout;
 			}
-			tx->ce_ring_doorbell_pa = va;
-			tx->num_tx_buffers = in->u.dl.num_tx_buffers;
+
+			IPADBG("CE doorbell pa: 0x%pa va:0x%lx\n", &pa, va);
+			IPADBG("Is wdi_over_pcie ? (%s)\n",
+				ipa3_ctx->wdi_over_pcie ? "Yes":"No");
+
+			if (ipa3_ctx->wdi_over_pcie)
+				tx->ce_ring_doorbell_pa = pa;
+			else
+				tx->ce_ring_doorbell_pa = va;
+
+			tx->num_tx_buffers = in->smmu_enabled ?
+				in->u.dl_smmu.num_tx_buffers :
+				in->u.dl.num_tx_buffers;
 			tx->ipa_pipe_number = ipa_ep_idx;
 		}
 		out->uc_door_bell_pa = ipa3_ctx->ipa_wrapper_base +
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index d015b22..3569760 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.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
@@ -1570,6 +1570,12 @@
 		goto bail_free_fltrt;
 	}
 
+	/* create an IPC buffer for the registers dump */
+	ipahal_ctx->regdumpbuf = ipc_log_context_create(IPAHAL_IPC_LOG_PAGES,
+		"ipa_regs", 0);
+	if (ipahal_ctx->regdumpbuf == NULL)
+		IPAHAL_ERR("failed to create IPA regdump log, continue...\n");
+
 	ipahal_debugfs_init();
 
 	return 0;
@@ -1577,6 +1583,8 @@
 bail_free_fltrt:
 	ipahal_fltrt_destroy();
 bail_free_ctx:
+	if (ipahal_ctx->regdumpbuf)
+		ipc_log_context_destroy(ipahal_ctx->regdumpbuf);
 	kfree(ipahal_ctx);
 	ipahal_ctx = NULL;
 bail_err_exit:
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 d46f13c..816bc58 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
@@ -46,23 +46,6 @@
 			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_DBG_REG_IPC_ONLY(fmt, args...) \
-	do { \
-		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, \
@@ -73,9 +56,24 @@
 				IPAHAL_DRV_NAME " %s:%d " fmt, ## args); \
 		} while (0)
 
+#define IPAHAL_DBG_REG(fmt, args...) \
+	do { \
+		pr_err(fmt, ## args); \
+		IPA_IPC_LOGGING(ipahal_ctx->regdumpbuf, \
+			" %s:%d " fmt, ## args); \
+	} while (0)
+
+#define IPAHAL_DBG_REG_IPC_ONLY(fmt, args...) \
+	do { \
+		IPA_IPC_LOGGING(ipahal_ctx->regdumpbuf, \
+			" %s:%d " fmt, ## args); \
+	} while (0)
+
 #define IPAHAL_MEM_ALLOC(__size, __is_atomic_ctx) \
 	(kzalloc((__size), ((__is_atomic_ctx) ? GFP_ATOMIC : GFP_KERNEL)))
 
+#define IPAHAL_IPC_LOG_PAGES 50
+
 /*
  * struct ipahal_context - HAL global context data
  * @hw_type: IPA H/W type/version.
@@ -92,6 +90,7 @@
 	struct dentry *dent;
 	struct device *ipa_pdev;
 	struct ipa_mem_buffer empty_fltrt_tbl;
+	void *regdumpbuf;
 };
 
 extern struct ipahal_context *ipahal_ctx;
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 2dbea95..88998ce 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -2237,7 +2237,7 @@
 		0x00000CC0, 0x70, 10, 23, 1},
 };
 
-int ipahal_print_all_regs(bool print_to_dmesg)
+void ipahal_print_all_regs(bool print_to_dmesg)
 {
 	int i, j;
 
@@ -2247,7 +2247,7 @@
 	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;
+		return;
 	}
 
 	for (i = 0; i < IPA_REG_MAX ; i++) {
@@ -2267,11 +2267,17 @@
 					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));
+		for (; j < ipahal_reg_objs[ipahal_ctx->hw_type][i].n_end; j++) {
+			if (print_to_dmesg)
+				IPAHAL_DBG_REG("%s_%u=0x%x\n",
+					ipahal_reg_name_str(i),
+					j, ipahal_read_reg_n(i, j));
+			else
+				IPAHAL_DBG_REG_IPC_ONLY("%s_%u=0x%x\n",
+					ipahal_reg_name_str(i),
+					j, ipahal_read_reg_n(i, j));
+		}
 	}
-	return 0;
 }
 
 /*
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 fdf4fd1..c1c86a3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
@@ -524,7 +524,7 @@
 };
 
 
-int ipahal_print_all_regs(bool print_to_dmesg);
+void ipahal_print_all_regs(bool print_to_dmesg);
 
 /*
  * ipahal_reg_name_str() - returns string that represent the register
diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c
index 3e577cf..3e245cc 100644
--- a/drivers/platform/msm/mhi_dev/mhi.c
+++ b/drivers/platform/msm/mhi_dev/mhi.c
@@ -1494,6 +1494,7 @@
 	enum mhi_dev_state state;
 	enum mhi_dev_event event = 0;
 	bool mhi_reset = false;
+	uint32_t bhi_imgtxdb = 0;
 
 	mutex_lock(&mhi_ctx->mhi_lock);
 	/* Check for interrupts */
@@ -1531,6 +1532,10 @@
 			pr_err("error sending SM event\n");
 			goto fail;
 		}
+
+		rc = mhi_dev_mmio_read(mhi, BHI_IMGTXDB, &bhi_imgtxdb);
+		mhi_log(MHI_MSG_VERBOSE,
+			"BHI_IMGTXDB = 0x%x\n", bhi_imgtxdb);
 	}
 
 	if (int_value & MHI_MMIO_CTRL_CRDB_STATUS_MSK) {
@@ -1889,6 +1894,7 @@
 			(struct mhi_dev_client_cb_reason *cb))
 {
 	int rc = 0;
+	int i = 0;
 	struct mhi_dev_channel *ch;
 	struct platform_device *pdev;
 
@@ -1912,6 +1918,38 @@
 		goto exit;
 	}
 
+	/* Pre allocate event requests */
+	ch->ereqs = kcalloc(MHI_MAX_EVT_REQ, sizeof(*ch->ereqs), GFP_KERNEL);
+	if (!ch->ereqs) {
+		rc = -ENOMEM;
+		goto free_client;
+	}
+	/* pre allocate buffers to queue transfer completion events */
+	ch->tr_events = kcalloc(MHI_MAX_EVT_REQ,
+				MAX_TR_EVENTS * sizeof(*ch->tr_events),
+				GFP_KERNEL);
+	if (!ch->tr_events) {
+		rc = -ENOMEM;
+		goto free_ereqs;
+	}
+
+	/*
+	 * Organize the above allocated event request block and
+	 * completion event block into linked lists. Each event
+	 * request includes a pointer to a block of MAX_TR_EVENTS
+	 * completion events.
+	 */
+	INIT_LIST_HEAD(&mhi_ctx->ch[chan_id].event_req_buffers);
+	for (i = 0; i < MHI_MAX_EVT_REQ; ++i) {
+		ch->ereqs[i].tr_events = ch->tr_events + i * MAX_TR_EVENTS;
+		list_add_tail(&ch->ereqs[i].list,
+				&mhi_ctx->ch[chan_id].event_req_buffers);
+	}
+	mhi_ctx->ch[chan_id].curr_ereq =
+		container_of(mhi_ctx->ch[chan_id].event_req_buffers.next,
+				struct event_req, list);
+	list_del_init(&mhi_ctx->ch[chan_id].curr_ereq->list);
+
 	ch->active_client = (*handle_client);
 	(*handle_client)->channel = ch;
 	(*handle_client)->event_trigger = mhi_dev_client_cb_reason;
@@ -1924,6 +1962,13 @@
 	else if (ch->state == MHI_DEV_CH_STOPPED)
 		ch->state = MHI_DEV_CH_PENDING_START;
 
+	goto exit;
+
+free_ereqs:
+	kfree(ch->ereqs);
+	ch->ereqs = NULL;
+free_client:
+	kfree(*handle_client);
 exit:
 	mutex_unlock(&ch->ch_lock);
 	return rc;
@@ -1957,14 +2002,12 @@
 			mhi_log(MHI_MSG_ERROR,
 				"Trying to close an active channel (%d)\n",
 				ch->ch_id);
-			mutex_unlock(&ch->ch_lock);
 			rc = -EAGAIN;
 			goto exit;
 		} else if (ch->tre_loc) {
 			mhi_log(MHI_MSG_ERROR,
 				"Trying to close channel (%d) when a TRE is active",
 				ch->ch_id);
-			mutex_unlock(&ch->ch_lock);
 			rc = -EAGAIN;
 			goto exit;
 		}
@@ -1972,6 +2015,10 @@
 
 	ch->state = MHI_DEV_CH_CLOSED;
 	ch->active_client = NULL;
+	kfree(ch->ereqs);
+	kfree(ch->tr_events);
+	ch->ereqs = NULL;
+	ch->tr_events = NULL;
 	kfree(handle);
 exit:
 	mutex_unlock(&ch->ch_lock);
@@ -2678,40 +2725,8 @@
 	if (!mhi->ch)
 		return -ENOMEM;
 
-
-	for (i = 0; i < mhi->cfg.channels; i++) {
+	for (i = 0; i < mhi->cfg.channels; i++)
 		mutex_init(&mhi->ch[i].ch_lock);
-		if (i == MHI_CLIENT_IP_SW_4_OUT || i == MHI_CLIENT_IP_SW_4_IN) {
-			int nreq = 0;
-
-			INIT_LIST_HEAD(&mhi->ch[i].event_req_buffers);
-			while (nreq < MHI_MAX_EVT_REQ) {
-				struct event_req *ereq;
-				/* Pre allocate event requests */
-				ereq = kzalloc(sizeof(struct event_req),
-						GFP_KERNEL);
-				if (!ereq)
-					return -ENOMEM;
-
-				/* pre allocate buffers to queue
-				 * transfer completion events
-				 */
-				ereq->tr_events = kzalloc(RING_ELEMENT_TYPE_SZ*
-						MAX_TR_EVENTS, GFP_KERNEL);
-				if (!ereq->tr_events) {
-					kfree(ereq);
-					return -ENOMEM;
-				}
-				list_add_tail(&ereq->list,
-						&mhi->ch[i].event_req_buffers);
-				nreq++;
-			}
-			mhi->ch[i].curr_ereq =
-				container_of(mhi->ch[i].event_req_buffers.next,
-						struct event_req, list);
-			list_del_init(&mhi->ch[i].curr_ereq->list);
-		}
-	}
 
 	spin_lock_init(&mhi->lock);
 	mhi->mmio_backup = devm_kzalloc(&pdev->dev,
diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h
index 2cc7809..26baa64 100644
--- a/drivers/platform/msm/mhi_dev/mhi.h
+++ b/drivers/platform/msm/mhi_dev/mhi.h
@@ -484,7 +484,13 @@
 	struct mutex			ch_lock;
 	/* client which the current inbound/outbound message is for */
 	struct mhi_dev_client		*active_client;
-
+	/*
+	 * Pointer to event request structs used to temporarily store
+	 * completion events and meta data before sending them to host
+	 */
+	struct event_req		*ereqs;
+	/* Pointer to completion event buffers */
+	union mhi_dev_ring_element_type *tr_events;
 	struct list_head		event_req_buffers;
 	struct event_req		*curr_ereq;
 
@@ -692,8 +698,8 @@
 	MHI_CLIENT_DUN_IN = 33,
 	MHI_CLIENT_IP_SW_0_OUT = 34,
 	MHI_CLIENT_IP_SW_0_IN = 35,
-	MHI_CLIENT_IP_SW_1_OUT = 36,
-	MHI_CLIENT_IP_SW_1_IN = 37,
+	MHI_CLIENT_ADB_OUT = 36,
+	MHI_CLIENT_ADB_IN = 37,
 	MHI_CLIENT_IP_SW_2_OUT = 38,
 	MHI_CLIENT_IP_SW_2_IN = 39,
 	MHI_CLIENT_IP_SW_3_OUT = 40,
@@ -704,7 +710,7 @@
 	MHI_CLIENT_SMCT_IN = 45,
 	MHI_CLIENT_IP_SW_4_OUT  = 46,
 	MHI_CLIENT_IP_SW_4_IN  = 47,
-	MHI_MAX_SOFTWARE_CHANNELS = 48,
+	MHI_MAX_SOFTWARE_CHANNELS,
 	MHI_CLIENT_TEST_OUT = 60,
 	MHI_CLIENT_TEST_IN = 61,
 	MHI_CLIENT_RESERVED_1_LOWER = 62,
diff --git a/drivers/platform/msm/mhi_dev/mhi_hwio.h b/drivers/platform/msm/mhi_dev/mhi_hwio.h
index 09a0118..936cac7 100644
--- a/drivers/platform/msm/mhi_dev/mhi_hwio.h
+++ b/drivers/platform/msm/mhi_dev/mhi_hwio.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2017-2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -192,4 +192,6 @@
 #define BHI_EXECENV_MASK				0xFFFFFFFF
 #define BHI_EXECENV_SHIFT				0
 
+#define BHI_IMGTXDB					(0x218)
+
 #endif
diff --git a/drivers/platform/msm/mhi_dev/mhi_ring.c b/drivers/platform/msm/mhi_dev/mhi_ring.c
index d6791ea..92b0616 100644
--- a/drivers/platform/msm/mhi_dev/mhi_ring.c
+++ b/drivers/platform/msm/mhi_dev/mhi_ring.c
@@ -278,11 +278,12 @@
 
 int mhi_dev_add_element(struct mhi_dev_ring *ring,
 				union mhi_dev_ring_element_type *element,
-				struct event_req *ereq, int evt_offset)
+				struct event_req *ereq, int size)
 {
 	uint32_t old_offset = 0;
 	struct mhi_addr host_addr;
-	uint32_t num_elem = 0;
+	uint32_t num_elem = 1;
+	uint32_t num_free_elem;
 
 	if (!ring || !element) {
 		pr_err("%s: Invalid context\n", __func__);
@@ -291,16 +292,24 @@
 
 	mhi_dev_update_wr_offset(ring);
 
-	if ((ring->rd_offset + 1) % ring->ring_size == ring->wr_offset) {
-		mhi_log(MHI_MSG_VERBOSE, "ring full to insert element\n");
+	if (ereq)
+		num_elem = size / (sizeof(union mhi_dev_ring_element_type));
+
+	if (ring->rd_offset < ring->wr_offset)
+		num_free_elem = ring->wr_offset - ring->rd_offset - 1;
+	else
+		num_free_elem = ring->ring_size - ring->rd_offset +
+				ring->wr_offset - 1;
+
+	if (num_free_elem < num_elem) {
+		mhi_log(MHI_MSG_ERROR, "No space to add %d elem in ring (%d)\n",
+			num_elem, ring->id);
 		return -EINVAL;
 	}
 
 	old_offset = ring->rd_offset;
 
-	if (evt_offset) {
-		num_elem = evt_offset /
-			(sizeof(union mhi_dev_ring_element_type));
+	if (ereq) {
 		ring->rd_offset += num_elem;
 		if (ring->rd_offset >= ring->ring_size)
 			ring->rd_offset -= ring->ring_size;
@@ -322,23 +331,47 @@
 		host_addr.device_va = ring->ring_shadow.device_va +
 			sizeof(union mhi_dev_ring_element_type) * old_offset;
 
-	host_addr.virt_addr = element;
-
-	if (evt_offset)
-		host_addr.size = evt_offset;
-	else
+	if (!ereq) {
+		/* We're adding only a single ring element */
+		host_addr.virt_addr = element;
 		host_addr.size = sizeof(union mhi_dev_ring_element_type);
 
-	mhi_log(MHI_MSG_VERBOSE, "adding element to ring (%d)\n", ring->id);
-	mhi_log(MHI_MSG_VERBOSE, "rd_ofset %d\n", ring->rd_offset);
-	mhi_log(MHI_MSG_VERBOSE, "type %d\n", element->generic.type);
+		mhi_log(MHI_MSG_VERBOSE, "adding element to ring (%d)\n",
+					ring->id);
+		mhi_log(MHI_MSG_VERBOSE, "rd_ofset %d\n", ring->rd_offset);
+		mhi_log(MHI_MSG_VERBOSE, "type %d\n", element->generic.type);
 
-	if (ereq)
 		mhi_dev_write_to_host(ring->mhi_dev, &host_addr,
-				ereq, MHI_DEV_DMA_ASYNC);
-	else
+			NULL, MHI_DEV_DMA_SYNC);
+		return 0;
+	}
+
+	/* Adding multiple ring elements */
+	if (ring->rd_offset == 0 || (ring->rd_offset > old_offset)) {
+		/* No wrap-around case */
+		host_addr.virt_addr = element;
+		host_addr.size = size;
 		mhi_dev_write_to_host(ring->mhi_dev, &host_addr,
-				NULL, MHI_DEV_DMA_SYNC);
+			ereq, MHI_DEV_DMA_ASYNC);
+	} else {
+		/* Wrap-around case - first chunk uses dma sync */
+		host_addr.virt_addr = element;
+		host_addr.size = (ring->ring_size - old_offset) *
+			sizeof(union mhi_dev_ring_element_type);
+		mhi_dev_write_to_host(ring->mhi_dev, &host_addr,
+			NULL, MHI_DEV_DMA_SYNC);
+
+		/* Copy remaining elements */
+		if (ring->mhi_dev->use_ipa)
+			host_addr.host_pa = ring->ring_shadow.host_pa;
+		else
+			host_addr.device_va = ring->ring_shadow.device_va;
+		host_addr.virt_addr = element + (ring->ring_size - old_offset);
+		host_addr.size = ring->rd_offset *
+			sizeof(union mhi_dev_ring_element_type);
+		mhi_dev_write_to_host(ring->mhi_dev, &host_addr,
+			ereq, MHI_DEV_DMA_ASYNC);
+	}
 	return 0;
 }
 EXPORT_SYMBOL(mhi_dev_add_element);
diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.c b/drivers/platform/msm/mhi_dev/mhi_sm.c
index af05c9e..917b258 100644
--- a/drivers/platform/msm/mhi_dev/mhi_sm.c
+++ b/drivers/platform/msm/mhi_dev/mhi_sm.c
@@ -398,15 +398,18 @@
 		break;
 	case EP_PCIE_EVENT_PM_D3_HOT:
 		res = ((curr_mstate == MHI_DEV_M3_STATE ||
-			curr_mstate == MHI_DEV_READY_STATE) &&
+			curr_mstate == MHI_DEV_READY_STATE ||
+			curr_mstate == MHI_DEV_RESET_STATE) &&
 			curr_dstate != MHI_SM_EP_PCIE_LINK_DISABLE);
 		break;
 	case EP_PCIE_EVENT_PM_D3_COLD:
 		res = (curr_dstate == MHI_SM_EP_PCIE_D3_HOT_STATE ||
-			curr_dstate == MHI_SM_EP_PCIE_D3_COLD_STATE);
+			curr_dstate == MHI_SM_EP_PCIE_D3_COLD_STATE ||
+			curr_dstate == MHI_SM_EP_PCIE_D0_STATE);
 		break;
 	case EP_PCIE_EVENT_PM_RST_DEAST:
 		res = (curr_dstate == MHI_SM_EP_PCIE_D0_STATE ||
+			curr_dstate == MHI_SM_EP_PCIE_D3_HOT_STATE ||
 			curr_dstate == MHI_SM_EP_PCIE_D3_COLD_STATE);
 		break;
 	case EP_PCIE_EVENT_PM_D0:
diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c
index febc867..52d324e 100644
--- a/drivers/platform/msm/mhi_dev/mhi_uci.c
+++ b/drivers/platform/msm/mhi_dev/mhi_uci.c
@@ -29,15 +29,18 @@
 #include <uapi/linux/mhi.h>
 #include "mhi.h"
 
-#define MHI_DEV_NODE_NAME_LEN		13
-#define MHI_MAX_NR_OF_CLIENTS		23
 #define MHI_SOFTWARE_CLIENT_START	0
 #define MHI_SOFTWARE_CLIENT_LIMIT	(MHI_MAX_SOFTWARE_CHANNELS/2)
 #define MHI_UCI_IPC_LOG_PAGES		(100)
 
+/* Max number of MHI write request structures (used in async writes) */
+#define MAX_UCI_WR_REQ			10
 #define MAX_NR_TRBS_PER_CHAN		9
 #define MHI_QTI_IFACE_ID		4
-#define DEVICE_NAME "mhi"
+#define DEVICE_NAME			"mhi"
+#define MAX_DEVICE_NAME_SIZE		80
+
+#define MHI_UCI_ASYNC_READ_TIMEOUT	msecs_to_jiffies(100)
 
 enum uci_dbg_level {
 	UCI_DBG_VERBOSE = 0x0,
@@ -72,6 +75,8 @@
 	enum mhi_chan_dir dir;
 	/* need to register mhi channel state change callback */
 	bool register_cb;
+	/* Name of char device */
+	char *device_name;
 };
 
 /* UCI channel attributes table */
@@ -81,119 +86,144 @@
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_LOOPBACK_IN,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_SAHARA_OUT,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_SAHARA_IN,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_EFS_OUT,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_EFS_IN,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_MBIM_OUT,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_MBIM_IN,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_QMI_OUT,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_QMI_IN,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_IP_CTRL_0_OUT,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_IP_CTRL_0_IN,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_IP_CTRL_1_OUT,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_IP_CTRL_1_IN,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_DUN_OUT,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_OUT,
-		false
+		false,
+		NULL
 	},
 	{
 		MHI_CLIENT_DUN_IN,
 		TRB_MAX_DATA_SIZE,
 		MAX_NR_TRBS_PER_CHAN,
 		MHI_DIR_IN,
-		false
+		false,
+		NULL
 	},
-	{ /* Must be the last */
-		MHI_CLIENT_INVALID,
-		0,
-		0,
-		MHI_DIR_INVALID,
-		false
+	{
+		MHI_CLIENT_ADB_OUT,
+		TRB_MAX_DATA_SIZE,
+		MAX_NR_TRBS_PER_CHAN,
+		MHI_DIR_OUT,
+		true,
+		NULL
+	},
+	{
+		MHI_CLIENT_ADB_IN,
+		TRB_MAX_DATA_SIZE,
+		MAX_NR_TRBS_PER_CHAN,
+		MHI_DIR_IN,
+		true,
+		"android_adb"
 	},
 };
 
@@ -227,6 +257,13 @@
 	struct mhi_uci_ctxt_t *uci_ctxt;
 	struct mutex in_chan_lock;
 	struct mutex out_chan_lock;
+	spinlock_t wr_req_lock;
+	unsigned int f_flags;
+	struct mhi_req *wreqs;
+	struct list_head wr_req_list;
+	struct completion read_done;
+	int (*send)(struct uci_client*, void*, u32);
+	int (*read)(struct uci_client*, struct mhi_req*, int*);
 };
 
 struct mhi_uci_ctxt_t {
@@ -301,8 +338,11 @@
 				client_handle->in_chan);
 		return -EINVAL;
 	}
-	buf_size = in_chan_attr->max_packet_size;
 
+	/* Init the completion event for read */
+	init_completion(&client_handle->read_done);
+
+	buf_size = in_chan_attr->max_packet_size;
 	for (i = 0; i < (in_chan_attr->nr_trbs); i++) {
 		data_loc = kmalloc(buf_size, GFP_KERNEL);
 		if (!data_loc) {
@@ -322,48 +362,129 @@
 	return rc;
 }
 
-static int mhi_uci_send_packet(struct mhi_dev_client **client_handle, void *buf,
-		u32 size, u32 is_uspace_buf)
+static void mhi_uci_write_completion_cb(void *req)
 {
-	void *data_loc = NULL;
-	uintptr_t memcpy_result = 0;
-	u32 data_inserted_so_far = 0;
+	struct mhi_req *ureq = req;
 	struct uci_client *uci_handle;
+	unsigned long flags;
+
+	uci_handle = (struct uci_client *)ureq->context;
+	kfree(ureq->buf);
+	ureq->buf = NULL;
+
+	spin_lock_irqsave(&uci_handle->wr_req_lock, flags);
+	list_add_tail(&ureq->list, &uci_handle->wr_req_list);
+	spin_unlock_irqrestore(&uci_handle->wr_req_lock, flags);
+}
+
+static void mhi_uci_read_completion_cb(void *req)
+{
+	struct mhi_req *ureq = req;
+	struct uci_client *uci_handle;
+
+	uci_handle = (struct uci_client *)ureq->context;
+	complete(&uci_handle->read_done);
+}
+
+static int mhi_uci_send_sync(struct uci_client *uci_handle,
+			void *data_loc, u32 size)
+{
 	struct mhi_req ureq;
+	int ret_val;
 
-
-	uci_handle = container_of(client_handle, struct uci_client,
-					out_handle);
-
-	if (!client_handle || !buf ||
-		!size || !uci_handle)
-		return -EINVAL;
-
-	if (is_uspace_buf) {
-		data_loc = kmalloc(size, GFP_KERNEL);
-		if (!data_loc) {
-			uci_log(UCI_DBG_ERROR,
-				"Failed to allocate memory 0x%x\n",
-				size);
-			return -ENOMEM;
-		}
-		memcpy_result = copy_from_user(data_loc, buf, size);
-		if (memcpy_result)
-			goto error_memcpy;
-	} else {
-		data_loc = buf;
-	}
-	ureq.client = *client_handle;
+	ureq.client = uci_handle->out_handle;
 	ureq.buf = data_loc;
 	ureq.len = size;
 	ureq.chan = uci_handle->out_chan;
 	ureq.mode = IPA_DMA_SYNC;
 
-	data_inserted_so_far = mhi_dev_write_channel(&ureq);
+	ret_val = mhi_dev_write_channel(&ureq);
+
+	kfree(data_loc);
+	return ret_val;
+}
+
+static int mhi_uci_send_async(struct uci_client *uci_handle,
+			void *data_loc, u32 size)
+{
+	int bytes_to_write;
+	struct mhi_req *ureq;
+
+	uci_log(UCI_DBG_VERBOSE,
+		"Got async write for ch %d of size %d\n",
+		uci_handle->out_chan, size);
+
+	spin_lock_irq(&uci_handle->wr_req_lock);
+	if (list_empty(&uci_handle->wr_req_list)) {
+		uci_log(UCI_DBG_ERROR, "Write request pool empty\n");
+		spin_unlock_irq(&uci_handle->wr_req_lock);
+		return -ENOMEM;
+	}
+	ureq = container_of(uci_handle->wr_req_list.next,
+						struct mhi_req, list);
+	list_del_init(&ureq->list);
+	spin_unlock_irq(&uci_handle->wr_req_lock);
+
+	ureq->client = uci_handle->out_handle;
+	ureq->context = uci_handle;
+	ureq->buf = data_loc;
+	ureq->len = size;
+	ureq->chan = uci_handle->out_chan;
+	ureq->mode = IPA_DMA_ASYNC;
+	ureq->client_cb = mhi_uci_write_completion_cb;
+	ureq->snd_cmpl = 1;
+
+	bytes_to_write = mhi_dev_write_channel(ureq);
+	if (bytes_to_write != size)
+		goto error_async_transfer;
+
+	return bytes_to_write;
+
+error_async_transfer:
+	kfree(data_loc);
+	ureq->buf = NULL;
+	spin_lock_irq(&uci_handle->wr_req_lock);
+	list_add_tail(&ureq->list, &uci_handle->wr_req_list);
+	spin_unlock_irq(&uci_handle->wr_req_lock);
+
+	return bytes_to_write;
+}
+
+static int mhi_uci_send_packet(struct mhi_dev_client **client_handle,
+		const char __user *buf, u32 size)
+{
+	void *data_loc;
+	unsigned long memcpy_result;
+	struct uci_client *uci_handle;
+
+	if (!client_handle || !buf || !size)
+		return -EINVAL;
+
+	if (size > TRB_MAX_DATA_SIZE) {
+		uci_log(UCI_DBG_ERROR,
+			"Too big write size: %d, max supported size is %d\n",
+			size, TRB_MAX_DATA_SIZE);
+		return -EFBIG;
+	}
+
+	uci_handle = container_of(client_handle, struct uci_client,
+					out_handle);
+	data_loc = kmalloc(size, GFP_KERNEL);
+	if (!data_loc) {
+		uci_log(UCI_DBG_ERROR,
+		"Failed to allocate kernel buf for user requested size 0x%x\n",
+			size);
+		return -ENOMEM;
+	}
+	memcpy_result = copy_from_user(data_loc, buf, size);
+	if (memcpy_result)
+		goto error_memcpy;
+
+	return uci_handle->send(uci_handle, data_loc, size);
 
 error_memcpy:
 	kfree(data_loc);
-	return data_inserted_so_far;
+	return -EFAULT;
 }
 
 static unsigned int mhi_uci_ctrl_poll(struct file *file, poll_table *wait)
@@ -421,6 +542,119 @@
 	return mask;
 }
 
+static int mhi_uci_alloc_write_reqs(struct uci_client *client)
+{
+	int i;
+
+	client->wreqs = kcalloc(MAX_UCI_WR_REQ,
+				sizeof(struct mhi_req),
+				GFP_KERNEL);
+	if (!client->wreqs) {
+		uci_log(UCI_DBG_ERROR, "Write reqs alloc failed\n");
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&client->wr_req_list);
+	for (i = 0; i < MAX_UCI_WR_REQ; ++i)
+		list_add_tail(&client->wreqs[i].list, &client->wr_req_list);
+
+	uci_log(UCI_DBG_INFO,
+		"UCI write reqs allocation successful\n");
+	return 0;
+}
+
+static int mhi_uci_read_async(struct uci_client *uci_handle,
+			struct mhi_req *ureq, int *bytes_avail)
+{
+	int ret_val = 0;
+	unsigned long compl_ret;
+
+	uci_log(UCI_DBG_ERROR,
+		"Async read for ch %d\n", uci_handle->in_chan);
+
+	ureq->mode = IPA_DMA_ASYNC;
+	ureq->client_cb = mhi_uci_read_completion_cb;
+	ureq->snd_cmpl = 1;
+	ureq->context = uci_handle;
+
+	reinit_completion(&uci_handle->read_done);
+
+	*bytes_avail = mhi_dev_read_channel(ureq);
+	uci_log(UCI_DBG_VERBOSE, "buf_size = 0x%x bytes_read = 0x%x\n",
+		ureq->len, *bytes_avail);
+	if (*bytes_avail < 0) {
+		uci_log(UCI_DBG_ERROR, "Failed to read channel ret %d\n",
+			*bytes_avail);
+		return -EIO;
+	}
+
+	if (*bytes_avail > 0) {
+		uci_log(UCI_DBG_VERBOSE,
+			"Waiting for async read completion!\n");
+		compl_ret =
+			wait_for_completion_interruptible_timeout(
+			&uci_handle->read_done,
+			MHI_UCI_ASYNC_READ_TIMEOUT);
+
+		if (compl_ret == -ERESTARTSYS) {
+			uci_log(UCI_DBG_ERROR, "Exit signal caught\n");
+			return compl_ret;
+		} else if (compl_ret == 0) {
+			uci_log(UCI_DBG_ERROR, "Read timed out for ch %d\n",
+				uci_handle->in_chan);
+			return -EIO;
+		}
+		uci_log(UCI_DBG_VERBOSE,
+			"wk up Read completed on ch %d\n", ureq->chan);
+
+		uci_handle->pkt_loc = (void *)ureq->buf;
+		uci_handle->pkt_size = ureq->actual_len;
+
+		uci_log(UCI_DBG_VERBOSE,
+			"Got pkt of sz 0x%x at adr %pK, ch %d\n",
+			uci_handle->pkt_size,
+			ureq->buf, ureq->chan);
+	} else {
+		uci_handle->pkt_loc = NULL;
+		uci_handle->pkt_size = 0;
+	}
+
+	return ret_val;
+}
+
+static int mhi_uci_read_sync(struct uci_client *uci_handle,
+			struct mhi_req *ureq, int *bytes_avail)
+{
+	int ret_val = 0;
+
+	ureq->mode = IPA_DMA_SYNC;
+	*bytes_avail = mhi_dev_read_channel(ureq);
+
+	uci_log(UCI_DBG_VERBOSE, "buf_size = 0x%x bytes_read = 0x%x\n",
+		ureq->len, *bytes_avail);
+
+	if (*bytes_avail < 0) {
+		uci_log(UCI_DBG_ERROR, "Failed to read channel ret %d\n",
+			*bytes_avail);
+		return -EIO;
+	}
+
+	if (*bytes_avail > 0) {
+		uci_handle->pkt_loc = (void *)ureq->buf;
+		uci_handle->pkt_size = ureq->actual_len;
+
+		uci_log(UCI_DBG_VERBOSE,
+			"Got pkt of sz 0x%x at adr %pK, ch %d\n",
+			uci_handle->pkt_size,
+			ureq->buf, ureq->chan);
+	} else {
+		uci_handle->pkt_loc = NULL;
+		uci_handle->pkt_size = 0;
+	}
+
+	return ret_val;
+}
+
 static int open_client_mhi_channels(struct uci_client *uci_client)
 {
 	int rc = 0;
@@ -431,16 +665,27 @@
 			uci_client->in_chan);
 	mutex_lock(&uci_client->out_chan_lock);
 	mutex_lock(&uci_client->in_chan_lock);
+
+	/* Allocate write requests for async operations */
+	if (!(uci_client->f_flags & O_SYNC)) {
+		rc = mhi_uci_alloc_write_reqs(uci_client);
+		if (rc)
+			goto handle_not_rdy_err;
+		uci_client->send = mhi_uci_send_async;
+		uci_client->read = mhi_uci_read_async;
+	} else {
+		uci_client->send = mhi_uci_send_sync;
+		uci_client->read = mhi_uci_read_sync;
+	}
+
 	uci_log(UCI_DBG_DBG,
 			"Initializing inbound chan %d.\n",
 			uci_client->in_chan);
-
 	rc = mhi_init_read_chan(uci_client, uci_client->in_chan);
-	if (rc < 0) {
+	if (rc < 0)
 		uci_log(UCI_DBG_ERROR,
 			"Failed to init inbound 0x%x, ret 0x%x\n",
 			uci_client->in_chan, rc);
-	}
 
 	rc = mhi_dev_open_channel(uci_client->out_chan,
 			&uci_client->out_handle,
@@ -451,7 +696,6 @@
 	rc = mhi_dev_open_channel(uci_client->in_chan,
 			&uci_client->in_handle,
 			uci_ctxt.event_notifier);
-
 	if (rc < 0) {
 		uci_log(UCI_DBG_ERROR,
 			"Failed to open chan %d, ret 0x%x\n",
@@ -506,6 +750,7 @@
 			return -ENOMEM;
 		}
 		uci_handle->uci_ctxt = &uci_ctxt;
+		uci_handle->f_flags = file_handle->f_flags;
 		if (!atomic_read(&uci_handle->mhi_chans_open)) {
 			uci_log(UCI_DBG_INFO,
 				"Opening channels client %d\n",
@@ -540,6 +785,8 @@
 		if (atomic_read(&uci_handle->mhi_chans_open)) {
 			atomic_set(&uci_handle->mhi_chans_open, 0);
 
+			if (!(uci_handle->f_flags & O_SYNC))
+				kfree(uci_handle->wreqs);
 			mutex_lock(&uci_handle->out_chan_lock);
 			rc = mhi_dev_close_channel(uci_handle->out_handle);
 			wake_up(&uci_handle->write_wq);
@@ -675,7 +922,6 @@
 	struct mutex *mutex;
 	ssize_t bytes_copied = 0;
 	u32 addr_offset = 0;
-	void *local_buf = NULL;
 	struct mhi_req ureq;
 
 	if (!file || !ubuf || !uspace_buf_size ||
@@ -691,44 +937,19 @@
 	ureq.client = client_handle;
 	ureq.buf = uci_handle->in_buf_list[0].addr;
 	ureq.len = uci_handle->in_buf_list[0].buf_size;
-	ureq.mode = IPA_DMA_SYNC;
+
 
 	uci_log(UCI_DBG_VERBOSE, "Client attempted read on chan %d\n",
 			ureq.chan);
 	do {
 		if (!uci_handle->pkt_loc &&
-				!atomic_read(&uci_ctxt.mhi_disabled)) {
-
-			bytes_avail = mhi_dev_read_channel(&ureq);
-
-			uci_log(UCI_DBG_VERBOSE,
-				"reading from mhi_core local_buf = %p",
-				local_buf);
-			uci_log(UCI_DBG_VERBOSE,
-					"buf_size = 0x%x bytes_read = 0x%x\n",
-					 ureq.len, bytes_avail);
-
-			if (bytes_avail < 0) {
-				uci_log(UCI_DBG_ERROR,
-				"Failed to read channel ret %d\n",
-					bytes_avail);
-				ret_val =  -EIO;
+			!atomic_read(&uci_ctxt.mhi_disabled)) {
+			ret_val = uci_handle->read(uci_handle, &ureq,
+							&bytes_avail);
+			if (ret_val)
 				goto error;
-			}
-
-			if (bytes_avail > 0) {
-				uci_handle->pkt_loc = (void *) ureq.buf;
-				uci_handle->pkt_size = ureq.actual_len;
-
+			if (bytes_avail > 0)
 				*bytes_pending = (loff_t)uci_handle->pkt_size;
-				uci_log(UCI_DBG_VERBOSE,
-					"Got pkt of sz 0x%x at adr %p, ch %d\n",
-					uci_handle->pkt_size,
-					ureq.buf, ureq.chan);
-			} else {
-				uci_handle->pkt_loc = 0;
-				uci_handle->pkt_size = 0;
-			}
 		}
 		if (bytes_avail == 0) {
 
@@ -737,7 +958,10 @@
 				"No data read_data_ready %d, chan %d\n",
 				atomic_read(&uci_handle->read_data_ready),
 				ureq.chan);
-
+			if (uci_handle->f_flags & (O_NONBLOCK | O_NDELAY)) {
+				ret_val = -EAGAIN;
+				goto error;
+			}
 			ret_val = wait_event_interruptible(uci_handle->read_wq,
 				(!mhi_dev_channel_isempty(client_handle)));
 
@@ -841,10 +1065,10 @@
 	mutex_lock(&uci_handle->out_chan_lock);
 	while (!ret_val) {
 		ret_val = mhi_uci_send_packet(&uci_handle->out_handle,
-				(void *)buf, count, 1);
+						buf, count);
 		if (ret_val < 0) {
 			uci_log(UCI_DBG_ERROR,
-				"Error while writing data to MHI, chan %d, buf %p, size %d\n",
+				"Error while writing data to MHI, chan %d, buf %pK, size %d\n",
 				chan, (void *)buf, count);
 			ret_val = -EIO;
 			break;
@@ -854,6 +1078,8 @@
 				"No descriptors available, did we poll, chan %d?\n",
 				chan);
 			mutex_unlock(&uci_handle->out_chan_lock);
+			if (uci_handle->f_flags & (O_NONBLOCK | O_NDELAY))
+				return -EAGAIN;
 			ret_val = wait_event_interruptible(uci_handle->write_wq,
 				!mhi_dev_channel_isempty(
 					uci_handle->out_handle));
@@ -870,31 +1096,6 @@
 	return ret_val;
 }
 
-static int uci_init_client_attributes(struct mhi_uci_ctxt_t *uci_ctxt)
-{
-	u32 i;
-	u32 index;
-	struct uci_client *client;
-	const struct chan_attr *chan_attrib;
-
-	for (i = 0; i < ARRAY_SIZE(uci_chan_attr_table); i += 2) {
-		chan_attrib = &uci_chan_attr_table[i];
-		if (chan_attrib->chan_id == MHI_CLIENT_INVALID)
-			break;
-		index = CHAN_TO_CLIENT(i);
-		client = &uci_ctxt->client_handles[index];
-		client->out_chan_attr = chan_attrib;
-		client->in_chan_attr = ++chan_attrib;
-		client->in_buf_list =
-			kcalloc(chan_attrib->nr_trbs,
-					sizeof(struct mhi_dev_iov),
-					GFP_KERNEL);
-		if (!client->in_buf_list)
-			return -ENOMEM;
-	}
-	return 0;
-}
-
 void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason)
 {
 	struct uci_ctrl *uci_ctrl_handle = NULL;
@@ -939,12 +1140,11 @@
 {
 	init_waitqueue_head(&mhi_client->read_wq);
 	init_waitqueue_head(&mhi_client->write_wq);
-	mhi_client->out_chan = index * 2 + 1;
-	mhi_client->in_chan = index * 2;
 	mhi_client->client_index = index;
 
 	mutex_init(&mhi_client->in_chan_lock);
 	mutex_init(&mhi_client->out_chan_lock);
+	spin_lock_init(&mhi_client->wr_req_lock);
 
 	uci_log(UCI_DBG_DBG, "Registering chan %d.\n", mhi_client->out_chan);
 	return 0;
@@ -1014,6 +1214,111 @@
 #endif
 };
 
+static int uci_device_create(struct uci_client *client)
+{
+	int r;
+	int n;
+	ssize_t dst_size;
+	unsigned int client_index;
+	static char device_name[MAX_DEVICE_NAME_SIZE];
+
+	client_index = CHAN_TO_CLIENT(client->out_chan);
+	if (uci_ctxt.client_handles[client_index].dev)
+		return -EEXIST;
+
+	cdev_init(&uci_ctxt.cdev[client_index], &mhi_uci_client_fops);
+	uci_ctxt.cdev[client_index].owner = THIS_MODULE;
+	r = cdev_add(&uci_ctxt.cdev[client_index],
+		uci_ctxt.start_ctrl_nr + client_index, 1);
+	if (IS_ERR_VALUE(r)) {
+		uci_log(UCI_DBG_ERROR,
+			"Failed to add cdev for client %d, ret 0x%x\n",
+			client_index, r);
+		return r;
+	}
+	if (!client->in_chan_attr->device_name) {
+		n = snprintf(device_name, sizeof(device_name),
+			DEVICE_NAME "_pipe_%d", CLIENT_TO_CHAN(client_index));
+		if (n >= sizeof(device_name)) {
+			uci_log(UCI_DBG_ERROR, "Device name buf too short\n");
+			r = -E2BIG;
+			goto error;
+		}
+	} else {
+		dst_size = strscpy(device_name,
+				client->in_chan_attr->device_name,
+				sizeof(device_name));
+		if (dst_size <= 0) {
+			uci_log(UCI_DBG_ERROR, "Device name buf too short\n");
+			r = dst_size;
+			goto error;
+		}
+	}
+
+	uci_ctxt.client_handles[client_index].dev =
+		device_create(uci_ctxt.mhi_uci_class, NULL,
+				uci_ctxt.start_ctrl_nr + client_index,
+				NULL, device_name);
+	if (IS_ERR(uci_ctxt.client_handles[client_index].dev)) {
+		uci_log(UCI_DBG_ERROR,
+			"Failed to create device for client %d\n",
+			client_index);
+		r = -EIO;
+		goto error;
+	}
+
+	uci_log(UCI_DBG_INFO,
+		"Created device with class 0x%pK and ctrl number %d\n",
+		uci_ctxt.mhi_uci_class,
+		uci_ctxt.start_ctrl_nr + client_index);
+
+	return 0;
+
+error:
+	cdev_del(&uci_ctxt.cdev[client_index]);
+	return r;
+}
+
+static void mhi_uci_client_cb(struct mhi_dev_client_cb_data *cb_data)
+{
+	struct uci_client *client = cb_data->user_data;
+
+	uci_log(UCI_DBG_VERBOSE, " Rcvd MHI cb for channel %d, state %d\n",
+		cb_data->channel, cb_data->ctrl_info);
+
+	if (cb_data->ctrl_info == MHI_STATE_CONNECTED)
+		uci_device_create(client);
+}
+
+static int uci_init_client_attributes(struct mhi_uci_ctxt_t *uci_ctxt)
+{
+	u32 i;
+	u32 index;
+	struct uci_client *client;
+	const struct chan_attr *chan_attrib;
+
+	for (i = 0; i < ARRAY_SIZE(uci_chan_attr_table); i += 2) {
+		chan_attrib = &uci_chan_attr_table[i];
+		index = CHAN_TO_CLIENT(chan_attrib->chan_id);
+		client = &uci_ctxt->client_handles[index];
+		client->out_chan_attr = chan_attrib;
+		client->in_chan_attr = ++chan_attrib;
+		client->in_chan = index * 2;
+		client->out_chan = index * 2 + 1;
+		client->in_buf_list =
+			kcalloc(chan_attrib->nr_trbs,
+			sizeof(struct mhi_dev_iov),
+			GFP_KERNEL);
+		if (!client->in_buf_list)
+			return -ENOMEM;
+		/* Register callback with MHI if requested */
+		if (client->out_chan_attr->register_cb)
+			mhi_register_state_cb(mhi_uci_client_cb, client,
+						client->out_chan);
+	}
+	return 0;
+}
+
 int mhi_uci_init(void)
 {
 	u32 i = 0;
@@ -1086,28 +1391,16 @@
 		mhi_client = &uci_ctxt.client_handles[i];
 		if (!mhi_client->in_chan_attr)
 			continue;
-		cdev_init(&uci_ctxt.cdev[i], &mhi_uci_client_fops);
-		uci_ctxt.cdev[i].owner = THIS_MODULE;
-		r = cdev_add(&uci_ctxt.cdev[i],
-				uci_ctxt.start_ctrl_nr + i, 1);
-		if (IS_ERR_VALUE(r)) {
-			uci_log(UCI_DBG_ERROR,
-				"Failed to add cdev %d, ret 0x%x\n",
-				i, r);
-			goto failed_char_add;
-		}
-
-		uci_ctxt.client_handles[i].dev =
-			device_create(uci_ctxt.mhi_uci_class, NULL,
-					uci_ctxt.start_ctrl_nr + i,
-					NULL, DEVICE_NAME "_pipe_%d",
-					i * 2);
-		if (IS_ERR(uci_ctxt.client_handles[i].dev)) {
-			uci_log(UCI_DBG_ERROR,
-					"Failed to add cdev %d\n", i);
-			cdev_del(&uci_ctxt.cdev[i]);
+		/*
+		 * Delay device node creation until the callback for
+		 * this client's channels is called by the MHI driver,
+		 * if one is registered.
+		 */
+		if (mhi_client->in_chan_attr->register_cb)
+			continue;
+		ret_val = uci_device_create(mhi_client);
+		if (ret_val)
 			goto failed_device_create;
-		}
 	}
 
 	/* Control node */
@@ -1144,7 +1437,6 @@
 
 	return 0;
 
-failed_char_add:
 failed_device_create:
 	while (--i >= 0) {
 		cdev_del(&uci_ctxt.cdev[i]);
diff --git a/drivers/platform/msm/qcom-geni-se.c b/drivers/platform/msm/qcom-geni-se.c
index ed4b837..267ed8d 100644
--- a/drivers/platform/msm/qcom-geni-se.c
+++ b/drivers/platform/msm/qcom-geni-se.c
@@ -675,9 +675,9 @@
 						geni_se_dev->cur_ab,
 						geni_se_dev->cur_ib);
 	GENI_SE_DBG(geni_se_dev->log_ctx, false, NULL,
-		    "%s: %lu:%lu (%lu:%lu) %d\n", __func__,
-		    geni_se_dev->cur_ab, geni_se_dev->cur_ib,
-		    rsc->ab, rsc->ib, bus_bw_update);
+			"%s: %s: cur_ab_ib(%lu:%lu) req_ab_ib(%lu:%lu) %d\n",
+			__func__, dev_name(rsc->ctrl_dev), geni_se_dev->cur_ab,
+			geni_se_dev->cur_ib, rsc->ab, rsc->ib, bus_bw_update);
 	mutex_unlock(&geni_se_dev->geni_dev_lock);
 	return ret;
 }
@@ -773,9 +773,9 @@
 						geni_se_dev->cur_ab,
 						geni_se_dev->cur_ib);
 	GENI_SE_DBG(geni_se_dev->log_ctx, false, NULL,
-		    "%s: %lu:%lu (%lu:%lu) %d\n", __func__,
-		    geni_se_dev->cur_ab, geni_se_dev->cur_ib,
-		    rsc->ab, rsc->ib, bus_bw_update);
+			"%s: %s: cur_ab_ib(%lu:%lu) req_ab_ib(%lu:%lu) %d\n",
+			__func__, dev_name(rsc->ctrl_dev), geni_se_dev->cur_ab,
+			geni_se_dev->cur_ib, rsc->ab, rsc->ib, bus_bw_update);
 	mutex_unlock(&geni_se_dev->geni_dev_lock);
 	return ret;
 }
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 6e54fbf..05a8c66 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.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
@@ -1020,8 +1020,6 @@
 				"sps:%s:BAMs are still registered", __func__);
 
 		sps_map_de_init();
-
-		kfree(sps);
 	}
 
 	sps_mem_de_init();
@@ -3006,6 +3004,7 @@
 		.name	= SPS_DRV_NAME,
 		.owner	= THIS_MODULE,
 		.of_match_table = msm_sps_match,
+		.suppress_bind_attrs = true,
 	},
 	.remove		= msm_sps_remove,
 };
diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c
index 1a28e56..0b8c212 100644
--- a/drivers/power/reset/msm-poweroff.c
+++ b/drivers/power/reset/msm-poweroff.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
@@ -56,8 +56,14 @@
 /* Download mode master kill-switch */
 static void __iomem *msm_ps_hold;
 static phys_addr_t tcsr_boot_misc_detect;
+/* Runtime could be only changed value once.
+ * There is no API from TZ to re-enable the registers.
+ * So the SDI cannot be re-enabled when it already by-passed.
+ */
 static int download_mode = 1;
 static struct kobject dload_kobj;
+static void scm_disable_sdi(void);
+
 
 #ifdef CONFIG_QCOM_DLOAD_MODE
 #define EDL_MODE_PROP "qcom,msm-imem-emergency_download_mode"
@@ -201,7 +207,10 @@
 	return 0;
 }
 #else
-#define set_dload_mode(x) do {} while (0)
+static void set_dload_mode(int on)
+{
+	return;
+}
 
 static void enable_emergency_dload_mode(void)
 {
@@ -214,6 +223,26 @@
 }
 #endif
 
+static void scm_disable_sdi(void)
+{
+	int ret;
+	struct scm_desc desc = {
+		.args[0] = 1,
+		.args[1] = 0,
+		.arginfo = SCM_ARGS(2),
+	};
+
+	/* Needed to bypass debug image on some chips */
+	if (!is_scm_armv8())
+		ret = scm_call_atomic2(SCM_SVC_BOOT,
+			       SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
+	else
+		ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
+			  SCM_WDOG_DEBUG_BOOT_PART), &desc);
+	if (ret)
+		pr_err("Failed to disable secure wdog debug: %d\n", ret);
+}
+
 void msm_set_restart_mode(int mode)
 {
 	restart_mode = mode;
@@ -366,13 +395,6 @@
 
 static void do_msm_restart(enum reboot_mode reboot_mode, const char *cmd)
 {
-	int ret;
-	struct scm_desc desc = {
-		.args[0] = 1,
-		.args[1] = 0,
-		.arginfo = SCM_ARGS(2),
-	};
-
 	pr_notice("Going down for restart now\n");
 
 	msm_restart_prepare(cmd);
@@ -387,16 +409,7 @@
 		msm_trigger_wdog_bite();
 #endif
 
-	/* Needed to bypass debug image on some chips */
-	if (!is_scm_armv8())
-		ret = scm_call_atomic2(SCM_SVC_BOOT,
-			       SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
-	else
-		ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
-			  SCM_WDOG_DEBUG_BOOT_PART), &desc);
-	if (ret)
-		pr_err("Failed to disable secure wdog debug: %d\n", ret);
-
+	scm_disable_sdi();
 	halt_spmi_pmic_arbiter();
 	deassert_ps_hold();
 
@@ -405,27 +418,11 @@
 
 static void do_msm_poweroff(void)
 {
-	int ret;
-	struct scm_desc desc = {
-		.args[0] = 1,
-		.args[1] = 0,
-		.arginfo = SCM_ARGS(2),
-	};
-
 	pr_notice("Powering off the SoC\n");
-#ifdef CONFIG_QCOM_DLOAD_MODE
+
 	set_dload_mode(0);
-#endif
+	scm_disable_sdi();
 	qpnp_pon_system_pwr_off(PON_POWER_OFF_SHUTDOWN);
-	/* Needed to bypass debug image on some chips */
-	if (!is_scm_armv8())
-		ret = scm_call_atomic2(SCM_SVC_BOOT,
-			       SCM_WDOG_DEBUG_BOOT_PART, 1, 0);
-	else
-		ret = scm_call2_atomic(SCM_SIP_FNID(SCM_SVC_BOOT,
-			  SCM_WDOG_DEBUG_BOOT_PART), &desc);
-	if (ret)
-		pr_err("Failed to disable wdog debug: %d\n", ret);
 
 	halt_spmi_pmic_arbiter();
 	deassert_ps_hold();
@@ -677,6 +674,8 @@
 		scm_deassert_ps_hold_supported = true;
 
 	set_dload_mode(download_mode);
+	if (!download_mode)
+		scm_disable_sdi();
 
 	return 0;
 
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index cd76a09..8281c41 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -338,6 +338,7 @@
 	POWER_SUPPLY_ATTR(esr_actual),
 	POWER_SUPPLY_ATTR(esr_nominal),
 	POWER_SUPPLY_ATTR(soh),
+	POWER_SUPPLY_ATTR(qc_opti_disable),
 	/* Local extensions of type int64_t */
 	POWER_SUPPLY_ATTR(charge_counter_ext),
 	/* Properties of type `const char *' */
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index e8d91ae..899cd31 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -79,6 +79,7 @@
 	struct wakeup_source	*pl_ws;
 	struct notifier_block	nb;
 	bool			pl_disable;
+	int			taper_entry_fv;
 };
 
 struct pl_data *the_chip;
@@ -452,6 +453,7 @@
 	int eff_fcc_ua;
 	int total_fcc_ua, master_fcc_ua, slave_fcc_ua = 0;
 
+	chip->taper_entry_fv = get_effective_result(chip->fv_votable);
 	chip->taper_work_running = true;
 	while (true) {
 		if (get_effective_result(chip->pl_disable_votable)) {
@@ -498,7 +500,25 @@
 			vote(chip->fcc_votable, TAPER_STEPPER_VOTER,
 					true, eff_fcc_ua);
 		} else {
-			pl_dbg(chip, PR_PARALLEL, "master is fast charging; waiting for next taper\n");
+			/*
+			 * Due to reduction of float voltage in JEITA condition
+			 * taper charging can be initiated at a lower FV. On
+			 * removal of JEITA condition, FV readjusts itself.
+			 * However, once taper charging is initiated, it doesn't
+			 * exits until parallel chaging is disabled due to which
+			 * FCC doesn't scale back to its original value, leading
+			 * to slow charging thereafter.
+			 * Check if FV increases in comparison to FV at which
+			 * taper charging was initiated, and if yes, exit taper
+			 * charging.
+			 */
+			if (get_effective_result(chip->fv_votable) >
+						chip->taper_entry_fv) {
+				pl_dbg(chip, PR_PARALLEL, "Float voltage increased. Exiting taper\n");
+				goto done;
+			} else {
+				pl_dbg(chip, PR_PARALLEL, "master is fast charging; waiting for next taper\n");
+			}
 		}
 		/* wait for the charger state to deglitch after FCC change */
 		msleep(PL_TAPER_WORK_DELAY_MS);
@@ -997,6 +1017,16 @@
 	/* handle fast/taper charge entry */
 	if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER
 			|| pval.intval == POWER_SUPPLY_CHARGE_TYPE_FAST) {
+		/*
+		 * Undo parallel charging termination if entered taper in
+		 * reduced float voltage condition due to jeita mitigation.
+		 */
+		if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_FAST &&
+			(chip->taper_entry_fv <
+			get_effective_result(chip->fv_votable))) {
+			vote(chip->pl_disable_votable, TAPER_END_VOTER,
+				false, 0);
+		}
 		pl_dbg(chip, PR_PARALLEL, "chg_state enabling parallel\n");
 		vote(chip->pl_disable_votable, CHG_STATE_VOTER, false, 0);
 		chip->charge_type = pval.intval;
diff --git a/drivers/power/supply/qcom/fg-alg.c b/drivers/power/supply/qcom/fg-alg.c
index 4003679..f3f2c66 100644
--- a/drivers/power/supply/qcom/fg-alg.c
+++ b/drivers/power/supply/qcom/fg-alg.c
@@ -803,9 +803,31 @@
 		i, soc_per_step, msoc_this_step, msoc_next_step,
 		ibatt_this_step, t_predicted_this_step, ttf_slope,
 		t_predicted_cv, t_predicted = 0, charge_type = 0,
-		float_volt_uv = 0;
+		float_volt_uv = 0, valid = 0, charge_status = 0;
 	s64 delta_ms;
 
+	rc = ttf->get_ttf_param(ttf->data, TTF_VALID, &valid);
+	if (rc < 0) {
+		pr_err("failed to get ttf_valid rc=%d\n", rc);
+		return rc;
+	}
+
+	if (!valid) {
+		*val = -EINVAL;
+		return 0;
+	}
+
+	rc =  ttf->get_ttf_param(ttf->data, TTF_CHG_STATUS, &charge_status);
+	if (rc < 0) {
+		pr_err("failed to get charge-status rc=%d\n", rc);
+		return rc;
+	}
+
+	if (charge_status != POWER_SUPPLY_STATUS_CHARGING) {
+		*val = -EINVAL;
+		return 0;
+	}
+
 	rc = ttf->get_ttf_param(ttf->data, TTF_MSOC, &msoc);
 	if (rc < 0) {
 		pr_err("failed to get msoc rc=%d\n", rc);
@@ -1103,7 +1125,30 @@
  */
 int ttf_get_time_to_empty(struct ttf *ttf, int *val)
 {
-	int rc, ibatt_avg, msoc, act_cap_mah, divisor;
+	int rc, ibatt_avg, msoc, act_cap_mah, divisor, valid = 0,
+		charge_status = 0;
+
+	rc = ttf->get_ttf_param(ttf->data, TTF_VALID, &valid);
+	if (rc < 0) {
+		pr_err("failed to get ttf_valid rc=%d\n", rc);
+		return rc;
+	}
+
+	if (!valid) {
+		*val = -EINVAL;
+		return 0;
+	}
+
+	rc =  ttf->get_ttf_param(ttf->data, TTF_CHG_STATUS, &charge_status);
+	if (rc < 0) {
+		pr_err("failed to get charge-status rc=%d\n", rc);
+		return rc;
+	}
+
+	if (charge_status == POWER_SUPPLY_STATUS_CHARGING) {
+		*val = -EINVAL;
+		return 0;
+	}
 
 	rc = ttf_circ_buf_median(&ttf->ibatt, &ibatt_avg);
 	if (rc < 0) {
@@ -1136,6 +1181,10 @@
 	divisor = ibatt_avg * divisor / 100;
 	divisor = max(100, divisor);
 	*val = act_cap_mah * msoc * HOURS_TO_SECONDS / divisor;
+
+	pr_debug("TTF: ibatt_avg=%d msoc=%d act_cap_mah=%d TTE=%d\n",
+			ibatt_avg, msoc, act_cap_mah, *val);
+
 	return 0;
 }
 
diff --git a/drivers/power/supply/qcom/fg-alg.h b/drivers/power/supply/qcom/fg-alg.h
index 70183ba..22e9c2b 100644
--- a/drivers/power/supply/qcom/fg-alg.h
+++ b/drivers/power/supply/qcom/fg-alg.h
@@ -76,6 +76,7 @@
 	TTF_VFLOAT,
 	TTF_CHG_TYPE,
 	TTF_CHG_STATUS,
+	TTF_VALID,
 };
 
 struct ttf_circ_buf {
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index f73e647..09c3640 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -311,10 +311,10 @@
 	int	esr_meas_curr_ma;
 	int	bmd_en_delay_ms;
 	int	ki_coeff_full_soc_dischg;
-	int	ki_coeff_low_dischg;
 	int	ki_coeff_hi_chg;
 	int	jeita_thresholds[NUM_JEITA_LEVELS];
 	int	ki_coeff_soc[KI_COEFF_SOC_LEVELS];
+	int	ki_coeff_low_dischg[KI_COEFF_SOC_LEVELS];
 	int	ki_coeff_med_dischg[KI_COEFF_SOC_LEVELS];
 	int	ki_coeff_hi_dischg[KI_COEFF_SOC_LEVELS];
 	int	slope_limit_coeffs[SLOPE_LIMIT_NUM_COEFFS];
@@ -335,7 +335,7 @@
 	bool		started[BUCKET_COUNT];
 	u16		count[BUCKET_COUNT];
 	u8		last_soc[BUCKET_COUNT];
-	int		id;
+	char		counter[BUCKET_COUNT * 8];
 	struct mutex	lock;
 };
 
diff --git a/drivers/power/supply/qcom/qg-core.h b/drivers/power/supply/qcom/qg-core.h
index f21b2a8..b0ff18c 100644
--- a/drivers/power/supply/qcom/qg-core.h
+++ b/drivers/power/supply/qcom/qg-core.h
@@ -54,6 +54,7 @@
 	int			esr_qual_i_ua;
 	int			esr_qual_v_uv;
 	int			esr_disable_soc;
+	int			esr_min_ibat_ua;
 	bool			hold_soc_while_full;
 	bool			linearize_soc;
 	bool			cl_disable;
@@ -133,6 +134,7 @@
 	u32			esr_last;
 	ktime_t			last_user_update_time;
 	ktime_t			last_fifo_update_time;
+	unsigned long		last_maint_soc_update_time;
 
 	/* soc params */
 	int			catch_up_soc;
@@ -142,6 +144,9 @@
 	int			batt_soc;
 	int			cc_soc;
 	int			full_soc;
+	int			sys_soc;
+	int			last_adj_ssoc;
+	int			recharge_soc;
 	struct alarm		alarm_timer;
 	u32			sdam_data[SDAM_MAX];
 
diff --git a/drivers/power/supply/qcom/qg-reg.h b/drivers/power/supply/qcom/qg-reg.h
index e0f400d..894e076 100644
--- a/drivers/power/supply/qcom/qg-reg.h
+++ b/drivers/power/supply/qcom/qg-reg.h
@@ -41,6 +41,9 @@
 #define QG_DATA_CTL1_REG			0x41
 #define MASTER_HOLD_OR_CLR_BIT			BIT(0)
 
+#define QG_DATA_CTL2_REG			0x42
+#define BURST_AVG_HOLD_FOR_READ_BIT		BIT(0)
+
 #define QG_MODE_CTL1_REG			0x43
 #define PARALLEL_IBAT_SENSE_EN_BIT		BIT(7)
 
@@ -97,6 +100,8 @@
 #define QG_LAST_ADC_V_DATA0_REG			0xC0
 #define QG_LAST_ADC_I_DATA0_REG			0xC2
 
+#define QG_LAST_BURST_AVG_I_DATA0_REG		0xC6
+
 #define QG_LAST_S3_SLEEP_V_DATA0_REG		0xCC
 
 /* SDAM offsets */
diff --git a/drivers/power/supply/qcom/qg-soc.c b/drivers/power/supply/qcom/qg-soc.c
index af8b158..711bd2b 100644
--- a/drivers/power/supply/qcom/qg-soc.c
+++ b/drivers/power/supply/qcom/qg-soc.c
@@ -17,15 +17,19 @@
 #include <linux/module.h>
 #include <linux/power_supply.h>
 #include <uapi/linux/qg.h>
+#include <uapi/linux/qg-profile.h>
 #include "fg-alg.h"
 #include "qg-sdam.h"
 #include "qg-core.h"
 #include "qg-reg.h"
 #include "qg-util.h"
 #include "qg-defs.h"
+#include "qg-soc.h"
 
 #define DEFAULT_UPDATE_TIME_MS			64000
 #define SOC_SCALE_HYST_MS			2000
+#define VBAT_LOW_HYST_UV			50000
+#define FULL_SOC				100
 
 static int qg_delta_soc_interval_ms = 20000;
 module_param_named(
@@ -37,6 +41,44 @@
 	soc_cold_interval_ms, qg_delta_soc_cold_interval_ms, int, 0600
 );
 
+static int qg_maint_soc_update_ms = 120000;
+module_param_named(
+	maint_soc_update_ms, qg_maint_soc_update_ms, int, 0600
+);
+
+int qg_adjust_sys_soc(struct qpnp_qg *chip)
+{
+	int soc, vbat_uv, rc;
+	int vcutoff_uv = chip->dt.vbatt_cutoff_mv * 1000;
+
+	chip->sys_soc = CAP(QG_MIN_SOC, QG_MAX_SOC, chip->sys_soc);
+
+	if (chip->sys_soc == QG_MIN_SOC) {
+		/* Hold SOC to 1% of VBAT has not dropped below cutoff */
+		rc = qg_get_battery_voltage(chip, &vbat_uv);
+		if (!rc && vbat_uv >= (vcutoff_uv + VBAT_LOW_HYST_UV))
+			soc = 1;
+		else
+			soc = 0;
+	} else if (chip->sys_soc == QG_MAX_SOC) {
+		soc = FULL_SOC;
+	} else if (chip->sys_soc >= (QG_MAX_SOC - 100)) {
+		/* Hold SOC to 100% if we are dropping from 100 to 99 */
+		if (chip->last_adj_ssoc == FULL_SOC)
+			soc = FULL_SOC;
+		else /* Hold SOC at 99% until we hit 100% */
+			soc = FULL_SOC - 1;
+	} else {
+		soc = DIV_ROUND_CLOSEST(chip->sys_soc, 100);
+	}
+
+	qg_dbg(chip, QG_DEBUG_SOC, "last_adj_sys_soc=%d  adj_sys_soc=%d\n",
+					chip->last_adj_ssoc, soc);
+	chip->last_adj_ssoc = soc;
+
+	return soc;
+}
+
 static void get_next_update_time(struct qpnp_qg *chip)
 {
 	int soc_points = 0, batt_temp = 0;
@@ -56,10 +98,11 @@
 
 	/* Lower the delta soc interval by half at cold */
 	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)
+	if (!rc && batt_temp < chip->dt.cold_temp_threshold)
 		min_delta_soc_interval_ms = qg_delta_soc_cold_interval_ms;
+	else if (chip->maint_soc > 0 && chip->maint_soc >= chip->recharge_soc)
+		/* if in maintenance mode scale slower */
+		min_delta_soc_interval_ms = qg_maint_soc_update_ms;
 
 	if (!min_delta_soc_interval_ms)
 		min_delta_soc_interval_ms = 1000;	/* 1 second */
@@ -98,9 +141,34 @@
 	return true;
 }
 
+static bool maint_soc_timeout(struct qpnp_qg *chip)
+{
+	unsigned long now;
+	int rc;
+
+	if (chip->maint_soc < 0)
+		return false;
+
+	rc = get_rtc_time(&now);
+	if (rc < 0)
+		return true;
+
+	/* Do not scale if we have dropped below recharge-soc */
+	if (chip->maint_soc < chip->recharge_soc)
+		return true;
+
+	if ((now - chip->last_maint_soc_update_time) >=
+			(qg_maint_soc_update_ms / 1000)) {
+		chip->last_maint_soc_update_time = now;
+		return true;
+	}
+
+	return false;
+}
+
 static void update_msoc(struct qpnp_qg *chip)
 {
-	int rc = 0, batt_temp = 0,  batt_soc_32bit = 0;
+	int rc = 0, sdam_soc, batt_temp = 0,  batt_soc_32bit = 0;
 	bool usb_present = is_usb_present(chip);
 
 	if (chip->catch_up_soc > chip->msoc) {
@@ -113,7 +181,8 @@
 	}
 	chip->msoc = CAP(0, 100, chip->msoc);
 
-	if (chip->maint_soc > 0 && chip->msoc < chip->maint_soc) {
+	if (chip->maint_soc > 0 && chip->msoc < chip->maint_soc
+				&& maint_soc_timeout(chip)) {
 		chip->maint_soc -= chip->dt.delta_soc;
 		chip->maint_soc = CAP(0, 100, chip->maint_soc);
 	}
@@ -128,8 +197,9 @@
 		pr_err("Failed to update MSOC register rc=%d\n", rc);
 
 	/* update SDAM with the new MSOC */
-	chip->sdam_data[SDAM_SOC] = chip->msoc;
-	rc = qg_sdam_write(SDAM_SOC, chip->msoc);
+	sdam_soc = (chip->maint_soc > 0) ? chip->maint_soc : chip->msoc;
+	chip->sdam_data[SDAM_SOC] = sdam_soc;
+	rc = qg_sdam_write(SDAM_SOC, sdam_soc);
 	if (rc < 0)
 		pr_err("Failed to update SDAM with MSOC rc=%d\n", rc);
 
diff --git a/drivers/power/supply/qcom/qg-soc.h b/drivers/power/supply/qcom/qg-soc.h
index 3b4eb60..cd64bd5 100644
--- a/drivers/power/supply/qcom/qg-soc.h
+++ b/drivers/power/supply/qcom/qg-soc.h
@@ -16,5 +16,6 @@
 int qg_scale_soc(struct qpnp_qg *chip, bool force_soc);
 int qg_soc_init(struct qpnp_qg *chip);
 void qg_soc_exit(struct qpnp_qg *chip);
+int qg_adjust_sys_soc(struct qpnp_qg *chip);
 
 #endif /* __QG_SOC_H__ */
diff --git a/drivers/power/supply/qcom/qg-util.c b/drivers/power/supply/qcom/qg-util.c
index 824d914..a3e045e 100644
--- a/drivers/power/supply/qcom/qg-util.c
+++ b/drivers/power/supply/qcom/qg-util.c
@@ -332,3 +332,60 @@
 
 	return rc;
 }
+
+int qg_get_battery_current(struct qpnp_qg *chip, int *ibat_ua)
+{
+	int rc = 0, last_ibat = 0;
+
+	if (chip->battery_missing) {
+		*ibat_ua = 0;
+		return 0;
+	}
+
+	/* hold data */
+	rc = qg_masked_write(chip, chip->qg_base + QG_DATA_CTL2_REG,
+				BURST_AVG_HOLD_FOR_READ_BIT,
+				BURST_AVG_HOLD_FOR_READ_BIT);
+	if (rc < 0) {
+		pr_err("Failed to hold burst-avg data rc=%d\n", rc);
+		goto release;
+	}
+
+	rc = qg_read(chip, chip->qg_base + QG_LAST_BURST_AVG_I_DATA0_REG,
+				(u8 *)&last_ibat, 2);
+	if (rc < 0) {
+		pr_err("Failed to read LAST_BURST_AVG_I reg, rc=%d\n", rc);
+		goto release;
+	}
+
+	last_ibat = sign_extend32(last_ibat, 15);
+	*ibat_ua = I_RAW_TO_UA(last_ibat);
+
+release:
+	/* release */
+	qg_masked_write(chip, chip->qg_base + QG_DATA_CTL2_REG,
+				BURST_AVG_HOLD_FOR_READ_BIT, 0);
+	return rc;
+}
+
+int qg_get_battery_voltage(struct qpnp_qg *chip, int *vbat_uv)
+{
+	int rc = 0;
+	u64 last_vbat = 0;
+
+	if (chip->battery_missing) {
+		*vbat_uv = 3700000;
+		return 0;
+	}
+
+	rc = qg_read(chip, chip->qg_base + QG_LAST_ADC_V_DATA0_REG,
+				(u8 *)&last_vbat, 2);
+	if (rc < 0) {
+		pr_err("Failed to read LAST_ADV_V reg, rc=%d\n", rc);
+		return rc;
+	}
+
+	*vbat_uv = V_RAW_TO_UV(last_vbat);
+
+	return rc;
+}
diff --git a/drivers/power/supply/qcom/qg-util.h b/drivers/power/supply/qcom/qg-util.h
index bb17afb..5dd6c85 100644
--- a/drivers/power/supply/qcom/qg-util.h
+++ b/drivers/power/supply/qcom/qg-util.h
@@ -25,5 +25,7 @@
 bool is_parallel_enabled(struct qpnp_qg *chip);
 int qg_write_monotonic_soc(struct qpnp_qg *chip, int msoc);
 int qg_get_battery_temp(struct qpnp_qg *chip, int *batt_temp);
+int qg_get_battery_current(struct qpnp_qg *chip, int *ibat_ua);
+int qg_get_battery_voltage(struct qpnp_qg *chip, int *vbat_uv);
 
 #endif
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index eaf138c..36521a1 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -1653,11 +1653,13 @@
 	mutex_unlock(&chip->cl.lock);
 }
 
+#define KI_COEFF_LOW_DISCHG_DEFAULT	800
 #define KI_COEFF_MED_DISCHG_DEFAULT	1500
 #define KI_COEFF_HI_DISCHG_DEFAULT	2200
 static int fg_adjust_ki_coeff_dischg(struct fg_chip *chip)
 {
 	int rc, i, msoc;
+	int ki_coeff_low = KI_COEFF_LOW_DISCHG_DEFAULT;
 	int ki_coeff_med = KI_COEFF_MED_DISCHG_DEFAULT;
 	int ki_coeff_hi = KI_COEFF_HI_DISCHG_DEFAULT;
 	u8 val;
@@ -1674,12 +1676,24 @@
 	if (chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) {
 		for (i = KI_COEFF_SOC_LEVELS - 1; i >= 0; i--) {
 			if (msoc < chip->dt.ki_coeff_soc[i]) {
+				ki_coeff_low = chip->dt.ki_coeff_low_dischg[i];
 				ki_coeff_med = chip->dt.ki_coeff_med_dischg[i];
 				ki_coeff_hi = chip->dt.ki_coeff_hi_dischg[i];
 			}
 		}
 	}
 
+	fg_encode(chip->sp, FG_SRAM_KI_COEFF_LOW_DISCHG, ki_coeff_low, &val);
+	rc = fg_sram_write(chip,
+			chip->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].addr_word,
+			chip->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].addr_byte, &val,
+			chip->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].len,
+			FG_IMA_DEFAULT);
+	if (rc < 0) {
+		pr_err("Error in writing ki_coeff_low, rc=%d\n", rc);
+		return rc;
+	}
+
 	fg_encode(chip->sp, FG_SRAM_KI_COEFF_MED_DISCHG, ki_coeff_med, &val);
 	rc = fg_sram_write(chip,
 			chip->sp[FG_SRAM_KI_COEFF_MED_DISCHG].addr_word,
@@ -1702,8 +1716,8 @@
 		return rc;
 	}
 
-	fg_dbg(chip, FG_STATUS, "Wrote ki_coeff_med %d ki_coeff_hi %d\n",
-		ki_coeff_med, ki_coeff_hi);
+	fg_dbg(chip, FG_STATUS, "Wrote ki_coeff_low %d ki_coeff_med %d ki_coeff_hi %d\n",
+		ki_coeff_low, ki_coeff_med, ki_coeff_hi);
 	return 0;
 }
 
@@ -2707,20 +2721,29 @@
 	mutex_unlock(&chip->cyc_ctr.lock);
 }
 
-static int fg_get_cycle_count(struct fg_chip *chip)
+static const char *fg_get_cycle_count(struct fg_chip *chip)
 {
-	int count;
+	int i, len = 0;
+	char *buf;
 
 	if (!chip->cyc_ctr.en)
-		return 0;
+		return NULL;
 
-	if ((chip->cyc_ctr.id <= 0) || (chip->cyc_ctr.id > BUCKET_COUNT))
-		return -EINVAL;
-
+	buf = chip->cyc_ctr.counter;
 	mutex_lock(&chip->cyc_ctr.lock);
-	count = chip->cyc_ctr.count[chip->cyc_ctr.id - 1];
+	for (i = 0; i < BUCKET_COUNT; i++) {
+		if (sizeof(chip->cyc_ctr.counter) - len < 8) {
+			pr_err("Invalid length %d\n", len);
+			mutex_unlock(&chip->cyc_ctr.lock);
+			return NULL;
+		}
+
+		len += snprintf(buf+len, 8, "%d ", chip->cyc_ctr.count[i]);
+	}
 	mutex_unlock(&chip->cyc_ctr.lock);
-	return count;
+
+	buf[len] = '\0';
+	return buf;
 }
 
 static void status_change_work(struct work_struct *work)
@@ -3847,11 +3870,8 @@
 	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
 		pval->intval = chip->bp.float_volt_uv;
 		break;
-	case POWER_SUPPLY_PROP_CYCLE_COUNT:
-		pval->intval = fg_get_cycle_count(chip);
-		break;
-	case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
-		pval->intval = chip->cyc_ctr.id;
+	case POWER_SUPPLY_PROP_CYCLE_COUNTS:
+		pval->strval = fg_get_cycle_count(chip);
 		break;
 	case POWER_SUPPLY_PROP_CHARGE_NOW_RAW:
 		rc = fg_get_charge_raw(chip, &pval->intval);
@@ -3917,15 +3937,6 @@
 	int rc = 0;
 
 	switch (psp) {
-	case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
-		if ((pval->intval > 0) && (pval->intval <= BUCKET_COUNT)) {
-			chip->cyc_ctr.id = pval->intval;
-		} else {
-			pr_err("rejecting invalid cycle_count_id = %d\n",
-				pval->intval);
-			return -EINVAL;
-		}
-		break;
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
 		rc = fg_set_constant_chg_voltage(chip, pval->intval);
 		break;
@@ -4008,7 +4019,6 @@
 						enum power_supply_property psp)
 {
 	switch (psp) {
-	case POWER_SUPPLY_PROP_CYCLE_COUNT_ID:
 	case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
 	case POWER_SUPPLY_PROP_CC_STEP:
 	case POWER_SUPPLY_PROP_CC_STEP_SEL:
@@ -4080,8 +4090,7 @@
 	POWER_SUPPLY_PROP_BATTERY_TYPE,
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
 	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
-	POWER_SUPPLY_PROP_CYCLE_COUNT,
-	POWER_SUPPLY_PROP_CYCLE_COUNT_ID,
+	POWER_SUPPLY_PROP_CYCLE_COUNTS,
 	POWER_SUPPLY_PROP_CHARGE_NOW_RAW,
 	POWER_SUPPLY_PROP_CHARGE_NOW,
 	POWER_SUPPLY_PROP_CHARGE_FULL,
@@ -4382,21 +4391,6 @@
 		}
 	}
 
-	if (chip->dt.ki_coeff_low_dischg != -EINVAL) {
-		fg_encode(chip->sp, FG_SRAM_KI_COEFF_LOW_DISCHG,
-			chip->dt.ki_coeff_low_dischg, &val);
-		rc = fg_sram_write(chip,
-				chip->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].addr_word,
-				chip->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].addr_byte,
-				&val, chip->sp[FG_SRAM_KI_COEFF_LOW_DISCHG].len,
-				FG_IMA_DEFAULT);
-		if (rc < 0) {
-			pr_err("Error in writing ki_coeff_low_dischg, rc=%d\n",
-				rc);
-			return rc;
-		}
-	}
-
 	if (chip->dt.ki_coeff_hi_chg != -EINVAL) {
 		fg_encode(chip->sp, FG_SRAM_KI_COEFF_HI_CHG,
 			chip->dt.ki_coeff_hi_chg, &val);
@@ -4878,16 +4872,22 @@
 	if (!rc)
 		chip->dt.ki_coeff_hi_chg = temp;
 
-	chip->dt.ki_coeff_low_dischg = -EINVAL;
-	rc = of_property_read_u32(node, "qcom,ki-coeff-low-dischg", &temp);
-	if (!rc)
-		chip->dt.ki_coeff_low_dischg = temp;
+	if (!of_find_property(node, "qcom,ki-coeff-soc-dischg", NULL) ||
+		(!of_find_property(node, "qcom,ki-coeff-low-dischg", NULL) &&
+		!of_find_property(node, "qcom,ki-coeff-med-dischg", NULL) &&
+		!of_find_property(node, "qcom,ki-coeff-hi-dischg", NULL)))
+		return 0;
 
 	rc = fg_parse_dt_property_u32_array(node, "qcom,ki-coeff-soc-dischg",
 		chip->dt.ki_coeff_soc, KI_COEFF_SOC_LEVELS);
 	if (rc < 0)
 		return rc;
 
+	rc = fg_parse_dt_property_u32_array(node, "qcom,ki-coeff-low-dischg",
+		chip->dt.ki_coeff_low_dischg, KI_COEFF_SOC_LEVELS);
+	if (rc < 0)
+		return rc;
+
 	rc = fg_parse_dt_property_u32_array(node, "qcom,ki-coeff-med-dischg",
 		chip->dt.ki_coeff_med_dischg, KI_COEFF_SOC_LEVELS);
 	if (rc < 0)
@@ -4905,9 +4905,9 @@
 			return -EINVAL;
 		}
 
-		if (chip->dt.ki_coeff_med_dischg[i] < 0 ||
-			chip->dt.ki_coeff_med_dischg[i] > KI_COEFF_MAX) {
-			pr_err("Error in ki_coeff_med_dischg values\n");
+		if (chip->dt.ki_coeff_low_dischg[i] < 0 ||
+			chip->dt.ki_coeff_low_dischg[i] > KI_COEFF_MAX) {
+			pr_err("Error in ki_coeff_low_dischg values\n");
 			return -EINVAL;
 		}
 
@@ -4916,6 +4916,12 @@
 			pr_err("Error in ki_coeff_med_dischg values\n");
 			return -EINVAL;
 		}
+
+		if (chip->dt.ki_coeff_hi_dischg[i] < 0 ||
+			chip->dt.ki_coeff_hi_dischg[i] > KI_COEFF_MAX) {
+			pr_err("Error in ki_coeff_hi_dischg values\n");
+			return -EINVAL;
+		}
 	}
 	chip->ki_coeff_dischg_en = true;
 	return 0;
@@ -5175,8 +5181,6 @@
 	}
 
 	chip->cyc_ctr.en = of_property_read_bool(node, "qcom,cycle-counter-en");
-	if (chip->cyc_ctr.en)
-		chip->cyc_ctr.id = 1;
 
 	chip->dt.force_load_profile = of_property_read_bool(node,
 					"qcom,fg-force-load-profile");
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index e86d2af..fede66f 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -45,12 +45,12 @@
 	debug_mask, qg_debug_mask, int, 0600
 );
 
-static int qg_esr_mod_count = 10;
+static int qg_esr_mod_count = 30;
 module_param_named(
 	esr_mod_count, qg_esr_mod_count, int, 0600
 );
 
-static int qg_esr_count = 5;
+static int qg_esr_count = 3;
 module_param_named(
 	esr_count, qg_esr_count, int, 0600
 );
@@ -452,13 +452,11 @@
 }
 
 #define MIN_FIFO_FULL_TIME_MS			12000
-static int process_rt_fifo_data(struct qpnp_qg *chip,
-			bool update_vbat_low, bool update_smb)
+static int process_rt_fifo_data(struct qpnp_qg *chip, bool update_smb)
 {
 	int rc = 0;
 	ktime_t now = ktime_get();
 	s64 time_delta;
-	u8 fifo_length;
 
 	/*
 	 * Reject the FIFO read event if there are back-to-back requests
@@ -467,11 +465,10 @@
 	 */
 	time_delta = ktime_ms_delta(now, chip->last_user_update_time);
 
-	qg_dbg(chip, QG_DEBUG_FIFO, "time_delta=%lld ms update_vbat_low=%d update_smb=%d\n",
-				time_delta, update_vbat_low, update_smb);
+	qg_dbg(chip, QG_DEBUG_FIFO, "time_delta=%lld ms update_smb=%d\n",
+				time_delta, update_smb);
 
-	if (time_delta > MIN_FIFO_FULL_TIME_MS || update_vbat_low
-						|| update_smb) {
+	if (time_delta > MIN_FIFO_FULL_TIME_MS || update_smb) {
 		rc = qg_master_hold(chip, true);
 		if (rc < 0) {
 			pr_err("Failed to hold master, rc=%d\n", rc);
@@ -484,20 +481,6 @@
 			goto done;
 		}
 
-		if (update_vbat_low) {
-			/* change FIFO length */
-			fifo_length = chip->vbat_low ?
-					chip->dt.s2_vbat_low_fifo_length :
-					chip->dt.s2_fifo_length;
-			rc = qg_update_fifo_length(chip, fifo_length);
-			if (rc < 0)
-				goto done;
-
-			qg_dbg(chip, QG_DEBUG_STATUS,
-				"FIFO length updated to %d vbat_low=%d\n",
-					fifo_length, chip->vbat_low);
-		}
-
 		if (update_smb) {
 			rc = qg_masked_write(chip, chip->qg_base +
 				QG_MODE_CTL1_REG, PARALLEL_IBAT_SENSE_EN_BIT,
@@ -539,60 +522,67 @@
 static int qg_vbat_low_wa(struct qpnp_qg *chip)
 {
 	int rc, i, temp = 0;
-	u32 vbat_low_uv = 0;
+	u32 vbat_low_uv = 0, fifo_length = 0;
 
-	rc = qg_get_battery_temp(chip, &temp);
-	if (rc < 0) {
-		pr_err("Failed to read batt_temp rc=%d\n", rc);
-		temp = 250;
-	}
+	if ((chip->wa_flags & QG_VBAT_LOW_WA) && chip->vbat_low) {
+		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;
-
-	/*
-	 * PMI632 1.0 does not generate a falling VBAT_LOW IRQ.
-	 * To exit from VBAT_LOW config, check if any of the FIFO
-	 * averages is > vbat_low threshold and reconfigure the
-	 * FIFO length to normal.
-	 */
-	for (i = 0; i < chip->kdata.fifo_length; i++) {
-		if (chip->kdata.fifo[i].v > vbat_low_uv) {
-			rc = qg_master_hold(chip, true);
-			if (rc < 0) {
-				pr_err("Failed to hold master, rc=%d\n", rc);
-				goto done;
-			}
-			rc = qg_update_fifo_length(chip,
-					chip->dt.s2_fifo_length);
-			if (rc < 0)
-				goto done;
-
-			rc = qg_master_hold(chip, false);
-			if (rc < 0) {
-				pr_err("Failed to release master, rc=%d\n", rc);
-				goto done;
-			}
-			/* FIFOs restarted */
-			chip->last_fifo_update_time = ktime_get();
-
-			chip->vbat_low = false;
-			pr_info("Exit VBAT_LOW vbat_avg=%duV vbat_low=%duV updated fifo_length=%d\n",
+		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;
+		/*
+		 * PMI632 1.0 does not generate a falling VBAT_LOW IRQ.
+		 * To exit from VBAT_LOW config, check if any of the FIFO
+		 * averages is > vbat_low threshold and reconfigure the
+		 * FIFO length to normal.
+		 */
+		for (i = 0; i < chip->kdata.fifo_length; i++) {
+			if (chip->kdata.fifo[i].v > vbat_low_uv) {
+				chip->vbat_low = false;
+				pr_info("Exit VBAT_LOW vbat_avg=%duV vbat_low=%duV updated fifo_length=%d\n",
 					chip->kdata.fifo[i].v, vbat_low_uv,
 					chip->dt.s2_fifo_length);
-			break;
+				break;
+			}
 		}
 	}
 
-	return 0;
+	rc = get_fifo_length(chip, &fifo_length, false);
+	if (rc < 0) {
+		pr_err("Failed to get FIFO length, rc=%d\n", rc);
+		return rc;
+	}
 
+	if (chip->vbat_low && fifo_length == chip->dt.s2_vbat_low_fifo_length)
+		return 0;
+
+	if (!chip->vbat_low && fifo_length == chip->dt.s2_fifo_length)
+		return 0;
+
+	rc = qg_master_hold(chip, true);
+	if (rc < 0) {
+		pr_err("Failed to hold master, rc=%d\n", rc);
+		goto done;
+	}
+
+	fifo_length = chip->vbat_low ? chip->dt.s2_vbat_low_fifo_length :
+					chip->dt.s2_fifo_length;
+
+	rc = qg_update_fifo_length(chip, fifo_length);
+	if (rc < 0)
+		goto done;
+
+	qg_dbg(chip, QG_DEBUG_STATUS, "FIFO length updated to %d vbat_low=%d\n",
+					fifo_length, chip->vbat_low);
 done:
 	qg_master_hold(chip, false);
+	/* FIFOs restarted */
+	chip->last_fifo_update_time = ktime_get();
 	return rc;
 }
 
@@ -854,7 +844,7 @@
 
 static int qg_esr_estimate(struct qpnp_qg *chip)
 {
-	int rc, i, ibat;
+	int rc, i, ibat = 0;
 	u8 esr_done_count, reg0 = 0, reg1 = 0;
 	bool is_charging = false;
 
@@ -862,13 +852,17 @@
 		return 0;
 
 	/*
-	 * Charge - enable ESR estimation only during fast-charging.
+	 * Charge - enable ESR estimation if IBAT > MIN_IBAT.
 	 * Discharge - enable ESR estimation only if enabled via DT.
 	 */
+	rc = qg_get_battery_current(chip, &ibat);
+	if (rc < 0)
+		return rc;
 	if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING &&
-			chip->charge_type != POWER_SUPPLY_CHARGE_TYPE_FAST) {
+				ibat > chip->dt.esr_min_ibat_ua) {
 		qg_dbg(chip, QG_DEBUG_ESR,
-			"Skip ESR, Not in fast-charge (CC)\n");
+			"Skip CHG ESR, Fails IBAT ibat(%d) min_ibat(%d)\n",
+				ibat, chip->dt.esr_min_ibat_ua);
 		return 0;
 	}
 
@@ -1002,6 +996,8 @@
 		pr_err("Failed to release master, rc=%d\n", rc);
 		goto done;
 	}
+	/* FIFOs restarted */
+	chip->last_fifo_update_time = ktime_get();
 
 	if (chip->esr_avg) {
 		chip->kdata.param[QG_ESR].data = chip->esr_avg;
@@ -1033,11 +1029,23 @@
 	if (chip->udata.param[QG_FULL_SOC].valid)
 		chip->full_soc = chip->udata.param[QG_FULL_SOC].data;
 
-	if (chip->udata.param[QG_SOC].valid) {
-		qg_dbg(chip, QG_DEBUG_SOC, "udata SOC=%d last SOC=%d\n",
-			chip->udata.param[QG_SOC].data, chip->catch_up_soc);
+	if (chip->udata.param[QG_SOC].valid ||
+			chip->udata.param[QG_SYS_SOC].valid) {
 
-		chip->catch_up_soc = chip->udata.param[QG_SOC].data;
+		qg_dbg(chip, QG_DEBUG_SOC, "udata update: QG_SOC=%d QG_SYS_SOC=%d last_catchup_soc=%d\n",
+				chip->udata.param[QG_SOC].valid ?
+				chip->udata.param[QG_SOC].data : -EINVAL,
+				chip->udata.param[QG_SYS_SOC].valid ?
+				chip->udata.param[QG_SYS_SOC].data : -EINVAL,
+				chip->catch_up_soc);
+
+		if (chip->udata.param[QG_SYS_SOC].valid) {
+			chip->sys_soc = chip->udata.param[QG_SYS_SOC].data;
+			chip->catch_up_soc = qg_adjust_sys_soc(chip);
+		} else {
+			chip->catch_up_soc = chip->udata.param[QG_SOC].data;
+		}
+
 		qg_scale_soc(chip, false);
 
 		/* update parameters to SDAM */
@@ -1168,10 +1176,6 @@
 
 	chip->vbat_low = !!(status & VBAT_LOW_INT_RT_STS_BIT);
 
-	rc = process_rt_fifo_data(chip, true, false);
-	if (rc < 0)
-		pr_err("Failed to process RT FIFO data, rc=%d\n", rc);
-
 	qg_dbg(chip, QG_DEBUG_IRQ, "VBAT_LOW = %d\n", chip->vbat_low);
 done:
 	mutex_unlock(&chip->data_lock);
@@ -1508,69 +1512,6 @@
 	return DEFAULT_BATT_TYPE;
 }
 
-static int qg_get_battery_current(struct qpnp_qg *chip, int *ibat_ua)
-{
-	int rc = 0, last_ibat = 0;
-	u32 fifo_length = 0;
-
-	if (chip->battery_missing) {
-		*ibat_ua = 0;
-		return 0;
-	}
-
-	if (chip->parallel_enabled) {
-		/* read the last real-time FIFO */
-		rc = get_fifo_length(chip, &fifo_length, true);
-		if (rc < 0) {
-			pr_err("Failed to read RT FIFO length, rc=%d\n", rc);
-			return rc;
-		}
-		fifo_length = (fifo_length == 0) ? 0 : fifo_length - 1;
-		fifo_length *= 2;
-		rc = qg_read(chip, chip->qg_base + QG_I_FIFO0_DATA0_REG +
-					fifo_length, (u8 *)&last_ibat, 2);
-		if (rc < 0) {
-			pr_err("Failed to read FIFO_I_%d reg, rc=%d\n",
-					fifo_length / 2, rc);
-			return rc;
-		}
-	} else {
-		rc = qg_read(chip, chip->qg_base + QG_LAST_ADC_I_DATA0_REG,
-					(u8 *)&last_ibat, 2);
-		if (rc < 0) {
-			pr_err("Failed to read LAST_ADV_I reg, rc=%d\n", rc);
-			return rc;
-		}
-	}
-
-	last_ibat = sign_extend32(last_ibat, 15);
-	*ibat_ua = I_RAW_TO_UA(last_ibat);
-
-	return rc;
-}
-
-static int qg_get_battery_voltage(struct qpnp_qg *chip, int *vbat_uv)
-{
-	int rc = 0;
-	u64 last_vbat = 0;
-
-	if (chip->battery_missing) {
-		*vbat_uv = 3700000;
-		return 0;
-	}
-
-	rc = qg_read(chip, chip->qg_base + QG_LAST_ADC_V_DATA0_REG,
-				(u8 *)&last_vbat, 2);
-	if (rc < 0) {
-		pr_err("Failed to read LAST_ADV_V reg, rc=%d\n", rc);
-		return rc;
-	}
-
-	*vbat_uv = V_RAW_TO_UV(last_vbat);
-
-	return rc;
-}
-
 #define DEBUG_BATT_SOC		67
 #define BATT_MISSING_SOC	50
 #define EMPTY_SOC		0
@@ -1614,10 +1555,10 @@
 	if (!chip)
 		return -ENODEV;
 
-	if (chip->battery_missing || !chip->profile_loaded)
-		return -ENODEV;
-
 	switch (param) {
+	case TTF_VALID:
+		*val = (!chip->battery_missing && chip->profile_loaded);
+		break;
 	case TTF_MSOC:
 		rc = qg_get_battery_capacity(chip, val);
 		break;
@@ -1917,9 +1858,11 @@
 		recharge_soc = DEFAULT_RECHARGE_SOC;
 	}
 	recharge_soc = prop.intval;
+	chip->recharge_soc = recharge_soc;
 
-	qg_dbg(chip, QG_DEBUG_STATUS, "msoc=%d health=%d charge_full=%d\n",
-				chip->msoc, health, chip->charge_full);
+	qg_dbg(chip, QG_DEBUG_STATUS, "msoc=%d health=%d charge_full=%d charge_done=%d\n",
+				chip->msoc, health, chip->charge_full,
+				chip->charge_done);
 	if (chip->charge_done && !chip->charge_full) {
 		if (chip->msoc >= 99 && health == POWER_SUPPLY_HEALTH_GOOD) {
 			chip->charge_full = true;
@@ -1930,10 +1873,18 @@
 			qg_dbg(chip, QG_DEBUG_STATUS, "Terminated charging @ msoc=%d\n",
 					chip->msoc);
 		}
-	} else if ((!chip->charge_done || chip->msoc < recharge_soc)
+	} else if ((!chip->charge_done || chip->msoc <= recharge_soc)
 				&& chip->charge_full) {
 
-		if (chip->wa_flags & QG_RECHARGE_SOC_WA) {
+		bool usb_present = is_usb_present(chip);
+
+		/*
+		 * force a recharge only if SOC <= recharge SOC and
+		 * we have not started charging.
+		 */
+		if ((chip->wa_flags & QG_RECHARGE_SOC_WA) &&
+			usb_present && chip->msoc <= recharge_soc &&
+			chip->charge_status != POWER_SUPPLY_STATUS_CHARGING) {
 			/* Force recharge */
 			prop.intval = 0;
 			rc = power_supply_set_property(chip->batt_psy,
@@ -1941,23 +1892,33 @@
 			if (rc < 0)
 				pr_err("Failed to force recharge rc=%d\n", rc);
 			else
-				qg_dbg(chip, QG_DEBUG_STATUS,
-					"Forced recharge\n");
+				qg_dbg(chip, QG_DEBUG_STATUS, "Forced recharge\n");
 		}
 
+
+		if (chip->charge_done)
+			return 0;	/* wait for recharge */
+
 		/*
-		 * If recharge or discharge has started and
-		 * if linearize soc dtsi property defined
-		 * scale msoc from 100% for better UX.
+		 * If SOC has indeed dropped below recharge-SOC or
+		 * the USB is removed, if linearize-soc is set scale
+		 * msoc from 100% for better UX.
 		 */
-		if (chip->dt.linearize_soc && chip->msoc < 99) {
-			chip->maint_soc = FULL_SOC;
-			qg_scale_soc(chip, false);
-		}
-
-		qg_dbg(chip, QG_DEBUG_STATUS, "msoc=%d recharge_soc=%d charge_full (1->0)\n",
+		if (chip->msoc < recharge_soc || !usb_present) {
+			if (chip->dt.linearize_soc) {
+				get_rtc_time(&chip->last_maint_soc_update_time);
+				chip->maint_soc = FULL_SOC;
+				qg_scale_soc(chip, false);
+			}
+			chip->charge_full = false;
+			qg_dbg(chip, QG_DEBUG_STATUS, "msoc=%d recharge_soc=%d charge_full (1->0)\n",
 					chip->msoc, recharge_soc);
-		chip->charge_full = false;
+		} else {
+			/* continue with charge_full state */
+			qg_dbg(chip, QG_DEBUG_STATUS, "msoc=%d recharge_soc=%d charge_full=%d usb_present=%d\n",
+					chip->msoc, recharge_soc,
+					chip->charge_full, usb_present);
+		}
 	}
 out:
 	return 0;
@@ -1985,7 +1946,7 @@
 	if (!chip->dt.qg_ext_sense)
 		update_smb = true;
 
-	rc = process_rt_fifo_data(chip, false, update_smb);
+	rc = process_rt_fifo_data(chip, update_smb);
 	if (rc < 0)
 		pr_err("Failed to process RT FIFO data, rc=%d\n", rc);
 
@@ -2526,6 +2487,7 @@
 		qg_dbg(chip, QG_DEBUG_PROFILE, "Battery Missing!\n");
 		chip->battery_missing = true;
 		chip->profile_loaded = false;
+		chip->soc_reporting_ready = true;
 	} else {
 		/* battery present */
 		rc = get_batt_id_ohm(chip, &chip->batt_id_ohm);
@@ -2534,11 +2496,14 @@
 			chip->profile_loaded = false;
 		} else {
 			rc = qg_load_battery_profile(chip);
-			if (rc < 0)
+			if (rc < 0) {
 				pr_err("Failed to load battery-profile rc=%d\n",
 								rc);
-			else
+				chip->profile_loaded = false;
+				chip->soc_reporting_ready = true;
+			} else {
 				chip->profile_loaded = true;
+			}
 		}
 	}
 
@@ -2665,7 +2630,7 @@
 		return rc;
 	}
 
-	chip->pon_soc = chip->catch_up_soc = chip->msoc = soc;
+	chip->last_adj_ssoc = chip->catch_up_soc = chip->msoc = soc;
 	chip->kdata.param[QG_PON_OCV_UV].data = ocv_uv;
 	chip->kdata.param[QG_PON_OCV_UV].valid = true;
 
@@ -2920,10 +2885,6 @@
 				PROFILE_IRQ_DISABLE, true, 0);
 		vote(chip->good_ocv_irq_disable_votable,
 				PROFILE_IRQ_DISABLE, true, 0);
-	} else {
-		/* disable GOOD_OCV IRQ at init */
-		vote(chip->good_ocv_irq_disable_votable,
-				QG_INIT_STATE_IRQ_DISABLE, true, 0);
 	}
 
 	/* restore ESR data */
@@ -3111,6 +3072,7 @@
 #define DEFAULT_ESR_QUAL_CURRENT_UA	130000
 #define DEFAULT_ESR_QUAL_VBAT_UV	7000
 #define DEFAULT_ESR_DISABLE_SOC		1000
+#define ESR_CHG_MIN_IBAT_UA		(-450000)
 static int qg_parse_dt(struct qpnp_qg *chip)
 {
 	int rc = 0;
@@ -3329,6 +3291,12 @@
 	else
 		chip->dt.esr_disable_soc = temp * 100;
 
+	rc = of_property_read_u32(node, "qcom,esr-chg-min-ibat-ua", &temp);
+	if (rc < 0)
+		chip->dt.esr_min_ibat_ua = ESR_CHG_MIN_IBAT_UA;
+	else
+		chip->dt.esr_min_ibat_ua = (int)temp;
+
 	chip->dt.qg_ext_sense = of_property_read_bool(node, "qcom,qg-ext-sns");
 
 	/* Capacity learning params*/
@@ -3408,9 +3376,6 @@
 		return 0;
 
 	cancel_delayed_work_sync(&chip->ttf->ttf_work);
-	/* disable GOOD_OCV IRQ in sleep */
-	vote(chip->good_ocv_irq_disable_votable,
-			QG_INIT_STATE_IRQ_DISABLE, true, 0);
 
 	chip->suspend_data = false;
 
@@ -3477,16 +3442,12 @@
 {
 	u8 status2 = 0, rt_status = 0;
 	u32 ocv_uv = 0, ocv_raw = 0;
-	int rc, batt_temp = 0;
+	int rc;
 
 	/* 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);
@@ -3499,16 +3460,11 @@
 			pr_err("Failed to read good_ocv, rc=%d\n", rc);
 			return rc;
 		}
-		rc = qg_get_battery_temp(chip, &batt_temp);
-		if (rc < 0) {
-			pr_err("Failed to read BATT_TEMP, rc=%d\n", rc);
-			return rc;
-		}
 
-		chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv;
-		chip->kdata.param[QG_GOOD_OCV_UV].valid = true;
 		 /* Clear suspend data as there has been a GOOD OCV */
 		memset(&chip->kdata, 0, sizeof(chip->kdata));
+		chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv;
+		chip->kdata.param[QG_GOOD_OCV_UV].valid = true;
 		chip->suspend_data = false;
 
 		qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV\n",
@@ -3577,9 +3533,41 @@
 	return 0;
 }
 
+static int qpnp_qg_suspend(struct device *dev)
+{
+	struct qpnp_qg *chip = dev_get_drvdata(dev);
+
+	/* skip if profile is not loaded */
+	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);
+
+	return 0;
+}
+
+static int qpnp_qg_resume(struct device *dev)
+{
+	struct qpnp_qg *chip = dev_get_drvdata(dev);
+
+	/* skip if profile is not loaded */
+	if (!chip->profile_loaded)
+		return 0;
+
+	/* enable GOOD_OCV IRQ when active */
+	vote(chip->good_ocv_irq_disable_votable,
+			QG_INIT_STATE_IRQ_DISABLE, false, 0);
+
+	return 0;
+}
+
 static const struct dev_pm_ops qpnp_qg_pm_ops = {
 	.suspend_noirq	= qpnp_qg_suspend_noirq,
 	.resume_noirq	= qpnp_qg_resume_noirq,
+	.suspend	= qpnp_qg_suspend,
+	.resume		= qpnp_qg_resume,
 };
 
 static int qpnp_qg_probe(struct platform_device *pdev)
@@ -3619,6 +3607,7 @@
 	chip->maint_soc = -EINVAL;
 	chip->batt_soc = INT_MIN;
 	chip->cc_soc = INT_MIN;
+	chip->sys_soc = INT_MIN;
 	chip->full_soc = QG_SOC_FULL;
 	chip->chg_iterm_ma = INT_MIN;
 	chip->soh = -EINVAL;
diff --git a/drivers/power/supply/qcom/qpnp-qnovo.c b/drivers/power/supply/qcom/qpnp-qnovo.c
index 53af341..6adc19a 100644
--- a/drivers/power/supply/qcom/qpnp-qnovo.c
+++ b/drivers/power/supply/qcom/qpnp-qnovo.c
@@ -127,6 +127,7 @@
 #define DC_READY_VOTER		"DC_READY_VOTER"
 
 #define PT_RESTART_VOTER	"PT_RESTART_VOTER"
+#define REG_WRITE_VOTER		"REG_WRITE_VOTER"
 
 struct qnovo_dt_props {
 	bool			external_rsense;
@@ -145,6 +146,7 @@
 	struct votable		*not_ok_to_qnovo_votable;
 	struct votable		*chg_ready_votable;
 	struct votable		*awake_votable;
+	struct votable		*auto_esr_votable;
 	struct class		qnovo_class;
 	struct pmic_revid_data	*pmic_rev_id;
 	u32			wa_flags;
@@ -340,15 +342,7 @@
 		return -EINVAL;
 	}
 
-	/*
-	 * fg must be available for enable FG_AVAILABLE_VOTER
-	 * won't enable it otherwise
-	 */
-
-	if (is_fg_available(chip))
-		power_supply_set_property(chip->bms_psy,
-				POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE,
-				&pval);
+	vote(chip->auto_esr_votable, QNOVO_OVERALL_VOTER, disable, 0);
 
 	vote(chip->pt_dis_votable, QNOVO_OVERALL_VOTER, disable, 0);
 	rc = qnovo_batt_psy_update(chip, disable);
@@ -420,6 +414,27 @@
 	return 0;
 }
 
+static int auto_esr_cb(struct votable *votable, void *data, int auto_esr,
+					const char *client)
+{
+	struct qnovo *chip = data;
+	union power_supply_propval pval = {0};
+
+	pval.intval = !auto_esr;
+	if (is_fg_available(chip))
+		power_supply_set_property(chip->bms_psy,
+				POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE,
+				&pval);
+
+	return 0;
+}
+
+static void pe_ctrl2_write_cb(struct qnovo *chip, u8 *val)
+{
+	if (get_effective_result(chip->disable_votable) == 0)
+		vote(chip->auto_esr_votable, REG_WRITE_VOTER, (*val == 0), 0);
+}
+
 static int qnovo_parse_dt(struct qnovo *chip)
 {
 	struct device_node *node = chip->dev->of_node;
@@ -497,6 +512,7 @@
 	int	reg_to_unit_offset;
 	int	min_val;
 	int	max_val;
+	void	(*callback)(struct qnovo *chip, u8 *val);
 	char	*units_str;
 };
 
@@ -523,6 +539,7 @@
 		.name			= "PE_CTRL2_REG",
 		.start_addr		= QNOVO_PE_CTRL2,
 		.num_regs		= 1,
+		.callback		= pe_ctrl2_write_cb,
 		.units_str		= "",
 	},
 	[PTRAIN_STS_REG] = {
@@ -892,6 +909,10 @@
 		pr_err("Couldn't write %s rc = %d\n", params[i].name, rc);
 		return -EINVAL;
 	}
+
+	if (params[i].callback)
+		params[i].callback(chip, buf);
+
 	return count;
 }
 
@@ -1464,6 +1485,8 @@
 	vote(chip->pt_dis_votable, QNOVO_OVERALL_VOTER, true, 0);
 	vote(chip->pt_dis_votable, ESR_VOTER, false, 0);
 
+	vote(chip->auto_esr_votable, QNOVO_OVERALL_VOTER, true, 0);
+
 	val = 0;
 	rc = qnovo_write(chip, QNOVO_STRM_CTRL, &val, 1);
 	if (rc < 0) {
@@ -1656,6 +1679,13 @@
 		goto destroy_chg_ready_votable;
 	}
 
+	chip->auto_esr_votable = create_votable("AUTO_ESR", VOTE_SET_ANY,
+					auto_esr_cb, chip);
+	if (IS_ERR(chip->auto_esr_votable)) {
+		rc = PTR_ERR(chip->auto_esr_votable);
+		goto destroy_auto_esr_votable;
+	}
+
 	INIT_WORK(&chip->status_change_work, status_change_work);
 	INIT_DELAYED_WORK(&chip->dc_debounce_work, dc_debounce_work);
 	INIT_DELAYED_WORK(&chip->usb_debounce_work, usb_debounce_work);
@@ -1700,6 +1730,8 @@
 
 unreg_notifier:
 	power_supply_unreg_notifier(&chip->nb);
+destroy_auto_esr_votable:
+	destroy_votable(chip->auto_esr_votable);
 destroy_awake_votable:
 	destroy_votable(chip->awake_votable);
 destroy_chg_ready_votable:
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index 29bc0cb..18c5c72 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -61,7 +61,7 @@
 	},
 	.icl_stat		= {
 		.name   = "input current limit status",
-		.reg    = AICL_ICL_STATUS_REG,
+		.reg    = ICL_STATUS_REG,
 		.min_u  = 0,
 		.max_u  = 3000000,
 		.step_u = 50000,
@@ -95,6 +95,22 @@
 		.step_u	= 400,
 		.set_proc = smblib_set_chg_freq,
 	},
+	.aicl_5v_threshold		= {
+		.name   = "AICL 5V threshold",
+		.reg    = USBIN_5V_AICL_THRESHOLD_REG,
+		.min_u  = 4000,
+		.max_u  = 4700,
+		.step_u = 100,
+	},
+	.aicl_cont_threshold		= {
+		.name   = "AICL CONT threshold",
+		.reg    = USBIN_CONT_AICL_THRESHOLD_REG,
+		.min_u  = 4000,
+		.max_u  = 8800,
+		.step_u = 100,
+		.get_proc = smblib_get_aicl_cont_threshold,
+		.set_proc = smblib_set_aicl_cont_threshold,
+	},
 };
 
 static struct smb_params smb5_pm855b_params = {
@@ -164,6 +180,22 @@
 		.step_u	= 400,
 		.set_proc = NULL,
 	},
+	.aicl_5v_threshold		= {
+		.name   = "AICL 5V threshold",
+		.reg    = USBIN_5V_AICL_THRESHOLD_REG,
+		.min_u  = 4000,
+		.max_u  = 4700,
+		.step_u = 100,
+	},
+	.aicl_cont_threshold		= {
+		.name   = "AICL CONT threshold",
+		.reg    = USBIN_CONT_AICL_THRESHOLD_REG,
+		.min_u  = 4000,
+		.max_u  = 1180,
+		.step_u = 100,
+		.get_proc = smblib_get_aicl_cont_threshold,
+		.set_proc = smblib_set_aicl_cont_threshold,
+	},
 };
 
 struct smb_dt_props {
@@ -178,6 +210,9 @@
 	int			wd_bark_time;
 	int			batt_profile_fcc_ua;
 	int			batt_profile_fv_uv;
+	int			term_current_src;
+	int			term_current_thresh_hi_ma;
+	int			term_current_thresh_lo_ma;
 };
 
 struct smb5 {
@@ -206,6 +241,13 @@
 	USBIN_VOLTAGE,
 };
 
+enum {
+	BAT_THERM = 0,
+	MISC_THERM,
+	CONN_THERM,
+	SMB_THERM,
+};
+
 #define PMI632_MAX_ICL_UA	3000000
 static int smb5_chg_config_init(struct smb5 *chip)
 {
@@ -240,6 +282,9 @@
 		break;
 	case PMI632_SUBTYPE:
 		chip->chg.smb_version = PMI632_SUBTYPE;
+		chg->wa_flags |= WEAK_ADAPTER_WA;
+		if (pmic_rev_id->rev4 >= 2)
+			chg->wa_flags |= MOISTURE_PROTECTION_WA;
 		chg->param = smb5_pmi632_params;
 		chg->use_extcon = true;
 		chg->name = "pmi632_charger";
@@ -266,6 +311,53 @@
 	return rc;
 }
 
+#define PULL_NO_PULL	0
+#define PULL_30K	30
+#define PULL_100K	100
+#define PULL_400K	400
+static int get_valid_pullup(int pull_up)
+{
+	int pull;
+
+	/* pull up can only be 0/30K/100K/400K) */
+	switch (pull_up) {
+	case PULL_NO_PULL:
+		pull = INTERNAL_PULL_NO_PULL;
+		break;
+	case PULL_30K:
+		pull = INTERNAL_PULL_30K_PULL;
+		break;
+	case PULL_100K:
+		pull = INTERNAL_PULL_100K_PULL;
+		break;
+	case PULL_400K:
+		pull = INTERNAL_PULL_400K_PULL;
+		break;
+	default:
+		pull = INTERNAL_PULL_100K_PULL;
+	}
+
+	return pull;
+}
+
+#define INTERNAL_PULL_UP_MASK	0x3
+static int smb5_configure_internal_pull(struct smb_charger *chg, int type,
+					int pull)
+{
+	int rc;
+	int shift = type * 2;
+	u8 mask = INTERNAL_PULL_UP_MASK << shift;
+	u8 val = pull << shift;
+
+	rc = smblib_masked_write(chg, BATIF_ADC_INTERNAL_PULL_UP_REG,
+				mask, val);
+	if (rc < 0)
+		dev_err(chg->dev,
+			"Couldn't configure ADC pull-up reg rc=%d\n", rc);
+
+	return rc;
+}
+
 #define MICRO_1P5A		1500000
 #define MICRO_1PA		1000000
 #define MICRO_P1A		100000
@@ -321,6 +413,18 @@
 		chg->otg_cl_ua = (chip->chg.smb_version == PMI632_SUBTYPE) ?
 							MICRO_1PA : MICRO_1P5A;
 
+	rc = of_property_read_u32(node, "qcom,chg-term-src",
+			&chip->dt.term_current_src);
+	if (rc < 0)
+		chip->dt.term_current_src = ITERM_SRC_UNSPECIFIED;
+
+	rc = of_property_read_u32(node, "qcom,chg-term-current-ma",
+			&chip->dt.term_current_thresh_hi_ma);
+
+	if (chip->dt.term_current_src == ITERM_SRC_ADC)
+		rc = of_property_read_u32(node, "qcom,chg-term-base-current-ma",
+				&chip->dt.term_current_thresh_lo_ma);
+
 	if (of_find_property(node, "qcom,thermal-mitigation", &byte_len)) {
 		chg->thermal_mitigation = devm_kzalloc(chg->dev, byte_len,
 			GFP_KERNEL);
@@ -387,14 +491,28 @@
 	if (rc < 0)
 		chg->otg_delay_ms = OTG_DEFAULT_DEGLITCH_TIME_MS;
 
+	chg->hw_die_temp_mitigation = of_property_read_bool(node,
+					"qcom,hw-die-temp-mitigation");
+
+	chg->hw_connector_mitigation = of_property_read_bool(node,
+					"qcom,hw-connector-mitigation");
+
+	chg->connector_pull_up = -EINVAL;
+	of_property_read_u32(node, "qcom,connector-internal-pull-kohm",
+					&chg->connector_pull_up);
+
+	chg->moisture_protection_enabled = of_property_read_bool(node,
+					"qcom,moisture-protection-enable");
+
 	return 0;
 }
 
 static int smb5_get_adc_data(struct smb_charger *chg, int channel,
 				union power_supply_propval *val)
 {
-	int rc;
+	int rc = 0;
 	struct qpnp_vadc_result result;
+	u8 reg;
 
 	if (!chg->vadc_dev) {
 		if (of_find_property(chg->dev->of_node, "qcom,chg-vadc",
@@ -418,30 +536,58 @@
 	if (IS_ERR(chg->vadc_dev))
 		return PTR_ERR(chg->vadc_dev);
 
+	mutex_lock(&chg->vadc_lock);
+
 	switch (channel) {
 	case USBIN_VOLTAGE:
+		/* Store ADC channel config */
+		rc = smblib_read(chg, BATIF_ADC_CHANNEL_EN_REG, &reg);
+		if (rc < 0) {
+			dev_err(chg->dev,
+				"Couldn't read ADC config rc=%d\n", rc);
+			goto done;
+		}
+
+		/* Disable all ADC channels except IBAT channel */
+		rc = smblib_write(chg, BATIF_ADC_CHANNEL_EN_REG,
+				IBATT_CHANNEL_EN_BIT);
+		if (rc < 0) {
+			dev_err(chg->dev,
+				"Couldn't write ADC config rc=%d\n", rc);
+			goto done;
+		}
+
 		rc = qpnp_vadc_read(chg->vadc_dev, VADC_USB_IN_V_DIV_16_PM5,
 				&result);
-		if (rc < 0) {
+		if (rc < 0)
 			pr_err("Failed to read USBIN_V over vadc, rc=%d\n", rc);
-			return rc;
-		}
-		val->intval = result.physical;
+		else
+			val->intval = result.physical;
+
+		/* Restore ADC channel config */
+		rc |= smblib_write(chg, BATIF_ADC_CHANNEL_EN_REG, reg);
+		if (rc < 0)
+			dev_err(chg->dev,
+				"Couldn't write ADC config rc=%d\n", rc);
+
 		break;
 	case USBIN_CURRENT:
 		rc = qpnp_vadc_read(chg->vadc_dev, VADC_USB_IN_I_PM5, &result);
 		if (rc < 0) {
 			pr_err("Failed to read USBIN_I over vadc, rc=%d\n", rc);
-			return rc;
+			goto done;
 		}
 		val->intval = result.physical;
 		break;
 	default:
 		pr_debug("Invalid channel\n");
-		return -EINVAL;
+		rc = -EINVAL;
+		break;
 	}
 
-	return 0;
+done:
+	mutex_unlock(&chg->vadc_lock);
+	return rc;
 }
 
 
@@ -471,9 +617,12 @@
 	POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
 	POWER_SUPPLY_PROP_CONNECTOR_TYPE,
 	POWER_SUPPLY_PROP_VOLTAGE_MAX,
+	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
 	POWER_SUPPLY_PROP_SCOPE,
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED,
+	POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
+	POWER_SUPPLY_PROP_MOISTURE_DETECTED,
 };
 
 static int smb5_usb_get_prop(struct power_supply *psy,
@@ -507,6 +656,9 @@
 	case POWER_SUPPLY_PROP_VOLTAGE_MAX:
 		rc = smblib_get_prop_usb_voltage_max(chg, val);
 		break;
+	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+		rc = smblib_get_prop_usb_voltage_max_design(chg, val);
+		break;
 	case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
 		val->intval = get_client_vote(chg->usb_icl_votable, PD_VOTER);
 		break;
@@ -602,6 +754,16 @@
 	case POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED:
 		val->intval = !chg->flash_active;
 		break;
+	case POWER_SUPPLY_PROP_QC_OPTI_DISABLE:
+		if (chg->hw_die_temp_mitigation)
+			val->intval = POWER_SUPPLY_QC_THERMAL_BALANCE_DISABLE
+					| POWER_SUPPLY_QC_INOV_THERMAL_DISABLE;
+		if (chg->hw_connector_mitigation)
+			val->intval |= POWER_SUPPLY_QC_CTM_DISABLE;
+		break;
+	case POWER_SUPPLY_PROP_MOISTURE_DETECTED:
+		val->intval = chg->moisture_present;
+		break;
 	default:
 		pr_err("get prop %d is not supported in usb\n", psp);
 		rc = -EINVAL;
@@ -909,6 +1071,10 @@
 					pr_err("Failed to force 5V\n");
 				else
 					chg->pulse_cnt = 0;
+			} else {
+				/* USB absent & flash not-active - vote 100mA */
+				vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER,
+							true, SDP_100_MA);
 			}
 
 			pr_debug("flash active VBUS 5V restriction %s\n",
@@ -1075,6 +1241,7 @@
 	POWER_SUPPLY_PROP_VOLTAGE_MAX,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
 	POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+	POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT,
 	POWER_SUPPLY_PROP_TEMP,
 	POWER_SUPPLY_PROP_TECHNOLOGY,
 	POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
@@ -1151,6 +1318,9 @@
 		val->intval = get_client_vote(chg->fcc_votable,
 					      BATT_PROFILE_VOTER);
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_TERM_CURRENT:
+		rc = smblib_get_prop_batt_iterm(chg, val);
+		break;
 	case POWER_SUPPLY_PROP_TEMP:
 		rc = smblib_get_prop_batt_temp(chg, val);
 		break;
@@ -1262,7 +1432,7 @@
 		rc = smblib_set_prop_ship_mode(chg, val);
 		break;
 	case POWER_SUPPLY_PROP_RERUN_AICL:
-		rc = smblib_rerun_aicl(chg);
+		rc = smblib_run_aicl(chg, RERUN_AICL);
 		break;
 	case POWER_SUPPLY_PROP_DP_DM:
 		if (!chg->flash_active)
@@ -1485,14 +1655,6 @@
 		return rc;
 	}
 
-	rc = smblib_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
-				TYPEC_WATER_DETECTION_INT_EN_BIT);
-	if (rc < 0) {
-		dev_err(chg->dev,
-			"Couldn't configure Type-C interrupts rc=%d\n", rc);
-		return rc;
-	}
-
 	rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
 				EN_TRY_SNK_BIT, EN_TRY_SNK_BIT);
 	if (rc < 0) {
@@ -1531,6 +1693,144 @@
 		return rc;
 	}
 
+	if (chg->moisture_protection_enabled &&
+				(chg->wa_flags & MOISTURE_PROTECTION_WA)) {
+		/* Enable moisture detection interrupt */
+		rc = smblib_masked_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
+				TYPEC_WATER_DETECTION_INT_EN_BIT,
+				TYPEC_WATER_DETECTION_INT_EN_BIT);
+		if (rc < 0) {
+			dev_err(chg->dev, "Couldn't enable moisture detection interrupt rc=%d\n",
+				rc);
+			return rc;
+		}
+
+		/* Enable uUSB factory mode */
+		rc = smblib_masked_write(chg, TYPEC_U_USB_CFG_REG,
+					EN_MICRO_USB_FACTORY_MODE_BIT,
+					EN_MICRO_USB_FACTORY_MODE_BIT);
+		if (rc < 0) {
+			dev_err(chg->dev, "Couldn't enable uUSB factory mode c=%d\n",
+				rc);
+			return rc;
+		}
+
+		/* Disable periodic monitoring of CC_ID pin */
+		rc = smblib_write(chg, TYPEC_U_USB_WATER_PROTECTION_CFG_REG, 0);
+		if (rc < 0) {
+			dev_err(chg->dev, "Couldn't disable periodic monitoring of CC_ID rc=%d\n",
+				rc);
+			return rc;
+		}
+	}
+
+	return rc;
+}
+
+static int smb5_configure_mitigation(struct smb_charger *chg)
+{
+	int rc;
+	u8 chan = 0;
+
+	if (!chg->hw_die_temp_mitigation && !chg->hw_connector_mitigation)
+		return 0;
+
+	if (chg->hw_die_temp_mitigation) {
+		rc = smblib_write(chg, MISC_THERMREG_SRC_CFG_REG,
+				THERMREG_CONNECTOR_ADC_SRC_EN_BIT
+				| THERMREG_DIE_ADC_SRC_EN_BIT
+				| THERMREG_DIE_CMP_SRC_EN_BIT);
+		if (rc < 0) {
+			dev_err(chg->dev,
+				"Couldn't configure THERM_SRC reg rc=%d\n", rc);
+			return rc;
+		};
+
+		chan = DIE_TEMP_CHANNEL_EN_BIT;
+	}
+
+	if (chg->hw_connector_mitigation)
+		chan |= CONN_THM_CHANNEL_EN_BIT;
+
+	rc = smblib_masked_write(chg, BATIF_ADC_CHANNEL_EN_REG,
+			CONN_THM_CHANNEL_EN_BIT | DIE_TEMP_CHANNEL_EN_BIT,
+			chan);
+	if (rc < 0) {
+		dev_err(chg->dev, "Couldn't enable ADC channel rc=%d\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int smb5_configure_iterm_thresholds_adc(struct smb5 *chip)
+{
+	u8 *buf;
+	int rc = 0;
+	s16 raw_hi_thresh, raw_lo_thresh;
+	struct smb_charger *chg = &chip->chg;
+
+	if (chip->dt.term_current_thresh_hi_ma < -10000 ||
+			chip->dt.term_current_thresh_hi_ma > 10000 ||
+			chip->dt.term_current_thresh_lo_ma < -10000 ||
+			chip->dt.term_current_thresh_lo_ma > 10000) {
+		dev_err(chg->dev, "ITERM threshold out of range rc=%d\n", rc);
+		return -EINVAL;
+	}
+
+	/*
+	 * Conversion:
+	 *	raw (A) = (scaled_mA * ADC_CHG_TERM_MASK) / (10 * 1000)
+	 * Note: raw needs to be converted to big-endian format.
+	 */
+
+	if (chip->dt.term_current_thresh_hi_ma) {
+		raw_hi_thresh = ((chip->dt.term_current_thresh_hi_ma *
+						ADC_CHG_TERM_MASK) / 10000);
+		raw_hi_thresh = sign_extend32(raw_hi_thresh, 15);
+		buf = (u8 *)&raw_hi_thresh;
+		raw_hi_thresh = buf[1] | (buf[0] << 8);
+
+		rc = smblib_batch_write(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG,
+				(u8 *)&raw_hi_thresh, 2);
+		if (rc < 0) {
+			dev_err(chg->dev, "Couldn't configure ITERM threshold HIGH rc=%d\n",
+					rc);
+			return rc;
+		}
+	}
+
+	if (chip->dt.term_current_thresh_lo_ma) {
+		raw_lo_thresh = ((chip->dt.term_current_thresh_lo_ma *
+					ADC_CHG_TERM_MASK) / 10000);
+		raw_lo_thresh = sign_extend32(raw_lo_thresh, 15);
+		buf = (u8 *)&raw_lo_thresh;
+		raw_lo_thresh = buf[1] | (buf[0] << 8);
+
+		rc = smblib_batch_write(chg, CHGR_ADC_ITERM_LO_THD_MSB_REG,
+				(u8 *)&raw_lo_thresh, 2);
+		if (rc < 0) {
+			dev_err(chg->dev, "Couldn't configure ITERM threshold LOW rc=%d\n",
+					rc);
+			return rc;
+		}
+	}
+
+	return rc;
+}
+
+static int smb5_configure_iterm_thresholds(struct smb5 *chip)
+{
+	int rc = 0;
+
+	switch (chip->dt.term_current_src) {
+	case ITERM_SRC_ADC:
+		rc = smb5_configure_iterm_thresholds_adc(chip);
+		break;
+	default:
+		break;
+	}
+
 	return rc;
 }
 
@@ -1553,6 +1853,12 @@
 
 	smblib_get_charge_param(chg, &chg->param.usb_icl,
 				&chg->default_icl_ua);
+	smblib_get_charge_param(chg, &chg->param.aicl_5v_threshold,
+				&chg->default_aicl_5v_threshold_mv);
+	chg->aicl_5v_threshold_mv = chg->default_aicl_5v_threshold_mv;
+	smblib_get_charge_param(chg, &chg->param.aicl_cont_threshold,
+				&chg->default_aicl_cont_threshold_mv);
+	chg->aicl_cont_threshold_mv = chg->default_aicl_cont_threshold_mv;
 
 	/* Use SW based VBUS control, disable HW autonomous mode */
 	rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
@@ -1640,6 +1946,13 @@
 		return rc;
 	}
 
+	/* configure temperature mitigation */
+	rc = smb5_configure_mitigation(chg);
+	if (rc < 0) {
+		dev_err(chg->dev, "Couldn't configure mitigation rc=%d\n", rc);
+		return rc;
+	}
+
 	/* vote 0mA on usb_icl for non battery platforms */
 	vote(chg->usb_icl_votable,
 		DEFAULT_VOTER, chip->dt.no_battery, 0);
@@ -1704,6 +2017,14 @@
 		return rc;
 	}
 
+	/* set termination current threshold values */
+	rc = smb5_configure_iterm_thresholds(chip);
+	if (rc < 0) {
+		pr_err("Couldn't configure ITERM thresholds rc=%d\n",
+				rc);
+		return rc;
+	}
+
 	/* configure float charger options */
 	switch (chip->dt.float_option) {
 	case FLOAT_DCP:
@@ -1850,6 +2171,17 @@
 		return rc;
 	}
 
+	if (chg->connector_pull_up != -EINVAL) {
+		rc = smb5_configure_internal_pull(chg, CONN_THERM,
+				get_valid_pullup(chg->connector_pull_up));
+		if (rc < 0) {
+			dev_err(chg->dev,
+				"Couldn't configure CONN_THERM pull-up rc=%d\n",
+				rc);
+			return rc;
+		}
+	}
+
 	return rc;
 }
 
@@ -2020,6 +2352,8 @@
 	[USBIN_UV_IRQ] = {
 		.name		= "usbin-uv",
 		.handler	= usbin_uv_irq_handler,
+		.wake		= true,
+		.storm_data	= {true, 3000, 5},
 	},
 	[USBIN_OV_IRQ] = {
 		.name		= "usbin-ov",
@@ -2396,6 +2730,7 @@
 	chg->irq_info = smb5_irqs;
 	chg->die_health = -EINVAL;
 	chg->otg_present = false;
+	mutex_init(&chg->vadc_lock);
 
 	chg->regmap = dev_get_regmap(chg->dev->parent, NULL);
 	if (!chg->regmap) {
diff --git a/drivers/power/supply/qcom/qpnp-smbcharger.c b/drivers/power/supply/qcom/qpnp-smbcharger.c
index 40cfd9c..e9e080d 100644
--- a/drivers/power/supply/qcom/qpnp-smbcharger.c
+++ b/drivers/power/supply/qcom/qpnp-smbcharger.c
@@ -632,6 +632,18 @@
 	mutex_unlock(&chip->pm_lock);
 };
 
+static bool is_bms_psy_present(struct smbchg_chip *chip)
+{
+	if (chip->bms_psy)
+		return true;
+
+	if (chip->bms_psy_name)
+		chip->bms_psy = power_supply_get_by_name(
+					(char *)chip->bms_psy_name);
+
+	return chip->bms_psy ? true : false;
+}
+
 enum pwr_path_type {
 	UNKNOWN = 0,
 	PWR_PATH_BATTERY = 1,
@@ -3748,17 +3760,11 @@
 static void smbchg_external_power_changed(struct power_supply *psy)
 {
 	struct smbchg_chip *chip = power_supply_get_drvdata(psy);
-	union power_supply_propval prop = {0,};
-	int rc, current_limit = 0, soc;
-	enum power_supply_type usb_supply_type;
-	char *usb_type_name = "null";
-
-	if (chip->bms_psy_name)
-		chip->bms_psy =
-			power_supply_get_by_name((char *)chip->bms_psy_name);
+	int rc, soc;
 
 	smbchg_aicl_deglitch_wa_check(chip);
-	if (chip->bms_psy) {
+
+	if (is_bms_psy_present(chip)) {
 		check_battery_type(chip);
 		soc = get_prop_batt_capacity(chip);
 		if (chip->previous_soc != soc) {
@@ -3773,37 +3779,8 @@
 									rc);
 	}
 
-	rc = power_supply_get_property(chip->usb_psy,
-				POWER_SUPPLY_PROP_CHARGING_ENABLED, &prop);
-	if (rc == 0)
-		vote(chip->usb_suspend_votable, POWER_SUPPLY_EN_VOTER,
-				!prop.intval, 0);
-
-	current_limit = chip->usb_current_max / 1000;
-
-	/* Override if type-c charger used */
-	if (chip->typec_current_ma > 500 &&
-			current_limit < chip->typec_current_ma)
-		current_limit = chip->typec_current_ma;
-
-	read_usb_type(chip, &usb_type_name, &usb_supply_type);
-
-	if (usb_supply_type != POWER_SUPPLY_TYPE_USB)
-		goto  skip_current_for_non_sdp;
-
-	pr_smb(PR_MISC, "usb type = %s current_limit = %d\n",
-			usb_type_name, current_limit);
-
-	rc = vote(chip->usb_icl_votable, PSY_ICL_VOTER, true,
-				current_limit);
-	if (rc < 0)
-		pr_err("Couldn't update USB PSY ICL vote rc=%d\n", rc);
-
-skip_current_for_non_sdp:
+	/* adjust vfloat */
 	smbchg_vfloat_adjust_check(chip);
-
-	if (chip->batt_psy)
-		power_supply_changed(chip->batt_psy);
 }
 
 static int smbchg_otg_regulator_enable(struct regulator_dev *rdev)
@@ -5754,6 +5731,21 @@
 	}
 }
 
+static int smbchg_set_sdp_current(struct smbchg_chip *chip, int current_ma)
+{
+	if (chip->usb_supply_type == POWER_SUPPLY_TYPE_USB) {
+		/* Override if type-c charger used */
+		if (chip->typec_current_ma > 500 &&
+				current_ma < chip->typec_current_ma) {
+			current_ma = chip->typec_current_ma;
+		}
+		pr_smb(PR_MISC, "from USB current_ma = %d\n", current_ma);
+		vote(chip->usb_icl_votable, PSY_ICL_VOTER, true, current_ma);
+	}
+
+	return 0;
+}
+
 static int smbchg_usb_get_property(struct power_supply *psy,
 				  enum power_supply_property psp,
 				  union power_supply_propval *val)
@@ -5762,7 +5754,12 @@
 
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
-		val->intval = chip->usb_current_max;
+	case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
+		if (chip->usb_icl_votable)
+			val->intval = get_client_vote(chip->usb_icl_votable,
+						PSY_ICL_VOTER) * 1000;
+		else
+			val->intval = 0;
 		break;
 	case POWER_SUPPLY_PROP_PRESENT:
 		val->intval = chip->usb_present;
@@ -5792,17 +5789,16 @@
 	struct smbchg_chip *chip = power_supply_get_drvdata(psy);
 
 	switch (psp) {
-	case POWER_SUPPLY_PROP_CURRENT_MAX:
-		chip->usb_current_max = val->intval;
-		break;
 	case POWER_SUPPLY_PROP_ONLINE:
 		chip->usb_online = val->intval;
 		break;
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+	case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
+		smbchg_set_sdp_current(chip, val->intval / 1000);
 	default:
 		return -EINVAL;
 	}
 
-	power_supply_changed(psy);
 	return 0;
 }
 
@@ -5812,6 +5808,7 @@
 {
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
+	case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
 		return 1;
 	default:
 		break;
@@ -5833,6 +5830,7 @@
 	POWER_SUPPLY_PROP_TYPE,
 	POWER_SUPPLY_PROP_REAL_TYPE,
 	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
 };
 
 #define CHARGE_OUTPUT_VTG_RATIO		840
@@ -7685,19 +7683,19 @@
 #define SMBCHG_LITE_MISC_SUBTYPE	0x57
 static int smbchg_request_irq(struct smbchg_chip *chip,
 				struct device_node *child,
-				int irq_num, char *irq_name,
+				int *irq_num, char *irq_name,
 				irqreturn_t (irq_handler)(int irq, void *_chip),
 				int flags)
 {
 	int rc;
 
-	irq_num = of_irq_get_byname(child, irq_name);
-	if (irq_num < 0) {
+	*irq_num = of_irq_get_byname(child, irq_name);
+	if (*irq_num < 0) {
 		dev_err(chip->dev, "Unable to get %s irqn", irq_name);
 		rc = -ENXIO;
 	}
 	rc = devm_request_threaded_irq(chip->dev,
-			irq_num, NULL, irq_handler, flags, irq_name,
+			*irq_num, NULL, irq_handler, flags, irq_name,
 			chip);
 	if (rc < 0) {
 		dev_err(chip->dev, "Unable to request %s irq: %dn",
@@ -7739,26 +7737,28 @@
 		case SMBCHG_CHGR_SUBTYPE:
 		case SMBCHG_LITE_CHGR_SUBTYPE:
 			rc = smbchg_request_irq(chip, child,
-				chip->chg_error_irq, "chg-error",
+				&chip->chg_error_irq, "chg-error",
 				chg_error_handler, flags);
 			if (rc < 0)
 				return rc;
-			rc = smbchg_request_irq(chip, child, chip->taper_irq,
+			rc = smbchg_request_irq(chip, child, &chip->taper_irq,
 				"chg-taper-thr", taper_handler,
 				(IRQF_TRIGGER_RISING | IRQF_ONESHOT));
 			if (rc < 0)
 				return rc;
 			disable_irq_nosync(chip->taper_irq);
-			rc = smbchg_request_irq(chip, child, chip->chg_term_irq,
+			rc = smbchg_request_irq(chip, child,
+				&chip->chg_term_irq,
 				"chg-tcc-thr", chg_term_handler,
 				(IRQF_TRIGGER_RISING | IRQF_ONESHOT));
 			if (rc < 0)
 				return rc;
-			rc = smbchg_request_irq(chip, child, chip->recharge_irq,
+			rc = smbchg_request_irq(chip, child,
+				&chip->recharge_irq,
 				"chg-rechg-thr", recharge_handler, flags);
 			if (rc < 0)
 				return rc;
-			rc = smbchg_request_irq(chip, child, chip->fastchg_irq,
+			rc = smbchg_request_irq(chip, child, &chip->fastchg_irq,
 				"chg-p2f-thr", fastchg_handler, flags);
 			if (rc < 0)
 				return rc;
@@ -7768,32 +7768,33 @@
 			break;
 		case SMBCHG_BAT_IF_SUBTYPE:
 		case SMBCHG_LITE_BAT_IF_SUBTYPE:
-			rc = smbchg_request_irq(chip, child, chip->batt_hot_irq,
+			rc = smbchg_request_irq(chip, child,
+				&chip->batt_hot_irq,
 				"batt-hot", batt_hot_handler, flags);
 			if (rc < 0)
 				return rc;
 			rc = smbchg_request_irq(chip, child,
-				chip->batt_warm_irq,
+				&chip->batt_warm_irq,
 				"batt-warm", batt_warm_handler, flags);
 			if (rc < 0)
 				return rc;
 			rc = smbchg_request_irq(chip, child,
-				chip->batt_cool_irq,
+				&chip->batt_cool_irq,
 				"batt-cool", batt_cool_handler, flags);
 			if (rc < 0)
 				return rc;
 			rc = smbchg_request_irq(chip, child,
-				chip->batt_cold_irq,
+				&chip->batt_cold_irq,
 				"batt-cold", batt_cold_handler, flags);
 			if (rc < 0)
 				return rc;
 			rc = smbchg_request_irq(chip, child,
-				chip->batt_missing_irq,
+				&chip->batt_missing_irq,
 				"batt-missing", batt_pres_handler, flags);
 			if (rc < 0)
 				return rc;
 			rc = smbchg_request_irq(chip, child,
-				chip->vbat_low_irq,
+				&chip->vbat_low_irq,
 				"batt-low", vbat_low_handler, flags);
 			if (rc < 0)
 				return rc;
@@ -7808,24 +7809,24 @@
 		case SMBCHG_USB_CHGPTH_SUBTYPE:
 		case SMBCHG_LITE_USB_CHGPTH_SUBTYPE:
 			rc = smbchg_request_irq(chip, child,
-				chip->usbin_uv_irq,
+				&chip->usbin_uv_irq,
 				"usbin-uv", usbin_uv_handler,
 				flags | IRQF_EARLY_RESUME);
 			if (rc < 0)
 				return rc;
 			rc = smbchg_request_irq(chip, child,
-				chip->usbin_ov_irq,
+				&chip->usbin_ov_irq,
 				"usbin-ov", usbin_ov_handler, flags);
 			if (rc < 0)
 				return rc;
 			rc = smbchg_request_irq(chip, child,
-				chip->src_detect_irq,
+				&chip->src_detect_irq,
 				"usbin-src-det",
 				src_detect_handler, flags);
 			if (rc < 0)
 				return rc;
 			rc = smbchg_request_irq(chip, child,
-				chip->aicl_done_irq,
+				&chip->aicl_done_irq,
 				"aicl-done",
 				aicl_done_handler,
 				(IRQF_TRIGGER_RISING | IRQF_ONESHOT));
@@ -7834,18 +7835,18 @@
 
 			if (chip->schg_version != QPNP_SCHG_LITE) {
 				rc = smbchg_request_irq(chip, child,
-					chip->otg_fail_irq, "otg-fail",
+					&chip->otg_fail_irq, "otg-fail",
 					otg_fail_handler, flags);
 				if (rc < 0)
 					return rc;
 				rc = smbchg_request_irq(chip, child,
-					chip->otg_oc_irq, "otg-oc",
+					&chip->otg_oc_irq, "otg-oc",
 					otg_oc_handler,
 					(IRQF_TRIGGER_RISING | IRQF_ONESHOT));
 				if (rc < 0)
 					return rc;
 				rc = smbchg_request_irq(chip, child,
-					chip->usbid_change_irq, "usbid-change",
+					&chip->usbid_change_irq, "usbid-change",
 					usbid_change_handler,
 					(IRQF_TRIGGER_FALLING | IRQF_ONESHOT));
 				if (rc < 0)
@@ -7864,7 +7865,7 @@
 			break;
 		case SMBCHG_DC_CHGPTH_SUBTYPE:
 		case SMBCHG_LITE_DC_CHGPTH_SUBTYPE:
-			rc = smbchg_request_irq(chip, child, chip->dcin_uv_irq,
+			rc = smbchg_request_irq(chip, child, &chip->dcin_uv_irq,
 				"dcin-uv", dcin_uv_handler, flags);
 			if (rc < 0)
 				return rc;
@@ -7872,16 +7873,17 @@
 			break;
 		case SMBCHG_MISC_SUBTYPE:
 		case SMBCHG_LITE_MISC_SUBTYPE:
-			rc = smbchg_request_irq(chip, child, chip->power_ok_irq,
+			rc = smbchg_request_irq(chip, child,
+				&chip->power_ok_irq,
 				"power-ok", power_ok_handler, flags);
 			if (rc < 0)
 				return rc;
-			rc = smbchg_request_irq(chip, child, chip->chg_hot_irq,
+			rc = smbchg_request_irq(chip, child, &chip->chg_hot_irq,
 				"temp-shutdown", chg_hot_handler, flags);
 			if (rc < 0)
 				return rc;
 			rc = smbchg_request_irq(chip, child,
-				chip->wdog_timeout_irq, "wdog-timeout",
+				&chip->wdog_timeout_irq, "wdog-timeout",
 				wdog_timeout_handler, flags);
 			if (rc < 0)
 				return rc;
@@ -7892,19 +7894,19 @@
 			break;
 		case SMBCHG_LITE_OTG_SUBTYPE:
 			rc = smbchg_request_irq(chip, child,
-				chip->usbid_change_irq, "usbid-change",
+				&chip->usbid_change_irq, "usbid-change",
 				usbid_change_handler,
 				(IRQF_TRIGGER_FALLING | IRQF_ONESHOT));
 			if (rc < 0)
 				return rc;
 			rc = smbchg_request_irq(chip, child,
-				chip->otg_oc_irq, "otg-oc",
+				&chip->otg_oc_irq, "otg-oc",
 				otg_oc_handler,
 				(IRQF_TRIGGER_RISING | IRQF_ONESHOT));
 			if (rc < 0)
 				return rc;
 			rc = smbchg_request_irq(chip, child,
-				chip->otg_fail_irq, "otg-fail",
+				&chip->otg_fail_irq, "otg-fail",
 				otg_fail_handler, flags);
 			if (rc < 0)
 				return rc;
diff --git a/drivers/power/supply/qcom/schgm-flash.c b/drivers/power/supply/qcom/schgm-flash.c
index eed70d3..3bbbdbf 100644
--- a/drivers/power/supply/qcom/schgm-flash.c
+++ b/drivers/power/supply/qcom/schgm-flash.c
@@ -101,6 +101,11 @@
 	}
 }
 
+bool is_flash_active(struct smb_charger *chg)
+{
+	return chg->flash_active ? true : false;
+}
+
 int schgm_flash_get_vreg_ok(struct smb_charger *chg, int *val)
 {
 	int rc, vreg_state;
@@ -147,6 +152,29 @@
 	return 0;
 }
 
+void schgm_flash_torch_priority(struct smb_charger *chg, enum torch_mode mode)
+{
+	int rc;
+	u8 reg;
+
+	/*
+	 * If torch is configured in default BOOST mode, skip any update in the
+	 * mode configuration.
+	 */
+	if (chg->headroom_mode == FIXED_MODE)
+		return;
+
+	if ((mode != TORCH_BOOST_MODE) && (mode != TORCH_BUCK_MODE))
+		return;
+
+	reg = mode;
+	rc = smblib_masked_write(chg, SCHGM_TORCH_PRIORITY_CONTROL_REG,
+					TORCH_PRIORITY_CONTROL_BIT, reg);
+	if (rc < 0)
+		pr_err("Couldn't configure Torch priority control rc=%d\n",
+				rc);
+}
+
 int schgm_flash_init(struct smb_charger *chg)
 {
 	int rc;
@@ -190,7 +218,7 @@
 
 		reg = (chg->headroom_mode == FIXED_MODE)
 					? TORCH_PRIORITY_CONTROL_BIT : 0;
-		rc = smblib_write(chg, SCHGM_TORCH_PRIORITY_CONTROL, reg);
+		rc = smblib_write(chg, SCHGM_TORCH_PRIORITY_CONTROL_REG, reg);
 		if (rc < 0) {
 			pr_err("Couldn't force 5V boost in torch mode rc=%d\n",
 					rc);
diff --git a/drivers/power/supply/qcom/schgm-flash.h b/drivers/power/supply/qcom/schgm-flash.h
index b6fff6c..aaa5932 100644
--- a/drivers/power/supply/qcom/schgm-flash.h
+++ b/drivers/power/supply/qcom/schgm-flash.h
@@ -37,7 +37,7 @@
 #define SCHGM_FLASH_CONTROL_REG			(SCHGM_FLASH_BASE + 0x60)
 #define SOC_LOW_FOR_FLASH_EN_BIT		BIT(7)
 
-#define SCHGM_TORCH_PRIORITY_CONTROL		(SCHGM_FLASH_BASE + 0x63)
+#define SCHGM_TORCH_PRIORITY_CONTROL_REG	(SCHGM_FLASH_BASE + 0x63)
 #define TORCH_PRIORITY_CONTROL_BIT		BIT(0)
 
 #define SCHGM_SOC_BASED_FLASH_DERATE_TH_CFG_REG	(SCHGM_FLASH_BASE + 0x67)
@@ -45,8 +45,15 @@
 #define SCHGM_SOC_BASED_FLASH_DISABLE_TH_CFG_REG \
 						(SCHGM_FLASH_BASE + 0x68)
 
+enum torch_mode {
+	TORCH_BUCK_MODE = 0,
+	TORCH_BOOST_MODE,
+};
+
 int schgm_flash_get_vreg_ok(struct smb_charger *chg, int *val);
+void schgm_flash_torch_priority(struct smb_charger *chg, enum torch_mode mode);
 int schgm_flash_init(struct smb_charger *chg);
+bool is_flash_active(struct smb_charger *chg);
 
 irqreturn_t schgm_flash_default_irq_handler(int irq, void *data);
 irqreturn_t schgm_flash_ilim2_irq_handler(int irq, void *data);
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 612c3dd..5b94ff2 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -4757,6 +4757,7 @@
 {
 	int rc;
 	u8 stat4, stat5;
+	bool lock = false;
 	struct smb_charger *chg = container_of(work, struct smb_charger,
 						rdstd_cc2_detach_work);
 
@@ -4819,9 +4820,28 @@
 	rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
 						EXIT_SNK_BASED_ON_CC_BIT, 0);
 	smblib_reg_block_restore(chg, cc2_detach_settings);
-	mutex_lock(&chg->lock);
+
+	/*
+	 * Mutex acquisition deadlock can happen while cancelling this work
+	 * during pd_hard_reset from the function smblib_cc2_sink_removal_exit
+	 * which is called in the same lock context that we try to acquire in
+	 * this work routine.
+	 * Check if this work is running during pd_hard_reset and use trylock
+	 * instead of mutex_lock to prevent any deadlock if mutext is already
+	 * held.
+	 */
+	if (chg->pd_hard_reset) {
+		if (mutex_trylock(&chg->lock))
+			lock = true;
+	} else {
+		mutex_lock(&chg->lock);
+		lock = true;
+	}
+
 	smblib_usb_typec_change(chg);
-	mutex_unlock(&chg->lock);
+
+	if (lock)
+		mutex_unlock(&chg->lock);
 	return;
 
 rerun:
diff --git a/drivers/power/supply/qcom/smb1355-charger.c b/drivers/power/supply/qcom/smb1355-charger.c
index 1d99ccb..2671d6b 100644
--- a/drivers/power/supply/qcom/smb1355-charger.c
+++ b/drivers/power/supply/qcom/smb1355-charger.c
@@ -80,8 +80,12 @@
 #define BATIF_CFG_SMISC_BATID_REG		(BATIF_BASE + 0x73)
 #define CFG_SMISC_RBIAS_EXT_CTRL_BIT		BIT(2)
 
-#define SMB2CHGS_BATIF_ENG_SMISC_DIETEMP	(BATIF_BASE + 0xC0)
+#define SMB2CHG_BATIF_ENG_SMISC_DIETEMP	(BATIF_BASE + 0xC0)
 #define TDIE_COMPARATOR_THRESHOLD		GENMASK(5, 0)
+#define DIE_LOW_RANGE_BASE_DEGC			34
+#define DIE_LOW_RANGE_DELTA			16
+#define DIE_LOW_RANGE_MAX_DEGC			97
+#define DIE_LOW_RANGE_SHIFT			4
 
 #define BATIF_ENG_SCMISC_SPARE1_REG		(BATIF_BASE + 0xC2)
 #define EXT_BIAS_PIN_BIT			BIT(2)
@@ -91,13 +95,10 @@
 #define VALLEY_COMPARATOR_EN_BIT		BIT(0)
 
 #define TEMP_COMP_STATUS_REG			(MISC_BASE + 0x07)
-#define SKIN_TEMP_RST_HOT_BIT			BIT(6)
-#define SKIN_TEMP_UB_HOT_BIT			BIT(5)
-#define SKIN_TEMP_LB_HOT_BIT			BIT(4)
-#define DIE_TEMP_TSD_HOT_BIT			BIT(3)
-#define DIE_TEMP_RST_HOT_BIT			BIT(2)
-#define DIE_TEMP_UB_HOT_BIT			BIT(1)
-#define DIE_TEMP_LB_HOT_BIT			BIT(0)
+#define TEMP_RST_HOT_BIT			BIT(2)
+#define TEMP_UB_HOT_BIT				BIT(1)
+#define TEMP_LB_HOT_BIT				BIT(0)
+#define SKIN_TEMP_SHIFT				4
 
 #define MISC_RT_STS_REG				(MISC_BASE + 0x10)
 #define HARD_ILIMIT_RT_STS_BIT			BIT(5)
@@ -223,6 +224,8 @@
 	bool	disable_ctm;
 	int	pl_mode;
 	int	pl_batfet_mode;
+	bool	hw_die_temp_mitigation;
+	u32	die_temp_threshold;
 };
 
 struct smb1355 {
@@ -250,6 +253,11 @@
 	struct votable		*irq_disable_votable;
 };
 
+enum {
+	CONNECTOR_TEMP = 0,
+	DIE_TEMP,
+};
+
 static bool is_secure(struct smb1355 *chip, int addr)
 {
 	if (addr == CLOCK_REQUEST_REG)
@@ -379,8 +387,7 @@
 	u8 temp_stat;
 
 	for (i = 0; i < BIT(5); i++) {
-		rc = smb1355_masked_write(chip,
-				SMB2CHGS_BATIF_ENG_SMISC_DIETEMP,
+		rc = smb1355_masked_write(chip, SMB2CHG_BATIF_ENG_SMISC_DIETEMP,
 				TDIE_COMPARATOR_THRESHOLD, i);
 		if (rc < 0) {
 			pr_err("Couldn't set temp comp threshold rc=%d\n", rc);
@@ -399,7 +406,7 @@
 			continue;
 		}
 
-		if (!(temp_stat & DIE_TEMP_UB_HOT_BIT)) {
+		if (!(temp_stat & TEMP_UB_HOT_BIT)) {
 			/* found the temp */
 			break;
 		}
@@ -465,6 +472,7 @@
 	return 0;
 }
 
+#define DEFAULT_DIE_TEMP_LOW_THRESHOLD		90
 static int smb1355_parse_dt(struct smb1355 *chip)
 {
 	struct device_node *node = chip->dev->of_node;
@@ -495,6 +503,15 @@
 	if (of_property_read_bool(node, "qcom,stacked-batfet"))
 		chip->dt.pl_batfet_mode = POWER_SUPPLY_PL_STACKED_BATFET;
 
+	chip->dt.hw_die_temp_mitigation = of_property_read_bool(node,
+					"qcom,hw-die-temp-mitigation");
+
+	chip->dt.die_temp_threshold = DEFAULT_DIE_TEMP_LOW_THRESHOLD;
+	of_property_read_u32(node, "qcom,die-temp-threshold-degc",
+				&chip->dt.die_temp_threshold);
+	if (chip->dt.die_temp_threshold > DIE_LOW_RANGE_MAX_DEGC)
+		chip->dt.die_temp_threshold = DIE_LOW_RANGE_MAX_DEGC;
+
 	return 0;
 }
 
@@ -520,6 +537,7 @@
 	POWER_SUPPLY_PROP_MIN_ICL,
 	POWER_SUPPLY_PROP_CURRENT_MAX,
 	POWER_SUPPLY_PROP_SET_SHIP_MODE,
+	POWER_SUPPLY_PROP_DIE_HEALTH,
 };
 
 static int smb1355_get_prop_batt_charge_type(struct smb1355 *chip,
@@ -546,10 +564,13 @@
 	return rc;
 }
 
-static int smb1355_get_prop_connector_health(struct smb1355 *chip)
+static int smb1355_get_prop_health(struct smb1355 *chip, int type)
 {
 	u8 temp;
-	int rc;
+	int rc, shift;
+
+	/* Connector-temp uses skin-temp configuration */
+	shift = (type == CONNECTOR_TEMP) ? SKIN_TEMP_SHIFT : 0;
 
 	rc = smb1355_read(chip, TEMP_COMP_STATUS_REG, &temp);
 	if (rc < 0) {
@@ -557,13 +578,13 @@
 		return POWER_SUPPLY_HEALTH_UNKNOWN;
 	}
 
-	if (temp & SKIN_TEMP_RST_HOT_BIT)
+	if (temp & (TEMP_RST_HOT_BIT << shift))
 		return POWER_SUPPLY_HEALTH_OVERHEAT;
 
-	if (temp & SKIN_TEMP_UB_HOT_BIT)
+	if (temp & (TEMP_UB_HOT_BIT << shift))
 		return POWER_SUPPLY_HEALTH_HOT;
 
-	if (temp & SKIN_TEMP_LB_HOT_BIT)
+	if (temp & (TEMP_LB_HOT_BIT << shift))
 		return POWER_SUPPLY_HEALTH_WARM;
 
 	return POWER_SUPPLY_HEALTH_COOL;
@@ -614,7 +635,17 @@
 		val->intval = chip->die_temp_deciDegC;
 		break;
 	case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
-		rc = smb1355_get_prop_charger_temp_max(chip, val);
+		/*
+		 * In case of h/w controlled die_temp mitigation,
+		 * die_temp/die_temp_max can not be reported as this
+		 * requires run time manipulation of DIE_TEMP low
+		 * threshold which will interfere with h/w mitigation
+		 * scheme.
+		 */
+		if (chip->dt.hw_die_temp_mitigation)
+			val->intval = -EINVAL;
+		else
+			rc = smb1355_get_prop_charger_temp_max(chip, val);
 		break;
 	case POWER_SUPPLY_PROP_INPUT_SUSPEND:
 		val->intval = chip->disabled;
@@ -635,10 +666,14 @@
 		break;
 	case POWER_SUPPLY_PROP_CONNECTOR_HEALTH:
 		if (chip->c_health == -EINVAL)
-			val->intval = smb1355_get_prop_connector_health(chip);
+			val->intval = smb1355_get_prop_health(chip,
+						CONNECTOR_TEMP);
 		else
 			val->intval = chip->c_health;
 		break;
+	case POWER_SUPPLY_PROP_DIE_HEALTH:
+		val->intval = smb1355_get_prop_health(chip, DIE_TEMP);
+		break;
 	case POWER_SUPPLY_PROP_PARALLEL_BATFET_MODE:
 		val->intval = chip->dt.pl_batfet_mode;
 		break;
@@ -708,13 +743,16 @@
 	}
 
 	chip->die_temp_deciDegC = -EINVAL;
-	if (disable) {
-		chip->exit_die_temp = true;
-		cancel_delayed_work_sync(&chip->die_temp_work);
-	} else {
-		/* start the work to measure temperature */
-		chip->exit_die_temp = false;
-		schedule_delayed_work(&chip->die_temp_work, 0);
+	/* Only enable temperature measurement for s/w based mitigation */
+	if (!chip->dt.hw_die_temp_mitigation) {
+		if (disable) {
+			chip->exit_die_temp = true;
+			cancel_delayed_work_sync(&chip->die_temp_work);
+		} else {
+			/* start the work to measure temperature */
+			chip->exit_die_temp = false;
+			schedule_delayed_work(&chip->die_temp_work, 0);
+		}
 	}
 
 	if (chip->irq_disable_votable)
@@ -978,6 +1016,7 @@
 static int smb1355_init_hw(struct smb1355 *chip)
 {
 	int rc;
+	u8 val, range;
 
 	/* request clock always on */
 	rc = smb1355_clk_request(chip, true);
@@ -1045,13 +1084,35 @@
 		return rc;
 	}
 
+	/* Configure DIE temp Low threshold */
+	if (chip->dt.hw_die_temp_mitigation) {
+		range = (chip->dt.die_temp_threshold - DIE_LOW_RANGE_BASE_DEGC)
+						/ (DIE_LOW_RANGE_DELTA);
+		val = (chip->dt.die_temp_threshold
+				- ((range * DIE_LOW_RANGE_DELTA)
+						+ DIE_LOW_RANGE_BASE_DEGC))
+				% DIE_LOW_RANGE_DELTA;
+
+		rc = smb1355_masked_write(chip, SMB2CHG_BATIF_ENG_SMISC_DIETEMP,
+				TDIE_COMPARATOR_THRESHOLD,
+				(range << DIE_LOW_RANGE_SHIFT) | val);
+		if (rc < 0) {
+			pr_err("Couldn't set temp comp threshold rc=%d\n", rc);
+			return rc;
+		}
+	}
+
 	/*
-	 * Enable thermal Die temperature comparator source and disable hw
-	 * mitigation for skin/die
+	 * Enable thermal Die temperature comparator source and
+	 * enable hardware controlled current adjustment for die temp
+	 * if charger is configured in h/w controlled die temp mitigation.
 	 */
+	val = THERMREG_DIE_CMP_SRC_EN_BIT;
+	if (!chip->dt.hw_die_temp_mitigation)
+		val |= BYP_THERM_CHG_CURR_ADJUST_BIT;
 	rc = smb1355_masked_write(chip, MISC_THERMREG_SRC_CFG_REG,
 		THERMREG_DIE_CMP_SRC_EN_BIT | BYP_THERM_CHG_CURR_ADJUST_BIT,
-		THERMREG_DIE_CMP_SRC_EN_BIT | BYP_THERM_CHG_CURR_ADJUST_BIT);
+		val);
 	if (rc < 0) {
 		pr_err("Couldn't set Skin temperature comparator src rc=%d\n",
 			rc);
@@ -1062,8 +1123,9 @@
 	 * Disable hysterisis for die temperature. This is so that sw can run
 	 * stepping scheme quickly
 	 */
+	val = chip->dt.hw_die_temp_mitigation ? DIE_TEMP_COMP_HYST_BIT : 0;
 	rc = smb1355_masked_write(chip, BATIF_ENG_SCMISC_SPARE1_REG,
-				DIE_TEMP_COMP_HYST_BIT, 0);
+				DIE_TEMP_COMP_HYST_BIT, val);
 	if (rc < 0) {
 		pr_err("Couldn't disable hyst. for die rc=%d\n", rc);
 		return rc;
diff --git a/drivers/power/supply/qcom/smb1360-charger-fg.c b/drivers/power/supply/qcom/smb1360-charger-fg.c
index ed9c610..4e98ec7 100644
--- a/drivers/power/supply/qcom/smb1360-charger-fg.c
+++ b/drivers/power/supply/qcom/smb1360-charger-fg.c
@@ -3424,8 +3424,8 @@
 	chip->otg_vreg.rdesc.owner = THIS_MODULE;
 	chip->otg_vreg.rdesc.type = REGULATOR_VOLTAGE;
 	chip->otg_vreg.rdesc.ops = &smb1360_otg_reg_ops;
-	chip->otg_vreg.rdesc.of_match = chip->dev->of_node->name;
-	chip->otg_vreg.rdesc.name = chip->dev->of_node->name;
+	chip->otg_vreg.rdesc.of_match = "qcom,smb1360-vbus";
+	chip->otg_vreg.rdesc.name = "qcom,smb1360-vbus";
 
 	cfg.dev = chip->dev;
 	cfg.driver_data = chip;
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index 86ecda5..e03e0a8 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -117,6 +117,11 @@
 	try_sink_enabled, __try_sink_enabled, int, 0600
 );
 
+static int __audio_headset_drp_wait_ms = 100;
+	module_param_named(
+	audio_headset_drp_wait_ms, __audio_headset_drp_wait_ms, int, 0600
+);
+
 static irqreturn_t smb138x_handle_slave_chg_state_change(int irq, void *data)
 {
 	struct smb_irq_data *irq_data = data;
@@ -1786,6 +1791,7 @@
 	chip->chg.try_sink_enabled = &__try_sink_enabled;
 	chip->chg.irq_info = smb138x_irqs;
 	chip->chg.name = "SMB";
+	chip->chg.audio_headset_drp_wait_ms = &__audio_headset_drp_wait_ms;
 
 	chip->chg.regmap = dev_get_regmap(chip->chg.dev->parent, NULL);
 	if (!chip->chg.regmap) {
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index d79e12b..6ef4b01 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -19,11 +19,14 @@
 #include <linux/irq.h>
 #include <linux/pmic-voter.h>
 #include <linux/of_batterydata.h>
+#include <linux/alarmtimer.h>
 #include "smb5-lib.h"
 #include "smb5-reg.h"
 #include "battery.h"
+#include "schgm-flash.h"
 #include "step-chg-jeita.h"
 #include "storm-watch.h"
+#include "schgm-flash.h"
 
 #define smblib_err(chg, fmt, ...)		\
 	pr_err("%s: %s: " fmt, chg->name,	\
@@ -320,6 +323,25 @@
 	return result;
 }
 
+#define AICL_RANGE2_MIN_MV		5600
+#define AICL_RANGE2_STEP_DELTA_MV	200
+#define AICL_RANGE2_OFFSET		16
+int smblib_get_aicl_cont_threshold(struct smb_chg_param *param, u8 val_raw)
+{
+	int base = param->min_u;
+	u8 reg = val_raw;
+	int step = param->step_u;
+
+
+	if (val_raw >= AICL_RANGE2_OFFSET) {
+		reg = val_raw - AICL_RANGE2_OFFSET;
+		base = AICL_RANGE2_MIN_MV;
+		step = AICL_RANGE2_STEP_DELTA_MV;
+	}
+
+	return base + (reg * step);
+}
+
 /********************
  * REGISTER SETTERS *
  ********************/
@@ -539,6 +561,29 @@
 	return rc;
 }
 
+int smblib_set_aicl_cont_threshold(struct smb_chg_param *param,
+				int val_u, u8 *val_raw)
+{
+	int base = param->min_u;
+	int offset = 0;
+	int step = param->step_u;
+
+	if (val_u > param->max_u)
+		val_u = param->max_u;
+	if (val_u < param->min_u)
+		val_u = param->min_u;
+
+	if (val_u >= AICL_RANGE2_MIN_MV) {
+		base = AICL_RANGE2_MIN_MV;
+		step = AICL_RANGE2_STEP_DELTA_MV;
+		offset = AICL_RANGE2_OFFSET;
+	};
+
+	*val_raw = ((val_u - base) / step) + offset;
+
+	return 0;
+}
+
 /********************
  * HELPER FUNCTIONS *
  ********************/
@@ -705,7 +750,6 @@
 	return 0;
 }
 
-#define SDP_100_MA			100000
 static void smblib_uusb_removal(struct smb_charger *chg)
 {
 	int rc;
@@ -730,7 +774,8 @@
 	/* reset both usbin current and voltage votes */
 	vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
 	vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
-	vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA);
+	vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true,
+			is_flash_active(chg) ? SDP_CURRENT_UA : SDP_100_MA);
 	vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0);
 
 	/* reconfigure allowed voltage for HVDCP */
@@ -960,7 +1005,7 @@
 
 	/* Re-run AICL */
 	if (chg->real_charger_type != POWER_SUPPLY_TYPE_USB)
-		rc = smblib_rerun_aicl(chg);
+		rc = smblib_run_aicl(chg, RERUN_AICL);
 out:
 	return rc;
 }
@@ -1001,6 +1046,100 @@
 	return 0;
 }
 
+/********************
+ * Moisture Protection *
+ ********************/
+#define MICRO_USB_DETECTION_ON_TIME_20_MS 0x08
+#define MICRO_USB_DETECTION_PERIOD_X_100 0x03
+#define U_USB_STATUS_WATER_PRESENT 0x00
+static int smblib_set_moisture_protection(struct smb_charger *chg,
+				bool enable)
+{
+	int rc = 0;
+
+	if (chg->moisture_present == enable) {
+		smblib_dbg(chg, PR_MISC, "No change in moisture protection status\n");
+		return rc;
+	}
+
+	if (enable) {
+		chg->moisture_present = true;
+
+		/* Disable uUSB factory mode detection */
+		rc = smblib_masked_write(chg, TYPEC_U_USB_CFG_REG,
+					EN_MICRO_USB_FACTORY_MODE_BIT, 0);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't disable uUSB factory mode detection rc=%d\n",
+				rc);
+			return rc;
+		}
+
+		/* Disable moisture detection and uUSB state change interrupt */
+		rc = smblib_masked_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
+					TYPEC_WATER_DETECTION_INT_EN_BIT |
+					MICRO_USB_STATE_CHANGE_INT_EN_BIT, 0);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't disable moisture detection interrupt rc=%d\n",
+			rc);
+			return rc;
+		}
+
+		/* Set 1% duty cycle on ID detection */
+		rc = smblib_masked_write(chg,
+					TYPEC_U_USB_WATER_PROTECTION_CFG_REG,
+					EN_MICRO_USB_WATER_PROTECTION_BIT |
+					MICRO_USB_DETECTION_ON_TIME_CFG_MASK |
+					MICRO_USB_DETECTION_PERIOD_CFG_MASK,
+					EN_MICRO_USB_WATER_PROTECTION_BIT |
+					MICRO_USB_DETECTION_ON_TIME_20_MS |
+					MICRO_USB_DETECTION_PERIOD_X_100);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't set 1 percent CC_ID duty cycle rc=%d\n",
+				rc);
+			return rc;
+		}
+
+		vote(chg->usb_icl_votable, MOISTURE_VOTER, true, 0);
+	} else {
+		chg->moisture_present = false;
+		vote(chg->usb_icl_votable, MOISTURE_VOTER, false, 0);
+
+		/* Enable moisture detection and uUSB state change interrupt */
+		rc = smblib_masked_write(chg, TYPE_C_INTERRUPT_EN_CFG_2_REG,
+					TYPEC_WATER_DETECTION_INT_EN_BIT |
+					MICRO_USB_STATE_CHANGE_INT_EN_BIT,
+					TYPEC_WATER_DETECTION_INT_EN_BIT |
+					MICRO_USB_STATE_CHANGE_INT_EN_BIT);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't enable moisture detection and uUSB state change interrupt rc=%d\n",
+				rc);
+			return rc;
+		}
+
+		/* Disable periodic monitoring of CC_ID pin */
+		rc = smblib_write(chg, TYPEC_U_USB_WATER_PROTECTION_CFG_REG, 0);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't disable 1 percent CC_ID duty cycle rc=%d\n",
+				rc);
+			return rc;
+		}
+
+		/* Enable uUSB factory mode detection */
+		rc = smblib_masked_write(chg, TYPEC_U_USB_CFG_REG,
+					EN_MICRO_USB_FACTORY_MODE_BIT,
+					EN_MICRO_USB_FACTORY_MODE_BIT);
+		if (rc < 0) {
+			smblib_err(chg, "Couldn't disable uUSB factory mode detection rc=%d\n",
+				rc);
+			return rc;
+		}
+	}
+
+	smblib_dbg(chg, PR_MISC, "Moisture protection %s\n",
+			chg->moisture_present ? "enabled" : "disabled");
+	return rc;
+}
+
 /*********************
  * VOTABLE CALLBACKS *
  *********************/
@@ -1469,6 +1608,45 @@
 	return rc;
 }
 
+int smblib_get_prop_batt_iterm(struct smb_charger *chg,
+		union power_supply_propval *val)
+{
+	int rc, temp;
+	u8 stat, buf[2];
+
+	/*
+	 * Currently, only ADC comparator-based termination is supported,
+	 * hence read only the threshold corresponding to ADC source.
+	 * Proceed only if CHGR_ITERM_USE_ANALOG_BIT is 0.
+	 */
+	rc = smblib_read(chg, CHGR_ENG_CHARGING_CFG_REG, &stat);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read CHGR_ENG_CHARGING_CFG_REG rc=%d\n",
+				rc);
+		return rc;
+	}
+
+	if (stat & CHGR_ITERM_USE_ANALOG_BIT) {
+		val->intval = -EINVAL;
+		return 0;
+	}
+
+	rc = smblib_batch_read(chg, CHGR_ADC_ITERM_UP_THD_MSB_REG, buf, 2);
+
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read CHGR_ADC_ITERM_UP_THD_MSB_REG rc=%d\n",
+				rc);
+		return rc;
+	}
+
+	temp = buf[1] | (buf[0] << 8);
+	temp = sign_extend32(temp, 15);
+	temp = DIV_ROUND_CLOSEST(temp * 10000, ADC_CHG_TERM_MASK);
+	val->intval = temp;
+
+	return rc;
+}
+
 int smblib_get_prop_batt_temp(struct smb_charger *chg,
 			      union power_supply_propval *val)
 {
@@ -1615,7 +1793,7 @@
 	return 0;
 }
 
-int smblib_rerun_aicl(struct smb_charger *chg)
+int smblib_run_aicl(struct smb_charger *chg, int type)
 {
 	int rc;
 	u8 stat;
@@ -1633,8 +1811,8 @@
 
 	smblib_dbg(chg, PR_MISC, "re-running AICL\n");
 
-	rc = smblib_masked_write(chg, AICL_CMD_REG, RERUN_AICL_BIT,
-				RERUN_AICL_BIT);
+	stat = (type == RERUN_AICL) ? RERUN_AICL_BIT : RESTART_AICL_BIT;
+	rc = smblib_masked_write(chg, AICL_CMD_REG, stat, stat);
 	if (rc < 0)
 		smblib_err(chg, "Couldn't write to AICL_CMD_REG rc=%d\n",
 				rc);
@@ -1894,6 +2072,28 @@
 	switch (chg->real_charger_type) {
 	case POWER_SUPPLY_TYPE_USB_HVDCP:
 	case POWER_SUPPLY_TYPE_USB_HVDCP_3:
+		if (chg->smb_version == PMI632_SUBTYPE)
+			val->intval = MICRO_9V;
+		else
+			val->intval = MICRO_12V;
+		break;
+	case POWER_SUPPLY_TYPE_USB_PD:
+		val->intval = chg->voltage_max_uv;
+		break;
+	default:
+		val->intval = MICRO_5V;
+		break;
+	}
+
+	return 0;
+}
+
+int smblib_get_prop_usb_voltage_max_design(struct smb_charger *chg,
+					union power_supply_propval *val)
+{
+	switch (chg->real_charger_type) {
+	case POWER_SUPPLY_TYPE_USB_HVDCP:
+	case POWER_SUPPLY_TYPE_USB_HVDCP_3:
 	case POWER_SUPPLY_TYPE_USB_PD:
 		if (chg->smb_version == PMI632_SUBTYPE)
 			val->intval = MICRO_9V;
@@ -1961,6 +2161,8 @@
 		return POWER_SUPPLY_TYPEC_SOURCE_MEDIUM;
 	case SNK_RP_3P0_BIT:
 		return POWER_SUPPLY_TYPEC_SOURCE_HIGH;
+	case SNK_RP_SHORT_BIT:
+		return POWER_SUPPLY_TYPEC_NON_COMPLIANT;
 	default:
 		break;
 	}
@@ -2109,7 +2311,7 @@
 	int rc;
 	u8 stat;
 
-	rc = smblib_read(chg, TEMP_RANGE_STATUS_REG, &stat);
+	rc = smblib_read(chg, MISC_TEMP_RANGE_STATUS_REG, &stat);
 	if (rc < 0) {
 		smblib_err(chg, "Couldn't read TEMP_RANGE_STATUS_REG rc=%d\n",
 									rc);
@@ -2137,13 +2339,6 @@
 	return 0;
 }
 
-#define SDP_CURRENT_UA			500000
-#define CDP_CURRENT_UA			1500000
-#define DCP_CURRENT_UA			1500000
-#define HVDCP_CURRENT_UA		3000000
-#define TYPEC_DEFAULT_CURRENT_UA	900000
-#define TYPEC_MEDIUM_CURRENT_UA		1500000
-#define TYPEC_HIGH_CURRENT_UA		3000000
 static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode)
 {
 	int rp_ua;
@@ -2183,6 +2378,7 @@
 					int usb_current)
 {
 	int rc = 0, rp_ua, typec_mode;
+	union power_supply_propval val = {0, };
 
 	if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_FLOAT) {
 		if (usb_current == -ETIMEDOUT) {
@@ -2237,8 +2433,16 @@
 				return rc;
 		}
 	} else {
-		rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
-					true, usb_current);
+		rc = smblib_get_prop_usb_present(chg, &val);
+		if (!rc && !val.intval)
+			return 0;
+
+		/* if flash is active force 500mA */
+		if ((usb_current < SDP_CURRENT_UA) && is_flash_active(chg))
+			usb_current = SDP_CURRENT_UA;
+
+		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;
@@ -2666,13 +2870,79 @@
 	return IRQ_HANDLED;
 }
 
+#define AICL_STEP_MV		200
+#define MAX_AICL_THRESHOLD_MV	4800
 irqreturn_t usbin_uv_irq_handler(int irq, void *data)
 {
 	struct smb_irq_data *irq_data = data;
 	struct smb_charger *chg = irq_data->parent_data;
 	struct storm_watch *wdata;
+	int rc;
 
 	smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
+
+	if ((chg->wa_flags & WEAK_ADAPTER_WA)
+			&& is_storming(&irq_data->storm_data)) {
+
+		if (chg->aicl_max_reached) {
+			smblib_dbg(chg, PR_MISC,
+					"USBIN_UV storm at max AICL threshold\n");
+			return IRQ_HANDLED;
+		}
+
+		smblib_dbg(chg, PR_MISC, "USBIN_UV storm at threshold %d\n",
+				chg->aicl_5v_threshold_mv);
+
+		/* suspend USBIN before updating AICL threshold */
+		vote(chg->usb_icl_votable, AICL_THRESHOLD_VOTER, true, 0);
+
+		/* delay for VASHDN deglitch */
+		msleep(20);
+
+		if (chg->aicl_5v_threshold_mv > MAX_AICL_THRESHOLD_MV) {
+			/* reached max AICL threshold */
+			chg->aicl_max_reached = true;
+			goto unsuspend_input;
+		}
+
+		/* Increase AICL threshold by 200mV */
+		rc = smblib_set_charge_param(chg, &chg->param.aicl_5v_threshold,
+				chg->aicl_5v_threshold_mv + AICL_STEP_MV);
+		if (rc < 0)
+			dev_err(chg->dev,
+				"Error in setting AICL threshold rc=%d\n", rc);
+		else
+			chg->aicl_5v_threshold_mv += AICL_STEP_MV;
+
+		rc = smblib_set_charge_param(chg,
+				&chg->param.aicl_cont_threshold,
+				chg->aicl_cont_threshold_mv + AICL_STEP_MV);
+		if (rc < 0)
+			dev_err(chg->dev,
+				"Error in setting AICL threshold rc=%d\n", rc);
+		else
+			chg->aicl_cont_threshold_mv += AICL_STEP_MV;
+
+unsuspend_input:
+		if (chg->smb_version == PMI632_SUBTYPE)
+			schgm_flash_torch_priority(chg, TORCH_BOOST_MODE);
+
+		if (chg->aicl_max_reached) {
+			smblib_dbg(chg, PR_MISC,
+				"Reached max AICL threshold resctricting ICL to 100mA\n");
+			vote(chg->usb_icl_votable, AICL_THRESHOLD_VOTER,
+					true, USBIN_100MA);
+			smblib_run_aicl(chg, RESTART_AICL);
+		} else {
+			smblib_run_aicl(chg, RESTART_AICL);
+			vote(chg->usb_icl_votable, AICL_THRESHOLD_VOTER,
+					false, 0);
+		}
+
+		wdata = &chg->irq_info[USBIN_UV_IRQ].irq_data->storm_data;
+		reset_storm_count(wdata);
+	}
+
 	if (!chg->irq_info[SWITCHER_POWER_OK_IRQ].irq_data)
 		return IRQ_HANDLED;
 
@@ -2691,6 +2961,24 @@
 	struct smb_charger *chg = irq_data->parent_data;
 
 	if (chg->mode == PARALLEL_MASTER) {
+		/*
+		 * Ignore if change in ICL is due to DIE temp mitigation.
+		 * This is to prevent any further ICL split.
+		 */
+		if (chg->hw_die_temp_mitigation) {
+			rc = smblib_read(chg, MISC_DIE_TEMP_STATUS_REG, &stat);
+			if (rc < 0) {
+				smblib_err(chg,
+					"Couldn't read DIE_TEMP rc=%d\n", rc);
+				return IRQ_HANDLED;
+			}
+			if (stat & (DIE_TEMP_UB_BIT | DIE_TEMP_LB_BIT)) {
+				smblib_dbg(chg, PR_PARALLEL,
+					"skip ICL change DIE_TEMP %x\n", stat);
+				return IRQ_HANDLED;
+			}
+		}
+
 		rc = smblib_read(chg, AICL_STATUS_REG, &stat);
 		if (rc < 0) {
 			smblib_err(chg, "Couldn't read AICL_STATUS rc=%d\n",
@@ -2804,6 +3092,33 @@
 			}
 		}
 
+		if (chg->wa_flags & WEAK_ADAPTER_WA) {
+			chg->aicl_5v_threshold_mv =
+					chg->default_aicl_5v_threshold_mv;
+			chg->aicl_cont_threshold_mv =
+					chg->default_aicl_cont_threshold_mv;
+
+			smblib_set_charge_param(chg,
+					&chg->param.aicl_5v_threshold,
+					chg->aicl_5v_threshold_mv);
+			smblib_set_charge_param(chg,
+					&chg->param.aicl_cont_threshold,
+					chg->aicl_cont_threshold_mv);
+			chg->aicl_max_reached = false;
+
+			if (chg->smb_version == PMI632_SUBTYPE)
+				schgm_flash_torch_priority(chg,
+						TORCH_BUCK_MODE);
+
+			data = chg->irq_info[USBIN_UV_IRQ].irq_data;
+			if (data) {
+				wdata = &data->storm_data;
+				reset_storm_count(wdata);
+			}
+			vote(chg->usb_icl_votable, AICL_THRESHOLD_VOTER,
+					false, 0);
+		}
+
 		rc = smblib_request_dpdm(chg, false);
 		if (rc < 0)
 			smblib_err(chg, "Couldn't disable DPDM rc=%d\n", rc);
@@ -2988,9 +3303,12 @@
 		 * enumeration is done.
 		 */
 		if (!is_client_vote_enabled(chg->usb_icl_votable,
-								USB_PSY_VOTER))
+						USB_PSY_VOTER)) {
+			/* if flash is active force 500mA */
 			vote(chg->usb_icl_votable, USB_PSY_VOTER, true,
-					SDP_100_MA);
+					is_flash_active(chg) ?
+					SDP_CURRENT_UA : SDP_100_MA);
+		}
 		vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, false, 0);
 		break;
 	case POWER_SUPPLY_TYPE_USB_CDP:
@@ -3195,7 +3513,8 @@
 	cancel_delayed_work_sync(&chg->pl_enable_work);
 
 	/* reset input current limit voters */
-	vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true, SDP_100_MA);
+	vote(chg->usb_icl_votable, SW_ICL_MAX_VOTER, true,
+			is_flash_active(chg) ? SDP_CURRENT_UA : SDP_100_MA);
 	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);
@@ -3271,11 +3590,28 @@
 	struct smb_charger *chg = irq_data->parent_data;
 
 	if (chg->connector_type == POWER_SUPPLY_CONNECTOR_MICRO_USB) {
+		if (chg->moisture_protection_enabled &&
+				(chg->wa_flags & MOISTURE_PROTECTION_WA)) {
+			/*
+			 * Adding pm_stay_awake as because pm_relax is called
+			 * on exit path from the work routine.
+			 */
+			pm_stay_awake(chg->dev);
+			schedule_work(&chg->moisture_protection_work);
+		}
+
 		cancel_delayed_work_sync(&chg->uusb_otg_work);
-		vote(chg->awake_votable, OTG_DELAY_VOTER, true, 0);
-		smblib_dbg(chg, PR_INTERRUPT, "Scheduling OTG work\n");
-		schedule_delayed_work(&chg->uusb_otg_work,
-				msecs_to_jiffies(chg->otg_delay_ms));
+		/*
+		 * Skip OTG enablement if RID interrupt triggers with moisture
+		 * protection still enabled.
+		 */
+		if (!chg->moisture_present) {
+			vote(chg->awake_votable, OTG_DELAY_VOTER, true, 0);
+			smblib_dbg(chg, PR_INTERRUPT, "Scheduling OTG work\n");
+			schedule_delayed_work(&chg->uusb_otg_work,
+					msecs_to_jiffies(chg->otg_delay_ms));
+		}
+
 		return IRQ_HANDLED;
 	}
 
@@ -3643,6 +3979,96 @@
 	vote(chg->awake_votable, PL_DELAY_VOTER, false, 0);
 }
 
+#define MOISTURE_PROTECTION_CHECK_DELAY_MS 300000		/* 5 mins */
+static void smblib_moisture_protection_work(struct work_struct *work)
+{
+	struct smb_charger *chg = container_of(work, struct smb_charger,
+						moisture_protection_work);
+	int rc;
+	bool usb_plugged_in;
+	u8 stat;
+
+	/*
+	 * Disable 1% duty cycle on CC_ID pin and enable uUSB factory mode
+	 * detection to track any change on RID, as interrupts are disable.
+	 */
+	rc = smblib_write(chg, TYPEC_U_USB_WATER_PROTECTION_CFG_REG, 0);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't disable periodic monitoring of CC_ID rc=%d\n",
+			rc);
+		goto out;
+	}
+
+	rc = smblib_masked_write(chg, TYPEC_U_USB_CFG_REG,
+					EN_MICRO_USB_FACTORY_MODE_BIT,
+					EN_MICRO_USB_FACTORY_MODE_BIT);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't enable uUSB factory mode detection rc=%d\n",
+			rc);
+		goto out;
+	}
+
+	/*
+	 * Add a delay of 100ms to allow change in rid to reflect on
+	 * status registers.
+	 */
+	msleep(100);
+
+	rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
+		goto out;
+	}
+	usb_plugged_in = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
+
+	/* Check uUSB status for moisture presence */
+	rc = smblib_read(chg, TYPEC_U_USB_STATUS_REG, &stat);
+	if (rc < 0) {
+		smblib_err(chg, "Couldn't read TYPE_C_U_USB_STATUS_REG rc=%d\n",
+				rc);
+		goto out;
+	}
+
+	/*
+	 * Factory mode detection happens in case of USB plugged-in by using
+	 * a different current source of 2uA which can hamper moisture
+	 * detection. Since factory mode is not supported in kernel, factory
+	 * mode detection can be considered as equivalent to presence of
+	 * moisture.
+	 */
+	if (stat == U_USB_STATUS_WATER_PRESENT || stat == U_USB_FMB1_BIT ||
+			stat == U_USB_FMB2_BIT || (usb_plugged_in &&
+			stat == U_USB_FLOAT1_BIT)) {
+		smblib_set_moisture_protection(chg, true);
+		alarm_start_relative(&chg->moisture_protection_alarm,
+			ms_to_ktime(MOISTURE_PROTECTION_CHECK_DELAY_MS));
+	} else {
+		smblib_set_moisture_protection(chg, false);
+		rc = alarm_cancel(&chg->moisture_protection_alarm);
+		if (rc < 0)
+			smblib_err(chg, "Couldn't cancel moisture protection alarm\n");
+	}
+
+out:
+	pm_relax(chg->dev);
+}
+
+static enum alarmtimer_restart moisture_protection_alarm_cb(struct alarm *alarm,
+							ktime_t now)
+{
+	struct smb_charger *chg = container_of(alarm, struct smb_charger,
+					moisture_protection_alarm);
+
+	smblib_dbg(chg, PR_MISC, "moisture Protection Alarm Triggered %lld\n",
+			ktime_to_ms(now));
+
+	/* Atomic context, cannot use voter */
+	pm_stay_awake(chg->dev);
+	schedule_work(&chg->moisture_protection_work);
+
+	return ALARMTIMER_NORESTART;
+}
+
 #define JEITA_SOFT			0
 #define JEITA_HARD			1
 static int smblib_update_jeita(struct smb_charger *chg, u32 *thresholds,
@@ -3845,6 +4271,21 @@
 	INIT_DELAYED_WORK(&chg->pl_enable_work, smblib_pl_enable_work);
 	INIT_DELAYED_WORK(&chg->uusb_otg_work, smblib_uusb_otg_work);
 	INIT_DELAYED_WORK(&chg->bb_removal_work, smblib_bb_removal_work);
+
+	if (chg->moisture_protection_enabled &&
+				(chg->wa_flags & MOISTURE_PROTECTION_WA)) {
+		INIT_WORK(&chg->moisture_protection_work,
+					smblib_moisture_protection_work);
+
+		if (alarmtimer_get_rtcdev()) {
+			alarm_init(&chg->moisture_protection_alarm,
+				ALARM_BOOTTIME, moisture_protection_alarm_cb);
+		} else {
+			smblib_err(chg, "Failed to initialize moisture protection alarm\n");
+			return -ENODEV;
+		}
+	}
+
 	chg->fake_capacity = -EINVAL;
 	chg->fake_input_current_limited = -EINVAL;
 	chg->fake_batt_status = -EINVAL;
@@ -3906,6 +4347,11 @@
 {
 	switch (chg->mode) {
 	case PARALLEL_MASTER:
+		if (chg->moisture_protection_enabled &&
+				(chg->wa_flags & MOISTURE_PROTECTION_WA)) {
+			alarm_cancel(&chg->moisture_protection_alarm);
+			cancel_work_sync(&chg->moisture_protection_work);
+		}
 		cancel_work_sync(&chg->bms_update_work);
 		cancel_work_sync(&chg->jeita_update_work);
 		cancel_work_sync(&chg->pl_update_work);
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index 7c02468..c5458d7 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -18,6 +18,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/consumer.h>
 #include <linux/extcon.h>
+#include <linux/alarmtimer.h>
 #include "storm-watch.h"
 
 enum print_reason {
@@ -67,12 +68,24 @@
 #define WBC_VOTER			"WBC_VOTER"
 #define HW_LIMIT_VOTER			"HW_LIMIT_VOTER"
 #define FORCE_RECHARGE_VOTER		"FORCE_RECHARGE_VOTER"
+#define AICL_THRESHOLD_VOTER		"AICL_THRESHOLD_VOTER"
+#define MOISTURE_VOTER			"MOISTURE_VOTER"
 
 #define BOOST_BACK_STORM_COUNT	3
 #define WEAK_CHG_STORM_COUNT	8
 
 #define VBAT_TO_VRAW_ADC(v)		div_u64((u64)v * 1000000UL, 194637UL)
 
+#define SDP_100_MA			100000
+#define SDP_CURRENT_UA			500000
+#define CDP_CURRENT_UA			1500000
+#define DCP_CURRENT_UA			1500000
+#define HVDCP_CURRENT_UA		3000000
+#define TYPEC_DEFAULT_CURRENT_UA	900000
+#define TYPEC_MEDIUM_CURRENT_UA		1500000
+#define TYPEC_HIGH_CURRENT_UA		3000000
+#define ADC_CHG_TERM_MASK	32767
+
 enum smb_mode {
 	PARALLEL_MASTER = 0,
 	PARALLEL_SLAVE,
@@ -87,6 +100,13 @@
 
 enum {
 	BOOST_BACK_WA			= BIT(0),
+	WEAK_ADAPTER_WA			= BIT(1),
+	MOISTURE_PROTECTION_WA		= BIT(2),
+};
+
+enum {
+	RERUN_AICL			= BIT(0),
+	RESTART_AICL			= BIT(1),
 };
 
 enum smb_irq_index {
@@ -172,6 +192,12 @@
 	SUSPEND_INPUT		= 4,
 };
 
+enum chg_term_config_src {
+	ITERM_SRC_UNSPECIFIED,
+	ITERM_SRC_ADC,
+	ITERM_SRC_ANALOG
+};
+
 struct smb_irq_info {
 	const char			*name;
 	const irq_handler_t		handler;
@@ -239,6 +265,8 @@
 	struct smb_chg_param	jeita_cc_comp_hot;
 	struct smb_chg_param	jeita_cc_comp_cold;
 	struct smb_chg_param	freq_switcher;
+	struct smb_chg_param	aicl_5v_threshold;
+	struct smb_chg_param	aicl_cont_threshold;
 };
 
 struct parallel_params {
@@ -277,6 +305,7 @@
 	/* locks */
 	struct mutex		lock;
 	struct mutex		ps_change_lock;
+	struct mutex		vadc_lock;
 
 	/* power supplies */
 	struct power_supply		*batt_psy;
@@ -313,6 +342,7 @@
 	struct work_struct	bms_update_work;
 	struct work_struct	pl_update_work;
 	struct work_struct	jeita_update_work;
+	struct work_struct	moisture_protection_work;
 	struct delayed_work	ps_change_timeout_work;
 	struct delayed_work	clear_hdc_work;
 	struct delayed_work	icl_change_work;
@@ -320,6 +350,9 @@
 	struct delayed_work	uusb_otg_work;
 	struct delayed_work	bb_removal_work;
 
+	/* alarm */
+	struct alarm		moisture_protection_alarm;
+
 	/* pd */
 	int			voltage_min_uv;
 	int			voltage_max_uv;
@@ -360,6 +393,16 @@
 	int			auto_recharge_soc;
 	bool			jeita_configured;
 	enum sink_src_mode	sink_src_mode;
+	bool			hw_die_temp_mitigation;
+	bool			hw_connector_mitigation;
+	int			connector_pull_up;
+	int			aicl_5v_threshold_mv;
+	int			default_aicl_5v_threshold_mv;
+	int			aicl_cont_threshold_mv;
+	int			default_aicl_cont_threshold_mv;
+	bool			aicl_max_reached;
+	bool			moisture_present;
+	bool			moisture_protection_enabled;
 
 	/* workaround flag */
 	u32			wa_flags;
@@ -394,7 +437,7 @@
 int smblib_get_charge_param(struct smb_charger *chg,
 			    struct smb_chg_param *param, int *val_u);
 int smblib_get_usb_suspend(struct smb_charger *chg, int *suspend);
-
+int smblib_get_aicl_cont_threshold(struct smb_chg_param *param, u8 val_raw);
 int smblib_enable_charging(struct smb_charger *chg, bool enable);
 int smblib_set_charge_param(struct smb_charger *chg,
 			    struct smb_chg_param *param, int val_u);
@@ -411,6 +454,8 @@
 				int val_u, u8 *val_raw);
 int smblib_set_prop_boost_current(struct smb_charger *chg,
 				const union power_supply_propval *val);
+int smblib_set_aicl_cont_threshold(struct smb_chg_param *param,
+				int val_u, u8 *val_raw);
 int smblib_vbus_regulator_enable(struct regulator_dev *rdev);
 int smblib_vbus_regulator_disable(struct regulator_dev *rdev);
 int smblib_vbus_regulator_is_enabled(struct regulator_dev *rdev);
@@ -459,6 +504,8 @@
 				union power_supply_propval *val);
 int smblib_get_prop_batt_current_now(struct smb_charger *chg,
 				union power_supply_propval *val);
+int smblib_get_prop_batt_iterm(struct smb_charger *chg,
+				union power_supply_propval *val);
 int smblib_get_prop_batt_temp(struct smb_charger *chg,
 				union power_supply_propval *val);
 int smblib_get_prop_batt_charge_counter(struct smb_charger *chg,
@@ -492,6 +539,8 @@
 				union power_supply_propval *val);
 int smblib_get_prop_usb_voltage_max(struct smb_charger *chg,
 				union power_supply_propval *val);
+int smblib_get_prop_usb_voltage_max_design(struct smb_charger *chg,
+				union power_supply_propval *val);
 int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
 				union power_supply_propval *val);
 int smblib_get_prop_typec_power_role(struct smb_charger *chg,
@@ -528,7 +577,7 @@
 				union power_supply_propval *val);
 int smblib_dp_dm(struct smb_charger *chg, int val);
 int smblib_disable_hw_jeita(struct smb_charger *chg, bool disable);
-int smblib_rerun_aicl(struct smb_charger *chg);
+int smblib_run_aicl(struct smb_charger *chg, int type);
 int smblib_set_icl_current(struct smb_charger *chg, int icl_ua);
 int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua);
 int smblib_get_charge_current(struct smb_charger *chg, int *total_current_ua);
diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h
index d1548c3..57eb22a 100644
--- a/drivers/power/supply/qcom/smb5-reg.h
+++ b/drivers/power/supply/qcom/smb5-reg.h
@@ -73,6 +73,11 @@
 
 #define CHGR_FAST_CHARGE_CURRENT_CFG_REG	(CHGR_BASE + 0x61)
 
+#define CHGR_ADC_ITERM_UP_THD_MSB_REG		(CHGR_BASE + 0x67)
+#define CHGR_ADC_ITERM_UP_THD_LSB_REG		(CHGR_BASE + 0x68)
+#define CHGR_ADC_ITERM_LO_THD_MSB_REG		(CHGR_BASE + 0x69)
+#define CHGR_ADC_ITERM_LO_THD_LSB_REG		(CHGR_BASE + 0x6A)
+
 #define CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG	(CHGR_BASE + 0x6B)
 #define NO_OF_SAMPLE_FOR_RCHG_SHIFT		2
 #define NO_OF_SAMPLE_FOR_RCHG			GENMASK(3, 2)
@@ -102,11 +107,15 @@
 #define JEITA_CCCOMP_CFG_COLD_REG		(CHGR_BASE + 0x93)
 
 #define CHGR_JEITA_THRESHOLD_BASE_REG(i)	(CHGR_BASE + 0x94 + (i * 4))
+
+#define CHGR_ENG_CHARGING_CFG_REG		(CHGR_BASE + 0xC0)
+#define CHGR_ITERM_USE_ANALOG_BIT		BIT(3)
+
 /********************************
  *  DCDC Peripheral Registers  *
  ********************************/
 #define ICL_MAX_STATUS_REG			(DCDC_BASE + 0x06)
-
+#define ICL_STATUS_REG				(DCDC_BASE + 0x07)
 #define AICL_ICL_STATUS_REG			(DCDC_BASE + 0x08)
 
 #define AICL_STATUS_REG				(DCDC_BASE + 0x0A)
@@ -117,6 +126,7 @@
 #define USBIN_SUSPEND_STS_BIT			BIT(6)
 #define USE_USBIN_BIT				BIT(4)
 #define USE_DCIN_BIT				BIT(3)
+#define POWER_PATH_MASK				GENMASK(2, 1)
 #define VALID_INPUT_POWER_SOURCE_STS_BIT	BIT(0)
 
 #define DCDC_CMD_OTG_REG			(DCDC_BASE + 0x40)
@@ -146,6 +156,19 @@
 #define SHIP_MODE_REG				(BATIF_BASE + 0x40)
 #define SHIP_MODE_EN_BIT			BIT(0)
 
+#define BATIF_ADC_CHANNEL_EN_REG		(BATIF_BASE + 0x82)
+#define IBATT_CHANNEL_EN_BIT			BIT(6)
+#define CONN_THM_CHANNEL_EN_BIT			BIT(4)
+#define DIE_TEMP_CHANNEL_EN_BIT			BIT(2)
+
+#define BATIF_ADC_INTERNAL_PULL_UP_REG		(BATIF_BASE + 0x86)
+#define INTERNAL_PULL_UP_CONN_THM_MASK		GENMASK(5, 4)
+#define CONN_THM_SHIFT				4
+#define INTERNAL_PULL_NO_PULL			0x00
+#define INTERNAL_PULL_30K_PULL			0x01
+#define INTERNAL_PULL_100K_PULL			0x02
+#define INTERNAL_PULL_400K_PULL			0x03
+
 /********************************
  *  USBIN Peripheral Registers  *
  ********************************/
@@ -238,6 +261,8 @@
 #define USBIN_AICL_OPTIONS_CFG_REG		(USBIN_BASE + 0x80)
 #define USBIN_AICL_ADC_EN_BIT			BIT(3)
 
+#define USBIN_5V_AICL_THRESHOLD_REG		(USBIN_BASE + 0x81)
+#define USBIN_CONT_AICL_THRESHOLD_REG		(USBIN_BASE + 0x84)
 /********************************
  *  DCIN Peripheral Registers   *
  ********************************/
@@ -252,10 +277,11 @@
  *  TYPEC Peripheral Registers  *
  ********************************/
 #define TYPE_C_SNK_STATUS_REG			(TYPEC_BASE + 0x06)
-#define DETECTED_SRC_TYPE_MASK			GENMASK(3, 1)
+#define DETECTED_SRC_TYPE_MASK			GENMASK(3, 0)
 #define SNK_RP_STD_BIT				BIT(3)
 #define SNK_RP_1P5_BIT				BIT(2)
 #define SNK_RP_3P0_BIT				BIT(1)
+#define SNK_RP_SHORT_BIT			BIT(0)
 
 #define TYPE_C_SRC_STATUS_REG			(TYPEC_BASE + 0x08)
 #define DETECTED_SNK_TYPE_MASK			GENMASK(4, 0)
@@ -269,6 +295,7 @@
 #define TYPEC_ATTACH_DETACH_STATE_BIT		BIT(5)
 
 #define TYPE_C_MISC_STATUS_REG			(TYPEC_BASE + 0x0B)
+#define TYPEC_WATER_DETECTION_STATUS_BIT	BIT(7)
 #define SNK_SRC_MODE_BIT			BIT(6)
 #define TYPEC_VBUS_ERROR_STATUS_BIT		BIT(4)
 #define CC_ORIENTATION_BIT			BIT(1)
@@ -281,6 +308,10 @@
 #define TYPEC_U_USB_STATUS_REG			(TYPEC_BASE + 0x0F)
 #define U_USB_GROUND_NOVBUS_BIT			BIT(6)
 #define U_USB_GROUND_BIT			BIT(4)
+#define U_USB_FMB1_BIT				BIT(3)
+#define U_USB_FLOAT1_BIT			BIT(2)
+#define U_USB_FMB2_BIT				BIT(1)
+#define U_USB_FLOAT2_BIT			BIT(0)
 
 #define TYPE_C_MODE_CFG_REG			(TYPEC_BASE + 0x44)
 #define TYPEC_POWER_ROLE_CMD_MASK		GENMASK(2, 1)
@@ -326,14 +357,20 @@
 #define REDUCE_TCCDEBOUNCE_TO_2MS_BIT		BIT(2)
 
 #define TYPEC_U_USB_CFG_REG			(TYPEC_BASE + 0x70)
+#define EN_MICRO_USB_FACTORY_MODE_BIT		BIT(1)
 #define EN_MICRO_USB_MODE_BIT			BIT(0)
 
+#define TYPEC_U_USB_WATER_PROTECTION_CFG_REG	(TYPEC_BASE + 0x72)
+#define EN_MICRO_USB_WATER_PROTECTION_BIT	BIT(4)
+#define MICRO_USB_DETECTION_ON_TIME_CFG_MASK	GENMASK(3, 2)
+#define MICRO_USB_DETECTION_PERIOD_CFG_MASK	GENMASK(1, 0)
+
 #define TYPEC_MICRO_USB_MODE_REG		(TYPEC_BASE + 0x73)
 #define MICRO_USB_MODE_ONLY_BIT			BIT(0)
 /********************************
  *  MISC Peripheral Registers  *
  ********************************/
-#define TEMP_RANGE_STATUS_REG			(MISC_BASE + 0x06)
+#define MISC_TEMP_RANGE_STATUS_REG		(MISC_BASE + 0x06)
 #define THERM_REG_ACTIVE_BIT			BIT(6)
 #define TLIM_BIT				BIT(5)
 #define TEMP_RANGE_MASK				GENMASK(4, 1)
@@ -343,10 +380,17 @@
 #define TEMP_BELOW_RANGE_BIT			BIT(1)
 #define THERMREG_DISABLED_BIT			BIT(0)
 
+#define MISC_DIE_TEMP_STATUS_REG		(MISC_BASE + 0x07)
+#define DIE_TEMP_SHDN_BIT			BIT(3)
+#define DIE_TEMP_RST_BIT			BIT(2)
+#define DIE_TEMP_UB_BIT				BIT(1)
+#define DIE_TEMP_LB_BIT				BIT(0)
+
 #define BARK_BITE_WDOG_PET_REG			(MISC_BASE + 0x43)
 #define BARK_BITE_WDOG_PET_BIT			BIT(0)
 
 #define AICL_CMD_REG				(MISC_BASE + 0x44)
+#define RESTART_AICL_BIT			BIT(1)
 #define RERUN_AICL_BIT				BIT(0)
 
 #define MISC_SMB_EN_CMD_REG			(MISC_BASE + 0x48)
@@ -366,6 +410,16 @@
 #define BARK_WDOG_TIMEOUT_MASK			GENMASK(3, 2)
 #define BITE_WDOG_TIMEOUT_MASK			GENMASK(1, 0)
 
+#define MISC_THERMREG_SRC_CFG_REG		(MISC_BASE + 0x70)
+#define THERMREG_SW_ICL_ADJUST_BIT		BIT(7)
+#define DIE_ADC_SEL_BIT				BIT(6)
+#define THERMREG_SMB_ADC_SRC_EN_BIT		BIT(5)
+#define THERMREG_CONNECTOR_ADC_SRC_EN_BIT	BIT(4)
+#define SKIN_ADC_CFG_BIT			BIT(3)
+#define THERMREG_SKIN_ADC_SRC_EN_BIT		BIT(2)
+#define THERMREG_DIE_ADC_SRC_EN_BIT		BIT(1)
+#define THERMREG_DIE_CMP_SRC_EN_BIT		BIT(0)
+
 #define MISC_SMB_CFG_REG			(MISC_BASE + 0x90)
 #define SMB_EN_SEL_BIT				BIT(4)
 #define CP_EN_POLARITY_CFG_BIT			BIT(3)
diff --git a/drivers/power/supply/qcom/step-chg-jeita.c b/drivers/power/supply/qcom/step-chg-jeita.c
index 2d147d4..3b4b275 100644
--- a/drivers/power/supply/qcom/step-chg-jeita.c
+++ b/drivers/power/supply/qcom/step-chg-jeita.c
@@ -349,17 +349,46 @@
 	int i;
 
 	*new_index = -EINVAL;
-	/* first find the matching index without hysteresis */
-	for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++)
+
+	/*
+	 * If the threshold is lesser than the minimum allowed range,
+	 * return -ENODATA.
+	 */
+	if (threshold < range[0].low_threshold)
+		return -ENODATA;
+
+	/* First try to find the matching index without hysteresis */
+	for (i = 0; i < MAX_STEP_CHG_ENTRIES; i++) {
+		if (!range[i].high_threshold && !range[i].low_threshold) {
+			/* First invalid table entry; exit loop */
+			break;
+		}
+
 		if (is_between(range[i].low_threshold,
 			range[i].high_threshold, threshold)) {
 			*new_index = i;
 			*val = range[i].value;
+			break;
+		}
+	}
+
+	/*
+	 * If nothing was found, the threshold exceeds the max range for sure
+	 * as the other case where it is lesser than the min range is handled
+	 * at the very beginning of this function. Therefore, clip it to the
+	 * max allowed range value, which is the one corresponding to the last
+	 * valid entry in the battery profile data array.
+	 */
+	if (*new_index == -EINVAL) {
+		if (i == 0) {
+			/* Battery profile data array is completely invalid */
+			return -ENODATA;
 		}
 
-	/* if nothing was found, return -ENODATA */
-	if (*new_index == -EINVAL)
-		return -ENODATA;
+		*new_index = (i - 1);
+		*val = range[*new_index].value;
+	}
+
 	/*
 	 * If we don't have a current_index return this
 	 * newfound value. There is no hysterisis from out of range
diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c
index cc01399..4e8d6f9 100644
--- a/drivers/regulator/qpnp-lcdb-regulator.c
+++ b/drivers/regulator/qpnp-lcdb-regulator.c
@@ -218,6 +218,7 @@
 	struct regmap			*regmap;
 	struct pmic_revid_data		*pmic_rev_id;
 	u32				base;
+	u32				wa_flags;
 	int				sc_irq;
 
 	/* TTW params */
@@ -288,6 +289,10 @@
 	LCDB_SETTING_MAX,
 };
 
+enum lcdb_wa_flags {
+	NCP_SCP_DISABLE_WA = BIT(0),
+};
+
 static u32 soft_start_us[] = {
 	0,
 	500,
@@ -747,9 +752,7 @@
 		return rc;
 	}
 
-	/* execute the below for rev1.1 */
-	if (lcdb->pmic_rev_id->rev3 == PM660L_V1P1_REV3 &&
-		lcdb->pmic_rev_id->rev4 == PM660L_V1P1_REV4) {
+	if (lcdb->wa_flags & NCP_SCP_DISABLE_WA) {
 		/*
 		 * delay to make sure that the MID pin – ie the
 		 * output of the LCDB boost – returns to 0V
@@ -1914,11 +1917,27 @@
 	return 0;
 }
 
+static void qpnp_lcdb_pmic_config(struct qpnp_lcdb *lcdb)
+{
+	switch (lcdb->pmic_rev_id->pmic_subtype) {
+	case PM660L_SUBTYPE:
+		if (lcdb->pmic_rev_id->rev4 < PM660L_V2P0_REV4)
+			lcdb->wa_flags |= NCP_SCP_DISABLE_WA;
+		break;
+	default:
+		break;
+	}
+
+	pr_debug("LCDB wa_flags = 0x%2x\n", lcdb->wa_flags);
+}
+
 static int qpnp_lcdb_hw_init(struct qpnp_lcdb *lcdb)
 {
 	int rc = 0;
 	u8 val = 0;
 
+	qpnp_lcdb_pmic_config(lcdb);
+
 	rc = qpnp_lcdb_init_bst(lcdb);
 	if (rc < 0) {
 		pr_err("Failed to initialize BOOST rc=%d\n", rc);
@@ -1937,8 +1956,7 @@
 		return rc;
 	}
 
-	if (lcdb->sc_irq >= 0 &&
-		lcdb->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE) {
+	if (lcdb->sc_irq >= 0 && !(lcdb->wa_flags & NCP_SCP_DISABLE_WA)) {
 		lcdb->sc_count = 0;
 		rc = devm_request_threaded_irq(lcdb->dev, lcdb->sc_irq,
 				NULL, qpnp_lcdb_sc_irq_handler, IRQF_ONESHOT,
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c6cfd18..0d72cd0 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -10239,7 +10239,15 @@
 	 * racing during clock frequency scaling sequence.
 	 */
 	if (ufshcd_is_auto_hibern8_supported(hba)) {
+		/*
+		 * Scaling prepare acquires the rw_sem: lock
+		 * h8 may sleep in case of errors.
+		 * e.g. link_recovery. Hence, release the rw_sem
+		 * before hibern8.
+		 */
+		up_write(&hba->lock);
 		ret = ufshcd_uic_hibern8_enter(hba);
+		down_write(&hba->lock);
 		if (ret)
 			/* link will be bad state so no need to scale_up_gear */
 			return ret;
@@ -10370,6 +10378,8 @@
 
 	hba->clk_scaling.is_allowed = value;
 
+	flush_work(&hba->eh_work);
+
 	if (value) {
 		ufshcd_resume_clkscaling(hba);
 	} else {
diff --git a/drivers/slimbus/slim-msm-ngd.c b/drivers/slimbus/slim-msm-ngd.c
index 26dfd3f..34be230 100644
--- a/drivers/slimbus/slim-msm-ngd.c
+++ b/drivers/slimbus/slim-msm-ngd.c
@@ -214,6 +214,8 @@
 						dsp);
 	struct pd_qmi_client_data *reg;
 
+	/* Resetting the log level */
+	SLIM_RST_LOGLVL(dev);
 	SLIM_INFO(dev, "SLIM DSP SSR/PDR notify cb:0x%lx, type:%d\n",
 			code, dsp->dom_t);
 	switch (code) {
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index 24a3ccf..1cc5d84 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -182,8 +182,12 @@
 	if (!ctrl_dev->iommu_desc.cb_dev)
 		return 0;
 
-	if (!IS_ERR_OR_NULL(ctrl_dev->iommu_desc.iommu_map))
-		return 0;
+	if (!IS_ERR_OR_NULL(ctrl_dev->iommu_desc.iommu_map)) {
+		arm_iommu_detach_device(ctrl_dev->iommu_desc.cb_dev);
+		arm_iommu_release_mapping(ctrl_dev->iommu_desc.iommu_map);
+		ctrl_dev->iommu_desc.iommu_map = NULL;
+		SLIM_INFO(ctrl_dev, "NGD IOMMU Dettach complete\n");
+	}
 
 	dev = ctrl_dev->iommu_desc.cb_dev;
 	iommu_map = arm_iommu_create_mapping(&platform_bus_type,
@@ -1300,12 +1304,6 @@
 			msm_slim_disconn_pipe_port(dev, i);
 	}
 
-	if (!IS_ERR_OR_NULL(dev->iommu_desc.iommu_map)) {
-		arm_iommu_detach_device(dev->iommu_desc.cb_dev);
-		arm_iommu_release_mapping(dev->iommu_desc.iommu_map);
-		dev->iommu_desc.iommu_map = NULL;
-	}
-
 	if (dereg) {
 		for (i = 0; i < dev->port_nums; i++) {
 			if (dev->pipes[i].connected)
@@ -1706,6 +1704,11 @@
 	struct qmi_handle *handle;
 	struct slimbus_select_inst_req_msg_v01 req;
 
+	if (dev->qmi.handle || dev->qmi.task) {
+		pr_err("%s: Destroying stale QMI client handle\n", __func__);
+		msm_slim_qmi_exit(dev);
+	}
+
 	kthread_init_worker(&dev->qmi.kworker);
 	init_completion(&dev->qmi.defer_comp);
 
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 3ecca59..52d9f65 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -52,6 +52,14 @@
 	  can start using the LLCC slices.
 	  Say yes here to enable llcc driver for SDM670.
 
+config QCOM_QCS605_LLCC
+	tristate "Qualcomm Technologies, Inc. QCS605 LLCC driver"
+	depends on QCOM_LLCC
+	help
+	  This provides Last level cache controller driver for QCS605.
+	  This driver provides data required to configure LLCC, so that clients
+	  can start using the LLCC slices.
+	  Say yes here to enable llcc driver for QCS605.
 
 config QCOM_LLCC_AMON
 	tristate "Qualcomm Technologies, Inc. LLCC Activity Monitor(AMON) driver"
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 0b71121..1da8346 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -7,6 +7,7 @@
 obj-$(CONFIG_QCOM_LLCC) += llcc-core.o llcc-slice.o
 obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
 obj-$(CONFIG_QCOM_SDM670_LLCC) += llcc-sdm670.o
+obj-$(CONFIG_QCOM_QCS605_LLCC) += llcc-qcs605.o
 obj-$(CONFIG_QCOM_LLCC_PERFMON) += llcc_perfmon.o
 obj-$(CONFIG_QCOM_LLCC_AMON) += llcc-amon.o
 obj-$(CONFIG_QPNP_PBS) += qpnp-pbs.o
diff --git a/drivers/soc/qcom/bgcom_interface.c b/drivers/soc/qcom/bgcom_interface.c
index 1cde8c6..75c9928 100644
--- a/drivers/soc/qcom/bgcom_interface.c
+++ b/drivers/soc/qcom/bgcom_interface.c
@@ -306,10 +306,23 @@
 
 int bg_soft_reset(void)
 {
-	/*pull down reset gpio */
-	gpio_direction_output(bgreset_gpio, 0);
+	pr_debug("do BG reset using gpio %d\n", bgreset_gpio);
+	if (!gpio_is_valid(bgreset_gpio)) {
+		pr_err("gpio %d is not valid\n", bgreset_gpio);
+		return -ENXIO;
+	}
+	if (gpio_direction_output(bgreset_gpio, 1))
+		pr_err("gpio %d direction not set\n", bgreset_gpio);
+
+	/* Sleep for 50ms for hardware to detect signal as high */
+	msleep(50);
+
+	gpio_set_value(bgreset_gpio, 0);
+
+	/* Sleep for 50ms for hardware to detect signal as high */
 	msleep(50);
 	gpio_set_value(bgreset_gpio, 1);
+
 	return 0;
 }
 EXPORT_SYMBOL(bg_soft_reset);
diff --git a/drivers/soc/qcom/dcc_v2.c b/drivers/soc/qcom/dcc_v2.c
index e641290..ac50996 100644
--- a/drivers/soc/qcom/dcc_v2.c
+++ b/drivers/soc/qcom/dcc_v2.c
@@ -990,6 +990,14 @@
 		apb_bus = 1;
 	}
 
+	if (len == 0)
+		len = 1;
+
+	if (base == 0) {
+		dev_err(drvdata->dev, "DCC: Invalid  Address\n");
+		return -EINVAL;
+	}
+
 	ret = dcc_config_add(drvdata, base, len, apb_bus);
 	if (ret)
 		return ret;
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index b8e9268..39b79f6 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -284,6 +284,7 @@
 	ICNSS_HOST_TRIGGERED_PDR,
 	ICNSS_FW_DOWN,
 	ICNSS_DRIVER_UNLOADING,
+	ICNSS_REJUVENATE,
 };
 
 struct ce_irq_list {
@@ -1172,6 +1173,14 @@
 }
 EXPORT_SYMBOL(icnss_is_fw_down);
 
+bool icnss_is_rejuvenate(void)
+{
+	if (!penv)
+		return false;
+	else
+		return test_bit(ICNSS_REJUVENATE, &penv->state);
+}
+EXPORT_SYMBOL(icnss_is_rejuvenate);
 
 int icnss_power_off(struct device *dev)
 {
@@ -2093,6 +2102,7 @@
 		event_data->crashed = true;
 		event_data->fw_rejuvenate = true;
 		fw_down_data.crashed = true;
+		set_bit(ICNSS_REJUVENATE, &penv->state);
 		icnss_call_driver_uevent(penv, ICNSS_UEVENT_FW_DOWN,
 					 &fw_down_data);
 		icnss_driver_event_post(ICNSS_DRIVER_EVENT_PD_SERVICE_DOWN,
@@ -2283,6 +2293,7 @@
 
 	icnss_call_driver_shutdown(priv);
 
+	clear_bit(ICNSS_REJUVENATE, &penv->state);
 	clear_bit(ICNSS_PD_RESTART, &priv->state);
 	priv->early_crash_ind = false;
 
@@ -3525,6 +3536,7 @@
 	int atomic_ctx = 1;
 	int s1_bypass = 1;
 	int fast = 1;
+	int stall_disable = 1;
 	int ret = 0;
 
 	icnss_pr_dbg("Initializing SMMU\n");
@@ -3568,6 +3580,16 @@
 			goto set_attr_fail;
 		}
 		icnss_pr_dbg("SMMU FAST map set\n");
+
+		ret = iommu_domain_set_attr(mapping->domain,
+					    DOMAIN_ATTR_CB_STALL_DISABLE,
+					    &stall_disable);
+		if (ret < 0) {
+			icnss_pr_err("Set stall disable map attribute failed, err = %d\n",
+				     ret);
+			goto set_attr_fail;
+		}
+		icnss_pr_dbg("SMMU STALL DISABLE map set\n");
 	}
 
 	ret = arm_iommu_attach_device(&priv->pdev->dev, mapping);
@@ -3989,6 +4011,9 @@
 		case ICNSS_FW_DOWN:
 			seq_puts(s, "FW DOWN");
 			continue;
+		case ICNSS_REJUVENATE:
+			seq_puts(s, "FW REJUVENATE");
+			continue;
 		case ICNSS_DRIVER_UNLOADING:
 			seq_puts(s, "DRIVER UNLOADING");
 		}
diff --git a/drivers/soc/qcom/ipc_router_glink_xprt.c b/drivers/soc/qcom/ipc_router_glink_xprt.c
index c93e0e1..fbb8046 100644
--- a/drivers/soc/qcom/ipc_router_glink_xprt.c
+++ b/drivers/soc/qcom/ipc_router_glink_xprt.c
@@ -23,6 +23,7 @@
 #include <linux/skbuff.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
+#include <linux/kthread.h>
 
 #include <soc/qcom/glink.h>
 #include <soc/qcom/subsystem_restart.h>
@@ -74,6 +75,7 @@
  * @xprt_option: XPRT specific options to be handled by IPC Router.
  * @disable_pil_loading: Disable PIL Loading of the subsystem.
  * @dynamic_wakeup_source: Dynamic wakeup source for this subsystem.
+ * @low_latency_xprt: Flag to indicate low latency transport.
  */
 struct ipc_router_glink_xprt {
 	struct list_head list;
@@ -85,7 +87,6 @@
 	char notify_rx_ws_name[IPC_RTR_WS_NAME_LEN];
 	struct msm_ipc_router_xprt xprt;
 	void *ch_hndl;
-	struct workqueue_struct *xprt_wq;
 	struct wakeup_source notify_rxv_ws;
 	struct rw_semaphore ss_reset_rwlock;
 	int ss_reset;
@@ -98,17 +99,21 @@
 	uint32_t cur_md_intents_cnt;
 	uint32_t cur_hi_intents_cnt;
 	bool dynamic_wakeup_source;
+	bool low_latency_xprt;
+
+	struct kthread_worker kworker;
+	struct task_struct *task;
 };
 
 struct ipc_router_glink_xprt_work {
 	struct ipc_router_glink_xprt *glink_xprtp;
-	struct work_struct work;
+	struct kthread_work kwork;
 };
 
 struct queue_rx_intent_work {
 	struct ipc_router_glink_xprt *glink_xprtp;
 	size_t intent_size;
-	struct work_struct work;
+	struct kthread_work kwork;
 };
 
 struct read_work {
@@ -117,12 +122,12 @@
 	size_t iovec_size;
 	void * (*vbuf_provider)(void *iovec, size_t offset, size_t *size);
 	void * (*pbuf_provider)(void *iovec, size_t offset, size_t *size);
-	struct work_struct work;
+	struct kthread_work kwork;
 };
 
-static void glink_xprt_read_data(struct work_struct *work);
-static void glink_xprt_open_event(struct work_struct *work);
-static void glink_xprt_close_event(struct work_struct *work);
+static void glink_xprt_read_data(struct kthread_work *work);
+static void glink_xprt_open_event(struct kthread_work *work);
+static void glink_xprt_close_event(struct kthread_work *work);
 
 /**
  * ipc_router_glink_xprt_config - Config. Info. of each GLINK XPRT
@@ -135,6 +140,7 @@
  * @xprt_version:	IPC Router header version supported by this XPRT.
  * @disable_pil_loading:Disable PIL Loading of the subsystem.
  * @dynamic_wakeup_source: Dynamic wakeup source for this subsystem.
+ * @low_latency_xprt: Flag to indicate low latency transport.
  */
 struct ipc_router_glink_xprt_config {
 	char ch_name[GLINK_NAME_SIZE];
@@ -147,6 +153,7 @@
 	unsigned int xprt_option;
 	bool disable_pil_loading;
 	bool dynamic_wakeup_source;
+	bool low_latency_xprt;
 };
 
 #define MODULE_NAME "ipc_router_glink_xprt"
@@ -311,6 +318,14 @@
 	return glink_xprtp->dynamic_wakeup_source;
 }
 
+static bool ipc_router_glink_xprt_latency_info(struct msm_ipc_router_xprt *xprt)
+{
+	struct ipc_router_glink_xprt *glink_xprtp =
+		container_of(xprt, struct ipc_router_glink_xprt, xprt);
+
+	return glink_xprtp->low_latency_xprt;
+}
+
 static struct rr_packet *glink_xprt_copy_data(struct read_work *rx_work)
 {
 	void *buf, *pbuf, *dest_buf;
@@ -352,11 +367,11 @@
 	return pkt;
 }
 
-static void glink_xprt_read_data(struct work_struct *work)
+static void glink_xprt_read_data(struct kthread_work *work)
 {
 	struct rr_packet *pkt;
 	struct read_work *rx_work =
-		container_of(work, struct read_work, work);
+		container_of(work, struct read_work, kwork);
 	struct ipc_router_glink_xprt *glink_xprtp = rx_work->glink_xprtp;
 	bool reuse_intent = false;
 
@@ -387,10 +402,10 @@
 	__pm_relax(&glink_xprtp->notify_rxv_ws);
 }
 
-static void glink_xprt_open_event(struct work_struct *work)
+static void glink_xprt_open_event(struct kthread_work *work)
 {
 	struct ipc_router_glink_xprt_work *xprt_work =
-		container_of(work, struct ipc_router_glink_xprt_work, work);
+		container_of(work, struct ipc_router_glink_xprt_work, kwork);
 	struct ipc_router_glink_xprt *glink_xprtp = xprt_work->glink_xprtp;
 	int i;
 
@@ -409,10 +424,10 @@
 	kfree(xprt_work);
 }
 
-static void glink_xprt_close_event(struct work_struct *work)
+static void glink_xprt_close_event(struct kthread_work *work)
 {
 	struct ipc_router_glink_xprt_work *xprt_work =
-		container_of(work, struct ipc_router_glink_xprt_work, work);
+		container_of(work, struct ipc_router_glink_xprt_work, kwork);
 	struct ipc_router_glink_xprt *glink_xprtp = xprt_work->glink_xprtp;
 
 	init_completion(&glink_xprtp->sft_close_complete);
@@ -424,11 +439,11 @@
 	kfree(xprt_work);
 }
 
-static void glink_xprt_qrx_intent_worker(struct work_struct *work)
+static void glink_xprt_qrx_intent_worker(struct kthread_work *work)
 {
 	size_t sz;
 	struct queue_rx_intent_work *qrx_intent_work =
-		container_of(work, struct queue_rx_intent_work, work);
+		container_of(work, struct queue_rx_intent_work, kwork);
 	struct ipc_router_glink_xprt *glink_xprtp =
 					qrx_intent_work->glink_xprtp;
 	uint32_t *cnt = NULL;
@@ -501,8 +516,8 @@
 	rx_work->pbuf_provider = pbuf_provider;
 	if (!glink_xprtp->dynamic_wakeup_source)
 		__pm_stay_awake(&glink_xprtp->notify_rxv_ws);
-	INIT_WORK(&rx_work->work, glink_xprt_read_data);
-	queue_work(glink_xprtp->xprt_wq, &rx_work->work);
+	kthread_init_work(&rx_work->kwork, glink_xprt_read_data);
+	kthread_queue_work(&glink_xprtp->kworker, &rx_work->kwork);
 }
 
 static void glink_xprt_notify_tx_done(void *handle, const void *priv,
@@ -535,8 +550,9 @@
 	}
 	qrx_intent_work->glink_xprtp = glink_xprtp;
 	qrx_intent_work->intent_size = sz;
-	INIT_WORK(&qrx_intent_work->work, glink_xprt_qrx_intent_worker);
-	queue_work(glink_xprtp->xprt_wq, &qrx_intent_work->work);
+	kthread_init_work(&qrx_intent_work->kwork,
+			  glink_xprt_qrx_intent_worker);
+	kthread_queue_work(&glink_xprtp->kworker, &qrx_intent_work->kwork);
 	return true;
 }
 
@@ -565,8 +581,8 @@
 			return;
 		}
 		xprt_work->glink_xprtp = glink_xprtp;
-		INIT_WORK(&xprt_work->work, glink_xprt_open_event);
-		queue_work(glink_xprtp->xprt_wq, &xprt_work->work);
+		kthread_init_work(&xprt_work->kwork, glink_xprt_open_event);
+		kthread_queue_work(&glink_xprtp->kworker, &xprt_work->kwork);
 		break;
 
 	case GLINK_LOCAL_DISCONNECTED:
@@ -587,8 +603,8 @@
 			return;
 		}
 		xprt_work->glink_xprtp = glink_xprtp;
-		INIT_WORK(&xprt_work->work, glink_xprt_close_event);
-		queue_work(glink_xprtp->xprt_wq, &xprt_work->work);
+		kthread_init_work(&xprt_work->kwork, glink_xprt_close_event);
+		kthread_queue_work(&glink_xprtp->kworker, &xprt_work->kwork);
 		break;
 	}
 }
@@ -712,6 +728,7 @@
 {
 	struct ipc_router_glink_xprt *glink_xprtp;
 	char xprt_wq_name[GLINK_NAME_SIZE];
+	struct sched_param param = {.sched_priority = 1};
 
 	glink_xprtp = kzalloc(sizeof(struct ipc_router_glink_xprt), GFP_KERNEL);
 	if (IS_ERR_OR_NULL(glink_xprtp)) {
@@ -729,6 +746,8 @@
 				glink_xprt_config->disable_pil_loading;
 	glink_xprtp->dynamic_wakeup_source =
 				glink_xprt_config->dynamic_wakeup_source;
+	glink_xprtp->low_latency_xprt =
+				glink_xprt_config->low_latency_xprt;
 
 	if (!glink_xprtp->disable_pil_loading)
 		strlcpy(glink_xprtp->pil_edge, glink_xprt_config->pil_edge,
@@ -752,6 +771,7 @@
 	glink_xprtp->xprt.close = ipc_router_glink_xprt_close;
 	glink_xprtp->xprt.sft_close_done = glink_xprt_sft_close_done;
 	glink_xprtp->xprt.get_ws_info = ipc_router_glink_xprt_get_ws_info;
+	glink_xprtp->xprt.get_latency_info = ipc_router_glink_xprt_latency_info;
 	glink_xprtp->xprt.priv = NULL;
 
 	init_rwsem(&glink_xprtp->ss_reset_rwlock);
@@ -760,15 +780,20 @@
 	scnprintf(xprt_wq_name, GLINK_NAME_SIZE, "%s_%s_%s",
 			glink_xprtp->ch_name, glink_xprtp->edge,
 			glink_xprtp->transport);
-	glink_xprtp->xprt_wq = create_singlethread_workqueue(xprt_wq_name);
-	if (IS_ERR_OR_NULL(glink_xprtp->xprt_wq)) {
-		IPC_RTR_ERR("%s:%s:%s:%s wq alloc failed\n",
-			    __func__, glink_xprt_config->ch_name,
-			    glink_xprt_config->edge,
-			    glink_xprt_config->transport);
+	kthread_init_worker(&glink_xprtp->kworker);
+	glink_xprtp->task = kthread_run(kthread_worker_fn,
+					&glink_xprtp->kworker,
+					"%s", xprt_wq_name);
+	if (IS_ERR(glink_xprtp->task)) {
+		IPC_RTR_ERR("%s:%s task alloc failed\n",
+			    __func__, xprt_wq_name);
 		kfree(glink_xprtp);
 		return -EFAULT;
 	}
+
+	if (glink_xprtp->low_latency_xprt)
+		sched_setscheduler(glink_xprtp->task, SCHED_FIFO, &param);
+
 	scnprintf(glink_xprtp->notify_rx_ws_name, IPC_RTR_WS_NAME_LEN,
 			"%s_%s_rx", glink_xprtp->ch_name, glink_xprtp->edge);
 	wakeup_source_init(&glink_xprtp->notify_rxv_ws,
@@ -853,6 +878,9 @@
 	glink_xprt_config->dynamic_wakeup_source =
 					of_property_read_bool(node, key);
 
+	key = "qcom,low-latency-xprt";
+	glink_xprt_config->low_latency_xprt =
+					of_property_read_bool(node, key);
 	return 0;
 
 error:
diff --git a/drivers/soc/qcom/jtagv8-etm.c b/drivers/soc/qcom/jtagv8-etm.c
index 23cbb7b..45511ce 100644
--- a/drivers/soc/qcom/jtagv8-etm.c
+++ b/drivers/soc/qcom/jtagv8-etm.c
@@ -1480,6 +1480,27 @@
 		etmdata->os_lock_present = false;
 }
 
+static bool coresight_authstatus_enabled(void __iomem *addr)
+{
+	int ret;
+	unsigned int auth_val;
+
+	if (!addr)
+		return false;
+
+	auth_val = readl_relaxed(addr + TRCAUTHSTATUS);
+
+	if ((BMVAL(auth_val, 0, 1) == 0x2) ||
+	    (BMVAL(auth_val, 2, 3) == 0x2) ||
+	    (BMVAL(auth_val, 4, 5) == 0x2) ||
+	    (BMVAL(auth_val, 6, 7) == 0x2))
+		ret = false;
+	else
+		ret = true;
+
+	return ret;
+}
+
 static void etm_init_arch_data(void *info)
 {
 	uint32_t val;
@@ -1487,6 +1508,9 @@
 
 	ETM_UNLOCK(etmdata);
 
+	if (!coresight_authstatus_enabled(etmdata->base))
+		goto out;
+
 	etm_os_lock_init(etmdata);
 
 	val = etm_readl(etmdata, TRCIDR1);
@@ -1505,6 +1529,7 @@
 	etmdata->nr_seq_state = BMVAL(val, 25, 27);
 	etmdata->nr_cntr = BMVAL(val, 28, 30);
 
+out:
 	ETM_LOCK(etmdata);
 }
 
diff --git a/drivers/soc/qcom/llcc-qcs605.c b/drivers/soc/qcom/llcc-qcs605.c
new file mode 100644
index 0000000..d3d3390
--- /dev/null
+++ b/drivers/soc/qcom/llcc-qcs605.c
@@ -0,0 +1,106 @@
+/* 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 <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/llcc-qcom.h>
+
+/*
+ * SCT entry contains of the following parameters
+ * name: Name of the client's use case for which the llcc slice is used
+ * uid: Unique id for the client's use case
+ * slice_id: llcc slice id for each client
+ * max_cap: The maximum capacity of the cache slice provided in KB
+ * priority: Priority of the client used to select victim line for replacement
+ * fixed_size: Determine of the slice has a fixed capacity
+ * bonus_ways: Bonus ways to be used by any slice, bonus way is used only if
+ *             it't not a reserved way.
+ * res_ways: Reserved ways for the cache slice, the reserved ways cannot be used
+ *           by any other client than the one its assigned to.
+ * cache_mode: Each slice operates as a cache, this controls the mode of the
+ *             slice normal or TCM
+ * probe_target_ways: Determines what ways to probe for access hit. When
+ *                    configured to 1 only bonus and reseved ways are probed.
+ *                    when configured to 0 all ways in llcc are probed.
+ * dis_cap_alloc: Disable capacity based allocation for a client
+ * retain_on_pc: If this bit is set and client has maitained active vote
+ *               then the ways assigned to this client are not flushed on power
+ *               collapse.
+ * activate_on_init: Activate the slice immidiately after the SCT is programmed
+ */
+#define SCT_ENTRY(n, uid, sid, mc, p, fs, bway, rway, cmod, ptw, dca, rp, a) \
+	{					\
+		.name = n,			\
+		.usecase_id = uid,		\
+		.slice_id = sid,		\
+		.max_cap = mc,			\
+		.priority = p,			\
+		.fixed_size = fs,		\
+		.bonus_ways = bway,		\
+		.res_ways = rway,		\
+		.cache_mode = cmod,		\
+		.probe_target_ways = ptw,	\
+		.dis_cap_alloc = dca,		\
+		.retain_on_pc = rp,		\
+		.activate_on_init = a,		\
+	}
+
+static struct llcc_slice_config qcs605_data[] =  {
+	SCT_ENTRY("cpuss",	 1,  1, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 1),
+	SCT_ENTRY("vidsc0",	 2,  2, 256, 2, 1, 0x3, 0x0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("vidsc1",	 3,  3, 256, 2, 1, 0x3, 0x0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("voice",	 5,  5, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("audio",	 6,  6, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("modem",	 8,  8, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("compute",	10, 10, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("gpu",	12, 12, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("mmuhwt",	13, 13, 512, 1, 0, 0xF, 0x0, 0, 0, 1, 0, 1),
+	SCT_ENTRY("audiohw",	22, 22, 512, 1, 1, 0xF, 0x0, 0, 0, 1, 1, 0),
+};
+
+static int qcs605_qcom_llcc_probe(struct platform_device *pdev)
+{
+	return qcom_llcc_probe(pdev, qcs605_data,
+				 ARRAY_SIZE(qcs605_data));
+}
+
+static const struct of_device_id qcs605_qcom_llcc_of_match[] = {
+	{ .compatible = "qcom,qcs605-llcc", },
+	{ },
+};
+
+static struct platform_driver qcs605_qcom_llcc_driver = {
+	.driver = {
+		.name = "qcs605-llcc",
+		.owner = THIS_MODULE,
+		.of_match_table = qcs605_qcom_llcc_of_match,
+	},
+	.probe = qcs605_qcom_llcc_probe,
+	.remove = qcom_llcc_remove,
+};
+
+static int __init qcs605_init_qcom_llcc_init(void)
+{
+	return platform_driver_register(&qcs605_qcom_llcc_driver);
+}
+module_init(qcs605_init_qcom_llcc_init);
+
+static void __exit qcs605_exit_qcom_llcc_exit(void)
+{
+	platform_driver_unregister(&qcs605_qcom_llcc_driver);
+}
+module_exit(qcs605_exit_qcom_llcc_exit);
+
+MODULE_DESCRIPTION("QTI qcs605 LLCC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
index ee9b7af..eb54119 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_adhoc.c
@@ -971,10 +971,8 @@
 
 	bus_node = kzalloc(sizeof(struct msm_bus_node_device_type), GFP_KERNEL);
 	if (!bus_node) {
-		MSM_BUS_ERR("%s:Bus node alloc failed\n", __func__);
-		kfree(bus_dev);
-		bus_dev = NULL;
-		goto exit_device_init;
+		ret = -ENOMEM;
+		goto err_device_init;
 	}
 	bus_dev = &bus_node->dev;
 	device_initialize(bus_dev);
@@ -982,47 +980,37 @@
 	node_info = devm_kzalloc(bus_dev,
 			sizeof(struct msm_bus_node_info_type), GFP_KERNEL);
 	if (!node_info) {
-		MSM_BUS_ERR("%s:Bus node info alloc failed\n", __func__);
-		devm_kfree(bus_dev, bus_node);
-		kfree(bus_dev);
-		bus_dev = NULL;
-		goto exit_device_init;
+		ret = -ENOMEM;
+		goto err_put_device;
 	}
 
 	bus_node->node_info = node_info;
 	bus_node->ap_owned = pdata->ap_owned;
 	bus_dev->of_node = pdata->of_node;
 
-	if (msm_bus_copy_node_info(pdata, bus_dev) < 0) {
-		devm_kfree(bus_dev, bus_node);
-		devm_kfree(bus_dev, node_info);
-		kfree(bus_dev);
-		bus_dev = NULL;
-		goto exit_device_init;
-	}
+	ret = msm_bus_copy_node_info(pdata, bus_dev);
+	if (ret)
+		goto err_put_device;
 
 	bus_dev->bus = &msm_bus_type;
 	dev_set_name(bus_dev, bus_node->node_info->name);
 
 	ret = device_add(bus_dev);
-	if (ret < 0) {
+	if (ret) {
 		MSM_BUS_ERR("%s: Error registering device %d",
 				__func__, pdata->node_info->id);
-		devm_kfree(bus_dev, bus_node);
-		devm_kfree(bus_dev, node_info->dev_connections);
-		devm_kfree(bus_dev, node_info->connections);
-		devm_kfree(bus_dev, node_info->black_connections);
-		devm_kfree(bus_dev, node_info->black_listed_connections);
-		devm_kfree(bus_dev, node_info);
-		kfree(bus_dev);
-		bus_dev = NULL;
-		goto exit_device_init;
+		goto err_put_device;
 	}
 	device_create_file(bus_dev, &dev_attr_bw);
 	INIT_LIST_HEAD(&bus_node->devlist);
-
-exit_device_init:
 	return bus_dev;
+
+err_put_device:
+	put_device(bus_dev);
+	bus_dev = NULL;
+	kfree(bus_node);
+err_device_init:
+	return ERR_PTR(ret);
 }
 
 static int msm_bus_setup_dev_conn(struct device *bus_dev, void *data)
@@ -1169,10 +1157,10 @@
 
 		node_dev = msm_bus_device_init(&pdata->info[i]);
 
-		if (!node_dev) {
+		if (IS_ERR(node_dev)) {
 			MSM_BUS_ERR("%s: Error during dev init for %d",
 				__func__, pdata->info[i].node_info->id);
-			ret = -ENXIO;
+			ret = PTR_ERR(node_dev);
 			goto exit_device_probe;
 		}
 
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
index c00749c..5a28e98 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
@@ -1471,7 +1471,7 @@
 	struct device *bus_dev = NULL;
 	struct msm_bus_node_device_type *bus_node = NULL;
 	struct msm_bus_node_info_type *node_info = NULL;
-	int ret = 0, i = 0;
+	int ret = -ENODEV, i = 0;
 
 	/**
 	* Init here so we can use devm calls
@@ -1479,10 +1479,8 @@
 
 	bus_node = kzalloc(sizeof(struct msm_bus_node_device_type), GFP_KERNEL);
 	if (!bus_node) {
-		MSM_BUS_ERR("%s:Bus node alloc failed\n", __func__);
-		kfree(bus_dev);
-		bus_dev = NULL;
-		goto exit_device_init;
+		ret = -ENOMEM;
+		goto err_device_init;
 	}
 	bus_dev = &bus_node->dev;
 	device_initialize(bus_dev);
@@ -1490,11 +1488,8 @@
 	node_info = devm_kzalloc(bus_dev,
 			sizeof(struct msm_bus_node_info_type), GFP_KERNEL);
 	if (!node_info) {
-		MSM_BUS_ERR("%s:Bus node info alloc failed\n", __func__);
-		devm_kfree(bus_dev, bus_node);
-		kfree(bus_dev);
-		bus_dev = NULL;
-		goto exit_device_init;
+		ret = -ENOMEM;
+		goto err_put_device;
 	}
 
 	bus_node->node_info = node_info;
@@ -1505,8 +1500,10 @@
 		bus_node->qos_bcms = devm_kzalloc(bus_dev,
 					(sizeof(struct qos_bcm_type) *
 					bus_node->num_qos_bcms), GFP_KERNEL);
-		if (!bus_node->qos_bcms)
-			goto exit_device_init;
+		if (!bus_node->qos_bcms) {
+			ret = -ENOMEM;
+			goto err_put_device;
+		}
 		for (i = 0; i < bus_node->num_qos_bcms; i++) {
 			bus_node->qos_bcms[i].qos_bcm_id =
 					pdata->qos_bcms[i].qos_bcm_id;
@@ -1519,36 +1516,29 @@
 
 	bus_dev->of_node = pdata->of_node;
 
-	if (msm_bus_copy_node_info(pdata, bus_dev) < 0) {
-		devm_kfree(bus_dev, bus_node);
-		devm_kfree(bus_dev, node_info);
-		kfree(bus_dev);
-		bus_dev = NULL;
-		goto exit_device_init;
-	}
+	ret = msm_bus_copy_node_info(pdata, bus_dev);
+	if (ret)
+		goto err_put_device;
 
 	bus_dev->bus = &msm_bus_type;
 	dev_set_name(bus_dev, bus_node->node_info->name);
 
 	ret = device_add(bus_dev);
-	if (ret < 0) {
+	if (ret) {
 		MSM_BUS_ERR("%s: Error registering device %d",
 				__func__, pdata->node_info->id);
-		devm_kfree(bus_dev, bus_node);
-		devm_kfree(bus_dev, node_info->dev_connections);
-		devm_kfree(bus_dev, node_info->connections);
-		devm_kfree(bus_dev, node_info->black_connections);
-		devm_kfree(bus_dev, node_info->black_listed_connections);
-		devm_kfree(bus_dev, node_info);
-		kfree(bus_dev);
-		bus_dev = NULL;
-		goto exit_device_init;
+		goto err_put_device;
 	}
 	device_create_file(bus_dev, &dev_attr_bw);
 	INIT_LIST_HEAD(&bus_node->devlist);
-
-exit_device_init:
 	return bus_dev;
+
+err_put_device:
+	put_device(bus_dev);
+	bus_dev = NULL;
+	kfree(bus_node);
+err_device_init:
+	return ERR_PTR(ret);
 }
 
 static int msm_bus_setup_dev_conn(struct device *bus_dev, void *data)
@@ -1736,10 +1726,10 @@
 
 		node_dev = msm_bus_device_init(&pdata->info[i]);
 
-		if (!node_dev) {
+		if (IS_ERR(node_dev)) {
 			MSM_BUS_ERR("%s: Error during dev init for %d",
 				__func__, pdata->info[i].node_info->id);
-			ret = -ENXIO;
+			ret = PTR_ERR(node_dev);
 			goto exit_device_probe;
 		}
 
diff --git a/drivers/soc/qcom/msm_glink_pkt.c b/drivers/soc/qcom/msm_glink_pkt.c
index 9a9b4df..4559f11 100644
--- a/drivers/soc/qcom/msm_glink_pkt.c
+++ b/drivers/soc/qcom/msm_glink_pkt.c
@@ -29,6 +29,7 @@
 #include <asm/ioctls.h>
 #include <linux/mm.h>
 #include <linux/of.h>
+#include <linux/vmalloc.h>
 #include <linux/ipc_logging.h>
 #include <linux/termios.h>
 
@@ -397,7 +398,10 @@
 	GLINK_PKT_INFO("%s(): priv[%p] pkt_priv[%p] ptr[%p]\n",
 					__func__, priv, pkt_priv, ptr);
 	/* Free Tx buffer allocated in glink_pkt_write */
-	kfree(ptr);
+	if (is_vmalloc_addr(ptr))
+		vfree_atomic(ptr);
+	else
+		kfree(ptr);
 }
 
 /**
@@ -775,8 +779,10 @@
 		__func__, devp->i, count);
 	data = kzalloc(count, GFP_KERNEL);
 	if (!data) {
-		GLINK_PKT_ERR("%s buffer allocation failed\n", __func__);
-		return -ENOMEM;
+		if (!strcmp(devp->open_cfg.edge, "bg"))
+			data = vzalloc(count);
+		if (!data)
+			return -ENOMEM;
 	}
 
 	ret = copy_from_user(data, buf, count);
@@ -784,14 +790,20 @@
 		GLINK_PKT_ERR(
 		"%s copy_from_user failed ret[%d] on dev id:%d size %zu\n",
 		 __func__, ret, devp->i, count);
-		kfree(data);
+		if (is_vmalloc_addr(data))
+			vfree_atomic(data);
+		else
+			kfree(data);
 		return -EFAULT;
 	}
 
 	ret = glink_tx(devp->handle, data, data, count, GLINK_TX_REQ_INTENT);
 	if (ret) {
 		GLINK_PKT_ERR("%s glink_tx failed ret[%d]\n", __func__, ret);
-		kfree(data);
+		if (is_vmalloc_addr(data))
+			vfree_atomic(data);
+		else
+			kfree(data);
 		return ret;
 	}
 
diff --git a/drivers/soc/qcom/msm_smem.c b/drivers/soc/qcom/msm_smem.c
index 1bbd751..959aab9 100644
--- a/drivers/soc/qcom/msm_smem.c
+++ b/drivers/soc/qcom/msm_smem.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
@@ -26,6 +26,7 @@
 #include <soc/qcom/subsystem_notif.h>
 #include <soc/qcom/subsystem_restart.h>
 #include <soc/qcom/ramdump.h>
+#include <soc/qcom/scm.h>
 
 #include <soc/qcom/smem.h>
 
@@ -1085,12 +1086,15 @@
 	void *handle;
 	struct restart_notifier_block *nb;
 
-	if (smem_dev)
-		smem_ramdump_dev = create_ramdump_device("smem", smem_dev);
-	if (IS_ERR_OR_NULL(smem_ramdump_dev)) {
-		LOG_ERR("%s: Unable to create smem ramdump device.\n",
-			__func__);
-		smem_ramdump_dev = NULL;
+	if (scm_is_secure_device()) {
+		if (smem_dev)
+			smem_ramdump_dev = create_ramdump_device("smem",
+								 smem_dev);
+		if (IS_ERR_OR_NULL(smem_ramdump_dev)) {
+			LOG_ERR("%s: Unable to create smem ramdump device.\n",
+				__func__);
+			smem_ramdump_dev = NULL;
+		}
 	}
 
 	for (i = 0; i < ARRAY_SIZE(restart_notifiers); i++) {
diff --git a/drivers/soc/qcom/qmp-debugfs-client.c b/drivers/soc/qcom/qmp-debugfs-client.c
index d7a473e..a327e031 100644
--- a/drivers/soc/qcom/qmp-debugfs-client.c
+++ b/drivers/soc/qcom/qmp-debugfs-client.c
@@ -116,8 +116,8 @@
 	.driver = {
 		.name = "debugfs-qmp-client",
 		.owner = THIS_MODULE,
+		.suppress_bind_attrs = true,
 		.of_match_table = aop_qmp_match_tbl,
 	},
 };
-
 builtin_platform_driver(aop_qmp_msg_driver);
diff --git a/drivers/soc/qcom/rpm-smd.c b/drivers/soc/qcom/rpm-smd.c
index c29cfcb..675551a 100644
--- a/drivers/soc/qcom/rpm-smd.c
+++ b/drivers/soc/qcom/rpm-smd.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
@@ -2138,6 +2138,7 @@
 	.driver = {
 		.name = "rpm-smd",
 		.owner = THIS_MODULE,
+		.suppress_bind_attrs = true,
 		.of_match_table = msm_rpm_match_table,
 	},
 };
diff --git a/drivers/soc/qcom/rpm_stats.c b/drivers/soc/qcom/rpm_stats.c
index a39856b..e7d9fac5 100644
--- a/drivers/soc/qcom/rpm_stats.c
+++ b/drivers/soc/qcom/rpm_stats.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
@@ -11,6 +11,8 @@
  *
  */
 
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
@@ -36,6 +38,7 @@
 struct msm_rpmstats_platform_data {
 	phys_addr_t phys_addr_base;
 	u32 phys_size;
+	u32 num_records;
 };
 
 struct msm_rpmstats_private_data {
@@ -43,7 +46,7 @@
 	u32 num_records;
 	u32 read_idx;
 	u32 len;
-	char buf[320];
+	char buf[480];
 	struct msm_rpmstats_platform_data *platform_data;
 };
 
@@ -61,6 +64,7 @@
 };
 
 struct msm_rpmstats_kobj_attr {
+	struct kobject *kobj;
 	struct kobj_attribute ka;
 	struct msm_rpmstats_platform_data *pd;
 };
@@ -175,29 +179,32 @@
 {
 	struct msm_rpmstats_private_data prvdata;
 	struct msm_rpmstats_platform_data *pdata = NULL;
+	ssize_t length;
 
 	pdata = GET_PDATA_OF_ATTR(attr);
 
 	prvdata.reg_base = ioremap_nocache(pdata->phys_addr_base,
 					pdata->phys_size);
 	if (!prvdata.reg_base) {
-		pr_err("%s: ERROR could not ioremap start=%pa, len=%u\n",
-			__func__, &pdata->phys_addr_base,
-			pdata->phys_size);
+		pr_err("ERROR could not ioremap start=%pa, len=%u\n",
+				&pdata->phys_addr_base, pdata->phys_size);
 		return -EBUSY;
 	}
 
 	prvdata.read_idx = prvdata.len = 0;
 	prvdata.platform_data = pdata;
-	prvdata.num_records = RPM_STATS_NUM_REC;
+	prvdata.num_records = pdata->num_records;
 
 	if (prvdata.read_idx < prvdata.num_records)
 		prvdata.len = msm_rpmstats_copy_stats(&prvdata);
 
-	return snprintf(buf, prvdata.len, "%s", prvdata.buf);
+	length = scnprintf(buf, prvdata.len, "%s", prvdata.buf);
+	iounmap(prvdata.reg_base);
+	return length;
 }
 
-static int msm_rpmstats_create_sysfs(struct msm_rpmstats_platform_data *pd)
+static int msm_rpmstats_create_sysfs(struct platform_device *pdev,
+				struct msm_rpmstats_platform_data *pd)
 {
 	struct kobject *rpmstats_kobj = NULL;
 	struct msm_rpmstats_kobj_attr *rpms_ka = NULL;
@@ -205,7 +212,7 @@
 
 	rpmstats_kobj = kobject_create_and_add("system_sleep", power_kobj);
 	if (!rpmstats_kobj) {
-		pr_err("%s: Cannot create rpmstats kobject\n", __func__);
+		pr_err("Cannot create rpmstats kobject\n");
 		ret = -ENOMEM;
 		goto fail;
 	}
@@ -217,6 +224,8 @@
 		goto fail;
 	}
 
+	rpms_ka->kobj = rpmstats_kobj;
+
 	sysfs_attr_init(&rpms_ka->ka.attr);
 	rpms_ka->pd = pd;
 	rpms_ka->ka.attr.mode = 0444;
@@ -225,6 +234,7 @@
 	rpms_ka->ka.store = NULL;
 
 	ret = sysfs_create_file(rpmstats_kobj, &rpms_ka->ka.attr);
+	platform_set_drvdata(pdev, rpms_ka);
 
 fail:
 	return ret;
@@ -233,28 +243,27 @@
 static int msm_rpmstats_probe(struct platform_device *pdev)
 {
 	struct msm_rpmstats_platform_data *pdata;
-	struct msm_rpmstats_platform_data *pd;
 	struct resource *res = NULL, *offset = NULL;
 	u32 offset_addr = 0;
 	void __iomem *phys_ptr = NULL;
+	char *key;
 
 	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
 	if (!pdata)
 		return -ENOMEM;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-							"phys_addr_base");
+	key = "phys_addr_base";
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
 	if (!res)
 		return -EINVAL;
 
-	offset = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-							"offset_addr");
+	key = "offset_addr";
+	offset = platform_get_resource_byname(pdev, IORESOURCE_MEM, key);
 	if (offset) {
 		/* Remap the rpm-stats pointer */
 		phys_ptr = ioremap_nocache(offset->start, SZ_4);
 		if (!phys_ptr) {
-			pr_err("%s: Failed to ioremap address: %x\n",
-					__func__, offset_addr);
+			pr_err("Failed to ioremap offset address\n");
 			return -ENODEV;
 		}
 		offset_addr = readl_relaxed(phys_ptr);
@@ -264,14 +273,33 @@
 	pdata->phys_addr_base  = res->start + offset_addr;
 	pdata->phys_size = resource_size(res);
 
-	if (pdev->dev.platform_data)
-		pd = pdev->dev.platform_data;
+	key = "qcom,num-records";
+	if (of_property_read_u32(pdev->dev.of_node, key, &pdata->num_records))
+		pdata->num_records = RPM_STATS_NUM_REC;
 
-	msm_rpmstats_create_sysfs(pdata);
+	msm_rpmstats_create_sysfs(pdev, pdata);
 
 	return 0;
 }
 
+static int msm_rpmstats_remove(struct platform_device *pdev)
+{
+	struct msm_rpmstats_kobj_attr *rpms_ka;
+
+	if (!pdev)
+		return -EINVAL;
+
+	rpms_ka = (struct msm_rpmstats_kobj_attr *)
+			platform_get_drvdata(pdev);
+
+	sysfs_remove_file(rpms_ka->kobj, &rpms_ka->ka.attr);
+	kobject_put(rpms_ka->kobj);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+
 static const struct of_device_id rpm_stats_table[] = {
 	{ .compatible = "qcom,rpm-stats" },
 	{ },
@@ -279,6 +307,7 @@
 
 static struct platform_driver msm_rpmstats_driver = {
 	.probe = msm_rpmstats_probe,
+	.remove = msm_rpmstats_remove,
 	.driver = {
 		.name = "msm_rpm_stat",
 		.owner = THIS_MODULE,
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 036990c..4f3c264 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -258,21 +258,28 @@
 	switch (state) {
 	case RPMH_ACTIVE_ONLY_STATE:
 	case RPMH_AWAKE_STATE:
-		if (req->sleep_val != UINT_MAX)
+		if (req->sleep_val != UINT_MAX) {
 			req->wake_val = cmd->data;
+			rpm->dirty = true;
+		}
 		break;
 	case RPMH_WAKE_ONLY_STATE:
-		req->wake_val = cmd->data;
+		if (req->wake_val != cmd->data) {
+			req->wake_val = cmd->data;
+			rpm->dirty = true;
+		}
 		break;
 	case RPMH_SLEEP_STATE:
-		req->sleep_val = cmd->data;
+		if (req->sleep_val != cmd->data) {
+			req->sleep_val = cmd->data;
+			rpm->dirty = true;
+		}
 		break;
 	default:
 		break;
 	};
 
 unlock:
-	rpm->dirty = true;
 	spin_unlock_irqrestore(&rpm->lock, flags);
 
 	return req;
diff --git a/drivers/soc/qcom/rpmh_master_stat.c b/drivers/soc/qcom/rpmh_master_stat.c
index 3a77ed8..80589de 100644
--- a/drivers/soc/qcom/rpmh_master_stat.c
+++ b/drivers/soc/qcom/rpmh_master_stat.c
@@ -265,6 +265,7 @@
 	kobject_put(prvdata->kobj);
 	platform_set_drvdata(pdev, NULL);
 	iounmap(rpmh_unit_base);
+	rpmh_unit_base = NULL;
 
 	return 0;
 }
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index dc45b20..eb3a3b9 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.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
@@ -98,6 +98,7 @@
  */
 struct qmi_client_info {
 	int instance_id;
+	char service_path[SERVREG_NOTIF_NAME_LENGTH];
 	enum pd_subsys_state subsys_state;
 	struct work_struct svc_arrive;
 	struct work_struct svc_exit;
@@ -390,7 +391,8 @@
 	mutex_lock(&notif_add_lock);
 	mutex_lock(&service_list_lock);
 	list_for_each_entry(service_notif, &service_list, list) {
-		if (service_notif->instance_id == data->instance_id) {
+		if (service_notif->instance_id == data->instance_id && !strcmp
+			(service_notif->service_path, data->service_path)) {
 			enum pd_subsys_state state = ROOT_PD_UP;
 			rc = register_notif_listener(service_notif, data,
 								&curr_state);
@@ -424,7 +426,8 @@
 	mutex_lock(&notif_add_lock);
 	mutex_lock(&service_list_lock);
 	list_for_each_entry(service_notif, &service_list, list) {
-		if (service_notif->instance_id == data->instance_id) {
+		if (service_notif->instance_id == data->instance_id && !strcmp
+			(data->service_path, service_notif->service_path)) {
 			rc = service_notif_queue_notification(service_notif,
 					SERVREG_NOTIF_SERVICE_STATE_DOWN_V01,
 					&state);
@@ -534,7 +537,8 @@
 	 */
 	mutex_lock(&qmi_list_lock);
 	list_for_each_entry(tmp, &qmi_client_list, list) {
-		if (tmp->instance_id == instance_id) {
+		if (tmp->instance_id == instance_id && !strcmp
+				(tmp->service_path, service_path)) {
 			if (tmp->service_connected) {
 				rc = register_notif_listener(service_notif, tmp,
 								curr_state);
@@ -560,6 +564,8 @@
 	}
 
 	qmi_data->instance_id = instance_id;
+	strlcpy(qmi_data->service_path, service_path,
+		ARRAY_SIZE(service_notif->service_path));
 	init_rwsem(&qmi_data->qmi_client_handle_rwlock);
 	qmi_data->clnt_handle = NULL;
 	qmi_data->notifier.notifier_call = service_event_notify;
@@ -680,7 +686,8 @@
 	int rc = 0;
 
 	list_for_each_entry(tmp, &qmi_client_list, list) {
-		if (tmp->instance_id == instance_id) {
+		if (tmp->instance_id == instance_id && !strcmp
+				(tmp->service_path, service_path)) {
 			if (tmp->service_connected) {
 				pr_info("Restarting service %s, instance-id %d\n",
 						service_path, instance_id);
diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c
index d568014..f2597e3 100644
--- a/drivers/soc/qcom/spcom.c
+++ b/drivers/soc/qcom/spcom.c
@@ -2764,7 +2764,7 @@
 	ret = spcom_register_chardev();
 	if (ret) {
 		pr_err("create character device failed.\n");
-		goto fail_reg_chardev;
+		goto fail_while_chardev_reg;
 	}
 
 	link_info.glink_link_state_notif_cb = spcom_link_state_notif_cb;
@@ -2802,6 +2802,7 @@
 fail_reg_chardev:
 	pr_err("Failed to init driver.\n");
 	spcom_unregister_chrdev();
+fail_while_chardev_reg:
 	kfree(dev);
 	spcom_dev = NULL;
 
diff --git a/drivers/soc/qcom/system_pm.c b/drivers/soc/qcom/system_pm.c
index 1befdcf..9ef685b 100644
--- a/drivers/soc/qcom/system_pm.c
+++ b/drivers/soc/qcom/system_pm.c
@@ -106,6 +106,7 @@
 	.probe = sys_pm_probe,
 	.driver = {
 		.name = KBUILD_MODNAME,
+		.suppress_bind_attrs = true,
 		.of_match_table = sys_pm_drv_match,
 	},
 };
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index 880fda4..22884ae 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -155,6 +155,7 @@
 	int num_xfers;
 	void *ipc;
 	bool shared_se;
+	bool dis_autosuspend;
 };
 
 static struct spi_master *get_spi_master(struct device *dev)
@@ -747,7 +748,7 @@
 static int spi_geni_prepare_transfer_hardware(struct spi_master *spi)
 {
 	struct spi_geni_master *mas = spi_master_get_devdata(spi);
-	int ret = 0;
+	int ret = 0, count = 0;
 	u32 max_speed = spi->cur_msg->spi->max_speed_hz;
 	struct se_geni_rsc *rsc = &mas->spi_rsc;
 
@@ -774,7 +775,12 @@
 	} else {
 		ret = 0;
 	}
-
+	if (mas->dis_autosuspend) {
+		count = atomic_read(&mas->dev->power.usage_count);
+		if (count <= 0)
+			GENI_SE_ERR(mas->ipc, false, NULL,
+				"resume usage count mismatch:%d", count);
+	}
 	if (unlikely(!mas->setup)) {
 		int proto = get_se_proto(mas->base);
 		unsigned int major;
@@ -863,6 +869,9 @@
 		mas->shared_se =
 			(geni_read_reg(mas->base, GENI_IF_FIFO_DISABLE_RO) &
 							FIFO_IF_DISABLE);
+		if (mas->dis_autosuspend)
+			GENI_SE_DBG(mas->ipc, false, mas->dev,
+					"Auto Suspend is disabled\n");
 	}
 exit_prepare_transfer_hardware:
 	return ret;
@@ -871,7 +880,7 @@
 static int spi_geni_unprepare_transfer_hardware(struct spi_master *spi)
 {
 	struct spi_geni_master *mas = spi_master_get_devdata(spi);
-
+	int count = 0;
 	if (mas->shared_se) {
 		struct se_geni_rsc *rsc;
 		int ret = 0;
@@ -884,8 +893,16 @@
 			"%s: Error %d pinctrl_select_state\n", __func__, ret);
 	}
 
-	pm_runtime_mark_last_busy(mas->dev);
-	pm_runtime_put_autosuspend(mas->dev);
+	if (mas->dis_autosuspend) {
+		pm_runtime_put_sync(mas->dev);
+		count = atomic_read(&mas->dev->power.usage_count);
+		if (count < 0)
+			GENI_SE_ERR(mas->ipc, false, NULL,
+				"suspend usage count mismatch:%d", count);
+	} else {
+		pm_runtime_mark_last_busy(mas->dev);
+		pm_runtime_put_autosuspend(mas->dev);
+	}
 	return 0;
 }
 
@@ -1350,6 +1367,7 @@
 		goto spi_geni_probe_err;
 	}
 
+	geni_mas->spi_rsc.ctrl_dev = geni_mas->dev;
 	rsc->geni_pinctrl = devm_pinctrl_get(&pdev->dev);
 	if (IS_ERR_OR_NULL(rsc->geni_pinctrl)) {
 		dev_err(&pdev->dev, "No pinctrl config specified!\n");
@@ -1411,7 +1429,9 @@
 	rt_pri = of_property_read_bool(pdev->dev.of_node, "qcom,rt");
 	if (rt_pri)
 		spi->rt = true;
-
+	geni_mas->dis_autosuspend =
+		of_property_read_bool(pdev->dev.of_node,
+				"qcom,disable-autosuspend");
 	geni_mas->phys_addr = res->start;
 	geni_mas->size = resource_size(res);
 	geni_mas->base = devm_ioremap(&pdev->dev, res->start,
@@ -1451,8 +1471,11 @@
 	init_completion(&geni_mas->tx_cb);
 	init_completion(&geni_mas->rx_cb);
 	pm_runtime_set_suspended(&pdev->dev);
-	pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTO_SUSPEND_DELAY);
-	pm_runtime_use_autosuspend(&pdev->dev);
+	if (!geni_mas->dis_autosuspend) {
+		pm_runtime_set_autosuspend_delay(&pdev->dev,
+					SPI_AUTO_SUSPEND_DELAY);
+		pm_runtime_use_autosuspend(&pdev->dev);
+	}
 	pm_runtime_enable(&pdev->dev);
 	ret = spi_register_master(spi);
 	if (ret) {
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 2e05046..c7d3fa9 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -696,6 +696,7 @@
 static const struct of_device_id spidev_dt_ids[] = {
 	{ .compatible = "rohm,dh2228fv" },
 	{ .compatible = "lineartechnology,ltc2488" },
+	{ .compatible = "qcom,spi-msm-slave" },
 	{},
 };
 MODULE_DEVICE_TABLE(of, spidev_dt_ids);
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 94a405f..9995a84 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -868,7 +868,7 @@
 		struct ion_handle *handle = rb_entry(n, struct ion_handle,
 						     node);
 
-		seq_printf(s, "%16.16s: %16zx : %16d : %12p",
+		seq_printf(s, "%16.16s: %16zx : %16d : %12pK",
 			   handle->buffer->heap->name,
 			   handle->buffer->size,
 			   atomic_read(&handle->ref.refcount),
diff --git a/drivers/thermal/msm-tsens.c b/drivers/thermal/msm-tsens.c
index 6241ef6..a4c89e0 100644
--- a/drivers/thermal/msm-tsens.c
+++ b/drivers/thermal/msm-tsens.c
@@ -220,6 +220,10 @@
 
 static int tsens_tm_remove(struct platform_device *pdev)
 {
+	struct tsens_device *tmdev = platform_get_drvdata(pdev);
+
+	if (tmdev)
+		list_del(&tmdev->list);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
@@ -278,6 +282,7 @@
 		.name = "msm-tsens",
 		.owner = THIS_MODULE,
 		.of_match_table = tsens_table,
+		.suppress_bind_attrs = true,
 	},
 };
 
diff --git a/drivers/thermal/qpnp-temp-alarm.c b/drivers/thermal/qpnp-temp-alarm.c
index 7398b7b..e8a8907 100644
--- a/drivers/thermal/qpnp-temp-alarm.c
+++ b/drivers/thermal/qpnp-temp-alarm.c
@@ -586,6 +586,20 @@
 	return 0;
 }
 
+static void qpnp_tm_shutdown(struct platform_device *pdev)
+{
+	struct qpnp_tm_chip *chip = dev_get_drvdata(&pdev->dev);
+	int rc;
+	u8 reg;
+
+	/* configure TEMP_ALARM to follow HW_EN */
+	reg = ALARM_CTRL_FOLLOW_HW_ENABLE;
+	rc = qpnp_tm_write(chip, QPNP_TM_REG_ALARM_CTRL, &reg, 1);
+	if (rc)
+		pr_err("Failed to cfg. TEMP_ALARM to follow HW_EN rc=%d\n", rc);
+}
+
+
 static const struct of_device_id qpnp_tm_match_table[] = {
 	{ .compatible = QPNP_TM_DRIVER_NAME, },
 	{}
@@ -604,6 +618,7 @@
 	},
 	.probe	  = qpnp_tm_probe,
 	.remove	  = qpnp_tm_remove,
+	.shutdown = qpnp_tm_shutdown,
 	.id_table = qpnp_tm_id,
 };
 
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 4e895ee..6352d54 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -1242,56 +1242,30 @@
 	unsigned int xmit_size;
 	unsigned int fifo_width_bytes =
 		(uart_console(uport) ? 1 : (msm_port->tx_fifo_width >> 3));
-	unsigned int geni_m_irq_en;
 	int temp_tail = 0;
 
 	xmit_size = uart_circ_chars_pending(xmit);
 	tx_fifo_status = geni_read_reg_nolog(uport->membase,
 					SE_GENI_TX_FIFO_STATUS);
 	/* Both FIFO and framework buffer are drained */
-	if ((xmit_size == msm_port->xmit_size) && !tx_fifo_status) {
-		/*
-		 * This will balance out the power vote put in during start_tx
-		 * allowing the device to suspend.
-		 */
-		if (!uart_console(uport)) {
-			IPC_LOG_MSG(msm_port->ipc_log_misc,
-				"%s.Power Off.\n", __func__);
-			msm_geni_serial_power_off(uport);
-		}
-		msm_port->xmit_size = 0;
-		uart_circ_clear(xmit);
+	if (!xmit_size && !tx_fifo_status) {
 		msm_geni_serial_stop_tx(uport);
 		goto exit_handle_tx;
 	}
-	xmit_size -= msm_port->xmit_size;
-
-	if (!uart_console(uport)) {
-		geni_m_irq_en = geni_read_reg_nolog(uport->membase,
-							SE_GENI_M_IRQ_EN);
-		geni_m_irq_en &= ~(M_TX_FIFO_WATERMARK_EN);
-		geni_write_reg_nolog(0, uport->membase,
-						SE_GENI_TX_WATERMARK_REG);
-		geni_write_reg_nolog(geni_m_irq_en, uport->membase,
-							SE_GENI_M_IRQ_EN);
-	}
 
 	avail_fifo_bytes = (msm_port->tx_fifo_depth - msm_port->tx_wm) *
 							fifo_width_bytes;
-	temp_tail = (xmit->tail + msm_port->xmit_size) & (UART_XMIT_SIZE - 1);
+	temp_tail = xmit->tail & (UART_XMIT_SIZE - 1);
+
 	if (xmit_size > (UART_XMIT_SIZE - temp_tail))
 		xmit_size = (UART_XMIT_SIZE - temp_tail);
 	if (xmit_size > avail_fifo_bytes)
 		xmit_size = avail_fifo_bytes;
-
 	if (!xmit_size)
 		goto exit_handle_tx;
 
 	msm_geni_serial_setup_tx(uport, xmit_size);
-
 	bytes_remaining = xmit_size;
-	dump_ipc(msm_port->ipc_log_tx, "Tx", (char *)&xmit->buf[temp_tail], 0,
-								xmit_size);
 	while (i < xmit_size) {
 		unsigned int tx_bytes;
 		unsigned int buf = 0;
@@ -1304,17 +1278,18 @@
 			buf |= (xmit->buf[temp_tail + c] << (c * 8));
 		geni_write_reg_nolog(buf, uport->membase, SE_GENI_TX_FIFOn);
 		i += tx_bytes;
-		temp_tail = (temp_tail + tx_bytes) & (UART_XMIT_SIZE - 1);
-		uport->icount.tx += tx_bytes;
 		bytes_remaining -= tx_bytes;
+		uport->icount.tx += tx_bytes;
+		temp_tail += tx_bytes;
 		/* Ensure FIFO write goes through */
 		wmb();
 	}
+	xmit->tail = temp_tail & (UART_XMIT_SIZE - 1);
 	if (uart_console(uport))
 		msm_geni_serial_poll_cancel_tx(uport);
-	msm_port->xmit_size += xmit_size;
 exit_handle_tx:
-	uart_write_wakeup(uport);
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(uport);
 	return ret;
 }
 
@@ -2427,6 +2402,8 @@
 	if (ret)
 		goto exit_geni_serial_probe;
 
+	dev_port->serial_rsc.ctrl_dev = &pdev->dev;
+
 	if (of_property_read_u32(pdev->dev.of_node, "qcom,wakeup-byte",
 					&wake_char)) {
 		dev_dbg(&pdev->dev, "No Wakeup byte specified\n");
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 876679a..f794741 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -763,18 +763,21 @@
 		return;
 
 	if (dev->rawdescriptors) {
-		for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
+		for (i = 0; i < dev->descriptor.bNumConfigurations &&
+				i < USB_MAXCONFIG; i++)
 			kfree(dev->rawdescriptors[i]);
 
 		kfree(dev->rawdescriptors);
 		dev->rawdescriptors = NULL;
 	}
 
-	for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
+	for (c = 0; c < dev->descriptor.bNumConfigurations &&
+			c < USB_MAXCONFIG; c++) {
 		struct usb_host_config *cf = &dev->config[c];
 
 		kfree(cf->string);
-		for (i = 0; i < cf->desc.bNumInterfaces; i++) {
+		for (i = 0; i < cf->desc.bNumInterfaces &&
+				i < USB_MAXINTERFACES; i++) {
 			if (cf->intf_cache[i])
 				kref_put(&cf->intf_cache[i]->ref,
 					  usb_release_interface_cache);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index bf1baf6..f99b2bd 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -255,6 +255,7 @@
 	struct notifier_block	id_nb;
 	struct notifier_block	eud_event_nb;
 	struct notifier_block	host_restart_nb;
+	struct notifier_block	self_power_nb;
 
 	struct notifier_block	host_nb;
 	bool			xhci_ss_compliance_enable;
@@ -296,6 +297,8 @@
 						unsigned int value);
 static int dwc3_restart_usb_host_mode(struct notifier_block *nb,
 					unsigned long event, void *ptr);
+static int dwc3_notify_pd_status(struct notifier_block *nb,
+				unsigned long event, void *ptr);
 
 /**
  *
@@ -3041,12 +3044,19 @@
 	if (!IS_ERR(edev)) {
 		mdwc->extcon_vbus = edev;
 		mdwc->vbus_nb.notifier_call = dwc3_msm_vbus_notifier;
+		mdwc->self_power_nb.notifier_call = dwc3_notify_pd_status;
 		ret = extcon_register_notifier(edev, EXTCON_USB,
 				&mdwc->vbus_nb);
 		if (ret < 0) {
 			dev_err(mdwc->dev, "failed to register notifier for USB\n");
 			return ret;
 		}
+		ret = extcon_register_blocking_notifier(edev, EXTCON_USB,
+							&mdwc->self_power_nb);
+		if (ret < 0) {
+			dev_err(mdwc->dev, "failed to register blocking notifier\n");
+			goto err1;
+		}
 	}
 
 	/*
@@ -3748,7 +3758,6 @@
 		mdwc->hs_phy->flags &= ~PHY_HOST_MODE;
 	of_platform_depopulate(&pdev->dev);
 
-	dbg_event(0xFF, "Remov put", 0);
 	pm_runtime_disable(mdwc->dev);
 	pm_runtime_barrier(mdwc->dev);
 	pm_runtime_put_sync(mdwc->dev);
@@ -4149,6 +4158,28 @@
 	return 0;
 }
 
+static int dwc3_notify_pd_status(struct notifier_block *nb,
+				unsigned long event, void *ptr)
+{
+	struct dwc3_msm *mdwc;
+	struct dwc3 *dwc;
+	int ret = 0;
+	union extcon_property_value val;
+
+	mdwc = container_of(nb, struct dwc3_msm, self_power_nb);
+	dwc = platform_get_drvdata(mdwc->dwc3);
+
+	ret = extcon_get_property(mdwc->extcon_vbus, EXTCON_USB,
+					EXTCON_PROP_USB_PD_CONTRACT, &val);
+
+	if (!ret)
+		dwc->gadget.self_powered = val.intval;
+	else
+		dwc->gadget.self_powered = 0;
+
+	return ret;
+}
+
 /* speed: 0 - USB_SPEED_HIGH, 1 - USB_SPEED_SUPER */
 static int dwc3_restart_usb_host_mode(struct notifier_block *nb,
 				unsigned long event, void *ptr)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index f878b8d1..e6c89a3 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1971,7 +1971,7 @@
 	if (dwc3_gadget_is_suspended(dwc)) {
 		pr_debug("USB bus is suspended. Scheduling wakeup and returning -EAGAIN.\n");
 		dwc3_gadget_wakeup(&dwc->gadget);
-		return -EAGAIN;
+		return -EACCES;
 	}
 
 	if (dwc->revision < DWC3_REVISION_220A) {
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 3de95d5..32729c6 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -490,11 +490,17 @@
 
 	spin_lock_irqsave(&func->config->cdev->lock, flags);
 	ret = usb_func_wakeup_int(func);
-	if (ret == -EAGAIN) {
+	if (ret == -EACCES) {
 		DBG(func->config->cdev,
 			"Function wakeup for %s could not complete due to suspend state. Delayed until after bus resume.\n",
 			func->name ? func->name : "");
 		ret = 0;
+		func->func_wakeup_pending = 1;
+	} else if (ret == -EAGAIN) {
+		DBG(func->config->cdev,
+			"Function wakeup for %s sent.\n",
+			func->name ? func->name : "");
+		ret = 0;
 	} else if (ret < 0 && ret != -ENOTSUPP) {
 		ERROR(func->config->cdev,
 			"Failed to wake function %s from suspend state. ret=%d. Canceling USB request.\n",
@@ -524,7 +530,12 @@
 	gadget = func->config->cdev->gadget;
 	if (func->func_is_suspended && func->func_wakeup_allowed) {
 		ret = usb_gadget_func_wakeup(gadget, func->intf_id);
-		if (ret == -EAGAIN) {
+		if (ret == -EACCES) {
+			pr_debug("bus suspended func wakeup for %s delayed until bus resume.\n",
+				func->name ? func->name : "");
+			func->func_wakeup_pending = 1;
+			ret = -EAGAIN;
+		} else if (ret == -EAGAIN) {
 			pr_debug("bus suspended func wakeup for %s delayed until bus resume.\n",
 				func->name ? func->name : "");
 		} else if (ret < 0 && ret != -ENOTSUPP) {
@@ -583,6 +594,10 @@
 	c->iConfiguration = config->iConfiguration;
 	c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes;
 	c->bMaxPower = encode_bMaxPower(speed, config);
+	if (config->cdev->gadget->self_powered) {
+		c->bmAttributes |= USB_CONFIG_ATT_SELFPOWER;
+		c->bMaxPower = 0;
+	}
 
 	/* There may be e.g. OTG descriptors */
 	if (config->descriptors) {
@@ -2471,22 +2486,24 @@
 	spin_lock_irqsave(&cdev->lock, flags);
 	if (cdev->config) {
 		list_for_each_entry(f, &cdev->config->functions, list) {
-			ret = usb_func_wakeup_int(f);
-			if (ret) {
-				if (ret == -EAGAIN) {
-					ERROR(f->config->cdev,
-						"Function wakeup for %s could not complete due to suspend state.\n",
-						f->name ? f->name : "");
-					break;
-				} else if (ret != -ENOTSUPP) {
-					ERROR(f->config->cdev,
-						"Failed to wake function %s from suspend state. ret=%d. Canceling USB request.\n",
-						f->name ? f->name : "",
-						ret);
+			if (f->func_wakeup_pending) {
+				ret = usb_func_wakeup_int(f);
+				if (ret) {
+					if (ret == -EAGAIN) {
+						ERROR(f->config->cdev,
+							"Function wakeup for %s could not complete due to suspend state.\n",
+							f->name ? f->name : "");
+					} else if (ret != -ENOTSUPP) {
+						ERROR(f->config->cdev,
+							"Failed to wake function %s from suspend state. ret=%d. Canceling USB request.\n",
+							f->name ? f->name : "",
+							ret);
+					}
 				}
+				f->func_wakeup_pending = 0;
 			}
 
-			if (f->resume)
+			if (gadget->speed != USB_SPEED_SUPER && f->resume)
 				f->resume(f);
 		}
 
diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c
index a7166e2..afa62e8 100644
--- a/drivers/usb/gadget/function/f_cdev.c
+++ b/drivers/usb/gadget/function/f_cdev.c
@@ -349,6 +349,23 @@
 	return container_of(cser, struct f_cdev, port_usb);
 }
 
+static unsigned int convert_uart_sigs_to_acm(unsigned int uart_sig)
+{
+	unsigned int acm_sig = 0;
+
+	/* should this needs to be in calling functions ??? */
+	uart_sig &= (TIOCM_RI | TIOCM_CD | TIOCM_DSR);
+
+	if (uart_sig & TIOCM_RI)
+		acm_sig |= ACM_CTRL_RI;
+	if (uart_sig & TIOCM_CD)
+		acm_sig |= ACM_CTRL_DCD;
+	if (uart_sig & TIOCM_DSR)
+		acm_sig |= ACM_CTRL_DSR;
+
+	return acm_sig;
+}
+
 static unsigned int convert_acm_sigs_to_uart(unsigned int acm_sig)
 {
 	unsigned int uart_sig = 0;
@@ -1333,6 +1350,12 @@
 
 	if (cser->serial_state & TIOCM_RI)
 		result |= TIOCM_RI;
+
+	if (cser->serial_state & TIOCM_DSR)
+		result |= TIOCM_DSR;
+
+	if (cser->serial_state & TIOCM_CTS)
+		result |= TIOCM_CTS;
 	return result;
 }
 
@@ -1373,6 +1396,24 @@
 		}
 	}
 
+	if (set & TIOCM_DSR)
+		cser->serial_state |= TIOCM_DSR;
+
+	if (clear & TIOCM_DSR)
+		cser->serial_state &= ~TIOCM_DSR;
+
+	if (set & TIOCM_CTS) {
+		if (cser->send_break) {
+			cser->serial_state |= TIOCM_CTS;
+			status = cser->send_break(cser, 0);
+		}
+	}
+	if (clear & TIOCM_CTS) {
+		if (cser->send_break) {
+			cser->serial_state &= ~TIOCM_CTS;
+			status = cser->send_break(cser, 1);
+		}
+	}
 	return status;
 }
 
@@ -1423,7 +1464,9 @@
 {
 	int temp;
 	struct f_cdev *port = fport;
+	struct cserial *cser;
 
+	cser = &port->port_usb;
 	if (!port) {
 		pr_err("port is null\n");
 		return;
@@ -1439,6 +1482,17 @@
 	port->cbits_to_modem = temp;
 	port->cbits_updated = true;
 
+	 /* if DTR is high, update latest modem info to laptop */
+	if (port->cbits_to_modem & TIOCM_DTR) {
+		unsigned int result;
+		unsigned int cbits_to_laptop;
+
+		result = f_cdev_tiocmget(port);
+		cbits_to_laptop = convert_uart_sigs_to_acm(result);
+		if (cser->send_modem_ctrl_bits)
+			cser->send_modem_ctrl_bits(cser, cbits_to_laptop);
+	}
+
 	wake_up(&port->read_wq);
 }
 
@@ -1488,8 +1542,10 @@
 
 void usb_cser_disconnect(struct f_cdev *port)
 {
+	struct cserial *cser;
 	unsigned long flags;
 
+	cser = &port->port_usb;
 	usb_cser_stop_io(port);
 
 	/* lower DTR to modem */
@@ -1497,6 +1553,7 @@
 
 	spin_lock_irqsave(&port->port_lock, flags);
 	port->is_connected = false;
+	cser->notify_modem = NULL;
 	port->nbytes_from_host = port->nbytes_to_host = 0;
 	port->nbytes_to_port_bridge = 0;
 	spin_unlock_irqrestore(&port->port_lock, flags);
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index b9c19d4..6fe4fc5 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -997,7 +997,6 @@
 	struct ffs_epfile *epfile = file->private_data;
 	struct usb_request *req;
 	struct ffs_ep *ep;
-	struct ffs_data *ffs = epfile->ffs;
 	char *data = NULL;
 	ssize_t ret, data_len = -EINVAL;
 	int halt;
@@ -1096,7 +1095,7 @@
 			data_len = usb_ep_align_maybe(gadget, ep->ep, data_len);
 		spin_unlock_irq(&epfile->ffs->eps_lock);
 
-		extra_buf_alloc = ffs->gadget->extra_buf_alloc;
+		extra_buf_alloc = gadget->extra_buf_alloc;
 		if (!io_data->read)
 			data = kmalloc(data_len + extra_buf_alloc,
 					GFP_KERNEL);
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 7170dc9..0c4baf2 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -24,6 +24,16 @@
 module_param(qti_packet_debug, bool, 0644);
 MODULE_PARM_DESC(qti_packet_debug, "Print QTI Packet's Raw Data");
 
+/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */
+static char *gsi_dev_addr;
+module_param(gsi_dev_addr, charp, 0644);
+MODULE_PARM_DESC(gsi_dev_addr, "QC Device Ethernet Address");
+
+/* this address is invisible to ifconfig */
+static char *gsi_host_addr;
+module_param(gsi_host_addr, charp, 0644);
+MODULE_PARM_DESC(gsi_host_addr, "QC Host Ethernet Address");
+
 static struct workqueue_struct *ipa_usb_wq;
 static struct f_gsi *__gsi[USB_PROT_MAX];
 static void *ipc_log_ctxt;
@@ -211,26 +221,23 @@
 	return ret;
 }
 
-static void debugfs_rw_timer_func(unsigned long arg)
+static void gsi_rw_timer_func(unsigned long arg)
 {
-	struct f_gsi *gsi;
-
-	gsi = (struct f_gsi *)arg;
+	struct f_gsi *gsi = (struct f_gsi *)arg;
 
 	if (!atomic_read(&gsi->connected)) {
-		log_event_dbg("%s: gsi not connected..del timer\n", __func__);
-		gsi->debugfs_rw_enable = 0;
-		del_timer(&gsi->debugfs_rw_timer);
+		log_event_dbg("%s: gsi not connected.. bail-out\n", __func__);
+		gsi->debugfs_rw_timer_enable = 0;
 		return;
 	}
 
 	log_event_dbg("%s: calling gsi_wakeup_host\n", __func__);
 	gsi_wakeup_host(gsi);
 
-	if (gsi->debugfs_rw_enable) {
+	if (gsi->debugfs_rw_timer_enable) {
 		log_event_dbg("%s: re-arm the timer\n", __func__);
-		mod_timer(&gsi->debugfs_rw_timer,
-			jiffies + msecs_to_jiffies(gsi->debugfs_rw_interval));
+		mod_timer(&gsi->gsi_rw_timer,
+			jiffies + msecs_to_jiffies(gsi->gsi_rw_timer_interval));
 	}
 }
 
@@ -279,7 +286,7 @@
 		goto err;
 	}
 
-	if (gsi->debugfs_rw_enable == !!input) {
+	if (gsi->debugfs_rw_timer_enable == !!input) {
 		if (!!input)
 			log_event_dbg("%s: RW already enabled\n", __func__);
 		else
@@ -287,21 +294,14 @@
 		goto err;
 	}
 
-	gsi->debugfs_rw_enable = !!input;
-	if (gsi->debugfs_rw_enable) {
-		init_timer(&gsi->debugfs_rw_timer);
-		gsi->debugfs_rw_timer.data = (unsigned long) gsi;
-		gsi->debugfs_rw_timer.function = debugfs_rw_timer_func;
+	gsi->debugfs_rw_timer_enable = !!input;
 
-		/* Use default remote wakeup timer interval if it is not set */
-		if (!gsi->debugfs_rw_interval)
-			gsi->debugfs_rw_interval = DEFAULT_RW_TIMER_INTERVAL;
-		gsi->debugfs_rw_timer.expires = jiffies +
-				msecs_to_jiffies(gsi->debugfs_rw_interval);
-		add_timer(&gsi->debugfs_rw_timer);
+	if (gsi->debugfs_rw_timer_enable) {
+		mod_timer(&gsi->gsi_rw_timer, jiffies +
+			  msecs_to_jiffies(gsi->gsi_rw_timer_interval));
 		log_event_dbg("%s: timer initialized\n", __func__);
 	} else {
-		del_timer_sync(&gsi->debugfs_rw_timer);
+		del_timer_sync(&gsi->gsi_rw_timer);
 		log_event_dbg("%s: timer deleted\n", __func__);
 	}
 
@@ -320,7 +320,7 @@
 		return 0;
 	}
 
-	seq_printf(s, "%d\n", gsi->debugfs_rw_enable);
+	seq_printf(s, "%d\n", gsi->debugfs_rw_timer_enable);
 
 	return 0;
 }
@@ -368,7 +368,7 @@
 		goto err;
 	}
 
-	gsi->debugfs_rw_interval = timer_val;
+	gsi->gsi_rw_timer_interval = timer_val;
 err:
 	return count;
 }
@@ -376,7 +376,6 @@
 static int usb_gsi_rw_timer_show(struct seq_file *s, void *unused)
 {
 	struct f_gsi *gsi;
-	unsigned int timer_interval;
 
 	gsi = get_connected_gsi();
 	if (!gsi) {
@@ -384,11 +383,7 @@
 		return 0;
 	}
 
-	timer_interval = DEFAULT_RW_TIMER_INTERVAL;
-	if (gsi->debugfs_rw_interval)
-		timer_interval = gsi->debugfs_rw_interval;
-
-	seq_printf(s, "%ums\n", timer_interval);
+	seq_printf(s, "%ums\n", gsi->gsi_rw_timer_interval);
 
 	return 0;
 }
@@ -2435,6 +2430,9 @@
 
 	atomic_set(&gsi->connected, 0);
 
+	del_timer(&gsi->gsi_rw_timer);
+	gsi->debugfs_rw_timer_enable = 0;
+
 	if (gsi->prot_id == USB_PROT_RNDIS_IPA)
 		rndis_uninit(gsi->params);
 
@@ -2505,6 +2503,16 @@
 	post_event(&gsi->d_port, EVT_SUSPEND);
 	queue_work(gsi->d_port.ipa_usb_wq, &gsi->d_port.usb_ipa_w);
 	log_event_dbg("gsi suspended");
+
+	/*
+	 * If host suspended bus without receiving notification request then
+	 * initiate remote-wakeup. As driver won't be able to do it later since
+	 * notification request is already queued.
+	 */
+	if (gsi->c_port.notify_req_queued && usb_gsi_remote_wakeup_allowed(f)) {
+		mod_timer(&gsi->gsi_rw_timer, jiffies + msecs_to_jiffies(2000));
+		log_event_dbg("%s: pending response, arm rw_timer\n", __func__);
+	}
 }
 
 static void gsi_resume(struct usb_function *f)
@@ -2522,6 +2530,10 @@
 		f->func_is_suspended)
 		return;
 
+	/* Keep timer enabled if user enabled using debugfs */
+	if (!gsi->debugfs_rw_timer_enable)
+		del_timer(&gsi->gsi_rw_timer);
+
 	if (gsi->c_port.notify && !gsi->c_port.notify->desc)
 		config_ep_by_speed(cdev->gadget, f, gsi->c_port.notify);
 
@@ -2553,6 +2565,11 @@
 static int gsi_get_status(struct usb_function *f)
 {
 	unsigned int remote_wakeup_en_status = f->func_wakeup_allowed ? 1 : 0;
+	struct f_gsi *gsi = func_to_gsi(f);
+
+	/* Disable function remote wake-up for DPL interface */
+	if (gsi->prot_id == USB_PROT_DIAG_IPA)
+		return 0;
 
 	return (remote_wakeup_en_status << FUNC_WAKEUP_ENABLE_SHIFT) |
 		(1 << FUNC_WAKEUP_CAPABLE_SHIFT);
@@ -2595,10 +2612,6 @@
 	struct usb_function *f = &gsi->function;
 	int status;
 
-	/* maybe allocate device-global string IDs */
-	if (info->string_defs[0].id != 0)
-		goto skip_string_id_alloc;
-
 	if (info->ctrl_str_idx >= 0 && info->ctrl_desc) {
 		/* ctrl interface label */
 		status = usb_string_id(cdev);
@@ -2635,7 +2648,6 @@
 		info->cdc_eth_desc->iMACAddress = status;
 	}
 
-skip_string_id_alloc:
 	if (info->ctrl_desc)
 		info->ctrl_desc->bInterfaceNumber = gsi->ctrl_id;
 
@@ -2812,6 +2824,26 @@
 	wake_up_interruptible(&gsi->d_port.wait_for_ipa_ready);
 }
 
+static void gsi_get_ether_addr(const char *str, u8 *dev_addr)
+{
+	if (str) {
+		unsigned int i;
+
+		for (i = 0; i < ETH_ALEN; i++) {
+			unsigned char num;
+
+			if ((*str == '.') || (*str == ':'))
+				str++;
+			num = hex_to_bin(*str++) << 4;
+			num |= hex_to_bin(*str++);
+			dev_addr[i] = num;
+		}
+		if (is_valid_ether_addr(dev_addr))
+			return;
+	}
+	random_ether_addr(dev_addr);
+}
+
 static int gsi_bind(struct usb_configuration *c, struct usb_function *f)
 {
 	struct usb_composite_dev *cdev = c->cdev;
@@ -2819,6 +2851,7 @@
 	struct f_gsi *gsi = func_to_gsi(f);
 	struct rndis_params *params;
 	struct net_device *net;
+	struct gsi_opts *opts;
 	char *name = NULL;
 	int status;
 	__u8  class;
@@ -2884,11 +2917,15 @@
 		rndis_set_param_medium(gsi->params, RNDIS_MEDIUM_802_3, 0);
 
 		/* export host's Ethernet address in CDC format */
-		random_ether_addr(gsi->d_port.ipa_init_params.device_ethaddr);
-		random_ether_addr(gsi->d_port.ipa_init_params.host_ethaddr);
+		gsi_get_ether_addr(gsi_dev_addr,
+				   gsi->d_port.ipa_init_params.device_ethaddr);
+
+		gsi_get_ether_addr(gsi_host_addr,
+				   gsi->d_port.ipa_init_params.host_ethaddr);
+
 		log_event_dbg("setting host_ethaddr=%pM, device_ethaddr = %pM",
-		gsi->d_port.ipa_init_params.host_ethaddr,
-		gsi->d_port.ipa_init_params.device_ethaddr);
+				gsi->d_port.ipa_init_params.host_ethaddr,
+				gsi->d_port.ipa_init_params.device_ethaddr);
 		memcpy(gsi->ethaddr, &gsi->d_port.ipa_init_params.host_ethaddr,
 				ETH_ALEN);
 		rndis_set_host_mac(gsi->params, gsi->ethaddr);
@@ -3022,18 +3059,15 @@
 		info.notify_buf_len = sizeof(struct usb_cdc_notification);
 		mbim_gsi_desc.wMaxSegmentSize = cpu_to_le16(0x800);
 
-		/*
-		 * If MBIM is bound in a config other than the first, tell
-		 * Windows about it by returning the num as a string in the
-		 * OS descriptor's subCompatibleID field. Windows only supports
-		 * up to config #4.
-		 */
-		if (c->bConfigurationValue >= 2 &&
-				c->bConfigurationValue <= 4) {
-			log_event_dbg("MBIM in configuration %d",
-					c->bConfigurationValue);
-			mbim_gsi_ext_config_desc.function.subCompatibleID[0] =
-				c->bConfigurationValue + '0';
+		if (cdev->use_os_string) {
+			f->os_desc_table = kzalloc(sizeof(*f->os_desc_table),
+						GFP_KERNEL);
+			if (!f->os_desc_table)
+				return -ENOMEM;
+			opts = container_of(f->fi, struct gsi_opts, func_inst);
+			f->os_desc_n = 1;
+			f->os_desc_table[0].os_desc = &opts->os_desc;
+			f->os_desc_table[0].if_id = gsi->data_id;
 		}
 		break;
 	case USB_PROT_RMNET_IPA:
@@ -3097,11 +3131,15 @@
 		info.notify_buf_len = GSI_CTRL_NOTIFY_BUFF_LEN;
 
 		/* export host's Ethernet address in CDC format */
-		random_ether_addr(gsi->d_port.ipa_init_params.device_ethaddr);
-		random_ether_addr(gsi->d_port.ipa_init_params.host_ethaddr);
+		gsi_get_ether_addr(gsi_dev_addr,
+				   gsi->d_port.ipa_init_params.device_ethaddr);
+
+		gsi_get_ether_addr(gsi_host_addr,
+				   gsi->d_port.ipa_init_params.host_ethaddr);
+
 		log_event_dbg("setting host_ethaddr=%pM, device_ethaddr = %pM",
-		gsi->d_port.ipa_init_params.host_ethaddr,
-		gsi->d_port.ipa_init_params.device_ethaddr);
+				gsi->d_port.ipa_init_params.host_ethaddr,
+				gsi->d_port.ipa_init_params.device_ethaddr);
 
 		snprintf(gsi->ethaddr, sizeof(gsi->ethaddr),
 		"%02X%02X%02X%02X%02X%02X",
@@ -3219,6 +3257,7 @@
 
 dereg_rndis:
 	rndis_deregister(gsi->params);
+	kfree(f->os_desc_table);
 fail:
 	return status;
 }
@@ -3250,8 +3289,11 @@
 		rndis_deregister(gsi->params);
 	}
 
-	if (gsi->prot_id == USB_PROT_MBIM_IPA)
-		mbim_gsi_ext_config_desc.function.subCompatibleID[0] = 0;
+	if (gsi->prot_id == USB_PROT_MBIM_IPA) {
+		kfree(f->os_desc_table);
+		f->os_desc_table = NULL;
+		f->os_desc_n = 0;
+	}
 
 	if (gadget_is_superspeed(c->cdev->gadget)) {
 		usb_free_descriptors(f->ss_descriptors);
@@ -3354,6 +3396,9 @@
 
 	gsi->d_port.ipa_usb_wq = ipa_usb_wq;
 
+	gsi->gsi_rw_timer_interval = DEFAULT_RW_TIMER_INTERVAL;
+	setup_timer(&gsi->gsi_rw_timer, gsi_rw_timer_func, (unsigned long) gsi);
+
 	return gsi;
 }
 
@@ -3571,6 +3616,8 @@
 	int name_len, prot_id, ret = 0;
 	struct gsi_opts *opts;
 	struct f_gsi *gsi;
+	struct usb_os_desc *descs[1];
+	char *names[1];
 
 	opts = container_of(fi, struct gsi_opts, func_inst);
 
@@ -3588,6 +3635,15 @@
 	if (prot_id == USB_PROT_RNDIS_IPA)
 		config_group_init_type_name(&opts->func_inst.group, "",
 					    &gsi_func_rndis_type);
+	if (prot_id == IPA_USB_MBIM) {
+		opts->os_desc.ext_compat_id = opts->ext_compat_id;
+		INIT_LIST_HEAD(&opts->os_desc.ext_prop);
+		descs[0] = &opts->os_desc;
+		names[0] = "MBIM";
+		opts->interf_group = usb_os_desc_prepare_interf_dir(
+						&opts->func_inst.group, 1,
+						descs, names, THIS_MODULE);
+	}
 
 	gsi = opts->gsi = __gsi[prot_id];
 	opts->gsi->prot_id = prot_id;
@@ -3602,8 +3658,11 @@
 {
 	struct gsi_opts *opts = container_of(f, struct gsi_opts, func_inst);
 
-	if (opts && opts->gsi && opts->gsi->c_port.ctrl_device.fops)
-		misc_deregister(&opts->gsi->c_port.ctrl_device);
+	if (opts) {
+		if (opts->gsi && opts->gsi->c_port.ctrl_device.fops)
+			misc_deregister(&opts->gsi->c_port.ctrl_device);
+		kfree(opts->interf_group);
+	}
 
 	kfree(opts);
 }
diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h
index cd146a0..5231213 100644
--- a/drivers/usb/gadget/function/f_gsi.h
+++ b/drivers/usb/gadget/function/f_gsi.h
@@ -29,6 +29,7 @@
 #include <linux/timer.h>
 
 #include "u_ether.h"
+#include "configfs.h"
 
 #define GSI_RMNET_CTRL_NAME "rmnet_ctrl"
 #define GSI_MBIM_CTRL_NAME "android_mbim"
@@ -278,10 +279,12 @@
 	struct gsi_data_port d_port;
 	struct gsi_ctrl_port c_port;
 	bool rmnet_dtr_status;
+
 	/* To test remote wakeup using debugfs */
-	struct timer_list debugfs_rw_timer;
-	u8 debugfs_rw_enable;
-	u16 debugfs_rw_interval;
+	struct timer_list gsi_rw_timer;
+	u8 debugfs_rw_timer_enable;
+	u16 gsi_rw_timer_interval;
+
 	bool host_supports_flow_control;
 };
 
@@ -306,6 +309,11 @@
 struct gsi_opts {
 	struct usb_function_instance func_inst;
 	struct f_gsi *gsi;
+
+	/* os desc support */
+	struct config_group *interf_group;
+	char ext_compat_id[16];
+	struct usb_os_desc os_desc;
 };
 
 static inline struct gsi_opts *to_gsi_opts(struct config_item *item)
@@ -1057,50 +1065,6 @@
 	NULL,
 };
 
-/* Microsoft OS Descriptors */
-
-/*
- * We specify our own bMS_VendorCode byte which Windows will use
- * as the bRequest value in subsequent device get requests.
- */
-#define MBIM_VENDOR_CODE	0xA5
-
-/* Microsoft Extended Configuration Descriptor Header Section */
-struct mbim_gsi_ext_config_desc_header {
-	__le32	dwLength;
-	__u16	bcdVersion;
-	__le16	wIndex;
-	__u8	bCount;
-	__u8	reserved[7];
-};
-
-/* Microsoft Extended Configuration Descriptor Function Section */
-struct mbim_gsi_ext_config_desc_function {
-	__u8	bFirstInterfaceNumber;
-	__u8	bInterfaceCount;
-	__u8	compatibleID[8];
-	__u8	subCompatibleID[8];
-	__u8	reserved[6];
-};
-
-/* Microsoft Extended Configuration Descriptor */
-static struct {
-	struct mbim_gsi_ext_config_desc_header	header;
-	struct mbim_gsi_ext_config_desc_function    function;
-} mbim_gsi_ext_config_desc = {
-	.header = {
-		.dwLength = cpu_to_le32(sizeof(mbim_gsi_ext_config_desc)),
-		.bcdVersion = cpu_to_le16(0x0100),
-		.wIndex = cpu_to_le16(4),
-		.bCount = 1,
-	},
-	.function = {
-		.bFirstInterfaceNumber = 0,
-		.bInterfaceCount = 1,
-		.compatibleID = { 'A', 'L', 'T', 'R', 'C', 'F', 'G' },
-		/* .subCompatibleID = DYNAMIC */
-	},
-};
 /* ecm device descriptors */
 #define ECM_QC_LOG2_STATUS_INTERVAL_MSEC	5
 #define ECM_QC_STATUS_BYTECOUNT			16 /* 8 byte header + data */
diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
index 6f3b623..373c31a 100644
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -1634,7 +1634,8 @@
 {
 	int value = -EOPNOTSUPP;
 
-	if (ctrl->bRequestType == 0x40 && ctrl->bRequest == 0xF0) {
+	if (ctrl->bRequestType == 0x40 && ctrl->bRequest == 0xF0
+			&& _ncm_setup_desc) {
 		_ncm_setup_desc->minor = (uint8_t)(ctrl->wValue >> 8);
 		_ncm_setup_desc->major = (uint8_t)(ctrl->wValue & 0xFF);
 		schedule_work(&_ncm_setup_desc->work);
diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c
index 2ec28c8..22a6755 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -1305,10 +1305,14 @@
 	}
 
 	tty_port_init(&port->port);
+	tty_buffer_set_limit(&port->port, 8388608);
 	spin_lock_init(&port->port_lock);
 	init_waitqueue_head(&port->drain_wait);
 	init_waitqueue_head(&port->close_wait);
 
+	pr_debug("%s open:ttyGS%d and set 8388608, avail:%d\n", __func__,
+		port_num, tty_buffer_space_avail(&port->port));
+
 	tasklet_init(&port->push, gs_rx_push, (unsigned long) port);
 
 	INIT_LIST_HEAD(&port->read_pool);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 9cba037..ccad0be 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3661,6 +3661,7 @@
 		del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);
 	}
 
+	virt_dev->udev = NULL;
 	spin_lock_irqsave(&xhci->lock, flags);
 	/* Don't disable the slot if the host controller is dead. */
 	state = readl(&xhci->op_regs->status);
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 6685f05..a9adf0b 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -374,7 +374,6 @@
 	struct rx_msg		*rx_ext_msg;
 
 	u32			received_pdos[PD_MAX_DATA_OBJ];
-	u32			received_ado;
 	u16			src_cap_id;
 	u8			selected_pdo;
 	u8			requested_pdo;
@@ -443,6 +442,7 @@
 	u8			src_cap_ext_db[PD_SRC_CAP_EXT_DB_LEN];
 	bool			send_get_pps_status;
 	u32			pps_status_db;
+	bool			send_get_status;
 	u8			status_db[PD_STATUS_DB_LEN];
 	bool			send_get_battery_cap;
 	u8			get_battery_cap_db;
@@ -533,6 +533,22 @@
 	extcon_set_state_sync(pd->extcon, EXTCON_USB, 1);
 }
 
+static void notify_pd_contract_status(struct usbpd *pd)
+{
+	int ret = 0;
+	union extcon_property_value val;
+
+	if (!pd)
+		return;
+
+	val.intval = pd->in_explicit_contract;
+	extcon_set_property(pd->extcon, EXTCON_USB,
+			EXTCON_PROP_USB_PD_CONTRACT, val);
+	ret = extcon_blocking_sync(pd->extcon, EXTCON_USB, 0);
+	if (ret)
+		usbpd_err(&pd->dev, "err(%d) while notifying pd status", ret);
+}
+
 /**
  * This API allows client driver to request for releasing SS lanes. It should
  * not be called from atomic context.
@@ -1252,6 +1268,7 @@
 
 	case PE_SRC_READY:
 		pd->in_explicit_contract = true;
+		notify_pd_contract_status(pd);
 
 		if (pd->vdm_tx)
 			kick_sm(pd, 0);
@@ -1398,6 +1415,7 @@
 
 	case PE_SNK_READY:
 		pd->in_explicit_contract = true;
+		notify_pd_contract_status(pd);
 
 		if (pd->vdm_tx)
 			kick_sm(pd, 0);
@@ -1433,6 +1451,7 @@
 				POWER_SUPPLY_PROP_PD_CURRENT_MAX, &val);
 
 		pd->in_explicit_contract = false;
+		notify_pd_contract_status(pd);
 
 		/*
 		 * need to update PR bit in message header so that
@@ -1929,6 +1948,22 @@
 	else
 		pd->vbus_enabled = true;
 
+	count = 10;
+	/*
+	 * Check to make sure VBUS voltage reaches above Vsafe5Vmin (4.75v)
+	 * before proceeding.
+	 */
+	while (count--) {
+		ret = power_supply_get_property(pd->usb_psy,
+				POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
+		if (ret || val.intval >= 4750000) /*vsafe5Vmin*/
+			break;
+		usleep_range(10000, 12000); /* Delay between two reads */
+	}
+
+	if (ret)
+		msleep(100); /* Delay to wait for VBUS ramp up if read fails */
+
 	return ret;
 }
 
@@ -1996,6 +2031,7 @@
 		pd->in_pr_swap = false;
 		pd->pd_connected = false;
 		pd->in_explicit_contract = false;
+		notify_pd_contract_status(pd);
 		pd->hard_reset_recvd = false;
 		pd->caps_count = 0;
 		pd->hard_reset_count = 0;
@@ -2079,6 +2115,7 @@
 				POWER_SUPPLY_PROP_PR_SWAP, &val);
 
 		pd->in_explicit_contract = false;
+		notify_pd_contract_status(pd);
 		pd->selected_pdo = pd->requested_pdo = 0;
 		pd->rdo = 0;
 		rx_msg_cleanup(pd);
@@ -2252,7 +2289,7 @@
 			pd->send_pr_swap = false;
 			ret = pd_send_msg(pd, MSG_PR_SWAP, NULL, 0, SOP_MSG);
 			if (ret) {
-				dev_err(&pd->dev, "Error sending PR Swap\n");
+				usbpd_err(&pd->dev, "Error sending PR Swap\n");
 				usbpd_set_state(pd, PE_SRC_SEND_SOFT_RESET);
 				break;
 			}
@@ -2263,7 +2300,7 @@
 			pd->send_dr_swap = false;
 			ret = pd_send_msg(pd, MSG_DR_SWAP, NULL, 0, SOP_MSG);
 			if (ret) {
-				dev_err(&pd->dev, "Error sending DR Swap\n");
+				usbpd_err(&pd->dev, "Error sending DR Swap\n");
 				usbpd_set_state(pd, PE_SRC_SEND_SOFT_RESET);
 				break;
 			}
@@ -2302,6 +2339,7 @@
 
 		pd_send_hard_reset(pd);
 		pd->in_explicit_contract = false;
+		notify_pd_contract_status(pd);
 		pd->rdo = 0;
 		rx_msg_cleanup(pd);
 		reset_vdm_state(pd);
@@ -2552,8 +2590,7 @@
 			ret = pd_send_msg(pd, MSG_GET_SOURCE_CAP_EXTENDED, NULL,
 				0, SOP_MSG);
 			if (ret) {
-				dev_err(&pd->dev,
-					"Error sending get_src_cap_ext\n");
+				usbpd_err(&pd->dev, "Error sending get_src_cap_ext\n");
 				usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
 				break;
 			}
@@ -2572,8 +2609,7 @@
 			ret = pd_send_msg(pd, MSG_GET_PPS_STATUS, NULL,
 				0, SOP_MSG);
 			if (ret) {
-				dev_err(&pd->dev,
-					"Error sending get_pps_status\n");
+				usbpd_err(&pd->dev, "Error sending get_pps_status\n");
 				usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
 				break;
 			}
@@ -2588,23 +2624,32 @@
 				sizeof(pd->pps_status_db));
 			complete(&pd->is_ready);
 		} else if (IS_DATA(rx_msg, MSG_ALERT)) {
-			if (rx_msg->data_len != sizeof(pd->received_ado)) {
+			u32 ado;
+
+			if (rx_msg->data_len != sizeof(ado)) {
 				usbpd_err(&pd->dev, "Invalid ado\n");
 				break;
 			}
-			memcpy(&pd->received_ado, rx_msg->payload,
-				sizeof(pd->received_ado));
-			ret = pd_send_msg(pd, MSG_GET_STATUS, NULL,
-				0, SOP_MSG);
+			memcpy(&ado, rx_msg->payload, sizeof(ado));
+			usbpd_dbg(&pd->dev, "Received Alert 0x%08x\n", ado);
+
+			/*
+			 * Don't send Get_Status right away so we can coalesce
+			 * multiple Alerts. 150ms should be enough to not get
+			 * in the way of any other AMS that might happen.
+			 */
+			pd->send_get_status = true;
+			kick_sm(pd, 150);
+		} else if (pd->send_get_status && is_sink_tx_ok(pd)) {
+			pd->send_get_status = false;
+			ret = pd_send_msg(pd, MSG_GET_STATUS, NULL, 0, SOP_MSG);
 			if (ret) {
-				dev_err(&pd->dev,
-					"Error sending get_status\n");
+				usbpd_err(&pd->dev, "Error sending get_status\n");
 				usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
 				break;
 			}
 			kick_sm(pd, SENDER_RESPONSE_TIME);
-		} else if (rx_msg &&
-			IS_EXT(rx_msg, MSG_STATUS)) {
+		} else if (rx_msg && IS_EXT(rx_msg, MSG_STATUS)) {
 			if (rx_msg->data_len != PD_STATUS_DB_LEN) {
 				usbpd_err(&pd->dev, "Invalid status db\n");
 				break;
@@ -2617,8 +2662,7 @@
 			ret = pd_send_ext_msg(pd, MSG_GET_BATTERY_CAP,
 				&pd->get_battery_cap_db, 1, SOP_MSG);
 			if (ret) {
-				dev_err(&pd->dev,
-					"Error sending get_battery_cap\n");
+				usbpd_err(&pd->dev, "Error sending get_battery_cap\n");
 				usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
 				break;
 			}
@@ -2637,8 +2681,7 @@
 			ret = pd_send_ext_msg(pd, MSG_GET_BATTERY_STATUS,
 				&pd->get_battery_status_db, 1, SOP_MSG);
 			if (ret) {
-				dev_err(&pd->dev,
-					"Error sending get_battery_status\n");
+				usbpd_err(&pd->dev, "Error sending get_battery_status\n");
 				usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
 				break;
 			}
@@ -2668,7 +2711,7 @@
 			pd->send_pr_swap = false;
 			ret = pd_send_msg(pd, MSG_PR_SWAP, NULL, 0, SOP_MSG);
 			if (ret) {
-				dev_err(&pd->dev, "Error sending PR Swap\n");
+				usbpd_err(&pd->dev, "Error sending PR Swap\n");
 				usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
 				break;
 			}
@@ -2679,7 +2722,7 @@
 			pd->send_dr_swap = false;
 			ret = pd_send_msg(pd, MSG_DR_SWAP, NULL, 0, SOP_MSG);
 			if (ret) {
-				dev_err(&pd->dev, "Error sending DR Swap\n");
+				usbpd_err(&pd->dev, "Error sending DR Swap\n");
 				usbpd_set_state(pd, PE_SNK_SEND_SOFT_RESET);
 				break;
 			}
@@ -2747,6 +2790,7 @@
 
 		pd_send_hard_reset(pd);
 		pd->in_explicit_contract = false;
+		notify_pd_contract_status(pd);
 		pd->selected_pdo = pd->requested_pdo = 0;
 		pd->rdo = 0;
 		reset_vdm_state(pd);
@@ -2778,6 +2822,7 @@
 		power_supply_set_property(pd->usb_psy,
 				POWER_SUPPLY_PROP_PR_SWAP, &val);
 		pd->in_explicit_contract = false;
+		notify_pd_contract_status(pd);
 
 		if (pd->vbus_enabled) {
 			regulator_disable(pd->vbus);
@@ -2838,7 +2883,6 @@
 
 	case PE_PRS_SNK_SRC_SOURCE_ON:
 		enable_vbus(pd);
-		msleep(200); /* allow time VBUS ramp-up, must be < tNewSrc */
 
 		ret = pd_send_msg(pd, MSG_PS_RDY, NULL, 0, SOP_MSG);
 		if (ret) {
@@ -3297,9 +3341,9 @@
 				"explicit" : "implicit");
 	add_uevent_var(env, "ALT_MODE=%d", pd->vdm_state == MODE_ENTERED);
 
-	add_uevent_var(env, "ADO=%08x", pd->received_ado);
-	for (i = 0; i < PD_STATUS_DB_LEN; i++)
-		add_uevent_var(env, "SDB%d=%08x", i, pd->status_db[i]);
+	add_uevent_var(env, "SDB=%02x %02x %02x %02x %02x", pd->status_db[0],
+			pd->status_db[1], pd->status_db[2], pd->status_db[3],
+			pd->status_db[4]);
 
 	return 0;
 }
@@ -3690,12 +3734,40 @@
 		return ret;
 
 	for (i = 0; i < PD_SRC_CAP_EXT_DB_LEN; i++)
-		len += snprintf(buf + len, PAGE_SIZE - len, "%d\n",
-			pd->src_cap_ext_db[i]);
+		len += snprintf(buf + len, PAGE_SIZE - len, "%s0x%02x",
+				i ? " " : "", pd->src_cap_ext_db[i]);
+
+	buf[len++] = '\n';
+	buf[len] = '\0';
+
 	return len;
 }
 static DEVICE_ATTR_RO(get_src_cap_ext);
 
+static ssize_t get_status_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int i, ret, len = 0;
+	struct usbpd *pd = dev_get_drvdata(dev);
+
+	if (pd->spec_rev == USBPD_REV_20)
+		return -EINVAL;
+
+	ret = trigger_tx_msg(pd, &pd->send_get_status);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < PD_STATUS_DB_LEN; i++)
+		len += snprintf(buf + len, PAGE_SIZE - len, "%s0x%02x",
+				i ? " " : "", pd->status_db[i]);
+
+	buf[len++] = '\n';
+	buf[len] = '\0';
+
+	return len;
+}
+static DEVICE_ATTR_RO(get_status);
+
 static ssize_t get_pps_status_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
@@ -3709,20 +3781,10 @@
 	if (ret)
 		return ret;
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", pd->pps_status_db);
+	return snprintf(buf, PAGE_SIZE, "0x%08x\n", pd->pps_status_db);
 }
 static DEVICE_ATTR_RO(get_pps_status);
 
-static ssize_t rx_ado_show(struct device *dev, struct device_attribute *attr,
-		char *buf)
-{
-	struct usbpd *pd = dev_get_drvdata(dev);
-
-	/* dump the ADO as a hex string */
-	return snprintf(buf, PAGE_SIZE, "%08x\n", pd->received_ado);
-}
-static DEVICE_ATTR_RO(rx_ado);
-
 static ssize_t get_battery_cap_store(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t size)
 {
@@ -3751,8 +3813,12 @@
 		return -EINVAL;
 
 	for (i = 0; i < PD_BATTERY_CAP_DB_LEN; i++)
-		len += snprintf(buf + len, PAGE_SIZE - len, "%d\n",
-			pd->battery_cap_db[i]);
+		len += snprintf(buf + len, PAGE_SIZE - len, "%s0x%02x",
+				i ? " " : "", pd->battery_cap_db[i]);
+
+	buf[len++] = '\n';
+	buf[len] = '\0';
+
 	return len;
 }
 static DEVICE_ATTR_RW(get_battery_cap);
@@ -3783,7 +3849,7 @@
 	if (pd->get_battery_status_db == -EINVAL)
 		return -EINVAL;
 
-	return snprintf(buf, PAGE_SIZE, "%d\n", pd->battery_sts_dobj);
+	return snprintf(buf, PAGE_SIZE, "0x%08x\n", pd->battery_sts_dobj);
 }
 static DEVICE_ATTR_RW(get_battery_status);
 
@@ -3807,8 +3873,8 @@
 	&dev_attr_rdo_h.attr,
 	&dev_attr_hard_reset.attr,
 	&dev_attr_get_src_cap_ext.attr,
+	&dev_attr_get_status.attr,
 	&dev_attr_get_pps_status.attr,
-	&dev_attr_rx_ado.attr,
 	&dev_attr_get_battery_cap.attr,
 	&dev_attr_get_battery_status.attr,
 	NULL,
@@ -3964,6 +4030,8 @@
 	extcon_set_property_capability(pd->extcon, EXTCON_USB,
 			EXTCON_PROP_USB_TYPEC_POLARITY);
 	extcon_set_property_capability(pd->extcon, EXTCON_USB,
+			EXTCON_PROP_USB_PD_CONTRACT);
+	extcon_set_property_capability(pd->extcon, EXTCON_USB,
 			EXTCON_PROP_USB_SS);
 	extcon_set_property_capability(pd->extcon, EXTCON_USB_HOST,
 			EXTCON_PROP_USB_TYPEC_POLARITY);
diff --git a/drivers/usb/pd/qpnp-pdphy.c b/drivers/usb/pd/qpnp-pdphy.c
index 2997976..a1b8a32 100644
--- a/drivers/usb/pd/qpnp-pdphy.c
+++ b/drivers/usb/pd/qpnp-pdphy.c
@@ -50,7 +50,7 @@
 #define TX_SIZE_MASK			0xF
 
 #define USB_PDPHY_TX_CONTROL		0x44
-#define TX_CONTROL_RETRY_COUNT		(BIT(6) | BIT(5))
+#define TX_CONTROL_RETRY_COUNT(n)	(((n) & 0x3) << 5)
 #define TX_CONTROL_FRAME_TYPE		(BIT(4) | BIT(3) | BIT(2))
 #define TX_CONTROL_FRAME_TYPE_CABLE_RESET (0x1 << 2)
 #define TX_CONTROL_SEND_SIGNAL		BIT(1)
@@ -80,6 +80,9 @@
 #define VDD_PDPHY_VOL_MAX		3088000 /* uV */
 #define VDD_PDPHY_HPM_LOAD		3000 /* uA */
 
+/* Message Spec Rev field */
+#define PD_MSG_HDR_REV(hdr)		(((hdr) >> 6) & 3)
+
 /* timers */
 #define RECEIVER_RESPONSE_TIME		15	/* tReceiverResponse */
 #define HARD_RESET_COMPLETE_TIME	5	/* tHardResetComplete */
@@ -437,12 +440,12 @@
 	if (ret)
 		return ret;
 
-	ret = wait_event_interruptible_timeout(pdphy->tx_waitq,
+	ret = wait_event_interruptible_hrtimeout(pdphy->tx_waitq,
 		pdphy->tx_status != -EINPROGRESS,
-		msecs_to_jiffies(HARD_RESET_COMPLETE_TIME));
-	if (ret <= 0) {
+		ms_to_ktime(HARD_RESET_COMPLETE_TIME));
+	if (ret) {
 		dev_err(pdphy->dev, "%s: failed ret %d", __func__, ret);
-		return ret ? ret : -ETIMEDOUT;
+		return ret;
 	}
 
 	ret = pdphy_reg_write(pdphy, USB_PDPHY_TX_CONTROL, 0);
@@ -520,18 +523,24 @@
 
 	usleep_range(2, 3);
 
-	val = TX_CONTROL_RETRY_COUNT | (sop << 2) | TX_CONTROL_SEND_MSG;
+	val = (sop << 2) | TX_CONTROL_SEND_MSG;
+
+	/* nRetryCount == 2 for PD 3.0, 3 for PD 2.0 */
+	if (PD_MSG_HDR_REV(hdr) == USBPD_REV_30)
+		val |= TX_CONTROL_RETRY_COUNT(2);
+	else
+		val |= TX_CONTROL_RETRY_COUNT(3);
 
 	ret = pdphy_reg_write(pdphy, USB_PDPHY_TX_CONTROL, val);
 	if (ret)
 		return ret;
 
-	ret = wait_event_interruptible_timeout(pdphy->tx_waitq,
+	ret = wait_event_interruptible_hrtimeout(pdphy->tx_waitq,
 		pdphy->tx_status != -EINPROGRESS,
-		msecs_to_jiffies(RECEIVER_RESPONSE_TIME));
-	if (ret <= 0) {
+		ms_to_ktime(RECEIVER_RESPONSE_TIME));
+	if (ret) {
 		dev_err(pdphy->dev, "%s: failed ret %d", __func__, ret);
-		return ret ? ret : -ETIMEDOUT;
+		return ret;
 	}
 
 	if (hdr && !pdphy->tx_status)
diff --git a/drivers/usb/phy/phy-msm-snps-hs.c b/drivers/usb/phy/phy-msm-snps-hs.c
index 28a9bf1..558a8aa 100644
--- a/drivers/usb/phy/phy-msm-snps-hs.c
+++ b/drivers/usb/phy/phy-msm-snps-hs.c
@@ -682,9 +682,6 @@
 
 	msm_hsphy_enable_clocks(phy, false);
 	msm_hsphy_enable_power(phy, false);
-
-	kfree(phy);
-
 	return 0;
 }
 
diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c
index 1795d24..5b734be 100644
--- a/drivers/usb/phy/phy-msm-ssusb-qmp.c
+++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c
@@ -1081,7 +1081,6 @@
 	usb_remove_phy(&phy->phy);
 	msm_ssphy_qmp_enable_clks(phy, false);
 	msm_ssusb_qmp_ldo_enable(phy, 0);
-	kfree(phy);
 	return 0;
 }
 
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index b8f4907..44c917d 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -35,6 +35,7 @@
 #include <linux/pm_wakeup.h>
 #include <linux/reset.h>
 #include <linux/extcon.h>
+#include <linux/power_supply.h>
 #include <soc/qcom/scm.h>
 
 #include <linux/usb.h>
@@ -1688,6 +1689,8 @@
 	}
 
 	disable_irq(motg->irq);
+	if (motg->phy_irq)
+		disable_irq(motg->phy_irq);
 	pm_stay_awake(&motg->pdev->dev);
 
 	/*
@@ -1806,6 +1809,8 @@
 		enable_irq(motg->async_int);
 		motg->async_int = 0;
 	}
+	if (motg->phy_irq)
+		enable_irq(motg->phy_irq);
 	enable_irq(motg->irq);
 
 	/* Enable ASYNC_IRQ only during LPM */
@@ -2837,11 +2842,11 @@
 			msm_otg_start_peripheral(otg, 0);
 			msm_otg_dbg_log_event(phy, "RT PM: B_PERI A PUT",
 				get_pm_runtime_counter(dev), 0);
+			/* Schedule work to finish cable disconnect processing*/
+			otg->state = OTG_STATE_B_IDLE;
 			/* _put for _get done on cable connect in B_IDLE */
 			pm_runtime_mark_last_busy(dev);
 			pm_runtime_put_autosuspend(dev);
-			/* Schedule work to finish cable disconnect processing*/
-			otg->state = OTG_STATE_B_IDLE;
 			work = 1;
 		} else if (test_bit(A_BUS_SUSPEND, &motg->inputs)) {
 			pr_debug("a_bus_suspend\n");
@@ -3717,6 +3722,46 @@
 	return ret;
 }
 
+static void msm_otg_handle_initial_extcon(struct msm_otg *motg)
+{
+	if (motg->extcon_vbus && extcon_get_cable_state_(motg->extcon_vbus,
+							EXTCON_USB))
+		msm_otg_vbus_notifier(&motg->vbus_nb, true, motg->extcon_vbus);
+
+	if (motg->extcon_id && extcon_get_cable_state_(motg->extcon_id,
+							EXTCON_USB_HOST))
+		msm_otg_id_notifier(&motg->id_nb, true, motg->extcon_id);
+}
+
+static void msm_otg_extcon_register_work(struct work_struct *w)
+{
+	struct msm_otg *motg = container_of(w, struct msm_otg,
+						extcon_register_work);
+
+	power_supply_unreg_notifier(&motg->psy_nb);
+
+	if (msm_otg_extcon_register(motg)) {
+		dev_err(&motg->pdev->dev, "failed to register extcon\n");
+		return;
+	}
+
+	msm_otg_handle_initial_extcon(motg);
+}
+
+static int msm_otg_psy_changed(struct notifier_block *nb, unsigned long evt,
+							void *ptr)
+{
+	struct msm_otg *motg = container_of(nb, struct msm_otg, psy_nb);
+
+	if (strcmp(((struct power_supply *)ptr)->desc->name, "usb") ||
+						evt != PSY_EVENT_PROP_CHANGED)
+		return 0;
+
+	queue_work(motg->otg_wq, &motg->extcon_register_work);
+
+	return 0;
+}
+
 struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
 {
 	struct device_node *node = pdev->dev.of_node;
@@ -4266,6 +4311,7 @@
 	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_charger_work, msm_otg_notify_charger_work);
+	INIT_WORK(&motg->extcon_register_work, msm_otg_extcon_register_work);
 	motg->otg_wq = alloc_ordered_workqueue("k_otg", 0);
 	if (!motg->otg_wq) {
 		pr_err("%s: Unable to create workqueue otg_wq\n",
@@ -4474,21 +4520,20 @@
 		}
 	}
 
-	psy = power_supply_get_by_name("usb");
-	if (!psy)
-		dev_warn(&pdev->dev, "Could not get usb power_supply\n");
-
+	/*
+	 * Try to register extcon handle from probe; by this time USB psy may or
+	 * may not have been registered. If this fails, then wait for the USB
+	 * psy to get registered which will again try to register extcon via
+	 * notifier call.
+	 */
 	ret = msm_otg_extcon_register(motg);
-	if (ret)
-		goto put_psy;
-
-	if (motg->extcon_vbus && extcon_get_cable_state_(motg->extcon_vbus,
-							EXTCON_USB))
-		msm_otg_vbus_notifier(&motg->vbus_nb, true, motg->extcon_vbus);
-
-	if (motg->extcon_id && extcon_get_cable_state_(motg->extcon_id,
-							EXTCON_USB_HOST))
-		msm_otg_id_notifier(&motg->id_nb, true, motg->extcon_id);
+	if (ret) {
+		dev_dbg(&pdev->dev, "Registering PSY notifier for extcon\n");
+		motg->psy_nb.notifier_call = msm_otg_psy_changed;
+		power_supply_reg_notifier(&motg->psy_nb);
+	} else {
+		msm_otg_handle_initial_extcon(motg);
+	}
 
 	if (gpio_is_valid(motg->pdata->hub_reset_gpio)) {
 		ret = devm_gpio_request(&pdev->dev,
@@ -4528,11 +4573,6 @@
 
 	return 0;
 
-put_psy:
-	if (psy)
-		power_supply_put(psy);
-	if (pdev->dev.of_node)
-		msm_otg_setup_devices(pdev, motg->pdata->mode, false);
 remove_cdev:
 	pm_runtime_disable(&pdev->dev);
 	device_remove_file(&pdev->dev, &dev_attr_dpdm_pulldown_enable);
@@ -4600,7 +4640,7 @@
 		return -EBUSY;
 
 	unregister_pm_notifier(&motg->pm_notify);
-
+	power_supply_unreg_notifier(&motg->psy_nb);
 	extcon_unregister_notifier(motg->extcon_id, EXTCON_USB_HOST,
 							&motg->id_nb);
 	extcon_unregister_notifier(motg->extcon_vbus, EXTCON_USB,
@@ -4618,6 +4658,7 @@
 	msm_otg_perf_vote_update(motg, false);
 	cancel_work_sync(&motg->sm_work);
 	cancel_work_sync(&motg->notify_charger_work);
+	cancel_work_sync(&motg->extcon_register_work);
 	destroy_workqueue(motg->otg_wq);
 
 	pm_runtime_resume(&pdev->dev);
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 2ef33d4..52bbbc4 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -1219,8 +1219,6 @@
 		console_unlock();
 		break;
 	default:
-		if (!lock_fb_info(info))
-			return -ENODEV;
 		fb = info->fbops;
 		if (fb->fb_ioctl_v2)
 			ret = fb->fb_ioctl_v2(info, cmd, arg, file);
@@ -1228,7 +1226,6 @@
 			ret = fb->fb_ioctl(info, cmd, arg);
 		else
 			ret = -ENOTTY;
-		unlock_fb_info(info);
 	}
 	return ret;
 }
diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.c b/drivers/video/fbdev/msm/mdss_compat_utils.c
index a81f149..23d4a27 100644
--- a/drivers/video/fbdev/msm/mdss_compat_utils.c
+++ b/drivers/video/fbdev/msm/mdss_compat_utils.c
@@ -2879,26 +2879,28 @@
 			*pp = compat_alloc_user_space(alloc_size);
 			if (*pp == NULL)
 				return -ENOMEM;
-			memset(*pp, 0, alloc_size);
-
-			(*pp)->data.lut_cfg_data.data.pgc_lut_data.r_data =
-					(struct mdp_ar_gc_lut_data *)
-					((unsigned long) *pp +
-					sizeof(struct msmfb_mdp_pp));
-			(*pp)->data.lut_cfg_data.data.pgc_lut_data.g_data =
-					(struct mdp_ar_gc_lut_data *)
+			if (clear_user(*pp, alloc_size))
+				return -EFAULT;
+			if (put_user((struct mdp_ar_gc_lut_data *)
+				((unsigned long) *pp +
+				sizeof(struct msmfb_mdp_pp)),
+			&(*pp)->data.lut_cfg_data.data.pgc_lut_data.r_data) ||
+				put_user((struct mdp_ar_gc_lut_data *)
 					((unsigned long) *pp +
 					sizeof(struct msmfb_mdp_pp) +
-					pgc_size);
-			(*pp)->data.lut_cfg_data.data.pgc_lut_data.b_data =
-					(struct mdp_ar_gc_lut_data *)
+					pgc_size),
+			&(*pp)->data.lut_cfg_data.data.pgc_lut_data.g_data) ||
+				put_user((struct mdp_ar_gc_lut_data *)
 					((unsigned long) *pp +
 					sizeof(struct msmfb_mdp_pp) +
-					(2 * pgc_size));
-			(*pp)->data.lut_cfg_data.data.pgc_lut_data.cfg_payload
-					 = (void *)((unsigned long) *pp +
+					(2 * pgc_size)),
+			&(*pp)->data.lut_cfg_data.data.pgc_lut_data.b_data) ||
+				put_user((void *)((unsigned long) *pp +
 					sizeof(struct msmfb_mdp_pp) +
-					(3 * pgc_size));
+					(3 * pgc_size)),
+					&(*pp)->data.lut_cfg_data.data.
+						pgc_lut_data.cfg_payload))
+				return -EFAULT;
 			break;
 		case mdp_lut_igc:
 			alloc_size += __pp_compat_size_igc();
@@ -2908,10 +2910,13 @@
 					alloc_size);
 				return -ENOMEM;
 			}
-			memset(*pp, 0, alloc_size);
-			(*pp)->data.lut_cfg_data.data.igc_lut_data.cfg_payload
-					= (void *)((unsigned long)(*pp) +
-					   sizeof(struct msmfb_mdp_pp));
+			if (clear_user(*pp, alloc_size))
+				return -EFAULT;
+			if (put_user((void *)((unsigned long)(*pp) +
+					sizeof(struct msmfb_mdp_pp)),
+					&(*pp)->data.lut_cfg_data.data.
+						igc_lut_data.cfg_payload))
+				return -EFAULT;
 			break;
 		case mdp_lut_hist:
 			alloc_size += __pp_compat_size_hist_lut();
@@ -2921,10 +2926,13 @@
 					alloc_size);
 				return -ENOMEM;
 			}
-			memset(*pp, 0, alloc_size);
-			(*pp)->data.lut_cfg_data.data.hist_lut_data.cfg_payload
-					= (void *)((unsigned long)(*pp) +
-					   sizeof(struct msmfb_mdp_pp));
+			if (clear_user(*pp, alloc_size))
+				return -EFAULT;
+			if (put_user((void *)((unsigned long)(*pp) +
+					sizeof(struct msmfb_mdp_pp)),
+					&(*pp)->data.lut_cfg_data.data.
+						hist_lut_data.cfg_payload))
+				return -EFAULT;
 			break;
 		default:
 			*pp = compat_alloc_user_space(alloc_size);
@@ -2933,7 +2941,8 @@
 					alloc_size, lut_type);
 				return -ENOMEM;
 			}
-			memset(*pp, 0, alloc_size);
+			if (clear_user(*pp, alloc_size))
+				return -EFAULT;
 			break;
 		}
 		break;
@@ -2945,10 +2954,12 @@
 				alloc_size);
 			return -ENOMEM;
 		}
-		memset(*pp, 0, alloc_size);
-		(*pp)->data.pcc_cfg_data.cfg_payload =
-				(void *)((unsigned long)(*pp) +
-				 sizeof(struct msmfb_mdp_pp));
+		if (clear_user(*pp, alloc_size))
+			return -EFAULT;
+		if (put_user((void *)((unsigned long)(*pp) +
+				sizeof(struct msmfb_mdp_pp)),
+			&(*pp)->data.pcc_cfg_data.cfg_payload))
+			return -EFAULT;
 		break;
 	case mdp_op_gamut_cfg:
 		alloc_size += __pp_compat_size_gamut();
@@ -2958,10 +2969,12 @@
 				alloc_size);
 			return -ENOMEM;
 		}
-		memset(*pp, 0, alloc_size);
-		(*pp)->data.gamut_cfg_data.cfg_payload =
-				(void *)((unsigned long)(*pp) +
-				 sizeof(struct msmfb_mdp_pp));
+		if (clear_user(*pp, alloc_size))
+			return -EFAULT;
+		if (put_user((void *)((unsigned long)(*pp) +
+				sizeof(struct msmfb_mdp_pp)),
+			&(*pp)->data.gamut_cfg_data.cfg_payload))
+			return -EFAULT;
 		break;
 	case mdp_op_pa_v2_cfg:
 		alloc_size += __pp_compat_size_pa();
@@ -2971,16 +2984,19 @@
 				alloc_size);
 			return -ENOMEM;
 		}
-		memset(*pp, 0, alloc_size);
-		(*pp)->data.pa_v2_cfg_data.cfg_payload =
-				(void *)((unsigned long)(*pp) +
-				sizeof(struct msmfb_mdp_pp));
+		if (clear_user(*pp, alloc_size))
+			return -EFAULT;
+		if (put_user((void *)((unsigned long)(*pp) +
+				sizeof(struct msmfb_mdp_pp)),
+			&(*pp)->data.pa_v2_cfg_data.cfg_payload))
+			return -EFAULT;
 		break;
 	default:
 		*pp = compat_alloc_user_space(alloc_size);
 		if (*pp == NULL)
 			return -ENOMEM;
-		memset(*pp, 0, alloc_size);
+		if (clear_user(*pp, alloc_size))
+			return -EFAULT;
 		break;
 	}
 	return 0;
@@ -3398,7 +3414,9 @@
 				 sizeof(struct mdp_histogram_start_req));
 			return -EINVAL;
 		}
-		memset(hist_req, 0, sizeof(struct mdp_histogram_start_req));
+		if (clear_user(hist_req,
+				 sizeof(struct mdp_histogram_start_req)))
+			return -EFAULT;
 		ret = __from_user_hist_start_req(hist_req32, hist_req);
 		if (ret)
 			goto histo_compat_err;
@@ -3418,7 +3436,8 @@
 				 sizeof(struct mdp_histogram_data));
 			return -EINVAL;
 		}
-		memset(hist, 0, sizeof(struct mdp_histogram_data));
+		if (clear_user(hist, sizeof(struct mdp_histogram_data)))
+			return -EFAULT;
 		ret = __from_user_hist_data(hist32, hist);
 		if (ret)
 			goto histo_compat_err;
@@ -3921,7 +3940,7 @@
 }
 
 
-static int __from_user_mdp_overlay(struct mdp_overlay *ov,
+static int __from_user_mdp_overlay(struct mdp_overlay __user *ov,
 				   struct mdp_overlay32 __user *ov32)
 {
 	__u32 data;
@@ -3980,12 +3999,12 @@
 	return 0;
 }
 
-static int __from_user_mdp_overlaylist(struct mdp_overlay_list *ovlist,
-				   struct mdp_overlay_list32 *ovlist32,
+static int __from_user_mdp_overlaylist(struct mdp_overlay_list __user *ovlist,
+				   struct mdp_overlay_list32 __user *ovlist32,
 				   struct mdp_overlay **to_list_head)
 {
 	__u32 i, ret;
-	unsigned long data, from_list_head;
+	unsigned long data, from_list_head, num_overlays;
 	struct mdp_overlay32 *iter;
 
 	if (!to_list_head || !ovlist32 || !ovlist) {
@@ -4006,11 +4025,13 @@
 			 sizeof(ovlist32->processed_overlays)))
 		return -EFAULT;
 
-	if (get_user(data, &ovlist32->overlay_list)) {
+	if (get_user(data, &ovlist32->overlay_list) ||
+		get_user(num_overlays, &ovlist32->num_overlays)) {
 		ret = -EFAULT;
 		goto validate_exit;
 	}
-	for (i = 0; i < ovlist32->num_overlays; i++) {
+
+	for (i = 0; i < num_overlays; i++) {
 		if (get_user(from_list_head, (__u32 *)data + i)) {
 			ret = -EFAULT;
 			goto validate_exit;
@@ -4023,7 +4044,8 @@
 			goto validate_exit;
 		}
 	}
-	ovlist->overlay_list = to_list_head;
+	if (put_user(to_list_head, &ovlist->overlay_list))
+		return -EFAULT;
 
 	return 0;
 
@@ -4032,8 +4054,8 @@
 	return -EFAULT;
 }
 
-static int __to_user_mdp_overlaylist(struct mdp_overlay_list32 *ovlist32,
-				   struct mdp_overlay_list *ovlist,
+static int __to_user_mdp_overlaylist(struct mdp_overlay_list32 __user *ovlist32,
+				   struct mdp_overlay_list __user *ovlist,
 				   struct mdp_overlay **l_ptr)
 {
 	__u32 i, ret;
@@ -4106,31 +4128,33 @@
 	return size;
 }
 
-static int __pp_sspp_set_offsets(struct mdp_overlay *ov)
+static int __pp_sspp_set_offsets(struct mdp_overlay __user *ov)
 {
 	if (!ov) {
 		pr_err("invalid overlay pointer\n");
 		return -EFAULT;
 	}
-	ov->overlay_pp_cfg.igc_cfg.cfg_payload = (void *)((unsigned long)ov +
-				sizeof(struct mdp_overlay));
-	ov->overlay_pp_cfg.pa_v2_cfg_data.cfg_payload =
-		ov->overlay_pp_cfg.igc_cfg.cfg_payload +
-		sizeof(struct mdp_igc_lut_data_v1_7);
-	ov->overlay_pp_cfg.pcc_cfg_data.cfg_payload =
-		ov->overlay_pp_cfg.pa_v2_cfg_data.cfg_payload +
-		sizeof(struct mdp_pa_data_v1_7);
-	ov->overlay_pp_cfg.hist_lut_cfg.cfg_payload =
-		ov->overlay_pp_cfg.pcc_cfg_data.cfg_payload +
-		sizeof(struct mdp_pcc_data_v1_7);
+	if (put_user((void *)((unsigned long)ov + sizeof(struct mdp_overlay)),
+			 &(ov->overlay_pp_cfg.igc_cfg.cfg_payload)) ||
+		put_user(ov->overlay_pp_cfg.igc_cfg.cfg_payload +
+			sizeof(struct mdp_igc_lut_data_v1_7),
+			&(ov->overlay_pp_cfg.pa_v2_cfg_data.cfg_payload)) ||
+		put_user(ov->overlay_pp_cfg.pa_v2_cfg_data.cfg_payload +
+			 sizeof(struct mdp_pa_data_v1_7),
+			&(ov->overlay_pp_cfg.pcc_cfg_data.cfg_payload)) ||
+		put_user(ov->overlay_pp_cfg.pcc_cfg_data.cfg_payload +
+			sizeof(struct mdp_pcc_data_v1_7),
+			&(ov->overlay_pp_cfg.hist_lut_cfg.cfg_payload)))
+		return -EFAULT;
 	return 0;
 }
 
 int mdss_compat_overlay_ioctl(struct fb_info *info, unsigned int cmd,
 			 unsigned long arg, struct file *file)
 {
-	struct mdp_overlay *ov, **layers_head;
-	struct mdp_overlay32 *ov32;
+	struct mdp_overlay **layers_head;
+	struct mdp_overlay __user *ov;
+	struct mdp_overlay32 __user *ov32;
 	struct mdp_overlay_list __user *ovlist;
 	struct mdp_overlay_list32 __user *ovlist32;
 	size_t layers_refs_sz, layers_sz, prepare_sz;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 4cfb48d..0b6195d 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -2559,7 +2559,7 @@
 			mixer_pool += ctl->mdata->ndspp;
 			nmixers -= ctl->mdata->ndspp;
 		} else if ((ctl->panel_data->panel_info.is_pluggable) &&
-				nmixers_active) {
+				nmixers_active > 1) {
 			mixer_pool += ctl->mdata->ndspp;
 			nmixers -= ctl->mdata->ndspp;
 		}
diff --git a/fs/exec.c b/fs/exec.c
index 3e2de29..d27f5e9 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -306,7 +306,7 @@
 	vma->vm_start = vma->vm_end - PAGE_SIZE;
 	vma->vm_flags = VM_SOFTDIRTY | VM_STACK_FLAGS | VM_STACK_INCOMPLETE_SETUP;
 	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
-	INIT_LIST_HEAD(&vma->anon_vma_chain);
+	INIT_VMA(vma);
 
 	err = insert_vm_struct(mm, vma);
 	if (err)
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index c585e7e..4fc0895 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1123,8 +1123,11 @@
 					goto out_mm;
 				}
 				for (vma = mm->mmap; vma; vma = vma->vm_next) {
-					vma->vm_flags &= ~VM_SOFTDIRTY;
+					vm_write_begin(vma);
+					WRITE_ONCE(vma->vm_flags,
+						vma->vm_flags & ~VM_SOFTDIRTY);
 					vma_set_page_prot(vma);
+					vm_write_end(vma);
 				}
 				downgrade_write(&mm->mmap_sem);
 				break;
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index 9d9c032..00b661d 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -499,8 +499,10 @@
 			vma = prev;
 		else
 			prev = vma;
-		vma->vm_flags = new_flags;
+		vm_write_begin(vma);
+		WRITE_ONCE(vma->vm_flags, new_flags);
 		vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
+		vm_write_end(vma);
 	}
 	up_write(&mm->mmap_sem);
 	mmput(mm);
@@ -895,8 +897,10 @@
 		 * the next vma was merged into the current one and
 		 * the current one has not been updated yet.
 		 */
-		vma->vm_flags = new_flags;
+		vm_write_begin(vma);
+		WRITE_ONCE(vma->vm_flags, new_flags);
 		vma->vm_userfaultfd_ctx.ctx = ctx;
+		vm_write_end(vma);
 
 	skip:
 		prev = vma;
@@ -1033,8 +1037,10 @@
 		 * the next vma was merged into the current one and
 		 * the current one has not been updated yet.
 		 */
-		vma->vm_flags = new_flags;
+		vm_write_begin(vma);
+		WRITE_ONCE(vma->vm_flags, new_flags);
 		vma->vm_userfaultfd_ctx = NULL_VM_UFFD_CTX;
+		vm_write_end(vma);
 
 	skip:
 		prev = vma;
diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h
index 288cc9e..f2d97b7 100644
--- a/include/asm-generic/atomic-long.h
+++ b/include/asm-generic/atomic-long.h
@@ -243,4 +243,7 @@
 #define atomic_long_inc_not_zero(l) \
 	ATOMIC_LONG_PFX(_inc_not_zero)((ATOMIC_LONG_PFX(_t) *)(l))
 
+#define atomic_long_cond_read_acquire(v, c) \
+	ATOMIC_LONG_PFX(_cond_read_acquire)((ATOMIC_LONG_PFX(_t) *)(v), (c))
+
 #endif  /*  _ASM_GENERIC_ATOMIC_LONG_H  */
diff --git a/include/asm-generic/qrwlock.h b/include/asm-generic/qrwlock.h
index 7d026bf..c39a93a 100644
--- a/include/asm-generic/qrwlock.h
+++ b/include/asm-generic/qrwlock.h
@@ -26,30 +26,17 @@
 
 /*
  * Writer states & reader shift and bias.
- *
- *       | +0 | +1 | +2 | +3 |
- *   ----+----+----+----+----+
- *    LE | 78 | 56 | 34 | 12 | 0x12345678
- *   ----+----+----+----+----+
- *       | wr |      rd      |
- *       +----+----+----+----+
- *
- *   ----+----+----+----+----+
- *    BE | 12 | 34 | 56 | 78 | 0x12345678
- *   ----+----+----+----+----+
- *       |      rd      | wr |
- *       +----+----+----+----+
  */
-#define	_QW_WAITING	1		/* A writer is waiting	   */
-#define	_QW_LOCKED	0xff		/* A writer holds the lock */
-#define	_QW_WMASK	0xff		/* Writer mask		   */
-#define	_QR_SHIFT	8		/* Reader count shift	   */
+#define	_QW_WAITING	0x100		/* A writer is waiting	   */
+#define	_QW_LOCKED	0x0ff		/* A writer holds the lock */
+#define	_QW_WMASK	0x1ff		/* Writer mask		   */
+#define	_QR_SHIFT	9		/* Reader count shift	   */
 #define _QR_BIAS	(1U << _QR_SHIFT)
 
 /*
  * External function declarations
  */
-extern void queued_read_lock_slowpath(struct qrwlock *lock, u32 cnts);
+extern void queued_read_lock_slowpath(struct qrwlock *lock);
 extern void queued_write_lock_slowpath(struct qrwlock *lock);
 
 /**
@@ -118,7 +105,7 @@
 		return;
 
 	/* The slowpath will decrement the reader count, if necessary. */
-	queued_read_lock_slowpath(lock, cnts);
+	queued_read_lock_slowpath(lock);
 }
 
 /**
@@ -147,22 +134,12 @@
 }
 
 /**
- * __qrwlock_write_byte - retrieve the write byte address of a queue rwlock
- * @lock : Pointer to queue rwlock structure
- * Return: the write byte address of a queue rwlock
- */
-static inline u8 *__qrwlock_write_byte(struct qrwlock *lock)
-{
-	return (u8 *)lock + 3 * IS_BUILTIN(CONFIG_CPU_BIG_ENDIAN);
-}
-
-/**
  * queued_write_unlock - release write lock of a queue rwlock
  * @lock : Pointer to queue rwlock structure
  */
 static inline void queued_write_unlock(struct qrwlock *lock)
 {
-	smp_store_release(__qrwlock_write_byte(lock), 0);
+	smp_store_release(&lock->wlocked, 0);
 }
 
 /*
diff --git a/include/asm-generic/qrwlock_types.h b/include/asm-generic/qrwlock_types.h
index 0abc6b6..8af752a 100644
--- a/include/asm-generic/qrwlock_types.h
+++ b/include/asm-generic/qrwlock_types.h
@@ -9,12 +9,23 @@
  */
 
 typedef struct qrwlock {
-	atomic_t		cnts;
+	union {
+		atomic_t cnts;
+		struct {
+#ifdef __LITTLE_ENDIAN
+			u8 wlocked;	/* Locked for write? */
+			u8 __lstate[3];
+#else
+			u8 __lstate[3];
+			u8 wlocked;	/* Locked for write? */
+#endif
+		};
+	};
 	arch_spinlock_t		wait_lock;
 } arch_rwlock_t;
 
 #define	__ARCH_RW_LOCK_UNLOCKED {		\
-	.cnts = ATOMIC_INIT(0),			\
+	{ .cnts = ATOMIC_INIT(0), },		\
 	.wait_lock = __ARCH_SPIN_LOCK_UNLOCKED,	\
 }
 
diff --git a/include/linux/atomic.h b/include/linux/atomic.h
index e71835b..bc7dba0 100644
--- a/include/linux/atomic.h
+++ b/include/linux/atomic.h
@@ -627,6 +627,8 @@
 }
 #endif
 
+#define atomic_cond_read_acquire(v, c)	smp_cond_load_acquire(&(v)->counter, (c))
+
 #ifdef CONFIG_GENERIC_ATOMIC64
 #include <asm-generic/atomic64.h>
 #endif
@@ -1023,6 +1025,8 @@
 }
 #endif
 
+#define atomic64_cond_read_acquire(v, c)	smp_cond_load_acquire(&(v)->counter, (c))
+
 #include <asm-generic/atomic-long.h>
 
 #endif /* _LINUX_ATOMIC_H */
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 45d5522..0fbce32 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -424,6 +424,7 @@
 #define CPUFREQ_START			(2)
 #define CPUFREQ_CREATE_POLICY		(3)
 #define CPUFREQ_REMOVE_POLICY		(4)
+#define CPUFREQ_STOP			(5)
 
 /* Govinfo Notifiers */
 #define CPUFREQ_LOAD_CHANGE		(0)
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index a9a16f2..94c7be2 100644
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
@@ -113,14 +113,19 @@
  * @type:       integer (intval)
  * @value:      0 (USB/USB2) or 1 (USB3)
  * @default:    0 (USB/USB2)
+ * -EXTCON_PROP_USB_PD_CONTRACT
+ * @type:	integer (intval)
+ * @value:	0 (bus powered) or 1 (self powered)
+ * @default:	0 (bus powered)
  *
  */
 #define EXTCON_PROP_USB_VBUS		0
 #define EXTCON_PROP_USB_TYPEC_POLARITY	1
 #define EXTCON_PROP_USB_SS		2
+#define EXTCON_PROP_USB_PD_CONTRACT	3
 
 #define EXTCON_PROP_USB_MIN		0
-#define EXTCON_PROP_USB_MAX		2
+#define EXTCON_PROP_USB_MAX		3
 #define EXTCON_PROP_USB_CNT	(EXTCON_PROP_USB_MAX - EXTCON_PROP_USB_MIN + 1)
 
 /* Properties of EXTCON_TYPE_CHG. */
diff --git a/include/linux/hugetlb_inline.h b/include/linux/hugetlb_inline.h
index a4e7ca0..6cfdfca 100644
--- a/include/linux/hugetlb_inline.h
+++ b/include/linux/hugetlb_inline.h
@@ -7,7 +7,7 @@
 
 static inline bool is_vm_hugetlb_page(struct vm_area_struct *vma)
 {
-	return !!(vma->vm_flags & VM_HUGETLB);
+	return !!(READ_ONCE(vma->vm_flags) & VM_HUGETLB);
 }
 
 #else
diff --git a/include/linux/ipc_router_xprt.h b/include/linux/ipc_router_xprt.h
index c4b7854..bba7179 100644
--- a/include/linux/ipc_router_xprt.h
+++ b/include/linux/ipc_router_xprt.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
@@ -128,6 +128,7 @@
  * @sft_close_done: Method to indicate to the XPRT that handling of reset
  *                  event is complete.
  * @get_ws_info: Method to get the wakeup soruce inforamtion of the XPRT
+ * @get_ws_info: Method to get the latency inforamtion of the XPRT.
  */
 struct msm_ipc_router_xprt {
 	char *name;
@@ -147,6 +148,7 @@
 	int (*close)(struct msm_ipc_router_xprt *xprt);
 	void (*sft_close_done)(struct msm_ipc_router_xprt *xprt);
 	bool (*get_ws_info)(struct msm_ipc_router_xprt *xprt);
+	bool (*get_latency_info)(struct msm_ipc_router_xprt *xprt);
 };
 
 void msm_ipc_router_xprt_notify(struct msm_ipc_router_xprt *xprt,
diff --git a/include/linux/migrate.h b/include/linux/migrate.h
index ae8d475..df8e0b0 100644
--- a/include/linux/migrate.h
+++ b/include/linux/migrate.h
@@ -89,14 +89,14 @@
 #ifdef CONFIG_NUMA_BALANCING
 extern bool pmd_trans_migrating(pmd_t pmd);
 extern int migrate_misplaced_page(struct page *page,
-				  struct vm_area_struct *vma, int node);
+				  struct fault_env *fe, int node);
 #else
 static inline bool pmd_trans_migrating(pmd_t pmd)
 {
 	return false;
 }
 static inline int migrate_misplaced_page(struct page *page,
-					 struct vm_area_struct *vma, int node)
+					 struct fault_env *fe, int node)
 {
 	return -EAGAIN; /* can't migrate now */
 }
diff --git a/include/linux/mm.h b/include/linux/mm.h
index b328cca..e7b9652 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -269,6 +269,11 @@
 /* This mask is used to clear all the VMA flags used by mlock */
 #define VM_LOCKED_CLEAR_MASK	(~(VM_LOCKED | VM_LOCKONFAULT))
 
+#ifdef CONFIG_ARCH_MSM8953_SOC_SETTINGS
+#define MSM8953_TLMM_START_ADDR	0x01000000
+#define MSM8953_TLMM_END_ADDR	(0x01300000 - 1)
+#endif
+
 /*
  * mapping from the currently active vm_flags protection bits (the
  * low four bits) to a page protection mask..
@@ -284,6 +289,9 @@
 #define FAULT_FLAG_USER		0x40	/* The fault originated in userspace */
 #define FAULT_FLAG_REMOTE	0x80	/* faulting for non current tsk/mm */
 #define FAULT_FLAG_INSTRUCTION  0x100	/* The fault was during an instruction fetch */
+/* Speculative fault, not holding mmap_sem */
+#define FAULT_FLAG_SPECULATIVE	0x200
+#define FAULT_FLAG_PREFAULT_OLD 0x400   /* Make faultaround ptes old */
 
 /*
  * vm_fault is filled by the the pagefault handler and passed to the vma's
@@ -300,7 +308,6 @@
 	gfp_t gfp_mask;			/* gfp mask to be used for allocations */
 	pgoff_t pgoff;			/* Logical page offset based on vma */
 	void __user *virtual_address;	/* Faulting virtual address */
-
 	struct page *cow_page;		/* Handler may choose to COW */
 	struct page *page;		/* ->fault handlers should return a
 					 * page here, unless VM_FAULT_NOPAGE
@@ -322,6 +329,7 @@
 struct fault_env {
 	struct vm_area_struct *vma;	/* Target VMA */
 	unsigned long address;		/* Faulting virtual address */
+	unsigned long fault_address;    /* Saved faulting virtual address */
 	unsigned int flags;		/* FAULT_FLAG_xxx flags */
 	pmd_t *pmd;			/* Pointer to pmd entry matching
 					 * the 'address'
@@ -341,12 +349,23 @@
 					 * page table to avoid allocation from
 					 * atomic context.
 					 */
+	/*
+	 * These entries are required when handling speculative page fault.
+	 * This way the page handling is done using consistent field values.
+	 */
+	unsigned long vma_flags;
+	pgprot_t vma_page_prot;
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+	unsigned int sequence;
+	pmd_t orig_pmd;			/* value of PMD at the time of fault */
+	pte_t orig_pte;                 /* Value of PTE at the time of fault */
+#endif
 };
 
 /*
  * These are the virtual MM functions - opening of an area, closing and
  * unmapping it (needed to keep files on disk up-to-date etc), pointer
- * to the functions called when a no-page or a wp-page exception occurs. 
+ * to the functions called when a no-page or a wp-page exception occurs.
  */
 struct vm_operations_struct {
 	void (*open)(struct vm_area_struct * area);
@@ -623,9 +642,9 @@
  * pte_mkwrite.  But get_user_pages can cause write faults for mappings
  * that do not have writing enabled, when used by access_process_vm.
  */
-static inline pte_t maybe_mkwrite(pte_t pte, struct vm_area_struct *vma)
+static inline pte_t maybe_mkwrite(pte_t pte, unsigned long vma_flags)
 {
-	if (likely(vma->vm_flags & VM_WRITE))
+	if (likely(vma_flags & VM_WRITE))
 		pte = pte_mkwrite(pte);
 	return pte;
 }
@@ -1118,6 +1137,7 @@
 #define VM_FAULT_DAX_LOCKED 0x1000	/* ->fault has locked DAX entry */
 
 #define VM_FAULT_HWPOISON_LARGE_MASK 0xf000 /* encodes hpage index for large hwpoison */
+#define VM_FAULT_PTNOTSAME 0x4000	/* Page table entries have changed */
 
 #define VM_FAULT_ERROR	(VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \
 			 VM_FAULT_HWPOISON | VM_FAULT_HWPOISON_LARGE | \
@@ -1167,8 +1187,23 @@
 	pgoff_t last_index;			/* Highest page->index to unmap */
 };
 
-struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
-		pte_t pte);
+struct page *__vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
+			      pte_t pte, unsigned long vma_flags);
+static inline struct page *vm_normal_page(struct vm_area_struct *vma,
+		unsigned long addr, pte_t pte)
+{
+	return __vm_normal_page(vma, addr, pte, vma->vm_flags);
+}
+
+static inline void INIT_VMA(struct vm_area_struct *vma)
+{
+	INIT_LIST_HEAD(&vma->anon_vma_chain);
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+	seqcount_init(&vma->vm_sequence);
+	atomic_set(&vma->vm_ref_count, 1);
+#endif
+}
+
 struct page *vm_normal_page_pmd(struct vm_area_struct *vma, unsigned long addr,
 				pmd_t pmd);
 
@@ -1238,6 +1273,47 @@
 	unmap_mapping_range(mapping, holebegin, holelen, 0);
 }
 
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+static inline void vm_write_begin(struct vm_area_struct *vma)
+{
+	write_seqcount_begin(&vma->vm_sequence);
+}
+static inline void vm_write_begin_nested(struct vm_area_struct *vma,
+					 int subclass)
+{
+	write_seqcount_begin_nested(&vma->vm_sequence, subclass);
+}
+static inline void vm_write_end(struct vm_area_struct *vma)
+{
+	write_seqcount_end(&vma->vm_sequence);
+}
+static inline void vm_raw_write_begin(struct vm_area_struct *vma)
+{
+	raw_write_seqcount_begin(&vma->vm_sequence);
+}
+static inline void vm_raw_write_end(struct vm_area_struct *vma)
+{
+	raw_write_seqcount_end(&vma->vm_sequence);
+}
+#else
+static inline void vm_write_begin(struct vm_area_struct *vma)
+{
+}
+static inline void vm_write_begin_nested(struct vm_area_struct *vma,
+					 int subclass)
+{
+}
+static inline void vm_write_end(struct vm_area_struct *vma)
+{
+}
+static inline void vm_raw_write_begin(struct vm_area_struct *vma)
+{
+}
+static inline void vm_raw_write_end(struct vm_area_struct *vma)
+{
+}
+#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
+
 extern void truncate_pagecache(struct inode *inode, loff_t new);
 extern void truncate_setsize(struct inode *inode, loff_t newsize);
 void pagecache_isize_extended(struct inode *inode, loff_t from, loff_t to);
@@ -1249,6 +1325,43 @@
 #ifdef CONFIG_MMU
 extern int handle_mm_fault(struct vm_area_struct *vma, unsigned long address,
 		unsigned int flags);
+
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+extern int __handle_speculative_fault(struct mm_struct *mm,
+				      unsigned long address,
+				      unsigned int flags,
+				      struct vm_area_struct **vma);
+static inline int handle_speculative_fault(struct mm_struct *mm,
+					   unsigned long address,
+					   unsigned int flags,
+					   struct vm_area_struct **vma)
+{
+	/*
+	 * Try speculative page fault for multithreaded user space task only.
+	 */
+	if (!(flags & FAULT_FLAG_USER) || atomic_read(&mm->mm_users) == 1) {
+		*vma = NULL;
+		return VM_FAULT_RETRY;
+	}
+	return __handle_speculative_fault(mm, address, flags, vma);
+}
+extern bool can_reuse_spf_vma(struct vm_area_struct *vma,
+			      unsigned long address);
+#else
+static inline int handle_speculative_fault(struct mm_struct *mm,
+					   unsigned long address,
+					   unsigned int flags,
+					   struct vm_area_struct **vma)
+{
+	return VM_FAULT_RETRY;
+}
+static inline bool can_reuse_spf_vma(struct vm_area_struct *vma,
+				     unsigned long address)
+{
+	return false;
+}
+#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
+
 extern int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
 			    unsigned long address, unsigned int fault_flags,
 			    bool *unlocked);
@@ -1957,16 +2070,29 @@
 extern int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin);
 extern int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
 	unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert,
-	struct vm_area_struct *expand);
+	struct vm_area_struct *expand, bool keep_locked);
 static inline int vma_adjust(struct vm_area_struct *vma, unsigned long start,
 	unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert)
 {
-	return __vma_adjust(vma, start, end, pgoff, insert, NULL);
+	return __vma_adjust(vma, start, end, pgoff, insert, NULL, false);
 }
-extern struct vm_area_struct *vma_merge(struct mm_struct *,
+
+extern struct vm_area_struct *__vma_merge(struct mm_struct *mm,
 	struct vm_area_struct *prev, unsigned long addr, unsigned long end,
-	unsigned long vm_flags, struct anon_vma *, struct file *, pgoff_t,
-	struct mempolicy *, struct vm_userfaultfd_ctx, const char __user *);
+	unsigned long vm_flags, struct anon_vma *anon, struct file *file,
+	pgoff_t pgoff, struct mempolicy *mpol, struct vm_userfaultfd_ctx uff,
+	const char __user *user, bool keep_locked);
+
+static inline struct vm_area_struct *vma_merge(struct mm_struct *mm,
+	struct vm_area_struct *prev, unsigned long addr, unsigned long end,
+	unsigned long vm_flags, struct anon_vma *anon, struct file *file,
+	pgoff_t off, struct mempolicy *pol, struct vm_userfaultfd_ctx uff,
+	const char __user *user)
+{
+	return __vma_merge(mm, prev, addr, end, vm_flags, anon, file, off,
+			   pol, uff, user, false);
+}
+
 extern struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *);
 extern int split_vma(struct mm_struct *,
 	struct vm_area_struct *, unsigned long addr, int new_below);
@@ -2465,6 +2591,8 @@
 static inline void setup_nr_node_ids(void) {}
 #endif
 
+extern int want_old_faultaround_pte;
+
 #ifdef CONFIG_PROCESS_RECLAIM
 struct reclaim_param {
 	struct vm_area_struct *vma;
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 5942478..cb2cc30 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -365,6 +365,10 @@
 	struct mempolicy *vm_policy;	/* NUMA policy for the VMA */
 #endif
 	struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+	seqcount_t vm_sequence;
+	atomic_t vm_ref_count;		/* see vma_get(), vma_put() */
+#endif
 };
 
 struct core_thread {
@@ -403,6 +407,9 @@
 struct mm_struct {
 	struct vm_area_struct *mmap;		/* list of VMAs */
 	struct rb_root mm_rb;
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+	rwlock_t mm_rb_lock;
+#endif
 	u32 vmacache_seqnum;                   /* per-thread vmacache */
 #ifdef CONFIG_MMU
 	unsigned long (*get_unmapped_area) (struct file *filp,
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 791c547..9dbf9c3 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -427,8 +427,8 @@
 	pgoff_t pgoff;
 	if (unlikely(is_vm_hugetlb_page(vma)))
 		return linear_hugepage_index(vma, address);
-	pgoff = (address - vma->vm_start) >> PAGE_SHIFT;
-	pgoff += vma->vm_pgoff;
+	pgoff = (address - READ_ONCE(vma->vm_start)) >> PAGE_SHIFT;
+	pgoff += READ_ONCE(vma->vm_pgoff);
 	return pgoff;
 }
 
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 25d7806..9412480 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -131,6 +131,12 @@
 	POWER_SUPPLY_PD_PPS_ACTIVE,
 };
 
+enum {
+	POWER_SUPPLY_QC_CTM_DISABLE = BIT(0),
+	POWER_SUPPLY_QC_THERMAL_BALANCE_DISABLE = BIT(1),
+	POWER_SUPPLY_QC_INOV_THERMAL_DISABLE = BIT(2),
+};
+
 enum power_supply_property {
 	/* Properties of type `int' */
 	POWER_SUPPLY_PROP_STATUS = 0,
@@ -295,6 +301,7 @@
 	POWER_SUPPLY_PROP_ESR_ACTUAL,
 	POWER_SUPPLY_PROP_ESR_NOMINAL,
 	POWER_SUPPLY_PROP_SOH,
+	POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
 	/* Local extensions of type int64_t */
 	POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
 	/* Properties of type `const char *' */
diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h
index b8dd63a..886b7d6 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -40,6 +40,7 @@
 
 /**
  * struct geni_se_rsc - GENI Serial Engine Resource
+ * @ctrl_dev		Pointer to controller device.
  * @wrapper_dev:	Pointer to the parent QUPv3 core.
  * @se_clk:		Handle to the core serial engine clock.
  * @m_ahb_clk:		Handle to the primary AHB clock.
@@ -53,6 +54,7 @@
  * @geni_gpi_sleep:	Handle to the sleep pinctrl state.
  */
 struct se_geni_rsc {
+	struct device *ctrl_dev;
 	struct device *wrapper_dev;
 	struct clk *se_clk;
 	struct clk *m_ahb_clk;
diff --git a/include/linux/rmap.h b/include/linux/rmap.h
index 71fd2b3..92a297c 100644
--- a/include/linux/rmap.h
+++ b/include/linux/rmap.h
@@ -168,8 +168,16 @@
 		unsigned long, bool);
 void do_page_add_anon_rmap(struct page *, struct vm_area_struct *,
 			   unsigned long, int);
-void page_add_new_anon_rmap(struct page *, struct vm_area_struct *,
-		unsigned long, bool);
+void __page_add_new_anon_rmap(struct page *page, struct vm_area_struct *vma,
+			      unsigned long address, bool compound);
+static inline void page_add_new_anon_rmap(struct page *page,
+					  struct vm_area_struct *vma,
+					  unsigned long address, bool compound)
+{
+	VM_BUG_ON_VMA(address < vma->vm_start || address >= vma->vm_end, vma);
+	__page_add_new_anon_rmap(page, vma, address, compound);
+}
+
 void page_add_file_rmap(struct page *, bool);
 void page_remove_rmap(struct page *, bool);
 
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 92d1fde..7b488ec 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -313,8 +313,14 @@
 
 extern void add_page_to_unevictable_list(struct page *page);
 
-extern void lru_cache_add_active_or_unevictable(struct page *page,
-						struct vm_area_struct *vma);
+extern void __lru_cache_add_active_or_unevictable(struct page *page,
+						unsigned long vma_flags);
+
+static inline void lru_cache_add_active_or_unevictable(struct page *page,
+						struct vm_area_struct *vma)
+{
+	return __lru_cache_add_active_or_unevictable(page, vma->vm_flags);
+}
 
 /* linux/mm/vmscan.c */
 extern unsigned long zone_reclaimable_pages(struct zone *zone);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 3f3a7e4..0267bed 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -539,6 +539,7 @@
 	u32				extra_buf_alloc;
 	bool				l1_supported;
 	bool				is_chipidea;
+	bool				self_powered;
 };
 #define work_to_gadget(w)	(container_of((w), struct usb_gadget, work))
 
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index d4f1759..2393c13 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -180,6 +180,8 @@
 		nominal mode.
  * @sdp_check: SDP detection work in case of USB_FLOAT power supply
  * @notify_charger_work: Charger notification work.
+ * @extcon_register_work: Extcon registration work.
+ * @psy_nb: Notification callback for PSY registration.
  */
 struct msm_otg {
 	struct usb_phy phy;
@@ -313,6 +315,8 @@
 	struct delayed_work perf_vote_work;
 	struct delayed_work sdp_check;
 	struct work_struct notify_charger_work;
+	struct work_struct extcon_register_work;
+	struct notifier_block psy_nb;
 };
 
 struct ci13xxx_platform_data {
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index a9c2e4c..4c679792 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -99,6 +99,9 @@
 		VMACACHE_FIND_HITS,
 		VMACACHE_FULL_FLUSHES,
 #endif
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+		SPECULATIVE_PGFAULT,
+#endif
 		NR_VM_EVENT_ITEMS
 };
 
diff --git a/include/net/cnss.h b/include/net/cnss.h
index 368d01e..3b864fc 100644
--- a/include/net/cnss.h
+++ b/include/net/cnss.h
@@ -102,11 +102,14 @@
 	u32 cap_flag;
 };
 
-/* WLAN driver status */
+/* WLAN driver status, keep it aligned with cnss2 */
 enum cnss_driver_status {
 	CNSS_UNINITIALIZED,
 	CNSS_INITIALIZED,
-	CNSS_LOAD_UNLOAD
+	CNSS_LOAD_UNLOAD,
+	CNSS_RECOVERY,
+	CNSS_FW_DOWN,
+	CNSS_SSR_FAIL,
 };
 
 enum cnss_runtime_request {
@@ -120,6 +123,8 @@
 	CNSS_PM_GET_NORESUME,
 };
 
+extern struct dma_iommu_mapping *cnss_smmu_get_mapping(void);
+extern int cnss_smmu_map(phys_addr_t paddr, uint32_t *iova_addr, size_t size);
 extern int cnss_get_fw_image(struct image_desc_info *image_desc_info);
 extern void cnss_runtime_init(struct device *dev, int auto_delay);
 extern void cnss_runtime_exit(struct device *dev);
diff --git a/include/net/cnss2.h b/include/net/cnss2.h
index 9dbf449..342907d 100644
--- a/include/net/cnss2.h
+++ b/include/net/cnss2.h
@@ -182,7 +182,7 @@
 			    enum cnss_driver_mode mode,
 			    const char *host_version);
 extern int cnss_wlan_disable(struct device *dev, enum cnss_driver_mode mode);
-extern unsigned int cnss_get_qmi_timeout(void);
+extern unsigned int cnss_get_boot_timeout(struct device *dev);
 extern int cnss_athdiag_read(struct device *dev, uint32_t offset,
 			     uint32_t mem_type, uint32_t data_len,
 			     uint8_t *output);
diff --git a/include/soc/qcom/icnss.h b/include/soc/qcom/icnss.h
index 31b4cce..7ef3db4 100644
--- a/include/soc/qcom/icnss.h
+++ b/include/soc/qcom/icnss.h
@@ -142,5 +142,6 @@
 extern bool icnss_is_qmi_disable(struct device *dev);
 extern bool icnss_is_fw_ready(void);
 extern bool icnss_is_fw_down(void);
+extern bool icnss_is_rejuvenate(void);
 extern int icnss_trigger_recovery(struct device *dev);
 #endif /* _ICNSS_WLAN_H_ */
diff --git a/include/trace/events/pagefault.h b/include/trace/events/pagefault.h
new file mode 100644
index 0000000..a9643b3
--- /dev/null
+++ b/include/trace/events/pagefault.h
@@ -0,0 +1,88 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM pagefault
+
+#if !defined(_TRACE_PAGEFAULT_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_PAGEFAULT_H
+
+#include <linux/tracepoint.h>
+#include <linux/mm.h>
+
+DECLARE_EVENT_CLASS(spf,
+
+	TP_PROTO(unsigned long caller,
+		 struct vm_area_struct *vma, unsigned long address),
+
+	TP_ARGS(caller, vma, address),
+
+	TP_STRUCT__entry(
+		__field(unsigned long, caller)
+		__field(unsigned long, vm_start)
+		__field(unsigned long, vm_end)
+		__field(unsigned long, address)
+	),
+
+	TP_fast_assign(
+		__entry->caller		= caller;
+		__entry->vm_start	= vma->vm_start;
+		__entry->vm_end		= vma->vm_end;
+		__entry->address	= address;
+	),
+
+	TP_printk("ip:%lx vma:%lx-%lx address:%lx",
+		  __entry->caller, __entry->vm_start, __entry->vm_end,
+		  __entry->address)
+);
+
+DEFINE_EVENT(spf, spf_pte_lock,
+
+	TP_PROTO(unsigned long caller,
+		 struct vm_area_struct *vma, unsigned long address),
+
+	TP_ARGS(caller, vma, address)
+);
+
+DEFINE_EVENT(spf, spf_vma_changed,
+
+	TP_PROTO(unsigned long caller,
+		 struct vm_area_struct *vma, unsigned long address),
+
+	TP_ARGS(caller, vma, address)
+);
+
+DEFINE_EVENT(spf, spf_vma_noanon,
+
+	TP_PROTO(unsigned long caller,
+		 struct vm_area_struct *vma, unsigned long address),
+
+	TP_ARGS(caller, vma, address)
+);
+
+DEFINE_EVENT(spf, spf_vma_notsup,
+
+	TP_PROTO(unsigned long caller,
+		 struct vm_area_struct *vma, unsigned long address),
+
+	TP_ARGS(caller, vma, address)
+);
+
+DEFINE_EVENT(spf, spf_vma_access,
+
+	TP_PROTO(unsigned long caller,
+		 struct vm_area_struct *vma, unsigned long address),
+
+	TP_ARGS(caller, vma, address)
+);
+
+DEFINE_EVENT(spf, spf_pmd_changed,
+
+	TP_PROTO(unsigned long caller,
+		 struct vm_area_struct *vma, unsigned long address),
+
+	TP_ARGS(caller, vma, address)
+);
+
+#endif /* _TRACE_PAGEFAULT_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index b355ebf..b3ec962 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -657,6 +657,10 @@
 		__field(unsigned int, capacity_orig		)
 		__field(int, idle_state				)
 		__field(u64, irqload				)
+		__field(int, online				)
+		__field(int, isolated				)
+		__field(int, reserved				)
+		__field(int, high_irq_load			)
 	),
 
 	TP_fast_assign(
@@ -669,10 +673,14 @@
 		__entry->capacity_orig		= capacity_orig_of(cpu);
 		__entry->idle_state		= idle_get_state_idx(cpu_rq(cpu));
 		__entry->irqload		= sched_irqload(cpu);
+		__entry->online			= cpu_online(cpu);
+		__entry->isolated		= cpu_isolated(cpu);
+		__entry->reserved		= is_reserved(cpu);
+		__entry->high_irq_load          = sched_cpu_high_irqload(cpu);
 	),
 
-	TP_printk("cpu=%d nr_running=%d cpu_util=%ld cpu_util_cum=%ld capacity_curr=%u capacity=%u capacity_orig=%u idle_state=%d irqload=%llu",
-		__entry->cpu, __entry->nr_running, __entry->cpu_util, __entry->cpu_util_cum, __entry->capacity_curr, __entry->capacity, __entry->capacity_orig, __entry->idle_state, __entry->irqload)
+	TP_printk("cpu=%d nr_running=%d cpu_util=%ld cpu_util_cum=%ld capacity_curr=%u capacity=%u capacity_orig=%u idle_state=%d irqload=%llu online=%u isolated=%u reserved=%u high_irq_load=%u",
+		__entry->cpu, __entry->nr_running, __entry->cpu_util, __entry->cpu_util_cum, __entry->capacity_curr, __entry->capacity, __entry->capacity_orig, __entry->idle_state, __entry->irqload, __entry->online, __entry->isolated, __entry->reserved, __entry->high_irq_load)
 );
 
 TRACE_EVENT(sched_energy_diff,
@@ -1637,10 +1645,11 @@
 
 	TP_PROTO(struct task_struct *tsk, bool prefer_idle,
 		unsigned long min_util, int start_cpu,
-		int best_idle, int best_active, int target),
+		int best_idle, int best_active, int target,
+		int backup_cpu),
 
 	TP_ARGS(tsk, prefer_idle, min_util, start_cpu,
-		best_idle, best_active, target),
+		best_idle, best_active, target, backup_cpu),
 
 	TP_STRUCT__entry(
 		__array( char,	comm,	TASK_COMM_LEN	)
@@ -1651,6 +1660,7 @@
 		__field( int,	best_idle		)
 		__field( int,	best_active		)
 		__field( int,	target			)
+		__field( int,	backup_cpu		)
 	),
 
 	TP_fast_assign(
@@ -1662,14 +1672,16 @@
 		__entry->best_idle	= best_idle;
 		__entry->best_active	= best_active;
 		__entry->target		= target;
+		__entry->backup_cpu	= backup_cpu;
 	),
 
 	TP_printk("pid=%d comm=%s prefer_idle=%d start_cpu=%d "
-		  "best_idle=%d best_active=%d target=%d",
+		  "best_idle=%d best_active=%d target=%d backup=%d",
 		__entry->pid, __entry->comm,
 		__entry->prefer_idle, __entry->start_cpu,
 		__entry->best_idle, __entry->best_active,
-		__entry->target)
+		__entry->target,
+		__entry->backup_cpu)
 );
 
 TRACE_EVENT(sched_group_energy,
diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h
index be4cb02..34ecd82 100644
--- a/include/uapi/linux/msm_ipa.h
+++ b/include/uapi/linux/msm_ipa.h
@@ -520,7 +520,13 @@
 	BRIDGE_VLAN_MAPPING_MAX
 };
 
-#define IPA_EVENT_MAX_NUM (BRIDGE_VLAN_MAPPING_MAX)
+enum ipa_wlan_fw_ssr_event {
+	WLAN_FWR_SSR_BEFORE_SHUTDOWN = BRIDGE_VLAN_MAPPING_MAX,
+	IPA_WLAN_FW_SSR_EVENT_MAX
+#define IPA_WLAN_FW_SSR_EVENT_MAX IPA_WLAN_FW_SSR_EVENT_MAX
+};
+
+#define IPA_EVENT_MAX_NUM (IPA_WLAN_FW_SSR_EVENT_MAX)
 #define IPA_EVENT_MAX ((int)IPA_EVENT_MAX_NUM)
 
 /**
diff --git a/include/uapi/linux/qg.h b/include/uapi/linux/qg.h
index 40882a7..54aa362 100644
--- a/include/uapi/linux/qg.h
+++ b/include/uapi/linux/qg.h
@@ -20,7 +20,7 @@
 	QG_ESR_DISCHARGE_SF,
 	QG_FULL_SOC,
 	QG_CLEAR_LEARNT_DATA,
-	QG_RESERVED_9,
+	QG_SYS_SOC,
 	QG_RESERVED_10,
 	QG_MAX,
 };
@@ -33,6 +33,7 @@
 #define QG_ESR_DISCHARGE_SF QG_ESR_DISCHARGE_SF
 #define QG_FULL_SOC QG_FULL_SOC
 #define QG_CLEAR_LEARNT_DATA QG_CLEAR_LEARNT_DATA
+#define QG_SYS_SOC QG_SYS_SOC
 
 struct fifo_data {
 	unsigned int			v;
diff --git a/include/uapi/media/cam_icp.h b/include/uapi/media/cam_icp.h
index cd2d2d2..680d05b 100644
--- a/include/uapi/media/cam_icp.h
+++ b/include/uapi/media/cam_icp.h
@@ -59,8 +59,9 @@
 /* Command meta types */
 #define CAM_ICP_CMD_META_GENERIC_BLOB           0x1
 
-/* Generic blon types */
+/* Generic blob types */
 #define CAM_ICP_CMD_GENERIC_BLOB_CLK            0x1
+#define CAM_ICP_CMD_GENERIC_BLOB_CFG_IO         0x2
 
 /**
  * struct cam_icp_clk_bw_request
diff --git a/include/uapi/media/msm_media_info.h b/include/uapi/media/msm_media_info.h
index 3fd0c88..796d6d2 100644
--- a/include/uapi/media/msm_media_info.h
+++ b/include/uapi/media/msm_media_info.h
@@ -1261,8 +1261,11 @@
 		size = MSM_MEDIA_ALIGN(size, 4096);
 
 		/* Additional size to cover last row of non-aligned frame */
-		size += MSM_MEDIA_ALIGN(width, w_alignment) * w_alignment;
-		size = MSM_MEDIA_ALIGN(size, 4096);
+		if (width >= 2400 && height >= 2400) {
+			size += MSM_MEDIA_ALIGN(width, w_alignment) *
+					w_alignment;
+			size = MSM_MEDIA_ALIGN(size, 4096);
+		}
 		break;
 	case COLOR_FMT_P010:
 		uv_alignment = 4096;
@@ -1302,8 +1305,11 @@
 		size = MSM_MEDIA_ALIGN(size, 4096);
 
 		/* Additional size to cover last row of non-aligned frame */
-		size += MSM_MEDIA_ALIGN(width, w_alignment) * w_alignment;
-		size = MSM_MEDIA_ALIGN(size, 4096);
+		if (width >= 2400 && height >= 2400) {
+			size += MSM_MEDIA_ALIGN(width, w_alignment) *
+					w_alignment;
+			size = MSM_MEDIA_ALIGN(size, 4096);
+		}
 		break;
 	case COLOR_FMT_NV12_BPP10_UBWC:
 		y_ubwc_plane = MSM_MEDIA_ALIGN(y_stride * y_sclines, 4096);
diff --git a/kernel/fork.c b/kernel/fork.c
index 79fdfd8..965c091 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -614,7 +614,7 @@
 		if (!tmp)
 			goto fail_nomem;
 		*tmp = *mpnt;
-		INIT_LIST_HEAD(&tmp->anon_vma_chain);
+		INIT_VMA(tmp);
 		retval = vma_dup_policy(mpnt, tmp);
 		if (retval)
 			goto fail_nomem_policy;
@@ -764,6 +764,9 @@
 	mm->mmap = NULL;
 	mm->mm_rb = RB_ROOT;
 	mm->vmacache_seqnum = 0;
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+	rwlock_init(&mm->mm_rb_lock);
+#endif
 	atomic_set(&mm->mm_users, 1);
 	atomic_set(&mm->mm_count, 1);
 	init_rwsem(&mm->mmap_sem);
diff --git a/kernel/locking/qrwlock.c b/kernel/locking/qrwlock.c
index 19248dd..c7471c3 100644
--- a/kernel/locking/qrwlock.c
+++ b/kernel/locking/qrwlock.c
@@ -20,51 +20,14 @@
 #include <linux/cpumask.h>
 #include <linux/percpu.h>
 #include <linux/hardirq.h>
+#include <linux/spinlock.h>
 #include <asm/qrwlock.h>
 
-/*
- * This internal data structure is used for optimizing access to some of
- * the subfields within the atomic_t cnts.
- */
-struct __qrwlock {
-	union {
-		atomic_t cnts;
-		struct {
-#ifdef __LITTLE_ENDIAN
-			u8 wmode;	/* Writer mode   */
-			u8 rcnts[3];	/* Reader counts */
-#else
-			u8 rcnts[3];	/* Reader counts */
-			u8 wmode;	/* Writer mode   */
-#endif
-		};
-	};
-	arch_spinlock_t	lock;
-};
-
-/**
- * rspin_until_writer_unlock - inc reader count & spin until writer is gone
- * @lock  : Pointer to queue rwlock structure
- * @writer: Current queue rwlock writer status byte
- *
- * In interrupt context or at the head of the queue, the reader will just
- * increment the reader count & wait until the writer releases the lock.
- */
-static __always_inline void
-rspin_until_writer_unlock(struct qrwlock *lock, u32 cnts)
-{
-	while ((cnts & _QW_WMASK) == _QW_LOCKED) {
-		cpu_relax_lowlatency();
-		cnts = atomic_read_acquire(&lock->cnts);
-	}
-}
-
 /**
  * queued_read_lock_slowpath - acquire read lock of a queue rwlock
  * @lock: Pointer to queue rwlock structure
- * @cnts: Current qrwlock lock value
  */
-void queued_read_lock_slowpath(struct qrwlock *lock, u32 cnts)
+void queued_read_lock_slowpath(struct qrwlock *lock)
 {
 	/*
 	 * Readers come here when they cannot get the lock without waiting
@@ -72,13 +35,11 @@
 	if (unlikely(in_interrupt())) {
 		/*
 		 * Readers in interrupt context will get the lock immediately
-		 * if the writer is just waiting (not holding the lock yet).
-		 * The rspin_until_writer_unlock() function returns immediately
-		 * in this case. Otherwise, they will spin (with ACQUIRE
-		 * semantics) until the lock is available without waiting in
-		 * the queue.
+		 * if the writer is just waiting (not holding the lock yet),
+		 * so spin with ACQUIRE semantics until the lock is available
+		 * without waiting in the queue.
 		 */
-		rspin_until_writer_unlock(lock, cnts);
+		atomic_cond_read_acquire(&lock->cnts, !(VAL & _QW_LOCKED));
 		return;
 	}
 	atomic_sub(_QR_BIAS, &lock->cnts);
@@ -87,14 +48,14 @@
 	 * Put the reader into the wait queue
 	 */
 	arch_spin_lock(&lock->wait_lock);
+	atomic_add(_QR_BIAS, &lock->cnts);
 
 	/*
 	 * The ACQUIRE semantics of the following spinning code ensure
 	 * that accesses can't leak upwards out of our subsequent critical
 	 * section in the case that the lock is currently held for write.
 	 */
-	cnts = atomic_fetch_add_acquire(_QR_BIAS, &lock->cnts);
-	rspin_until_writer_unlock(lock, cnts);
+	atomic_cond_read_acquire(&lock->cnts, !(VAL & _QW_LOCKED));
 
 	/*
 	 * Signal the next one in queue to become queue head
@@ -109,8 +70,6 @@
  */
 void queued_write_lock_slowpath(struct qrwlock *lock)
 {
-	u32 cnts;
-
 	/* Put the writer into the wait queue */
 	arch_spin_lock(&lock->wait_lock);
 
@@ -119,30 +78,14 @@
 	    (atomic_cmpxchg_acquire(&lock->cnts, 0, _QW_LOCKED) == 0))
 		goto unlock;
 
-	/*
-	 * Set the waiting flag to notify readers that a writer is pending,
-	 * or wait for a previous writer to go away.
-	 */
-	for (;;) {
-		struct __qrwlock *l = (struct __qrwlock *)lock;
+	/* Set the waiting flag to notify readers that a writer is pending */
+	atomic_add(_QW_WAITING, &lock->cnts);
 
-		if (!READ_ONCE(l->wmode) &&
-		   (cmpxchg_relaxed(&l->wmode, 0, _QW_WAITING) == 0))
-			break;
-
-		cpu_relax_lowlatency();
-	}
-
-	/* When no more readers, set the locked flag */
-	for (;;) {
-		cnts = atomic_read(&lock->cnts);
-		if ((cnts == _QW_WAITING) &&
-		    (atomic_cmpxchg_acquire(&lock->cnts, _QW_WAITING,
-					    _QW_LOCKED) == _QW_WAITING))
-			break;
-
-		cpu_relax_lowlatency();
-	}
+	/* When no more readers or writers, set the locked flag */
+	do {
+		atomic_cond_read_acquire(&lock->cnts, VAL == _QW_WAITING);
+	} while (atomic_cmpxchg_relaxed(&lock->cnts, _QW_WAITING,
+					_QW_LOCKED) != _QW_WAITING);
 unlock:
 	arch_spin_unlock(&lock->wait_lock);
 }
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index fb2e56c..b755eb8 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -2172,7 +2172,7 @@
 	rq = cpu_rq(task_cpu(p));
 	raw_spin_lock(&rq->lock);
 	old_load = task_load(p);
-	wallclock = ktime_get_ns();
+	wallclock = sched_ktime_clock();
 	update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
 	update_task_ravg(p, rq, TASK_WAKE, wallclock, 0);
 	raw_spin_unlock(&rq->lock);
@@ -2259,7 +2259,7 @@
 	trace_sched_waking(p);
 
 	if (!task_on_rq_queued(p)) {
-		u64 wallclock = ktime_get_ns();
+		u64 wallclock = sched_ktime_clock();
 
 		update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
 		update_task_ravg(p, rq, TASK_WAKE, wallclock, 0);
@@ -3261,7 +3261,7 @@
 	old_load = task_load(curr);
 	set_window_start(rq);
 
-	wallclock = ktime_get_ns();
+	wallclock = sched_ktime_clock();
 	update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
 
 	update_rq_clock(rq);
@@ -3633,7 +3633,7 @@
 	clear_preempt_need_resched();
 	rq->clock_skip_update = 0;
 
-	wallclock = ktime_get_ns();
+	wallclock = sched_ktime_clock();
 	if (likely(prev != next)) {
 		if (!prev->on_rq)
 			prev->last_sleep_ts = wallclock;
@@ -9611,7 +9611,7 @@
 	rq = task_rq_lock(p, &rf);
 
 	/* rq->curr == p */
-	wallclock = ktime_get_ns();
+	wallclock = sched_ktime_clock();
 	update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
 	dequeue_task(rq, p, 0);
 	/*
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 83fb0b1..dc9518b 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -465,7 +465,7 @@
 	mutex_lock(&sg_policy->work_lock);
 	raw_spin_lock_irqsave(&sg_policy->update_lock, flags);
 	sugov_track_cycles(sg_policy, sg_policy->policy->cur,
-			   ktime_get_ns());
+			   sched_ktime_clock());
 	raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags);
 	__cpufreq_driver_target(sg_policy->policy, sg_policy->next_freq,
 				CPUFREQ_RELATION_L);
@@ -918,7 +918,7 @@
 		mutex_lock(&sg_policy->work_lock);
 		raw_spin_lock_irqsave(&sg_policy->update_lock, flags);
 		sugov_track_cycles(sg_policy, sg_policy->policy->cur,
-				   ktime_get_ns());
+				   sched_ktime_clock());
 		raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags);
 		cpufreq_policy_apply_limits(policy);
 		mutex_unlock(&sg_policy->work_lock);
diff --git a/kernel/sched/energy.c b/kernel/sched/energy.c
index 77d8361..01daf82 100644
--- a/kernel/sched/energy.c
+++ b/kernel/sched/energy.c
@@ -25,6 +25,7 @@
 #include <linux/sched_energy.h>
 #include <linux/stddef.h>
 #include <linux/cpu.h>
+#include <linux/cpuset.h>
 #include <linux/pm_opp.h>
 #include <linux/platform_device.h>
 
@@ -49,6 +50,17 @@
 	}
 }
 
+static int update_topology;
+
+/*
+ * Ideally this should be arch specific implementation,
+ * let's define here to help rebuild sched_domain with new capacities.
+ */
+int arch_update_cpu_topology(void)
+{
+	return update_topology;
+}
+
 void init_sched_energy_costs(void)
 {
 	struct device_node *cn, *cp;
@@ -273,8 +285,22 @@
 
 	kfree(max_frequencies);
 
-	if (is_sge_valid)
+	if (is_sge_valid) {
+		/*
+		 * Sched_domains might have built with default cpu capacity
+		 * values on bootup.
+		 *
+		 * Let's rebuild them again with actual cpu capacities.
+		 * And partition_sched_domain() expects update in cpu topology
+		 * to rebuild the domains, so make it satisfied..
+		 */
+		update_topology = 1;
+		rebuild_sched_domains();
+		update_topology = 0;
+
 		walt_sched_energy_populated_callback();
+	}
+
 	dev_info(&pdev->dev, "Sched-energy-costs capacity updated\n");
 	return 0;
 
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index b0e962b..91a909f 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6930,6 +6930,8 @@
 	int target_cpu = -1;
 	int cpu, i;
 	unsigned int active_cpus_count = 0;
+	int isolated_candidate = -1;
+	int prev_cpu = task_cpu(p);
 
 	*backup_cpu = -1;
 
@@ -6975,16 +6977,18 @@
 			unsigned long wake_util, new_util, min_capped_util;
 
 			cpumask_clear_cpu(i, &search_cpus);
-			if (avoid_prev_cpu && i == task_cpu(p))
-				continue;
-
-			if (!cpu_online(i) || cpu_isolated(i) || is_reserved(i))
-				continue;
-
-			if (walt_cpu_high_irqload(i))
-				continue;
 
 			trace_sched_cpu_util(i);
+			if (!cpu_online(i) || cpu_isolated(i))
+				continue;
+
+			isolated_candidate = i;
+
+			if (avoid_prev_cpu && i == prev_cpu)
+				continue;
+
+			if (walt_cpu_high_irqload(i) || is_reserved(i))
+				continue;
 
 			/*
 			 * p's blocked utilization is still accounted for on prev_cpu
@@ -7054,7 +7058,8 @@
 					trace_sched_find_best_target(p,
 							prefer_idle, min_util,
 							cpu, best_idle_cpu,
-							best_active_cpu, i);
+							best_active_cpu,
+							i, -1);
 
 					return i;
 				}
@@ -7231,7 +7236,7 @@
 
 	if (best_idle_cpu != -1 && !is_packing_eligible(p, target_cpu, fbt_env,
 					active_cpus_count, best_idle_cstate)) {
-		if (target_cpu == task_cpu(p))
+		if (target_cpu == prev_cpu)
 			fbt_env->avoid_prev_cpu = true;
 
 		target_cpu = best_idle_cpu;
@@ -7267,9 +7272,31 @@
 		? best_active_cpu
 		: best_idle_cpu;
 
+	if (target_cpu == -1 && cpu_isolated(prev_cpu) &&
+			isolated_candidate != -1) {
+		target_cpu = isolated_candidate;
+		fbt_env->avoid_prev_cpu = true;
+	}
+
+	/*
+	 * - It is possible for target and backup
+	 *   to select same CPU - if so, drop backup
+	 *
+	 * - The next step of energy evaluation includes
+	 *   prev_cpu. Drop target or backup if it is
+	 *   same as prev_cpu.
+	 */
+	if (*backup_cpu == target_cpu || *backup_cpu == prev_cpu)
+		*backup_cpu = -1;
+
+	if (target_cpu == prev_cpu) {
+		target_cpu = *backup_cpu;
+		*backup_cpu = -1;
+	}
+
 	trace_sched_find_best_target(p, prefer_idle, min_util, cpu,
 				     best_idle_cpu, best_active_cpu,
-				     target_cpu);
+				     target_cpu, *backup_cpu);
 
 	schedstat_inc(p->se.statistics.nr_wakeups_fbt_count);
 	schedstat_inc(this_rq()->eas_stats.fbt_count);
@@ -7442,12 +7469,10 @@
 		goto out;
 	}
 
-	rcu_read_lock();
-
 	sd = rcu_dereference(per_cpu(sd_ea, prev_cpu));
 	if (!sd) {
 		target_cpu = prev_cpu;
-		goto unlock;
+		goto out;
 	}
 
 	sync_entity_load_avg(&p->se);
@@ -7457,14 +7482,14 @@
 				    &fbt_env);
 	if (next_cpu == -1) {
 		target_cpu = prev_cpu;
-		goto unlock;
+		goto out;
 	}
 
 	if (fbt_env.placement_boost || fbt_env.need_idle ||
 			fbt_env.avoid_prev_cpu || (rtg_target &&
 			!cpumask_test_cpu(prev_cpu, rtg_target))) {
 		target_cpu = next_cpu;
-		goto unlock;
+		goto out;
 	}
 
 	/* Unconditionally prefer IDLE CPUs for boosted/prefer_idle tasks */
@@ -7472,7 +7497,7 @@
 		schedstat_inc(p->se.statistics.nr_wakeups_secb_idle_bt);
 		schedstat_inc(this_rq()->eas_stats.secb_idle_bt);
 		target_cpu = next_cpu;
-		goto unlock;
+		goto out;
 	}
 
 	target_cpu = prev_cpu;
@@ -7506,7 +7531,7 @@
 			schedstat_inc(p->se.statistics.nr_wakeups_secb_insuff_cap);
 			schedstat_inc(this_rq()->eas_stats.secb_insuff_cap);
 			target_cpu = next_cpu;
-			goto unlock;
+			goto out;
 		}
 
 		/* Check if EAS_CPU_NXT is a more energy efficient CPU */
@@ -7514,20 +7539,18 @@
 			schedstat_inc(p->se.statistics.nr_wakeups_secb_nrg_sav);
 			schedstat_inc(this_rq()->eas_stats.secb_nrg_sav);
 			target_cpu = eenv.cpu[eenv.next_idx].cpu_id;
-			goto unlock;
+			goto out;
 		}
 
 		schedstat_inc(p->se.statistics.nr_wakeups_secb_no_nrg_sav);
 		schedstat_inc(this_rq()->eas_stats.secb_no_nrg_sav);
 		target_cpu = prev_cpu;
-		goto unlock;
+		goto out;
 	}
 
 	schedstat_inc(p->se.statistics.nr_wakeups_secb_count);
 	schedstat_inc(this_rq()->eas_stats.secb_count);
 
-unlock:
-	rcu_read_unlock();
 out:
 	trace_sched_task_util(p, next_cpu, backup_cpu, target_cpu, sync,
 			      fbt_env.need_idle, fastpath,
@@ -7563,8 +7586,12 @@
 			cpumask_test_cpu(cpu, tsk_cpus_allowed(p)));
 	}
 
-	if (energy_aware())
-		return select_energy_cpu_brute(p, prev_cpu, sync);
+	if (energy_aware()) {
+		rcu_read_lock();
+		new_cpu = select_energy_cpu_brute(p, prev_cpu, sync);
+		rcu_read_unlock();
+		return new_cpu;
+	}
 
 	rcu_read_lock();
 	for_each_domain(cpu, tmp) {
@@ -9700,8 +9727,11 @@
 	if (busiest->group_type == group_imbalanced)
 		goto force_balance;
 
-	/* SD_BALANCE_NEWIDLE trumps SMP nice when underutilized */
-	if (env->idle == CPU_NEWLY_IDLE && group_has_capacity(env, local) &&
+	/*
+	 * When dst_cpu is idle, prevent SMP nice and/or asymmetric group
+	 * capacities from resulting in underutilization due to avg_load.
+	 */
+	if (env->idle != CPU_NOT_IDLE && group_has_capacity(env, local) &&
 	    busiest->group_no_capacity)
 		goto force_balance;
 
@@ -11811,7 +11841,7 @@
 	if (is_max_capacity_cpu(src_cpu))
 		return;
 
-	wc = ktime_get_ns();
+	wc = sched_ktime_clock();
 	for_each_possible_cpu(i) {
 		struct rq *rq = cpu_rq(i);
 
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 44c767a..95b68bd 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -1805,7 +1805,6 @@
 				}
 			}
 		} while (sg = sg->next, sg != sd->groups);
-		rcu_read_unlock();
 
 		if (sg_target) {
 			cpumask_and(&search_cpu, lowest_mask,
@@ -1894,6 +1893,7 @@
 		}
 
 		if (best_cpu != -1 && placement_boost != SCHED_BOOST_ON_ALL) {
+			rcu_read_unlock();
 			return best_cpu;
 		} else if (!cpumask_empty(&backup_search_cpu)) {
 			cpumask_copy(&search_cpu, &backup_search_cpu);
@@ -1902,6 +1902,7 @@
 			placement_boost = SCHED_BOOST_NONE;
 			goto retry;
 		}
+		rcu_read_unlock();
 	}
 
 noea:
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index d73dfae..e24df36 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -2234,8 +2234,13 @@
 #endif /* CONFIG_IRQ_TIME_ACCOUNTING */
 
 #ifdef CONFIG_SCHED_WALT
+u64 sched_ktime_clock(void);
 void note_task_waking(struct task_struct *p, u64 wallclock);
 #else /* CONFIG_SCHED_WALT */
+static inline u64 sched_ktime_clock(void)
+{
+	return 0;
+}
 static inline void note_task_waking(struct task_struct *p, u64 wallclock) { }
 #endif /* CONFIG_SCHED_WALT */
 
@@ -2276,7 +2281,7 @@
 	data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data,
 					cpu_of(rq)));
 	if (data)
-		data->func(data, ktime_get_ns(), flags);
+		data->func(data, sched_ktime_clock(), flags);
 }
 
 static inline void cpufreq_update_this_cpu(struct rq *rq, unsigned int flags)
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
index 8bacb6f..4afefd6 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -19,6 +19,7 @@
  *             and Todd Kjos
  */
 
+#include <linux/syscore_ops.h>
 #include <linux/cpufreq.h>
 #include <linux/list_sort.h>
 #include <linux/jiffies.h>
@@ -41,6 +42,8 @@
 
 #define EARLY_DETECTION_DURATION 9500000
 
+static ktime_t ktime_last;
+static bool sched_ktime_suspended;
 static struct cpu_cycle_counter_cb cpu_cycle_counter_cb;
 static bool use_cycle_counter;
 DEFINE_MUTEX(cluster_lock);
@@ -50,14 +53,50 @@
 static struct irq_work walt_cpufreq_irq_work;
 static struct irq_work walt_migration_irq_work;
 
+u64 sched_ktime_clock(void)
+{
+	if (unlikely(sched_ktime_suspended))
+		return ktime_to_ns(ktime_last);
+	return ktime_get_ns();
+}
+
+static void sched_resume(void)
+{
+	sched_ktime_suspended = false;
+}
+
+static int sched_suspend(void)
+{
+	ktime_last = ktime_get();
+	sched_ktime_suspended = true;
+	return 0;
+}
+
+static struct syscore_ops sched_syscore_ops = {
+	.resume	= sched_resume,
+	.suspend = sched_suspend
+};
+
+static int __init sched_init_ops(void)
+{
+	register_syscore_ops(&sched_syscore_ops);
+	return 0;
+}
+late_initcall(sched_init_ops);
+
 static void acquire_rq_locks_irqsave(const cpumask_t *cpus,
 				     unsigned long *flags)
 {
-	int cpu;
+	int cpu, level = 0;
 
 	local_irq_save(*flags);
-	for_each_cpu(cpu, cpus)
-		raw_spin_lock(&cpu_rq(cpu)->lock);
+	for_each_cpu(cpu, cpus) {
+		if (level == 0)
+			raw_spin_lock(&cpu_rq(cpu)->lock);
+		else
+			raw_spin_lock_nested(&cpu_rq(cpu)->lock, level);
+		level++;
+	}
 }
 
 static void release_rq_locks_irqrestore(const cpumask_t *cpus,
@@ -270,12 +309,7 @@
 	u64 old_window_start = rq->window_start;
 
 	delta = wallclock - rq->window_start;
-	/* If the MPM global timer is cleared, set delta as 0 to avoid kernel BUG happening */
-	if (delta < 0) {
-		delta = 0;
-		WARN_ONCE(1, "WALT wallclock appears to have gone backwards or reset\n");
-	}
-
+	BUG_ON(delta < 0);
 	if (delta < sched_ravg_window)
 		return old_window_start;
 
@@ -363,10 +397,17 @@
 	if (!rq->window_start || sched_disable_window_stats)
 		return;
 
+	/*
+	 * We don’t have to note down an irqstart event when cycle
+	 * counter is not used.
+	 */
+	if (!use_cycle_counter)
+		return;
+
 	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, ktime_get_ns());
+		update_task_cpu_cycles(curr, cpu, sched_ktime_clock());
 		raw_spin_unlock(&rq->lock);
 	}
 }
@@ -427,7 +468,7 @@
 	cur_jiffies_ts = get_jiffies_64();
 
 	if (is_idle_task(curr))
-		update_task_ravg(curr, rq, IRQ_UPDATE, ktime_get_ns(),
+		update_task_ravg(curr, rq, IRQ_UPDATE, sched_ktime_clock(),
 				 delta);
 
 	nr_windows = cur_jiffies_ts - rq->irqload_ts;
@@ -665,14 +706,11 @@
 	BUG_ON((s64)src_rq->nt_curr_runnable_sum < 0);
 }
 
-static int load_to_index(u32 load)
+static u32 load_to_index(u32 load)
 {
-	if (load < sched_load_granule)
-		return 0;
-	else if (load >= sched_ravg_window)
-		return NUM_LOAD_INDICES - 1;
-	else
-		return load / sched_load_granule;
+	u32 index = load / sched_load_granule;
+
+	return min(index, (u32)(NUM_LOAD_INDICES - 1));
 }
 
 static void
@@ -764,7 +802,7 @@
 	if (sched_disable_window_stats)
 		goto done;
 
-	wallclock = ktime_get_ns();
+	wallclock = sched_ktime_clock();
 
 	update_task_ravg(task_rq(p)->curr, task_rq(p),
 			 TASK_UPDATE,
@@ -2051,7 +2089,7 @@
 		return;
 	}
 
-	wallclock = ktime_get_ns();
+	wallclock = sched_ktime_clock();
 	p->ravg.mark_start = p->last_wake_ts = wallclock;
 	p->last_enqueued_ts = wallclock;
 	p->last_switch_out_ts = 0;
@@ -2453,7 +2491,7 @@
 
 				raw_spin_lock_irqsave(&rq->lock, flags);
 				update_task_ravg(rq->curr, rq, TASK_UPDATE,
-						 ktime_get_ns(), 0);
+						 sched_ktime_clock(), 0);
 				raw_spin_unlock_irqrestore(&rq->lock, flags);
 			}
 		}
@@ -2603,7 +2641,7 @@
 		return;
 	}
 
-	wallclock = ktime_get_ns();
+	wallclock = sched_ktime_clock();
 
 	/*
 	 * wakeup of two or more related tasks could race with each other and
@@ -2630,7 +2668,7 @@
 
 	grp->preferred_cluster = best_cluster(grp,
 			combined_demand, group_boost);
-	grp->last_update = ktime_get_ns();
+	grp->last_update = sched_ktime_clock();
 	trace_sched_set_preferred_cluster(grp, combined_demand);
 }
 
@@ -2654,7 +2692,7 @@
 	 * has passed since we last updated preference
 	 */
 	if (abs(new_load - old_load) > sched_ravg_window / 4 ||
-		ktime_get_ns() - grp->last_update > sched_ravg_window)
+		sched_ktime_clock() - grp->last_update > sched_ravg_window)
 		return 1;
 
 	return 0;
@@ -3037,7 +3075,7 @@
 	bool new_task;
 	int i;
 
-	wallclock = ktime_get_ns();
+	wallclock = sched_ktime_clock();
 
 	update_task_ravg(rq->curr, rq, TASK_UPDATE, wallclock, 0);
 	update_task_ravg(p, rq, TASK_UPDATE, wallclock, 0);
@@ -3137,16 +3175,23 @@
 	u64 wc;
 	int flag = SCHED_CPUFREQ_WALT;
 	bool is_migration = false;
+	int level = 0;
 
 	/* Am I the window rollover work or the migration work? */
 	if (irq_work == &walt_migration_irq_work)
 		is_migration = true;
 
-	for_each_cpu(cpu, cpu_possible_mask)
-		raw_spin_lock(&cpu_rq(cpu)->lock);
+	for_each_cpu(cpu, cpu_possible_mask) {
+		if (level == 0)
+			raw_spin_lock(&cpu_rq(cpu)->lock);
+		else
+			raw_spin_lock_nested(&cpu_rq(cpu)->lock, level);
+		level++;
+	}
 
-	wc = ktime_get_ns();
+	wc = sched_ktime_clock();
 	walt_load_reported_window = atomic64_read(&walt_irq_work_lastq_ws);
+
 	for_each_sched_cluster(cluster) {
 		u64 aggr_grp_load = 0;
 
diff --git a/kernel/sched/walt.h b/kernel/sched/walt.h
index be06e7d4..cac925c 100644
--- a/kernel/sched/walt.h
+++ b/kernel/sched/walt.h
@@ -292,7 +292,7 @@
 
 static inline void walt_update_last_enqueue(struct task_struct *p)
 {
-	p->last_enqueued_ts = ktime_get_ns();
+	p->last_enqueued_ts = sched_ktime_clock();
 }
 extern void walt_rotate_work_init(void);
 extern void walt_rotation_checkpoint(int nr_big);
diff --git a/kernel/smpboot.c b/kernel/smpboot.c
index 10c5a3a..653cf6d 100644
--- a/kernel/smpboot.c
+++ b/kernel/smpboot.c
@@ -106,6 +106,7 @@
 {
 	struct smpboot_thread_data *td = data;
 	struct smp_hotplug_thread *ht = td->ht;
+	unsigned long flags;
 
 	while (1) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -157,9 +158,9 @@
 			 *     p->state = TASK_RUNNING;
 			 *                                   schedule();
 			 */
-			raw_spin_lock(&current->pi_lock);
+			raw_spin_lock_irqsave(&current->pi_lock, flags);
 			__set_current_state(TASK_RUNNING);
-			raw_spin_unlock(&current->pi_lock);
+			raw_spin_unlock_irqrestore(&current->pi_lock, flags);
 			preempt_enable();
 			if (ht->park && td->status == HP_THREAD_ACTIVE) {
 				BUG_ON(td->cpu != smp_processor_id());
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 09a1611..75ae656 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1486,6 +1486,15 @@
 		.extra1		= &zero,
 		.extra2		= &one_hundred,
 	},
+	{
+		.procname       = "want_old_faultaround_pte",
+		.data           = &want_old_faultaround_pte,
+		.maxlen         = sizeof(want_old_faultaround_pte),
+		.mode           = 0644,
+		.proc_handler   = proc_dointvec_minmax,
+		.extra1         = &zero,
+		.extra2         = &one,
+	},
 #ifdef CONFIG_HUGETLB_PAGE
 	{
 		.procname	= "nr_hugepages",
diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c
index 59b482f..de63dab 100644
--- a/kernel/trace/trace_irqsoff.c
+++ b/kernel/trace/trace_irqsoff.c
@@ -804,10 +804,9 @@
 static inline void tracer_preempt_off(unsigned long a0, unsigned long a1) { }
 #endif
 
+#if defined(CONFIG_TRACE_IRQFLAGS) && !defined(CONFIG_PROVE_LOCKING)
 /* Per-cpu variable to prevent redundant calls when IRQs already off */
 static DEFINE_PER_CPU(int, tracing_irq_cpu);
-
-#if defined(CONFIG_TRACE_IRQFLAGS) && !defined(CONFIG_PROVE_LOCKING)
 void trace_hardirqs_on(void)
 {
 	if (!this_cpu_read(tracing_irq_cpu))
diff --git a/mm/Kconfig b/mm/Kconfig
index 051f7bc..b452197 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -638,6 +638,16 @@
 	  information to userspace via debugfs.
 	  If unsure, say N.
 
+config VMAP_LAZY_PURGING_FACTOR
+	int "multiplier to the size of purged vmap areas"
+	default "8" if ARM
+	default "32"
+	help
+	  It is used as a multiplier to the max VA pages purged in a
+	  single attempt. For 32-bit in order to reduce fragmentation
+	  of vmalloc space, we decrease the default value to "8".
+
+
 config GENERIC_EARLY_IOREMAP
 	bool
 
@@ -747,3 +757,25 @@
 	 (addr, addr + size-bytes) of the process.
 
 	 Any other vaule is ignored.
+
+config ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT
+       def_bool n
+
+config SPECULATIVE_PAGE_FAULT
+       bool "Speculative page faults"
+       default y
+       depends on ARCH_SUPPORTS_SPECULATIVE_PAGE_FAULT
+       depends on MMU && SMP
+       help
+         Try to handle user space page faults without holding the mmap_sem.
+
+	 This should allow better concurrency for massively threaded process
+	 since the page fault handler will not wait for other threads memory
+	 layout change to be done, assuming that this change is done in another
+	 part of the process's memory space. This type of page fault is named
+	 speculative page fault.
+
+	 If the speculative page fault fails because of a concurrency is
+	 detected or because underlying PMD or PTE tables are not yet
+	 allocating, it is failing its processing and a classic page fault
+	 is then tried.
diff --git a/mm/filemap.c b/mm/filemap.c
index 211df83..b27d2ca 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -47,6 +47,8 @@
 
 #include <asm/mman.h>
 
+int want_old_faultaround_pte = 1;
+
 /*
  * Shared mappings implemented 30.11.1994. It's not fully working yet,
  * though.
@@ -2287,6 +2289,14 @@
 		if (fe->pte)
 			fe->pte += iter.index - last_pgoff;
 		last_pgoff = iter.index;
+
+		if (want_old_faultaround_pte) {
+			if (fe->address == fe->fault_address)
+				fe->flags &= ~FAULT_FLAG_PREFAULT_OLD;
+			else
+				fe->flags |= FAULT_FLAG_PREFAULT_OLD;
+		}
+
 		if (alloc_set_pte(fe, NULL, page))
 			goto unlock;
 		unlock_page(page);
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 7243728..a557862 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -958,8 +958,8 @@
 
 	for (i = 0; i < HPAGE_PMD_NR; i++, haddr += PAGE_SIZE) {
 		pte_t entry;
-		entry = mk_pte(pages[i], vma->vm_page_prot);
-		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+		entry = mk_pte(pages[i], fe->vma_page_prot);
+		entry = maybe_mkwrite(pte_mkdirty(entry), fe->vma_flags);
 		memcg = (void *)page_private(pages[i]);
 		set_page_private(pages[i], 0);
 		page_add_new_anon_rmap(pages[i], fe->vma, haddr, false);
@@ -1679,7 +1679,7 @@
 				entry = pte_swp_mksoft_dirty(entry);
 		} else {
 			entry = mk_pte(page + i, READ_ONCE(vma->vm_page_prot));
-			entry = maybe_mkwrite(entry, vma);
+			entry = maybe_mkwrite(entry, vma->vm_flags);
 			if (!write)
 				entry = pte_wrprotect(entry);
 			if (!young)
diff --git a/mm/init-mm.c b/mm/init-mm.c
index 975e49f..4d21629 100644
--- a/mm/init-mm.c
+++ b/mm/init-mm.c
@@ -16,6 +16,9 @@
 
 struct mm_struct init_mm = {
 	.mm_rb		= RB_ROOT,
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+	.mm_rb_lock	= __RW_LOCK_UNLOCKED(init_mm.mm_rb_lock),
+#endif
 	.pgd		= swapper_pg_dir,
 	.mm_users	= ATOMIC_INIT(2),
 	.mm_count	= ATOMIC_INIT(1),
diff --git a/mm/internal.h b/mm/internal.h
index 6aa1c51..d9ac6de 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -38,6 +38,26 @@
 
 int do_swap_page(struct fault_env *fe, pte_t orig_pte);
 
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+extern struct vm_area_struct *get_vma(struct mm_struct *mm,
+				      unsigned long addr);
+extern void put_vma(struct vm_area_struct *vma);
+
+static inline bool vma_has_changed(struct fault_env *fe)
+{
+	int ret = RB_EMPTY_NODE(&fe->vma->vm_rb);
+	unsigned int seq = READ_ONCE(fe->vma->vm_sequence.sequence);
+
+	/*
+	 * Matches both the wmb in write_seqlock_{begin,end}() and
+	 * the wmb in vma_rb_erase().
+	 */
+	smp_rmb();
+
+	return ret || seq != fe->sequence;
+}
+#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
+
 void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
 		unsigned long floor, unsigned long ceiling);
 
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 1df37ee..6b58aaf 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -887,6 +887,8 @@
 		.address = address,
 		.flags = FAULT_FLAG_ALLOW_RETRY,
 		.pmd = pmd,
+		.vma_flags = vma->vm_flags,
+		.vma_page_prot = vma->vm_page_prot,
 	};
 
 	/* we only decide to swapin, if there is enough young ptes */
@@ -1011,6 +1013,7 @@
 	if (mm_find_pmd(mm, address) != pmd)
 		goto out;
 
+	vm_write_begin(vma);
 	anon_vma_lock_write(vma->anon_vma);
 
 	pte = pte_offset_map(pmd, address);
@@ -1046,6 +1049,7 @@
 		pmd_populate(mm, pmd, pmd_pgtable(_pmd));
 		spin_unlock(pmd_ptl);
 		anon_vma_unlock_write(vma->anon_vma);
+		vm_write_end(vma);
 		result = SCAN_FAIL;
 		goto out;
 	}
@@ -1080,6 +1084,7 @@
 	set_pmd_at(mm, address, pmd, _pmd);
 	update_mmu_cache_pmd(vma, address, pmd);
 	spin_unlock(pmd_ptl);
+	vm_write_end(vma);
 
 	*hpage = NULL;
 
diff --git a/mm/madvise.c b/mm/madvise.c
index 59d1aae..ee7ad9b 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -135,8 +135,10 @@
 	/*
 	 * vm_flags is protected by the mmap_sem held in write mode.
 	 */
-	vma->vm_flags = new_flags;
 
+	vm_write_begin(vma);
+	WRITE_ONCE(vma->vm_flags, new_flags);
+	vm_write_end(vma);
 out:
 	if (error == -ENOMEM)
 		error = -EAGAIN;
@@ -404,9 +406,11 @@
 		.private = tlb,
 	};
 
+	vm_write_begin(vma);
 	tlb_start_vma(tlb, vma);
 	walk_page_range(addr, end, &free_walk);
 	tlb_end_vma(tlb, vma);
+	vm_write_end(vma);
 }
 
 static int madvise_free_single_vma(struct vm_area_struct *vma,
diff --git a/mm/memory.c b/mm/memory.c
index cc6ab38..7a88700 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -75,6 +75,9 @@
 
 #include "internal.h"
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/pagefault.h>
+
 #if defined(LAST_CPUPID_NOT_IN_PAGE_FLAGS) && !defined(CONFIG_COMPILE_TEST)
 #warning Unfortunate NUMA and NUMA Balancing config, growing page-frame for last_cpupid.
 #endif
@@ -549,7 +552,9 @@
 		 * Hide vma from rmap and truncate_pagecache before freeing
 		 * pgtables
 		 */
+		vm_write_begin(vma);
 		unlink_anon_vmas(vma);
+		vm_write_end(vma);
 		unlink_file_vma(vma);
 
 		if (is_vm_hugetlb_page(vma)) {
@@ -563,7 +568,9 @@
 			       && !is_vm_hugetlb_page(next)) {
 				vma = next;
 				next = vma->vm_next;
+				vm_write_begin(vma);
 				unlink_anon_vmas(vma);
+				vm_write_end(vma);
 				unlink_file_vma(vma);
 			}
 			free_pgd_range(tlb, addr, vma->vm_end,
@@ -689,7 +696,8 @@
 	if (page)
 		dump_page(page, "bad pte");
 	pr_alert("addr:%p vm_flags:%08lx anon_vma:%p mapping:%p index:%lx\n",
-		 (void *)addr, vma->vm_flags, vma->anon_vma, mapping, index);
+		 (void *)addr, READ_ONCE(vma->vm_flags), vma->anon_vma,
+		 mapping, index);
 	/*
 	 * Choose text because data symbols depend on CONFIG_KALLSYMS_ALL=y
 	 */
@@ -703,7 +711,8 @@
 }
 
 /*
- * vm_normal_page -- This function gets the "struct page" associated with a pte.
+ * __vm_normal_page -- This function gets the "struct page" associated with
+ * a pte.
  *
  * "Special" mappings do not wish to be associated with a "struct page" (either
  * it doesn't exist, or it exists but they don't want to touch it). In this
@@ -749,8 +758,8 @@
 #else
 # define HAVE_PTE_SPECIAL 0
 #endif
-struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
-				pte_t pte)
+struct page *__vm_normal_page(struct vm_area_struct *vma, unsigned long addr,
+			      pte_t pte, unsigned long vma_flags)
 {
 	unsigned long pfn = pte_pfn(pte);
 
@@ -759,7 +768,7 @@
 			goto check_pfn;
 		if (vma->vm_ops && vma->vm_ops->find_special_page)
 			return vma->vm_ops->find_special_page(vma, addr);
-		if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP))
+		if (vma_flags & (VM_PFNMAP | VM_MIXEDMAP))
 			return NULL;
 		if (!is_zero_pfn(pfn))
 			print_bad_pte(vma, addr, pte, NULL);
@@ -767,9 +776,13 @@
 	}
 
 	/* !HAVE_PTE_SPECIAL case follows: */
+	/*
+	 * This part should never get called when CONFIG_SPECULATIVE_PAGE_FAULT
+	 * is set. This is mainly because we can't rely on vm_start.
+	 */
 
-	if (unlikely(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP))) {
-		if (vma->vm_flags & VM_MIXEDMAP) {
+	if (unlikely(vma_flags & (VM_PFNMAP|VM_MIXEDMAP))) {
+		if (vma_flags & VM_MIXEDMAP) {
 			if (!pfn_valid(pfn))
 				return NULL;
 			goto out;
@@ -778,7 +791,7 @@
 			off = (addr - vma->vm_start) >> PAGE_SHIFT;
 			if (pfn == vma->vm_pgoff + off)
 				return NULL;
-			if (!is_cow_mapping(vma->vm_flags))
+			if (!is_cow_mapping(vma_flags))
 				return NULL;
 		}
 	}
@@ -1285,6 +1298,7 @@
 	unsigned long next;
 
 	BUG_ON(addr >= end);
+	vm_write_begin(vma);
 	tlb_start_vma(tlb, vma);
 	pgd = pgd_offset(vma->vm_mm, addr);
 	do {
@@ -1294,6 +1308,7 @@
 		next = zap_pud_range(tlb, vma, pgd, addr, next, details);
 	} while (pgd++, addr = next, addr != end);
 	tlb_end_vma(tlb, vma);
+	vm_write_end(vma);
 }
 
 
@@ -1961,6 +1976,145 @@
 }
 EXPORT_SYMBOL_GPL(apply_to_page_range);
 
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+static bool pte_spinlock(struct mm_struct *mm,
+			struct fault_env *fe)
+{
+	bool ret = false;
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+	pmd_t pmdval;
+#endif
+
+	/* Check if vma is still valid */
+	if (!(fe->flags & FAULT_FLAG_SPECULATIVE)) {
+		fe->ptl = pte_lockptr(mm, fe->pmd);
+		spin_lock(fe->ptl);
+		return true;
+	}
+
+	local_irq_disable();
+	if (vma_has_changed(fe)) {
+		trace_spf_vma_changed(_RET_IP_, fe->vma, fe->address);
+		goto out;
+	}
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+	/*
+	 * We check if the pmd value is still the same to ensure that there
+	 * is not a huge collapse operation in progress in our back.
+	 */
+	pmdval = READ_ONCE(*fe->pmd);
+	if (!pmd_same(pmdval, fe->orig_pmd)) {
+		trace_spf_pmd_changed(_RET_IP_, fe->vma, fe->address);
+		goto out;
+	}
+#endif
+
+	fe->ptl = pte_lockptr(mm, fe->pmd);
+	if (unlikely(!spin_trylock(fe->ptl))) {
+		trace_spf_pte_lock(_RET_IP_, fe->vma, fe->address);
+		goto out;
+	}
+
+	if (vma_has_changed(fe)) {
+		spin_unlock(fe->ptl);
+		trace_spf_vma_changed(_RET_IP_, fe->vma, fe->address);
+		goto out;
+	}
+
+	ret = true;
+out:
+	local_irq_enable();
+	return ret;
+}
+
+static bool pte_map_lock(struct mm_struct *mm,
+				struct fault_env *fe)
+{
+	bool ret = false;
+	pte_t *pte;
+	spinlock_t *ptl;
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+	pmd_t pmdval;
+#endif
+
+	if (!(fe->flags & FAULT_FLAG_SPECULATIVE)) {
+		fe->pte = pte_offset_map_lock(mm, fe->pmd,
+					       fe->address, &fe->ptl);
+		return true;
+	}
+
+	/*
+	 * The first vma_has_changed() guarantees the page-tables are still
+	 * valid, having IRQs disabled ensures they stay around, hence the
+	 * second vma_has_changed() to make sure they are still valid once
+	 * we've got the lock. After that a concurrent zap_pte_range() will
+	 * block on the PTL and thus we're safe.
+	 */
+	local_irq_disable();
+	if (vma_has_changed(fe)) {
+		trace_spf_vma_changed(_RET_IP_, fe->vma, fe->address);
+		goto out;
+	}
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+	/*
+	 * We check if the pmd value is still the same to ensure that there
+	 * is not a huge collapse operation in progress in our back.
+	 */
+	pmdval = READ_ONCE(*fe->pmd);
+	if (!pmd_same(pmdval, fe->orig_pmd)) {
+		trace_spf_pmd_changed(_RET_IP_, fe->vma, fe->address);
+		goto out;
+	}
+#endif
+
+	/*
+	 * Same as pte_offset_map_lock() except that we call
+	 * spin_trylock() in place of spin_lock() to avoid race with
+	 * unmap path which may have the lock and wait for this CPU
+	 * to invalidate TLB but this CPU has irq disabled.
+	 * Since we are in a speculative patch, accept it could fail
+	 */
+	ptl = pte_lockptr(mm, fe->pmd);
+	pte = pte_offset_map(fe->pmd, fe->address);
+	if (unlikely(!spin_trylock(ptl))) {
+		pte_unmap(pte);
+		trace_spf_pte_lock(_RET_IP_, fe->vma, fe->address);
+		goto out;
+	}
+
+	if (vma_has_changed(fe)) {
+		pte_unmap_unlock(pte, ptl);
+		trace_spf_vma_changed(_RET_IP_, fe->vma, fe->address);
+		goto out;
+	}
+
+	fe->pte = pte;
+	fe->ptl = ptl;
+	ret = true;
+out:
+	local_irq_enable();
+	return ret;
+}
+#else
+static inline bool pte_spinlock(struct mm_struct *mm,
+			struct fault_env *fe)
+{
+	fe->ptl = pte_lockptr(mm, fe->pmd);
+	spin_lock(fe->ptl);
+	return true;
+}
+
+static inline bool pte_map_lock(struct mm_struct *mm,
+			struct fault_env *fe)
+{
+	fe->pte = pte_offset_map_lock(mm, fe->pmd,
+				       fe->address, &fe->ptl);
+	return true;
+}
+#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
+
 /*
  * handle_pte_fault chooses page fault handler according to an entry which was
  * read non-atomically.  Before making any commitment, on those architectures
@@ -1968,21 +2122,30 @@
  * parts, do_swap_page must check under lock before unmapping the pte and
  * proceeding (but do_wp_page is only called after already making such a check;
  * and do_anonymous_page can safely check later on).
+ *
+ * pte_unmap_same() returns:
+ *	0			if the PTE are the same
+ *	VM_FAULT_PTNOTSAME	if the PTE are different
+ *	VM_FAULT_RETRY		if the VMA has changed in our back during
+ *				a speculative page fault handling.
  */
-static inline int pte_unmap_same(struct mm_struct *mm, pmd_t *pmd,
-				pte_t *page_table, pte_t orig_pte)
+static inline int pte_unmap_same(struct mm_struct *mm, struct fault_env *fe,
+					pte_t orig_pte)
 {
-	int same = 1;
+	int ret = 0;
+
 #if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
 	if (sizeof(pte_t) > sizeof(unsigned long)) {
-		spinlock_t *ptl = pte_lockptr(mm, pmd);
-		spin_lock(ptl);
-		same = pte_same(*page_table, orig_pte);
-		spin_unlock(ptl);
+		if (pte_spinlock(mm, fe)) {
+			if (!pte_same(*fe->pte, orig_pte))
+				ret = VM_FAULT_PTNOTSAME;
+			spin_unlock(fe->ptl);
+		} else
+			ret = VM_FAULT_RETRY;
 	}
 #endif
-	pte_unmap(page_table);
-	return same;
+	pte_unmap(fe->pte);
+	return ret;
 }
 
 static inline void cow_user_page(struct page *dst, struct page *src, unsigned long va, struct vm_area_struct *vma)
@@ -2085,7 +2248,7 @@
 
 	flush_cache_page(vma, fe->address, pte_pfn(orig_pte));
 	entry = pte_mkyoung(orig_pte);
-	entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+	entry = maybe_mkwrite(pte_mkdirty(entry), fe->vma_flags);
 	if (ptep_set_access_flags(vma, fe->address, fe->pte, entry, 1))
 		update_mmu_cache(vma, fe->address, fe->pte);
 	pte_unmap_unlock(fe->pte, fe->ptl);
@@ -2145,24 +2308,25 @@
 	const unsigned long mmun_start = fe->address & PAGE_MASK;
 	const unsigned long mmun_end = mmun_start + PAGE_SIZE;
 	struct mem_cgroup *memcg;
+	int ret = VM_FAULT_OOM;
 
 	if (unlikely(anon_vma_prepare(vma)))
-		goto oom;
+		goto out;
 
 	if (is_zero_pfn(pte_pfn(orig_pte))) {
 		new_page = alloc_zeroed_user_highpage_movable(vma, fe->address);
 		if (!new_page)
-			goto oom;
+			goto out;
 	} else {
 		new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma,
 				fe->address);
 		if (!new_page)
-			goto oom;
+			goto out;
 		cow_user_page(new_page, old_page, fe->address, vma);
 	}
 
 	if (mem_cgroup_try_charge(new_page, mm, GFP_KERNEL, &memcg, false))
-		goto oom_free_new;
+		goto out_free_new;
 
 	__SetPageUptodate(new_page);
 
@@ -2171,7 +2335,10 @@
 	/*
 	 * Re-check the pte - we dropped the lock
 	 */
-	fe->pte = pte_offset_map_lock(mm, fe->pmd, fe->address, &fe->ptl);
+	if (!pte_map_lock(mm, fe)) {
+		ret = VM_FAULT_RETRY;
+		goto out_uncharge;
+	}
 	if (likely(pte_same(*fe->pte, orig_pte))) {
 		if (old_page) {
 			if (!PageAnon(old_page)) {
@@ -2183,8 +2350,8 @@
 			inc_mm_counter_fast(mm, MM_ANONPAGES);
 		}
 		flush_cache_page(vma, fe->address, pte_pfn(orig_pte));
-		entry = mk_pte(new_page, vma->vm_page_prot);
-		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+		entry = mk_pte(new_page, fe->vma_page_prot);
+		entry = maybe_mkwrite(pte_mkdirty(entry), fe->vma_flags);
 		/*
 		 * Clear the pte entry and flush it first, before updating the
 		 * pte with the new entry. This will avoid a race condition
@@ -2192,9 +2359,9 @@
 		 * thread doing COW.
 		 */
 		ptep_clear_flush_notify(vma, fe->address, fe->pte);
-		page_add_new_anon_rmap(new_page, vma, fe->address, false);
+		__page_add_new_anon_rmap(new_page, vma, fe->address, false);
 		mem_cgroup_commit_charge(new_page, memcg, false, false);
-		lru_cache_add_active_or_unevictable(new_page, vma);
+		__lru_cache_add_active_or_unevictable(new_page, fe->vma_flags);
 		/*
 		 * We call the notify macro here because, when using secondary
 		 * mmu page tables (such as kvm shadow page tables), we want the
@@ -2245,7 +2412,7 @@
 		 * Don't let another task, with possibly unlocked vma,
 		 * keep the mlocked page.
 		 */
-		if (page_copied && (vma->vm_flags & VM_LOCKED)) {
+		if (page_copied && (fe->vma_flags & VM_LOCKED)) {
 			lock_page(old_page);	/* LRU manipulation */
 			if (PageMlocked(old_page))
 				munlock_vma_page(old_page);
@@ -2254,12 +2421,14 @@
 		put_page(old_page);
 	}
 	return page_copied ? VM_FAULT_WRITE : 0;
-oom_free_new:
+out_uncharge:
+	mem_cgroup_cancel_charge(new_page, memcg, false);
+out_free_new:
 	put_page(new_page);
-oom:
+out:
 	if (old_page)
 		put_page(old_page);
-	return VM_FAULT_OOM;
+	return ret;
 }
 
 /*
@@ -2284,8 +2453,8 @@
 		ret = vma->vm_ops->pfn_mkwrite(vma, &vmf);
 		if (ret & VM_FAULT_ERROR)
 			return ret;
-		fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd, fe->address,
-				&fe->ptl);
+		if (!pte_map_lock(vma->vm_mm, fe))
+			return VM_FAULT_RETRY;
 		/*
 		 * We might have raced with another page fault while we
 		 * released the pte_offset_map_lock.
@@ -2361,7 +2530,8 @@
 	struct vm_area_struct *vma = fe->vma;
 	struct page *old_page;
 
-	old_page = vm_normal_page(vma, fe->address, orig_pte);
+	old_page = __vm_normal_page(vma, fe->address, orig_pte,
+				     fe->vma_flags);
 	if (!old_page) {
 		/*
 		 * VM_MIXEDMAP !pfn_valid() case, or VM_SOFTDIRTY clear on a
@@ -2370,7 +2540,7 @@
 		 * We should not cow pages in a shared writeable mapping.
 		 * Just mark the pages writable and/or call ops->pfn_mkwrite.
 		 */
-		if ((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
+		if ((fe->vma_flags & (VM_WRITE|VM_SHARED)) ==
 				     (VM_WRITE|VM_SHARED))
 			return wp_pfn_shared(fe, orig_pte);
 
@@ -2388,8 +2558,11 @@
 			get_page(old_page);
 			pte_unmap_unlock(fe->pte, fe->ptl);
 			lock_page(old_page);
-			fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd,
-					fe->address, &fe->ptl);
+			if (!pte_map_lock(vma->vm_mm, fe)) {
+				unlock_page(old_page);
+				put_page(old_page);
+				return VM_FAULT_RETRY;
+			}
 			if (!pte_same(*fe->pte, orig_pte)) {
 				unlock_page(old_page);
 				pte_unmap_unlock(fe->pte, fe->ptl);
@@ -2413,7 +2586,7 @@
 			return wp_page_reuse(fe, orig_pte, old_page, 0, 0);
 		}
 		unlock_page(old_page);
-	} else if (unlikely((vma->vm_flags & (VM_WRITE|VM_SHARED)) ==
+	} else if (unlikely((fe->vma_flags & (VM_WRITE|VM_SHARED)) ==
 					(VM_WRITE|VM_SHARED))) {
 		return wp_page_shared(fe, orig_pte, old_page);
 	}
@@ -2523,9 +2696,17 @@
 	int exclusive = 0;
 	int ret = 0;
 
-	if (!pte_unmap_same(vma->vm_mm, fe->pmd, fe->pte, orig_pte))
+	ret = pte_unmap_same(vma->vm_mm, fe, orig_pte);
+	if (ret) {
+		/*
+		 * If pte != orig_pte, this means another thread did the
+		 * swap operation in our back.
+		 * So nothing else to do.
+		 */
+		if (ret == VM_FAULT_PTNOTSAME)
+			ret = 0;
 		goto out;
-
+	}
 	entry = pte_to_swp_entry(orig_pte);
 	if (unlikely(non_swap_entry(entry))) {
 		if (is_migration_entry(entry)) {
@@ -2545,11 +2726,16 @@
 					GFP_HIGHUSER_MOVABLE, vma, fe->address);
 		if (!page) {
 			/*
-			 * Back out if somebody else faulted in this pte
-			 * while we released the pte lock.
+			 * Back out if the VMA has changed in our back during
+			 * a speculative page fault or if somebody else
+			 * faulted in this pte while we released the pte lock.
 			 */
-			fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd,
-					fe->address, &fe->ptl);
+			if (!pte_map_lock(vma->vm_mm, fe)) {
+				delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
+				ret = VM_FAULT_RETRY;
+				goto out;
+			}
+
 			if (likely(pte_same(*fe->pte, orig_pte)))
 				ret = VM_FAULT_OOM;
 			delayacct_clear_flag(DELAYACCT_PF_SWAPIN);
@@ -2603,10 +2789,13 @@
 	}
 
 	/*
-	 * Back out if somebody else already faulted in this pte.
+	 * Back out if the VMA has changed in our back during a speculative
+	 * page fault or if somebody else already faulted in this pte.
 	 */
-	fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd, fe->address,
-			&fe->ptl);
+	if (!pte_map_lock(vma->vm_mm, fe)) {
+		ret = VM_FAULT_RETRY;
+		goto out_cancel_cgroup;
+	}
 	if (unlikely(!pte_same(*fe->pte, orig_pte)))
 		goto out_nomap;
 
@@ -2627,9 +2816,9 @@
 
 	inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
 	dec_mm_counter_fast(vma->vm_mm, MM_SWAPENTS);
-	pte = mk_pte(page, vma->vm_page_prot);
+	pte = mk_pte(page, fe->vma_page_prot);
 	if ((fe->flags & FAULT_FLAG_WRITE) && reuse_swap_page(page, NULL)) {
-		pte = maybe_mkwrite(pte_mkdirty(pte), vma);
+		pte = maybe_mkwrite(pte_mkdirty(pte), fe->vma_flags);
 		fe->flags &= ~FAULT_FLAG_WRITE;
 		ret |= VM_FAULT_WRITE;
 		exclusive = RMAP_EXCLUSIVE;
@@ -2643,14 +2832,14 @@
 		mem_cgroup_commit_charge(page, memcg, true, false);
 		activate_page(page);
 	} else { /* ksm created a completely new copy */
-		page_add_new_anon_rmap(page, vma, fe->address, false);
+		__page_add_new_anon_rmap(page, vma, fe->address, false);
 		mem_cgroup_commit_charge(page, memcg, false, false);
-		lru_cache_add_active_or_unevictable(page, vma);
+		__lru_cache_add_active_or_unevictable(page, fe->vma_flags);
 	}
 
 	swap_free(entry);
 	if (mem_cgroup_swap_full(page) ||
-	    (vma->vm_flags & VM_LOCKED) || PageMlocked(page))
+	    (fe->vma_flags & VM_LOCKED) || PageMlocked(page))
 		try_to_free_swap(page);
 	unlock_page(page);
 	if (page != swapcache) {
@@ -2680,8 +2869,9 @@
 out:
 	return ret;
 out_nomap:
-	mem_cgroup_cancel_charge(page, memcg, false);
 	pte_unmap_unlock(fe->pte, fe->ptl);
+out_cancel_cgroup:
+	mem_cgroup_cancel_charge(page, memcg, false);
 out_page:
 	unlock_page(page);
 out_release:
@@ -2703,10 +2893,11 @@
 	struct vm_area_struct *vma = fe->vma;
 	struct mem_cgroup *memcg;
 	struct page *page;
+	int ret = 0;
 	pte_t entry;
 
 	/* File mapping without ->vm_ops ? */
-	if (vma->vm_flags & VM_SHARED)
+	if (fe->vma_flags & VM_SHARED)
 		return VM_FAULT_SIGBUS;
 
 	/*
@@ -2730,11 +2921,19 @@
 	if (!(fe->flags & FAULT_FLAG_WRITE) &&
 			!mm_forbids_zeropage(vma->vm_mm)) {
 		entry = pte_mkspecial(pfn_pte(my_zero_pfn(fe->address),
-						vma->vm_page_prot));
-		fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd, fe->address,
-				&fe->ptl);
+						fe->vma_page_prot));
+		if (!pte_map_lock(vma->vm_mm, fe))
+			return VM_FAULT_RETRY;
 		if (!pte_none(*fe->pte))
 			goto unlock;
+		/*
+		 * Don't call the userfaultfd during the speculative path.
+		 * We already checked for the VMA to not be managed through
+		 * userfaultfd, but it may be set in our back once we have lock
+		 * the pte. In such a case we can ignore it this time.
+		 */
+		if (fe->flags & FAULT_FLAG_SPECULATIVE)
+			goto setpte;
 		/* Deliver the page fault to userland, check inside PT lock */
 		if (userfaultfd_missing(vma)) {
 			pte_unmap_unlock(fe->pte, fe->ptl);
@@ -2760,17 +2959,19 @@
 	 */
 	__SetPageUptodate(page);
 
-	entry = mk_pte(page, vma->vm_page_prot);
-	if (vma->vm_flags & VM_WRITE)
+	entry = mk_pte(page, fe->vma_page_prot);
+	if (fe->vma_flags & VM_WRITE)
 		entry = pte_mkwrite(pte_mkdirty(entry));
 
-	fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd, fe->address,
-			&fe->ptl);
-	if (!pte_none(*fe->pte))
+	if (!pte_map_lock(vma->vm_mm, fe)) {
+		ret = VM_FAULT_RETRY;
 		goto release;
+	}
+	if (!pte_none(*fe->pte))
+		goto unlock_and_release;
 
 	/* Deliver the page fault to userland, check inside PT lock */
-	if (userfaultfd_missing(vma)) {
+	if (!(fe->flags & FAULT_FLAG_SPECULATIVE) && userfaultfd_missing(vma)) {
 		pte_unmap_unlock(fe->pte, fe->ptl);
 		mem_cgroup_cancel_charge(page, memcg, false);
 		put_page(page);
@@ -2778,9 +2979,9 @@
 	}
 
 	inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
-	page_add_new_anon_rmap(page, vma, fe->address, false);
+	__page_add_new_anon_rmap(page, vma, fe->address, false);
 	mem_cgroup_commit_charge(page, memcg, false, false);
-	lru_cache_add_active_or_unevictable(page, vma);
+	__lru_cache_add_active_or_unevictable(page, fe->vma_flags);
 setpte:
 	set_pte_at(vma->vm_mm, fe->address, fe->pte, entry);
 
@@ -2788,11 +2989,13 @@
 	update_mmu_cache(vma, fe->address, fe->pte);
 unlock:
 	pte_unmap_unlock(fe->pte, fe->ptl);
-	return 0;
+	return ret;
+unlock_and_release:
+	pte_unmap_unlock(fe->pte, fe->ptl);
 release:
 	mem_cgroup_cancel_charge(page, memcg, false);
 	put_page(page);
-	goto unlock;
+	return ret;
 oom_free_page:
 	put_page(page);
 oom:
@@ -2897,8 +3100,9 @@
 	 * pte_none() under vmf->ptl protection when we return to
 	 * alloc_set_pte().
 	 */
-	fe->pte = pte_offset_map_lock(vma->vm_mm, fe->pmd, fe->address,
-			&fe->ptl);
+	if (!pte_map_lock(vma->vm_mm, fe))
+		return VM_FAULT_RETRY;
+
 	return 0;
 }
 
@@ -2937,7 +3141,7 @@
 	for (i = 0; i < HPAGE_PMD_NR; i++)
 		flush_icache_page(vma, page + i);
 
-	entry = mk_huge_pmd(page, vma->vm_page_prot);
+	entry = mk_huge_pmd(page, fe->vma_page_prot);
 	if (write)
 		entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
 
@@ -3005,15 +3209,19 @@
 		return VM_FAULT_NOPAGE;
 
 	flush_icache_page(vma, page);
-	entry = mk_pte(page, vma->vm_page_prot);
+	entry = mk_pte(page, fe->vma_page_prot);
 	if (write)
-		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
+		entry = maybe_mkwrite(pte_mkdirty(entry), fe->vma_flags);
+
+	if (fe->flags & FAULT_FLAG_PREFAULT_OLD)
+		entry = pte_mkold(entry);
+
 	/* copy-on-write page */
-	if (write && !(vma->vm_flags & VM_SHARED)) {
+	if (write && !(fe->vma_flags & VM_SHARED)) {
 		inc_mm_counter_fast(vma->vm_mm, MM_ANONPAGES);
-		page_add_new_anon_rmap(page, vma, fe->address, false);
+		__page_add_new_anon_rmap(page, vma, fe->address, false);
 		mem_cgroup_commit_charge(page, memcg, false, false);
-		lru_cache_add_active_or_unevictable(page, vma);
+		__lru_cache_add_active_or_unevictable(page, fe->vma_flags);
 	} else {
 		inc_mm_counter_fast(vma->vm_mm, mm_counter_file(page));
 		page_add_file_rmap(page, false);
@@ -3026,8 +3234,16 @@
 	return 0;
 }
 
+/*
+ * If architecture emulates "accessed" or "young" bit without HW support,
+ * there is no much gain with fault_around.
+ */
 static unsigned long fault_around_bytes __read_mostly =
-	rounddown_pow_of_two(4096);
+#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+	PAGE_SIZE;
+#else
+	rounddown_pow_of_two(65536);
+#endif
 
 #ifdef CONFIG_DEBUG_FS
 static int fault_around_bytes_get(void *data, u64 *val)
@@ -3096,6 +3312,7 @@
 	pgoff_t end_pgoff;
 	int off, ret = 0;
 
+	fe->fault_address = address;
 	nr_pages = READ_ONCE(fault_around_bytes) >> PAGE_SHIFT;
 	mask = ~(nr_pages * PAGE_SIZE - 1) & PAGE_MASK;
 
@@ -3301,7 +3518,7 @@
 		return VM_FAULT_SIGBUS;
 	if (!(fe->flags & FAULT_FLAG_WRITE))
 		return do_read_fault(fe, pgoff);
-	if (!(vma->vm_flags & VM_SHARED))
+	if (!(fe->vma_flags & VM_SHARED))
 		return do_cow_fault(fe, pgoff);
 	return do_shared_fault(fe, pgoff);
 }
@@ -3341,22 +3558,22 @@
 	* page table entry is not accessible, so there would be no
 	* concurrent hardware modifications to the PTE.
 	*/
-	fe->ptl = pte_lockptr(vma->vm_mm, fe->pmd);
-	spin_lock(fe->ptl);
+	if (!pte_spinlock(vma->vm_mm, fe))
+		return VM_FAULT_RETRY;
 	if (unlikely(!pte_same(*fe->pte, pte))) {
 		pte_unmap_unlock(fe->pte, fe->ptl);
 		goto out;
 	}
 
 	/* Make it present again */
-	pte = pte_modify(pte, vma->vm_page_prot);
+	pte = pte_modify(pte, fe->vma_page_prot);
 	pte = pte_mkyoung(pte);
 	if (was_writable)
 		pte = pte_mkwrite(pte);
 	set_pte_at(vma->vm_mm, fe->address, fe->pte, pte);
 	update_mmu_cache(vma, fe->address, fe->pte);
 
-	page = vm_normal_page(vma, fe->address, pte);
+	page = __vm_normal_page(vma, fe->address, pte, fe->vma_flags);
 	if (!page) {
 		pte_unmap_unlock(fe->pte, fe->ptl);
 		return 0;
@@ -3383,7 +3600,7 @@
 	 * Flag if the page is shared between multiple address spaces. This
 	 * is later used when determining whether to group tasks together
 	 */
-	if (page_mapcount(page) > 1 && (vma->vm_flags & VM_SHARED))
+	if (page_mapcount(page) > 1 && (fe->vma_flags & VM_SHARED))
 		flags |= TNF_SHARED;
 
 	last_cpupid = page_cpupid_last(page);
@@ -3397,7 +3614,7 @@
 	}
 
 	/* Migrate to the requested node */
-	migrated = migrate_misplaced_page(page, vma, target_nid);
+	migrated = migrate_misplaced_page(page, fe, target_nid);
 	if (migrated) {
 		page_nid = target_nid;
 		flags |= TNF_MIGRATED;
@@ -3430,7 +3647,7 @@
 				fe->flags);
 
 	/* COW handled on pte level: split pmd */
-	VM_BUG_ON_VMA(fe->vma->vm_flags & VM_SHARED, fe->vma);
+	VM_BUG_ON_VMA(fe->vma_flags & VM_SHARED, fe->vma);
 	split_huge_pmd(fe->vma, fe->pmd, fe->address);
 
 	return VM_FAULT_FALLBACK;
@@ -3458,17 +3675,26 @@
  */
 static int handle_pte_fault(struct fault_env *fe)
 {
-	pte_t entry;
+	pte_t uninitialized_var(entry);
 
 	if (unlikely(pmd_none(*fe->pmd))) {
 		/*
+		 * In the case of the speculative page fault handler we abort
+		 * the speculative path immediately as the pmd is probably
+		 * in the way to be converted in a huge one. We will try
+		 * again holding the mmap_sem (which implies that the collapse
+		 * operation is done).
+		 */
+		if (fe->flags & FAULT_FLAG_SPECULATIVE)
+			return VM_FAULT_RETRY;
+		/*
 		 * Leave __pte_alloc() until later: because vm_ops->fault may
 		 * want to allocate huge page, and if we expose page table
 		 * for an instant, it will be difficult to retract from
 		 * concurrent faults and from rmap lookups.
 		 */
 		fe->pte = NULL;
-	} else {
+	} else if (!(fe->flags & FAULT_FLAG_SPECULATIVE)) {
 		/* See comment in pte_alloc_one_map() */
 		if (pmd_devmap_trans_unstable(fe->pmd))
 			return 0;
@@ -3477,6 +3703,9 @@
 		 * pmd from under us anymore at this point because we hold the
 		 * mmap_sem read mode and khugepaged takes it in write mode.
 		 * So now it's safe to run pte_offset_map().
+		 * This is not applicable to the speculative page fault handler
+		 * but in that case, the pte is fetched earlier in
+		 * handle_speculative_fault().
 		 */
 		fe->pte = pte_offset_map(fe->pmd, fe->address);
 
@@ -3500,18 +3729,24 @@
 	if (!fe->pte) {
 		if (vma_is_anonymous(fe->vma))
 			return do_anonymous_page(fe);
+		else if (fe->flags & FAULT_FLAG_SPECULATIVE)
+			return VM_FAULT_RETRY;
 		else
 			return do_fault(fe);
 	}
 
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+	if (fe->flags & FAULT_FLAG_SPECULATIVE)
+		entry = fe->orig_pte;
+#endif
 	if (!pte_present(entry))
 		return do_swap_page(fe, entry);
 
 	if (pte_protnone(entry) && vma_is_accessible(fe->vma))
 		return do_numa_page(fe, entry);
 
-	fe->ptl = pte_lockptr(fe->vma->vm_mm, fe->pmd);
-	spin_lock(fe->ptl);
+	if (!pte_spinlock(fe->vma->vm_mm, fe))
+		return VM_FAULT_RETRY;
 	if (unlikely(!pte_same(*fe->pte, entry)))
 		goto unlock;
 	if (fe->flags & FAULT_FLAG_WRITE) {
@@ -3551,6 +3786,8 @@
 		.vma = vma,
 		.address = address,
 		.flags = flags,
+		.vma_flags = vma->vm_flags,
+		.vma_page_prot = vma->vm_page_prot,
 	};
 	struct mm_struct *mm = vma->vm_mm;
 	pgd_t *pgd;
@@ -3570,7 +3807,9 @@
 	} else {
 		pmd_t orig_pmd = *fe.pmd;
 		int ret;
-
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+		fe.sequence = raw_read_seqcount(&vma->vm_sequence);
+#endif
 		barrier();
 		if (pmd_trans_huge(orig_pmd) || pmd_devmap(orig_pmd)) {
 			if (pmd_protnone(orig_pmd) && vma_is_accessible(vma))
@@ -3591,6 +3830,247 @@
 	return handle_pte_fault(&fe);
 }
 
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+
+#ifndef __HAVE_ARCH_PTE_SPECIAL
+/* This is required by vm_normal_page() */
+#error "Speculative page fault handler requires __HAVE_ARCH_PTE_SPECIAL"
+#endif
+/*
+ * vm_normal_page() adds some processing which should be done while
+ * hodling the mmap_sem.
+ */
+
+/*
+ * Tries to handle the page fault in a speculative way, without grabbing the
+ * mmap_sem.
+ * When VM_FAULT_RETRY is returned, the vma pointer is valid and this vma must
+ * be checked later when the mmap_sem has been grabbed by calling
+ * can_reuse_spf_vma().
+ * This is needed as the returned vma is kept in memory until the call to
+ * can_reuse_spf_vma() is made.
+ */
+int __handle_speculative_fault(struct mm_struct *mm, unsigned long address,
+			       unsigned int flags, struct vm_area_struct **vma)
+{
+	struct fault_env fe = {
+		.address = address,
+	};
+	pgd_t *pgd, pgdval;
+	pud_t *pud, pudval;
+	int seq, ret;
+
+	/* Clear flags that may lead to release the mmap_sem to retry */
+	flags &= ~(FAULT_FLAG_ALLOW_RETRY|FAULT_FLAG_KILLABLE);
+	flags |= FAULT_FLAG_SPECULATIVE;
+
+	*vma = get_vma(mm, address);
+	if (!*vma)
+		return VM_FAULT_RETRY;
+	fe.vma = *vma;
+
+	/* rmb <-> seqlock,vma_rb_erase() */
+	seq = raw_read_seqcount(&fe.vma->vm_sequence);
+	if (seq & 1) {
+		trace_spf_vma_changed(_RET_IP_, fe.vma, address);
+		return VM_FAULT_RETRY;
+	}
+
+	/*
+	 * Can't call vm_ops service has we don't know what they would do
+	 * with the VMA.
+	 * This include huge page from hugetlbfs.
+	 */
+	if (fe.vma->vm_ops) {
+		trace_spf_vma_notsup(_RET_IP_, fe.vma, address);
+		return VM_FAULT_RETRY;
+	}
+
+	/*
+	 * __anon_vma_prepare() requires the mmap_sem to be held
+	 * because vm_next and vm_prev must be safe. This can't be guaranteed
+	 * in the speculative path.
+	 */
+	if (unlikely(!fe.vma->anon_vma)) {
+		trace_spf_vma_notsup(_RET_IP_, fe.vma, address);
+		return VM_FAULT_RETRY;
+	}
+
+	fe.vma_flags = READ_ONCE(fe.vma->vm_flags);
+	fe.vma_page_prot = READ_ONCE(fe.vma->vm_page_prot);
+
+	/* Can't call userland page fault handler in the speculative path */
+	if (unlikely(fe.vma_flags & VM_UFFD_MISSING)) {
+		trace_spf_vma_notsup(_RET_IP_, fe.vma, address);
+		return VM_FAULT_RETRY;
+	}
+
+	if (fe.vma_flags & VM_GROWSDOWN || fe.vma_flags & VM_GROWSUP) {
+		/*
+		 * This could be detected by the check address against VMA's
+		 * boundaries but we want to trace it as not supported instead
+		 * of changed.
+		 */
+		trace_spf_vma_notsup(_RET_IP_, fe.vma, address);
+		return VM_FAULT_RETRY;
+	}
+
+	if (address < READ_ONCE(fe.vma->vm_start)
+	    || READ_ONCE(fe.vma->vm_end) <= address) {
+		trace_spf_vma_changed(_RET_IP_, fe.vma, address);
+		return VM_FAULT_RETRY;
+	}
+
+	if (!arch_vma_access_permitted(fe.vma, flags & FAULT_FLAG_WRITE,
+				       flags & FAULT_FLAG_INSTRUCTION,
+				       flags & FAULT_FLAG_REMOTE))
+		goto out_segv;
+
+	/* This is one is required to check that the VMA has write access set */
+	if (flags & FAULT_FLAG_WRITE) {
+		if (unlikely(!(fe.vma_flags & VM_WRITE)))
+			goto out_segv;
+	} else if (unlikely(!(fe.vma_flags & (VM_READ|VM_EXEC|VM_WRITE))))
+		goto out_segv;
+
+#ifdef CONFIG_NUMA
+	struct mempolicy *pol;
+
+	/*
+	 * MPOL_INTERLEAVE implies additional checks in
+	 * mpol_misplaced() which are not compatible with the
+	 *speculative page fault processing.
+	 */
+	pol = __get_vma_policy(fe.vma, address);
+	if (!pol)
+		pol = get_task_policy(current);
+
+	if (pol && pol->mode == MPOL_INTERLEAVE) {
+		trace_spf_vma_notsup(_RET_IP_, fe.vma, address);
+		return VM_FAULT_RETRY;
+	}
+#endif
+
+	/*
+	 * Do a speculative lookup of the PTE entry.
+	 */
+	local_irq_disable();
+	pgd = pgd_offset(mm, address);
+	pgdval = READ_ONCE(*pgd);
+	if (pgd_none(pgdval) || unlikely(pgd_bad(pgdval)))
+		goto out_walk;
+
+	pud = pud_offset(pgd, address);
+	pudval = READ_ONCE(*pud);
+	if (pud_none(pudval) || unlikely(pud_bad(pudval)))
+		goto out_walk;
+
+	fe.pmd = pmd_offset(pud, address);
+	fe.orig_pmd = READ_ONCE(*fe.pmd);
+	/*
+	 * pmd_none could mean that a hugepage collapse is in progress
+	 * in our back as collapse_huge_page() mark it before
+	 * invalidating the pte (which is done once the IPI is catched
+	 * by all CPU and we have interrupt disabled).
+	 * For this reason we cannot handle THP in a speculative way since we
+	 * can't safely indentify an in progress collapse operation done in our
+	 * back on that PMD.
+	 * Regarding the order of the following checks, see comment in
+	 * pmd_devmap_trans_unstable()
+	 */
+	if (unlikely(pmd_devmap(fe.orig_pmd) ||
+		     pmd_none(fe.orig_pmd) || pmd_trans_huge(fe.orig_pmd)))
+		goto out_walk;
+
+	/*
+	 * The above does not allocate/instantiate page-tables because doing so
+	 * would lead to the possibility of instantiating page-tables after
+	 * free_pgtables() -- and consequently leaking them.
+	 *
+	 * The result is that we take at least one !speculative fault per PMD
+	 * in order to instantiate it.
+	 */
+
+	fe.pte = pte_offset_map(fe.pmd, address);
+	fe.orig_pte = READ_ONCE(*fe.pte);
+	barrier(); /* See comment in handle_pte_fault() */
+	if (pte_none(fe.orig_pte)) {
+		pte_unmap(fe.pte);
+		fe.pte = NULL;
+	}
+
+	fe.sequence = seq;
+	fe.flags = flags;
+
+	local_irq_enable();
+
+	/*
+	 * We need to re-validate the VMA after checking the bounds, otherwise
+	 * we might have a false positive on the bounds.
+	 */
+	if (read_seqcount_retry(&fe.vma->vm_sequence, seq)) {
+		trace_spf_vma_changed(_RET_IP_, fe.vma, address);
+		return VM_FAULT_RETRY;
+	}
+
+	mem_cgroup_oom_enable();
+	ret = handle_pte_fault(&fe);
+	mem_cgroup_oom_disable();
+
+	/*
+	 * If there is no need to retry, don't return the vma to the caller.
+	 */
+	if (ret != VM_FAULT_RETRY) {
+		count_vm_event(SPECULATIVE_PGFAULT);
+		put_vma(fe.vma);
+		*vma = NULL;
+	}
+
+	/*
+	 * The task may have entered a memcg OOM situation but
+	 * if the allocation error was handled gracefully (no
+	 * VM_FAULT_OOM), there is no need to kill anything.
+	 * Just clean up the OOM state peacefully.
+	 */
+	if (task_in_memcg_oom(current) && !(ret & VM_FAULT_OOM))
+		mem_cgroup_oom_synchronize(false);
+	return ret;
+
+out_walk:
+	trace_spf_vma_notsup(_RET_IP_, fe.vma, address);
+	local_irq_enable();
+	return VM_FAULT_RETRY;
+
+out_segv:
+	trace_spf_vma_access(_RET_IP_, fe.vma, address);
+	/*
+	 * We don't return VM_FAULT_RETRY so the caller is not expected to
+	 * retrieve the fetched VMA.
+	 */
+	put_vma(fe.vma);
+	*vma = NULL;
+	return VM_FAULT_SIGSEGV;
+}
+
+/*
+ * This is used to know if the vma fetch in the speculative page fault handler
+ * is still valid when trying the regular fault path while holding the
+ * mmap_sem.
+ * The call to put_vma(vma) must be made after checking the vma's fields, as
+ * the vma may be freed by put_vma(). In such a case it is expected that false
+ * is returned.
+ */
+bool can_reuse_spf_vma(struct vm_area_struct *vma, unsigned long address)
+{
+	bool ret;
+
+	ret = !RB_EMPTY_NODE(&vma->vm_rb) &&
+		vma->vm_start <= address && address < vma->vm_end;
+	put_vma(vma);
+	return ret;
+}
+#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
+
 /*
  * By the time we get here, we already hold the mm semaphore
  *
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index d0adeef..ecbe6ec 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -442,8 +442,11 @@
 	struct vm_area_struct *vma;
 
 	down_write(&mm->mmap_sem);
-	for (vma = mm->mmap; vma; vma = vma->vm_next)
+	for (vma = mm->mmap; vma; vma = vma->vm_next) {
+		vm_write_begin(vma);
 		mpol_rebind_policy(vma->vm_policy, new, MPOL_REBIND_ONCE);
+		vm_write_end(vma);
+	}
 	up_write(&mm->mmap_sem);
 }
 
@@ -601,9 +604,11 @@
 {
 	int nr_updated;
 
+	vm_write_begin(vma);
 	nr_updated = change_protection(vma, addr, end, PAGE_NONE, 0, 1);
 	if (nr_updated)
 		count_vm_numa_events(NUMA_PTE_UPDATES, nr_updated);
+	vm_write_end(vma);
 
 	return nr_updated;
 }
@@ -704,6 +709,7 @@
 	if (IS_ERR(new))
 		return PTR_ERR(new);
 
+	vm_write_begin(vma);
 	if (vma->vm_ops && vma->vm_ops->set_policy) {
 		err = vma->vm_ops->set_policy(vma, new);
 		if (err)
@@ -711,11 +717,17 @@
 	}
 
 	old = vma->vm_policy;
-	vma->vm_policy = new; /* protected by mmap_sem */
+	/*
+	 * The speculative page fault handler accesses this field without
+	 * hodling the mmap_sem.
+	 */
+	WRITE_ONCE(vma->vm_policy,  new);
+	vm_write_end(vma);
 	mpol_put(old);
 
 	return 0;
  err_out:
+	vm_write_end(vma);
 	mpol_put(new);
 	return err;
 }
@@ -1586,23 +1598,28 @@
 struct mempolicy *__get_vma_policy(struct vm_area_struct *vma,
 						unsigned long addr)
 {
-	struct mempolicy *pol = NULL;
+	struct mempolicy *pol;
 
-	if (vma) {
-		if (vma->vm_ops && vma->vm_ops->get_policy) {
-			pol = vma->vm_ops->get_policy(vma, addr);
-		} else if (vma->vm_policy) {
-			pol = vma->vm_policy;
+	if (!vma)
+		return NULL;
 
-			/*
-			 * shmem_alloc_page() passes MPOL_F_SHARED policy with
-			 * a pseudo vma whose vma->vm_ops=NULL. Take a reference
-			 * count on these policies which will be dropped by
-			 * mpol_cond_put() later
-			 */
-			if (mpol_needs_cond_ref(pol))
-				mpol_get(pol);
-		}
+	if (vma->vm_ops && vma->vm_ops->get_policy)
+		return vma->vm_ops->get_policy(vma, addr);
+
+	/*
+	 * This could be called without holding the mmap_sem in the
+	 * speculative page fault handler's path.
+	 */
+	pol = READ_ONCE(vma->vm_policy);
+	if (pol) {
+		/*
+		 * shmem_alloc_page() passes MPOL_F_SHARED policy with
+		 * a pseudo vma whose vma->vm_ops=NULL. Take a reference
+		 * count on these policies which will be dropped by
+		 * mpol_cond_put() later
+		 */
+		if (mpol_needs_cond_ref(pol))
+			mpol_get(pol);
 	}
 
 	return pol;
diff --git a/mm/migrate.c b/mm/migrate.c
index eb1f043..595b456 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -241,7 +241,7 @@
 
 	/* Recheck VMA as permissions can change since migration started  */
 	if (is_write_migration_entry(entry))
-		pte = maybe_mkwrite(pte, vma);
+		pte = maybe_mkwrite(pte, vma->vm_flags);
 
 #ifdef CONFIG_HUGETLB_PAGE
 	if (PageHuge(new)) {
@@ -1855,7 +1855,7 @@
  * node. Caller is expected to have an elevated reference count on
  * the page that will be dropped by this function before returning.
  */
-int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma,
+int migrate_misplaced_page(struct page *page, struct fault_env *fe,
 			   int node)
 {
 	pg_data_t *pgdat = NODE_DATA(node);
@@ -1868,7 +1868,7 @@
 	 * with execute permissions as they are probably shared libraries.
 	 */
 	if (page_mapcount(page) != 1 && page_is_file_cache(page) &&
-	    (vma->vm_flags & VM_EXEC))
+	    (fe->vma_flags & VM_EXEC))
 		goto out;
 
 	/*
diff --git a/mm/mlock.c b/mm/mlock.c
index 9cdd063..f648acb 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -438,7 +438,9 @@
 void munlock_vma_pages_range(struct vm_area_struct *vma,
 			     unsigned long start, unsigned long end)
 {
-	vma->vm_flags &= VM_LOCKED_CLEAR_MASK;
+	vm_write_begin(vma);
+	WRITE_ONCE(vma->vm_flags, vma->vm_flags & VM_LOCKED_CLEAR_MASK);
+	vm_write_end(vma);
 
 	while (start < end) {
 		struct page *page;
@@ -563,10 +565,11 @@
 	 * It's okay if try_to_unmap_one unmaps a page just after we
 	 * set VM_LOCKED, populate_vma_page_range will bring it back.
 	 */
-
-	if (lock)
-		vma->vm_flags = newflags;
-	else
+	if (lock) {
+		vm_write_begin(vma);
+		WRITE_ONCE(vma->vm_flags, newflags);
+		vm_write_end(vma);
+	} else
 		munlock_vma_pages_range(vma, start, end);
 
 out:
diff --git a/mm/mmap.c b/mm/mmap.c
index 2ce3870..9ba15d8 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -160,6 +160,27 @@
 	}
 }
 
+static void __free_vma(struct vm_area_struct *vma)
+{
+	if (vma->vm_file)
+		fput(vma->vm_file);
+	mpol_put(vma_policy(vma));
+	kmem_cache_free(vm_area_cachep, vma);
+}
+
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+void put_vma(struct vm_area_struct *vma)
+{
+	if (atomic_dec_and_test(&vma->vm_ref_count))
+		__free_vma(vma);
+}
+#else
+static inline void put_vma(struct vm_area_struct *vma)
+{
+	__free_vma(vma);
+}
+#endif
+
 /*
  * Close a vm structure and free it, returning the next.
  */
@@ -170,10 +191,7 @@
 	might_sleep();
 	if (vma->vm_ops && vma->vm_ops->close)
 		vma->vm_ops->close(vma);
-	if (vma->vm_file)
-		fput(vma->vm_file);
-	mpol_put(vma_policy(vma));
-	kmem_cache_free(vm_area_cachep, vma);
+	put_vma(vma);
 	return next;
 }
 
@@ -391,6 +409,14 @@
 #define validate_mm(mm) do { } while (0)
 #endif
 
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+#define mm_rb_write_lock(mm)	write_lock(&(mm)->mm_rb_lock)
+#define mm_rb_write_unlock(mm)	write_unlock(&(mm)->mm_rb_lock)
+#else
+#define mm_rb_write_lock(mm)	do { } while (0)
+#define mm_rb_write_unlock(mm)	do { } while (0)
+#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
+
 RB_DECLARE_CALLBACKS(static, vma_gap_callbacks, struct vm_area_struct, vm_rb,
 		     unsigned long, rb_subtree_gap, vma_compute_subtree_gap)
 
@@ -409,26 +435,37 @@
 }
 
 static inline void vma_rb_insert(struct vm_area_struct *vma,
-				 struct rb_root *root)
+				 struct mm_struct *mm)
 {
+	struct rb_root *root = &mm->mm_rb;
+
 	/* All rb_subtree_gap values must be consistent prior to insertion */
 	validate_mm_rb(root, NULL);
 
 	rb_insert_augmented(&vma->vm_rb, root, &vma_gap_callbacks);
 }
 
-static void __vma_rb_erase(struct vm_area_struct *vma, struct rb_root *root)
+static void __vma_rb_erase(struct vm_area_struct *vma, struct mm_struct *mm)
 {
+	struct rb_root *root = &mm->mm_rb;
 	/*
 	 * Note rb_erase_augmented is a fairly large inline function,
 	 * so make sure we instantiate it only once with our desired
 	 * augmented rbtree callbacks.
 	 */
+	mm_rb_write_lock(mm);
 	rb_erase_augmented(&vma->vm_rb, root, &vma_gap_callbacks);
+	mm_rb_write_unlock(mm); /* wmb */
+
+	/*
+	 * Ensure the removal is complete before clearing the node.
+	 * Matched by vma_has_changed()/handle_speculative_fault().
+	 */
+	RB_CLEAR_NODE(&vma->vm_rb);
 }
 
 static __always_inline void vma_rb_erase_ignore(struct vm_area_struct *vma,
-						struct rb_root *root,
+						struct mm_struct *mm,
 						struct vm_area_struct *ignore)
 {
 	/*
@@ -436,21 +473,21 @@
 	 * with the possible exception of the "next" vma being erased if
 	 * next->vm_start was reduced.
 	 */
-	validate_mm_rb(root, ignore);
+	validate_mm_rb(&mm->mm_rb, ignore);
 
-	__vma_rb_erase(vma, root);
+	__vma_rb_erase(vma, mm);
 }
 
 static __always_inline void vma_rb_erase(struct vm_area_struct *vma,
-					 struct rb_root *root)
+					 struct mm_struct *mm)
 {
 	/*
 	 * All rb_subtree_gap values must be consistent prior to erase,
 	 * with the possible exception of the vma being erased.
 	 */
-	validate_mm_rb(root, vma);
+	validate_mm_rb(&mm->mm_rb, vma);
 
-	__vma_rb_erase(vma, root);
+	__vma_rb_erase(vma, mm);
 }
 
 /*
@@ -565,10 +602,12 @@
 	 * immediately update the gap to the correct value. Finally we
 	 * rebalance the rbtree after all augmented values have been set.
 	 */
+	mm_rb_write_lock(mm);
 	rb_link_node(&vma->vm_rb, rb_parent, rb_link);
 	vma->rb_subtree_gap = 0;
 	vma_gap_update(vma);
-	vma_rb_insert(vma, &mm->mm_rb);
+	vma_rb_insert(vma, mm);
+	mm_rb_write_unlock(mm);
 }
 
 static void __vma_link_file(struct vm_area_struct *vma)
@@ -644,7 +683,7 @@
 {
 	struct vm_area_struct *next;
 
-	vma_rb_erase_ignore(vma, &mm->mm_rb, ignore);
+	vma_rb_erase_ignore(vma, mm, ignore);
 	next = vma->vm_next;
 	if (has_prev)
 		prev->vm_next = next;
@@ -678,7 +717,7 @@
  */
 int __vma_adjust(struct vm_area_struct *vma, unsigned long start,
 	unsigned long end, pgoff_t pgoff, struct vm_area_struct *insert,
-	struct vm_area_struct *expand)
+	struct vm_area_struct *expand, bool keep_locked)
 {
 	struct mm_struct *mm = vma->vm_mm;
 	struct vm_area_struct *next = vma->vm_next, *orig_vma = vma;
@@ -690,6 +729,30 @@
 	long adjust_next = 0;
 	int remove_next = 0;
 
+	/*
+	 * Why using vm_raw_write*() functions here to avoid lockdep's warning ?
+	 *
+	 * Locked is complaining about a theoretical lock dependency, involving
+	 * 3 locks:
+	 *   mapping->i_mmap_rwsem --> vma->vm_sequence --> fs_reclaim
+	 *
+	 * Here are the major path leading to this dependency :
+	 *  1. __vma_adjust() mmap_sem  -> vm_sequence -> i_mmap_rwsem
+	 *  2. move_vmap() mmap_sem -> vm_sequence -> fs_reclaim
+	 *  3. __alloc_pages_nodemask() fs_reclaim -> i_mmap_rwsem
+	 *  4. unmap_mapping_range() i_mmap_rwsem -> vm_sequence
+	 *
+	 * So there is no way to solve this easily, especially because in
+	 * unmap_mapping_range() the i_mmap_rwsem is grab while the impacted
+	 * VMAs are not yet known.
+	 * However, the way the vm_seq is used is guarantying that we will
+	 * never block on it since we just check for its value and never wait
+	 * for it to move, see vma_has_changed() and handle_speculative_fault().
+	 */
+	vm_raw_write_begin(vma);
+	if (next)
+		vm_raw_write_begin(next);
+
 	if (next && !insert) {
 		struct vm_area_struct *exporter = NULL, *importer = NULL;
 
@@ -770,8 +833,12 @@
 
 			importer->anon_vma = exporter->anon_vma;
 			error = anon_vma_clone(importer, exporter);
-			if (error)
+			if (error) {
+				if (next && next != vma)
+					vm_raw_write_end(next);
+				vm_raw_write_end(vma);
 				return error;
+			}
 		}
 	}
 again:
@@ -817,17 +884,18 @@
 	}
 
 	if (start != vma->vm_start) {
-		vma->vm_start = start;
+		WRITE_ONCE(vma->vm_start, start);
 		start_changed = true;
 	}
 	if (end != vma->vm_end) {
-		vma->vm_end = end;
+		WRITE_ONCE(vma->vm_end, end);
 		end_changed = true;
 	}
-	vma->vm_pgoff = pgoff;
+	WRITE_ONCE(vma->vm_pgoff, pgoff);
 	if (adjust_next) {
-		next->vm_start += adjust_next << PAGE_SHIFT;
-		next->vm_pgoff += adjust_next;
+		WRITE_ONCE(next->vm_start,
+			   next->vm_start + (adjust_next << PAGE_SHIFT));
+		WRITE_ONCE(next->vm_pgoff, next->vm_pgoff + adjust_next);
 	}
 
 	if (root) {
@@ -892,15 +960,13 @@
 	}
 
 	if (remove_next) {
-		if (file) {
+		if (file)
 			uprobe_munmap(next, next->vm_start, next->vm_end);
-			fput(file);
-		}
 		if (next->anon_vma)
 			anon_vma_merge(vma, next);
 		mm->map_count--;
-		mpol_put(vma_policy(next));
-		kmem_cache_free(vm_area_cachep, next);
+		vm_raw_write_end(next);
+		put_vma(next);
 		/*
 		 * In mprotect's case 6 (see comments on vma_merge),
 		 * we must remove another next too. It would clutter
@@ -914,6 +980,8 @@
 			 * "vma->vm_next" gap must be updated.
 			 */
 			next = vma->vm_next;
+			if (next)
+				vm_raw_write_begin(next);
 		} else {
 			/*
 			 * For the scope of the comment "next" and
@@ -960,6 +1028,11 @@
 	if (insert && file)
 		uprobe_mmap(insert);
 
+	if (next && next != vma)
+		vm_raw_write_end(next);
+	if (!keep_locked)
+		vm_raw_write_end(vma);
+
 	validate_mm(mm);
 
 	return 0;
@@ -1099,13 +1172,13 @@
  * parameter) may establish ptes with the wrong permissions of NNNN
  * instead of the right permissions of XXXX.
  */
-struct vm_area_struct *vma_merge(struct mm_struct *mm,
+struct vm_area_struct *__vma_merge(struct mm_struct *mm,
 			struct vm_area_struct *prev, unsigned long addr,
 			unsigned long end, unsigned long vm_flags,
 			struct anon_vma *anon_vma, struct file *file,
 			pgoff_t pgoff, struct mempolicy *policy,
 			struct vm_userfaultfd_ctx vm_userfaultfd_ctx,
-			const char __user *anon_name)
+			const char __user *anon_name, bool keep_locked)
 {
 	pgoff_t pglen = (end - addr) >> PAGE_SHIFT;
 	struct vm_area_struct *area, *next;
@@ -1155,10 +1228,11 @@
 							/* cases 1, 6 */
 			err = __vma_adjust(prev, prev->vm_start,
 					 next->vm_end, prev->vm_pgoff, NULL,
-					 prev);
+					 prev, keep_locked);
 		} else					/* cases 2, 5, 7 */
 			err = __vma_adjust(prev, prev->vm_start,
-					 end, prev->vm_pgoff, NULL, prev);
+					   end, prev->vm_pgoff, NULL, prev,
+					   keep_locked);
 		if (err)
 			return NULL;
 		khugepaged_enter_vma_merge(prev, vm_flags);
@@ -1176,10 +1250,12 @@
 					     anon_name)) {
 		if (prev && addr < prev->vm_end)	/* case 4 */
 			err = __vma_adjust(prev, prev->vm_start,
-					 addr, prev->vm_pgoff, NULL, next);
+					 addr, prev->vm_pgoff, NULL, next,
+					 keep_locked);
 		else {					/* cases 3, 8 */
 			err = __vma_adjust(area, addr, next->vm_end,
-					 next->vm_pgoff - pglen, NULL, next);
+					 next->vm_pgoff - pglen, NULL, next,
+					 keep_locked);
 			/*
 			 * In case 3 area is already equal to next and
 			 * this is a noop, but in case 8 "area" has
@@ -1704,7 +1780,7 @@
 	vma->vm_flags = vm_flags;
 	vma->vm_page_prot = vm_get_page_prot(vm_flags);
 	vma->vm_pgoff = pgoff;
-	INIT_LIST_HEAD(&vma->anon_vma_chain);
+	INIT_VMA(vma);
 
 	if (file) {
 		if (vm_flags & VM_DENYWRITE) {
@@ -1757,13 +1833,15 @@
 out:
 	perf_event_mmap(vma);
 
+	vm_write_begin(vma);
 	vm_stat_account(mm, vm_flags, len >> PAGE_SHIFT);
 	if (vm_flags & VM_LOCKED) {
 		if (!((vm_flags & VM_SPECIAL) || is_vm_hugetlb_page(vma) ||
 					vma == get_gate_vma(current->mm)))
 			mm->locked_vm += (len >> PAGE_SHIFT);
 		else
-			vma->vm_flags &= VM_LOCKED_CLEAR_MASK;
+			WRITE_ONCE(vma->vm_flags,
+				   vma->vm_flags & VM_LOCKED_CLEAR_MASK);
 	}
 
 	if (file)
@@ -1776,9 +1854,10 @@
 	 * then new mapped in-place (which must be aimed as
 	 * a completely new data area).
 	 */
-	vma->vm_flags |= VM_SOFTDIRTY;
+	WRITE_ONCE(vma->vm_flags, vma->vm_flags | VM_SOFTDIRTY);
 
 	vma_set_page_prot(vma);
+	vm_write_end(vma);
 
 	return addr;
 
@@ -2150,15 +2229,11 @@
 EXPORT_SYMBOL(get_unmapped_area);
 
 /* Look up the first VMA which satisfies  addr < vm_end,  NULL if none. */
-struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
+static struct vm_area_struct *__find_vma(struct mm_struct *mm,
+					 unsigned long addr)
 {
 	struct rb_node *rb_node;
-	struct vm_area_struct *vma;
-
-	/* Check the cache first. */
-	vma = vmacache_find(mm, addr);
-	if (likely(vma))
-		return vma;
+	struct vm_area_struct *vma = NULL;
 
 	rb_node = mm->mm_rb.rb_node;
 
@@ -2176,13 +2251,40 @@
 			rb_node = rb_node->rb_right;
 	}
 
+	return vma;
+}
+
+struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
+{
+	struct vm_area_struct *vma;
+
+	/* Check the cache first. */
+	vma = vmacache_find(mm, addr);
+	if (likely(vma))
+		return vma;
+
+	vma = __find_vma(mm, addr);
 	if (vma)
 		vmacache_update(addr, vma);
 	return vma;
 }
-
 EXPORT_SYMBOL(find_vma);
 
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+struct vm_area_struct *get_vma(struct mm_struct *mm, unsigned long addr)
+{
+	struct vm_area_struct *vma = NULL;
+
+	read_lock(&mm->mm_rb_lock);
+	vma = __find_vma(mm, addr);
+	if (vma)
+		atomic_inc(&vma->vm_ref_count);
+	read_unlock(&mm->mm_rb_lock);
+
+	return vma;
+}
+#endif
+
 /*
  * Same as find_vma, but also return a pointer to the previous VMA in *pprev.
  */
@@ -2412,8 +2514,8 @@
 					mm->locked_vm += grow;
 				vm_stat_account(mm, vma->vm_flags, grow);
 				anon_vma_interval_tree_pre_update_vma(vma);
-				vma->vm_start = address;
-				vma->vm_pgoff -= grow;
+				WRITE_ONCE(vma->vm_start, address);
+				WRITE_ONCE(vma->vm_pgoff, vma->vm_pgoff - grow);
 				anon_vma_interval_tree_post_update_vma(vma);
 				vma_gap_update(vma);
 				spin_unlock(&mm->page_table_lock);
@@ -2555,7 +2657,7 @@
 	insertion_point = (prev ? &prev->vm_next : &mm->mmap);
 	vma->vm_prev = NULL;
 	do {
-		vma_rb_erase(vma, &mm->mm_rb);
+		vma_rb_erase(vma, mm);
 		mm->map_count--;
 		tail_vma = vma;
 		vma = vma->vm_next;
@@ -2595,7 +2697,7 @@
 	/* most fields are the same, copy all, and then fixup */
 	*new = *vma;
 
-	INIT_LIST_HEAD(&new->anon_vma_chain);
+	INIT_VMA(new);
 
 	if (new_below)
 		new->vm_end = addr;
@@ -2952,7 +3054,7 @@
 		return -ENOMEM;
 	}
 
-	INIT_LIST_HEAD(&vma->anon_vma_chain);
+	INIT_VMA(vma);
 	vma->vm_mm = mm;
 	vma->vm_start = addr;
 	vma->vm_end = addr + len;
@@ -3115,9 +3217,21 @@
 
 	if (find_vma_links(mm, addr, addr + len, &prev, &rb_link, &rb_parent))
 		return NULL;	/* should never get here */
-	new_vma = vma_merge(mm, prev, addr, addr + len, vma->vm_flags,
-			    vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma),
-			    vma->vm_userfaultfd_ctx, vma_get_anon_name(vma));
+
+	/* There is 3 cases to manage here in
+	 *     AAAA            AAAA              AAAA              AAAA
+	 * PPPP....      PPPP......NNNN      PPPP....NNNN      PP........NN
+	 * PPPPPPPP(A)   PPPP..NNNNNNNN(B)   PPPPPPPPPPPP(1)       NULL
+	 *                                   PPPPPPPPNNNN(2)
+	 *                                   PPPPNNNNNNNN(3)
+	 *
+	 * new_vma == prev in case A,1,2
+	 * new_vma == next in case B,3
+	 */
+	new_vma = __vma_merge(mm, prev, addr, addr + len, vma->vm_flags,
+			      vma->anon_vma, vma->vm_file, pgoff,
+			      vma_policy(vma), vma->vm_userfaultfd_ctx,
+				vma_get_anon_name(vma), true);
 	if (new_vma) {
 		/*
 		 * Source vma may have been merged into new_vma
@@ -3150,13 +3264,22 @@
 		new_vma->vm_pgoff = pgoff;
 		if (vma_dup_policy(vma, new_vma))
 			goto out_free_vma;
-		INIT_LIST_HEAD(&new_vma->anon_vma_chain);
+		INIT_VMA(new_vma);
 		if (anon_vma_clone(new_vma, vma))
 			goto out_free_mempol;
 		if (new_vma->vm_file)
 			get_file(new_vma->vm_file);
 		if (new_vma->vm_ops && new_vma->vm_ops->open)
 			new_vma->vm_ops->open(new_vma);
+		/*
+		 * As the VMA is linked right now, it may be hit by the
+		 * speculative page fault handler. But we don't want it to
+		 * to start mapping page in this area until the caller has
+		 * potentially move the pte from the moved VMA. To prevent
+		 * that we protect it right now, and let the caller unprotect
+		 * it once the move is done.
+		 */
+		vm_raw_write_begin(new_vma);
 		vma_link(mm, new_vma, prev, rb_link, rb_parent);
 		*need_rmap_locks = false;
 	}
@@ -3288,7 +3411,7 @@
 	if (unlikely(vma == NULL))
 		return ERR_PTR(-ENOMEM);
 
-	INIT_LIST_HEAD(&vma->anon_vma_chain);
+	INIT_VMA(vma);
 	vma->vm_mm = mm;
 	vma->vm_start = addr;
 	vma->vm_end = addr + len;
diff --git a/mm/mprotect.c b/mm/mprotect.c
index 1f2c969..60b16418 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -329,12 +329,14 @@
 	 * vm_flags and vm_page_prot are protected by the mmap_sem
 	 * held in write mode.
 	 */
-	vma->vm_flags = newflags;
+	vm_write_begin(vma);
+	WRITE_ONCE(vma->vm_flags, newflags);
 	dirty_accountable = vma_wants_writenotify(vma, vma->vm_page_prot);
 	vma_set_page_prot(vma);
 
 	change_protection(vma, start, end, vma->vm_page_prot,
 			  dirty_accountable, 0);
+	vm_write_end(vma);
 
 	/*
 	 * Private VM_LOCKED VMA becoming writable: trigger COW to avoid major
diff --git a/mm/mremap.c b/mm/mremap.c
index 1597671..2302762 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -289,6 +289,14 @@
 	if (!new_vma)
 		return -ENOMEM;
 
+	/* new_vma is returned protected by copy_vma, to prevent speculative
+	 * page fault to be done in the destination area before we move the pte.
+	 * Now, we must also protect the source VMA since we don't want pages
+	 * to be mapped in our back while we are copying the PTEs.
+	 */
+	if (vma != new_vma)
+		vm_raw_write_begin(vma);
+
 	moved_len = move_page_tables(vma, old_addr, new_vma, new_addr, old_len,
 				     need_rmap_locks);
 	if (moved_len < old_len) {
@@ -305,6 +313,8 @@
 		 */
 		move_page_tables(new_vma, new_addr, vma, old_addr, moved_len,
 				 true);
+		if (vma != new_vma)
+			vm_raw_write_end(vma);
 		vma = new_vma;
 		old_len = new_len;
 		old_addr = new_addr;
@@ -312,7 +322,10 @@
 	} else {
 		arch_remap(mm, old_addr, old_addr + old_len,
 			   new_addr, new_addr + new_len);
+		if (vma != new_vma)
+			vm_raw_write_end(vma);
 	}
+	vm_raw_write_end(new_vma);
 
 	/* Conceal VM_ACCOUNT so old reservation is not undone */
 	if (vm_flags & VM_ACCOUNT) {
diff --git a/mm/nommu.c b/mm/nommu.c
index 44265e0..d033ee8 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1243,7 +1243,7 @@
 	region->vm_flags = vm_flags;
 	region->vm_pgoff = pgoff;
 
-	INIT_LIST_HEAD(&vma->anon_vma_chain);
+	INIT_VMA(vma);
 	vma->vm_flags = vm_flags;
 	vma->vm_pgoff = pgoff;
 
diff --git a/mm/rmap.c b/mm/rmap.c
index 4d19dd1..24470a6 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1266,7 +1266,7 @@
 }
 
 /**
- * page_add_new_anon_rmap - add pte mapping to a new anonymous page
+ * __page_add_new_anon_rmap - add pte mapping to a new anonymous page
  * @page:	the page to add the mapping to
  * @vma:	the vm area in which the mapping is added
  * @address:	the user virtual address mapped
@@ -1276,12 +1276,11 @@
  * This means the inc-and-test can be bypassed.
  * Page does not have to be locked.
  */
-void page_add_new_anon_rmap(struct page *page,
+void __page_add_new_anon_rmap(struct page *page,
 	struct vm_area_struct *vma, unsigned long address, bool compound)
 {
 	int nr = compound ? hpage_nr_pages(page) : 1;
 
-	VM_BUG_ON_VMA(address < vma->vm_start || address >= vma->vm_end, vma);
 	__SetPageSwapBacked(page);
 	if (compound) {
 		VM_BUG_ON_PAGE(!PageTransHuge(page), page);
diff --git a/mm/swap.c b/mm/swap.c
index 6f22754..5827225 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -468,12 +468,12 @@
  * directly back onto it's zone's unevictable list, it does NOT use a
  * per cpu pagevec.
  */
-void lru_cache_add_active_or_unevictable(struct page *page,
-					 struct vm_area_struct *vma)
+void __lru_cache_add_active_or_unevictable(struct page *page,
+					   unsigned long vma_flags)
 {
 	VM_BUG_ON_PAGE(PageLRU(page), page);
 
-	if (likely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED)) {
+	if (likely((vma_flags & (VM_LOCKED | VM_SPECIAL)) != VM_LOCKED)) {
 		SetPageActive(page);
 		lru_cache_add(page);
 		return;
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 5ac5846..35f882d 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -467,6 +467,10 @@
  * the readahead.
  *
  * Caller must hold down_read on the vma->vm_mm if vma is not NULL.
+ * This is needed to ensure the VMA will not be freed in our back. In the case
+ * of the speculative page fault handler, this cannot happen, even if we don't
+ * hold the mmap_sem. Callees are assumed to take care of reading VMA's fields
+ * using READ_ONCE() to read consistent values.
  */
 struct page *swapin_readahead(swp_entry_t entry, gfp_t gfp_mask,
 			struct vm_area_struct *vma, unsigned long addr)
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index ed89128..6b5f0bc 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -543,7 +543,7 @@
 		}
 	}
 
-	if (printk_ratelimit())
+	if (!(gfp_mask & __GFP_NOWARN) && printk_ratelimit())
 		pr_warn("vmap allocation for size %lu failed: use vmalloc=<size> to increase size\n",
 			size);
 	kfree(va);
@@ -657,7 +657,8 @@
 
 	log = fls(num_online_cpus());
 
-	return log * (32UL * 1024 * 1024 / PAGE_SIZE);
+	return log * (1UL * CONFIG_VMAP_LAZY_PURGING_FACTOR *
+					1024 * 1024 / PAGE_SIZE);
 }
 
 static atomic_t vmap_lazy_nr = ATOMIC_INIT(0);
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 8bd62ed..3d128da 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -1088,7 +1088,10 @@
 	"vmacache_find_hits",
 	"vmacache_full_flushes",
 #endif
-#endif /* CONFIG_VM_EVENTS_COUNTERS */
+#ifdef CONFIG_SPECULATIVE_PAGE_FAULT
+	"speculative_pgfault"
+#endif
+#endif /* CONFIG_VM_EVENT_COUNTERS */
 };
 #endif /* CONFIG_PROC_FS || CONFIG_SYSFS || CONFIG_NUMA */
 
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 340a3db..59c1581 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -889,9 +889,12 @@
 	now = jiffies;
 	next = now + HZ;
 
-	if (!(state & NUD_IN_TIMER))
-		goto out;
-
+	if (!(state & NUD_IN_TIMER)) {
+		if (neigh_probe_enable && (state & NUD_STALE))
+			neigh_dbg(2, "neigh %pK is still alive\n", neigh);
+		else
+			goto out;
+	}
 	if (state & NUD_REACHABLE) {
 		if (time_before_eq(now,
 				   neigh->confirmed + neigh->parms->reachable_time)) {
@@ -1182,7 +1185,10 @@
 		neigh_del_timer(neigh);
 		if (new & NUD_PROBE)
 			atomic_set(&neigh->probes, 0);
-		if (new & NUD_IN_TIMER)
+		if (new & NUD_IN_TIMER || (
+			neigh_probe_enable &&
+			(neigh->tbl->family == AF_INET6) &&
+			(new & NUD_STALE)))
 			neigh_add_timer(neigh, (jiffies +
 						((new & NUD_REACHABLE) ?
 						 neigh->parms->reachable_time :
diff --git a/net/core/sockev_nlmcast.c b/net/core/sockev_nlmcast.c
index 04f61fc..f238edb 100644
--- a/net/core/sockev_nlmcast.c
+++ b/net/core/sockev_nlmcast.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2015, 2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-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
@@ -36,6 +36,8 @@
 
 static void _sockev_event(unsigned long event, __u8 *evstr, int buflen)
 {
+	memset(evstr, 0, buflen);
+
 	switch (event) {
 	case SOCKEV_SOCKET:
 		strlcpy(evstr, "SOCKEV_SOCKET", buflen);
@@ -67,14 +69,17 @@
 	struct nlmsghdr *nlh;
 	struct sknlsockevmsg *smsg;
 	struct socket *sock;
+	struct sock *sk;
 
 	sock = (struct socket *)data;
-	if (socknlmsgsk == 0)
-		goto done;
-	if ((!socknlmsgsk) || (!sock) || (!sock->sk))
+	if (!socknlmsgsk || !sock)
 		goto done;
 
-	if (sock->sk->sk_family != AF_INET && sock->sk->sk_family != AF_INET6)
+	sk = sock->sk;
+	if (!sk)
+		goto done;
+
+	if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)
 		goto done;
 
 	if (event != SOCKEV_BIND && event != SOCKEV_LISTEN)
@@ -95,12 +100,11 @@
 	smsg = nlmsg_data(nlh);
 	smsg->pid = current->pid;
 	_sockev_event(event, smsg->event, sizeof(smsg->event));
-	smsg->skfamily = sock->sk->sk_family;
-	smsg->skstate = sock->sk->sk_state;
-	smsg->skprotocol = sock->sk->sk_protocol;
-	smsg->sktype = sock->sk->sk_type;
-	smsg->skflags = sock->sk->sk_flags;
-
+	smsg->skfamily = sk->sk_family;
+	smsg->skstate = sk->sk_state;
+	smsg->skprotocol = sk->sk_protocol;
+	smsg->sktype = sk->sk_type;
+	smsg->skflags = sk->sk_flags;
 	nlmsg_notify(socknlmsgsk, skb, 0, SKNLGRP_SOCKEV, 0, GFP_KERNEL);
 done:
 	return 0;
diff --git a/net/ipc_router/Kconfig b/net/ipc_router/Kconfig
index 9121667..20f94aa 100644
--- a/net/ipc_router/Kconfig
+++ b/net/ipc_router/Kconfig
@@ -33,3 +33,12 @@
 	  The NODE defined here is used as the local NODE ID by IPC Router
 	  core and publish the same NODE ID to other NODES present in the
 	  network.
+
+config IPC_ROUTER_FIFO_XPRT
+	depends on IPC_ROUTER
+	bool "IPC Router FIFO Transport"
+	help
+	  FIFO Transport Layer that enables IPC Router communication between
+	  two virtual machines. When the Shared FIFO becomes available, this
+	  layer registers the transport with IPC Router and enable message
+	  exchange.
diff --git a/net/ipc_router/Makefile b/net/ipc_router/Makefile
index 501688e..63d33a5 100644
--- a/net/ipc_router/Makefile
+++ b/net/ipc_router/Makefile
@@ -5,3 +5,4 @@
 obj-$(CONFIG_IPC_ROUTER) := ipc_router_core.o
 obj-$(CONFIG_IPC_ROUTER) += ipc_router_socket.o
 obj-$(CONFIG_IPC_ROUTER_SECURITY) += ipc_router_security.o
+obj-$(CONFIG_IPC_ROUTER_FIFO_XPRT) += ipc_router_fifo_xprt.o
diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c
index 1a6b539..7c12a16 100644
--- a/net/ipc_router/ipc_router_core.c
+++ b/net/ipc_router/ipc_router_core.c
@@ -31,6 +31,7 @@
 #include <linux/ipc_router.h>
 #include <linux/ipc_router_xprt.h>
 #include <linux/kref.h>
+#include <linux/kthread.h>
 #include <soc/qcom/subsystem_notif.h>
 #include <soc/qcom/subsystem_restart.h>
 
@@ -144,12 +145,14 @@
 	struct mutex tx_lock_lhb2; /* lock for xprt tx operations */
 	u32 need_len;
 	u32 abort_data_read;
-	struct work_struct read_data;
-	struct workqueue_struct *workqueue;
 	void *log_ctx;
 	struct kref ref;
 	struct completion ref_complete;
 	bool dynamic_ws;
+
+	struct kthread_worker kworker;
+	struct task_struct *task;
+	struct kthread_work read_data;
 };
 
 #define RT_HASH_SIZE 4
@@ -176,7 +179,7 @@
 static DECLARE_RWSEM(routing_table_lock_lha3);
 static int routing_table_inited;
 
-static void do_read_data(struct work_struct *work);
+static void do_read_data(struct kthread_work *work);
 
 static LIST_HEAD(xprt_info_list);
 static DECLARE_RWSEM(xprt_info_list_lock_lha5);
@@ -2758,7 +2761,7 @@
 	return rc;
 }
 
-static void do_read_data(struct work_struct *work)
+static void do_read_data(struct kthread_work *work)
 {
 	struct rr_header_v1 *hdr;
 	struct rr_packet *pkt = NULL;
@@ -4077,6 +4080,7 @@
 static int msm_ipc_router_add_xprt(struct msm_ipc_router_xprt *xprt)
 {
 	struct msm_ipc_router_xprt_info *xprt_info;
+	struct sched_param param = {.sched_priority = 1};
 
 	xprt_info = kmalloc(sizeof(*xprt_info), GFP_KERNEL);
 	if (!xprt_info)
@@ -4092,7 +4096,6 @@
 	wakeup_source_init(&xprt_info->ws, xprt->name);
 	xprt_info->need_len = 0;
 	xprt_info->abort_data_read = 0;
-	INIT_WORK(&xprt_info->read_data, do_read_data);
 	INIT_LIST_HEAD(&xprt_info->list);
 	kref_init(&xprt_info->ref);
 	init_completion(&xprt_info->ref_complete);
@@ -4100,11 +4103,17 @@
 	if (xprt->get_ws_info)
 		xprt_info->dynamic_ws = xprt->get_ws_info(xprt);
 
-	xprt_info->workqueue = create_singlethread_workqueue(xprt->name);
-	if (!xprt_info->workqueue) {
+	kthread_init_work(&xprt_info->read_data, do_read_data);
+	kthread_init_worker(&xprt_info->kworker);
+	xprt_info->task = kthread_run(kthread_worker_fn,
+				      &xprt_info->kworker,
+				      "%s", xprt->name);
+	if (IS_ERR(xprt_info->task)) {
 		kfree(xprt_info);
 		return -ENOMEM;
 	}
+	if (xprt->get_latency_info && xprt->get_latency_info(xprt))
+		sched_setscheduler(xprt_info->task, SCHED_FIFO, &param);
 
 	xprt_info->log_ctx = ipc_router_get_log_ctx(xprt->name);
 
@@ -4144,8 +4153,9 @@
 		mutex_lock(&xprt_info->rx_lock_lhb2);
 		xprt_info->abort_data_read = 1;
 		mutex_unlock(&xprt_info->rx_lock_lhb2);
-		flush_workqueue(xprt_info->workqueue);
-		destroy_workqueue(xprt_info->workqueue);
+		kthread_flush_worker(&xprt_info->kworker);
+		kthread_stop(xprt_info->task);
+		xprt_info->task = NULL;
 		mutex_lock(&xprt_info->rx_lock_lhb2);
 		list_for_each_entry_safe(pkt, temp_pkt,
 					 &xprt_info->pkt_list, list) {
@@ -4288,7 +4298,7 @@
 		}
 	}
 	mutex_unlock(&xprt_info->rx_lock_lhb2);
-	queue_work(xprt_info->workqueue, &xprt_info->read_data);
+	kthread_queue_work(&xprt_info->kworker, &xprt_info->read_data);
 }
 
 /**
diff --git a/net/ipc_router/ipc_router_fifo_xprt.c b/net/ipc_router/ipc_router_fifo_xprt.c
new file mode 100644
index 0000000..c90534d
--- /dev/null
+++ b/net/ipc_router/ipc_router_fifo_xprt.c
@@ -0,0 +1,500 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/ipc_router_xprt.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/sched.h>
+#include <microvisor/microvisor.h>
+
+#define MODULE_NAME "ipc_router_fifo_xprt"
+#define XPRT_NAME_LEN 32
+
+#define FIFO_MAGIC_KEY 0x24495043 /* "$IPC" */
+#define FIFO_SIZE 0x4000
+#define FIFO_0_START 0x1000
+#define FIFO_1_START (FIFO_0_START + FIFO_SIZE)
+#define FIFO_MAGIC_IDX 0x0
+#define TAIL_0_IDX 0x1
+#define HEAD_0_IDX 0x2
+#define TAIL_1_IDX 0x3
+#define HEAD_1_IDX 0x4
+
+struct msm_ipc_pipe {
+	__le32 *tail;
+	__le32 *head;
+
+	void *fifo;
+	size_t length;
+};
+
+/**
+ * ipcr_fifo_xprt - IPC Router's FIFO XPRT structure
+ * @xprt: IPC Router XPRT structure to contain XPRT specific info.
+ * @tx_pipe: TX FIFO specific info.
+ * @rx_pipe: RX FIFO specific info.
+ * @fifo_xprt_wq: Workqueue to queue read & other XPRT related works.
+ * @in_pkt: Pointer to any partially read packet.
+ * @read_work: Read Work to perform read operation from SMD.
+ * @sft_close_complete: Variable to indicate completion of SSR handling
+ *                      by IPC Router.
+ * @xprt_version: IPC Router header version supported by this XPRT.
+ * @driver: Platform drivers register by this XPRT.
+ * @xprt_name: Name of the XPRT to be registered with IPC Router.
+ */
+struct ipcr_fifo_xprt {
+	struct msm_ipc_router_xprt xprt;
+	struct msm_ipc_pipe tx_pipe;
+	struct msm_ipc_pipe rx_pipe;
+	struct workqueue_struct *xprt_wq;
+	struct rr_packet *in_pkt;
+	struct delayed_work read_work;
+	struct completion sft_close_complete;
+	unsigned int xprt_version;
+	struct platform_driver driver;
+	char xprt_name[XPRT_NAME_LEN];
+	void *fifo_base;
+	size_t fifo_size;
+	int tx_fifo_idx;
+	okl4_kcap_t kcap;
+};
+
+static void xprt_read_data(struct work_struct *work);
+static void ipcr_fifo_raise_virq(struct ipcr_fifo_xprt *xprtp);
+
+static size_t fifo_rx_avail(struct msm_ipc_pipe *pipe)
+{
+	u32 head;
+	u32 tail;
+
+	head = le32_to_cpu(*pipe->head);
+	tail = le32_to_cpu(*pipe->tail);
+
+	if (head < tail)
+		return pipe->length - tail + head;
+
+	return head - tail;
+}
+
+static void fifo_rx_peak(struct msm_ipc_pipe *pipe,
+			 void *data, unsigned int offset, size_t count)
+{
+	size_t len;
+	u32 tail;
+
+	tail = le32_to_cpu(*pipe->tail);
+	tail += offset;
+	if (tail >= pipe->length)
+		tail -= pipe->length;
+
+	len = min_t(size_t, count, pipe->length - tail);
+	if (len)
+		memcpy_fromio(data, pipe->fifo + tail, len);
+
+	if (len != count)
+		memcpy_fromio(data + len, pipe->fifo, (count - len));
+}
+
+static void fifo_rx_advance(struct msm_ipc_pipe *pipe, size_t count)
+{
+	u32 tail;
+
+	tail = le32_to_cpu(*pipe->tail);
+
+	tail += count;
+	if (tail > pipe->length)
+		tail -= pipe->length;
+
+	*pipe->tail = cpu_to_le32(tail);
+}
+
+static size_t fifo_tx_avail(struct msm_ipc_pipe *pipe)
+{
+	u32 head;
+	u32 tail;
+	u32 avail;
+
+	 head = le32_to_cpu(*pipe->head);
+	 tail = le32_to_cpu(*pipe->tail);
+
+	if (tail <= head)
+		avail = pipe->length - head + tail;
+	else
+		avail = tail - head;
+
+	return avail;
+}
+
+static void fifo_tx_write(struct msm_ipc_pipe *pipe,
+			  const void *data, size_t count)
+{
+	size_t len;
+	u32 head;
+
+	head = le32_to_cpu(*pipe->head);
+
+	len = min_t(size_t, count, pipe->length - head);
+	if (len)
+		memcpy_toio(pipe->fifo + head, data, len);
+
+	if (len != count)
+		memcpy_toio(pipe->fifo, data + len, count - len);
+
+	head += count;
+	if (head >= pipe->length)
+		head -= pipe->length;
+
+	/* Ensure ordering of fifo and head update */
+	wmb();
+
+	*pipe->head = cpu_to_le32(head);
+}
+
+/**
+ * set_xprt_version() - Set IPC Router header version in the transport
+ * @xprt: Reference to the transport structure.
+ * @version: The version to be set in transport.
+ */
+static void set_xprt_version(struct msm_ipc_router_xprt *xprt,
+			     unsigned int version)
+{
+	struct ipcr_fifo_xprt *xprtp;
+
+	if (!xprt)
+		return;
+	xprtp = container_of(xprt, struct ipcr_fifo_xprt, xprt);
+	xprtp->xprt_version = version;
+}
+
+static int get_xprt_version(struct msm_ipc_router_xprt *xprt)
+{
+	struct ipcr_fifo_xprt *xprtp;
+
+	if (!xprt)
+		return -EINVAL;
+	xprtp = container_of(xprt, struct ipcr_fifo_xprt, xprt);
+	return (int)xprtp->xprt_version;
+}
+
+static int get_xprt_option(struct msm_ipc_router_xprt *xprt)
+{
+	/* fragmented data is NOT supported */
+	return 0;
+}
+
+static int xprt_close(struct msm_ipc_router_xprt *xprt)
+{
+	return 0;
+}
+
+static void xprt_sft_close_done(struct msm_ipc_router_xprt *xprt)
+{
+	struct ipcr_fifo_xprt *xprtp;
+
+	if (!xprt)
+		return;
+
+	xprtp = container_of(xprt, struct ipcr_fifo_xprt, xprt);
+	complete_all(&xprtp->sft_close_complete);
+}
+
+static int xprt_write(void *data, uint32_t len,
+		      struct msm_ipc_router_xprt *xprt)
+{
+	struct rr_packet *pkt = (struct rr_packet *)data;
+	struct sk_buff *skb;
+	struct ipcr_fifo_xprt *xprtp;
+
+	xprtp = container_of(xprt, struct ipcr_fifo_xprt, xprt);
+
+	if (!pkt)
+		return -EINVAL;
+
+	if (!len || pkt->length != len)
+		return -EINVAL;
+
+	/* TODO: FIFO write : check if we can write full packet at one shot */
+	if (skb_queue_len(pkt->pkt_fragment_q) != 1) {
+		pr_err("IPC router core is given fragmented data\n");
+		return -EINVAL;
+	}
+	if (fifo_tx_avail(&xprtp->tx_pipe) < len) {
+		pr_err("No Space in FIFO\n");
+		return -EAGAIN;
+	}
+
+	skb_queue_walk(pkt->pkt_fragment_q, skb) {
+		fifo_tx_write(&xprtp->tx_pipe, skb->data, skb->len);
+	}
+
+	ipcr_fifo_raise_virq(xprtp);
+
+	return len;
+}
+
+static void xprt_read_data(struct work_struct *work)
+{
+	void *data;
+	size_t hdr_len;
+	size_t rx_avail;
+	size_t pkt_len;
+	struct rr_header_v1 hdr;
+	struct sk_buff *ipc_rtr_pkt;
+	struct ipcr_fifo_xprt *xprtp;
+	struct delayed_work *rwork = to_delayed_work(work);
+
+	xprtp = container_of(rwork, struct ipcr_fifo_xprt, read_work);
+
+	hdr_len = sizeof(struct rr_header_v1);
+	while (1) {
+		rx_avail = fifo_rx_avail(&xprtp->rx_pipe);
+		if (!rx_avail)
+			break;
+
+		fifo_rx_peak(&xprtp->rx_pipe, &hdr, 0, hdr_len);
+		pkt_len = ipc_router_peek_pkt_size((char *)&hdr);
+
+		if (pkt_len < 0) {
+			pr_err("%s invalid pkt_len %zu\n", __func__, pkt_len);
+			break;
+		}
+		if (!xprtp->in_pkt) {
+			xprtp->in_pkt = create_pkt(NULL);
+			if (!xprtp->in_pkt)
+				break;
+		}
+		ipc_rtr_pkt = alloc_skb(pkt_len, GFP_KERNEL);
+		if (!ipc_rtr_pkt) {
+			release_pkt(xprtp->in_pkt);
+			xprtp->in_pkt = NULL;
+			break;
+		}
+		data = skb_put(ipc_rtr_pkt, pkt_len);
+		do {
+			rx_avail = fifo_rx_avail(&xprtp->rx_pipe);
+			if (rx_avail >= pkt_len) {
+				fifo_rx_peak(&xprtp->rx_pipe, data, 0, pkt_len);
+				fifo_rx_advance(&xprtp->rx_pipe, pkt_len);
+				break;
+			}
+			pr_debug("%s wait for FULL PKT [avail: len][%zu:%zu]\n",
+				 __func__, rx_avail, pkt_len);
+			/* wait for complete packet written into FIFO */
+			msleep(20);
+		} while (1);
+
+		skb_queue_tail(xprtp->in_pkt->pkt_fragment_q, ipc_rtr_pkt);
+		xprtp->in_pkt->length = pkt_len;
+		msm_ipc_router_xprt_notify(&xprtp->xprt,
+					   IPC_ROUTER_XPRT_EVENT_DATA,
+					   (void *)xprtp->in_pkt);
+		release_pkt(xprtp->in_pkt);
+		xprtp->in_pkt = NULL;
+	}
+}
+
+static void ipcr_fifo_raise_virq(struct ipcr_fifo_xprt *xprtp)
+{
+	okl4_error_t err;
+	unsigned long payload = 0xffff;
+
+	err = _okl4_sys_vinterrupt_raise(xprtp->kcap, payload);
+}
+
+static irqreturn_t ipcr_fifo_virq_handler(int irq, void *dev_id)
+{
+	struct ipcr_fifo_xprt *xprtp = dev_id;
+
+	queue_delayed_work(xprtp->xprt_wq, &xprtp->read_work, 0);
+	return IRQ_HANDLED;
+}
+
+/**
+ * ipcr_fifo_config_init() - init FIFO xprt configs
+ *
+ * @return: 0 on success, standard Linux error codes on error.
+ *
+ * This function is called to initialize the FIFO XPRT pointer with
+ * the FIFO XPRT configurations either from device tree or static arrays.
+ */
+static int ipcr_fifo_config_init(struct ipcr_fifo_xprt *xprtp)
+{
+	__le32 *descs;
+
+	descs = xprtp->fifo_base;
+	descs[FIFO_MAGIC_IDX] = FIFO_MAGIC_KEY;
+
+	if (xprtp->tx_fifo_idx) {
+		xprtp->tx_pipe.tail = &descs[TAIL_0_IDX];
+		xprtp->tx_pipe.head = &descs[HEAD_0_IDX];
+		xprtp->tx_pipe.fifo = xprtp->fifo_base + FIFO_0_START;
+		xprtp->tx_pipe.length = FIFO_SIZE;
+
+		xprtp->rx_pipe.tail = &descs[TAIL_1_IDX];
+		xprtp->rx_pipe.head = &descs[HEAD_1_IDX];
+		xprtp->rx_pipe.fifo = xprtp->fifo_base + FIFO_1_START;
+		xprtp->rx_pipe.length = FIFO_SIZE;
+	} else {
+		xprtp->tx_pipe.tail = &descs[TAIL_1_IDX];
+		xprtp->tx_pipe.head = &descs[HEAD_1_IDX];
+		xprtp->tx_pipe.fifo = xprtp->fifo_base + FIFO_1_START;
+		xprtp->tx_pipe.length = FIFO_SIZE;
+
+		xprtp->rx_pipe.tail = &descs[TAIL_0_IDX];
+		xprtp->rx_pipe.head = &descs[HEAD_0_IDX];
+		xprtp->rx_pipe.fifo = xprtp->fifo_base + FIFO_0_START;
+		xprtp->rx_pipe.length = FIFO_SIZE;
+	}
+
+	/* Reset respective index */
+	*xprtp->tx_pipe.head = 0;
+	*xprtp->rx_pipe.tail = 0;
+
+	xprtp->xprt.link_id = 1;
+	xprtp->xprt_version = 1;
+
+	strlcpy(xprtp->xprt_name, "IPCR_FIFO_XPRT", XPRT_NAME_LEN);
+	xprtp->xprt.name = xprtp->xprt_name;
+
+	xprtp->xprt.set_version = set_xprt_version;
+	xprtp->xprt.get_version = get_xprt_version;
+	xprtp->xprt.get_option = get_xprt_option;
+	xprtp->xprt.read_avail = NULL;
+	xprtp->xprt.read = NULL;
+	xprtp->xprt.write_avail = NULL;
+	xprtp->xprt.write = xprt_write;
+	xprtp->xprt.close = xprt_close;
+	xprtp->xprt.sft_close_done = xprt_sft_close_done;
+	xprtp->xprt.priv = NULL;
+
+	xprtp->in_pkt = NULL;
+	xprtp->xprt_wq = create_singlethread_workqueue(xprtp->xprt_name);
+	if (!xprtp->xprt_wq)
+		return -EFAULT;
+
+	INIT_DELAYED_WORK(&xprtp->read_work, xprt_read_data);
+
+	msm_ipc_router_xprt_notify(&xprtp->xprt,
+				   IPC_ROUTER_XPRT_EVENT_OPEN,
+				   NULL);
+
+	if (fifo_rx_avail(&xprtp->rx_pipe))
+		queue_delayed_work(xprtp->xprt_wq, &xprtp->read_work, 0);
+
+	return 0;
+}
+
+/**
+ * ipcr_fifo_xprt_probe() - Probe an FIFO xprt
+ *
+ * @pdev: Platform device corresponding to FIFO xprt.
+ *
+ * @return: 0 on success, standard Linux error codes on error.
+ *
+ * This function is called when the underlying device tree driver registers
+ * a platform device, mapped to an FIFO transport.
+ */
+static int ipcr_fifo_xprt_probe(struct platform_device *pdev)
+{
+	int irq;
+	int ret;
+	struct resource *r;
+	struct device *parent;
+	struct ipcr_fifo_xprt *xprtp;
+	struct device_node *ipc_irq_np;
+	struct device_node *ipc_shm_np;
+	struct platform_device *ipc_shm_dev;
+
+	xprtp = devm_kzalloc(&pdev->dev, sizeof(*xprtp), GFP_KERNEL);
+	if (IS_ERR_OR_NULL(xprtp))
+		return -ENOMEM;
+
+	parent = &pdev->dev;
+	ipc_irq_np = parent->of_node;
+
+	irq = platform_get_irq(pdev, 0);
+
+	if (irq >= 0) {
+		ret = devm_request_irq(parent, irq, ipcr_fifo_virq_handler,
+				       IRQF_TRIGGER_RISING, dev_name(parent),
+				       xprtp);
+		if (ret < 0)
+			return -ENODEV;
+	}
+
+	/* this kcap is required to raise VIRQ */
+	ret = of_property_read_u32(ipc_irq_np, "reg", &xprtp->kcap);
+	if (ret < 0)
+		return -ENODEV;
+
+	ipc_shm_np = of_parse_phandle(ipc_irq_np, "qcom,ipc-shm", 0);
+	if (!ipc_shm_np)
+		return -ENODEV;
+
+	ipc_shm_dev = of_find_device_by_node(ipc_shm_np);
+	if (!ipc_shm_dev)
+		return -ENODEV;
+
+	r = platform_get_resource(ipc_shm_dev, IORESOURCE_MEM, 0);
+	if (!r) {
+		pr_err("%s failed to get shared FIFO\n", __func__);
+		return -ENODEV;
+	}
+
+	xprtp->tx_fifo_idx = of_property_read_bool(ipc_shm_np,
+						   "qcom,tx-is-first");
+
+	xprtp->fifo_size = resource_size(r);
+	xprtp->fifo_base = devm_ioremap_nocache(&pdev->dev, r->start,
+						resource_size(r));
+	if (!xprtp->fifo_base) {
+		pr_err("%s ioreamp_nocache() failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	ret = ipcr_fifo_config_init(xprtp);
+	if (ret) {
+		IPC_RTR_ERR("%s init failed ret[%d]\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id ipcr_fifo_xprt_match_table[] = {
+	{ .compatible = "qcom,ipcr-fifo-xprt" },
+	{},
+};
+
+static struct platform_driver ipcr_fifo_xprt_driver = {
+	.probe = ipcr_fifo_xprt_probe,
+	.driver = {
+		.name = MODULE_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = ipcr_fifo_xprt_match_table,
+	 },
+};
+
+static int __init ipcr_fifo_xprt_init(void)
+{
+	int rc;
+
+	rc = platform_driver_register(&ipcr_fifo_xprt_driver);
+	if (rc) {
+		IPC_RTR_ERR("%s: driver register failed %d\n", __func__, rc);
+		return rc;
+	}
+
+	return 0;
+}
+
+module_init(ipcr_fifo_xprt_init);
+MODULE_DESCRIPTION("IPC Router FIFO XPRT");
+MODULE_LICENSE("GPL v2");
diff --git a/net/ipc_router/ipc_router_socket.c b/net/ipc_router/ipc_router_socket.c
index a758a09..4e53861 100644
--- a/net/ipc_router/ipc_router_socket.c
+++ b/net/ipc_router/ipc_router_socket.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
@@ -146,6 +146,7 @@
 			return -EINVAL;
 		}
 		ctl_msg = (union rr_control_msg *)(temp->data);
+		memset(addr, 0x0, sizeof(*addr));
 		addr->family = AF_MSM_IPC;
 		addr->address.addrtype = MSM_IPC_ADDR_ID;
 		addr->address.addr.port_addr.node_id = ctl_msg->cli.node_id;
@@ -154,6 +155,7 @@
 		return offset;
 	}
 	if (addr && (hdr->type == IPC_ROUTER_CTRL_CMD_DATA)) {
+		memset(addr, 0x0, sizeof(*addr));
 		addr->family = AF_MSM_IPC;
 		addr->address.addrtype = MSM_IPC_ADDR_ID;
 		addr->address.addr.port_addr.node_id = hdr->src_node_id;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index c88874f..0a67d80 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -949,6 +949,7 @@
 	nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
 
 	list_del_rcu(&wdev->list);
+	synchronize_rcu();
 	rdev->devlist_generation++;
 
 	switch (wdev->iftype) {
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index f900f5c..d82f8b4 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -594,9 +594,9 @@
 
 country JP: DFS-JP
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (20), AUTO-BW, NO-OUTDOOR
-	(5250 - 5330 @ 80), (20), DFS, AUTO-BW, NO-OUTDOOR
-	(5490 - 5710 @ 160), (20), DFS
+	(5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR
+	(5250 - 5330 @ 80), (26), DFS, AUTO-BW, NO-OUTDOOR
+	(5490 - 5710 @ 160), (26), DFS
 	# 60 gHz band channels 1-4
 	(57240 - 65880 @ 2160), (40)
 
@@ -622,8 +622,8 @@
 country KR: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
 	(5170 - 5250 @ 80), (20), AUTO-BW
-	(5250 - 5330 @ 80), (20), DFS, AUTO-BW
-	(5490 - 5730 @ 160), (30), DFS
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5490 - 5710 @ 160), (30), DFS
 	(5735 - 5835 @ 80), (30)
 	# 60 GHz band channels 1-4,
 	# ref: http://www.law.go.kr/%ED%96%89%EC%A0%95%EA%B7%9C%EC%B9%99/%EB%AC%B4%EC%84%A0%EC%84%A4%EB%B9%84%EA%B7%9C%EC%B9%99
@@ -896,9 +896,10 @@
 
 country PA:
 	(2402 - 2472 @ 40), (36)
-	(5170 - 5250 @ 80), (23), AUT0-BW
-	(5250 - 5330 @ 80), (30), AUTO-BW
-	(5735 - 5835 @ 80), (36)
+	(5170 - 5250 @ 80), (30), AUT0-BW
+	(5250 - 5330 @ 80), (24), AUTO-BW
+	(5490 - 5730 @ 160), (24),
+	(5735 - 5835 @ 80), (30)
 
 country PE: DFS-FCC
 	(2402 - 2482 @ 40), (20)
@@ -993,7 +994,7 @@
 	(2402 - 2482 @ 40), (20)
 	(5170 - 5250 @ 80), (23), AUTO-BW
 	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
-	(5490 - 5730 @ 80), (20), DFS
+	(5490 - 5730 @ 160), (20), DFS
 	(5735 - 5875 @ 80), (20)
 
 country RE: DFS-ETSI
@@ -1167,10 +1168,10 @@
 # disputable definitions there.
 country UA: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5170 - 5250 @ 80), (20), AUTO-BW
-	(5250 - 5330 @ 80), (20), DFS, AUTO-BW
-	(5490 - 5670 @ 160), (20), DFS
-	(5735 - 5835 @ 80), (20)
+	(5170 - 5250 @ 80), (23), AUTO-BW
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5490 - 5710 @ 160), (24), DFS
+	(5735 - 5835 @ 80), (24)
 	# 60 gHz band channels 1-4, ref: Etsi En 302 567
 	(57240 - 65880 @ 2160), (20)
 
diff --git a/security/pfe/pfk_ice.c b/security/pfe/pfk_ice.c
index 16ed516..a86042c 100644
--- a/security/pfe/pfk_ice.c
+++ b/security/pfe/pfk_ice.c
@@ -121,7 +121,7 @@
 		goto out;
 	}
 
-	ret = scm_call2(smc_id, &desc);
+	ret = scm_call2_noretry(smc_id, &desc);
 
 	if (ret) {
 		pr_err("%s: Set Key Error: %d\n", __func__, ret);
@@ -134,13 +134,14 @@
 		smc_id = TZ_ES_INVALIDATE_ICE_KEY_ID;
 		desc.arginfo = TZ_ES_INVALIDATE_ICE_KEY_PARAM_ID;
 		desc.args[0] = index;
-		ret1 = scm_call2(smc_id, &desc);
+		ret1 = scm_call2_noretry(smc_id, &desc);
 		if (ret1)
 			pr_err("%s: Invalidate Key Error: %d\n", __func__,
 					ret1);
-		goto out;
 	}
-	ret = qcom_ice_setup_ice_hw((const char *)s_type, false);
+	ret1 = qcom_ice_setup_ice_hw((const char *)s_type, false);
+	if (ret1)
+		pr_err("%s: Error %d disabling clocks\n", __func__, ret1);
 
 out:
 	return ret;
@@ -175,7 +176,7 @@
 		return ret;
 	}
 
-	ret = scm_call2(smc_id, &desc);
+	ret = scm_call2_noretry(smc_id, &desc);
 
 	if (ret) {
 		pr_err("%s: Error: 0x%x\n", __func__, ret);
diff --git a/sound/usb/usb_audio_qmi_svc.c b/sound/usb/usb_audio_qmi_svc.c
index ce1f0ad..fe29aed 100644
--- a/sound/usb/usb_audio_qmi_svc.c
+++ b/sound/usb/usb_audio_qmi_svc.c
@@ -110,8 +110,8 @@
 	unsigned long curr_xfer_buf_iova;
 	/* bit fields representing pcm card enabled */
 	unsigned long card_slot;
-	/* cache event ring phys addr */
-	u64 er_phys_addr;
+	/* indicate event ring mapped or not */
+	bool er_mapped;
 };
 
 static struct uaudio_qmi_dev *uaudio_qdev;
@@ -295,7 +295,7 @@
 	case MEM_EVENT_RING:
 		va = IOVA_BASE;
 		/* er already mapped */
-		if (uaudio_qdev->er_phys_addr == pa)
+		if (uaudio_qdev->er_mapped)
 			map = false;
 		break;
 	case MEM_XFER_RING:
@@ -407,8 +407,8 @@
 
 	switch (mtype) {
 	case MEM_EVENT_RING:
-		if (uaudio_qdev->er_phys_addr)
-			uaudio_qdev->er_phys_addr = 0;
+		if (uaudio_qdev->er_mapped)
+			uaudio_qdev->er_mapped = false;
 		else
 			unmap = false;
 		break;
@@ -637,7 +637,7 @@
 						uaudio_qdev->sid);
 	resp->xhci_mem_info.evt_ring.pa = dma;
 	resp->xhci_mem_info.evt_ring.size = PAGE_SIZE;
-	uaudio_qdev->er_phys_addr = xhci_pa;
+	uaudio_qdev->er_mapped = true;
 
 	resp->speed_info = get_speed_info(subs->dev->speed);
 	if (resp->speed_info == USB_AUDIO_DEVICE_SPEED_INVALID_V01)