Merge "msm: vidc: modify v4l2 mbaff flag to avoid conflict"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index 561a181..bacaeb6 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -366,3 +366,4 @@
 compatible = "qcom,sdxpoorwills-rumi"
 compatible = "qcom,sdxpoorwills-mtp"
 compatible = "qcom,sdxpoorwills-cdp"
+compatible = "qcom,mdm9607-ttp"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_ion.txt b/Documentation/devicetree/bindings/arm/msm/msm_ion.txt
index 6527675..d3325e2 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_ion.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_ion.txt
@@ -22,6 +22,7 @@
     - "SYSTEM"
     - "SYSTEM_CONTIG"
     - "CARVEOUT"
+    - "SECURE_CARVEOUT"
     - "CHUNK"
     - "CP"
     - "DMA"
@@ -41,6 +42,7 @@
   Will set to a reasonable default value (e.g. the maximum heap size)
   if this option is not set.
 
+
 Example:
 	qcom,ion {
                  compatible = "qcom,msm-ion";
@@ -70,3 +72,32 @@
                          qcom,ion-heap-type = "CARVEOUT";
                  };
 	};
+
+"SECURE_CARVEOUT"
+
+This heap type is expected to contain multiple child nodes. Each child node
+shall contain the following required properties:
+
+- memory-regions:
+Refer to Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
+
+- token:
+A u32 containing the set of secure domains which will be able to access the
+memory-region.
+
+Example:
+qcom,ion {
+	compatible = "qcom,msm-ion";
+	#address-cells = <1>;
+	#size-cells = <0>;
+
+	qcom,ion-heap@14 {
+		reg = <14>;
+		qcom,ion-heap-type = "SECURE_CARVEOUT";
+
+		node1 {
+			memory-regions = <&cp_region>;
+			token = <ION_FLAG_CP_TOUCH>;
+		};
+	};
+};
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_watchdog.txt b/Documentation/devicetree/bindings/arm/msm/msm_watchdog.txt
index 53ad68e..cf13d34 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_watchdog.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_watchdog.txt
@@ -33,6 +33,7 @@
 - qcom,ipi-ping : (boolean) send keep alive ping to other cpus if present
 - qcom,wakeup-enable : (boolean) enable non secure watchdog to freeze / unfreeze
                         automatically across suspend / resume path.
+- qcom,scandump-size : size of scan dump memory region.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-log.txt b/Documentation/devicetree/bindings/arm/msm/rpm-log.txt
new file mode 100644
index 0000000..298dd18
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-log.txt
@@ -0,0 +1,61 @@
+* RPM Log
+
+RPM maintains Ulog in the RPM RAM. A device tree node is added
+that will hold the address of the RPM RAM region from where
+Ulog is read. The physical address from the RPM RAM region
+contains a header where various parameters to read the log are
+defined. These parameter's offsets in the header are also stored
+as a part of the device tree node.
+
+The required properties for rpm-log are:
+
+- compatible: "qcom,rpm-log"
+- reg: Specifies the base physical address and the size of the RPM
+	registers from where ulog is read.
+	Second register(optional) specifies the offset of the rpm
+	log start address pointer. If the second register is available,
+	the offset value read is added to the first register address
+	to read the ulog message.
+- qcom,rpm-addr-phys: RPM reads physical address of the RPM RAM region
+		differently when compared to Apps. Physical address of
+		the RPM RAM region is at an offset when seen from Apps.
+		This property specifies the offset which will get added
+		to the physical address of RPM RAM to make it
+		accessible to the Apps.
+- qcom,offset-version: Offset from the start of the phys_addr_base where version
+			information is stored.
+- qcom,offset-page-buffer-addr: Offset from the start of the phys_addr_base
+				where raw log start address is stored. Raw log
+				start address is the start of raw log in the
+				RPM address space as it should be seen from rpm.
+- qcom,offset-log-len: Offset from the start of the phy_addr_base where log
+			length is stored.
+- qcom,offset-log-len-mask: Offset from the start of the phy_addr_base where
+				log length mask is stored.
+- qcom,offset-page-indices: Offset from the start of the phy_addr_base where
+				index to the writer is stored.
+
+Example 1:
+qcom,rpm-log@fc19dc00 {
+	compatible = "qcom,rpm-log";
+	reg = <0xfc19dc00 0x2000>;
+	qcom,offset-rpm-addr = <0xfc000000>;
+	qcom,offset-version = <4>;
+	qcom,offset-page-buffer-addr = <36>;
+	qcom,offset-log-len = <40>;
+	qcom,offset-log-len-mask = <44>;
+	qcom,offset-page-indices = <56>;
+};
+
+Example 2:
+qcom,rpm-log@fc000000 {
+	compatible = "qcom,rpm-log";
+	reg = <0xfc000000 0x2000>,
+		<0xfc190018 0x4>;
+	qcom,offset-rpm-addr = <0xfc000000>;
+	qcom,offset-version = <4>;
+	qcom,offset-page-buffer-addr = <36>;
+	qcom,offset-log-len = <40>;
+	qcom,offset-log-len-mask = <44>;
+	qcom,offset-page-indices = <56>;
+};
diff --git a/Documentation/devicetree/bindings/arm/msm/rpm-rbcpr-stats.txt b/Documentation/devicetree/bindings/arm/msm/rpm-rbcpr-stats.txt
new file mode 100644
index 0000000..9b69037
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/rpm-rbcpr-stats.txt
@@ -0,0 +1,26 @@
+* RPM RBCPR
+
+The RBCPR(Rapid Bridge Core Power Reduction) is  module on RPM that controls
+the voltage level on the chip based on feedback received through various
+sensors on the chip that allow compensation of the chip process variation,
+temperature etc.
+RPM maintains RBCPR (Rapid Bridge Core Power Reduction) related stats in
+data memory. This module allows users to read those stats.
+
+The required properties for rpm-stats are:
+
+- compatible: "qcom,rpmrbcpr-stats"
+- reg: Pointer to the start of the RPM Data Memory. The size of the memory
+		is inclusive of the entire RPM data memory.
+- qcom,start_offset: The offset at which the RBCPR stats are maintained. The
+			driver module reads this parameter to get another offset
+			that contain the rbcpr stats.
+
+
+Example:
+
+qcom,rpm-rbcpr-stats@fc000000 {
+	compatible = "qcom,rpmrbcpr-stats";
+	reg = <0xfc000000 0x1a0000>;
+	qcom,start-offset = <0x190010>;
+};
diff --git a/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt b/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt
index 7b89497..49233d4 100644
--- a/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt
+++ b/Documentation/devicetree/bindings/bluetooth/bluetooth_power.txt
@@ -6,6 +6,7 @@
   - compatible: Should be set to one of the following:
 	qca,ar3002
 	qca,qca6174
+	qca,qca9379
 	qca,wcn3990
   - qca,bt-reset-gpio: GPIO pin to bring BT Controller out of reset
 
diff --git a/Documentation/devicetree/bindings/bt-fm/fm.txt b/Documentation/devicetree/bindings/bt-fm/fm.txt
new file mode 100644
index 0000000..ed73e5d2
--- /dev/null
+++ b/Documentation/devicetree/bindings/bt-fm/fm.txt
@@ -0,0 +1,29 @@
+Qti radio iris device
+
+-FM RX playback with no RDS
+
+   FM samples is filtered by external RF chips at baseband, then send to Riva-FM core through serial link.
+   FM signal is demodulated then audio L/R samples are stored inside memory.
+   FM Rx received samples data is connected to external audio codec.
+
+-Audio playback to FM TX
+
+  Used to play audio source  to FM TX.
+  FM TX module will read the audio samples from memory then modulated samples will be send through serial interface to external RF chip.
+
+-RX playback with RDS
+
+  FM Rx receive audio data along with RDS.
+
+-FM TX with RDS
+
+  Used to send RDS messages to external FM receiver.
+
+Required Properties:
+- compatible: "qcom,iris_fm"
+
+Example:
+        qcom,iris-fm {
+                compatible = "qcom,iris_fm";
+        };
+
diff --git a/Documentation/devicetree/bindings/cnss/cnss-wlan.txt b/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
index 9dff08d..ea3afc7 100644
--- a/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
+++ b/Documentation/devicetree/bindings/cnss/cnss-wlan.txt
@@ -36,6 +36,8 @@
                               always on regulator in VDDmin.
   - vdd-wlan-core-supply: phandle to the 1.3V CORE regulator for QCA6174
   - vdd-wlan-sp2t-supply: phandle to the 2.7V SP2T regulator for QCA6174
+  - qcom,smmu-s1-enable: Boolean property to decide whether to enable SMMU
+                         S1 stage or not
   - qcom,wlan-smmu-iova-address: I/O virtual address range as <start length>
                                  format to be used for allocations associated
                                  between WLAN/PCIe and SMMU
diff --git a/Documentation/devicetree/bindings/display/bridge/lt9611.txt b/Documentation/devicetree/bindings/display/bridge/lt9611.txt
index 61688b5..419be2d 100644
--- a/Documentation/devicetree/bindings/display/bridge/lt9611.txt
+++ b/Documentation/devicetree/bindings/display/bridge/lt9611.txt
@@ -8,7 +8,7 @@
 	- lt,reset-gpio				Main reset gpio mapping
 
 
-	Optional properties:
+Optional properties:
 	- lt,hdmi-ps-gpio:			gpio mapping for HDMI PS
 	- lt,hdmi-en-gpio:			gpio mapping for HDMI EN
 
@@ -29,6 +29,7 @@
 	-- lt,supply-post-off-sleep: time to sleep (ms) after turning off
 
 	- lt,non-pluggable: Boolean to indicate if display is non pluggable.
+	- lt,preferred-mode: Preferred display mode.
 	- lt,customize-modes: Customized modes when it's non-pluggable display.
 	e.g. lt,customize-mode-id@0
 	-- lt,mode-h-active: Horizontal active pixels for this mode.
@@ -66,6 +67,8 @@
 		lt,reset-gpio = <&tlmm 134 0x0>;
 		lt,hdmi-ps-gpio = <&tlmm 136 0x0>;
 		lt,hdmi-en-gpio = <&tlmm 137 0x0>;
+		lt,non-pluggable;
+		lt,preferred-mode = "1920x1080";
 
 		vcc-supply = <&pm660l_l6>;
 		vdd-supply = <&pm660_l11>;
diff --git a/Documentation/devicetree/bindings/display/msm/sde.txt b/Documentation/devicetree/bindings/display/msm/sde.txt
index 4b4c274..0589165 100644
--- a/Documentation/devicetree/bindings/display/msm/sde.txt
+++ b/Documentation/devicetree/bindings/display/msm/sde.txt
@@ -78,6 +78,8 @@
 Optional properties:
 - clock-rate:		List of clock rates in Hz.
 - clock-max-rate:	List of maximum clock rate in Hz that this device supports.
+- connectors:		Specifies the connector components.
+- bridges:		Specifies the bridge components.
 - qcom,platform-supply-entries:	A node that lists the elements of the supply. There
 				can be more than one instance of this binding,
 				in which case the entry would be appended with
diff --git a/Documentation/devicetree/bindings/input/qpnp-power-on.txt b/Documentation/devicetree/bindings/input/qpnp-power-on.txt
index 33d0236..0f1d9e1 100644
--- a/Documentation/devicetree/bindings/input/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/input/qpnp-power-on.txt
@@ -112,6 +112,9 @@
 				trigger during system shutdown case.
 - qcom,ps-hold-hard-reset-disable	Boolean property to disable PS_HOLD
 				POFF trigger during system hard reset case.
+- qcom,use-legacy-hard-reset-offset	Boolean property to support legacy
+				hard-reset offset of the PON_RB_SPARE register for
+				some (PON gen2) platforms.
 
 All the below properties are in the sub-node section (properties of the child
 node).
diff --git a/Documentation/devicetree/bindings/input/touchscreen/focaltech_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/focaltech_ts.txt
new file mode 100644
index 0000000..0174e3d
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/focaltech_ts.txt
@@ -0,0 +1,54 @@
+FocalTech touch controller
+
+The focaltech controller is connected to host processor
+via i2c. The controller generates interrupts when the
+user touches the panel. The host controller is expected
+to read the touch coordinates over i2c and pass the coordinates
+to the rest of the system.
+
+Required properties:
+
+ - compatible		: should be "focaltech,fts".
+ - reg				: i2c slave address of the device.
+ - interrupt-parent	: parent of interrupt.
+ - interrupts		: touch sample interrupt to indicate presense or release
+				of fingers on the panel.
+ - vdd-supply		: Power supply needed to power up the device.
+ - vcc-i2c-supply	: Power source required to power up i2c bus.
+ - focaltech,irq-gpio	: irq gpio which is to provide interrupts to host,
+				same as "interrupts" node. It will also
+				contain active low or active high information.
+ - focaltech,reset-gpio	: reset gpio to control the reset of chip.
+ - focaltech,display-coords : display coordinates in pixels. It is a four
+				tuple consisting of min x, min y, max x and
+				max y values
+
+Optional properties:
+ - focaltech,max-touch-number	: maximnum number of touch points supported.
+ - focaltech,have-key 		: specify whether virtual keys are present.
+ - focaltech,key-number 	: number of keys, maximum 3.
+ - focaltech,keys 			: array of key code.
+ - focaltech,key-y-coord 	: y coordinate for the keys.
+ - focaltech,key-x-coords	: array of x coordinates for the keys.
+ - focaltech,wakeup-gestures-en	: enable wakeup gestures.
+
+Example:
+	i2c@f9923000{
+		focaltech@38{
+			compatible = "focaltech,fts";
+			reg = <0x38>;
+			interrupt-parent = <&msmgpio>;
+			interrupts = <98 0x2008>;
+			vdd-supply = <&pm8110_l19>;
+			vcc_i2c-supply = <&pm8110_l14>;
+			focaltech,reset-gpio = <&msmgpio 16 0x00>;
+			focaltech,irq-gpio = <&msmgpio 98 0x2008>;
+			focaltech,display-coords = <0 0 480 800>;
+			focaltech,max-touch-number = <2>;
+			focaltech,have-key;
+			focaltech,key-number = <3>;
+			focaltech,keys = <139 142 140>;
+			focaltech,key-y-coord = <700>;
+			focaltech,key-x-coords = <80 240 400>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/pil/pil-blackghost.txt b/Documentation/devicetree/bindings/pil/pil-blackghost.txt
new file mode 100644
index 0000000..66cde5c
--- /dev/null
+++ b/Documentation/devicetree/bindings/pil/pil-blackghost.txt
@@ -0,0 +1,33 @@
+Qualcomm Technologies Inc Blackghost(BG) PIL driver:
+
+Blackghost(BG) PIL driver provide interface to load and boot Blackghost(BG)
+SOC. Blackghost(BG) SOC is an external SOC which communicate to MSM via
+SPI. The PIL driver loads firmware into memory and invoke secure app via
+qseecom to transfer and handshake the boot process. Once Blackghost(BG) SOC
+is booted it raises ready interrupt which is handled by BG PIL driver, and
+this event is informed to other MSM drivers, other remote subsystem via
+notifier framework. The PIL driver also handles interrupt for the BG SOC
+crash upon arrival of which it reset and initiates ramdump collection for BG
+SOC.
+
+Required properties:
+- compatible:			Must be "qcom,PIL-blackghost"
+- qcom,firmware-name:		Base name of the firmware image.
+- qcom,bg2ap-status-gpio:	GPIO used by the blackghost to indicate status to the apps.
+- qcom,bg2ap-errfatal-gpio:	GPIO used by the blackghost to indicate software error to the apps.
+- qcom,ap2bg-status-gpio:	GPIO used by the apps to indicate its status to blackghost.
+- qcom,ap2bg-errfatal-gpio:	GPIO used by the apps to indicate blackghost about apps reset.
+
+Example:
+
+	qcom,blackghost {
+		compatible = "qcom,pil-blackghost";
+		qcom,firmware-name = "bgelf";
+
+		/* GPIO inputs from blackghost */
+		qcom,bg2ap-status-gpio = <&msm_gpio 97 0>;
+		qcom,bg2ap-errfatal-gpio = <&msm_gpio 95 0>;
+		/* GPIO output to blackghost */
+		qcom,ap2bg-status-gpio = <&msm_gpio 17 0>;
+		qcom,ap2bg-errfatal-gpio = <&msm_gpio 23 0>;
+	};
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-pinctrl.txt
new file mode 100644
index 0000000..7d48334
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-pinctrl.txt
@@ -0,0 +1,191 @@
+Qualcomm Technologies, Inc. MDM9607 TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+MDM9607 platform.
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be "qcom,mdm9607-pinctrl"
+
+- reg:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: the base address and size of the TLMM register space.
+
+- interrupts:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: should specify the TLMM summary IRQ.
+
+- interrupt-controller:
+	Usage: required
+	Value type: <none>
+	Definition: identifies this node as an interrupt controller
+
+- #interrupt-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 2. Specifying the pin number and flags, as defined
+		    in <dt-bindings/interrupt-controller/irq.h>
+
+- gpio-controller:
+	Usage: required
+	Value type: <none>
+	Definition: identifies this node as a gpio controller
+
+- #gpio-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 2. Specifying the pin number and flags, as defined
+		    in <dt-bindings/gpio/gpio.h>
+
+- qcom,tlmm-emmc-boot-select:
+	Usage: optional
+	Value type: <u32>
+	Definition: selects the bit-field position to set.
+
+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
+a general description of GPIO and interrupt bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, drive strength, etc.
+
+
+PIN CONFIGURATION NODES:
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pin configuration subnode:
+
+- pins:
+	Usage: required
+	Value type: <string-array>
+	Definition: List of gpio pins affected by the properties specified in
+		    this subnode.  Valid pins are:
+		    gpio0-gpio79,
+		    sdc1_clk,
+		    sdc1_cmd,
+		    sdc1_data,
+		    sdc2_clk,
+		    sdc2_cmd,
+		    sdc2_data,
+		    qdsd_clk,
+		    qdsd_cmd,
+		    qdsd_data0,
+		    qdsd_data1,
+		    qdsd_data2,
+		    qdsd_data3
+
+- function:
+	Usage: required
+	Value type: <string>
+	Definition: Specify the alternative function to be configured for the
+		    specified pins. Functions are only valid for gpio pins.
+		    Valid values are:
+
+		blsp_spi3, blsp_uart3, qdss_tracedata_a, bimc_dte1, blsp_i2c3,
+		qdss_traceclk_a, bimc_dte0, qdss_cti_trig_in_a1, blsp_spi2,
+		blsp_uart2, blsp_uim2, blsp_i2c2, qdss_tracectl_a, sensor_int2,
+		blsp_spi5, blsp_uart5, ebi2_lcd, m_voc, sensor_int3, sensor_en,
+		blsp_i2c5, ebi2_a, qdss_tracedata_b, sensor_rst, blsp2_spi,
+		blsp_spi1, blsp_uart1, blsp_uim1, blsp3_spi, gcc_gp2_clk_b,
+		gcc_gp3_clk_b, blsp_i2c1, gcc_gp1_clk_b, blsp_spi4, blsp_uart4,
+		rcm_marker1, blsp_i2c4, qdss_cti_trig_out_a1, rcm_marker2,
+		qdss_cti_trig_out_a0, blsp_spi6, blsp_uart6, pri_mi2s_ws_a,
+		ebi2_lcd_te_b, blsp1_spi, backlight_en_b, pri_mi2s_data0_a,
+		pri_mi2s_data1_a, blsp_i2c6, ebi2_a_d_8_b, pri_mi2s_sck_a,
+		ebi2_lcd_cs_n_b, touch_rst, pri_mi2s_mclk_a, pwr_nav_enabled_a,
+		ts_int, sd_write, pwr_crypto_enabled_a, codec_rst, adsp_ext,
+		atest_combodac_to_gpio_native, uim2_data, gmac_mdio, gcc_gp1_clk_a,
+		uim2_clk, gcc_gp2_clk_a, eth_irq, uim2_reset, gcc_gp3_clk_a,
+		eth_rst, uim2_present, prng_rosc, uim1_data, uim1_clk,
+		uim1_reset, uim1_present, gcc_plltest, uim_batt, coex_uart,
+		codec_int, qdss_cti_trig_in_a0, atest_bbrx1, cri_trng0, atest_bbrx0,
+		cri_trng, qdss_cti_trig_in_b0, atest_gpsadc_dtest0_native,
+		qdss_cti_trig_out_b0, qdss_tracectl_b, qdss_traceclk_b, pa_indicator,
+		modem_tsync, nav_tsync_out_a, nav_ptp_pps_in_a, ptp_pps_out_a,
+		gsm0_tx, qdss_cti_trig_in_b1, cri_trng1, qdss_cti_trig_out_b1,
+		ssbi1, atest_gpsadc_dtest1_native, ssbi2, atest_char3, atest_char2,
+		atest_char1, atest_char0, atest_char, ebi0_wrcdc, ldo_update,
+		gcc_tlmm, ldo_en, dbg_out, atest_tsens, lcd_rst, wlan_en1,
+		nav_tsync_out_b, nav_ptp_pps_in_b, ptp_pps_out_b, pbs0, sec_mi2s,
+		pwr_modem_enabled_a, pbs1, pwr_modem_enabled_b, pbs2, pwr_nav_enabled_b,
+		pwr_crypto_enabled_b, gpio
+
+- bias-disable:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as no pull.
+
+- bias-pull-down:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as pull down.
+
+- bias-pull-up:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as pull up.
+
+- output-high:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins are configured in output mode, driven
+		    high.
+		    Not valid for sdc pins.
+
+- output-low:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins are configured in output mode, driven
+		    low.
+		    Not valid for sdc pins.
+
+- drive-strength:
+	Usage: optional
+	Value type: <u32>
+	Definition: Selects the drive strength for the specified pins, in mA.
+		    Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
+
+Example:
+
+	tlmm: pinctrl@01010000 {
+		compatible = "qcom,mdm9607-pinctrl";
+		reg = <0x01010000 0x300000>;
+		interrupts = <0 208 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		qcom,tlmm-emmc-boot-select = <0x1>;
+
+		uart_console_active: uart_console_active {
+			mux {
+				pins = "gpio8", "gpio9";
+				function = "blsp_uart5";
+			};
+
+			config {
+				pins = "gpio8", "gpio9";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+	};
diff --git a/Documentation/devicetree/bindings/power/smb1360-charger-fg.txt b/Documentation/devicetree/bindings/power/smb1360-charger-fg.txt
new file mode 100644
index 0000000..8b2234e
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/smb1360-charger-fg.txt
@@ -0,0 +1,246 @@
+SMB1360 battery charger and fuel gauge
+
+SMB1360 is a single path switch-mode battery charger and
+fuel gauge. The charger has a max current rating of 1.5A.
+The fuel gauge uses voltage + coulomb counting to report
+the state of charge.
+
+The smb1360 interface is via I2C bus.
+
+Required Properties:
+- compatible:			Must be "qcom,smb1360-charger-fg"
+- reg:				The device 7-bit I2C address.
+
+Optional Properties:
+
+- interrupts			This indicates the IRQ number of the GPIO
+				connected to the STAT pin.
+- pinctrl-names:		The state name of the pin configuration. Only
+				support: "default".
+- pinctrl-0:			The phandle of the pin configuration node in
+				pinctrl for smb_int_pin.
+				For details of pinctrl properties, please refer to:
+				"Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt"
+- qcom,float-voltage-mv	 	Float Voltage in mV - the maximum voltage up to which
+				the battery is charged. Supported range 3460V to 4360V
+- qcom,charging-timeout		Maximum duration in minutes that a single charge
+				cycle may last.  Supported values are: 0, 192, 384,
+				768, and 1536.  A value of 0 means that no
+				charge cycle timeout is used and charging can
+				continue indefinitely.
+- qcom,charging-disabled		Set this if charging should be disabled in the build
+				by default. Useful in usecases where battery current
+				needs to be profiled even when USB is present.
+- qcom,recharge-thresh-mv	Specifies the minimum voltage drop in millivolts
+				below the float voltage that is required in
+				order to initiate a new charging cycle.
+				Supported values are: 50, 100, 200 and 300mV.
+- qcom,recharge-disabled		Disabled the auto-recharge function
+- qcom,iterm-ma			Specifies the termination current to indicate end-of-charge.
+				Possible values in mA - 25, 50, 75, 100, 125, 150, 175, 200
+- qcom,iterm-disabled		Disables the termination current feature. This is a bool
+				property.
+- qcom,chg-inhibit-disabled	Disables the charger-inhibit function.
+- qcom,disable-ov-ends-chg-cycle
+				The boolean property to indicate if the ov-ends-charge-cycle
+				feature is disabled. If the feature is disabled, charging
+				could be resumed from battery OV (over voltage) status; otherwise,
+				charging cycle will be terminated after battery OV event and
+				won't be resumed until disable/enable charging.
+- qcom,batt-id-disabled		Disabled the batt-id function. Doing this will
+				disable the ability of RID based battery profile selection.
+- qcom,fg-delta-soc		The delta in SOC which will generate an interrupt
+- qcom,fg-soc-max		SOC value (max) at which an interrupt is generated.
+				This can be used to alert the system when the
+				battery reaches a specific (maximum) SOC value.
+- qcom,fg-soc-min		SOC value (min) at which an interrupt is generated.
+				This can be used to alert the system when the
+				battery reaches a specific (minimum) SOC value.
+- qcom,fg-voltage-min-mv	The minimum volatge at which an interrupt is generated.
+				This can be used as an alert mechanism.
+- qcom,fg-voltage-empty-mv	The voltage which indicates the battery is empty.
+- qcom,thermal-mitigation:	Array of input current limit values for different
+				system thermal mitigation level.
+- qcom,stat-pulsed-irq:		A boolean flag to indicate the state-irq pin will generate pulse
+				signal when interrupt happened. If this property is not specified,
+				the default configuration is static level irq.
+- qcom,shdn-after-pwroff:	A bool property to configure smb1360 for shutdown at power-off.
+- qcom,empty-soc-disabled:	A bool property to indicate whether stop updating empty_soc flag.
+				System reports 0% SOC when empty_soc being set.
+- qcom,awake-min-soc		A bool property to indicate whether the system is prevented from
+				sleeping when SOC is under the min_soc threshold.
+- qcom,batt-profile-select	A boolean flag to indicate of battery-profile
+				selection is enabled.
+- qcom,profile-a-rid-kohm	The battery-ID resistor (RID) in Kohm supported by
+				profile-A of SMB1360. This should be specified
+				if 'batt-profile-select' is defined.
+- qcom,profile-b-rid-kohm	The battery-ID resistor (RID) in Kohm supported by
+				profile-B of SMB1360. This should be specified
+				if 'batt-profile-select' is defined.
+- qcom,batt-id-vref-uv		The reference voltage on the battery-ID line
+				specified in micro-volts.
+- qcom,batt-id-rpullup-kohm	The pull-up resistor connected on the battery-ID
+				(vref) line.
+- qcom,smb1360-vadc		VADC device phandle (used for reading the RID)
+- qcom,fg-batt-capacity-mah	The new battery capacity to be supported.
+				This updates the ACTUAL and NOMINAL CAPACITY
+				of the profile.
+- qcom,fg-cc-soc-coeff		The CC_TO_SOC_COEFF of the new battery capacity.
+				This is updated only if 'fg-batt-capacity-mah'
+				is specified. This value is calculated from the
+				batt-capacity and then encoded as floating number.
+				cc_soc_coeff = HALF_ENCODING(8192 / batt-capacity)
+- qcom,fg-cutoff-voltage-mv	This is the minimum allowed system voltage. The
+				FG will report SOC = 0 at this volatge. This
+				value is in mv.
+- qcom,fg-iterm-ma		This is termination current at which the
+				Monotonic SOC reports 100. The value passed here
+				is negated in the driver (assuming that the iterm
+				is always -ve). This value is in mA.
+- qcom,fg-ibatt-standby-ma	This is the minimum current value for the SOC to
+				be above 0% at the cutoff voltage. This value
+				is in mA.
+- qcom,fg-cc-to-cv-mv		This is the voltage at which the FG transitions
+				from CC to CV. This value should never be
+				higher than the float volatge. Its in mV.
+- qcom,thermistor-c1-coeff	This is the NTC thermistor C1 coeff for the
+				thermistor inside the battery. This value is
+				16-bit float encoded value determined from the
+				NTC-c1_coeff mapping.
+- qcom,otg-batt-curr-limit	This property defines the current threshold draw
+				from battery when device working at OTG mode.
+				The possible values are: 350, 550, 950, 1500mA.
+- qcom,fg-auto-recharge-soc	This property defines the auto recharging SOC threshold.
+- qcom,min-icl-100ma		A bool property to set the minimum ICL current
+				to 100mA. If this property is not set the minimum
+				ICL is set to 500mA in all the scenarios.
+- qcom,config-hard-thresholds	This property indicates if cold and hot thresholds need be modified.
+				If it's not defined, default temp thresholds will be used. If this
+				defined, it's required to specify the "qcom,hot-bat-decidegc" and
+				"qcom,cold-bat-decidegc" values. If this defined, the serial properties
+				(qcom,otp-hard-jeita-config, qcom,otp-hot-bat-decidegc,
+				qcom,otp-cold-bat-decidegc) mustn't be defined.
+- qcom,hot-bat-decidegc		Hot battery temperature in decidegC. This property should only be
+				defined when "qcom,config-hard-thresholds" defined, and the value
+				must be out of range [0, 55].
+- qcom,cold-bat-decidegc	Cold battery temperature in decidegC. This property should only be
+				defined when "qcom,config-hard-thresholds" defined, and the value
+				must be out of range [0, 55].
+- qcom,otp-hard-jeita-config	This property indicates if cold and hot thresholds need be modified.
+				If it's not defined, default temp thresholds [0, 55] will be used.
+				If this defined, it's required to specify the "qcom,otp-hot-bat-decidegc"
+				and "qcom,otp-cold-bat-decidegc" values. If this is defined, the serial
+				properties (qcom,config-hard-thresholds, qcom,hot-bat-decidegc,
+				qcom,cold-bat-decidegc) mustn't be defined.
+- qcom,otp-hot-bat-decidegc	Hot battery temperature in decidegC. This property could only be
+				defined when qcom,config-otp-hard-jeita exist.
+- qcom,otp-cold-bat-decidegc	Cold battery temperature in decidegC. This property could only be
+				defined when qcom,config-otp-hard-jeita exist.
+- qcom,otp-hard-jeita-hysteresis This property contains two intergers to define the temperature
+				hysteresis (in decidegC unit) for hard cold and hard hot.
+				This property could only be defined when qcom,config-otp-hard-jeita exist.
+- qcom,soft-jeita-supported	This property indicates whether soft jeita supported.
+- qcom,warm-bat-decidegc	Warm battery temperature in decidegC. After hitting this threshold,
+				"qcom,warm-bat-ma" defines maximum charging current and
+				"qcom,warm-bat-mv" defines maximum target voltage.
+				This property must be in range [0, 55] if needed.
+- qcom,cool-bat-decidegc	Cool battery temperature in decidegC. After hitting this threshold,
+				"qcom,cool-bat-ma" defines maximum charging current and
+				"qcom,cool-bat-mv" defines maximum target voltage.
+				This property must be in range [0, 55] if needed.
+- qcom,warm-bat-mv		Maximum warm battery target voltage in milli-volts.
+- qcom,cool-bat-mv		Maximum cool battery target voltage in milli-volts.
+- qcom,warm-bat-ma		Maximum warm battery charge current in milli-amps.
+- qcom,cool-bat-ma		Maximum cool battery charge current in milli-amps.
+- qcom,fg-reset-at-pon		This is a bool property which indicates if the
+				FG reset at power-on is enabled.
+- qcom,fg-reset-thresold-mv	This value indicates the volatge threshold to
+				reset the FG. This value is compared against
+				the difference between in predicted voltage and
+				current voltage. If this value is not specified
+				a default value of 50mV is used. Unit is in milli-volts.
+- qcom,rsense-10mhom		A bool property to indicate the Rsense resistor
+				configuration. If set, the Rsense is 10mOhm else
+				its 20mOhm.
+- qcom,otg-fet-present		A bool property to indicate that a pMOS FET is present
+				to boost the OTG current. On enabling this the max OTG
+				current supported is 3x(qcom,otg-batt-curr-limit).
+- qcom,otg-fet-enable-gpio	GPIO for enabling and disabling OTG FET.
+				Following should be the PMIC gpio configuration:
+				{
+					qcom,mode = <1>; //Digital output
+					qcom,pull = <0>; //Pull up configuration
+					qcom,vin-sel = <0>; //Voltage level: VPH_PWR
+					qcom,src-sel = <0>; //Pin function: GPIO
+					qcom,master-en = <1>; //Enable
+				}
+				Please go through the documentation for PMIC gpio
+				configuration details:
+				Documentation/devicetree/bindings/gpio/qpnp-pin.txt
+- qcom,parallel-charging-enabled: A bool property which enables SMB1360 to
+				operate in the parallel mode. SMB1360 acts
+				as the primary charger.
+- qcom,max-parallel-current-ma: This is the max charging current which can be
+				drawn from the secondary charger. If this is
+				not specified this value defaults to 540mA.
+				The overall current charging current is
+				1500mA(from SMB) + qcom,max-parallel-current-ma.
+
+Example:
+	i2c@f9967000 {
+		smb1360-chg-fg@1b {
+			compatible = "qcom,smb1360-chg-fg";
+			reg = <0x1b>;
+			interrupt-parent = <&spmi_bus>;
+			interrupts = <0x00 0xcd 0>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&smb_int_default>;
+
+			/* battery-profile selection properties */
+			qcom,batt-profile-select;
+			qcom,smb1360-vadc = <&pm8916_vadc>;
+			qcom,batt-id-vref-uv = <1800000>;
+			qcom,batt-id-rpullup-kohm = <100>;
+			qcom,profile-a-rid-kohm = <78>;
+			qcom,profile-b-rid-kohm = <200>;
+
+			/* battery capacity */
+			qcom,fg-batt-capacity-mah = <4000>;
+			qcom,fg-cc-soc-coeff = <0x8009>;
+
+			qcom,fg-cutoff-voltage-mv = <3300>;
+			qcom,fg-iterm-ma = <100>;
+			qcom,fg-ibatt-standby-ma = <200>;
+			qcom,fg-cc-to-cv-mv = <4180>;
+			qcom,thermistor-c1-coeff = <0x86DB>;
+
+			qcom,float-voltage-mv = <4200>;
+			qcom,iterm-ma = <100>;
+			qcom,charging-disabled;
+			qcom,recharge-thresh-mv = <100>;
+			qcom,fg-soc-max = <85>;
+			qcom,fg-soc-min = <15>;
+			qcom,fg-auto-recharge-soc = <99>;
+			qcom,thermal-mitigation = <1500 700 300 0>;
+			qcom,config-hard-thresholds;
+			qcom,hot-bat-decidegc = <650>;
+			qcom,cold-bat-decidegc = <(-100)>;
+			qcom,soft-jeita-supported;
+			qcom,warm-bat-decidegc = <450>;
+			qcom,cool-bat-decidegc = <100>;
+			qcom,otp-hard-jeita-config;
+			qcom,otp-hot-bat-decidegc = <550>;
+			qcom,otp-cold-bat-decidegc = <0>;
+			qcom,otp-hard-jeita-hysteresis = <0, 50>;
+			qcom,warm-bat-mv = <4100>;
+			qcom,cool-bat-mv = <4100>;
+			qcom,warm-bat-ma = <750>;
+			qcom,cool-bat-ma = <750>;
+
+			qcom,otg-batt-curr-limit = <950>;
+			qcom,fg-reset-at-pon;
+
+			qcom,otg-fet-present;
+			qcom,otg-fet-enable-gpio = <&pm8916_gpios 3 0>;
+		};
+	};
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 5034e9f..392ee7b 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen3.txt
@@ -380,7 +380,7 @@
 	Value type: <u32>
 	Definition: Value in micro percentage for low temperature ESR tight
 		    filter. If this is not specified, then a default value of
-		    48829 (4.88 %) will be used. Lowest possible value is 1954
+		    30000 (3 %) will be used. Lowest possible value is 1954
 		    (0.19 %).
 
 - qcom,fg-esr-broad-lt-filter-micro-pct
@@ -388,9 +388,35 @@
 	Value type: <u32>
 	Definition: Value in micro percentage for low temperature ESR broad
 		    filter. If this is not specified, then a default value of
-		    148438 (14.84 %) will be used. Lowest possible value is
+		    30000 (3 %) will be used. Lowest possible value is
 		    1954 (0.19 %).
 
+- qcom,fg-esr-rt-filter-switch-temp
+	Usage:      optional
+	Value type: <u32>
+	Definition: Battery temperature threshold below which ESR relax
+		    filter coefficients will be applied after a certain
+		    number of delta battery temperature interrupts firing in
+		    an interval of time. This will be applied only when Qnovo
+		    is enabled. If this is not specified, then the default
+		    value used will be -100. Unit is in decidegC.
+
+- qcom,fg-esr-tight-rt-filter-micro-pct
+	Usage:      optional
+	Value type: <u32>
+	Definition: Value in micro percentage for relax temperature ESR tight
+		    filter. If this is not specified, then a default value of
+		    5860 will be used. Lowest possible value is 1954 (0.19 %).
+		    This will be applied only if Qnovo is enabled.
+
+- qcom,fg-esr-broad-rt-filter-micro-pct
+	Usage:      optional
+	Value type: <u32>
+	Definition: Value in micro percentage for relax temperature ESR broad
+		    filter. If this is not specified, then a default value of
+		    156250 will be used. Lowest possible value is 1954 (0.19 %).
+		    This will be applied only if Qnovo is enabled.
+
 - qcom,fg-auto-recharge-soc
 	Usage:      optional
 	Value type: <empty>
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb1390-charger.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb1390-charger.txt
new file mode 100644
index 0000000..b55d517
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/supply/qcom/smb1390-charger.txt
@@ -0,0 +1,73 @@
+Qualcomm Technologies, Inc. SMB1390 Charger Specific Bindings
+
+SMB1390 charge pump is paired with QTI family of standalone chargers to
+enable a high current, high efficiency Li+ battery charging system.
+
+=======================
+Required Node Structure
+=======================
+
+SMB1390 Charger must be described in two levels of device nodes.
+
+==================================
+First Level Node - SMB1390 Charger
+==================================
+
+Charger specific properties:
+- compatible
+  Usage:      required
+  Value type: <string>
+  Definition: "qcom,smb1390-charger".
+
+- qcom,pmic-revid
+  Usage:      required
+  Value type: phandle
+  Definition: Should specify the phandle of SMB's revid module. This is used
+	      to identify the SMB subtype.
+
+- qcom,channel-num
+  Usage:      required
+  Value type: <u32>
+  Definition: Specifies the ADC channel number for reading die temperature.
+
+================================================
+Second Level Nodes - SMB1390 Charger Peripherals
+================================================
+
+Peripheral specific properties:
+- interrupts
+  Usage:      required
+  Value type: <prop-encoded-array>
+  Definition: Peripheral interrupt specifier.
+
+- interrupt-names
+  Usage:      required
+  Value type: <stringlist>
+  Definition: Interrupt names.  This list must match up 1-to-1 with the
+	      interrupts specified in the 'interrupts' property.
+
+=======
+Example
+=======
+
+smb1390_charger: qcom,charge_pump {
+	compatible = "qcom,smb1390-charger";
+	qcom,pmic-revid = <&smb1390_revid>;
+	qcom,channel-num = <15>
+	interrupt-parent = <&smb1390>;
+	qcom,smb-vadc = <&pm8998_vadc>;
+	status = "disabled";
+
+	qcom,core {
+		interrupts = <0x10 0x0 IRQ_TYPE_EDGE_RISING>,
+			     <0x10 0x1 IRQ_TYPE_EDGE_RISING>,
+			     <0x10 0x2 IRQ_TYPE_EDGE_RISING>,
+			     <0x10 0x3 IRQ_TYPE_EDGE_RISING>,
+			     <0x10 0x4 IRQ_TYPE_EDGE_RISING>;
+		interrupt-names = "switcher-off-window",
+				  "switcher-off-fault",
+				  "vph-ov-soft",
+				  "ilim",
+				  "temp-alarm";
+	};
+};
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 33dc684..991e26c 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -1872,6 +1872,140 @@
 		asoc-wsa-codec-prefixes = "SpkrLeft";
 	};
 
+* APQ8009 I2S ASoC Machine driver
+
+Required properties:
+- compatible : "qcom,apq8009-audio-i2s-codec"
+- qcom,model : The user-visible name of this sound card.
+- qcom,pinctrl-names : Lists all the possible combinations of the gpio sets
+	mentioned in qcom,msm-gpios. Say we have 2^N combinations for N GPIOs,
+	this would list all the 2^N combinations.
+- pinctrl-names : The combinations of gpio sets from above that are supported in
+	the flavor. This can be sometimes same as qcom,pinctrl-names i.e with 2^N
+	combinations or will have less incase if some combination is not supported.
+- pinctrl-# : Pinctrl states as mentioned in pinctrl-names.
+- qcom,audio-routing : A list of the connections between audio components.
+	Each entry is a pair of strings, the first being the connection's sink,
+	the second being the connection's source.
+
+Optional properties:
+- qcom,cdc-us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
+- 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
+	in "asoc-cpu". The cpu names are in the form of "%s.%d" form,
+	where the id (%d) field represents the back-end AFE port id that
+	this CPU dai is associated with.
+- 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: This property contains list of wsa codec names. The names
+		should comply with the wsa nodes configurations.
+- qcom,wsa-aux-dev-prefix: This property contains list of wsa codec prefixes.
+- qcom,tdm-i2s-switch-enable: For chipsets where tdm mics are controlled by
+			      switch, drive corresponding gpio to output high
+			      to enable switch.
+
+Example:
+	sound {
+		compatible = "qcom,apq8009-audio-i2s-codec";
+		qcom,model = "apq8009-tashalite-snd-card";
+		qcom,msm-codec-type = "external";
+		qcom,msm-mbhc-hphl-swh = <0>;
+		qcom,msm-mbhc-gnd-swh = <0>;
+		qcom,msm-mclk-freq = <9600000>;
+		qcom,msm-hs-micbias-type = "internal";
+		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 BIAS2",
+			"MIC BIAS2", "Digital Mic2",
+			"DMIC3", "MIC BIAS2",
+			"MIC BIAS2", "Digital Mic3",
+			"SpkrLeft IN", "SPK1 OUT",
+			"SpkrRight IN", "SPK2 OUT";
+
+		qcom,msm-gpios =
+			"pri_i2s",
+			"quat_i2s";
+		qcom,pinctrl-names =
+			"all_off",
+			"pri_i2s_act",
+			"quat_i2s_act",
+			"pri_i2s_quat_i2s_act";
+		pinctrl-names =
+			"all_off",
+			"pri_i2s_act",
+			"quat_i2s_act",
+			"pri_i2s_quat_i2s_act";
+		pinctrl-0 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
+			&pri_mi2s_dout_sleep &pri_mi2s_din_sleep
+			&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+		pinctrl-1 = <&pri_mi2s_active &pri_mi2s_ws_active
+			&pri_mi2s_dout_active &pri_mi2s_din_active
+			&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+		pinctrl-2 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
+			&pri_mi2s_dout_sleep &pri_mi2s_din_sleep
+			&quat_mi2s_active &quat_mi2s_din_active>;
+		pinctrl-3 = <&pri_mi2s_active &pri_mi2s_ws_active
+			&pri_mi2s_dout_active &pri_mi2s_din_active
+			&quat_mi2s_active &quat_mi2s_din_active>;
+
+		asoc-platform = <&pcm0>, <&pcm1>, <&voip>, <&voice>,
+			<&loopback>, <&compress>, <&hostless>,
+			<&afe>, <&lsm>, <&routing>, <&cpe>, <&lpa>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+			"msm-voip-dsp", "msm-pcm-voice", "msm-pcm-loopback",
+			"msm-compress-dsp", "msm-pcm-hostless", "msm-pcm-afe",
+			"msm-lsm-client", "msm-pcm-routing", "msm-cpe-lsm",
+			"msm-pcm-lpa";
+		asoc-cpu =  <&dai_pri_auxpcm>, <&dai_hdmi>,<&dai_mi2s0>,
+			<&dai_mi2s2>, <&dai_mi2s3>,
+			<&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+			<&sb_3_rx>, <&sb_3_tx>,
+			<&sb_4_rx>, <&sb_4_tx>, <&afe_pcm_rx>,
+			<&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
+			<&incall_record_rx>, <&incall_record_tx>,
+			<&incall_music_rx>, <&incall_music_2_rx>,
+			<&bt_sco_rx>,
+			<&bt_sco_tx>, <&int_fm_rx>, <&int_fm_tx>;
+		asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-hdmi.8",
+			"msm-dai-q6-mi2s.0",
+			"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+			"msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
+			"msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+			"msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+			"msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+			"msm-dai-q6-dev.224",
+			"msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
+			"msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
+			"msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773",
+			"msm-dai-q6-dev.32770",
+			"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+			"msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293";
+		asoc-codec = <&stub_codec>;
+		asoc-codec-names = "msm-stub-codec.1";
+		qcom,wsa-max-devs = <2>;
+		qcom,wsa-devs = <&wsa881x_213>, <&wsa881x_214>;
+		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight";
+	};
+
 * MSM8909 BG ASoC Machine driver
 
 Required properties:
diff --git a/Documentation/devicetree/bindings/sound/taiko_codec.txt b/Documentation/devicetree/bindings/sound/taiko_codec.txt
new file mode 100644
index 0000000..5f8d293
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/taiko_codec.txt
@@ -0,0 +1,636 @@
+taiko audio CODEC
+
+Required properties:
+
+ - compatible : "qcom,taiko-slim-pgd" or "qcom,tapan-slim-pgd" for Tapan codec
+		or "qcom,tomtom-slim-pgd" for the Tomtom codec
+		or "qcom,tasha-slim-pgd" or "qcom,tasha-i2c-pgd" for Tasha Codec
+ - elemental-addr: codec slimbus slave PGD enumeration address.(48 bits)
+
+ - qcom,cdc-reset-gpio: gpio used for codec SOC reset.
+                        If this property is not defined, it is expected
+                        to atleast have "qcom,wcd-rst-n-gpio" to be defined.
+ - qcom,wcd-rst-gpio-node: Phandle reference to the DT node having codec reset gpio
+                        configuration. If this property is not defined, it is
+                        expected to atleast define "qcom,cdc-reset-gpio" property.
+
+ - cdc-vdd-buck-supply: phandle of buck supply's regulator device tree node.
+ - qcom,cdc-vdd-buck-voltage: buck supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-buck-current: buck supply's max current in mA.
+
+ - cdc-vdd-tx-h-supply: phandle of tx-h supply's regulator device tree node.
+ - qcom,cdc-vdd-tx-h-voltage: tx-h supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-tx-h-current: tx-h supply's max current in mA.
+
+ - cdc-vdd-rx-h-supply: phandle of rx-h supply's regulator device tree node.
+ - qcom,cdc-vdd-rx-h-voltage: rx-h supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-rx-h-current: rx-h supply's max current in mA.
+
+ - cdc-vddpx-1-supply: phandle of px-1 supply's regulator device tree node.
+ - qcom,cdc-vddpx-1-voltage: px-1 supply's voltage level min and max in mV.
+ - qcom,cdc-vddpx-1-current: px-1 supply's max current in mA.
+
+ - cdc-vdd-a-1p2v-supply: phandle of 1.2v supply's regulator device tree node.
+ - qcom,cdc-vdd-a-1p2v-voltage: 1.2v supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-a-1p2v-current: 1.2v supply's max current in mA.
+
+ - cdc-vddcx-1-supply: phandle of cx-1 supply's regulator device tree node.
+ - qcom,cdc-vddcx-1-voltage: cx-1 supply's voltage level min and max in mV.
+ - qcom,cdc-vddcx-1-current: cx-1 supply's max current in mA.
+
+ - cdc-vddcx-2-supply: phandle of cx-2 supply's regulator device tree node.
+ - qcom,cdc-vddcx-2-voltage: cx-2 supply's voltage level min and max in mV.
+ - qcom,cdc-vddcx-2-current: cx-2 supply's max current in mA.
+
+ - cdc-vdd-buckhelper-supply: phandle of helper regulator supply's
+				device tree node. This supply is a helper regulator for
+				cdc-vdd-buck-supply regulator.
+ - cdc-vdd-buckhelper-voltage: helper supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-buckhelper-current: helper supply's max current in mA.
+
+ - qcom,cdc-static-supplies: List of supplies to be enabled prior to codec
+			     hardware probe.  Supplies in this list will be
+			     stay enabled.
+
+ - qcom,cdc-micbias-ldoh-v - LDOH output in volts (should be 1.95 V and 3.00 V).
+
+ - qcom,cdc-micbias-cfilt1-mv - cfilt1 output voltage in milli volts.
+ - qcom,cdc-micbias-cfilt2-mv - cfilt2 output voltage in milli volts.
+ - qcom,cdc-micbias-cfilt3-mv - cfilt3 output voltage in milli volts.
+   cfilt voltage can be set to max of qcom,cdc-micbias-ldoh-v - 0.15V.
+
+ - qcom,cdc-micbias1-cfilt-sel = cfilt to use for micbias1
+				 (should be from 1 to 3).
+ - qcom,cdc-micbias2-cfilt-sel = cfilt to use for micbias2
+				 (should be from 1 to 3).
+ - qcom,cdc-micbias3-cfilt-sel = cfilt to use for micbias3
+				 (should be from 1 to 3).
+ - qcom,cdc-micbias4-cfilt-sel = cfilt to use for micbias4
+				 (should be from 1 to 3).
+   This value represents the connected CFLIT to MIC Bias.
+
+ - qcom,cdc-micbias1-ext-cap: Boolean. Enable micbias 1 external capacitor mode.
+ - qcom,cdc-micbias2-ext-cap: Boolean. Enable micbias 2 external capacitor mode.
+ - qcom,cdc-micbias3-ext-cap: Boolean. Enable micbias 3 external capacitor mode.
+ - qcom,cdc-micbias4-ext-cap: Boolean. Enable micbias 4 external capacitor mode.
+ - qcom,cdc-mclk-clk-rate - Specifies the master clock rate in Hz required for
+			    codec.
+ - qcom,cdc-slim-ifd-dev - namme of the codec slim interface device.
+ - qcom,cdc-slim-ifd-elemental-addr - codec slimbus slave interface device
+				     enumeration address.
+
+Optional properties:
+ - cdc-dmic-sample-rate: Specifies the sample rate of digital mic in HZ. The
+			 values for 9.6MHZ mclk can be 2400000 Hz, 3200000 Hz
+			 and 4800000 Hz.  The values for 12.288MHz mclk can be
+			 3072200 Hz, 4096000 Hz and 6144000 Hz.
+
+ - qcom,cdc-mad-dmic-rate: Specifies the sample rate of digital mic in HZ to be
+			   used by MAD (Microphone Activity Detection) hardware
+			   block on the codec. The valid set of values are same
+			   as that of cdc-dmic-sample-rate, but this rate will
+			   only be used by MAD and all other audio use cases
+			   involving DMIC will use the rate defined by
+			   cdc-dmic-sample-rate.
+
+ - qcom,cdc-ecpp-dmic-rate: Specifies the sample rate of digital mic in HZ to be
+			   used by ECPP (Echo Cancellation Ping Pong) block
+			   on the codec. The valid set of values are same
+			   as that of cdc-dmic-sample-rate, but this rate will
+			   only be used by ECPP and all other audio use cases
+			   involving DMIC will use the rate defined by
+			   cdc-dmic-sample-rate.
+
+ - qcom,cdc-dmic-clk-drv-strength: Specifies the drive strength for digital microphone
+				   clock in the codec. Accepted values are 2,4,8 and 16.
+				   The clock drive strentgh is in uA. Codec driver will
+				   choose default value for particular codec if this
+				   value is not specified in device tree.
+
+ - qcom,cdc-on-demand-supplies: List of supplies which can be enabled
+				dynamically.
+				Supplies in this list are off by default.
+
+- qcom,cdc-cp-supplies: List of supplies required for codec chargepump enable
+				Supplies in this list can be enabled/disabled dynamically and
+				are off by default.
+
+ - qcom,cdc-micbias2-headset-only: Boolean. Allow micbias 2 only to headset mic.
+
+ - qcom,cdc-variant: Indicates codec variant, WCD9XXX indicates all codecs till Taiko
+			WCD9330 indicates wcd9330 audio codec
+
+ - qcom,cdc-micbias1-mv: micbias1 output voltage in milli volts.
+			 This is used when cfilt is not user configurable
+			 and micbias1 is directly controlled with a register
+			 write.
+
+ - qcom,cdc-micbias2-mv: micbias2 output voltage in milli volts.
+			 This is used when cfilt is not user configurable
+			 and micbias2 is directly controlled with a register
+			 write.
+
+ - qcom,cdc-micbias3-mv: micbias3 output voltage in milli volts.
+			 This is used when cfilt is not user configurable
+			 and micbias3 is directly controlled with a register
+			 write.
+
+ - qcom,cdc-micbias4-mv: micbias4 output voltage in milli volts.
+			 This is used when cfilt is not user configurable
+			 and micbias4 is directly controlled with a register
+			 write.
+
+ - qcom,cdc-mic-unmute-delay: based on dmic characteristics the initial pop
+			      time that is observed in TX path is varying.
+			      Configure PGA unmute delay based on DT value.
+
+ - clock-names : clock name defined for external clock.
+ - clocks : external clock defined for codec clock.
+
+Example:
+
+taiko_codec {
+	compatible = "qcom,taiko-slim-pgd";
+	elemental-addr = [00 01 A0 00 17 02];
+
+	qcom,cdc-reset-gpio = <&msmgpio 63 0>;
+
+	cdc-vdd-buck-supply = <&pm8941_s2>;
+	qcom,cdc-vdd-buck-voltage = <2150000 2150000>;
+	qcom,cdc-vdd-buck-current = <500000>;
+
+	cdc-vdd-tx-h-supply = <&pm8941_s3>;
+	qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+	qcom,cdc-vdd-tx-h-current = <200000>;
+
+	cdc-vdd-rx-h-supply = <&pm8941_s3>;
+	qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+	qcom,cdc-vdd-rx-h-current = <200000>;
+
+	cdc-vddpx-1-supply = <&pm8941_s3>;
+	qcom,cdc-vddpx-1-voltage = <1800000 1800000>;
+	qcom,cdc-vddpx-1-current = <5000>;
+
+	cdc-vdd-a-1p2v-supply = <&pm8941_l1>;
+	qcom,cdc-vdd-a-1p2v-voltage = <1225000 1225000>;
+	qcom,cdc-vdd-a-1p2v-current = <5000>;
+
+	cdc-vddcx-1-supply = <&pm8941_l1>;
+	qcom,cdc-vddcx-1-voltage = <1225000 1225000>;
+	qcom,cdc-vddcx-1-current = <5000>;
+
+	cdc-vddcx-2-supply = <&pm8941_l1>;
+	qcom,cdc-vddcx-2-voltage = <1225000 1225000>;
+	qcom,cdc-vddcx-2-current = <5000>;
+
+	qcom,cdc-static-supplies = "cdc-vdd-buck",
+				   "cdc-vdd-tx-h",
+				   "cdc-vdd-rx-h",
+				   "cdc-vddpx-1",
+				   "cdc-vdd-a-1p2v",
+				   "cdc-vddcx-1",
+				   "cdc-vddcx-2";
+
+	com,cdc-on-demand-supplies = "cdc-vdd-spkdrv";
+
+	qcom,cdc-micbias-ldoh-v = <0x3>;
+	qcom,cdc-micbias-cfilt1-mv = <1800>;
+	qcom,cdc-micbias-cfilt2-mv = <2700>;
+	qcom,cdc-micbias-cfilt3-mv = <1800>;
+	qcom,cdc-micbias1-cfilt-sel = <0x0>;
+	qcom,cdc-micbias2-cfilt-sel = <0x1>;
+	qcom,cdc-micbias3-cfilt-sel = <0x2>;
+	qcom,cdc-micbias4-cfilt-sel = <0x2>;
+	qcom,cdc-micbias1-ext-cap;
+	qcom,cdc-micbias2-ext-cap;
+	qcom,cdc-micbias3-ext-cap;
+	qcom,cdc-micbias4-ext-cap;
+	qcom,cdc-mclk-clk-rate = <9600000>;
+	qcom,cdc-slim-ifd = "taiko-slim-ifd";
+	qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 00 17 02];
+	qcom,cdc-dmic-sample-rate = <4800000>;
+	qcom,cdc-micbias2-headset-only;
+};
+
+Wcd9xxx audio CODEC in I2C mode
+
+ - compatible = "qcom,wcd9xxx-i2c-device";
+ - reg: represents the slave address provided to the I2C driver.
+ - qcom,cdc-reset-gpio: gpio used for codec SOC reset.
+
+ - cdc-vdd-buck-supply: phandle of buck supply's regulator device tree node.
+ - qcom,cdc-vdd-buck-voltage: buck supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-buck-current: buck supply's max current in mA.
+
+ - cdc-vdd-tx-h-supply: phandle of tx-h supply's regulator device tree node.
+ - qcom,cdc-vdd-tx-h-voltage: tx-h supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-tx-h-current: tx-h supply's max current in mA.
+
+ - cdc-vdd-rx-h-supply: phandle of rx-h supply's regulator device tree node.
+ - qcom,cdc-vdd-rx-h-voltage: rx-h supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-rx-h-current: rx-h supply's max current in mA.
+
+ - cdc-vddpx-1-supply: phandle of px-1 supply's regulator device tree node.
+ - qcom,cdc-vddpx-1-voltage: px-1 supply's voltage level min and max in mV.
+ - qcom,cdc-vddpx-1-current: px-1 supply's max current in mA.
+
+ - cdc-vdd-a-1p2v-supply: phandle of 1.2v supply's regulator device tree node.
+ - qcom,cdc-vdd-a-1p2v-voltage: 1.2v supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-a-1p2v-current: 1.2v supply's max current in mA.
+
+ - cdc-vddcx-1-supply: phandle of cx-1 supply's regulator device tree node.
+ - qcom,cdc-vddcx-1-voltage: cx-1 supply's voltage level min and max in mV.
+ - qcom,cdc-vddcx-1-current: cx-1 supply's max current in mA.
+
+ - cdc-vddcx-2-supply: phandle of cx-2 supply's regulator device tree node.
+ - qcom,cdc-vddcx-2-voltage: cx-2 supply's voltage level min and max in mV.
+ - qcom,cdc-vddcx-2-current: cx-2 supply's max current in mA.
+
+ - qcom,cdc-static-supplies: List of supplies to be enabled prior to codec
+			     hardware probe.  Supplies in this list will be
+			     stay enabled.
+
+ - qcom,cdc-micbias-ldoh-v - LDOH output in volts (should be 1.95 V and 3.00 V).
+
+ - qcom,cdc-micbias-cfilt1-mv - cfilt1 output voltage in milli volts.
+ - qcom,cdc-micbias-cfilt2-mv - cfilt2 output voltage in milli volts.
+ - qcom,cdc-micbias-cfilt3-mv - cfilt3 output voltage in milli volts.
+   cfilt voltage can be set to max of qcom,cdc-micbias-ldoh-v - 0.15V.
+
+ - qcom,cdc-micbias1-cfilt-sel = cfilt to use for micbias1
+				 (should be from 1 to 3).
+ - qcom,cdc-micbias2-cfilt-sel = cfilt to use for micbias2
+				 (should be from 1 to 3).
+ - qcom,cdc-micbias3-cfilt-sel = cfilt to use for micbias3
+				 (should be from 1 to 3).
+ - qcom,cdc-micbias4-cfilt-sel = cfilt to use for micbias4
+				 (should be from 1 to 3).
+   This value represents the connected CFLIT to MIC Bias.
+
+ - qcom,cdc-micbias1-ext-cap: Boolean. Enable micbias 1 external capacitor mode.
+ - qcom,cdc-micbias2-ext-cap: Boolean. Enable micbias 2 external capacitor mode.
+ - qcom,cdc-micbias3-ext-cap: Boolean. Enable micbias 3 external capacitor mode.
+ - qcom,cdc-micbias4-ext-cap: Boolean. Enable micbias 4 external capacitor mode.
+ - qcom,cdc-mclk-clk-rate - Specifies the master clock rate in Hz required for
+			    codec.
+
+Optional properties:
+
+ - cdc-vdd-spkdrv-supply: phandle of spkdrv supply's regulator device tree node.
+ - qcom,cdc-vdd-spkdrv-voltage: spkdrv supply voltage level min and max in mV.
+ - qcom,cdc-vdd-spkdrv-current: spkdrv supply max current in mA.
+
+ - cdc-vdd-spkdrv-supply: phandle of spkdrv supply's regulator device tree node.
+ - qcom,cdc-vdd-spkdrv-voltage: spkdrv supply voltage level min and max in mV.
+ - qcom,cdc-vdd-spkdrv-current: spkdrv supply max current in mA.
+
+ - cdc-vdd-spkdrv-2-supply: phandle of spkdrv2 supply's regulator device tree node.
+ - qcom,cdc-vdd-spkdrv-2-voltage: spkdrv2 supply voltage level min and max in mV.
+ - qcom,cdc-vdd-spkdrv-2-current: spkdrv2 supply max current in mA.
+
+ - qcom,cdc-on-demand-supplies: List of supplies which can be enabled
+				dynamically.
+				Supplies in this list are off by default.
+
+Example:
+i2c@f9925000 {
+	cell-index = <3>;
+	compatible = "qcom,i2c-qup";
+	reg = <0xf9925000 0x1000>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg-names = "qup_phys_addr";
+	interrupts = <0 97 0>;
+	interrupt-names = "qup_err_intr";
+	qcom,i2c-bus-freq = <100000>;
+	qcom,i2c-src-freq = <24000000>;
+
+	wcd9xxx_codec@0d{
+		compatible = "qcom,wcd9xxx-i2c";
+		reg = <0x0d>;
+		qcom,cdc-reset-gpio = <&msmgpio 22 0>;
+		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>;
+
+		cdc-vdd-buck-supply = <&pm8019_l11>;
+		qcom,cdc-vdd-buck-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-buck-current = <25000>;
+
+		cdc-vdd-tx-h-supply = <&pm8019_l11>;
+		qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-tx-h-current = <25000>;
+
+		cdc-vdd-rx-h-supply = <&pm8019_l11>;
+		qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-rx-h-current = <25000>;
+
+		cdc-vddpx-1-supply = <&pm8019_l11>;
+		qcom,cdc-vddpx-1-voltage = <1800000 1800000>;
+		qcom,cdc-vddpx-1-current = <10000>;
+
+		cdc-vdd-a-1p2v-supply = <&pm8019_l9>;
+		qcom,cdc-vdd-a-1p2v-voltage = <1200000 1200000>;
+		qcom,cdc-vdd-a-1p2v-current = <10000>;
+
+		cdc-vddcx-1-supply = <&pm8019_l9>;
+		qcom,cdc-vddcx-1-voltage = <1200000 1200000>;
+		qcom,cdc-vddcx-1-current = <10000>;
+
+		cdc-vddcx-2-supply = <&pm8019_l9>;
+		qcom,cdc-vddcx-2-voltage = <1200000 1200000>;
+		qcom,cdc-vddcx-2-current = <10000>;
+
+		qcom,cdc-static-supplies = "cdc-vdd-buck",
+					   "cdc-vdd-tx-h",
+					   "cdc-vdd-rx-h",
+					   "cdc-vddpx-1",
+					   "cdc-vdd-a-1p2v",
+					   "cdc-vddcx-1",
+					   "cdc-vddcx-2";
+
+		cdc-vdd-spkdrv-supply = <&pmi8994_boost>;
+		qcom,cdc-vdd-spkdrv-voltage = <5000000 5000000>;
+		qcom,cdc-vdd-spkdrv-current = <600000>;
+
+		cdc-vdd-spkdrv-2-supply = <&pmi8994_boost>;
+		qcom,cdc-vdd-spkdrv-2-voltage = <5000000 5000000>;
+		qcom,cdc-vdd-spkdrv-2-current = <600000>;
+
+		qcom,cdc-on-demand-supplies = "cdc-vdd-spkdrv",
+					      "cdc-vdd-spkdrv-2";
+
+		qcom,cdc-micbias-ldoh-v = <0x3>;
+		qcom,cdc-micbias-cfilt1-mv = <1800>;
+		qcom,cdc-micbias-cfilt2-mv = <2700>;
+		qcom,cdc-micbias-cfilt3-mv = <1800>;
+		qcom,cdc-micbias1-cfilt-sel = <0x0>;
+		qcom,cdc-micbias2-cfilt-sel = <0x1>;
+		qcom,cdc-micbias3-cfilt-sel = <0x2>;
+		qcom,cdc-micbias4-cfilt-sel = <0x2>;
+		qcom,cdc-mclk-clk-rate = <12288000>;
+	};
+
+	wcd9xxx_codec@77{
+		compatible = "qcom,wcd9xxx-i2c";
+		reg = <0x77>;
+	};
+
+	wcd9xxx_codec@66{
+		compatible = "qcom,wcd9xxx-i2c";
+		reg = <0x66>;
+	};
+	wcd9xxx_codec@55{
+		compatible = "qcom,wcd9xxx-i2c";
+		reg = <0x55>;
+	};
+};
+
+Tombak audio CODEC in SPMI mode
+
+ - compatible = "qcom,msm8x16_wcd_codec";
+ - reg: represents the slave base address provided to the peripheral.
+ - interrupt-parent : The parent interrupt controller.
+ - interrupts: List of interrupts in given SPMI peripheral.
+ - interrupt-names: Names specificed to above list of interrupts in same
+		    order.
+
+Optional properties:
+
+ - cdc-vdda-cp-supply: phandle of cp supply's regulator device tree node.
+ - qcom,cdc-vdda-cp-voltage: cp supply's voltage level min and max in mV.
+ - qcom,cdc-vdda-cp-current: cp supply's max current in mA.
+
+ - cdc-vdda-rx-h-supply: phandle of vdda-rx-h supply's regulator device tree node.
+ - qcom,cdc-vdda-rx-h-voltage: vdda-rx-h supply's voltage level min and max in mV.
+ - qcom,cdc-vdda-rx-h-current: vdda-rx-h supply's max current in mA.
+
+ - cdc-vdda-tx-h-supply: phandle of vdda-tx-h supply's regulator device tree node.
+ - qcom,cdc-vdda-tx-h-voltage: vdda-tx-h supply's voltage level min and max in mV.
+ - qcom,cdc-vdda-tx-h-current: vdda-tx-h supply's max current in mA.
+
+ - cdc-vdd-px-supply: phandle of vdd-px supply's regulator device tree node.
+ - qcom,cdc-vdd-px-voltage: vdd-px supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-px-current: vdd-px supply's max current in mA.
+
+ - cdc-vdd-pa-supply: phandle of vdd-pa supply's regulator device tree node.
+ - qcom,cdc-vdd-pa-voltage: vdd-pa supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-pa-current: vdd-pa supply's max current in mA.
+
+ - cdc-vdd-mic-bias-supply: phandle of mic-bias supply's regulator device tree
+			    node.
+ - qcom,cdc-vdd-mic-bias-voltage: mic-bias supply's voltage level min and max
+				  in mV.
+ - qcom,cdc-vdd-mic-bias-current: mic-bias supply's max current in mA.
+
+ - qcom,cdc-mclk-clk-rate: Specifies the master clock rate in Hz required for
+			    codec.
+
+ - qcom,cdc-static-supplies: List of supplies to be enabled prior to codec
+			     hardware probe.  Supplies in this list will be
+			     stay enabled.
+
+ - qcom,cdc-on-demand-supplies: List of supplies which can be enabled
+				dynamically.
+				Supplies in this list are off by default.
+ - qcom,cdc-micbias-cfilt-mv : MICBIAS voltage value
+ - qcom,cdc-boost-voltage: Specifies the analog boost output voltage value.
+				Value from 4000 to 5550 in mV in steps of 50 mV can be given.
+ - qcom,dig-cdc-base-addr: Specifies the digital codec base address for MSM digital
+				core register writes.
+
+Example:
+msm8x16_wcd_codec@f000{
+	compatible = "qcom,msm8x16_wcd_codec";
+	reg = <0xf000 0x100>;
+	interrupt-parent = <&spmi_bus>;
+	interrupts = <0x1 0xf0 0x0>,
+		     <0x1 0xf0 0x1>,
+		     <0x1 0xf0 0x2>,
+		     <0x1 0xf0 0x3>,
+		     <0x1 0xf0 0x4>,
+		     <0x1 0xf0 0x5>,
+		     <0x1 0xf0 0x6>,
+		     <0x1 0xf0 0x7>;
+	interrupt-names = "spk_cnp_int",
+			  "spk_clip_int",
+			  "spk_ocp_int",
+			  "ins_rem_det1",
+			  "but_rel_det",
+			  "but_press_det",
+			  "ins_rem_det",
+			  "mbhc_int";
+
+	cdc-vdda-cp-supply = <&pm8916_s4>;
+	qcom,cdc-vdda-cp-voltage = <1800000 2200000>;
+	qcom,cdc-vdda-cp-current = <770000>;
+
+	cdc-vdda-rx-h-supply = <&pm8916_l5>;
+	qcom,cdc-vdda-rx-h-voltage = <1800000 1800000>;
+	qcom,cdc-vdda-rx-h-current = <20000>;
+
+	cdc-vdda-tx-h-supply = <&pm8916_l5>;
+	qcom,cdc-vdda-tx-h-voltage = <1800000 1800000>;
+	qcom,cdc-vdda-tx-h-current = <20000>;
+
+	cdc-vdd-px-supply = <&pm8916_s4>;
+	qcom,cdc-vdd-px-voltage = <1800000 2200000>;
+	qcom,cdc-vdd-px-current = <770000>;
+
+	cdc-vdd-pa-supply = <&pm8916_l5>;
+	qcom,cdc-vdd-pa-voltage = <1800000 1800000>;
+	qcom,cdc-vdd-pa-current = <5000>;
+
+	cdc-vdd-mic-bias-supply = <&pm8916_l13>;
+	qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+	qcom,cdc-vdd-mic-bias-current = <25000>;
+
+	qcom,cdc-mclk-clk-rate = <9600000>;
+
+	qcom,cdc-static-supplies = "cdc-vdda-h",
+				   "cdc-vdd-px",
+				   "cdc-vdd-pa",
+				   "cdc-vdda-cp";
+
+	qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+	qcom,dig-cdc-base-addr = <0xc0f0000>;
+};
+
+Tasha audio CODEC in I2C mode
+
+ - compatible = "qcom,tasha-i2c-pgd";
+ - reg: represents the slave address provided to the I2C driver.
+ - qcom,cdc-reset-gpio: gpio used for codec SOC reset.
+
+ - cdc-vdd-buck-supply: phandle of buck supply's regulator device tree node.
+ - qcom,cdc-vdd-buck-voltage: buck supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-buck-current: buck supply's max current in mA.
+
+ - cdc-buck-sido-supply: phandle of sido supply's regulator device tree node.
+ - qcom,cdc-buck-sido-voltage = sido supply's voltage level min and max in mV.
+ - qcom,cdc-buck-sido-current = sido supply's max current in mA.
+
+ - cdc-vdd-tx-h-supply: phandle of tx-h supply's regulator device tree node.
+ - qcom,cdc-vdd-tx-h-voltage: tx-h supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-tx-h-current: tx-h supply's max current in mA.
+
+ - cdc-vdd-rx-h-supply: phandle of rx-h supply's regulator device tree node.
+ - qcom,cdc-vdd-rx-h-voltage: rx-h supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-rx-h-current: rx-h supply's max current in mA.
+
+ - cdc-vddpx-1-supply: phandle of px-1 supply's regulator device tree node.
+ - qcom,cdc-vddpx-1-voltage: px-1 supply's voltage level min and max in mV.
+ - qcom,cdc-vddpx-1-current: px-1 supply's max current in mA.
+
+ - qcom,cdc-static-supplies: List of supplies to be enabled prior to codec
+			     hardware probe.  Supplies in this list will be
+			     stay enabled.
+
+ - qcom,cdc-micbias1-mv - micbias1 output voltage in milli volts.
+ - qcom,cdc-micbias2-mv - micbias2 output voltage in milli volts.
+ - qcom,cdc-micbias3-mv - micbias3 output voltage in milli volts.
+ - qcom,cdc-micbias4-mv - micbias4 output voltage in milli volts.
+
+ - qcom,cdc-mclk-clk-rate - Specifies the master clock rate in Hz required for
+			    codec.
+
+ - qcom,cdc-dmic-sample-rate - Specifies dmic sample rate.
+ - qcom,cdc-variant - Specifies codec variant.
+ - qcom,wcd9xxx-mic-tristate: For chipsets where I2S TX line is shared between
+			      the Codec and TDM mics, tristate the WCD mics to
+			      avoid PCM interference as the end product uses
+			      only TDM mics.
+
+Example:
+i2c_3: i2c@78B7000 { /* BLSP1 QUP3 */
+	compatible = "qcom,i2c-msm-v2";
+	#address-cells = <1>;
+	#size-cells = <0>;
+	reg-names = "qup_phys_addr";
+	reg = <0x78B7000 0x600>;
+	interrupt-names = "qup_irq";
+	interrupts = <0 97 0>;
+	dmas = <&dma_blsp1 12 64 0x20000020 0x20>,
+		<&dma_blsp1 13 32 0x20000020 0x20>;
+	dma-names = "tx", "rx";
+	qcom,master-id = <86>;
+	qcom,clk-freq-out = <400000>;
+	qcom,clk-freq-in  = <19200000>;
+	clock-names = "iface_clk", "core_clk";
+	clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+		 <&clock_gcc clk_gcc_blsp1_qup3_i2c_apps_clk>;
+	pinctrl-names = "i2c_active", "i2c_sleep";
+	pinctrl-0 = <&i2c_3_active>;
+	pinctrl-1 = <&i2c_3_sleep>;
+	status = "disabled";
+
+	wcd9xxx_codec@d{
+		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,cdc-reset-gpio = <&tlmm_pinmux 90 0>;
+
+		cdc-vdd-buck-supply = <&codec_buck_vreg>;
+		qcom,cdc-vdd-buck-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-buck-current = <650000>;
+
+		cdc-buck-sido-supply = <&codec_buck_vreg>;
+		qcom,cdc-buck-sido-voltage = <1800000 1800000>;
+		qcom,cdc-buck-sido-current = <200000>;
+
+		cdc-vdd-tx-h-supply = <&pmd9650_l6>;
+		qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-tx-h-current = <25000>;
+
+		cdc-vdd-rx-h-supply = <&pmd9650_l6>;
+		qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-rx-h-current = <25000>;
+
+		cdc-vddpx-1-supply = <&pmd9650_l6>;
+		qcom,cdc-vddpx-1-voltage = <1800000 1800000>;
+		qcom,cdc-vddpx-1-current = <10000>;
+
+		qcom,cdc-static-supplies = "cdc-vdd-buck",
+					   "cdc-buck-sido",
+					   "cdc-vdd-tx-h",
+					   "cdc-vdd-rx-h",
+					   "cdc-vddpx-1";
+
+		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 = <12288000>;
+		qcom,cdc-dmic-sample-rate = <4800000>;
+
+		swr_master {
+			compatible = "qcom,swr-wcd";
+			#address-cells = <2>;
+			#size-cells = <0>;
+
+			wsa881x_1: wsa881x@20170212 {
+				compatible = "qcom,wsa881x";
+				reg = <0x00 0x20170212>;
+				qcom,spkr-sd-n-gpio = <&tlmm_pinmux 80 0>;
+
+				cdc-vdd-d-supply = <&pmd9650_l6>;
+				qcom,cdc-vdd-d-voltage = <1800000
+							  1800000>;
+				qcom,cdc-vdd-d-current = <2000>;
+
+				cdc-vdd-a-supply = <&pmd9650_l6>;
+				qcom,cdc-vdd-a-voltage = <1800000
+							  1800000>;
+				qcom,cdc-vdd-a-current = <2000>;
+
+				qcom,cdc-static-supplies = "cdc-vdd-d",
+							   "cdc-vdd-a";
+			};
+		};
+	};
+};
diff --git a/Documentation/devicetree/bindings/sound/wcd-spi.txt b/Documentation/devicetree/bindings/sound/wcd-spi.txt
index 2cd833d..d879544 100644
--- a/Documentation/devicetree/bindings/sound/wcd-spi.txt
+++ b/Documentation/devicetree/bindings/sound/wcd-spi.txt
@@ -35,3 +35,23 @@
 		qcom,mem-base-addr = <0x100000>;
 	};
 };
+
+WCD SPI Accces Control driver support
+
+* wcd_spi_ac
+
+The wcd_spi_ac driver can be added as child device node to the wcd_spi node
+to indicate that the WCD SPI bus needs access control and the access needs
+to be arbitrated with other masters, possibly residing on another processor.
+The wcd-spi driver will parse this node and register platform_device for
+this node.
+
+Required properties:
+
+- compatible : "qcom,wcd-spi-ac"
+
+Example:
+
+wcd_spi_ac {
+	compatible = "qcom,wcd-spi-ac";
+};
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index f56516c..f42fcd4 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -131,7 +131,7 @@
 KBUILD_CFLAGS	+=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
 KBUILD_AFLAGS	+=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
 
-CHECKFLAGS	+= -D__arm__
+CHECKFLAGS	+= -D__arm__ -m32
 
 #Default value
 head-y		:= arch/arm/kernel/head$(MMUEXT).o
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index d9be3c3..b4bc69f 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -4,6 +4,10 @@
 	sdxpoorwills-mtp.dtb \
 	sdxpoorwills-cdp-256.dtb \
 	sdxpoorwills-mtp-256.dtb \
+	sdxpoorwills-dualwifi-cdp.dtb \
+	sdxpoorwills-dualwifi-mtp.dtb \
+	sdxpoorwills-pcie-ep-cdp-256.dtb \
+	sdxpoorwills-pcie-ep-mtp-256.dtb \
 	sdxpoorwills-pcie-ep-cdp.dtb \
 	sdxpoorwills-pcie-ep-mtp.dtb
 
@@ -12,6 +16,9 @@
 	mdm9650-v1.1-nand-mtp.dtb \
 	mdm9650-v1.1-nand-cv2x.dtb
 
+dtb-$(CONFIG_ARCH_MDM9607) += mdm9607-mtp.dtb \
+	mdm9607-ttp.dtb
+
 targets += dtbs
 targets += $(addprefix ../, $(dtb-y))
 
diff --git a/arch/arm/boot/dts/qcom/mdm9607-bus.dtsi b/arch/arm/boot/dts/qcom/mdm9607-bus.dtsi
new file mode 100644
index 0000000..ffb466e
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-bus.dtsi
@@ -0,0 +1,677 @@
+/* Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/msm/msm-bus-ids.h>
+
+&soc {
+	/* Version = 1 */
+	ad_hoc_bus: ad-hoc-bus {
+		compatible = "qcom,msm-bus-device";
+		reg = <0x401000 0x58000>,
+		      <0x500000 0x15080>;
+		reg-names = "bimc-base", "pcnoc-base";
+
+		/* Buses */
+
+		fab_bimc: fab-bimc {
+			cell-id = <MSM_BUS_FAB_BIMC>;
+			label = "fab-bimc";
+			qcom,fab-dev;
+			qcom,base-name = "bimc-base";
+			qcom,bus-type = <2>;
+			qcom,util-fact = <154>;
+			clock-names = "bus_clk", "bus_a_clk";
+			clocks = <&clock_gcc  clk_bimc_msmbus_clk>,
+				<&clock_gcc  clk_bimc_msmbus_a_clk>;
+
+			coresight-id = <203>;
+			coresight-name = "coresight-bimc";
+			coresight-nr-inports = <0>;
+			coresight-outports = <0>;
+			coresight-child-list = <&funnel_in0>;
+			coresight-child-ports = <3>;
+		};
+
+		fab_pcnoc: fab-pcnoc {
+			cell-id = <MSM_BUS_FAB_PERIPH_NOC>;
+			label = "fab-pcnoc";
+			qcom,fab-dev;
+			qcom,base-name = "pcnoc-base";
+			qcom,base-offset = <0x7000>;
+			qcom,qos-off = <0x1000>;
+			qcom,bus-type = <1>;
+			clock-names = "bus_clk", "bus_a_clk";
+			clocks = <&clock_gcc  clk_pcnoc_msmbus_clk>,
+				<&clock_gcc  clk_pcnoc_msmbus_a_clk>;
+
+			coresight-id = <201>;
+			coresight-name = "coresight-pcnoc";
+			coresight-nr-inports = <0>;
+			coresight-outports = <0>;
+			coresight-child-list = <&funnel_in2>;
+			coresight-child-ports = <0>;
+		};
+
+		/* Masters */
+
+		mas_apps_proc: mas-apps-proc {
+			cell-id = <MSM_BUS_MASTER_AMPSS_M0>;
+			label = "mas-apps-proc";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,qport = <0>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = < &slv_bimc_pcnoc &slv_ebi>;
+			qcom,prio-lvl = <0>;
+			qcom,prio-rd = <0>;
+			qcom,prio-wr = <0>;
+			qcom,bus-dev = <&fab_bimc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_APPSS_PROC>;
+		};
+
+		mas_pcnoc_bimc_1: mas-pcnoc-bimc-1 {
+			cell-id = <MSM_BUS_MASTER_PCNOC_BIMC_1>;
+			label = "mas-pcnoc-bimc-1";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&slv_ebi>;
+			qcom,bus-dev = <&fab_bimc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_BIMC_1>;
+		};
+
+		mas_tcu_0: mas-tcu-0 {
+			cell-id = <MSM_BUS_MASTER_TCU_0>;
+			label = "mas-tcu-0";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,qport = <5>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&slv_ebi>;
+			qcom,prio-lvl = <2>;
+			qcom,prio-rd = <2>;
+			qcom,prio-wr = <2>;
+			qcom,bus-dev = <&fab_bimc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_TCU_0>;
+		};
+
+		mas_qdss_bam: mas-qdss-bam {
+			cell-id = <MSM_BUS_MASTER_QDSS_BAM>;
+			label = "mas-qdss-bam";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&qdss_int>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_QDSS_BAM>;
+			qcom,blacklist = <&pcnoc_s_1 &pcnoc_s_2 &pcnoc_s_0
+				 &pcnoc_s_4 &pcnoc_s_5 &pcnoc_s_3 &slv_tcu>;
+		};
+
+		mas_bimc_pcnoc: mas-bimc-pcnoc {
+			cell-id = <MSM_BUS_MASTER_BIMC_PCNOC>;
+			label = "mas-bimc-pcnoc";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&pcnoc_int_0
+				 &pcnoc_int_2 &slv_cats_0>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_BIMC_PCNOC>;
+		};
+
+		mas_qdss_etr: mas-qdss-etr {
+			cell-id = <MSM_BUS_MASTER_QDSS_ETR>;
+			label = "mas-qdss-etr";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&qdss_int>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_QDSS_ETR>;
+			qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2
+					  &pcnoc_s_3 &pcnoc_s_4 &pcnoc_s_5
+					  &slv_crypto_0_cfg &slv_message_ram
+					  &slv_pdm &slv_prng &slv_qdss_stm
+					  &slv_tcu>;
+		};
+
+		mas_audio: mas-audio {
+			cell-id = <MSM_BUS_MASTER_AUDIO>;
+			label = "mas-audio";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&pcnoc_m_0>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_AUDIO>;
+			qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_1
+					 &pcnoc_s_2 &pcnoc_s_3
+					 &pcnoc_s_4 &pcnoc_s_5 &slv_tcu>;
+		};
+
+		mas_qpic: mas-qpic {
+			cell-id = <MSM_BUS_MASTER_QPIC>;
+			label = "mas-qpic";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&pcnoc_m_0>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_QPIC>;
+			qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2
+					  &pcnoc_s_3 &pcnoc_s_4
+					  &pcnoc_s_5 &slv_tcu
+					  &slv_crypto_0_cfg &slv_pdm
+					  &slv_prng &slv_usb2 >;
+		};
+
+		mas_hsic: mas-hsic {
+			cell-id = <MSM_BUS_MASTER_USB_HSIC>;
+			label = "mas-hsic";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&pcnoc_m_0>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_USB_HSIC>;
+		};
+
+		mas_blsp_1: mas-blsp-1 {
+			cell-id = <MSM_BUS_MASTER_BLSP_1>;
+			label = "mas-blsp-1";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&pcnoc_m_1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_BLSP_1>;
+			qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_1
+					 &pcnoc_s_2 &pcnoc_s_3
+					 &pcnoc_s_4 &pcnoc_s_5 &slv_tcu >;
+		};
+
+		mas_usb_hs1: mas-usb-hs1 {
+			cell-id = <MSM_BUS_MASTER_USB_HS>;
+			label = "mas-usb-hs1";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&pcnoc_m_1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_USB_HS1>;
+			qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2 &pcnoc_s_4
+					 &pcnoc_s_5 &slv_tcu
+					 &slv_crypto_0_cfg
+					 &slv_pdm &slv_prng &slv_usb2
+					 &slv_usb_phy> ;
+		};
+
+		mas_crypto: mas-crypto {
+			cell-id = <MSM_BUS_MASTER_CRYPTO>;
+			label = "mas-crypto";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,qport = <0>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&pcnoc_int_3>;
+			qcom,prio1 = <2>;
+			qcom,prio0 = <2>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_CRYPTO>;
+			qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2 &pcnoc_s_3
+					  &pcnoc_s_4 &pcnoc_s_5 &slv_tcu
+					  &slv_crypto_0_cfg &slv_pdm
+					  &slv_usb2 &slv_prng>;
+		};
+
+		mas_sdcc_1: mas-sdcc-1 {
+			cell-id = <MSM_BUS_MASTER_SDCC_1>;
+			label = "mas-sdcc-1";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&pcnoc_int_3>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_SDCC_1>;
+			qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2 &pcnoc_s_3
+					 &pcnoc_s_4 &pcnoc_s_5 &slv_tcu
+					 &slv_crypto_0_cfg &slv_pdm
+					 &slv_usb2 &slv_prng>;
+		};
+
+		mas_sdcc_2: mas-sdcc-2 {
+			cell-id = <MSM_BUS_MASTER_SDCC_2>;
+			label = "mas-sdcc-2";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&pcnoc_int_3>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_SDCC_2>;
+			qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2 &pcnoc_s_3
+					 &pcnoc_s_4 &pcnoc_s_5 &slv_tcu
+					 &slv_crypto_0_cfg &slv_pdm
+					 &slv_usb2 &slv_prng>;
+		};
+
+		mas_xi_usb_hs1: mas-xi-usb-hs1 {
+			cell-id = <MSM_BUS_MASTER_XM_USB_HS1>;
+			label = "mas-xi-usb-hs1";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&slv_pcnoc_bimc_1 &pcnoc_int_2>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_XI_USB_HS1>;
+			qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2 &pcnoc_s_4
+					 &pcnoc_s_5 &slv_tcu &slv_crypto_0_cfg
+					 &slv_pdm &slv_usb2 &slv_prng
+					 &slv_usb_phy>;
+		};
+
+		mas_xi_hsic: mas-xi-hsic {
+			cell-id = <MSM_BUS_MASTER_XI_USB_HSIC>;
+			label = "mas-xi-hsic";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&slv_pcnoc_bimc_1 &pcnoc_int_2>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_XI_HSIC>;
+			qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2
+					 &pcnoc_s_3 &pcnoc_s_4 &pcnoc_s_5
+					 &slv_tcu &slv_crypto_0_cfg
+					 &slv_pdm &slv_usb2 &slv_prng>;
+		};
+
+		mas_sgmii: mas-sgmii {
+			cell-id = <MSM_BUS_MASTER_SGMII>;
+			label = "mas-sgmii";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,qport = <10>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&slv_pcnoc_bimc_1 &pcnoc_int_2>;
+			qcom,prio1 = <1>;
+			qcom,prio0 = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_SGMII>;
+			qcom,blacklist = <&pcnoc_s_0 &pcnoc_s_2 &pcnoc_s_3
+					 &pcnoc_s_4 &pcnoc_s_5 &slv_tcu
+					 &slv_crypto_0_cfg &slv_pdm
+					 &slv_usb2 &slv_prng>;
+		};
+
+		/* Internal nodes */
+
+		pcnoc_m_0: pcnoc-m-0 {
+			cell-id = <MSM_BUS_PNOC_M_0>;
+			label = "pcnoc-m-0";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&slv_pcnoc_bimc_1 &pcnoc_int_2>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_M_0>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_M_0>;
+		};
+
+		pcnoc_m_1: pcnoc-m-1 {
+			cell-id = <MSM_BUS_PNOC_M_1>;
+			label = "pcnoc-m-1";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&slv_pcnoc_bimc_1 &pcnoc_int_2>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_M_1>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_M_1>;
+		};
+
+		qdss_int: qdss-int {
+			cell-id = <MSM_BUS_SNOC_QDSS_INT>;
+			label = "qdss-int";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&pcnoc_int_0 &slv_pcnoc_bimc_1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_QDSS_INT>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_QDSS_INT>;
+		};
+
+		pcnoc_int_0: pcnoc-int-0 {
+			cell-id = <MSM_BUS_PNOC_INT_0>;
+			label = "pcnoc-int-0";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,connections = <&slv_imem &slv_qdss_stm>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_INT_0>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_INT_0>;
+		};
+
+		pcnoc_int_2: pcnoc-int-2 {
+			cell-id = <MSM_BUS_PNOC_INT_2>;
+			label = "pcnoc-int-2";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&pcnoc_s_1 &pcnoc_s_2
+					 &pcnoc_s_0 &pcnoc_s_4
+					 &pcnoc_s_5 &pcnoc_s_3
+					 &slv_tcu >;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_INT_2>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_INT_2>;
+		};
+
+		pcnoc_int_3: pcnoc-int-3 {
+			cell-id = <MSM_BUS_PNOC_INT_3>;
+			label = "pcnoc-int-3";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&slv_pcnoc_bimc_1 &pcnoc_int_2>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_INT_3>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_INT_3>;
+		};
+
+		pcnoc_s_0: pcnoc-s-0 {
+			cell-id = <MSM_BUS_PNOC_SLV_0>;
+			label = "pcnoc-s-0";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&slv_tcsr &slv_sdcc_1 &slv_blsp_1
+				 &slv_sgmii>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_0>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_0>;
+		};
+
+		pcnoc_s_1: pcnoc-s-1 {
+			cell-id = <MSM_BUS_PNOC_SLV_1>;
+			label = "pcnoc-s-1";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&slv_usb2 &slv_crypto_0_cfg
+					 &slv_prng &slv_pdm
+					 &slv_message_ram>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_1>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_1>;
+		};
+
+		pcnoc_s_2: pcnoc-s-2 {
+			cell-id = <MSM_BUS_PNOC_SLV_2>;
+			label = "pcnoc-s-2";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&slv_hsic &slv_sdcc_2 &slv_audio>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_2>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_2>;
+		};
+
+		pcnoc_s_3: pcnoc-s-3 {
+			cell-id = <MSM_BUS_PNOC_SLV_3>;
+			label = "pcnoc-s-3";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,connections = <&slv_usb_phy>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_3>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_3>;
+		};
+
+		pcnoc_s_4: pcnoc-s-4 {
+			cell-id = <MSM_BUS_PNOC_SLV_4>;
+			label = "pcnoc-s-4";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&slv_imem_cfg &slv_pmic_arb>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_4>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_4>;
+		};
+
+		pcnoc_s_5: pcnoc-s-5 {
+			cell-id = <MSM_BUS_PNOC_SLV_5>;
+			label = "pcnoc-s-5";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,connections = <&slv_tlmm>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_5>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_5>;
+		};
+
+		/* Slaves */
+
+		slv_ebi:slv-ebi {
+			cell-id = <MSM_BUS_SLAVE_EBI_CH0>;
+			label = "slv-ebi";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_bimc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_EBI1>;
+		};
+
+		slv_bimc_pcnoc:slv-bimc-pcnoc {
+			cell-id = <MSM_BUS_SLAVE_BIMC_PCNOC>;
+			label = "slv-bimc-pcnoc";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_bimc>;
+			qcom,connections = <&mas_bimc_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_BIMC_PCNOC>;
+		};
+
+		slv_pcnoc_bimc_1:slv-pcnoc-bimc-1 {
+			cell-id = <MSM_BUS_SLAVE_PCNOC_BIMC_1>;
+			label = "slv-pcnoc-bimc-1";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,connections = <&mas_pcnoc_bimc_1>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_BIMC_1>;
+		};
+
+		slv_qdss_stm:slv-qdss-stm {
+			cell-id = <MSM_BUS_SLAVE_QDSS_STM>;
+			label = "slv-qdss-stm";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_QDSS_STM>;
+		};
+
+		slv_cats_0:slv-cats-0 {
+			cell-id = <MSM_BUS_SLAVE_CATS_128>;
+			label = "slv-cats-0";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_CATS_0>;
+		};
+
+		slv_imem:slv-imem {
+			cell-id = <MSM_BUS_SLAVE_SYSTEM_IMEM>;
+			label = "slv-imem";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_IMEM>;
+		};
+
+		slv_tcsr:slv-tcsr {
+			cell-id = <MSM_BUS_SLAVE_TCSR>;
+			label = "slv-tcsr";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_TCSR>;
+		};
+
+		slv_sdcc_1:slv-sdcc-1 {
+			cell-id = <MSM_BUS_SLAVE_SDCC_1>;
+			label = "slv-sdcc-1";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_SDCC_1>;
+		};
+
+		slv_blsp_1:slv-blsp-1 {
+			cell-id = <MSM_BUS_SLAVE_BLSP_1>;
+			label = "slv-blsp-1";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_BLSP_1>;
+		};
+
+		slv_sgmii:slv-sgmii {
+			cell-id = <MSM_BUS_SLAVE_SGMII>;
+			label = "slv-sgmii";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_SGMII>;
+		};
+
+		slv_crypto_0_cfg:slv-crypto-0-cfg {
+			cell-id = <MSM_BUS_SLAVE_CRYPTO_0_CFG>;
+			label = "slv-crypto-0-cfg";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_CRYPTO_0_CFG>;
+		};
+
+		slv_message_ram:slv-message-ram {
+			cell-id = <MSM_BUS_SLAVE_MESSAGE_RAM>;
+			label = "slv-message-ram";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_MESSAGE_RAM>;
+		};
+
+		slv_pdm:slv-pdm {
+			cell-id = <MSM_BUS_SLAVE_PDM>;
+			label = "slv-pdm";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PDM>;
+		};
+
+		slv_prng:slv-prng {
+			cell-id = <MSM_BUS_SLAVE_PRNG>;
+			label = "slv-prng";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PRNG>;
+		};
+
+		slv_usb2:slv-usb2 {
+			cell-id = <MSM_BUS_SLAVE_USB_HS>;
+			label = "slv-usb2";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_USB_HS>;
+		};
+
+		slv_sdcc_2:slv-sdcc-2 {
+			cell-id = <MSM_BUS_SLAVE_SDCC_2>;
+			label = "slv-sdcc-2";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_SDCC_2>;
+		};
+
+		slv_audio:slv-audio {
+			cell-id = <MSM_BUS_SLAVE_AUDIO>;
+			label = "slv-audio";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_AUDIO>;
+		};
+
+		slv_hsic:slv-hsic {
+			cell-id = <MSM_BUS_SLAVE_USB_HSIC>;
+			label = "slv-hsic";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_USB_HSIC>;
+		};
+
+		slv_usb_phy:slv-usb-phy {
+			cell-id = <MSM_BUS_SLAVE_USB_PHYS_CFG>;
+			label = "slv-usb-phy";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_USB_PHY_CFG>;
+		};
+
+		slv_tlmm:slv-tlmm {
+			cell-id = <MSM_BUS_SLAVE_TLMM>;
+			label = "slv-tlmm";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_TLMM>;
+		};
+
+		slv_imem_cfg:slv-imem-cfg {
+			cell-id = <MSM_BUS_SLAVE_IMEM_CFG>;
+			label = "slv-imem-cfg";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_IMEM_CFG>;
+		};
+
+		slv_pmic_arb:slv-pmic-arb {
+			cell-id = <MSM_BUS_SLAVE_PMIC_ARB>;
+			label = "slv-pmic-arb";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PMIC_ARB>;
+		};
+
+		slv_tcu:slv-tcu {
+			cell-id = <MSM_BUS_SLAVE_TCU>;
+			label = "slv-tcu";
+			qcom,buswidth = <8>;
+			qcom,agg-ports = <1>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_TCU>;
+		};
+
+		slv_qipc {
+			cell-id = <MSM_BUS_SLAVE_QPIC>;
+			label = "slv-qpic";
+			qcom,buswidth = <4>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_QPIC>;
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-cdp.dts b/arch/arm/boot/dts/qcom/mdm9607-cdp.dts
new file mode 100644
index 0000000..0133c16
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-cdp.dts
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include "mdm9607-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MDM 9607 CDP";
+	compatible = "qcom,mdm9607-cdp", "qcom,mdm9607", "qcom,cdp";
+	qcom,board-id = <1 0>;
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-cdp.dtsi b/arch/arm/boot/dts/qcom/mdm9607-cdp.dtsi
new file mode 100644
index 0000000..9940f56
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-cdp.dtsi
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "mdm9607.dtsi"
+#include "mdm9607-pinctrl.dtsi"
+#include "mdm9607-display.dtsi"
+#include "qpic-panel-ili-hvga.dtsi"
+
+/ {
+	bluetooth: bt_qca6174 {
+		compatible = "qca,qca6174";
+		qca,bt-reset-gpio = <&pm8019_gpios 2 0>; /* BT_EN */
+		qca,bt-vdd-pa-supply = <&rome_vreg>;
+		qca,bt-vdd-io-supply = <&mdm9607_l11>;
+		qca,bt-vdd-xtal-supply = <&mdm9607_l2>;
+		qca,bt-vdd-io-voltage-level = <1800000 1800000>;
+		qca,bt-vdd-xtal-voltage-level = <1800000 1800000>;
+	};
+};
+
+&soc {
+};
+
+&blsp1_uart5 {
+	status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console_sleep>;
+};
+
+&i2c_4 {
+	status = "ok";
+};
+
+&spi_1 {
+	status = "ok";
+};
+
+&blsp1_uart3 {
+	status = "ok";
+};
+
+&qnand_1 {
+	status = "ok";
+};
+
+&emac0 {
+	status = "ok";
+};
+
+/* MPP pin 2 configs for SMB358 interrupt line */
+&pm8019_mpps {
+	mpp@a100 {
+		qcom,mode = <0>;	/* Digital input */
+		qcom,vin-sel = <3>;	/* 1.8V (L11) */
+		qcom,src-sel = <0>;	/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,pull = <2>;	/* PULL UP 10KOHM */
+		qcom,master-en = <1>;
+	};
+};
+
+&pm8019_gpios {
+	gpio@c100 { /* BT_EN */
+		qcom,mode = <1>;         /* Digital output*/
+		qcom,pull = <4>;         /* Pulldown 10uA */
+		qcom,vin-sel = <2>;      /* VIN2 */
+		qcom,src-sel = <0>;      /* GPIO */
+		qcom,invert = <0>;       /* Invert */
+		qcom,master-en = <1>;    /* Enable GPIO */
+		status = "ok";
+	};
+
+	/* PMIC gpio for wlan power supply */
+	gpio@c200 {
+		qcom,mode = <1>;		/* Digital output */
+		qcom,output-type = <0>;		/* CMOS logic */
+		qcom,invert = <1>;		/* Output high */
+		qcom,vin-sel = <3>;		/* VPH_PWR */
+		qcom,src-sel = <0>;		/* Constant */
+		qcom,out-strength = <1>;	/* High drive strength */
+		qcom,master-en = <1>;		/* Enable GPIO */
+		status = "okay";
+	};
+
+	/* ROME 32k Sleep Clock */
+	gpio@c500 {
+		qcom,mode = <1>;               /* Digital output */
+		qcom,output-type = <0>;        /* CMOS logic */
+		qcom,invert = <0>;             /* no inversion */
+		qcom,vin-sel = <2>;            /* VIN 2 */
+		qcom,src-sel = <2>;            /* Function 2 */
+		qcom,out-strength = <2>;       /* Medium */
+		qcom,master-en = <1>;          /* Enable GPIO */
+		status = "ok";
+	};
+};
+
+/* MPP pin 4 configs for SGMII */
+&pm8019_mpps {
+	mpp@a300 { /* MPP 4 */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,vin-sel = <2>;		/* 1.8V */
+		qcom,src-sel = <0>;		/* Constant */
+		qcom,master-en = <1>;		/* Enable GPIO */
+		status = "okay";
+	};
+};
+
+&sdhc_1 {
+	vdd-io-supply = <&mdm9607_l11>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <0 30000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&pmx_sdc1_clk_on &pmx_sdc1_cmd_on &pmx_sdc1_data_on
+						&sdc1_wlan_gpio_active>;
+	pinctrl-1 = <&pmx_sdc1_clk_off &pmx_sdc1_cmd_off &pmx_sdc1_data_off
+						&sdc1_wlan_gpio_sleep>;
+	qcom,nonremovable;
+	qcom,core_3_0v_support;
+	status = "ok";
+};
+
+&hsic {
+	status = "ok";
+};
+
+&android_usb_hsic {
+	status = "ok";
+};
+
+&sdhc_2 {
+	vdd-supply = <&sdcard_ext_vreg>;
+	qcom,vdd-voltage-level = <2850000 2850000>;
+	qcom,vdd-current-level = <15000 400000>;
+
+	vdd-io-supply = <&mdm9607_l13>;
+	qcom,vdd-io-voltage-level = <1800000 2850000>;
+	qcom,vdd-io-current-level = <200 50000>;
+
+	#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_pinmux 26 0>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&tlmm_pinmux 26 0x1>;
+
+	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>;
+
+	status = "disabled";
+};
+
+/* Display */
+&mdss_qpic {
+	pinctrl-names= "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_ldo_active &mdss_cs_active &mdss_te_active
+		&mdss_rs_active &mdss_ad_active &mdss_bl_active>;
+	pinctrl-1 = <&mdss_ldo_sleep &mdss_cs_sleep &mdss_te_sleep
+		&mdss_rs_sleep &mdss_ad_sleep &mdss_bl_sleep>;
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-coresight.dtsi b/arch/arm/boot/dts/qcom/mdm9607-coresight.dtsi
new file mode 100644
index 0000000..fd35177
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-coresight.dtsi
@@ -0,0 +1,462 @@
+/*
+ * 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.
+ */
+
+&soc {
+	tmc_etr: tmc@6026000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0x6026000 0x1000>,
+		      <0x6084000 0x15000>;
+		reg-names = "tmc-base", "bam-base";
+		interrupts = <0 166 0>;
+		interrupt-names = "byte-cntr-irq";
+
+		qcom,memory-size = <0x100000>;
+		qcom,sg-enable;
+
+		coresight-id = <0>;
+		coresight-name = "coresight-tmc-etr";
+		coresight-nr-inports = <1>;
+		coresight-ctis = <&cti0 &cti8>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	tpiu: tpiu@6020000 {
+		compatible = "arm,coresight-tpiu";
+		reg = <0x6020000 0x1000>,
+		      <0x1100000 0xb0000>;
+		reg-names = "tpiu-base", "nidnt-base";
+
+		coresight-id = <1>;
+		coresight-name = "coresight-tpiu";
+		coresight-nr-inports = <1>;
+
+		pinctrl-names = "sdcard", "trace", "swduart",
+				"swdtrc", "jtag", "spmi";
+		/* NIDnT */
+		pinctrl-0 = <&qdsd_clk_sdcard &qdsd_cmd_sdcard
+			     &qdsd_data0_sdcard &qdsd_data1_sdcard
+			     &qdsd_data2_sdcard &qdsd_data3_sdcard>;
+		pinctrl-1 = <&qdsd_clk_trace &qdsd_cmd_trace
+			     &qdsd_data0_trace &qdsd_data1_trace
+			     &qdsd_data2_trace &qdsd_data3_trace>;
+		pinctrl-2 = <&qdsd_cmd_swduart &qdsd_data0_swduart
+			     &qdsd_data1_swduart &qdsd_data2_swduart
+			     &qdsd_data3_swduart>;
+		pinctrl-3 = <&qdsd_clk_swdtrc &qdsd_cmd_swdtrc
+			     &qdsd_data0_swdtrc &qdsd_data1_swdtrc
+			     &qdsd_data2_swdtrc &qdsd_data3_swdtrc>;
+		pinctrl-4 = <&qdsd_cmd_jtag &qdsd_data0_jtag
+			     &qdsd_data1_jtag &qdsd_data2_jtag
+			     &qdsd_data3_jtag>;
+		pinctrl-5 = <&qdsd_clk_spmi &qdsd_cmd_spmi
+			     &qdsd_data0_spmi &qdsd_data3_spmi>;
+
+		qcom,nidnthw;
+		qcom,nidnt-swduart;
+		qcom,nidnt-swdtrc;
+		qcom,nidnt-jtag;
+		qcom,nidnt-spmi;
+		nidnt-gpio = <26>;
+		nidnt-gpio-polarity = <1>;
+
+		interrupts = <0 82 0>;
+		interrupt-names = "nidnt-irq";
+
+		vdd-supply = <&sdcard_ext_vreg>;
+		qcom,vdd-voltage-level = <2850000 2850000>;
+		qcom,vdd-current-level = <15 400000>;
+
+		vdd-io-supply = <&mdm9607_l13>;
+		qcom,vdd-io-voltage-level = <1800000 2950000>;
+		qcom,vdd-io-current-level = <200 300000>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	replicator: replicator@6024000 {
+		compatible = "qcom,coresight-replicator";
+		reg = <0x6024000 0x1000>;
+		reg-names = "replicator-base";
+
+		coresight-id = <2>;
+		coresight-name = "coresight-replicator";
+		coresight-nr-inports = <1>;
+		coresight-outports = <0 1>;
+		coresight-child-list = <&tmc_etr &tpiu>;
+		coresight-child-ports = <0 0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	tmc_etf: tmc@6025000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0x6025000 0x1000>;
+		reg-names = "tmc-base";
+
+		coresight-id = <3>;
+		coresight-name = "coresight-tmc-etf";
+		coresight-nr-inports = <1>;
+		coresight-outports = <0>;
+		coresight-child-list = <&replicator>;
+		coresight-child-ports = <0>;
+		coresight-default-sink;
+		coresight-ctis = <&cti0 &cti8>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	funnel_in0: funnel@6021000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0x6021000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <4>;
+		coresight-name = "coresight-funnel-in0";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&tmc_etf>;
+		coresight-child-ports = <0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	funnel_in2: funnel@6068000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0x6068000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <5>;
+		coresight-name = "coresight-funnel-in2";
+		coresight-nr-inports = <2>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <6>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti0: cti@6010000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x6010000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <6>;
+		coresight-name = "coresight-cti0";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti1: cti@6011000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x6011000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <7>;
+		coresight-name = "coresight-cti1";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti2: cti@6012000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x6012000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <8>;
+		coresight-name = "coresight-cti2";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti3: cti@6013000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x6013000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <9>;
+		coresight-name = "coresight-cti3";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti4: cti@6014000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x6014000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <10>;
+		coresight-name = "coresight-cti4";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti5: cti@6015000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x6015000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <11>;
+		coresight-name = "coresight-cti5";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti6: cti@6016000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x6016000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <12>;
+		coresight-name = "coresight-cti6";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti7: cti@6017000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x6017000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <13>;
+		coresight-name = "coresight-cti7";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti8: cti@6018000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x6018000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <14>;
+		coresight-name = "coresight-cti8";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti_cpu0: cti@6043000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x6043000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <15>;
+		coresight-name = "coresight-cti-cpu0";
+		coresight-nr-inports = <0>;
+		coresight-cti-cpu = <&CPU0>;
+
+		qcom,cti-save;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti_rpm_cpu0: cti@603c000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x603c000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <16>;
+		coresight-name = "coresight-cti-rpm-cpu0";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti_modem_cpu0: cti@6038000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x6038000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <17>;
+		coresight-name = "coresight-cti-modem-cpu0";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	stm: stm@6002000 {
+		compatible = "arm,coresight-stm";
+		reg = <0x6002000 0x1000>,
+		      <0x9280000 0x180000>;
+		reg-names = "stm-base", "stm-data-base";
+
+		coresight-id = <18>;
+		coresight-name = "coresight-stm";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <7>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	csr: csr@6001000 {
+		compatible = "qcom,coresight-csr";
+		reg = <0x6001000 0x1000>;
+		reg-names = "csr-base";
+
+		coresight-id = <19>;
+		coresight-name = "coresight-csr";
+		coresight-nr-inports = <0>;
+
+		qcom,blk-size = <1>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	etm0: etm@6042000 {
+		compatible = "arm,coresight-etm";
+		reg = <0x6042000 0x1000>;
+		reg-names = "etm-base";
+
+		coresight-id = <20>;
+		coresight-name = "coresight-etm0";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <4>;
+		coresight-etm-cpu = <&CPU0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	hwevent: hwevent@606c000 {
+		compatible = "qcom,coresight-hwevent";
+		reg = <0x606c000 0x148>,
+		      <0x606cfb0 0x4>,
+		      <0x78640cc 0x4>,
+		      <0x78240cc 0x4>,
+		      <0x7885010 0x4>,
+		      <0x200c004 0x4>,
+		      <0x78d90a0 0x4>;
+		reg-names = "wrapper-mux", "wrapper-lockaccess",
+			    "wrapper-sdcc2", "wrapper-sdcc1",
+			    "blsp-mux", "spmi-mux" ,"usb-mux";
+
+		coresight-id = <21>;
+		coresight-name = "coresight-hwevent";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	rpm_etm0 {
+		compatible = "qcom,coresight-remote-etm";
+
+		coresight-id = <22>;
+		coresight-name = "coresight-rpm-etm0";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <0>;
+
+		qcom,inst-id = <4>;
+	};
+
+	modem_etm0 {
+		compatible = "qcom,coresight-remote-etm";
+
+		coresight-id = <23>;
+		coresight-name = "coresight-modem-etm0";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <2>;
+
+		qcom,inst-id = <2>;
+	};
+
+	fuse: fuse@a601c {
+		compatible = "arm,coresight-fuse-v2";
+		reg = <0xa601c 0x8>;
+		reg-names = "fuse-base";
+
+		coresight-id = <24>;
+		coresight-name = "coresight-fuse";
+		coresight-nr-inports = <0>;
+	};
+
+	dbgui: dbgui@606d000 {
+		compatible = "qcom,coresight-dbgui";
+		reg = <0x606d000 0x1000>;
+		reg-names = "dbgui-base";
+
+		coresight-id = <25>;
+		coresight-name = "coresight-dbgui";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in2>;
+		coresight-child-ports = <1>;
+
+		qcom,dbgui-addr-offset = <0x30>;
+		qcom,dbgui-data-offset = <0xB0>;
+		qcom,dbgui-size = <32>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-display.dtsi b/arch/arm/boot/dts/qcom/mdm9607-display.dtsi
new file mode 100644
index 0000000..fd7f5ef
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-display.dtsi
@@ -0,0 +1,36 @@
+/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	mdss_qpic: qcom,msm_qpic@7980000 {
+		compatible = "qcom,mdss_qpic";
+		reg = <0x7980000 0x24000>;
+		reg-names = "qpic_base";
+		interrupts = <0 251 0>;
+
+		qcom,msm-bus,name = "mdss_qpic";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+
+		qcom,msm-bus,vectors-KBps =
+			<91 512 0 0>,
+			/* Voting for max b/w on PNOC bus for now */
+			<91 512 400000 800000>;
+
+		vdd-supply = <&mdm9607_l11>;
+
+		clock-names = "core_clk", "core_a_clk";
+		clocks = <&clock_gcc clk_qpic_clk>,
+			<&clock_gcc clk_qpic_a_clk>;
+
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-ion.dtsi b/arch/arm/boot/dts/qcom/mdm9607-ion.dtsi
new file mode 100644
index 0000000..6da25c2
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-ion.dtsi
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015, 2017, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	qcom,ion {
+		compatible = "qcom,msm-ion";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,ion-heap@25 {
+			reg = <25>;
+			qcom,ion-heap-type = "SYSTEM";
+		};
+
+		qcom,ion-heap@28 { /* AUDIO HEAP */
+			reg = <28>;
+			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";
+		};
+
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-mtp-sdcard.dts b/arch/arm/boot/dts/qcom/mdm9607-mtp-sdcard.dts
new file mode 100644
index 0000000..0cc1783
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-mtp-sdcard.dts
@@ -0,0 +1,56 @@
+/*
+ * 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
+ * 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 "mdm9607-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MDM 9607 MTP SDCARD";
+	compatible = "qcom,mdm9607-mtp", "qcom,mdm9607", "qcom,mtp";
+	qcom,board-id = <8 1>;
+};
+
+&sdhc_2 {
+	/delete-property/cd-gpios;
+
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-lpm-sup;
+
+	#address-cells = <0>;
+	interrupt-parent = <&sdhc_2>;
+	interrupts = <0 1>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 221 0>;
+	interrupt-names = "hc_irq", "pwr_irq";
+
+	pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on>;
+
+	qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+	qcom,nonremovable;
+	status = "ok";
+};
+
+&pm8019_gpios {
+	gpio@c300 { /* GPIO 4 */
+		qcom,mode = <1>;		/* Digital Output */
+		qcom,output-type = <0>;		/* CMOS Logic */
+		qcom,invert = <0>;		/* Output High */
+		qcom,vin-sel = <0>;		/* VPH_PWR */
+		qcom,src-sel = <0>;		/* GPIO */
+		qcom,out-strength = <1>;	/* Low Drive Strength */
+		qcom,master-en = <1>;		/* Enable GPIO */
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-mtp.dts b/arch/arm/boot/dts/qcom/mdm9607-mtp.dts
new file mode 100644
index 0000000..5334444
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-mtp.dts
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include "mdm9607-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MDM 9607 MTP";
+	compatible = "qcom,mdm9607-mtp", "qcom,mdm9607", "qcom,mtp";
+	qcom,board-id = <8 0>;
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi b/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi
new file mode 100644
index 0000000..df09bdf
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-mtp.dtsi
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "mdm9607.dtsi"
+#include "mdm9607-pinctrl.dtsi"
+#include "mdm9607-display.dtsi"
+#include "qpic-panel-ili-hvga.dtsi"
+
+/ {
+	bluetooth: bt_qca6174 {
+		compatible = "qca,qca6174";
+		qca,bt-reset-gpio = <&pm8019_gpios 2 0>; /* BT_EN */
+		qca,bt-vdd-pa-supply = <&rome_vreg>;
+		qca,bt-vdd-io-supply = <&mdm9607_l11>;
+		qca,bt-vdd-xtal-supply = <&mdm9607_l2>;
+		qca,bt-vdd-io-voltage-level = <1800000 1800000>;
+		qca,bt-vdd-xtal-voltage-level = <1800000 1800000>;
+	};
+};
+
+&blsp1_uart5 {
+	status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console_sleep>;
+};
+
+&i2c_4 {
+	status = "ok";
+};
+
+&blsp1_uart3 {
+	status = "ok";
+};
+
+&qnand_1 {
+	status = "ok";
+};
+
+/* MPP pin 2 configs for SMB358 interrupt line */
+&pm8019_mpps {
+	mpp@a100 {
+		qcom,mode = <0>;	/* Digital input */
+		qcom,vin-sel = <3>;	/* 1.8V (L11) */
+		qcom,src-sel = <0>;	/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,pull = <2>;	/* PULL UP 10KOHM */
+		qcom,master-en = <1>;
+	};
+};
+
+&pm8019_gpios {
+	gpio@c100 { /* BT_EN */
+		qcom,mode = <1>;         /* Digital output*/
+		qcom,pull = <4>;         /* Pulldown 10uA */
+		qcom,vin-sel = <2>;      /* VIN2 */
+		qcom,src-sel = <0>;      /* GPIO */
+		qcom,invert = <0>;       /* Invert */
+		qcom,master-en = <1>;    /* Enable GPIO */
+		status = "ok";
+	};
+
+	/* PMIC gpio for wlan power supply */
+	gpio@c200 {
+		qcom,mode = <1>;		/* Digital output */
+		qcom,output-type = <0>;		/* CMOS logic */
+		qcom,invert = <1>;		/* Output high */
+		qcom,vin-sel = <3>;		/* VPH_PWR */
+		qcom,src-sel = <0>;		/* Constant */
+		qcom,out-strength = <1>;	/* High drive strength */
+		qcom,master-en = <1>;		/* Enable GPIO */
+		status = "okay";
+	};
+
+	/* ROME 32k Sleep Clock */
+	gpio@c500 {
+		qcom,mode = <1>;               /* Digital output */
+		qcom,output-type = <0>;        /* CMOS logic */
+		qcom,invert = <0>;             /* no inversion */
+		qcom,vin-sel = <2>;            /* VIN 2 */
+		qcom,src-sel = <2>;            /* Function 2 */
+		qcom,out-strength = <2>;       /* Medium */
+		qcom,master-en = <1>;          /* Enable GPIO */
+		status = "ok";
+	};
+};
+
+&sdhc_1 {
+	vdd-io-supply = <&mdm9607_l11>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <0 30000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&pmx_sdc1_clk_on &pmx_sdc1_cmd_on &pmx_sdc1_data_on
+						&sdc1_wlan_gpio_active>;
+	pinctrl-1 = <&pmx_sdc1_clk_off &pmx_sdc1_cmd_off &pmx_sdc1_data_off
+						&sdc1_wlan_gpio_sleep>;
+	qcom,nonremovable;
+	qcom,core_3_0v_support;
+	status = "ok";
+};
+
+/* MPP pin 4 configs for SGMII */
+&pm8019_mpps {
+	mpp@a300 { /* MPP 4 */
+		qcom,mode = <1>;		/* Digital output */
+		qcom,vin-sel = <2>;		/* 1.8V */
+		qcom,src-sel = <0>;		/* Constant */
+		qcom,master-en = <1>;		/* Enable GPIO */
+		status = "okay";
+	};
+};
+
+&sdhc_2 {
+	vdd-supply = <&sdcard_ext_vreg>;
+	qcom,vdd-voltage-level = <2850000 2850000>;
+	qcom,vdd-current-level = <15000 400000>;
+
+	vdd-io-supply = <&mdm9607_l13>;
+	qcom,vdd-io-voltage-level = <1800000 2850000>;
+	qcom,vdd-io-current-level = <200 50000>;
+
+	#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_pinmux 26 0>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&tlmm_pinmux 26 0x1>;
+
+	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>;
+
+	status = "disabled";
+};
+
+/* Display */
+&mdss_qpic {
+	pinctrl-names= "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_ldo_active &mdss_cs_active &mdss_te_active
+		&mdss_rs_active &mdss_ad_active &mdss_bl_active>;
+	pinctrl-1 = <&mdss_ldo_sleep &mdss_cs_sleep &mdss_te_sleep
+		&mdss_rs_sleep &mdss_ad_sleep &mdss_bl_sleep>;
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi b/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi
new file mode 100644
index 0000000..670667d
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-pinctrl.dtsi
@@ -0,0 +1,1159 @@
+/*
+ * 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.
+ */
+
+&soc {
+	tlmm_pinmux: pinctrl@1000000 {
+		compatible = "qcom,mdm9607-pinctrl";
+		reg = <0x1000000 0x300000>;
+		interrupts = <0 208 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		qcom,tlmm-emmc-boot-select = <0x1>;
+
+		uart_console_sleep: uart_console_sleep {
+			mux {
+				pins = "gpio8", "gpio9";
+				function = "blsp_uart5";
+			};
+			config {
+				pins = "gpio8", "gpio9";
+				drive-strength = <2>;
+				bias-pull-down;
+			};
+		};
+
+		blsp1_uart3_active: blsp1_uart3_active {
+			mux {
+				pins = "gpio0", "gpio1", "gpio2", "gpio3";
+				function = "blsp_uart3";
+			};
+
+			config {
+				pins = "gpio0", "gpio1", "gpio2", "gpio3";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		blsp1_uart3_sleep: blsp1_uart3_sleep {
+			mux {
+				pins = "gpio0", "gpio1", "gpio2", "gpio3";
+				function = "gpio";
+			};
+
+
+			config {
+				pins = "gpio0", "gpio1", "gpio2", "gpio3";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		spi1 {
+
+			spi1_default: spi1_default {
+				/* active state */
+				mux {
+					/* MOSI, MISO, CLK */
+					pins = "gpio4", "gpio5", "gpio7";
+					function = "blsp_spi2";
+				};
+
+				config {
+					pins = "gpio4", "gpio5", "gpio7";
+					drive-strength = <12>; /* 12 MA */
+					bias-disable = <0>; /* No PULL */
+				};
+			};
+
+
+			spi1_sleep: spi1_sleep {
+				/* suspended state */
+				mux {
+					/* MOSI, MISO, CLK */
+					pins = "gpio4", "gpio5", "gpio7";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio4", "gpio5", "gpio7";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-down; /* PULL Down */
+				};
+			};
+
+			spi1_cs0_active: cs0_active {
+				/* CS */
+				mux {
+					pins = "gpio6";
+					function = "blsp_spi2";
+				};
+
+				config {
+					pins = "gpio6";
+					drive-strength = <2>;
+					bias-disable = <0>;
+				};
+			};
+
+			spi1_cs0_sleep: cs0_sleep {
+				/* CS */
+				mux {
+					pins = "gpio6";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio6";
+					drive-strength = <2>;
+					bias-disable = <0>;
+				};
+			};
+		};
+
+	/* SDC pin type */
+
+	pmx_sdc1_cmd {
+		pmx_sdc1_cmd_on: pmx_sdc1_cmd_on {
+			 config {
+				pins  = "sdc1_cmd";
+				drive-strength = <10>;
+				bias-pull-up;
+			 };
+		 };
+
+		pmx_sdc1_cmd_off: pmx_sdc1_cmd_off {
+			 config {
+				pins = "sdc1_cmd";
+				bias-pull-up;
+				drive-strength = <2>;
+			};
+		};
+	 };
+
+	 pmx_sdc1_clk {
+		pmx_sdc1_clk_on: pmx_sdc1_clk_on {
+			 config {
+				pins = "sdc1_clk";
+				drive-strength = <16>;
+				bias-disable;
+			};
+		 };
+
+		pmx_sdc1_clk_off: pmx_sdc1_clk_off {
+			  config {
+				pins = "sdc1_clk";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+	 };
+
+	 pmx_sdc1_data {
+		pmx_sdc1_data_on: pmx_sdc1_data_on {
+			  config {
+				pins = "sdc1_data";
+				bias-pull-up;
+				drive-strength = <10>;
+			};
+		};
+
+		pmx_sdc1_data_off: pmx_sdc1_data_off {
+			config {
+				pins = "sdc1_data";
+				bias-pull-up;
+				drive-strength = <2>;
+			};
+		};
+	};
+
+	sdc1_wlan_gpio {
+		sdc1_wlan_gpio_active: sdc1_wlan_gpio_active {
+			mux {
+				pins = "gpio38";
+				function  = "gpio";
+			};
+			config {
+				pins  = "gpio38";
+				output-high;
+				drive-strength = <8>;
+				bias-pull-up;
+			};
+		};
+
+		sdc1_wlan_gpio_sleep: sdc1_wlan_gpio_sleep {
+			mux {
+				pins = "gpio38";
+				function  = "gpio";
+			};
+			config {
+				pins  = "gpio38";
+				drive-strength = <2>;
+				bias-disable;
+				output-low;
+			};
+		};
+	};
+
+		i2c_4 {
+			i2c_4_active: i2c_4_active {
+				/* active state */
+				mux {
+					pins = "gpio18", "gpio19";
+					function = "blsp_i2c4";
+				};
+				config {
+					pins = "gpio18", "gpio19";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			i2c_4_sleep: i2c_4_sleep {
+				/* suspended state */
+				mux {
+					pins = "gpio18", "gpio19";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio18", "gpio19";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
+		bmi160_int1_default: bmi160_int1_default {
+			mux {
+				pins = "gpio78";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio78";
+				drive-strength = <16>; /* 16 mA */
+				bias-pull-down; /* pull down */
+			};
+		};
+
+		bmi160_int2_default: bmi160_int2_default {
+			mux {
+				pins = "gpio79";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio79";
+				drive-strength = <16>; /* 16 mA */
+				bias-pull-down; /* pull down */
+			};
+		};
+
+		codec_reset {
+			codec_reset_active: codec_reset_active {
+				mux {
+					pins = "gpio26";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio26";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+					output-high;
+				};
+			};
+			codec_reset_sleep: codec_reset_sleep {
+				mux {
+					pins = "gpio26";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio26";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;	        /* PULL DOWN */
+				};
+			};
+		};
+
+
+		pmx_pri_mi2s_aux {
+			pri_ws_active_master: pri_ws_active_master {
+				mux {
+					pins = "gpio20";
+					function = "pri_mi2s_ws_a";
+				};
+
+				config {
+					pins = "gpio20";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+					output-high;
+				};
+			};
+
+			pri_sck_active_master: pri_sck_active_master {
+				mux {
+					pins = "gpio23";
+					function = "pri_mi2s_sck_a";
+				};
+
+				config {
+					pins = "gpio23";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+					output-high;
+				};
+			};
+
+			pri_ws_active_slave: pri_ws_active_slave {
+				mux {
+					pins = "gpio20";
+					function = "pri_mi2s_ws_a";
+				};
+
+				config {
+					pins = "gpio20";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+				};
+			};
+
+			pri_sck_active_slave: pri_sck_active_slave {
+				mux {
+					pins = "gpio23";
+					function = "pri_mi2s_sck_a";
+				};
+
+				config {
+					pins = "gpio23";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+				};
+			};
+
+			pri_dout_active: pri_dout_active {
+				mux {
+					pins = "gpio22";
+					function = "pri_mi2s_data1_a";
+				};
+
+				config {
+					pins = "gpio22";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+					output-high;
+				};
+			};
+
+			pri_ws_sleep: pri_ws_sleep {
+				mux {
+					pins = "gpio20";
+					function = "pri_mi2s_ws_a";
+				};
+
+				config {
+					pins = "gpio20";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;	        /* PULL DOWN */
+				};
+			};
+
+			pri_sck_sleep: pri_sck_sleep {
+				mux {
+					pins = "gpio23";
+					function = "pri_mi2s_sck_a";
+				};
+
+				config {
+					pins = "gpio23";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;	        /* PULL DOWN */
+				};
+			};
+
+			pri_dout_sleep: pri_dout_sleep {
+				mux {
+					pins = "gpio22";
+					function = "pri_mi2s_data1_a";
+				};
+
+				config {
+					pins = "gpio22";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;	        /* PULL DOWN */
+				};
+			};
+		};
+
+		pmx_pri_mi2s_aux_din {
+				pri_din_active: pri_din_active {
+				mux {
+					pins = "gpio21";
+					function = "pri_mi2s_data0_a";
+				};
+
+				config {
+					pins = "gpio21";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;	        /* No PULL */
+				};
+			};
+
+			pri_din_sleep: pri_din_sleep {
+				mux {
+					pins = "gpio21";
+					function = "pri_mi2s_data0_a";
+				};
+
+				config {
+					pins = "gpio21";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;	        /* PULL DOWN */
+				};
+			};
+		};
+
+		pmx_sec_mi2s_aux {
+			sec_ws_active_master: sec_ws_active_master {
+				mux {
+					pins = "gpio79";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio79";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+					output-high;
+				};
+			};
+
+			sec_sck_active_master: sec_sck_active_master {
+				mux {
+					pins = "gpio78";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio78";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+					output-high;
+				};
+			};
+
+			sec_ws_active_slave: sec_ws_active_slave {
+				mux {
+					pins = "gpio79";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio79";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+				};
+			};
+
+			sec_sck_active_slave: sec_sck_active_slave {
+				mux {
+					pins = "gpio78";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio78";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+				};
+			};
+
+			sec_dout_active: sec_dout_active {
+				mux {
+					pins = "gpio77";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio77";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+					output-high;
+				};
+			};
+
+			sec_ws_sleep: sec_ws_sleep {
+				mux {
+					pins = "gpio79";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio79";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;	        /* PULL DOWN */
+				};
+			};
+
+			sec_sck_sleep: sec_sck_sleep {
+				mux {
+					pins = "gpio78";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio78";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;	        /* PULL DOWN */
+				};
+			};
+
+			sec_dout_sleep: sec_dout_sleep {
+				mux {
+					pins = "gpio77";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio77";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;	        /* PULL DOWN */
+				};
+			};
+		};
+
+		pmx_sec_mi2s_aux_din {
+			sec_din_active: sec_din_active {
+				mux {
+					pins = "gpio76";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio76";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;	        /* No PULL */
+				};
+			};
+
+			sec_din_sleep: sec_din_sleep {
+				mux {
+					pins = "gpio76";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio76";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;	        /* PULL DOWN */
+				};
+			};
+		};
+
+		pmx_qdsd_clk {
+			qdsd_clk_sdcard: clk_sdcard {
+				config {
+					pins = "qdsd_clk";
+					bias-disable; /* NO pull */
+					drive-strength = <16>; /* 16 MA */
+				};
+			};
+			qdsd_clk_trace: clk_trace {
+				config {
+					pins = "qdsd_clk";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_clk_swdtrc: clk_swdtrc {
+				config {
+					pins = "qdsd_clk";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_clk_spmi: clk_spmi {
+				config {
+					pins = "qdsd_clk";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_qdsd_cmd {
+			qdsd_cmd_sdcard: cmd_sdcard {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_cmd_trace: cmd_trace {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_cmd_swduart: cmd_uart {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_cmd_swdtrc: cmd_swdtrc {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_cmd_jtag: cmd_jtag {
+				config {
+					pins = "qdsd_cmd";
+					bias-disable; /* NO pull */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_cmd_spmi: cmd_spmi {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-down; /* pull down */
+					drive-strength = <10>; /* 10 MA */
+				};
+			};
+		};
+
+		pmx_qdsd_data0 {
+			qdsd_data0_sdcard: data0_sdcard {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data0_trace: data0_trace {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data0_swduart: data0_uart {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data0_swdtrc: data0_swdtrc {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data0_jtag: data0_jtag {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data0_spmi: data0_spmi {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_qdsd_data1 {
+			qdsd_data1_sdcard: data1_sdcard {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data1_trace: data1_trace {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data1_swduart: data1_uart {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data1_swdtrc: data1_swdtrc {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data1_jtag: data1_jtag {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_qdsd_data2 {
+			qdsd_data2_sdcard: data2_sdcard {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data2_trace: data2_trace {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data2_swduart: data2_uart {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data2_swdtrc: data2_swdtrc {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data2_jtag: data2_jtag {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-up; /* pull up */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+		};
+
+		pmx_qdsd_data3 {
+			qdsd_data3_sdcard: data3_sdcard {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data3_trace: data3_trace {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data3_swduart: data3_uart {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data3_swdtrc: data3_swdtrc {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data3_jtag: data3_jtag {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data3_spmi: data3_spmi {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+		};
+
+		pmx_sdc2_clk {
+			sdc2_clk_on: sdc2_clk_on {
+				config {
+					pins = "sdc2_clk";
+					drive-strength = <16>; /* 16 MA */
+					bias-disable; /* NO pull */
+				};
+			};
+			sdc2_clk_off: sdc2_clk_off {
+				config {
+					pins = "sdc2_clk";
+					bias-disable; /* NO pull */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_sdc2_cmd {
+			sdc2_cmd_on: sdc2_cmd_on {
+				config {
+					pins = "sdc2_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <10>; /* 10 MA */
+				};
+			};
+			sdc2_cmd_off: sdc2_cmd_off {
+				config {
+					pins = "sdc2_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+		      };
+		};
+
+		pmx_sdc2_data {
+			sdc2_data_on: sdc2_data_on {
+				config {
+					pins = "sdc2_data";
+					bias-pull-up; /* pull up */
+					drive-strength = <10>; /* 10 MA */
+				};
+			};
+			sdc2_data_off: sdc2_data_off {
+			       config {
+				       pins = "sdc2_data";
+				       bias-pull-up; /* pull up */
+				       drive-strength = <2>; /* 2 MA */
+			       };
+			};
+		};
+
+		sdhc2_cd_pin {
+			sdc2_cd_on: cd_on {
+			    mux {
+				    pins = "gpio26";
+				    function = "gpio";
+			    };
+			    config {
+				    pins = "gpio26";
+				    drive-strength = <2>;
+				    bias-pull-up;
+			    };
+			};
+			sdc2_cd_off: cd_off {
+				mux {
+					pins = "gpio26";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio26";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		emac0 {
+			emac0_mdio_active: emac0_mdio_active {
+				/* active state */
+				mux {
+					/* MDC MDIO */
+					pins = "gpio27", "gpio28";
+					function = "gmac_mdio";
+				};
+
+				config {
+					pins = "gpio27", "gpio28";
+					drive-strength = <16>; /* 16 MA */
+					bias-pull-up;
+				};
+			};
+
+			emac0_mdio_sleep: emac0_mdio_sleep {
+				/* suspended state */
+				mux {
+					/* MDC MDIO */
+					pins = "gpio27", "gpio28";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio27", "gpio28";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-down;
+				};
+			};
+
+			emac0_ephy_active: emac0_ephy_active {
+				/* active state */
+				mux {
+					/* EPHY RST */
+					pins = "gpio29";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio29";
+					drive-strength = <16>; /* 16 MA */
+					bias-pull-up;
+					output-high;
+				};
+			};
+
+			emac0_ephy_sleep: emac0_ephy_sleep {
+				/* suspended state */
+				mux {
+					/* EPHY RST */
+					pins = "gpio29";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio29";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable;
+					output-low;
+				};
+			};
+		};
+
+		mdss_cs_active: mdss_cs_active {
+			mux {
+				pins = "gpio23";
+				function = "ebi2_lcd_cs_n_b";
+			};
+
+			config {
+				pins = "gpio23";
+				drive-strength = <10>;/*10mA*/
+				bias-disable;/*NOpull*/
+			};
+		};
+
+		mdss_cs_sleep:mdss_cs_sleep {
+			mux {
+				pins = "gpio23";
+				function = "ebi2_lcd_cs_n_b";
+			};
+
+			config {
+				pins = "gpio23";
+				drive-strength = <2>;/*2mA*/
+				bias-disable;/*NOpull*/
+			};
+		};
+
+		mdss_te_active:mdss_te_active {
+			mux {
+				pins = "gpio20";
+				function = "ebi2_lcd_te_b";
+			};
+
+			config {
+				pins = "gpio20";
+				drive-strength = <10>;/*10mA*/
+				bias-disable;/*NOpull*/
+			};
+		};
+
+		mdss_te_sleep:mdss_te_sleep {
+			mux {
+				pins = "gpio20";
+				function = "ebi2_lcd_te_b";
+			};
+
+			config {
+				pins = "gpio20";
+				drive-strength = <2>;/*2mA*/
+				bias-disable;/*NOpull*/
+			};
+		};
+
+		mdss_rs_active:mdss_rs_active {
+			mux {
+				pins = "gpio74";
+				function = "ebi2_lcd";
+			};
+
+			config {
+				pins = "gpio74";
+				drive-strength = <10>;/*10mA*/
+				bias-disable;/*NOpull*/
+			};
+		};
+
+		mdss_rs_sleep:mdss_rs_sleep {
+			mux {
+				pins = "gpio74";
+				function = "ebi2_lcd";
+			};
+
+			config {
+				pins = "gpio74";
+				drive-strength = <2>;/*2mA*/
+				bias-disable;/*NOpull*/
+			};
+		};
+
+		mdss_ad_active:mdss_ad_active {
+			mux {
+				pins = "gpio22";
+				function = "ebi2_a_d_8_b";
+			};
+
+			config {
+				pins = "gpio22";
+				drive-strength = <10>;/*10mA*/
+				bias-disable;/*NOpull*/
+			};
+		};
+
+		mdss_ad_sleep:mdss_ad_sleep {
+			mux {
+				pins = "gpio22";
+				function = "ebi2_a_d_8_b";
+			};
+
+			config {
+				pins = "gpio22";
+				drive-strength = <2>;/*2mA*/
+				bias-disable;/*NOpull*/
+			};
+		};
+
+		mdss_bl_active:mdss_bl_active {
+			mux {
+				pins = "gpio21";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio21";
+				drive-strength = <10>;/*10mA*/
+				bias-disable;/*NOpull*/
+				output-high;
+			};
+		};
+
+		mdss_bl_sleep:mdss_bl_sleep {
+			mux {
+				pins = "gpio21";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio21";
+				drive-strength = <2>;/*2mA*/
+				bias-disable;/*NOpull*/
+			};
+		};
+
+		mdss_ldo_active:mdss_ldo_active {
+			mux {
+				pins = "gpio10";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio10";
+				drive-strength = <10>;/*10mA*/
+				bias-disable;/*NOpull*/
+				output-high;
+			};
+		};
+
+		mdss_ldo_sleep:mdss_ldo_sleep {
+			mux {
+				pins = "gpio10";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio10";
+				drive-strength = <2>;/*2mA*/
+				bias-disable;/*NOpull*/
+				output-low;
+			};
+		};
+
+		pinctrl_pps: ppsgrp {
+			mux {
+				pins = "gpio53";
+				function = "nav_tsync_out_a";
+			};
+
+			config {
+				pins = "gpio53";
+				bias-pull-down;
+			};
+		};
+
+		can_reset {
+			can_rst_on: rst_on {
+				mux {
+					pins = "gpio11";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio11";
+					drive-strength = <2>; /* 2 mA */
+					bias-pull-up;
+				};
+			};
+
+			can_rst_off: rst_off {
+				mux {
+					pins = "gpio11";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio11";
+					drive-strength = <2>; /* 2 mA */
+					bias-pull-up;
+					output-high;
+				};
+			};
+		};
+
+		ntn_rst_gpio_default: ntn_rst_gpio_default {
+			mux {
+				pins = "gpio30";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio30";
+				drive-strength = <16>;
+				bias-pull-up;
+				output-high;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-pm.dtsi b/arch/arm/boot/dts/qcom/mdm9607-pm.dtsi
new file mode 100644
index 0000000..58ec0c0
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-pm.dtsi
@@ -0,0 +1,258 @@
+/* Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/msm/pm.h>
+
+&soc {
+	qcom,spm@b009000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb009000 0x1000>;
+		qcom,name = "cpu0";
+		qcom,cpu = <&CPU0>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x1>;
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0xe>;
+		qcom,mode0 {
+			qcom,label = "qcom,saw2-spm-cmd-wfi";
+			qcom,sequence = [04 03 04 0f];
+			qcom,spm_en;
+		};
+		qcom,mode1 {
+			qcom,label = "qcom,saw2-spm-cmd-spc";
+			qcom,sequence = [1f 34 04 44 24 54 03
+				54 44 04 24 34 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+		qcom,mode2 {
+			qcom,label = "qcom,saw2-spm-cmd-pc";
+			qcom,sequence = [1f 34 04 44 14 24 54 03
+				54 44 14 04 04 24 04 34 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+			qcom,slp_cmd_mode;
+		};
+	};
+
+	qcom,lpm-levels {
+		compatible = "qcom,lpm-levels";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,pm-cluster@0{
+			#address-cells = <1>;
+			#size-cells = <0>;
+			reg = <0>;
+			label = "system";
+			qcom,default-level=<0>;
+
+			qcom,pm-cluster-level@0 {
+				reg = <0>;
+				label = "l2-active";
+				qcom,latency-us = <270>;
+				qcom,ss-power = <455>;
+				qcom,energy-overhead = <270621>;
+				qcom,time-overhead = <500>;
+			};
+
+			qcom,pm-cluster-level@1 {
+				reg = <1>;
+				label = "l2-pc";
+				qcom,latency-us = <285>;
+				qcom,ss-power = <442>;
+				qcom,energy-overhead = <306621>;
+				qcom,time-overhead = <540>;
+				qcom,min-child-idx = <2>;
+				qcom,notify-rpm;
+				qcom,reset-level = <LPM_RESET_LVL_PC>;
+			};
+
+			qcom,pm-cpu {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				qcom,pm-cpu-level@0{
+					reg = <0>;
+					qcom,spm-cpu-mode = "wfi";
+					qcom,latency-us = <1>;
+					qcom,ss-power = <473>;
+					qcom,energy-overhead = <100000>;
+					qcom,time-overhead = <25>;
+				};
+
+				qcom,pm-cpu-level@1 {
+					reg = <1>;
+					qcom,spm-cpu-mode ="standalone_pc";
+					qcom,latency-us = <240>;
+					qcom,ss-power = <467>;
+					qcom,energy-overhead = <202781>;
+					qcom,time-overhead = <420>;
+					qcom,use-broadcast-timer;
+					qcom,is-reset;
+					qcom,reset-level = <LPM_RESET_LVL_PC>;
+				};
+
+				qcom,pm-cpu-level@2 {
+					reg = <2>;
+					qcom,spm-cpu-mode = "pc";
+					qcom,latency-us = <270>;
+					qcom,ss-power = <455>;
+					qcom,energy-overhead = <270621>;
+					qcom,time-overhead = <500>;
+					qcom,use-broadcast-timer;
+					qcom,is-reset;
+					qcom,reset-level = <LPM_RESET_LVL_PC>;
+				};
+			};
+		};
+	};
+
+	qcom,mpm@601d0 {
+		compatible = "qcom,mpm-v2";
+		reg = <0x601d0 0x1000>, /* MSM_RPM_MPM_BASE 4K */
+		    <0xb011008 0x4>;
+		reg-names = "vmpm", "ipc";
+		interrupts = <0 171 1>;
+		clocks = <&clock_gcc clk_xo_lpm_clk>;
+		clock-names = "xo";
+		qcom,ipc-bit-offset = <1>;
+		qcom,gic-parent = <&intc>;
+		qcom,gic-map = <2 216>, /* tsens_upper_lower_int */
+			<49 172>, /* usb1_hs_async_wakeup_irq */
+			<51 174>, /* usb2_hs_async_wakeup_irq */
+			<53 104>, /* mdss_irq */
+			<58 166>, /* usb_hs_irq */
+			<62 222>, /* ee0_apps_hlos_spmi_periph_irq */
+			<0xff 18>,  /* WDT_biteInt */
+			<0xff 19>,  /* WDT_barkInt */
+			<0xff 35>,  /* CTI_SPI_intx */
+			<0xff 38>,  /* QTMR_qgicFrm0VirtIrq */
+			<0xff 47>,
+			<0xff 56>,  /* q6_wdog_expired_irq */
+			<0xff 57>,  /* mss_to_apps_irq(0) */
+			<0xff 58>,  /* mss_to_apps_irq(1) */
+			<0xff 59>,  /* mss_to_apps_irq(2) */
+			<0xff 60>,  /* mss_to_apps_irq(3) */
+			<0xff 61>,  /* mss_a2_bam_irq */
+			<0xff 77>,  /* qpic_bam_irq[1] */
+			<0xff 114>, /* qdsd_intr_out */
+			<0xff 130>, /* peripheral_irq[9] */
+			<0xff 131>, /* qup_irq */
+			<0xff 140>, /* uart_dm_intr */
+			<0xff 153>, /* peripheral_irq[4] */
+			<0xff 155>, /* sdc1_irq(0) */
+			<0xff 157>, /* sdc2_irq(0) */
+			<0xff 161>, /* qpic_nandc_op_done_irq */
+			<0xff 163>, /* qpic_lcdc_irq */
+			<0xff 164>, /* qpic_bam_irq[0] */
+			<0xff 168>,
+			<0xff 170>, /* sdc1_pwr_cmd_irq */
+			<0xff 173>, /* hsic_core_irq */
+			<0xff 192>, /* audio_out0_irq */
+			<0xff 198>, /* qdss_etrbytecnt_irq */
+			<0xff 200>, /* rpm_ipc(4) */
+			<0xff 201>, /* rpm_ipc(5) */
+			<0xff 202>, /* rpm_ipc(6) */
+			<0xff 203>, /* rpm_ipc(7) */
+			<0xff 204>, /* rpm_ipc(24) */
+			<0xff 205>, /* rpm_ipc(25) */
+			<0xff 206>, /* rpm_ipc(26) */
+			<0xff 207>, /* rpm_ipc(27) */
+			<0xff 208>, /* rbif_irq[0] */
+			<0xff 215>, /* o_bimc_intr */
+			<0xff 224>, /* spdm_realtime_irq(1) */
+			<0xff 239>, /* crypto_bam_irq[1]*/
+			<0xff 240>, /* summary_irq_kpss */
+			<0xff 244>, /* bam_irq[2] */
+			<0xff 253>, /* sdc2_pwr_cmd_irq */
+			<0xff 269>, /* rpm_wdog_expired_irq */
+			<0xff 270>, /* bam_irq[0] */
+			<0xff 275>, /* rpm_ipc(30) */
+			<0xff 276>; /* rpm_ipc(31) */
+
+		qcom,gpio-parent = <&tlmm_pinmux>;
+		qcom,gpio-map = <3  16>,
+			<4  5>,
+			<5  11>,
+			<6  12>,
+			<7  3>,
+			<8  17>,
+			<9  9>,
+			<10  13>,
+			<11  1>,
+			<12  20>,
+			<13  21>,
+			<14  22>,
+			<15  75>,
+			<16  74>,
+			<17  28>,
+			<18  44>,
+			<19  26>,
+			<20  43>,
+			<21  42>,
+			<22  29>,
+			<23  69>,
+			<24  30>,
+			<25  37>,
+			<26  25>,
+			<27  71>,
+			<28  34>,
+			<29  55>,
+			<30  8>,
+			<31  40>,
+			<32  48>,
+			<33  52>,
+			<34  57>,
+			<35  62>,
+			<36  66>,
+			<37  59>,
+			<38  79>,
+			<39  38>,
+			<40  63>,
+			<41  76>;
+	};
+
+	qcom,pm@8600664 {
+		compatible = "qcom,pm";
+		reg = <0x8600664 0x40>;
+		clocks = <&clock_cpu  clk_a7ssmux>;
+		clock-names = "cpu0_clk";
+		qcom,use-sync-timer;
+		qcom,synced-clocks;
+		qcom,tz-flushes-cache;
+	};
+
+	qcom,cpu-sleep-status@b088008{
+		compatible = "qcom,cpu-sleep-status";
+		reg = <0xb088008 0x100>;
+		qcom,cpu-alias-addr = <0x10000>;
+		qcom,sleep-status-mask= <0x80000>;
+	};
+
+	qcom,rpm-stats@29dba0 {
+		compatible = "qcom,rpm-stats";
+		reg = <0x29dba0 0x1000>;
+		reg-names = "phys_addr_base";
+		qcom,sleep-stats-version = <2>;
+	};
+
+	qcom,rpm-master-stats@60150 {
+		compatible = "qcom,rpm-master-stats";
+		reg = <0x60150 0x2030>;
+		qcom,masters = "APSS", "MPSS", "PRONTO";
+		qcom,master-stats-version = <2>;
+		qcom,master-offset = <4096>;
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-rcm.dts b/arch/arm/boot/dts/qcom/mdm9607-rcm.dts
new file mode 100644
index 0000000..cdf518c
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-rcm.dts
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+/dts-v1/;
+
+#include "mdm9607-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MDM 9607 RCM";
+	compatible = "qcom,mdm9607-cdp", "qcom,mdm9607", "qcom,cdp";
+	qcom,board-id = <21 0>;
+};
+
+&emac0 {
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-regulator.dtsi b/arch/arm/boot/dts/qcom/mdm9607-regulator.dtsi
new file mode 100644
index 0000000..3b4bb36
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-regulator.dtsi
@@ -0,0 +1,413 @@
+/* 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.
+ */
+
+&rpm_bus {
+	rpm-regulator-smpa2 {
+		status = "okay";
+		mdm9607_s2: regulator-s2 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_s2";
+			regulator-min-microvolt = <750000>;
+			regulator-max-microvolt = <1275000>;
+			qcom,init-voltage = <750000>;
+			status = "okay";
+		};
+	};
+
+	/* CX supply */
+	rpm-regulator-smpa3 {
+		status = "okay";
+		mdm9607_s3_level: regulator-s3-level {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_s3_level";
+			qcom,set = <3>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+			qcom,use-voltage-level;
+		};
+
+		mdm9607_s3_level_ao: regulator-s3-level-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_s3_level_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+			qcom,use-voltage-level;
+		};
+
+		mdm9607_s3_floor_level: regulator-s3-floor-level {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_s3_floor_level";
+			qcom,set = <3>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+			qcom,use-voltage-floor-level;
+			qcom,always-send-voltage;
+		};
+
+		mdm9607_s3_level_so: regulator-s3-level-so {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_s3_level_so";
+			qcom,set = <2>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+			qcom,use-voltage-level;
+		};
+	};
+
+	rpm-regulator-smpa4 {
+		status = "okay";
+		mdm9607_s4: regulator-s4 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_s4";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1950000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		status = "okay";
+		mdm9607_l1: regulator-l1 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l1";
+			regulator-min-microvolt = <1250000>;
+			regulator-max-microvolt = <1250000>;
+			qcom,init-voltage = <1250000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		status = "okay";
+		mdm9607_l2: regulator-l2 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l2";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		status = "okay";
+		mdm9607_l3: regulator-l3 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l3";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+		status = "okay";
+		mdm9607_l4: regulator-l4 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l4";
+			regulator-min-microvolt = <3075000>;
+			regulator-max-microvolt = <3075000>;
+			qcom,init-voltage = <3075000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		status = "okay";
+		mdm9607_l5: regulator-l5 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l5";
+			regulator-min-microvolt = <1700000>;
+			regulator-max-microvolt = <3050000>;
+			qcom,init-voltage = <1700000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		status = "okay";
+		mdm9607_l6: regulator-l6 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l6";
+			regulator-min-microvolt = <1700000>;
+			regulator-max-microvolt = <3050000>;
+			qcom,init-voltage = <1700000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		status = "okay";
+		mdm9607_l7: regulator-l7 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l7";
+			regulator-min-microvolt = <1700000>;
+			regulator-max-microvolt = <1900000>;
+			qcom,init-voltage = <1700000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		status = "okay";
+		mdm9607_l8: regulator-l8 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l8";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+		status = "okay";
+		mdm9607_l9: regulator-l9 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l9";
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1250000>;
+			qcom,init-voltage = <1200000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		status = "okay";
+		mdm9607_l10: regulator-l10 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l10";
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1050000>;
+			qcom,init-voltage = <1050000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa11 {
+		status = "okay";
+		mdm9607_l11: regulator-l11 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l11";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	/* MX supply */
+	rpm-regulator-ldoa12 {
+		status = "okay";
+		mdm9607_l12_level: regulator-l12-level {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l12_level";
+			qcom,set = <3>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+			qcom,use-voltage-level;
+		};
+
+		mdm9607_l12_level_ao: regulator-l12-level-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l12_level_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+			qcom,use-voltage-level;
+			qcom,always-send-voltage;
+		};
+
+		mdm9607_l12_level_so: regulator-l12-level-so {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l12_level_so";
+			qcom,set = <2>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+			qcom,use-voltage-level;
+		};
+
+		mdm9607_l12_floor_level: regulator-l12-floor-level {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l12_floor_lebel";
+			qcom,set = <3>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+			qcom,use-voltage-floor-level;
+			qcom,always-send-voltage;
+		};
+	};
+
+	rpm-regulator-ldoa13 {
+		status = "okay";
+		mdm9607_l13: regulator-l13 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l13";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2850000>;
+			qcom,init-voltage = <2850000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		status = "okay";
+		mdm9607_l14: regulator-l14 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "mdm9607_l14";
+			regulator-min-microvolt = <2650000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,init-voltage = <2650000>;
+			status = "okay";
+		};
+	};
+};
+
+&spmi_bus {
+	qcom,pm8019@1 {
+		/* APC supply */
+		mdm9607_s1: spm-regulator@1400 {
+			compatible = "qcom,spm-regulator";
+			reg = <0x1400 0x100>;
+			regulator-name = "mdm9607_s1";
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1350000>;
+			qcom,bypass-spm; /* TODO: Remove once SPM is up */
+		};
+	};
+};
+
+&soc {
+	mem_acc_vreg_corner: regulator@1942130 {
+		compatible = "qcom,mem-acc-regulator";
+		reg = <0x1942130 0x4>;
+		reg-names = "acc-sel-l1";
+		regulator-name = "mem_acc_corner";
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <3>;
+
+		qcom,acc-sel-l1-bit-pos = <0>;
+		qcom,corner-acc-map = <0 1 1>;
+	};
+
+	apc_vreg_corner: regulator@b018000 {
+		compatible = "qcom,cpr-regulator";
+		reg = <0xb018000 0x1000>, <0xb010058 4>, <0xa4000 0x1000>;
+		reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
+		interrupts = <0 20 0>;
+		regulator-name = "apc_corner";
+		qcom,cpr-fuse-corners = <3>;
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <7>;
+
+		qcom,cpr-voltage-ceiling = <1050000 1225000 1350000>;
+		qcom,cpr-voltage-floor = <1050000 1050000 1150000>;
+		vdd-apc-supply = <&mdm9607_s1>;
+
+		vdd-mx-supply = <&mdm9607_l12_level_ao>;
+		qcom,vdd-mx-vmin-method = <4>;
+		qcom,vdd-mx-corner-map = < RPM_SMD_REGULATOR_LEVEL_SVS
+					   RPM_SMD_REGULATOR_LEVEL_NOM
+					   RPM_SMD_REGULATOR_LEVEL_TURBO>;
+		qcom,vdd-mx-vmax = <RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR>;
+
+		mem-acc-supply = <&mem_acc_vreg_corner>;
+
+		qcom,cpr-ref-clk = <19200>;
+		qcom,cpr-timer-delay = <5000>;
+		qcom,cpr-timer-cons-up = <0>;
+		qcom,cpr-timer-cons-down = <2>;
+		qcom,cpr-irq-line = <0>;
+		qcom,cpr-step-quotient = <22 0 24 0 0 0 0 0>;
+		qcom,cpr-up-threshold = <2>;
+		qcom,cpr-down-threshold = <3>;
+		qcom,cpr-idle-clocks = <15>;
+		qcom,cpr-gcnt-time = <1>;
+		qcom,vdd-apc-step-up-limit = <1>;
+		qcom,vdd-apc-step-down-limit = <1>;
+		qcom,cpr-apc-volt-step = <12500>;
+
+		qcom,cpr-fuse-row = <65 0>;
+		qcom,cpr-fuse-target-quot = <24 12 0>;
+		qcom,cpr-fuse-ro-sel = <42 39 36>;
+		qcom,cpr-fuse-bp-cpr-disable = <54>;
+		qcom,cpr-fuse-init-voltage =
+					<66 6 6 0>,
+					<66 0 6 0>,
+					<65 45 6 0>;
+		qcom,cpr-fuse-revision = <65 51 3 0>;
+		qcom,cpr-init-voltage-ref = <1050000 1225000 1350000>;
+		qcom,cpr-init-voltage-step = <10000>;
+		qcom,cpr-corner-map = <1 2 3 3 3 3 3>;
+		qcom,cpr-init-voltage-as-ceiling;
+		qcom,cpr-corner-frequency-map =
+					<1 400000000>,
+					<2 800000000>,
+					<3 998400000>,
+					<4 1094400000>,
+					<5 1190400000>,
+					<6 1248000000>,
+					<7 1305600000>;
+		qcom,speed-bin-fuse-sel = <37 34 3 0>;
+		qcom,cpr-speed-bin-max-corners =
+					<0 0 1 2 7>;
+		qcom,cpr-quot-adjust-scaling-factor-max = <1400>;
+		qcom,disable-closed-loop-in-pc;
+		qcom,cpr-cpus = <&CPU0>;
+		qcom,cpr-enable;
+	};
+
+/* Miscellaneous regulators */
+	sdcard_ext_vreg: sdcard_ext_vreg {
+		compatible = "regulator-fixed";
+		regulator-name = "sdcard_ext_vreg";
+		startup-delay-us = <250>;
+		enable-active-high;
+		gpio = <&pm8019_gpios 4 0>;
+	};
+
+	/* Rome 3.3V supply */
+	rome_vreg: rome_vreg {
+		compatible = "regulator-fixed";
+		regulator-name = "rome_vreg";
+		startup-delay-us = <4000>;
+		enable-active-high;
+		gpio = <&pm8019_gpios 3 0>;
+	};
+
+	emac_lan_vreg: emac_lan_vreg {
+		compatible = "regulator-fixed";
+		regulator-name = "emac_lan_vreg";
+		startup-delay-us = <250>;
+		enable-active-high;
+		gpio = <&pm8019_mpps 4 0>;
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-rpm-regulator.dtsi b/arch/arm/boot/dts/qcom/mdm9607-rpm-regulator.dtsi
new file mode 100644
index 0000000..a085957
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-rpm-regulator.dtsi
@@ -0,0 +1,302 @@
+/*
+ * 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.
+ */
+
+&rpm_bus {
+	rpm-regulator-smpa1 {
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-s1 {
+			regulator-name = "mdm9607_s1";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-smpa2 {
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-s2 {
+			regulator-name = "mdm9607_s2";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-smpa3 {
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-s3 {
+			regulator-name = "mdm9607_s3";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-smpa4 {
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-s4 {
+			regulator-name = "mdm9607_s4";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l1 {
+			regulator-name = "mdm9607_l1";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l2 {
+			regulator-name = "mdm9607_l2";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l3 {
+			regulator-name = "mdm9607_l3";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l4 {
+			regulator-name = "mdm9607_l4";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <5>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l5 {
+			regulator-name = "mdm9607_l5";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <6>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l6 {
+			regulator-name = "mdm9607_l6";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <7>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l7 {
+			regulator-name = "mdm9607_l7";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <8>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l8 {
+			regulator-name = "mdm9607_l8";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <9>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l9 {
+			regulator-name = "mdm9607_l9";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <10>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l10 {
+			regulator-name = "mdm9607_l10";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa11 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <11>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l11 {
+			regulator-name = "mdm9607_l11";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <12>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l12 {
+			regulator-name = "mdm9607_l12";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa13 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <13>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l13 {
+			regulator-name = "mdm9607_l13";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <14>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		compatible = "qcom,rpm-smd-regulator-resource";
+		status = "disabled";
+
+		regulator-l14 {
+			regulator-name = "mdm9607_l14";
+			qcom,set = <3>;
+			status = "disabled";
+			compatible = "qcom,rpm-smd-regulator";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-rumi.dts b/arch/arm/boot/dts/qcom/mdm9607-rumi.dts
new file mode 100644
index 0000000..c4cec0b
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-rumi.dts
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "mdm9607.dtsi"
+#include "mdm9607-pinctrl.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MDM 9607 RUMI";
+	compatible = "qcom,mdm9607-rumi", "qcom,mdm9607", "qcom,rumi";
+	qcom,board-id = <15 0>;
+};
+
+&blsp1_uart5 {
+	status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console_sleep>;
+};
+
+&qnand_1 {
+	status = "ok";
+};
+
+&usb_otg {
+	qcom,hsusb-otg-mode = <1>; /* DEVICE only */
+	qcom,hsusb-otg-otg-control = <1>; /* PHY control */
+	qcom,emulation;
+	/delete-property/ qcom,boost-sysclk-with-streaming;
+	/delete-property/ vbus_otg-supply;
+};
+
+&clock_gcc {
+	compatible="qcom,dummycc";
+	#clock-cells = <1>;
+};
+
+&clock_debug {
+	status = "disabled";
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-smp2p.dtsi b/arch/arm/boot/dts/qcom/mdm9607-smp2p.dtsi
new file mode 100644
index 0000000..609cf0d
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-smp2p.dtsi
@@ -0,0 +1,104 @@
+/* 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.
+ */
+
+&soc {
+	qcom,smp2p-modem {
+		compatible = "qcom,smp2p";
+		reg = <0x0b011008 0x4>;
+		qcom,remote-pid = <1>;
+		qcom,irq-bitmask = <0x4000>;
+		interrupts = <0 27 1>;
+	};
+
+	smp2pgpio_smp2p_15_in: qcom,smp2pgpio-smp2p-15-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <15>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_15_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_15_in";
+		gpios = <&smp2pgpio_smp2p_15_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_15_out: qcom,smp2pgpio-smp2p-15-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <15>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_15_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_15_out";
+		gpios = <&smp2pgpio_smp2p_15_out 0 0>;
+	};
+
+	smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+		gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+		gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+	};
+
+	smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
+			compatible = "qcom,smp2pgpio";
+			qcom,entry-name = "slave-kernel";
+			qcom,remote-pid = <1>;
+			qcom,is-inbound;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+	};
+
+	smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
+			compatible = "qcom,smp2pgpio";
+			qcom,entry-name = "master-kernel";
+			qcom,remote-pid = <1>;
+			gpio-controller;
+			#gpio-cells = <2>;
+			interrupt-controller;
+			#interrupt-cells = <2>;
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607-ttp.dts b/arch/arm/boot/dts/qcom/mdm9607-ttp.dts
new file mode 100644
index 0000000..fb76558
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607-ttp.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "mdm9607-mtp.dtsi"
+/ {
+	model = "Qualcomm Technologies, Inc. MDM 9206 TTP";
+	compatible = "qcom,mdm9607-ttp", "qcom,mdm9607", "qcom,ttp";
+	qcom,board-id = <0x1E 0>;
+};
+
+&emac_lan_vreg{
+	regulator-always-on;
+};
diff --git a/arch/arm/boot/dts/qcom/mdm9607.dtsi b/arch/arm/boot/dts/qcom/mdm9607.dtsi
new file mode 100644
index 0000000..ba6401e
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/mdm9607.dtsi
@@ -0,0 +1,1538 @@
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "skeleton.dtsi"
+#include <dt-bindings/clock/mdm-clocks-9607.h>
+#include <dt-bindings/clock/msm-clocks-a7.h>
+#include <dt-bindings/regulator/qcom,rpm-smd-regulator.h>
+
+/ {
+	model = "Qualcomm Technologies, Inc. MDM 9607";
+	compatible = "qcom,mdm9607";
+	qcom,msm-id = <290 0x10000>, <296 0x10000>, <297 0x10000>,
+		      <298 0x10000>, <299 0x10000>;
+	interrupt-parent = <&intc>;
+
+	aliases {
+		sdhc1 = &sdhc_1;/* SDC1 for SDIO slot */
+		qpic_nand1 = &qnand_1;
+	};
+
+	reserved-memory {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		modem_adsp_mem: modem_adsp_region@0 {
+			compatible = "removed-dma-pool";
+			no-map-fixup;
+			reg = <0x82a00000 0x5000000>;
+		};
+
+		cnss_debug_mem: cnss_debug_region@0 {
+			compatible = "removed-dma-pool";
+			no-map;
+			reg = <0x87a00000 0x200000>;
+		};
+
+		external_image_mem: external_image_region@0 {
+			compatible = "removed-dma-pool";
+			no-map;
+			reg = <0x87c00000 0x400000>;
+		};
+
+		audio_mem: audio_region@0 {
+			compatible = "shared-dma-pool";
+			reusable;
+			alignment = <0x400000>;
+			size = <0x400000>;
+		};
+
+		qseecom_mem: qseecom_region@0 {
+			compatible = "shared-dma-pool";
+			reusable;
+			alignment = <0x400000>;
+			size = <0x0400000>;
+			status = "disabled";
+		};
+	};
+
+	aliases {
+		/* smdtty devices */
+		smd7 = &smdtty_data1;
+		smd8 = &smdtty_data4;
+		smd11 = &smdtty_data11;
+		smd21 = &smdtty_data21;
+		smd36 = &smdtty_loopback;
+		/* spi device */
+		spi1  = &spi_1;
+		i2c4 = &i2c_4;
+		sdhc2 = &sdhc_2; /* SDC2 SD card slot */
+	};
+
+	cpus {
+		#size-cells = <0>;
+		#address-cells = <1>;
+
+		CPU0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x0>;
+			qcom,limits-info = <&mitigation_profile0>;
+		};
+	};
+	soc: soc { };
+};
+
+#include "mdm9607-ion.dtsi"
+#include "mdm9607-smp2p.dtsi"
+#include "mdm9607-bus.dtsi"
+#include "mdm9607-coresight.dtsi"
+#include "mdm9607-pm.dtsi"
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges;
+
+	intc: interrupt-controller@b000000 {
+		compatible = "qcom,msm-qgic2";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x0b000000 0x1000>,
+		      <0x0b002000 0x1000>;
+	};
+
+	qcom,mpm2-sleep-counter@4a3000 {
+		compatible = "qcom,mpm2-sleep-counter";
+		reg = <0x4a3000 0x1000>;
+		clock-frequency = <32768>;
+	};
+
+	timer@b020000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		compatible = "arm,armv7-timer-mem";
+		reg = <0xb020000 0x1000>;
+		clock-frequency = <19200000>;
+
+		frame@b021000 {
+			frame-number = <0>;
+			interrupts = <0 7 0x4>,
+				     <0 6 0x4>;
+			reg = <0xb021000 0x1000>,
+			      <0xb022000 0x1000>;
+		};
+
+		frame@b023000 {
+			frame-number = <1>;
+			interrupts = <0 8 0x4>;
+			reg = <0xb023000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@b024000 {
+			frame-number = <2>;
+			interrupts = <0 9 0x4>;
+			reg = <0xb024000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@b025000 {
+			frame-number = <3>;
+			interrupts = <0 10 0x4>;
+			reg = <0xb025000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@b026000 {
+			frame-number = <4>;
+			interrupts = <0 11 0x4>;
+			reg = <0xb026000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@b027000 {
+			frame-number = <5>;
+			interrupts = <0 12 0x4>;
+			reg = <0xb027000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@b028000 {
+			frame-number = <6>;
+			interrupts = <0 13 0x4>;
+			reg = <0xb028000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@b029000 {
+			frame-number = <7>;
+			interrupts = <0 14 0x4>;
+			reg = <0xb029000 0x1000>;
+			status = "disabled";
+		};
+	};
+
+	qcom,wdt@b017000 {
+		compatible = "qcom,msm-watchdog";
+		reg = <0xb017000 0x1000>;
+		reg-names = "wdt-base";
+		interrupts = <0 3 0>, <0 4 0>;
+		qcom,bark-time = <11000>;
+		qcom,pet-time = <10000>;
+		qcom,wakeup-enable;
+	};
+
+	qcom,msm-rtb {
+		compatible = "qcom,msm-rtb";
+		qcom,rtb-size = <0x10000>; /* 64K EBI1 buffer */
+	};
+
+	qcom,msm-imem@8600000 {
+		compatible = "qcom,msm-imem";
+		reg = <0x08600000 0x1000>; /* Address and size of IMEM */
+		ranges = <0x0 0x08600000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		mem_dump_table@10 {
+			compatible = "qcom,msm-imem-mem_dump_table";
+			reg = <0x10 8>;
+		};
+
+		restart_reason@65c {
+			compatible = "qcom,msm-imem-restart_reason";
+			reg = <0x65c 4>;
+		};
+
+		boot_stats@6b0 {
+			compatible = "qcom,msm-imem-boot_stats";
+			reg = <0x6b0 32>;
+		};
+
+		pil@94c {
+			compatible = "qcom,msm-imem-pil";
+			reg = <0x94c 200>;
+		};
+	};
+
+	restart@4ab000 {
+		compatible = "qcom,pshold";
+		reg = <0x4ab000 0x4>,
+		      <0x193d100 0x4>;
+		      reg-names = "pshold-base", "tcsr-boot-misc-detect";
+	};
+
+	jtag_fuse: jtagfuse@a601c {
+		compatible = "qcom,jtag-fuse-v2";
+		reg = <0xa601c 0x8>;
+		reg-names = "fuse-base";
+	};
+
+	jtag_mm: jtagmm@6042000 {
+		compatible = "qcom,jtagv8-mm";
+		reg = <0x6042000 0x1000>,
+		      <0x6040000 0x1000>;
+		reg-names = "etm-base", "debug-base";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+
+		qcom,coresight-jtagmm-cpu = <&CPU0>;
+	};
+
+	clock_gcc: qcom,gcc@1800000 {
+		compatible = "qcom,gcc-mdm9607";
+		reg = <0x1800000 0x80000>,
+			<0x0b008000 0x00050>;
+		reg-names = "cc_base", "apcs_base";
+		vdd_dig-supply = <&mdm9607_s3_level>;
+		vdd_stromer_dig-supply = <&mdm9607_s3_level_ao>;
+		#clock-cells = <1>;
+	};
+
+	clock_debug: qcom,debug@1874000 {
+		compatible = "qcom,cc-debug-mdm9607";
+		reg = <0x1800000 0x80000>,
+			<0xb01101c 0x8>;
+		reg-names = "cc_base", "meas";
+		#clock-cells = <1>;
+	};
+
+	clock_cpu: qcom,clock-a7@0b010008 {
+		compatible = "qcom,clock-a7-mdm9607";
+		reg = <0x0b010008 0x8>,
+			<0x000a412c 0x8>;
+		reg-names = "rcg-base", "efuse";
+		qcom,safe-freq = < 400000000 >;
+		cpu-vdd-supply = <&apc_vreg_corner>;
+		clocks = <&clock_gcc clk_gpll0_ao_clk_src>,
+				<&clock_gcc clk_a7sspll>;
+		clock-names = "clk-1", "clk-5";
+		qcom,speed4-bin-v0 =
+			<          0 0>,
+			<  400000000 1>,
+			<  800000000 2>,
+			<  998400000 3>,
+			< 1094400000 4>,
+			< 1190400000 5>,
+			< 1248000000 6>,
+			< 1305600000 7>;
+		qcom,a7ssmux-opp-store-vcorner = <&CPU0>;
+		#clock-cells = <1>;
+	};
+
+	cpubw: qcom,cpubw {
+		compatible = "qcom,devbw";
+		governor = "cpufreq";
+		qcom,src-dst-ports = <1 512>;
+		qcom,active-only;
+		qcom,bw-tbl =
+			<  366 /*  48   MHz */>,
+			<  732 /*  96   MHz */>,
+			<  915 /* 120   MHz */>,
+			< 1145 /* 150.15 MHz */>,
+			< 1831 /* 240   MHz */>,
+			< 2291 /* 300.3 MHZ */>;
+	};
+
+	devfreq-cpufreq {
+		cpubw-cpufreq {
+			target-dev = <&cpubw>;
+			cpu-to-dev-map =
+				 <  400000   732>,
+				 <  800000   915>,
+				 <  998400  1145>,
+				 < 1094400  1831>,
+				 < 1305600  2291>;
+		};
+	};
+
+	qcom,cpu-bwmon {
+		compatible = "qcom,bimc-bwmon2";
+		reg = <0x408000 0x300>, <0x401000 0x200>;
+		reg-names = "base", "global_base";
+		interrupts = <0 183 4>;
+		qcom,mport = <0>;
+		qcom,target-dev = <&cpubw>;
+	};
+
+	qcom,msm-cpufreq {
+		reg = <0 4>;
+		compatible = "qcom,msm-cpufreq";
+		clocks = <&clock_cpu  clk_a7ssmux>;
+		clock-names = "cpu0_clk";
+		qcom,cpufreq-table =
+				<  400000 >,
+				<  800000 >,
+				<  998400 >,
+				< 1094400 >,
+				< 1190400 >,
+				< 1248000 >,
+				< 1305600 >;
+	};
+
+	qcom,sps {
+		compatible = "qcom,msm_sps_4k";
+		qcom,pipe-attr-ee;
+	};
+
+	blsp1_uart5: serial@78b3000 { /* BLSP1 UART5 */
+		compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+		reg = <0x78b3000 0x200>;
+		interrupts = <0 121 0>;
+		clocks = <&clock_gcc clk_gcc_blsp1_uart5_apps_clk>,
+			 <&clock_gcc clk_gcc_blsp1_ahb_clk>;
+		clock-names = "core_clk", "iface_clk";
+		status = "disabled";
+	};
+
+	dma_blsp1: qcom,sps-dma@7884000 { /* BLSP1 */
+		#dma-cells = <4>;
+		compatible = "qcom,sps-dma";
+		reg = <0x7884000 0x2b000>;
+		interrupts = <0 238 0>;
+		qcom,summing-threshold = <10>;
+	};
+
+	i2c_4: i2c@78b8000 { /* BLSP1 QUP4 */
+		compatible = "qcom,i2c-msm-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0x78b8000 0x600>;
+		interrupt-names = "qup_irq";
+		interrupts = <0 98 0>;
+		qcom,clk-freq-out = <400000>;
+		qcom,clk-freq-in  = <19200000>;
+		clock-names = "iface_clk", "core_clk";
+		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+			<&clock_gcc clk_gcc_blsp1_qup4_i2c_apps_clk>;
+
+		pinctrl-names = "i2c_active", "i2c_sleep";
+		pinctrl-0 = <&i2c_4_active>;
+		pinctrl-1 = <&i2c_4_sleep>;
+		qcom,noise-rjct-scl = <0>;
+		qcom,noise-rjct-sda = <0>;
+		qcom,master-id = <86>;
+		dmas = <&dma_blsp1 18 64 0x20000020 0x20>,
+			<&dma_blsp1 19 32 0x20000020 0x20>;
+		dma-names = "tx", "rx";
+		status = "disabled";
+
+		wcd9xxx_tomtom_codec@0d{
+			compatible = "qcom,wcd9xxx-i2c";
+			reg = <0x0d>;
+
+			qcom,cdc-reset-gpio = <&tlmm_pinmux 26 0>;
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&codec_reset_active>;
+			pinctrl-1 = <&codec_reset_sleep>;
+
+			qcom,cdc-micbias1-ext-cap;
+
+			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>;
+			cdc-vdd-buck-supply = <&mdm9607_s4>;
+			qcom,cdc-vdd-buck-voltage = <1950000 1950000>;
+			qcom,cdc-vdd-buck-current = <25000>;
+
+			cdc-vdd-tx-h-supply = <&mdm9607_l11>;
+			qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-tx-h-current = <25000>;
+
+			cdc-vdd-rx-h-supply = <&mdm9607_l11>;
+			qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-rx-h-current = <25000>;
+
+			cdc-vddpx-1-supply = <&mdm9607_l11>;
+			qcom,cdc-vddpx-1-voltage = <1800000 1800000>;
+			qcom,cdc-vddpx-1-current = <10000>;
+
+			cdc-vdd-a-1p2v-supply = <&mdm9607_l9>;
+			qcom,cdc-vdd-a-1p2v-voltage = <1225000 1225000>;
+			qcom,cdc-vdd-a-1p2v-current = <10000>;
+
+			cdc-vddcx-1-supply = <&mdm9607_l9>;
+			qcom,cdc-vddcx-1-voltage = <1225000 1225000>;
+			qcom,cdc-vddcx-1-current = <10000>;
+
+			cdc-vddcx-2-supply = <&mdm9607_l9>;
+			qcom,cdc-vddcx-2-voltage = <1225000 1225000>;
+			qcom,cdc-vddcx-2-current = <10000>;
+
+			qcom,cdc-static-supplies = "cdc-vdd-buck",
+						   "cdc-vdd-tx-h",
+						   "cdc-vdd-rx-h",
+						   "cdc-vddpx-1",
+						   "cdc-vdd-a-1p2v",
+						   "cdc-vddcx-1",
+						   "cdc-vddcx-2";
+
+			qcom,cdc-micbias-ldoh-v = <0x3>;
+			qcom,cdc-micbias-cfilt1-mv = <1800>;
+			qcom,cdc-micbias-cfilt2-mv = <2700>;
+			qcom,cdc-micbias-cfilt3-mv = <1800>;
+			qcom,cdc-micbias1-cfilt-sel = <0x0>;
+			qcom,cdc-micbias2-cfilt-sel = <0x1>;
+			qcom,cdc-micbias3-cfilt-sel = <0x2>;
+			qcom,cdc-micbias4-cfilt-sel = <0x2>;
+			qcom,cdc-mclk-clk-rate = <12288000>;
+			qcom,cdc-dmic-sample-rate = <4800000>;
+			qcom,cdc-variant = "WCD9330";
+		};
+
+		wcd9xxx_tapan_codec@0d{
+			compatible = "qcom,wcd9xxx-i2c";
+			reg = <0x0d>;
+
+			status = "disabled";
+			qcom,cdc-reset-gpio = <&tlmm_pinmux 26 0>;
+			pinctrl-names = "default", "idle";
+			pinctrl-0 = <&codec_reset_active>;
+			pinctrl-1 = <&codec_reset_sleep>;
+
+			qcom,cdc-micbias1-ext-cap;
+
+			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>;
+			cdc-vdd-buck-supply = <&mdm9607_s4>;
+			qcom,cdc-vdd-buck-voltage = <1950000 1950000>;
+			qcom,cdc-vdd-buck-current = <25000>;
+
+			cdc-vdd-tx-h-supply = <&mdm9607_l11>;
+			qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-tx-h-current = <25000>;
+
+			cdc-vdd-rx-h-supply = <&mdm9607_l11>;
+			qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-rx-h-current = <25000>;
+
+			cdc-vddpx-1-supply = <&mdm9607_l11>;
+			qcom,cdc-vddpx-1-voltage = <1800000 1800000>;
+			qcom,cdc-vddpx-1-current = <10000>;
+
+			cdc-vdd-cx-supply = <&mdm9607_l9>;
+			qcom,cdc-vdd-cx-voltage = <1225000 1225000>;
+			qcom,cdc-vdd-cx-current = <10000>;
+
+			qcom,cdc-static-supplies = "cdc-vdd-buck",
+						   "cdc-vdd-tx-h",
+						   "cdc-vdd-rx-h",
+						   "cdc-vddpx-1",
+						   "cdc-vdd-cx";
+
+			qcom,cdc-micbias-ldoh-v = <0x3>;
+			qcom,cdc-micbias-cfilt1-mv = <1800>;
+			qcom,cdc-micbias-cfilt2-mv = <2700>;
+			qcom,cdc-micbias-cfilt3-mv = <1800>;
+			qcom,cdc-micbias1-cfilt-sel = <0x0>;
+			qcom,cdc-micbias2-cfilt-sel = <0x1>;
+			qcom,cdc-micbias3-cfilt-sel = <0x2>;
+			qcom,cdc-micbias4-cfilt-sel = <0x2>;
+			qcom,cdc-mclk-clk-rate = <12288000>;
+			qcom,cdc-dmic-sample-rate = <4800000>;
+			qcom,cdc-variant = "WCD9306";
+		};
+
+		wcd9xxx_codec@77{
+			compatible = "qcom,wcd9xxx-i2c";
+			reg = <0x77>;
+		};
+
+		wcd9xxx_codec@66{
+			compatible = "qcom,wcd9xxx-i2c";
+			reg = <0x66>;
+		};
+
+		wcd9xxx_codec@55{
+			compatible = "qcom,wcd9xxx-i2c";
+			reg = <0x55>;
+		};
+
+	};
+
+	blsp1_uart3: uart@78b1000 {
+		compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+		reg = <0x78b1000 0x200>,
+			<0x7884000 0x2b000>;
+		reg-names = "core_mem", "bam_mem";
+		interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+		#address-cells = <0>;
+		interrupt-parent = <&blsp1_uart3>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 119 0
+				1 &intc 0 238 0
+				2 &tlmm_pinmux 1 0>;
+
+		qcom,inject-rx-on-wakeup;
+		qcom,rx-char-to-inject = <0xFD>;
+
+		qcom,bam-tx-ep-pipe-index = <4>;
+		qcom,bam-rx-ep-pipe-index = <5>;
+		qcom,master-id = <86>;
+		clock-names = "core_clk", "iface_clk";
+		clocks = <&clock_gcc clk_gcc_blsp1_uart3_apps_clk>,
+				<&clock_gcc clk_gcc_blsp1_ahb_clk>;
+		pinctrl-names = "sleep", "default";
+		pinctrl-0 = <&blsp1_uart3_sleep>;
+		pinctrl-1 = <&blsp1_uart3_active>;
+		qcom,msm-bus,name = "blsp1_uart3";
+		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 = "disabled";
+	};
+
+	qcom,cnss-sdio {
+		compatible = "qcom,cnss_sdio";
+		reg = <0x87a00000 0x200000>;
+		reg-names = "ramdump";
+		subsys-name = "AR6320";
+		vdd-wlan-supply = <&rome_vreg>;
+		vdd-wlan-dsrc-supply = <&sdcard_ext_vreg>;
+		vdd-wlan-io-supply = <&mdm9607_l11>;
+		vdd-wlan-xtal-supply = <&mdm9607_l2>;
+	};
+
+	usb_otg: usb@78d9000 {
+		compatible = "qcom,hsusb-otg";
+		reg = <0x78d9000 0x400>, <0x6c000 0x200>;
+		reg-names = "core", "phy_csr";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+
+		interrupts = <0 134 0>, <0 140 0>;
+		interrupt-names = "core_irq", "async_irq";
+
+		hsusb_vdd_dig-supply = <&mdm9607_l9>;
+		HSUSB_1p8-supply = <&mdm9607_l2>;
+		HSUSB_3p3-supply = <&mdm9607_l4>;
+		qcom,vdd-voltage-level = <0 1225000 1225000>;
+
+		qcom,hsusb-otg-phy-init-seq =
+			<0x44 0x80 0x38 0x81 0x24 0x82 0x13 0x83 0xffffffff>;
+
+		qcom,hsusb-otg-phy-type = <3>; /* SNPS Femto PHY */
+		qcom,hsusb-otg-mode = <3>; /* OTG mode */
+		qcom,hsusb-otg-otg-control = <2>; /* PMIC control */
+		qcom,usbid-gpio = <&pm8019_mpps 1 0>;
+		qcom,hsusb-log2-itc = <4>;
+		qcom,dp-manual-pullup;
+		qcom,boost-sysclk-with-streaming;
+		qcom,phy-dvdd-always-on;
+		qcom,hsusb-otg-lpm-on-dev-suspend;
+		qcom,axi-prefetch-enable;
+		qcom,hsusb-otg-mpm-dpsehv-int = <49>;
+		qcom,hsusb-otg-mpm-dmsehv-int = <58>;
+		qcom,hsusb-otg-delay-lpm;
+		qcom,enable-phy-id-pullup;
+
+		qcom,msm-bus,name = "usb2";
+		qcom,msm-bus,num-cases = <3>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<87 512 0 0>,
+				<87 512 80000 0>,
+				<87 512 6000  6000>;
+		clocks = <&clock_gcc clk_gcc_usb_hs_ahb_clk>,
+			 <&clock_gcc clk_gcc_usb_hs_system_clk>,
+			 <&clock_gcc clk_gcc_usb2a_phy_sleep_clk>,
+			 <&clock_gcc clk_bimc_usb_a_clk>,
+			 <&clock_gcc clk_pcnoc_usb_a_clk>,
+			 <&clock_gcc clk_gcc_qusb2_phy_clk>,
+			 <&clock_gcc clk_gcc_usb2_hs_phy_only_clk>,
+			 <&clock_gcc clk_gcc_usb_hs_phy_cfg_ahb_clk>,
+			 <&clock_gcc clk_xo_otg_clk>;
+		clock-names = "iface_clk", "core_clk", "sleep_clk",
+				"bimc_clk", "pcnoc_clk", "phy_reset_clk",
+				"phy_por_clk", "phy_csr_clk", "xo";
+		qcom,bus-clk-rate = <240000000 0 100000000
+				     120000000 0  50000000>;
+		qcom,max-nominal-sysclk-rate = <133330000>;
+		qcom,max-svs-sysclk-rate = <69500000>;
+		qcom,default-mode-svs;
+
+		qcom,usbbam@78c4000 {
+			compatible = "qcom,usb-bam-msm";
+			reg = <0x78c4000 0x15000>;
+			interrupt-parent = <&intc>;
+			interrupts = <0 135 0>;
+			qcom,bam-type = <1>;
+			qcom,usb-bam-num-pipes = <2>;
+			qcom,usb-bam-fifo-baseaddr = <0x08603800>;
+			qcom,ignore-core-reset-ack;
+			qcom,disable-clk-gating;
+			qcom,reset-bam-on-disconnect;
+
+			qcom,pipe0 {
+				label = "hsusb-qdss-in-0";
+				qcom,usb-bam-mem-type = <2>;
+				qcom,dir = <1>;
+				qcom,pipe-num = <0>;
+				qcom,peer-bam = <0>;
+				qcom,peer-bam-physical-address = <0x6084000>;
+				qcom,src-bam-pipe-index = <0>;
+				qcom,dst-bam-pipe-index = <0>;
+				qcom,data-fifo-offset = <0x0>;
+				qcom,data-fifo-size = <0x600>;
+				qcom,descriptor-fifo-offset = <0x600>;
+				qcom,descriptor-fifo-size = <0x200>;
+			};
+		};
+	};
+
+	android_usb: android_usb@086000c8 {
+		compatible = "qcom,android-usb";
+		reg = <0x086000c8 0xc8>;
+		qcom,pm-qos-latency = <2 1001 12701>;
+	};
+
+	android_usb_hsic: android_usb-hsic {
+		compatible = "qcom,android-usb";
+		qcom,usb-core-id = <1>;
+		status = "disabled";
+	};
+
+	qnand_1: nand@7980000 {
+		compatible = "qcom,msm-nand";
+		reg = <0x07980000 0x1000>,
+		      <0x07984000 0x1a000>;
+		reg-names = "nand_phys",
+			    "bam_phys";
+		qcom,reg-adjustment-offset = <0x4000>;
+
+		interrupts = <0 132 0>;
+		interrupt-names = "bam_irq";
+
+		qcom,msm-bus,name = "qpic_nand";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+
+		qcom,msm-bus,vectors-KBps =
+			<91 512 0 0>,
+			/* Voting for max b/w on PNOC bus for now */
+			<91 512 400000 400000>;
+
+		clock-names = "core_clk";
+		clocks = <&clock_gcc clk_qpic_clk>;
+		status = "disabled";
+	};
+
+	sdhc_1: sdhci@7824900 {
+		compatible = "qcom,sdhci-msm";
+		reg = <0x7824900 0x200>, <0x7824000 0x800>, <0x01111000 0x4>;
+		reg-names = "hc_mem", "core_mem", "tlmm_mem";
+
+		qcom,cpu-dma-latency-us = <701>;
+		qcom,bus-width = <4>;
+		gpios = <&tlmm_pinmux 16 0>, /* CLK */
+		      <&tlmm_pinmux 17 0>, /* CMD */
+		      <&tlmm_pinmux 15 0>, /* DATA0 */
+		      <&tlmm_pinmux 14 0>, /* DATA1 */
+		      <&tlmm_pinmux 13 0>, /* DATA2 */
+		      <&tlmm_pinmux 12 0>; /* DATA3 */
+		qcom,gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
+		qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+			200000000>;
+
+		clock-names = "iface_clk", "core_clk";
+		clocks = <&clock_gcc clk_gcc_sdcc1_ahb_clk>,
+		       <&clock_gcc clk_gcc_sdcc1_apps_clk>;
+
+		qcom,msm-bus,name = "sdhc1";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
+			<78 512 1600 3200>,    /* 400 KB/s*/
+			<78 512 80000 160000>, /* 20 MB/s */
+			<78 512 100000 200000>, /* 25 MB/s */
+			<78 512 200000 400000>, /* 50 MB/s */
+			<78 512 400000 800000>, /* 100 MB/s */
+			<78 512 800000 800000>, /* 200 MB/s */
+			<78 512 2048000 4096000>; /* Max. bandwidth */
+			qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000
+			50000000 100000000 200000000 4294967295>;
+
+			#address-cells = <0>;
+			interrupt-parent = <&sdhc_1>;
+			interrupts = <0 1 2>;
+			#interrupt-cells = <1>;
+			interrupt-map-mask = <0xffffffff>;
+			interrupt-map = <0 &intc 0 123 0
+				1 &intc 0 138 0
+				2 &tlmm_pinmux 59 0x4>;
+			interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+			qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50",
+					"DDR50","SDR104";
+
+			qcom,pm-qos-irq-type = "affine_irq";
+			qcom,pm-qos-irq-latency = <2 250>;
+
+			status = "disabled";
+	};
+
+	wcd9xxx_intc: wcd9xxx-irq {
+		compatible = "qcom,wcd9xxx-irq";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&tlmm_pinmux>;
+		qcom,gpio-connect = <&tlmm_pinmux 75 0>;
+		interrupt-names = "cdc-int";
+	};
+
+	qcom,msm-adsp-loader {
+		compatible = "qcom,adsp-loader";
+		qcom,adsp-state = <0>;
+		qcom,proc-img-to-load = "modem";
+	};
+
+	qcom,msm-audio-ion {
+		compatible = "qcom,msm-audio-ion";
+		qcom,scm-mp-enabled;
+		memory-region = <&audio_mem>;
+	};
+
+	pcm0: qcom,msm-pcm {
+		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <0>;
+	};
+
+	routing: qcom,msm-pcm-routing {
+		compatible = "qcom,msm-pcm-routing";
+	};
+
+	pcm1: qcom,msm-pcm-low-latency {
+		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <1>;
+		qcom,msm-pcm-low-latency;
+		qcom,latency-level = "ultra";
+	};
+
+	qcom,msm-compr-dsp {
+		compatible = "qcom,msm-compr-dsp";
+	};
+
+	voip: qcom,msm-voip-dsp {
+		compatible = "qcom,msm-voip-dsp";
+	};
+
+	voice: qcom,msm-pcm-voice {
+		compatible = "qcom,msm-pcm-voice";
+		qcom,destroy-cvd;
+	};
+
+	stub_codec: qcom,msm-stub-codec {
+		compatible = "qcom,msm-stub-codec";
+	};
+
+	qcom,msm-dai-fe {
+		compatible = "qcom,msm-dai-fe";
+	};
+
+	afe: qcom,msm-pcm-afe {
+		compatible = "qcom,msm-pcm-afe";
+	};
+
+	hostless: qcom,msm-pcm-hostless {
+		compatible = "qcom,msm-pcm-hostless";
+	};
+
+	host_pcm: qcom,msm-voice-host-pcm {
+		compatible = "qcom,msm-voice-host-pcm";
+	};
+
+	loopback: qcom,msm-pcm-loopback {
+		compatible = "qcom,msm-pcm-loopback";
+	};
+
+	compress: qcom,msm-compress-dsp {
+		compatible = "qcom,msm-compress-dsp";
+		qcom,adsp-version = "MDSP 2.8";
+	};
+
+	 qcom,msm-dai-stub {
+		compatible = "qcom,msm-dai-stub";
+		dtmf_tx: qcom,msm-dai-stub-dtmf-tx {
+			compatible = "qcom,msm-dai-stub-dev";
+			qcom,msm-dai-stub-dev-id = <4>;
+		};
+
+		rx_capture_tx: qcom,msm-dai-stub-host-rx-capture-tx {
+			compatible = "qcom,msm-dai-stub-dev";
+			qcom,msm-dai-stub-dev-id = <5>;
+		};
+
+		rx_playback_rx: qcom,msm-dai-stub-host-rx-playback-rx {
+			compatible = "qcom,msm-dai-stub-dev";
+			qcom,msm-dai-stub-dev-id = <6>;
+		};
+
+		tx_capture_tx: qcom,msm-dai-stub-host-tx-capture-tx {
+			compatible = "qcom,msm-dai-stub-dev";
+			qcom,msm-dai-stub-dev-id = <7>;
+		};
+
+		tx_playback_rx: qcom,msm-dai-stub-host-tx-playback-rx {
+			compatible = "qcom,msm-dai-stub-dev";
+			qcom,msm-dai-stub-dev-id = <8>;
+		};
+	};
+
+	qcom,msm-dai-q6 {
+		compatible = "qcom,msm-dai-q6";
+		afe_pcm_rx: qcom,msm-dai-q6-be-afe-pcm-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <224>;
+		};
+
+		afe_pcm_tx: qcom,msm-dai-q6-be-afe-pcm-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <225>;
+		};
+
+		afe_proxy_rx: qcom,msm-dai-q6-afe-proxy-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <241>;
+		};
+
+		afe_proxy_tx: qcom,msm-dai-q6-afe-proxy-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <240>;
+		};
+
+		incall_record_rx: qcom,msm-dai-q6-incall-record-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32771>;
+		};
+
+		incall_record_tx: qcom,msm-dai-q6-incall-record-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32772>;
+		};
+
+		incall_music_rx: qcom,msm-dai-q6-incall-music-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32773>;
+		};
+	};
+
+	pcm_dtmf: qcom,msm-pcm-dtmf {
+		compatible = "qcom,msm-pcm-dtmf";
+	};
+
+	dai_pri_auxpcm: qcom,msm-pri-auxpcm {
+		compatible = "qcom,msm-auxpcm-dev";
+		qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
+		qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
+		qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
+		qcom,msm-cpudai-auxpcm-num-slots = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-slot-mapping = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-data = <0>, <0>;
+		qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+		qcom,msm-auxpcm-interface = "primary";
+		qcom,msm-cpudai-afe-clk-ver = <2>;
+	};
+
+	dai_sec_auxpcm: qcom,msm-sec-auxpcm {
+		compatible = "qcom,msm-auxpcm-dev";
+		qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
+		qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
+		qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
+		qcom,msm-cpudai-auxpcm-num-slots = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-slot-mapping = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-data = <0>, <0>;
+		qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+		qcom,msm-auxpcm-interface = "secondary";
+		qcom,msm-cpudai-afe-clk-ver = <2>;
+	};
+
+	qcom,msm-dai-mi2s {
+		compatible = "qcom,msm-dai-mi2s";
+		mi2s_prim: qcom,msm-dai-q6-mi2s-prim {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <0>;
+			qcom,msm-mi2s-rx-lines = <2>;
+			qcom,msm-mi2s-tx-lines = <1>;
+		};
+		mi2s_sec: qcom,msm-dai-q6-mi2s-sec {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <1>;
+			qcom,msm-mi2s-rx-lines = <2>;
+			qcom,msm-mi2s-tx-lines = <1>;
+		};
+	};
+
+	qcom,msm-thermal {
+		compatible = "qcom,msm-thermal";
+		qcom,sensor-id = <4>;
+		qcom,poll-ms = <250>;
+		qcom,limit-temp = <60>;
+		qcom,temp-hysteresis = <10>;
+		qcom,freq-step = <2>;
+		qcom,freq-mitigation-temp = <105>;
+		qcom,freq-mitigation-temp-hysteresis = <15>;
+		qcom,freq-mitigation-value = <800000>;
+		qcom,disable-cx-phase-ctrl;
+		qcom,disable-gfx-phase-ctrl;
+		qcom,disable-psm;
+		qcom,disable-ocr;
+		qcom,mx-restriction-temp = <10>;
+		qcom,mx-restriction-temp-hysteresis = <5>;
+		qcom,mx-retention-min =
+			<RPM_SMD_REGULATOR_LEVEL_NOM_PLUS>;
+		vdd-mx-supply = <&mdm9607_l12_floor_level>;
+		qcom,vdd-restriction-temp = <10>;
+		qcom,vdd-restriction-temp-hysteresis = <15>;
+		vdd-dig-supply = <&mdm9607_s3_floor_level>;
+		qcom,therm-ddr-lm-info = <2 78 70>;
+
+		qcom,vdd-dig-rstr{
+			qcom,vdd-rstr-reg = "vdd-dig";
+			qcom,levels = <RPM_SMD_REGULATOR_LEVEL_TURBO_NO_CPR
+					RPM_SMD_REGULATOR_LEVEL_BINNING
+					RPM_SMD_REGULATOR_LEVEL_BINNING>;
+			qcom,min-level = <RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+		};
+
+		 msm_thermal_freq: qcom,vdd-apps-rstr {
+			qcom,vdd-rstr-reg = "vdd-apps";
+			qcom,levels = <998400>;
+			qcom,freq-req;
+		};
+	};
+
+	qcom,sensor-information {
+		compatible = "qcom,sensor-information";
+		sensor_information0: qcom,sensor-information-0 {
+			qcom,sensor-type = "tsens";
+			qcom,sensor-name = "tsens_tz_sensor0";
+		};
+
+		sensor_information1: qcom,sensor-information-1 {
+			qcom,sensor-type =  "tsens";
+			qcom,sensor-name = "tsens_tz_sensor1";
+		};
+
+		sensor_information2: qcom,sensor-information-2 {
+			qcom,sensor-type =  "tsens";
+			qcom,sensor-name = "tsens_tz_sensor2";
+		};
+
+		sensor_information3: qcom,sensor-information-3 {
+			qcom,sensor-type = "tsens";
+			qcom,sensor-name = "tsens_tz_sensor3";
+		};
+
+		sensor_information4: qcom,sensor-information-4 {
+			qcom,sensor-type = "tsens";
+			qcom,sensor-name = "tsens_tz_sensor4";
+		};
+
+		sensor_information5: qcom,sensor-information-5 {
+			qcom,sensor-type = "adc";
+			qcom,sensor-name = "pa_therm0";
+		};
+
+		sensor_information6: qcom,sensor-information-6 {
+			qcom,sensor-type = "adc";
+			qcom,sensor-name = "pa_therm1";
+		};
+
+		sensor_information7: qcom,sensor-information-7 {
+			qcom,sensor-type = "adc";
+			qcom,sensor-name = "xo_therm";
+		};
+
+		sensor_information8: qcom,sensor-information-8 {
+			qcom,sensor-type = "adc";
+			qcom,sensor-name = "xo_therm_amux";
+		};
+	};
+
+	mitigation_profile0: qcom,limit_info-0 {
+		qcom,temperature-sensor = <&sensor_information4>;
+		qcom,boot-frequency-mitigate;
+		qcom,emergency-frequency-mitigate;
+	};
+
+	qcom,ipc-spinlock@1905000 {
+		compatible = "qcom,ipc-spinlock-sfpb";
+		reg = <0x1905000 0x8000>;
+		qcom,num-locks = <8>;
+	};
+
+	qcom,smem@87d00000 {
+		compatible = "qcom,smem";
+		reg = <0x87d00000 0x100000>,
+			<0x0b011008 0x4>,
+			<0x60000 0x8000>,
+			<0x193d000 0x8>;
+		reg-names = "smem", "irq-reg-base", "aux-mem1",
+				"smem_targ_info_reg";
+		qcom,mpu-enabled;
+
+		qcom,smd-modem {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <0>;
+			qcom,smd-irq-offset = <0x0>;
+			qcom,smd-irq-bitmask = <0x1000>;
+			interrupts = <0 25 1>;
+			label = "modem";
+			qcom,not-loadable;
+		};
+
+		qcom,smsm-modem {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <0>;
+			qcom,smsm-irq-offset = <0x0>;
+			qcom,smsm-irq-bitmask = <0x2000>;
+			interrupts = <0 26 1>;
+		};
+
+		qcom,smd-rpm {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <15>;
+			qcom,smd-irq-offset = <0x0>;
+			qcom,smd-irq-bitmask = <0x1>;
+			interrupts = <0 168 1>;
+			label = "rpm";
+			qcom,irq-no-suspend;
+			qcom,not-loadable;
+		};
+	};
+
+	rpm_bus: qcom,rpm-smd {
+		compatible = "qcom,rpm-smd";
+		rpm-channel-name = "rpm_requests";
+		rpm-channel-type = <15>; /* SMD_APPS_RPM */
+	};
+
+	qcom,smdtty {
+		compatible = "qcom,smdtty";
+
+		smdtty_data1: qcom,smdtty-data1 {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "DATA1";
+		};
+
+		smdtty_data4: qcom,smdtty-data4 {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "DATA4";
+		};
+
+		smdtty_data11: qcom,smdtty-data11 {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "DATA11";
+		};
+
+		smdtty_data21: qcom,smdtty-data21 {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "DATA21";
+		};
+
+		smdtty_loopback: smdtty-loopback {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "LOOPBACK";
+			qcom,smdtty-dev-name = "LOOPBACK_TTY";
+		};
+	};
+
+	qcom,smdpkt {
+		compatible = "qcom,smdpkt";
+
+		qcom,smdpkt-data5-cntl {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "DATA5_CNTL";
+			qcom,smdpkt-dev-name = "smdcntl0";
+		};
+
+		qcom,smdpkt-data22 {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "DATA22";
+			qcom,smdpkt-dev-name = "smd22";
+		};
+
+		qcom,smdpkt-data40-cntl {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "DATA40_CNTL";
+			qcom,smdpkt-dev-name = "smdcntl8";
+		};
+
+		qcom,smdpkt-apr-apps2 {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "apr_apps2";
+			qcom,smdpkt-dev-name = "apr_apps2";
+		};
+
+		qcom,smdpkt-loopback {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "LOOPBACK";
+			qcom,smdpkt-dev-name = "smd_pkt_loopback";
+		};
+	};
+
+	qcom,ipc_router {
+		compatible = "qcom,ipc_router";
+		qcom,node-id = <1>;
+	};
+
+	qcom,ipc_router_modem_xprt {
+		compatible = "qcom,ipc_router_smd_xprt";
+		qcom,ch-name = "IPCRTR";
+		qcom,xprt-remote = "modem";
+		qcom,xprt-linkid = <1>;
+		qcom,xprt-version = <1>;
+		qcom,fragmented-data;
+		qcom,disable-pil-loading;
+	};
+
+	qcom,bam_dmux@4044000 {
+		compatible = "qcom,bam_dmux";
+		reg = <0x4044000 0x19000>;
+		interrupts = <0 29 1>;
+		qcom,rx-ring-size = <32>;
+		qcom,max-rx-mtu = <4096>;
+		qcom,fast-shutdown;
+	};
+
+	spmi_bus: qcom,spmi@200f000 {
+		compatible = "qcom,spmi-pmic-arb";
+		reg = <0x200f000 0x1000>,
+			<0x2400000 0x800000>,
+			<0x2c00000 0x800000>,
+			<0x3800000 0x200000>,
+			<0x200a000 0x2100>;
+		reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+		interrupts = <0 190 0>;
+		qcom,pmic-arb-channel = <0>;
+		qcom,pmic-arb-max-peripherals = <128>;
+		qcom,pmic-arb-max-periph-interrupts = <128>;
+		qcom,pmic-arb-ee = <0>;
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cell-index = <0>;
+	};
+
+	spi_1: spi@78b6000 { /* BLSP1 QUP1 */
+		compatible = "qcom,spi-qup-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "spi_physical", "spi_bam_physical";
+		reg = <0x78b6000 0x600>,
+		      <0x7884000 0x2b000>;
+		interrupt-names = "spi_irq", "spi_bam_irq";
+		interrupts = <0 96 0>, <0 238 0>;
+		spi-max-frequency = <19200000>;
+		pinctrl-names = "spi_default", "spi_sleep";
+		pinctrl-0 = <&spi1_default &spi1_cs0_active>;
+		pinctrl-1 = <&spi1_sleep &spi1_cs0_sleep>;
+		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+			 <&clock_gcc clk_gcc_blsp1_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 = <14>;
+		qcom,bam-producer-pipe-index = <15>;
+		qcom,master-id = <86>;
+		status = "disabled";
+	};
+
+	qcom,mss@4080000 {
+		compatible = "qcom,pil-q6v55-mss";
+		reg =   <0x04080000 0x100>,
+			<0x0194f000 0x010>,
+			<0x01950000 0x008>,
+			<0x01951000 0x008>,
+			<0x04020000 0x040>,
+			<0x0183e000 0x004>;
+		reg-names = "qdsp6_base", "halt_q6", "halt_modem", "halt_nc",
+				"rmb_base", "restart_reg";
+
+		interrupts = <0 24 1>;
+		vdd_cx-supply = <&mdm9607_s3_level>;
+		vdd_cx-voltage = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+		vdd_mx-supply = <&mdm9607_l12_level>;
+		vdd_pll-supply = <&mdm9607_l3>;
+		qcom,vdd_pll = <1800000>;
+
+		clocks = <&clock_gcc clk_xo_pil_mss_clk>,
+			 <&clock_gcc clk_gcc_mss_cfg_ahb_clk>,
+			 <&clock_gcc clk_gcc_mss_q6_bimc_axi_clk>,
+			 <&clock_gcc clk_gcc_boot_rom_ahb_clk>;
+		clock-names = "xo", "iface_clk", "bus_clk", "mem_clk";
+		qcom,proxy-clock-names = "xo";
+		qcom,active-clock-names = "iface_clk", "bus_clk", "mem_clk";
+
+		qcom,firmware-name = "modem";
+		qcom,pil-self-auth;
+		qcom,override-acc-1 = <0x80800000>;
+		qcom,sysmon-id = <0>;
+		qcom,ssctl-instance-id = <0x12>;
+		qcom,qdsp6v56-1-8-inrush-current;
+
+		/* GPIO inputs from mss */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
+		qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_1_in 3 0>;
+		qcom,gpio-shutdown-ack = <&smp2pgpio_ssr_smp2p_1_in 7 0>;
+
+		/* GPIO output to mss */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
+		memory-region = <&modem_adsp_mem>;
+	};
+
+	sdhc_2: sdhci@07864900 {
+		compatible = "qcom,sdhci-msm";
+		reg = <0x07864900 0x200>, <0x07864000 0x800>;
+		reg-names = "hc_mem", "core_mem";
+
+		interrupts = <0 125 0>, <0 221 0>;
+		interrupt-names = "hc_irq", "pwr_irq";
+
+		qcom,bus-width = <4>;
+
+		qcom,devfreq,freq-table = <50000000 200000000>;
+
+		qcom,msm-bus,name = "sdhc2";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
+				<81 512 1600 3200>,    /* 400 KB/s*/
+				<81 512 80000 160000>, /* 20 MB/s */
+				<81 512 100000 200000>, /* 25 MB/s */
+				<81 512 200000 400000>, /* 50 MB/s */
+				<81 512 400000 800000>, /* 100 MB/s */
+				<81 512 800000 800000>, /* 200 MB/s */
+				<81 512 2048000 4096000>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+						100000000 200000000 4294967295>;
+
+		clocks = <&clock_gcc clk_gcc_sdcc2_ahb_clk>,
+			 <&clock_gcc clk_gcc_sdcc2_apps_clk>;
+		clock-names = "iface_clk", "core_clk";
+
+		qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+
+		qcom,pm-qos-irq-type = "affine_irq";
+		qcom,pm-qos-irq-latency = <2 250>;
+
+		status = "disabled";
+	};
+
+	qrng: rng@22000 {
+		compatible = "qcom,msm-rng";
+		reg = <0x22000 0x140>;
+		qcom,msm-rng-iface-clk;
+		qcom,msm-bus,name = "msm-rng-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<1 618 0 0>,
+			<1 618 0 800>;
+		clocks = <&clock_gcc clk_gcc_prng_ahb_clk>;
+		clock-names = "iface_clk";
+	};
+
+	qcom_crypto: qcrypto@720000 {
+		compatible = "qcom,qcrypto";
+		reg = <0x720000 0x20000>,
+			<0x704000 0x20000>;
+		reg-names = "crypto-base","crypto-bam-base";
+		interrupts = <0 207 0>;
+		qcom,bam-pipe-pair = <2>;
+		qcom,ce-hw-instance = <0>;
+		qcom,ce-device = <0>;
+		qcom,clk-mgmt-sus-res;
+		qcom,msm-bus,name = "qcrypto-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<47 512 0 0>,
+				<47 512 393600 800000>;
+		clocks = <&clock_gcc clk_crypto_clk_src>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>;
+		clock-names = "core_clk_src", "core_clk",
+				"iface_clk", "bus_clk";
+		qcom,use-sw-aes-cbc-ecb-ctr-algo;
+		qcom,use-sw-aes-xts-algo;
+		qcom,use-sw-aes-ccm-algo;
+		qcom,use-sw-ahash-algo;
+		qcom,use-sw-hmac-algo;
+		qcom,use-sw-aead-algo;
+		qcom,ce-opp-freq = <100000000>;
+	};
+
+	qcom_qcedev: qcedev@720000 {
+		compatible = "qcom,qcedev";
+		reg = <0x720000 0x20000>,
+			<0x704000 0x20000>;
+		reg-names = "crypto-base","crypto-bam-base";
+		interrupts = <0 207 0>;
+		qcom,bam-pipe-pair = <1>;
+		qcom,ce-hw-instance = <0>;
+		qcom,ce-device = <0>;
+		qcom,ce-hw-shared;
+		qcom,msm-bus,name = "qcedev-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<47 512 0 0>,
+				<47 512 3936000 393600>;
+		clocks = <&clock_gcc clk_crypto_clk_src>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>;
+		clock-names = "core_clk_src", "core_clk",
+				"iface_clk", "bus_clk";
+		qcom,ce-opp-freq = <100000000>;
+	};
+
+	qcom_seecom: qseecom@87a80000 {
+		compatible = "qcom,qseecom";
+		reg = <0x87a80000 0x100000>;
+		reg-names = "secapp-region";
+		qcom,hlos-ce-hw-instance = <0>;
+		qcom,qsee-ce-hw-instance = <0>;
+		qcom,msm-bus,name = "qseecom-noc";
+		qcom,msm-bus,num-cases = <4>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<47 512 0 0>,
+				<47 512 0 0>,
+				<47 512 120000 1200000>,
+				<47 512 393600 3936000>;
+		clocks = <&clock_gcc clk_crypto_clk_src>,
+			<&clock_gcc clk_gcc_crypto_clk>,
+			<&clock_gcc clk_gcc_crypto_ahb_clk>,
+			<&clock_gcc clk_gcc_crypto_axi_clk>;
+		clock-names = "core_clk_src", "core_clk",
+				"iface_clk", "bus_clk";
+		qcom,ce-opp-freq = <100000000>;
+		status = "disabled";
+	};
+
+	pps {
+		compatible = "pps-gpio";
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pps>;
+		gpios = <&tlmm_pinmux 53 0>;
+		status = "okay";
+	};
+};
+
+#include "mdm9607-rpm-regulator.dtsi"
+#include "msm-pm8019.dtsi"
+#include "mdm9607-regulator.dtsi"
+
+/* MPP pin 1 config for USB ID interrupt line */
+&pm8019_mpps {
+	mpp@a000 {
+		qcom,mode = <0>;	/* Digital input */
+		qcom,vin-sel = <3>;	/* 1.8V (L11) */
+		qcom,src-sel = <0>;	/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,pull = <2>;	/* PULL UP 10KOHM */
+		qcom,master-en = <1>;
+		status = "okay";
+	};
+};
+
+&pm8019_vadc {
+	chan@6 {
+		label = "vbat_sns";
+		reg = <6>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <1>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@7 {
+		label = "vph_pwr";
+		reg = <7>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <1>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@31 {
+		label = "batt_id_therm";
+		reg = <0x31>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	 };
+
+	chan@33 {
+		label = "pa_therm0";
+		reg = <0x33>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@34 {
+		label = "pa_therm1";
+		reg = <0x34>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@32 {
+		label = "xo_therm";
+		reg = <0x32>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <4>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@3c {
+		label = "xo_therm_amux";
+		reg = <0x3c>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <4>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+	};
+};
+
+&pm8019_adc_tm {
+	/* Channel Node */
+	chan@33 {
+		label = "pa_therm0";
+		reg = <0x33>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+		qcom,btm-channel-number = <0x48>;
+		qcom,thermal-node;
+	};
+
+	chan@34 {
+		label = "pa_therm1";
+		reg = <0x34>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+		qcom,btm-channel-number = <0x68>;
+		qcom,thermal-node;
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/msm-pm8019.dtsi b/arch/arm/boot/dts/qcom/msm-pm8019.dtsi
new file mode 100644
index 0000000..afb4723
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/msm-pm8019.dtsi
@@ -0,0 +1,421 @@
+/* Copyright (c) 2012, 2013, 2015, Linux Foundation. All rights reserved.
+ *
+ * This 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.
+ */
+
+&spmi_bus {
+	#address-cells = <1>;
+	#size-cells = <0>;
+	interrupt-controller;
+	#interrupt-cells = <3>;
+
+	qcom,pm8019@0 {
+		spmi-slave-container;
+		reg = <0x0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		pm8019_revid: qcom,revid@100 {
+			compatible = "qcom,qpnp-revid";
+			reg = <0x100 0x100>;
+		};
+
+		qcom,power_on@800 {
+			compatible = "qcom,qpnp-power-on";
+			reg = <0x800 0x100>;
+			interrupts = <0x0 0x8 0x2>;
+			interrupt-names = "cblpwr";
+			qcom,pon-dbc-delay = <15625>;
+			qcom,system-reset;
+
+			qcom,pon_1 {
+				qcom,pon-type = <2>;
+				qcom,pull-up = <1>;
+				linux,code = <116>;
+			};
+		};
+
+		clkdiv@5b00 {
+			reg = <0x5b00 0x100>;
+			compatible = "qcom,qpnp-clkdiv";
+			qcom,cxo-freq = <19200000>;
+		};
+
+		clkdiv@5c00 {
+			reg = <0x5c00 0x100>;
+			compatible = "qcom,qpnp-clkdiv";
+			qcom,cxo-freq = <19200000>;
+		};
+
+		clkdiv@5d00 {
+			reg = <0x5d00 0x100>;
+			compatible = "qcom,qpnp-clkdiv";
+			qcom,cxo-freq = <19200000>;
+		};
+
+		rtc {
+			spmi-dev-container;
+			compatible = "qcom,qpnp-rtc";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			qcom,qpnp-rtc-write = <0>;
+			qcom,qpnp-rtc-alarm-pwrup = <0>;
+
+			qcom,pm8019_rtc_rw@6000 {
+				reg = <0x6000 0x100>;
+			};
+
+			qcom,pm8019_rtc_alarm@6100 {
+				reg = <0x6100 0x100>;
+				interrupts = <0x0 0x61 0x1>;
+			};
+		};
+
+		pm8019_gpios: gpios {
+			spmi-dev-container;
+			compatible = "qcom,qpnp-pin";
+			gpio-controller;
+			#gpio-cells = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			label = "pm8019-gpio";
+
+			gpio@c000 {
+				reg = <0xc000 0x100>;
+				qcom,pin-num = <1>;
+			};
+
+			gpio@c100 {
+				reg = <0xc100 0x100>;
+				qcom,pin-num = <2>;
+			};
+
+			gpio@c200 {
+				reg = <0xc200 0x100>;
+				qcom,pin-num = <3>;
+			};
+
+			gpio@c300 {
+				reg = <0xc300 0x100>;
+				qcom,pin-num = <4>;
+			};
+
+			gpio@c400 {
+				reg = <0xc400 0x100>;
+				qcom,pin-num = <5>;
+			};
+
+			gpio@c500 {
+				reg = <0xc500 0x100>;
+				qcom,pin-num = <6>;
+			};
+		};
+
+		pm8019_mpps: mpps {
+			spmi-dev-container;
+			compatible = "qcom,qpnp-pin";
+			gpio-controller;
+			#gpio-cells = <2>;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			label = "pm8019-mpp";
+
+			mpp@a000 {
+				reg = <0xa000 0x100>;
+				qcom,pin-num = <1>;
+			};
+
+			mpp@a100 {
+				reg = <0xa100 0x100>;
+				qcom,pin-num = <2>;
+			};
+
+			mpp@a200 {
+				reg = <0xa200 0x100>;
+				qcom,pin-num = <3>;
+			};
+
+			mpp@a300 {
+				reg = <0xa300 0x100>;
+				qcom,pin-num = <4>;
+			};
+
+			mpp@a400 {
+				reg = <0xa400 0x100>;
+				qcom,pin-num = <5>;
+			};
+
+			mpp@a500 {
+				reg = <0xa500 0x100>;
+				qcom,pin-num = <6>;
+			};
+		};
+
+		pm8019_vadc: vadc@3100 {
+			compatible = "qcom,qpnp-vadc";
+			reg = <0x3100 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0x0 0x31 0x0>;
+			interrupt-names = "eoc-int-en-set";
+			qcom,adc-bit-resolution = <15>;
+			qcom,adc-vdd-reference = <1800>;
+			qcom,vadc-poll-eoc;
+
+			chan@8 {
+				label = "die_temp";
+				reg = <8>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <3>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@9 {
+				label = "ref_625mv";
+				reg = <9>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@a {
+				label = "ref_1250v";
+				reg = <0xa>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+		};
+
+		pm8019_adc_tm: vadc@3400 {
+			compatible = "qcom,qpnp-adc-tm";
+			reg = <0x3400 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0x0 0x34 0x0>,
+					<0x0 0x34 0x3>,
+					<0x0 0x34 0x4>;
+			interrupt-names = "eoc-int-en-set",
+						"high-thr-en-set",
+						"low-thr-en-set";
+			qcom,adc-bit-resolution = <15>;
+			qcom,adc_tm-vadc = <&pm8019_vadc>;
+			qcom,adc-vdd-reference = <1800>;
+		};
+	};
+
+	qcom,pm8019@1 {
+		spmi-slave-container;
+		reg = <0x1>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		regulator@1400 {
+			regulator-name = "8019_s1";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x1400 0x300>;
+			status = "disabled";
+
+			qcom,ctl@1400 {
+				reg = <0x1400 0x100>;
+			};
+			qcom,ps@1500 {
+				reg = <0x1500 0x100>;
+			};
+			qcom,freq@1600 {
+				reg = <0x1600 0x100>;
+			};
+		};
+
+		regulator@1700 {
+			regulator-name = "8019_s2";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x1700 0x300>;
+			status = "disabled";
+
+			qcom,ctl@1700 {
+				reg = <0x1700 0x100>;
+			};
+			qcom,ps@1800 {
+				reg = <0x1800 0x100>;
+			};
+			qcom,freq@1900 {
+				reg = <0x1900 0x100>;
+			};
+		};
+
+		regulator@1a00 {
+			regulator-name = "8019_s3";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x1a00 0x300>;
+			status = "disabled";
+
+			qcom,ctl@1a00 {
+				reg = <0x1a00 0x100>;
+			};
+			qcom,ps@1b00 {
+				reg = <0x1b00 0x100>;
+			};
+			qcom,freq@1c00 {
+				reg = <0x1c00 0x100>;
+			};
+		};
+
+		regulator@1d00 {
+			regulator-name = "8019_s4";
+			spmi-dev-container;
+			#address-cells = <1>;
+			#size-cells = <1>;
+			compatible = "qcom,qpnp-regulator";
+			reg = <0x1d00 0x300>;
+			status = "disabled";
+
+			qcom,ctl@1d00 {
+				reg = <0x1d00 0x100>;
+			};
+			qcom,ps@1e00 {
+				reg = <0x1e00 0x100>;
+			};
+			qcom,freq@1f00 {
+				reg = <0x1f00 0x100>;
+			};
+		};
+
+		regulator@4000 {
+			regulator-name = "8019_l1";
+			reg = <0x4000 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4100 {
+			regulator-name = "8019_l2";
+			reg = <0x4100 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4200 {
+			regulator-name = "8019_l3";
+			reg = <0x4200 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4300 {
+			regulator-name = "8019_l4";
+			reg = <0x4300 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4400 {
+			regulator-name = "8019_l5";
+			reg = <0x4400 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4500 {
+			regulator-name = "8019_l6";
+			reg = <0x4500 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4600 {
+			regulator-name = "8019_l7";
+			reg = <0x4600 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4700 {
+			regulator-name = "8019_l8";
+			reg = <0x4700 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4800 {
+			regulator-name = "8019_l9";
+			reg = <0x4800 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4900 {
+			regulator-name = "8019_l10";
+			reg = <0x4900 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4a00 {
+			regulator-name = "8019_l11";
+			reg = <0x4a00 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4b00 {
+			regulator-name = "8019_l12";
+			reg = <0x4b00 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4c00 {
+			regulator-name = "8019_l13";
+			reg = <0x4c00 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4d00 {
+			regulator-name = "8019_l14";
+			reg = <0x4d00 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4e00 {
+			regulator-name = "8019_ldo_xo";
+			reg = <0x4e00 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+
+		regulator@4f00 {
+			regulator-name = "8019_ldo_rfclk";
+			reg = <0x4f00 0x100>;
+			compatible = "qcom,qpnp-regulator";
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-bus.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-bus.dtsi
index ad1e6ca..b4e91ab 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-bus.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-bus.dtsi
@@ -35,6 +35,14 @@
 		};
 
 		/*BCMs*/
+		bcm_acv: bcm-acv {
+			cell-id = <MSM_BUS_BCM_ACV>;
+			label = "ACV";
+			qcom,bcm-name = "ACV";
+			qcom,rscs = <&rsc_apps>;
+			qcom,bcm-dev;
+		};
+
 		bcm_alc: bcm-alc {
 			cell-id = <MSM_BUS_BCM_ALC>;
 			label = "ALC";
@@ -564,6 +572,15 @@
 			qcom,prio = <0>;
 		};
 
+		mas_alc: mas-alc {
+			cell-id = <MSM_BUS_MASTER_ALC>;
+			label = "mas-alc";
+			qcom,buswidth = <1>;
+			qcom,agg-ports = <1>;
+			qcom,bus-dev = <&fab_mc_virt>;
+			qcom,bcms = <&bcm_alc>;
+		};
+
 		/*Internal nodes*/
 
 		/*Slaves*/
@@ -583,7 +600,7 @@
 			qcom,buswidth = <4>;
 			qcom,agg-ports = <1>;
 			qcom,bus-dev = <&fab_mc_virt>;
-			qcom,bcms = <&bcm_mc0>;
+			qcom,bcms = <&bcm_mc0>, <&bcm_acv>;
 		};
 
 		slv_qns_llcc:slv-qns-llcc {
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dtsi
index 19b4164..8c506b9 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-cdp.dtsi
@@ -15,8 +15,6 @@
 #include "sdxpoorwills-cdp-audio-overlay.dtsi"
 
 &serial_uart {
-	pinctrl-names = "default";
-	pinctrl-0 = <&uart3_console_active>;
 	status = "ok";
 };
 
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dts
new file mode 100644
index 0000000..6909ef5
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dts
@@ -0,0 +1,30 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdxpoorwills-dualwifi-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDXPOORWILLS DUAL-WIFI CDP";
+	compatible = "qcom,sdxpoorwills-cdp",
+		"qcom,sdxpoorwills", "qcom,cdp";
+	qcom,board-id = <1 0x105>;
+};
+
+&cnss_pcie {
+	qcom,is-dual-wifi-enabled;
+};
+
+&cnss_sdio {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dtsi
new file mode 100644
index 0000000..8a7b771
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-cdp.dtsi
@@ -0,0 +1,13 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "sdxpoorwills-cdp.dtsi"
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts
new file mode 100644
index 0000000..5fd7042
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts
@@ -0,0 +1,30 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdxpoorwills-dualwifi-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDXPOORWILLS DUAL-WIFI MTP";
+	compatible = "qcom,sdxpoorwills-mtp",
+		"qcom,sdxpoorwills", "qcom,mtp";
+	qcom,board-id = <8 0x104>;
+};
+
+&cnss_pcie {
+	qcom,is-dual-wifi-enabled;
+};
+
+&cnss_sdio {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi
new file mode 100644
index 0000000..4a2ece8c
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi
@@ -0,0 +1,13 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "sdxpoorwills-mtp.dtsi"
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dtsi
index 6389e95..ef1150a 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-mtp.dtsi
@@ -15,8 +15,6 @@
 #include "sdxpoorwills-mtp-audio-overlay.dtsi"
 
 &serial_uart {
-	pinctrl-names = "default";
-	pinctrl-0 = <&uart3_console_active>;
 	status = "ok";
 };
 
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
new file mode 100644
index 0000000..cbbf585
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp-256.dts
@@ -0,0 +1,22 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdxpoorwills-pcie-ep-cdp-256.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDXPOORWILLS(M) PCIE-EP CDP";
+	compatible = "qcom,sdxpoorwills-cdp",
+		"qcom,sdxpoorwills", "qcom,cdp";
+	qcom,board-id = <1 0x1>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp-256.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp-256.dtsi
new file mode 100644
index 0000000..518d8a1
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp-256.dtsi
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "sdxpoorwills-cdp.dtsi"
+
+&vbus_detect {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+	extcon = <&vbus_detect>;
+};
+
+&pcie_ep {
+	status = "okay";
+};
+
+&pcie0 {
+	status = "disabled";
+};
+
+&mhi_device {
+	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 52eaba3..2a2e496 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dts
@@ -12,32 +12,12 @@
 
 /dts-v1/;
 
-#include "sdxpoorwills-cdp.dtsi"
+#include "sdxpoorwills-pcie-ep-cdp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDXPOORWILLS PCIE-EP CDP";
 	compatible = "qcom,sdxpoorwills-cdp",
 		"qcom,sdxpoorwills", "qcom,cdp";
-	qcom,board-id = <1 0x1>, <1 0x101>;
+	qcom,board-id = <1 0x106>;
 };
 
-&vbus_detect {
-	status = "okay";
-};
-
-&usb {
-	status = "okay";
-	extcon = <&vbus_detect>;
-};
-
-&pcie_ep {
-	status = "okay";
-};
-
-&pcie0 {
-	status = "disabled";
-};
-
-&mhi_device {
-	status = "okay";
-};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dtsi
new file mode 100644
index 0000000..518d8a1
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dtsi
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "sdxpoorwills-cdp.dtsi"
+
+&vbus_detect {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+	extcon = <&vbus_detect>;
+};
+
+&pcie_ep {
+	status = "okay";
+};
+
+&pcie0 {
+	status = "disabled";
+};
+
+&mhi_device {
+	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
new file mode 100644
index 0000000..6b6aab5
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp-256.dts
@@ -0,0 +1,22 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdxpoorwills-pcie-ep-mtp-256.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDXPOORWILLS(M) PCIE-EP MTP";
+	compatible = "qcom,sdxpoorwills-mtp",
+		"qcom,sdxpoorwills", "qcom,mtp";
+	qcom,board-id = <8 0x1>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp-256.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp-256.dtsi
new file mode 100644
index 0000000..eb544e6
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp-256.dtsi
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "sdxpoorwills-mtp.dtsi"
+
+&vbus_detect {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+	extcon = <&vbus_detect>;
+};
+
+&pcie_ep {
+	status = "okay";
+};
+
+&pcie0 {
+	status = "disabled";
+};
+
+&mhi_device {
+	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 b68e401..8c22348 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dts
@@ -12,32 +12,11 @@
 
 /dts-v1/;
 
-#include "sdxpoorwills-mtp.dtsi"
+#include "sdxpoorwills-pcie-ep-mtp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDXPOORWILLS PCIE-EP MTP";
 	compatible = "qcom,sdxpoorwills-mtp",
 		"qcom,sdxpoorwills", "qcom,mtp";
-	qcom,board-id = <8 0x1>, <8 0x101>;
-};
-
-&vbus_detect {
-	status = "okay";
-};
-
-&usb {
-	status = "okay";
-	extcon = <&vbus_detect>;
-};
-
-&pcie_ep {
-	status = "okay";
-};
-
-&pcie0 {
-	status = "disabled";
-};
-
-&mhi_device {
-	status = "okay";
+	qcom,board-id = <8 0x105>;
 };
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dtsi
new file mode 100644
index 0000000..eb544e6
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dtsi
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "sdxpoorwills-mtp.dtsi"
+
+&vbus_detect {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+	extcon = <&vbus_detect>;
+};
+
+&pcie_ep {
+	status = "okay";
+};
+
+&pcie0 {
+	status = "disabled";
+};
+
+&mhi_device {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
index 4111071..ce4d882 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
@@ -39,7 +39,7 @@
 			qcom,pm-cluster-level@1 {
 				reg = <1>;
 				label = "cx_min";
-				qcom,psci-mode = <0x0>;
+				qcom,psci-mode = <0x4>;
 				qcom,latency-us = <285>;
 				qcom,ss-power = <442>;
 				qcom,energy-overhead = <306621>;
@@ -81,7 +81,7 @@
 				qcom,pm-cpu-level@2 {
 					reg = <2>;
 					label = "system-pc";
-					qcom,psci-cpu-mode = <0x8>;
+					qcom,psci-cpu-mode = <0x4>;
 					qcom,latency-us = <270>;
 					qcom,ss-power = <455>;
 					qcom,energy-overhead = <270621>;
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index b125e08..98d09de 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -43,6 +43,16 @@
 			label = "sbl_mem";
 		};
 
+		flex_sec_apps_mem: flex_sec_apps_regions@8fcfd000 {
+			no-map;
+			reg = <0x8fcfd000 0x3000>;
+		};
+
+		access_control_mem: access_control_mem@8fc80000 {
+			no-map;
+			reg = <0x8fc80000 0x40000>;
+		};
+
 		hyp_region: hyp_region@8fc00000 {
 			no-map;
 			reg = <0x8fc00000 0x80000>;
@@ -278,6 +288,9 @@
 		clocks = <&clock_gcc GCC_BLSP1_UART3_APPS_CLK>,
 			<&clock_gcc GCC_BLSP1_AHB_CLK>;
 		clock-names = "core", "iface";
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&uart3_console_active>;
+		pinctrl-1 = <&uart3_console_sleep>;
 	};
 
 	gdsc_usb30: qcom,gdsc@10b004 {
@@ -516,6 +529,8 @@
 			<&clock_gcc GCC_SDCC1_APPS_CLK>;
 		clock-names = "iface_clk", "core_clk";
 
+		qcom,restore-after-cx-collapse;
+
 		status = "disabled";
 	};
 
@@ -823,6 +838,8 @@
 		qcom,mhi-event-ring-id-limits = <9 10>; /* start and end */
 		qcom,modem-cfg-emb-pipe-flt;
 		qcom,use-ipa-pm;
+		qcom,arm-smmu;
+		qcom,smmu-fast-map;
 		qcom,bandwidth-vote-for-ipa;
 		qcom,msm-bus,name = "ipa";
 		qcom,msm-bus,num-cases = <5>;
@@ -964,6 +981,33 @@
 			compatible = "qcom,smp2pgpio-map-ipa-1-in";
 			gpios = <&smp2pgpio_ipa_1_in 0 0>;
 		};
+
+		ipa_smmu_ap: ipa_smmu_ap {
+			compatible = "qcom,ipa-smmu-ap-cb";
+			qcom,smmu-s1-bypass;
+			iommus = <&apps_smmu 0x5E0 0x0>;
+			qcom,iova-mapping = <0x20000000 0x40000000>;
+			qcom,additional-mapping =
+				/* modem tables in IMEM */
+				<0x14686000 0x14686000 0x3000>;
+			qcom,ipa-q6-smem-size = <16384>;
+		};
+
+		ipa_smmu_wlan: ipa_smmu_wlan {
+			compatible = "qcom,ipa-smmu-wlan-cb";
+			qcom,smmu-s1-bypass;
+			iommus = <&apps_smmu 0x5E1 0x0>;
+			qcom,additional-mapping =
+				/* ipa-uc ram */
+				<0x1E60000 0x1E60000 0xA000>;
+		};
+
+		ipa_smmu_uc: ipa_smmu_uc {
+			compatible = "qcom,ipa-smmu-uc-cb";
+			qcom,smmu-s1-bypass;
+			iommus = <&apps_smmu 0x5E2 0x0>;
+			qcom,iova-mapping = <0x40000000 0x20000000>;
+		};
 	};
 
 	qmp_aop: qcom,qmp-aop@c300000 {
@@ -1142,12 +1186,12 @@
 			<0x36000 0x100>,
 			<0x3900000 0x300000>;
 		reg-names = "emac-base", "rgmii-base", "tlmm-central-base";
-		interrupts = <0 62 4>, <0 60 4>,
-			<0 45 4>, <0 49 4>,
-			<0 50 4>, <0 51 4>,
-			<0 52 4>, <0 53 4>,
-			<0 54 4>, <0 55 4>,
-			<0 56 4>, <0 57 4>;
+		interrupts-extended = <&pdc 0 62 4>, <&pdc 0 60 4>,
+			<&tlmm 84 2>, <&pdc 0 49 4>,
+			<&pdc 0 50 4>, <&pdc 0 51 4>,
+			<&pdc 0 52 4>, <&pdc 0 53 4>,
+			<&pdc 0 54 4>, <&pdc 0 55 4>,
+			<&pdc 0 56 4>, <&pdc 0 57 4>;
 		interrupt-names = "sbd-intr", "lpi-intr",
 			"wol-intr", "tx-ch0-intr",
 			"tx-ch1-intr", "tx-ch2-intr",
diff --git a/arch/arm/configs/mdm9607-perf_defconfig b/arch/arm/configs/mdm9607-perf_defconfig
new file mode 100644
index 0000000..1728981
--- /dev/null
+++ b/arch/arm/configs/mdm9607-perf_defconfig
@@ -0,0 +1,293 @@
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MDM9607=y
+# CONFIG_VDSO is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CMA=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IPGRE=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_INET6_ESP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y
+CONFIG_IPV6_GRE=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=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_SNMP=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_CT_NETLINK_TIMEOUT=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_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=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_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_IP_SET=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_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_NATTYPE_MODULE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=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_AH=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+CONFIG_IP6_NF_MATCH_RT=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_BRIDGE_EBT_T_FILTER=y
+CONFIG_BRIDGE_EBT_T_NAT=y
+CONFIG_BRIDGE_EBT_ARP=y
+CONFIG_BRIDGE_EBT_IP=y
+CONFIG_BRIDGE_EBT_IP6=y
+CONFIG_BRIDGE_EBT_ARPREPLY=y
+CONFIG_BRIDGE_EBT_DNAT=y
+CONFIG_BRIDGE_EBT_SNAT=y
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_CAN=y
+CONFIG_CAN_VCAN=y
+CONFIG_BT=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_RFKILL=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=4
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+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
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+CONFIG_KS8851=y
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_QCOM_EMAC=m
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_AT803X_PHY=m
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_USB_USBNET=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CNSS=y
+CONFIG_CNSS_SDIO=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=m
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SPI=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_PPS_CLIENT_GPIO=y
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_PINCTRL_MDM9607=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_SMB1351_USB_CHARGER=y
+CONFIG_THERMAL=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_RTC_CLASS=y
+CONFIG_DMADEVICES=y
+CONFIG_UIO=y
+CONFIG_STAGING=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_USB_BAM=y
+CONFIG_COMMON_CLK_MSM=y
+CONFIG_MAILBOX=y
+CONFIG_MSM_SPM=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_TRACER_PKT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_CNSS_CRYPTO=y
+CONFIG_IIO=y
+CONFIG_IIO_BUFFER=y
+CONFIG_IIO_BUFFER_CB=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_ANDROID=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PAGE_POISONING=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_IPC_LOGGING=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
+CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/mdm9607_defconfig b/arch/arm/configs/mdm9607_defconfig
new file mode 100644
index 0000000..f6dfe7f
--- /dev/null
+++ b/arch/arm/configs/mdm9607_defconfig
@@ -0,0 +1,300 @@
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MDM9607=y
+# CONFIG_VDSO is not set
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CMA=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IPGRE=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_INET6_ESP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=y
+CONFIG_IPV6_GRE=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_DEBUG=y
+CONFIG_BRIDGE_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+CONFIG_NF_CONNTRACK_TIMESTAMP=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_SNMP=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SIP=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NF_CT_NETLINK_TIMEOUT=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_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+CONFIG_NETFILTER_XT_MATCH_CONNLABEL=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_IPRANGE=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_IP_SET=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_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_NATTYPE_MODULE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=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_AH=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+CONFIG_IP6_NF_MATCH_RT=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_BRIDGE_EBT_T_FILTER=y
+CONFIG_BRIDGE_EBT_T_NAT=y
+CONFIG_BRIDGE_EBT_ARP=y
+CONFIG_BRIDGE_EBT_IP=y
+CONFIG_BRIDGE_EBT_IP6=y
+CONFIG_BRIDGE_EBT_ARPREPLY=y
+CONFIG_BRIDGE_EBT_DNAT=y
+CONFIG_BRIDGE_EBT_SNAT=y
+CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_CAN=y
+CONFIG_CAN_VCAN=y
+CONFIG_BT=y
+CONFIG_BT_HCIUART=y
+CONFIG_BT_HCIUART_H4=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_DEBUGFS=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_RFKILL=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=4
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+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
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_NETDEVICES=y
+CONFIG_TUN=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+CONFIG_KS8851=y
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_QCOM_EMAC=m
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_AT803X_PHY=m
+CONFIG_PPP=y
+CONFIG_PPP_ASYNC=y
+CONFIG_USB_USBNET=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CNSS=y
+CONFIG_CNSS_SDIO=y
+# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_GPIO=m
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM=y
+CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SPI=y
+CONFIG_SPI_SPIDEV=m
+CONFIG_PPS_CLIENT_GPIO=y
+CONFIG_PTP_1588_CLOCK=y
+CONFIG_PINCTRL_MDM9607=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_SMB1351_USB_CHARGER=y
+CONFIG_THERMAL=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CI13XXX_MSM=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=m
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_RTC_CLASS=y
+CONFIG_DMADEVICES=y
+CONFIG_UIO=y
+CONFIG_STAGING=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_USB_BAM=y
+CONFIG_COMMON_CLK_MSM=y
+CONFIG_MAILBOX=y
+CONFIG_MSM_SPM=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_TRACER_PKT=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_CNSS_CRYPTO=y
+CONFIG_IIO=y
+CONFIG_IIO_BUFFER=y
+CONFIG_IIO_BUFFER_CB=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_ANDROID=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_STACK_USAGE=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_IPC_LOGGING=y
+CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_PANIC_ON_DATA_CORRUPTION=y
+CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index 8b6a931..0c04f9c 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -26,6 +26,7 @@
 CONFIG_NAMESPACES=y
 CONFIG_SCHED_AUTOGROUP=y
 CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_BPF_SYSCALL=y
@@ -53,6 +54,7 @@
 CONFIG_BALANCE_ANON_FILE_RECLAIM=y
 CONFIG_SECCOMP=y
 CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
 CONFIG_CPU_IDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
@@ -257,6 +259,10 @@
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v26=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y
+CONFIG_TOUCHSCREEN_FTS=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_QPNP_POWER_ON=y
 CONFIG_INPUT_UINPUT=y
@@ -419,10 +425,13 @@
 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_QCOM_DEVFREQ_DEVBW=y
 CONFIG_IIO=y
 CONFIG_QCOM_SPMI_IADC=y
 CONFIG_QCOM_SPMI_VADC=y
diff --git a/arch/arm/configs/msm8909w_defconfig b/arch/arm/configs/msm8909w_defconfig
index 8b6a931..0c04f9c 100644
--- a/arch/arm/configs/msm8909w_defconfig
+++ b/arch/arm/configs/msm8909w_defconfig
@@ -26,6 +26,7 @@
 CONFIG_NAMESPACES=y
 CONFIG_SCHED_AUTOGROUP=y
 CONFIG_SCHED_TUNE=y
+CONFIG_DEFAULT_USE_ENERGY_AWARE=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_BPF_SYSCALL=y
@@ -53,6 +54,7 @@
 CONFIG_BALANCE_ANON_FILE_RECLAIM=y
 CONFIG_SECCOMP=y
 CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
 CONFIG_CPU_IDLE=y
 CONFIG_VFP=y
 CONFIG_NEON=y
@@ -257,6 +259,10 @@
 CONFIG_KEYBOARD_GPIO=y
 CONFIG_INPUT_JOYSTICK=y
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v26=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v26=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v26=y
+CONFIG_TOUCHSCREEN_FTS=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_QPNP_POWER_ON=y
 CONFIG_INPUT_UINPUT=y
@@ -419,10 +425,13 @@
 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_QCOM_DEVFREQ_DEVBW=y
 CONFIG_IIO=y
 CONFIG_QCOM_SPMI_IADC=y
 CONFIG_QCOM_SPMI_VADC=y
diff --git a/arch/arm/configs/msm8953-perf_defconfig b/arch/arm/configs/msm8953-perf_defconfig
index 459b07e..6ac3955 100644
--- a/arch/arm/configs/msm8953-perf_defconfig
+++ b/arch/arm/configs/msm8953-perf_defconfig
@@ -32,7 +32,6 @@
 # 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
@@ -51,6 +50,7 @@
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_MSM8953=y
 CONFIG_ARCH_MSM8937=y
+CONFIG_ARCH_MSM8917=y
 CONFIG_ARCH_SDM450=y
 # CONFIG_VDSO is not set
 CONFIG_SMP=y
@@ -291,6 +291,9 @@
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_VT is not set
 # CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_MSM_HS=y
 CONFIG_SERIAL_MSM_SMD=y
 CONFIG_DIAG_CHAR=y
 CONFIG_DIAG_USES_SMD=y
@@ -300,6 +303,7 @@
 CONFIG_MSM_ADSPRPC=y
 CONFIG_MSM_RDBG=m
 CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MSM_V2=y
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
 CONFIG_SPI_SPIDEV=y
@@ -316,6 +320,7 @@
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_QCOM=y
 CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_SYSCON=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_QPNP_FG=y
 CONFIG_SMB135X_CHARGER=y
@@ -384,6 +389,8 @@
 CONFIG_MSM_JPEGDMA=y
 CONFIG_MSM_VIDC_3X_V4L2=y
 CONFIG_MSM_VIDC_3X_GOVERNORS=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=y
 CONFIG_QCOM_KGSL=y
 CONFIG_FB=y
 CONFIG_FB_MSM=y
@@ -504,6 +511,7 @@
 CONFIG_QPNP_COINCELL=y
 CONFIG_QPNP_REVID=y
 CONFIG_USB_BAM=y
+CONFIG_MSM_RMNET_BAM=y
 CONFIG_MSM_MDSS_PLL=y
 CONFIG_REMOTE_SPINLOCK_MSM=y
 CONFIG_MAILBOX=y
@@ -544,6 +552,7 @@
 CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_QCOM_BIMC_BWMON=y
 CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_SIMPLE_DEV=y
 CONFIG_QCOM_DEVFREQ_DEVBW=y
 CONFIG_SPDM_SCM=y
 CONFIG_DEVFREQ_SPDM=y
diff --git a/arch/arm/configs/msm8953_defconfig b/arch/arm/configs/msm8953_defconfig
index 1a706cb..104e206 100644
--- a/arch/arm/configs/msm8953_defconfig
+++ b/arch/arm/configs/msm8953_defconfig
@@ -36,7 +36,6 @@
 # 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
@@ -57,6 +56,7 @@
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_MSM8953=y
 CONFIG_ARCH_MSM8937=y
+CONFIG_ARCH_MSM8917=y
 CONFIG_ARCH_SDM450=y
 # CONFIG_VDSO is not set
 CONFIG_SMP=y
@@ -300,8 +300,11 @@
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_VT is not set
 # CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_SERIAL_MSM_HS=y
 CONFIG_SERIAL_MSM_SMD=y
 CONFIG_DIAG_CHAR=y
 CONFIG_DIAG_USES_SMD=y
@@ -311,6 +314,7 @@
 CONFIG_MSM_ADSPRPC=y
 CONFIG_MSM_RDBG=m
 CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MSM_V2=y
 CONFIG_SPI=y
 CONFIG_SPI_QUP=y
 CONFIG_SPI_SPIDEV=y
@@ -327,6 +331,7 @@
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_QCOM=y
 CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_SYSCON=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_QPNP_FG=y
 CONFIG_SMB135X_CHARGER=y
@@ -395,6 +400,8 @@
 CONFIG_MSM_JPEGDMA=y
 CONFIG_MSM_VIDC_3X_V4L2=y
 CONFIG_MSM_VIDC_3X_GOVERNORS=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=y
 CONFIG_QCOM_KGSL=y
 CONFIG_FB=y
 CONFIG_FB_VIRTUAL=y
@@ -518,6 +525,7 @@
 CONFIG_QPNP_REVID=y
 CONFIG_USB_BAM=y
 CONFIG_MSM_EXT_DISPLAY=y
+CONFIG_MSM_RMNET_BAM=y
 CONFIG_MSM_MDSS_PLL=y
 CONFIG_REMOTE_SPINLOCK_MSM=y
 CONFIG_MAILBOX=y
@@ -564,6 +572,7 @@
 CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_QCOM_BIMC_BWMON=y
 CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_SIMPLE_DEV=y
 CONFIG_QCOM_DEVFREQ_DEVBW=y
 CONFIG_SPDM_SCM=y
 CONFIG_DEVFREQ_SPDM=y
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index b2dc7f7..e3c1c1a 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -194,6 +194,7 @@
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_AT803X_PHY=y
 CONFIG_PPP=y
 CONFIG_PPP_ASYNC=y
 CONFIG_USB_USBNET=y
@@ -305,8 +306,11 @@
 CONFIG_USB_CONFIGFS_F_GSI=y
 CONFIG_USB_CONFIGFS_F_QDSS=y
 CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
 CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
 CONFIG_MMC_TEST=m
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
@@ -321,6 +325,7 @@
 CONFIG_ION_MSM=y
 CONFIG_GSI=y
 CONFIG_IPA3=y
+CONFIG_IPA_WDI_UNIFIED_API=y
 CONFIG_RMNET_IPA3=y
 CONFIG_ECM_IPA=y
 CONFIG_RNDIS_IPA=y
@@ -330,6 +335,7 @@
 CONFIG_EP_PCIE=y
 CONFIG_EP_PCIE_HW=y
 CONFIG_QPNP_REVID=y
+CONFIG_MSM_MHI_DEV=y
 CONFIG_USB_BAM=y
 CONFIG_MSM_CLK_RPMH=y
 CONFIG_MSM_CLK_AOP_QMP=y
@@ -365,6 +371,7 @@
 CONFIG_MSM_PIL_SSR_GENERIC=y
 CONFIG_QCOM_COMMAND_DB=y
 CONFIG_MSM_PM=y
+CONFIG_QCOM_DCC_V2=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_EXTCON_QCOM_SPMI_MISC=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index ac15d6ea..fd3d784 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -186,6 +186,7 @@
 # CONFIG_NET_VENDOR_SEEQ is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
+CONFIG_AT803X_PHY=y
 CONFIG_PPP=y
 CONFIG_PPP_ASYNC=y
 CONFIG_USB_USBNET=y
@@ -307,8 +308,12 @@
 CONFIG_USB_CONFIGFS_F_GSI=y
 CONFIG_USB_CONFIGFS_F_QDSS=y
 CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_RING_BUFFER=y
 CONFIG_MMC_PARANOID_SD_INIT=y
+CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_BLOCK_DEFERRED_RESUME=y
 CONFIG_MMC_TEST=m
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
@@ -326,6 +331,7 @@
 CONFIG_ION_MSM=y
 CONFIG_GSI=y
 CONFIG_IPA3=y
+CONFIG_IPA_WDI_UNIFIED_API=y
 CONFIG_RMNET_IPA3=y
 CONFIG_ECM_IPA=y
 CONFIG_RNDIS_IPA=y
@@ -335,6 +341,7 @@
 CONFIG_EP_PCIE=y
 CONFIG_EP_PCIE_HW=y
 CONFIG_QPNP_REVID=y
+CONFIG_MSM_MHI_DEV=y
 CONFIG_USB_BAM=y
 CONFIG_MSM_CLK_RPMH=y
 CONFIG_MSM_CLK_AOP_QMP=y
@@ -370,6 +377,7 @@
 CONFIG_MSM_PIL_SSR_GENERIC=y
 CONFIG_QCOM_COMMAND_DB=y
 CONFIG_MSM_PM=y
+CONFIG_QCOM_DCC_V2=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_QCOM_DEVFREQ_DEVBW=y
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index e8d96df..65b43ea 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -152,5 +152,27 @@
 	select MSM_RPM_STATS_LOG
 	select HAVE_CLK_PREPARE
 
+config ARCH_MDM9607
+	bool "MDM9607"
+	select ARM_GIC
+	select CPU_V7
+	select REGULATOR
+	select REGULATOR_RPM_SMD
+	select HAVE_ARM_ARCH_TIMER
+	select MSM_RPM_SMD
+	select MEMORY_HOLE_CARVEOUT
+	select MSM_CORTEX_A7
+	select PINCTRL
+	select PINCTRL_MSM_TLMM
+	select USE_PINCTRL_IRQ
+	select MSM_IRQ
+	select MSM_PM if PM
+	select PM_DEVFREQ
+	select MSM_DEVFREQ_DEVBW
+	select MSM_BIMC_BWMON
+	select DEVFREQ_GOV_MSM_BW_HWMON
+	select ARM_HAS_SG_CHAIN
+	select HAVE_CLK_PREPARE
+
 endmenu
 endif
diff --git a/arch/arm/mach-qcom/Makefile b/arch/arm/mach-qcom/Makefile
index cfc4eac..c167075 100644
--- a/arch/arm/mach-qcom/Makefile
+++ b/arch/arm/mach-qcom/Makefile
@@ -7,3 +7,4 @@
 obj-$(CONFIG_ARCH_MSM8917) += board-msm8917.o
 obj-$(CONFIG_ARCH_SDM450) += board-sdm450.o
 obj-$(CONFIG_ARCH_MDM9650) += board-9650.o
+obj-$(CONFIG_ARCH_MDM9607) += board-9607.o
diff --git a/arch/arm/mach-qcom/board-9607.c b/arch/arm/mach-qcom/board-9607.c
new file mode 100644
index 0000000..fc18b90
--- /dev/null
+++ b/arch/arm/mach-qcom/board-9607.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+#include "board-dt.h"
+
+static const char *mdm9607_dt_match[] __initconst = {
+	"qcom,mdm9607",
+	NULL
+};
+
+static void __init mdm9607_init(void)
+{
+	board_dt_populate(NULL);
+}
+
+DT_MACHINE_START(MDM9607_DT,
+	"Qualcomm Technologies, Inc. MDM 9607 (Flattened Device Tree)")
+	.init_machine	= mdm9607_init,
+	.dt_compat	= mdm9607_dt_match,
+MACHINE_END
diff --git a/arch/arm/mach-qcom/board-msm8909.c b/arch/arm/mach-qcom/board-msm8909.c
index 3c5928d..38aad14 100644
--- a/arch/arm/mach-qcom/board-msm8909.c
+++ b/arch/arm/mach-qcom/board-msm8909.c
@@ -19,6 +19,7 @@
 
 static const char *msm8909_dt_match[] __initconst = {
 	"qcom,msm8909",
+	"qcom,apq8009",
 	NULL
 };
 
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index cc75e7f..a92f511 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -165,6 +165,15 @@
 	  This enables support for the MSM8937 chipset. If you do not
 	  wish to build a kernel that runs on this chipset, say 'N' here.
 
+config ARCH_MSM8917
+	bool "Enable Support for Qualcomm Technologies Inc. MSM8917"
+	depends on ARCH_QCOM
+	select CPU_FREQ_QCOM
+	select COMMON_CLK_MSM
+	help
+	  This enables support for the MSM8917 chipset. If you do not
+	  wish to build a kernel that runs on this chipset, say 'N' here.
+
 config ARCH_SDM450
 	bool "Enable Support for Qualcomm Technologies Inc. SDM450"
 	depends on ARCH_QCOM
diff --git a/arch/arm64/boot/dts/qcom/8909-pm8916.dtsi b/arch/arm64/boot/dts/qcom/8909-pm8916.dtsi
new file mode 100644
index 0000000..af56793
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/8909-pm8916.dtsi
@@ -0,0 +1,355 @@
+/* Copyright (c) 2014-2016, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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 "pm8916-rpm-regulator.dtsi"
+#include "pm8916.dtsi"
+#include "msm8916-regulator.dtsi"
+
+/ {
+	qcom,pmic-id = <0x1000B 0x0 0x0 0x0>;
+};
+
+&soc {
+	/* remove msm8916 acc/cpr regulator node */
+	/delete-node/ regulator@1946000;
+	/delete-node/ regulator@b018000;
+
+	mem_acc_vreg_corner: regulator@1942130 {
+		compatible = "qcom,mem-acc-regulator";
+		reg = <0x1942130 0x4>;
+		reg-names = "acc-sel-l1";
+		regulator-name = "mem_acc_corner";
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <3>;
+
+		qcom,acc-sel-l1-bit-pos = <0>;
+		qcom,corner-acc-map = <0 1 1>;
+	};
+
+	apc_vreg_corner: regulator@b018000 {
+		compatible = "qcom,cpr-regulator";
+		reg = <0xb018000 0x1000>, <0xb011064 0x4>, <0x58000 0x1000>;
+		reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
+		interrupts = <0 15 0>;
+		regulator-name = "apc_corner";
+		qcom,cpr-fuse-corners = <3>;
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <9>;
+
+		qcom,cpr-voltage-ceiling = <1050000 1225000 1350000>;
+		qcom,cpr-voltage-floor = <1050000 1050000 1155000>;
+		vdd-apc-supply = <&pm8916_s2>;
+
+		qcom,vdd-mx-corner-map = <4 5 7>;
+		qcom,vdd-mx-vmin-method = <4>;
+		vdd-mx-supply = <&pm8916_l3_corner_ao>;
+		qcom,vdd-mx-vmax = <7>;
+
+		mem-acc-supply = <&mem_acc_vreg_corner>;
+
+		qcom,cpr-ref-clk = <19200>;
+		qcom,cpr-timer-delay = <5000>;
+		qcom,cpr-timer-cons-up = <0>;
+		qcom,cpr-timer-cons-down = <2>;
+		qcom,cpr-irq-line = <0>;
+		qcom,cpr-step-quotient = <26>;
+		qcom,cpr-up-threshold = <0>;
+		qcom,cpr-down-threshold = <2>;
+		qcom,cpr-idle-clocks = <15>;
+		qcom,cpr-gcnt-time = <1>;
+		qcom,vdd-apc-step-up-limit = <1>;
+		qcom,vdd-apc-step-down-limit = <1>;
+		qcom,cpr-apc-volt-step = <12500>;
+
+		qcom,cpr-fuse-row = <26 0>;
+		qcom,cpr-fuse-target-quot = <42 24 6>;
+		qcom,cpr-fuse-ro-sel = <61 61 54>;
+		qcom,cpr-fuse-bp-cpr-disable = <58>;
+		qcom,cpr-fuse-init-voltage =
+					<26 36 6 0>,
+					<26 18 6 0>,
+					<26 0 6 0>;
+		qcom,cpr-fuse-revision = <26 59 2 0>;
+		qcom,cpr-init-voltage-ref = <1050000 1225000 1350000>;
+		qcom,cpr-init-voltage-step = <10000>;
+		qcom,cpr-corner-map = <1 1 2 2 3 3 3 3 3>;
+		qcom,cpr-init-voltage-as-ceiling;
+		qcom,cpr-corner-frequency-map =
+					<1 200000000>,
+					<2 400000000>,
+					<3 533330000>,
+					<4 800000000>,
+					<5 998400000>,
+					<6 1094400000>,
+					<7 1190400000>,
+					<8 1248000000>,
+					<9 1267200000>;
+		qcom,speed-bin-fuse-sel = <1 34 3 0>;
+		qcom,cpr-speed-bin-max-corners =
+					<0 0 2 4 9>,
+					<2 0 2 4 6>;
+		qcom,cpr-quot-adjust-scaling-factor-max = <1400>;
+		qcom,cpr-enable;
+	};
+
+	qcom,gcc@1800000 {
+		vdd_dig-supply = <&pm8916_s1_corner>;
+		vdd_sr2_dig-supply = <&pm8916_s1_corner_ao>;
+		vdd_sr2_pll-supply = <&pm8916_l7_ao>;
+	};
+
+	qcom,clock-a7@0b011050 {
+		cpu-vdd-supply = <&apc_vreg_corner>;
+		qcom,speed0-bin-v0 =
+			<          0 0>,
+			<  200000000 1>,
+			<  400000000 2>,
+			<  533333000 3>,
+			<  800000000 4>,
+			<  998400000 5>,
+			< 1094400000 6>,
+			< 1190400000 7>,
+			< 1248000000 8>,
+			< 1267200000 9>;
+
+		qcom,speed2-bin-v0 =
+			<          0 0>,
+			<  200000000 1>,
+			<  400000000 2>,
+			<  533333000 3>,
+			<  800000000 4>,
+			<  998400000 5>,
+			< 1094400000 6>;
+	};
+
+	qcom,supply-lm@1946000 {
+		status = "disabled";
+	};
+
+	qcom,wcnss-wlan@a000000 {
+		qcom,pronto-vddmx-supply = <&pm8916_l3_corner_ao>;
+		qcom,pronto-vddcx-supply = <&pm8916_s1_corner>;
+		qcom,pronto-vddpx-supply = <&pm8916_l7>;
+		qcom,iris-vddxo-supply   = <&pm8916_l7>;
+		qcom,iris-vddrfa-supply  = <&pm8916_s3>;
+		qcom,iris-vddpa-supply   = <&pm8916_l9>;
+		qcom,iris-vdddig-supply  = <&pm8916_l5>;
+		qcom,wcnss-adc_tm = <&pm8916_adc_tm>;
+	};
+
+	usb_otg: usb@78d9000 {
+		hsusb_vdd_dig-supply = <&pm8916_l2>;
+		HSUSB_1p8-supply = <&pm8916_l7>;
+		HSUSB_3p3-supply = <&pm8916_l13>;
+	};
+
+	qcom,pronto@a21b000 {
+		vdd_pronto_pll-supply = <&pm8916_l7>;
+	};
+
+	qcom,mss@4080000 {
+		vdd_cx-supply = <&pm8916_s1_corner>;
+		vdd_mx-supply = <&pm8916_l3_corner_ao>;
+		vdd_pll-supply = <&pm8916_l7>;
+	};
+
+	tpiu@820000 {
+		vdd-supply = <&pm8916_l11>;
+		vdd-io-supply = <&pm8916_l12>;
+	};
+
+	qpdi@1941000 {
+		vdd-supply = <&pm8916_l11>;
+		vdd-io-supply = <&pm8916_l12>;
+	};
+
+	qcom,mdss_dsi@0 {
+		vdda-supply = <&pm8916_l2>;
+		vddio-supply = <&pm8916_l6>;
+
+		qcom,mdss_dsi_ctrl0@1ac8000 {
+			vdd-supply = <&pm8916_l17>;
+			vddio-supply = <&pm8916_l6>;
+		};
+	};
+
+	qcom,mdss_dsi_pll@1ac8300 {
+		vddio-supply = <&pm8916_l6>;
+	};
+
+	qcom,msm-thermal {
+		vdd-dig-supply = <&pm8916_s1_floor_corner>;
+
+		qcom,vdd-apps-rstr {
+			qcom,vdd-rstr-reg = "vdd-apps";
+			qcom,levels = <800000>;
+			qcom,freq-req;
+		};
+	};
+};
+
+
+&pm8916_vadc {
+	chan@0 {
+		label = "usb_in";
+		reg = <0>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <7>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@2 {
+		label = "ireg_fb";
+		reg = <2>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <6>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@5 {
+		label = "vcoin";
+		reg = <5>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <1>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@6 {
+		label = "vbat_sns";
+		reg = <6>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <1>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@7 {
+		label = "vph_pwr";
+		reg = <7>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <1>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@b {
+		label = "chg_temp";
+		reg = <0xb>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <3>;
+		qcom,hw-settle-time = <0>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@30 {
+		label = "batt_therm";
+		reg = <0x30>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <1>;
+		qcom,hw-settle-time = <0xb>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@31 {
+		label = "batt_id";
+		reg = <0x31>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0xb>;
+		qcom,fast-avg-setup = <0>;
+	};
+
+	chan@36 {
+		label = "pa_therm0";
+		reg = <0x36>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <2>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+		qcom,vadc-thermal-node;
+	};
+
+	chan@32 {
+		label = "xo_therm";
+		reg = <0x32>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <4>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+		qcom,vadc-thermal-node;
+	};
+
+	chan@3c {
+		label = "xo_therm_buf";
+		reg = <0x3c>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <4>;
+		qcom,hw-settle-time = <2>;
+		qcom,fast-avg-setup = <0>;
+		qcom,vadc-thermal-node;
+	};
+};
+
+&pm8916_adc_tm {
+	/* Channel Node */
+	chan@30 {
+		label = "batt_therm";
+		reg = <0x30>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <0>;
+		qcom,calibration-type = "ratiometric";
+		qcom,scale-function = <1>;
+		qcom,hw-settle-time = <0xb>;
+		qcom,fast-avg-setup = <0x2>;
+		qcom,btm-channel-number = <0x48>;
+	};
+
+	chan@6 {
+		label = "vbat_sns";
+		reg = <0x6>;
+		qcom,decimation = <0>;
+		qcom,pre-div-channel-scaling = <1>;
+		qcom,calibration-type = "absolute";
+		qcom,scale-function = <0>;
+		qcom,hw-settle-time = <0xb>;
+		qcom,fast-avg-setup = <0x2>;
+		qcom,btm-channel-number = <0x68>;
+	};
+};
+
+#include "msm8909-pm8916-pm.dtsi"
+
diff --git a/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi b/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
index 211e28c..c9996f8 100644
--- a/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
@@ -326,6 +326,10 @@
 		};
 	};
 
+	qcom,power-on@800 {
+		qcom,use-legacy-hard-reset-offset;
+	};
+
 	pm660_rradc: rradc@4500 {
 		compatible = "qcom,rradc";
 		reg = <0x4500 0x100>;
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 8675d09..315b3fd 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -143,7 +143,27 @@
 		qcs605-mtp-overlay.dtbo \
 		qcs605-360camera-overlay.dtbo \
 		qcs605-external-codec-mtp-overlay.dtbo \
-		qcs605-lc-mtp-overlay.dtbo
+		qcs605-lc-mtp-overlay.dtbo \
+		sdm710-cdp-overlay.dtbo \
+		sdm710-mtp-overlay.dtbo \
+		sdm710-qrd-overlay.dtbo \
+		sdm710-qrd-sku2-overlay.dtbo \
+		sdm710-pm660a-cdp-overlay.dtbo \
+		sdm710-pm660a-mtp-overlay.dtbo \
+		sdm710-external-codec-cdp-overlay.dtbo \
+		sdm710-external-codec-mtp-overlay.dtbo \
+		sdm710-external-codec-pm660a-cdp-overlay.dtbo \
+		sdm710-external-codec-pm660a-mtp-overlay.dtbo \
+		sdm710-usbc-cdp-overlay.dtbo \
+		sdm710-usbc-mtp-overlay.dtbo \
+		sdm710-usbc-pm660a-cdp-overlay.dtbo \
+		sdm710-usbc-pm660a-mtp-overlay.dtbo \
+		sdm710-usbc-external-codec-cdp-overlay.dtbo \
+		sdm710-usbc-external-codec-mtp-overlay.dtbo \
+		sdm710-usbc-external-codec-pm660a-cdp-overlay.dtbo \
+		sdm710-usbc-external-codec-pm660a-mtp-overlay.dtbo \
+		sdm710-tasha-codec-cdp-overlay.dtbo \
+		sdm710-pm660a-tasha-codec-cdp-overlay.dtbo
 
 sdm670-cdp-overlay.dtbo-base := sdm670.dtb
 sdm670-mtp-overlay.dtbo-base := sdm670.dtb
@@ -175,6 +195,26 @@
 qcs605-external-codec-mtp-overlay.dtbo-base := qcs605.dtb
 qcs605-lc-mtp-overlay.dtbo-base := qcs605-lc.dtb
 qcs605-360camera-overlay.dtbo-base := qcs605.dtb
+sdm710-cdp-overlay.dtbo-base := sdm710.dtb
+sdm710-mtp-overlay.dtbo-base := sdm710.dtb
+sdm710-qrd-overlay.dtbo-base := sdm710.dtb
+sdm710-qrd-sku2-overlay.dtbo-base := sdm710.dtb
+sdm710-pm660a-cdp-overlay.dtbo-base := sdm710.dtb
+sdm710-pm660a-mtp-overlay.dtbo-base := sdm710.dtb
+sdm710-external-codec-cdp-overlay.dtbo-base := sdm710.dtb
+sdm710-external-codec-mtp-overlay.dtbo-base := sdm710.dtb
+sdm710-external-codec-pm660a-cdp-overlay.dtbo-base := sdm710.dtb
+sdm710-external-codec-pm660a-mtp-overlay.dtbo-base := sdm710.dtb
+sdm710-usbc-cdp-overlay.dtbo-base := sdm710.dtb
+sdm710-usbc-mtp-overlay.dtbo-base := sdm710.dtb
+sdm710-usbc-pm660a-cdp-overlay.dtbo-base := sdm710.dtb
+sdm710-usbc-pm660a-mtp-overlay.dtbo-base := sdm710.dtb
+sdm710-usbc-external-codec-cdp-overlay.dtbo-base := sdm710.dtb
+sdm710-usbc-external-codec-mtp-overlay.dtbo-base := sdm710.dtb
+sdm710-usbc-external-codec-pm660a-cdp-overlay.dtbo-base := sdm710.dtb
+sdm710-usbc-external-codec-pm660a-mtp-overlay.dtbo-base := sdm710.dtb
+sdm710-tasha-codec-cdp-overlay.dtbo-base := sdm710.dtb
+sdm710-pm660a-tasha-codec-cdp-overlay.dtbo-base := sdm710.dtb
 
 else
 dtb-$(CONFIG_ARCH_SDM670) += sdm670-rumi.dtb \
@@ -206,7 +246,27 @@
 	qcs605-mtp.dtb \
 	qcs605-cdp.dtb \
 	qcs605-external-codec-mtp.dtb \
-	qcs605-lc-mtp.dtb
+	qcs605-lc-mtp.dtb \
+	sdm710-mtp.dtb \
+	sdm710-cdp.dtb \
+	sdm710-qrd.dtb \
+	sdm710-qrd-sku2.dtb \
+	sdm710-pm660a-mtp.dtb \
+	sdm710-pm660a-cdp.dtb \
+	sdm710-external-codec-cdp.dtb \
+	sdm710-external-codec-mtp.dtb \
+	sdm710-external-codec-pm660a-cdp.dtb \
+	sdm710-external-codec-pm660a-mtp.dtb \
+	sdm710-usbc-cdp.dtb \
+	sdm710-usbc-external-codec-cdp.dtb \
+	sdm710-usbc-external-codec-mtp.dtb \
+	sdm710-usbc-external-codec-pm660a-cdp.dtb \
+	sdm710-usbc-external-codec-pm660a-mtp.dtb \
+	sdm710-usbc-mtp.dtb \
+	sdm710-usbc-pm660a-cdp.dtb \
+	sdm710-usbc-pm660a-mtp.dtb \
+	sdm710-tasha-codec-cdp.dtb \
+	sdm710-pm660a-tasha-codec-cdp.dtb
 endif
 
 ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y)
@@ -306,7 +366,10 @@
 
 dtb-$(CONFIG_ARCH_MSM8917) += msm8917-pmi8950-mtp.dtb
 
-dtb-$(CONFIG_ARCH_MSM8909) += msm8909w-bg-wtp-v2.dtb
+dtb-$(CONFIG_ARCH_MSM8909) += msm8909w-bg-wtp-v2.dtb \
+	apq8009w-bg-wtp-v2.dtb \
+	apq8009w-bg-alpha.dtb \
+	apq8009-mtp-wcd9326-refboard.dtb
 
 dtb-$(CONFIG_ARCH_SDM450) += sdm450-rcm.dtb \
 	sdm450-cdp.dtb \
diff --git a/arch/arm64/boot/dts/qcom/apq8009-audio-external_codec.dtsi b/arch/arm64/boot/dts/qcom/apq8009-audio-external_codec.dtsi
new file mode 100644
index 0000000..d28e139
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8009-audio-external_codec.dtsi
@@ -0,0 +1,270 @@
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&pm8916_tombak_dig {
+	status = "disabled";
+};
+
+&pm8916_tombak_analog {
+	status = "disabled";
+};
+
+&soc {
+	sound-9335 {
+		compatible = "qcom,apq8009-audio-i2s-codec";
+		qcom,model = "apq8009-tashalite-snd-card";
+		qcom,msm-mbhc-hphl-swh = <0>;
+		qcom,msm-mbhc-gnd-swh = <0>;
+		qcom,afe-rxtx-lb;
+		qcom,msm-mclk-freq = <9600000>;
+		qcom,tdm-audio-intf;
+		qcom,msm-hs-micbias-type = "internal";
+		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 BIAS2",
+			"MIC BIAS2", "Digital Mic2",
+			"DMIC3", "MIC BIAS2",
+			"MIC BIAS2", "Digital Mic3",
+			"SpkrLeft IN", "SPK1 OUT",
+			"SpkrRight IN", "SPK2 OUT";
+
+		qcom,msm-gpios =
+			"pri_i2s",
+			"quat_i2s";
+		qcom,pinctrl-names =
+			"all_off",
+			"pri_i2s_act",
+			"quat_i2s_act",
+			"pri_i2s_quat_i2s_act";
+		pinctrl-names =
+			"all_off",
+			"pri_i2s_act",
+			"quat_i2s_act",
+			"pri_i2s_quat_i2s_act";
+		pinctrl-0 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
+			&pri_mi2s_dout_sleep &pri_mi2s_din_sleep
+			&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+		pinctrl-1 = <&pri_mi2s_active &pri_mi2s_ws_active
+			&pri_mi2s_dout_active &pri_mi2s_din_active
+			&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+		pinctrl-2 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
+			&pri_mi2s_dout_sleep &pri_mi2s_din_sleep
+			&quat_mi2s_active &quat_mi2s_din_active>;
+		pinctrl-3 = <&pri_mi2s_active &pri_mi2s_ws_active
+			&pri_mi2s_dout_active &pri_mi2s_din_active
+			&quat_mi2s_active &quat_mi2s_din_active>;
+
+		asoc-platform = <&pcm0>, <&pcm1>, <&voip>, <&voice>,
+				<&loopback>, <&compress>, <&hostless>,
+				<&afe>, <&lsm>, <&routing>, <&cpe>, <&lpa>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+				"msm-voip-dsp", "msm-pcm-voice",
+				"msm-pcm-loopback", "msm-compress-dsp",
+				"msm-pcm-hostless", "msm-pcm-afe",
+				"msm-lsm-client", "msm-pcm-routing",
+				"msm-cpe-lsm", "msm-pcm-lpa";
+		asoc-cpu =  <&dai_pri_auxpcm>, <&dai_hdmi>,<&dai_mi2s0>,
+				<&dai_mi2s2>, <&dai_mi2s3>,
+				<&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+				<&sb_3_rx>, <&sb_3_tx>,
+				<&sb_4_rx>, <&sb_4_tx>, <&afe_pcm_rx>,
+				<&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
+				<&incall_record_rx>, <&incall_record_tx>,
+				<&incall_music_rx>, <&incall_music_2_rx>,
+				<&bt_sco_rx>,
+				<&bt_sco_tx>, <&int_fm_rx>, <&int_fm_tx>,
+				<&afe_loopback_tx>, <&dai_pri_tdm_rx_0>,
+				<&dai_pri_tdm_tx_0>;
+		asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-hdmi.8",
+				 "msm-dai-q6-mi2s.0",
+				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+				"msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
+				"msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+				"msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+				"msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+				"msm-dai-q6-dev.224",
+				"msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
+				"msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
+				"msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773",
+				"msm-dai-q6-dev.32770",
+				"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+				"msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293",
+				"msm-dai-q6-dev.24577", "msm-dai-q6-tdm.36864",
+				"msm-dai-q6-tdm.36865";
+		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";
+	};
+	cpe: qcom,msm-cpe-lsm {
+		compatible = "qcom,msm-cpe-lsm";
+	};
+
+	compress: qcom,msm-compress-dsp {
+		compatible = "qcom,msm-compress-dsp";
+		qcom,adsp-version = "MDSP 2.8";
+	};
+
+	wcd9xxx_intc: wcd9xxx-irq {
+		compatible = "qcom,wcd9xxx-irq";
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		interrupt-parent = <&msm_gpio>;
+		interrupts = <64 0>;
+		interrupt-names = "cdc-int";
+		qcom,gpio-connect = <&msm_gpio 64 0>;
+	};
+
+	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 {
+			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,cdc-reset-gpio = <&msm_gpio 17 0>;
+
+			cdc-vdd-buck-supply = <&pm8916_s4>;
+			qcom,cdc-vdd-buck-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-buck-current = <650000>;
+
+			cdc-buck-sido-supply = <&pm8916_s4>;
+			qcom,cdc-buck-sido-voltage = <1800000 1800000>;
+			qcom,cdc-buck-sido-current = <250000>;
+
+			cdc-vdd-tx-h-supply = <&pm8916_l5>;
+			qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-tx-h-current = <25000>;
+
+			cdc-vdd-rx-h-supply = <&pm8916_l5>;
+			qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-rx-h-current = <25000>;
+
+			cdc-vdd-px-supply = <&pm8916_l5>;
+			qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-px-current = <10000>;
+
+			qcom,cdc-static-supplies =
+				"cdc-vdd-buck",
+				"cdc-buck-sido",
+				"cdc-vdd-tx-h",
+				"cdc-vdd-rx-h",
+				"cdc-vdd-px";
+
+			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-dmic-sample-rate = <4800000>;
+			qcom,cdc-variant = "WCD9335";
+
+			clock-names = "wcd_clk";
+			clocks = <&clock_audio clk_audio_lpass_mclk>;
+
+			swr_master {
+				compatible = "qcom,swr-wcd";
+				#address-cells = <2>;
+				#size-cells = <0>;
+				wsa881x_211:wsa881x@21170211 {
+					compatible = "qcom,wsa881x";
+					reg = <0x00 0x21170211>;
+					qcom,spkr-sd-n-gpio = <&msm_gpio 72 0>;
+				};
+
+				wsa881x_212:wsa881x@21170212 {
+					compatible = "qcom,wsa881x";
+					reg = <0x00 0x21170212>;
+					qcom,spkr-sd-n-gpio = <&msm_gpio 73 0>;
+				};
+
+				wsa881x_213:wsa881x@21170213 {
+					compatible = "qcom,wsa881x";
+					reg = <0x00 0x21170213>;
+					qcom,spkr-sd-n-gpio = <&msm_gpio 72 0>;
+				};
+
+				wsa881x_214:wsa881x@21170214 {
+					compatible = "qcom,wsa881x";
+					reg = <0x00 0x21170214>;
+					qcom,spkr-sd-n-gpio = <&msm_gpio 73 0>;
+				};
+			};
+		};
+	};
+
+	pri_tdm_rx: qcom,msm-dai-tdm-pri-rx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37120>;
+		qcom,msm-cpudai-tdm-group-num-ports = <1>;
+		qcom,msm-cpudai-tdm-group-port-id = <36864>;
+		qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+		qcom,msm-cpudai-tdm-sec-port-enable;
+		qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <1>;
+		dai_pri_tdm_rx_0: qcom,msm-dai-q6-tdm-pri-rx-0 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36864>;
+			qcom,msm-cpudai-tdm-sync-mode = <0>;
+			qcom,msm-cpudai-tdm-sync-src = <1>;
+			qcom,msm-cpudai-tdm-data-out = <0>;
+			qcom,msm-cpudai-tdm-invert-sync = <0>;
+			qcom,msm-cpudai-tdm-data-delay = <1>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+
+	pri_tdm_tx: qcom,msm-dai-tdm-pri-tx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37121>;
+		qcom,msm-cpudai-tdm-group-num-ports = <1>;
+		qcom,msm-cpudai-tdm-group-port-id = <36865>;
+		qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+		qcom,msm-cpudai-tdm-sec-port-enable;
+		qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <1>;
+		dai_pri_tdm_tx_0: qcom,msm-dai-q6-tdm-pri-tx-0 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36865>;
+			qcom,msm-cpudai-tdm-sync-mode = <0>;
+			qcom,msm-cpudai-tdm-sync-src = <1>;
+			qcom,msm-cpudai-tdm-data-out = <0>;
+			qcom,msm-cpudai-tdm-invert-sync = <0>;
+			qcom,msm-cpudai-tdm-data-delay = <1>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8009-memory.dtsi b/arch/arm64/boot/dts/qcom/apq8009-memory.dtsi
new file mode 100644
index 0000000..018b96e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8009-memory.dtsi
@@ -0,0 +1,23 @@
+/* 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.
+ */
+
+&external_image_mem {
+	reg = <0x0 0x87a00000 0x0 0x0600000>;
+};
+
+&modem_adsp_mem {
+	reg = <0x0 0x88000000 0x0 0x01e00000>;
+};
+
+&peripheral_mem {
+	reg = <0x0 0x89e00000 0x0 0x0700000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
new file mode 100644
index 0000000..9efd808
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
@@ -0,0 +1,330 @@
+/* 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>
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8009 WCD9326 Reference Board";
+	compatible = "qcom,apq8009-mtp", "qcom,apq8009", "qcom,mtp";
+	qcom,msm-id = <265 2>;
+	qcom,board-id= <8 0x8>;
+};
+
+&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 {
+	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";
+	};
+
+	i2c@78b8000 {
+		wcd9xxx_codec@d {
+			qcom,cdc-reset-gpio = <&msm_gpio 27 0>;
+		};
+	};
+
+	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 */
+	};
+
+	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>;
+		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>;
+	};
+};
+
+&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 {
+	smb1360_otg_supply: smb1360-chg-fg@14 {
+		compatible = "qcom,smb1360-chg-fg";
+		reg = <0x14>;
+		interrupt-parent = <&msm_gpio>;
+		interrupts = <58 8>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&smb_int_default>;
+		qcom,charging-disabled;
+		qcom,empty-soc-disabled;
+		qcom,chg-inhibit-disabled;
+		qcom,float-voltage-mv = <4200>;
+		qcom,iterm-ma = <200>;
+		qcom,recharge-thresh-mv = <100>;
+		qcom,thermal-mitigation = <1500 700 600 0>;
+		regulator-name = "smb1360_otg_vreg";
+	};
+};
+
+&usb_otg {
+	interrupts = <0 134 0>, <0 140 0>;
+	interrupt-names = "core_irq", "async_irq";
+
+	qcom,hsusb-otg-mode = <3>;
+	vbus_otg-supply = <&vbus_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";
+};
+
+/delete-node/ &cont_splash_mem;
diff --git a/arch/arm64/boot/dts/qcom/apq8009w-bg-alpha.dts b/arch/arm64/boot/dts/qcom/apq8009w-bg-alpha.dts
new file mode 100644
index 0000000..57a28d0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8009w-bg-alpha.dts
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "msm8909-mtp.dtsi"
+#include "msm8909w.dtsi"
+#include "8909w-pm660.dtsi"
+#include "apq8009w-bg-memory.dtsi"
+#include "msm8909-audio-bg_codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8009W-PM660 BG Alpha";
+	compatible = "qcom,apq8009-mtp", "qcom,apq8009", "qcom,mtp";
+	qcom,msm-id =   <265 0>,
+			<301 0>;
+	qcom,board-id = <8 0x113>;
+	qcom,pmic-id =  <0x0001001b 0x0 0x0 0x0>,
+			<0x0001011b 0x0 0x0 0x0>;
+};
+
+&soc {
+	i2c@78b9000 { /* BLSP1 QUP5 */
+		focaltech@38 {
+			compatible = "focaltech,fts";
+			reg = <0x38>;
+			interrupt-parent = <&msm_gpio>;
+			interrupts = <98 0x2008>;
+			vdd-supply = <&pm660_l18>;
+			vcc-i2c-supply = <&pm660_l13>;
+			focaltech,irq-gpio = <&msm_gpio 98 0x2008>;
+			focaltech,reset-gpio = <&msm_gpio 16 0x00>;/**/
+			focaltech,max-touch-number = <5>;
+			focaltech,display-coords = <0 0 390 390>;/**/
+			focaltech,wakeup-gestures-en;
+		};
+
+		/delete-node/ it7260@46;
+		/delete-node/ synaptics@20;
+	};
+
+	qcom,blackghost {
+		compatible = "qcom,pil-blackghost";
+
+		qcom,firmware-name = "bg-wear";
+		/* GPIO inputs from blackghost */
+		qcom,bg2ap-status-gpio = <&msm_gpio 97 0>;
+		qcom,bg2ap-errfatal-gpio = <&msm_gpio 95 0>;
+		/* GPIO output to blackghost */
+		qcom,ap2bg-status-gpio = <&msm_gpio 17 0>;
+		qcom,ap2bg-errfatal-gpio = <&msm_gpio 23 0>;
+	};
+
+	qcom,msm-ssc-sensors {
+		compatible = "qcom,msm-ssc-sensors";
+	};
+
+	qcom,glink-bgcom-xprt-bg {
+		compatible = "qcom,glink-bgcom-xprt";
+		label = "bg";
+		qcom,qos-config = <&glink_qos_bg>;
+		qcom,ramp-time = <0x10>,
+				     <0x20>,
+				     <0x30>,
+				     <0x40>;
+	};
+
+	glink_qos_bg: qcom,glink-qos-config-bg {
+		compatible = "qcom,glink-qos-config";
+		qcom,flow-info = <0x80 0x0>,
+				 <0x70 0x1>,
+				 <0x60 0x2>,
+				 <0x50 0x3>;
+		qcom,mtu-size = <0x800>;
+		qcom,tput-stats-cycle = <0xa>;
+	};
+
+	qcom,glink_pkt {
+		compatible = "qcom,glinkpkt";
+
+		qcom,glinkpkt-bg-daemon {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "bg-daemon";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon";
+		};
+
+		qcom,glinkpkt-bg-display-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "display-ctrl";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_display_ctrl";
+		};
+
+		qcom,glinkpkt-bg-display-data {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "display-data";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_display_data";
+		};
+
+		qcom,glinkpkt-bg-rsb-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "RSB_CTRL";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_rsb_ctrl";
+		};
+	};
+
+	spi@78B8000 {  /* BLSP1 QUP4 */
+		status = "ok";
+		qcom,bg-spi {
+			compatible = "qcom,bg-spi";
+			reg = <0>;
+			spi-max-frequency = <16000000>;
+			interrupt-parent = <&msm_gpio>;
+			qcom,irq-gpio = <&msm_gpio 110 1>;
+		};
+	};
+
+	qcom,bg-rsb {
+		compatible = "qcom,bg-rsb";
+		vdd-ldo1-supply = <&pm660_l11>;
+		vdd-ldo2-supply = <&pm660_l15>;
+	};
+
+	qcom,bg-daemon {
+		compatible = "qcom,bg-daemon";
+		qcom,bg-reset-gpio = <&pm660_gpios 5 0>;
+		ssr-reg1-supply = <&pm660_l3>;
+		ssr-reg2-supply = <&pm660_l9>;
+	};
+};
+
+&i2c_1 {
+	status = "okay";
+	nq@28 {
+		compatible = "qcom,nq-nci";
+		reg = <0x28>;
+		qcom,nq-irq = <&msm_gpio 50 0x00>;
+		qcom,nq-ven = <&msm_gpio 36 0x00>;
+		qcom,nq-firm = <&msm_gpio 38 0x00>;
+		qcom,nq-esepwr = <&msm_gpio 49 0x00>;
+		qcom,nq-clkreq = <&pm660_gpios 4 0x00>;
+		qcom,clk-src = "BBCLK3";
+		interrupt-parent = <&msm_gpio>;
+		interrupts = <50 0>;
+		interrupt-names = "nfc_irq";
+		pinctrl-names = "nfc_active","nfc_suspend";
+		pinctrl-0 = <&nfcw_int_active &nfcw_disable_active>;
+		pinctrl-1 = <&nfcw_int_suspend &nfcw_disable_suspend>;
+		clock-names = "ref_clk";
+	};
+};
+
+&spi_0 {
+	status = "disabled";
+};
+
+&i2c_3 {
+	status = "disabled";
+};
+
+&i2c_4 {
+	status = "disabled";
+};
+
+&i2c_2 {
+	status = "disabled";
+};
+
+&sdc1_clk_off {
+	config {
+		pins = "sdc1_clk";
+		bias-disable; /* NO pull */
+		drive-strength = <2>; /* 2 MA */
+		output-low;
+	};
+};
+
+&sdc1_cmd_off {
+	config {
+		pins = "sdc1_cmd";
+		bias-disable; /* NO pull */
+		drive-strength = <2>; /* 2 MA */
+		output-low;
+	};
+};
+
+&sdc1_data_off {
+	config {
+		pins = "sdc1_data";
+		bias-disable; /* NO pull */
+		drive-strength = <2>; /* 2 MA */
+		output-low;
+	};
+};
+
+&sdhc_2 {
+	status = "disabled";
+};
+
+&audio_codec_mtp {
+	status = "disabled";
+};
+
+&audio_codec_bg {
+	status = "ok";
+};
+
+&bg_cdc {
+	status = "ok";
+	vdd-spkr-supply = <&pm660_l11>;
+};
+
+&blsp1_uart1 {
+	status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console_sleep>;
+};
+
+/* Pinctrl dt nodes for interrupt and reset gpio for Synaptics controller */
+&ts_int_active {
+	mux {
+		pins = "gpio98";
+	};
+
+	config {
+		pins = "gpio98";
+	};
+};
+
+&ts_int_suspend {
+	mux {
+		pins = "gpio98";
+	};
+
+	config {
+		pins = "gpio98";
+	};
+};
+
+&ts_reset_active {
+	mux {
+		pins = "gpio16";
+	};
+
+	config {
+		pins = "gpio16";
+	};
+};
+
+&ts_reset_suspend {
+	mux {
+		pins = "gpio16";
+	};
+
+	config {
+		pins = "gpio16";
+	};
+};
+
+&ts_release {
+	mux {
+		pins = "gpio98", "gpio16";
+	};
+
+	config {
+		pins = "gpio98", "gpio16";
+	};
+};
+
+&pm660_charger {
+	qcom,micro-usb;
+};
+
+&spi4_cs0_active {
+	mux {
+		pins = "gpio14";
+		function = "blsp_spi4";
+	};
+	config {
+		pins = "gpio14";
+		drive-strength = <2>;
+		bias-disable; /* No PULL */
+		output-high;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8009w-bg-memory.dtsi b/arch/arm64/boot/dts/qcom/apq8009w-bg-memory.dtsi
new file mode 100644
index 0000000..d41a792
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8009w-bg-memory.dtsi
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+&external_image_mem {
+	reg = <0x0 0x87b00000 0x0 0x0500000>;
+};
+
+&modem_adsp_mem {
+	reg = <0x0 0x88000000 0x0 0x02300000>;
+};
+
+&peripheral_mem {
+	reg = <0x0 0x8a300000 0x0 0x0600000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8009w-bg-wtp-v2.dts b/arch/arm64/boot/dts/qcom/apq8009w-bg-wtp-v2.dts
new file mode 100644
index 0000000..454ba81
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8009w-bg-wtp-v2.dts
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "msm8909-mtp.dtsi"
+#include "msm8909w.dtsi"
+#include "8909w-pm660.dtsi"
+#include "apq8009w-bg-memory.dtsi"
+#include "msm8909-audio-bg_codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. APQ8009W-PM660 BLACKGHOST WTP";
+	compatible = "qcom,apq8009-mtp", "qcom,apq8009", "qcom,mtp";
+	qcom,msm-id =   <265 0>,
+			<301 0>;
+	qcom,board-id = <8 0x10f>;
+	qcom,pmic-id =  <0x0001001b 0x0 0x0 0x0>,
+			<0x0001011b 0x0 0x0 0x0>;
+};
+
+&soc {
+	i2c@78b9000 { /* BLSP1 QUP5 */
+		synaptics@20 {
+			compatible = "synaptics,dsx-i2c";
+			reg = <0x20>;
+			interrupt-parent = <&msm_gpio>;
+			interrupts = <98 0x2008>;
+			vdd_ana-supply = <&pm660_l18>;
+			vcc_i2c-supply = <&pm660_l13>;
+			synaptics,pwr-reg-name = "vdd_ana";
+			synaptics,bus-reg-name = "vcc_i2c";
+			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>;
+			synaptics,irq-gpio = <&msm_gpio 98 0x2008>;
+			synaptics,irq-on-state = <0>;
+			synaptics,irq-flags = <0x2008>;
+			synaptics,power-delay-ms = <200>;
+			synaptics,reset-delay-ms = <200>;
+			synaptics,max-y-for-2d = <389>;
+			synaptics,bus-lpm-cur-uA = <450>;
+			synaptics,do-not-disable-regulators;
+			synaptics,wakeup-gestures-en;
+			synaptics,resume-in-workqueue;
+			synaptics,x-flip;
+			synaptics,y-flip;
+			/delete-property/ synaptics,reset-gpio;
+			/delete-property/ synaptics,display-coords;
+			/delete-property/ synaptics,panel-coords;
+			/delete-property/ synaptics,power-down;
+			/delete-property/ synaptics,disable-gpios;
+			/delete-property/ synaptics,is_wake;
+		};
+
+		/delete-node/ it7260@46;
+	};
+
+	qcom,blackghost {
+		compatible = "qcom,pil-blackghost";
+
+		qcom,firmware-name = "bg-wear";
+		/* GPIO inputs from blackghost */
+		qcom,bg2ap-status-gpio = <&msm_gpio 97 0>;
+		qcom,bg2ap-errfatal-gpio = <&msm_gpio 95 0>;
+		/* GPIO output to blackghost */
+		qcom,ap2bg-status-gpio = <&msm_gpio 17 0>;
+		qcom,ap2bg-errfatal-gpio = <&msm_gpio 23 0>;
+	};
+
+	qcom,msm-ssc-sensors {
+		compatible = "qcom,msm-ssc-sensors";
+	};
+
+	qcom,glink-bgcom-xprt-bg {
+		compatible = "qcom,glink-bgcom-xprt";
+		label = "bg";
+		qcom,qos-config = <&glink_qos_bg>;
+		qcom,ramp-time = <0x10>,
+				     <0x20>,
+				     <0x30>,
+				     <0x40>;
+	};
+
+	glink_qos_bg: qcom,glink-qos-config-bg {
+		compatible = "qcom,glink-qos-config";
+		qcom,flow-info = <0x80 0x0>,
+				 <0x70 0x1>,
+				 <0x60 0x2>,
+				 <0x50 0x3>;
+		qcom,mtu-size = <0x800>;
+		qcom,tput-stats-cycle = <0xa>;
+	};
+
+	qcom,glink_pkt {
+		compatible = "qcom,glinkpkt";
+
+		qcom,glinkpkt-bg-daemon {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "bg-daemon";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon";
+		};
+
+		qcom,glinkpkt-bg-display-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "display-ctrl";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_display_ctrl";
+		};
+
+		qcom,glinkpkt-bg-display-data {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "display-data";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_display_data";
+		};
+
+		qcom,glinkpkt-bg-rsb-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "RSB_CTRL";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_rsb_ctrl";
+		};
+	};
+
+	spi@78B8000 {  /* BLSP1 QUP4 */
+		status = "ok";
+		qcom,bg-spi {
+			compatible = "qcom,bg-spi";
+			reg = <0>;
+			spi-max-frequency = <16000000>;
+			interrupt-parent = <&msm_gpio>;
+			qcom,irq-gpio = <&msm_gpio 110 1>;
+		};
+	};
+
+	qcom,bg-rsb {
+		compatible = "qcom,bg-rsb";
+		vdd-ldo1-supply = <&pm660_l11>;
+		vdd-ldo2-supply = <&pm660_l15>;
+	};
+
+	qcom,bg-daemon {
+		compatible = "qcom,bg-daemon";
+		qcom,bg-reset-gpio = <&pm660_gpios 5 0>;
+		ssr-reg1-supply = <&pm660_l3>;
+		ssr-reg2-supply = <&pm660_l9>;
+	};
+};
+
+&i2c_1 {
+	status = "okay";
+	nq@28 {
+		compatible = "qcom,nq-nci";
+		reg = <0x28>;
+		qcom,nq-irq = <&msm_gpio 50 0x00>;
+		qcom,nq-ven = <&msm_gpio 36 0x00>;
+		qcom,nq-firm = <&msm_gpio 38 0x00>;
+		qcom,nq-esepwr = <&msm_gpio 49 0x00>;
+		qcom,nq-clkreq = <&pm660_gpios 4 0x00>;
+		qcom,clk-src = "BBCLK3";
+		interrupt-parent = <&msm_gpio>;
+		interrupts = <50 0>;
+		interrupt-names = "nfc_irq";
+		pinctrl-names = "nfc_active","nfc_suspend";
+		pinctrl-0 = <&nfcw_int_active &nfcw_disable_active>;
+		pinctrl-1 = <&nfcw_int_suspend &nfcw_disable_suspend>;
+		clock-names = "ref_clk";
+	};
+};
+
+&spi_0 {
+	status = "disabled";
+};
+
+&i2c_3 {
+	status = "disabled";
+};
+
+&i2c_4 {
+	status = "disabled";
+};
+
+&i2c_2 {
+	status = "disabled";
+};
+
+&sdc1_clk_off {
+	config {
+		pins = "sdc1_clk";
+		bias-disable; /* NO pull */
+		drive-strength = <2>; /* 2 MA */
+		output-low;
+	};
+};
+
+&sdc1_cmd_off {
+	config {
+		pins = "sdc1_cmd";
+		bias-disable; /* NO pull */
+		drive-strength = <2>; /* 2 MA */
+		output-low;
+	};
+};
+
+&sdc1_data_off {
+	config {
+		pins = "sdc1_data";
+		bias-disable; /* NO pull */
+		drive-strength = <2>; /* 2 MA */
+		output-low;
+	};
+};
+
+&sdhc_2 {
+	status = "disabled";
+};
+
+&audio_codec_mtp {
+	status = "disabled";
+};
+
+&audio_codec_bg {
+	status = "ok";
+};
+
+&bg_cdc {
+	status = "ok";
+	vdd-spkr-supply = <&pm660_l11>;
+};
+
+&blsp1_uart1 {
+	status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console_sleep>;
+};
+
+/* Pinctrl dt nodes for interrupt and reset gpio for Synaptics controller */
+&ts_int_active {
+	mux {
+		pins = "gpio98";
+	};
+
+	config {
+		pins = "gpio98";
+	};
+};
+
+&ts_int_suspend {
+	mux {
+		pins = "gpio98";
+	};
+
+	config {
+		pins = "gpio98";
+		/delete-property/ bias-pull-down;
+		bias-disable; /* No PULL */
+	};
+};
+
+&ts_reset_active {
+	mux {
+		pins = "gpio16";
+	};
+
+	config {
+		pins = "gpio16";
+	};
+};
+
+&ts_reset_suspend {
+	mux {
+		pins = "gpio16";
+	};
+
+	config {
+		pins = "gpio16";
+	};
+};
+
+&ts_release {
+	mux {
+		pins = "gpio98", "gpio16";
+	};
+
+	config {
+		pins = "gpio98", "gpio16";
+	};
+};
+
+&spi4_cs0_active {
+	mux {
+		pins = "gpio14";
+		function = "blsp_spi4";
+	};
+	config {
+		pins = "gpio14";
+		drive-strength = <2>;
+		bias-disable; /* No PULL */
+		output-high;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/apq8053-camera-sensor-mtp.dtsi
new file mode 100644
index 0000000..c1dd0f1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/apq8053-camera-sensor-mtp.dtsi
@@ -0,0 +1,143 @@
+/*
+ * 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.
+ */
+
+&soc{
+	led_ir0: qcom,ir-led {
+		cell-index = <0>;
+		compatible = "qcom,ir-led";
+		label = "led-ir-label";
+		pwms = <&pm8953_pwm 0 0>;
+	};
+
+	ir_cut0: qcom,ir-cut {
+		cell-index = <0>;
+		compatible = "qcom,ir-cut";
+		label = "ir-cut-label";
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_ir_cut_default>;
+		pinctrl-1 = <&cam_sensor_ir_cut_sleep>;
+		gpios = <&tlmm 38 0>, <&tlmm 39 0>;
+		qcom,gpio-ir-p = <0>;
+		qcom,gpio-ir-m =  <1>;
+		qcom,gpio-req-tbl-num = <0 1>;
+		qcom,gpio-req-tbl-flags = <0 0>;
+		qcom,gpio-req-tbl-label = "IR_CUT_FILTER_P",
+				"IR_CUT_FILTER_M";
+	};
+};
+
+&pm8953_pwm {
+	status = "okay";
+	qcom,dtest-line = <2>;   /* DTEST2 */
+	qcom,dtest-output = <2>; /* OUTPUT PWM */
+};
+
+&pm8953_mpps {
+	mpp@a300 {
+		qcom,mode = <1>;        /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <3>;     /* L5 @ 1.8V */
+		qcom,src-sel = <5>;     /* DTEST2 */
+		qcom,master-en = <1>;   /* Enable MPP */
+		qcom,invert = <0>;      /* Enable MPP */
+		status = "okay";
+	};
+};
+
+&cci {
+	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>;
+		cam_vdig-supply = <&pm8953_l2>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vana-supply = <&pm8953_l22>;
+		qcom,ir-led-src = <&led_ir0>;
+		qcom,ir-cut-src = <&ir_cut0>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-min-voltage = <1100000 0 2850000>;
+		qcom,cam-vreg-max-voltage = <1100000 0 2850000>;
+		qcom,cam-vreg-op-mode = <0 105000 80000>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_default
+				&cam_sensor_rear_default
+				&cam_sensor_rear_vana>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
+				&cam_sensor_rear_vana_sleep>;
+		gpios = <&tlmm 26 0>,
+			<&tlmm 40 0>,
+			<&tlmm 46 0>,
+			<&tlmm 134 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-vdig =  <2>;
+		qcom,gpio-vana =  <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_VDIG",
+			"CAM_VANA";
+		qcom,sensor-position = <0>;
+		qcom,sensor-mode = <0>;
+		qcom,cci-master = <0>;
+		status = "ok";
+		clocks = <&clock_gcc clk_mclk0_clk_src>,
+				<&clock_gcc clk_gcc_camss_mclk0_clk>;
+		clock-names = "cam_src_clk", "cam_clk";
+		qcom,clock-rates = <24000000 0>;
+	};
+
+	qcom,camera@1 {
+		cell-index = <1>;
+		compatible = "qcom,camera";
+		reg = <0x1>;
+		qcom,csiphy-sd-index = <1>;
+		qcom,csid-sd-index = <1>;
+		qcom,mount-angle = <270>;
+		cam_vdig-supply = <&pm8953_l1>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vana-supply = <&pm8953_l17>;
+		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+		qcom,cam-vreg-min-voltage = <1100000 0 2850000>;
+		qcom,cam-vreg-max-voltage = <1100000 0 2850000>;
+		qcom,cam-vreg-op-mode = <105000 0 80000>;
+		qcom,gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_default
+				&cam_sensor_front1_default>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep
+				&cam_sensor_front1_sleep>;
+		gpios = <&tlmm 26 0>,
+			<&tlmm 129 0>,
+			<&tlmm 130 0>;
+		qcom,gpio-reset = <1>;
+		qcom,gpio-standby = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
+		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+					  "CAM_RESET2",
+					  "CAM_STANDBY2";
+		qcom,sensor-position = <1>;
+		qcom,sensor-mode = <1>;
+		qcom,cci-master = <1>;
+		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/apq8053-iot-mtp.dts b/arch/arm64/boot/dts/qcom/apq8053-iot-mtp.dts
index 44b4792..8f7e326 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-iot-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053-iot-mtp.dts
@@ -17,6 +17,7 @@
 #include "pmi8950.dtsi"
 #include "msm8953-mtp.dtsi"
 #include "msm8953-pmi8950.dtsi"
+#include "apq8053-camera-sensor-mtp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. APQ8053 + PMI8950 IOT MTP";
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
index 76b1fa2..f2d4ef3 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon.dtsi
@@ -344,47 +344,54 @@
 };
 
 &pmi8950_gpios {
-	gpio@c000 {	/* GPIO_1 */
-		status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pmi_gpio1_default>;
+	pmi_gpio1_default: pmi8950_gpio1 {
+		pins = "gpio1";
+		function = "normal";
+		input-enable;
+		power-source = <0>;
+		status = "okay";
 	};
 };
 
 &pmi8950_mpps {
-	mpp@a200 {	/* MPP_3 */
-		qcom,mode = <1>;		/* Digital output */
-		qcom,output-type = <0>;	/* CMOS logic */
-		qcom,vin-sel = <2>;		/* 1.8V */
-		qcom,src-sel = <0>;		/* Constant */
-		qcom,master-en = <1>;	/* Enable GPIO */
-		qcom,invert = <0>;
-		status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&ext_fet_wled_pwr_en_default>;
+	ext_fet_wled_pwr_en_default: pmi8950_mpp3 {
+		pins = "mpp3";  /* MPP_3 */
+		function = "digital"; /* Digital */
+		output-high; /* Output */
+		drive-strength = <2>; /* 1.8 mA */
+		power-source = <1>;
+		bias-disable = <0>; /* no pull */
+		status = "okay";
 	};
 };
 
 &pm8953_gpios {
-	gpio@c000 {	/* GPIO_1 */
-		status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pm_gpio1_div_clk2_default>;
+	pm_gpio1_div_clk2_default: pm8953_gpio1 {
+		pins = "gpio1";
+		function = "normal";
+		output-high;
+		power-source = <1>;
+		status = "okay";
 	};
 };
 
 &pm8953_mpps {
-	mpp@a000 {	/* MPP_1 */		/* VDD_PX */
-		status = "disabled";
-	};
-	mpp@a100 {	/* MPP_2 */
-		status = "disabled";
-	};
-	mpp@a200 {	/* MPP_3 */
-		status = "disabled";
-	};
-
-	mpp@a300 {	/* MPP_4 */		/* WLED_PWM_CTRL */
-		qcom,mode = <1>;		/* Digital output */
-		qcom,output-type = <0>;	/* CMOS logic */
-		qcom,vin-sel = <0>;		/* VPH_PWR */
-		qcom,src-sel = <4>;		/* DTEST1 */
-		qcom,master-en = <1>;	/* Enable GPIO */
-		qcom,invert = <0>;
-		status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&pm_mpp4_wled_pwm_ctrl_default>;
+	pm_mpp4_wled_pwm_ctrl_default: pm8953_mpp4 {
+		pins = "mpp4"; /* WLED_PWM_CTRL */
+		function = "digital"; /* Digital */
+		output-high;	/* Output */
+		drive-strength = <2>; /* 1.8 mA */
+		power-source = <0>; /* VPH_PWR */
+		qcom,dtest = <1>; /* DTEST1 */
+		bias-disable = <0>; /* no pull */
+		status = "okay";
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/batterydata-palladium.dtsi b/arch/arm64/boot/dts/qcom/batterydata-palladium.dtsi
new file mode 100644
index 0000000..2a89e71
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/batterydata-palladium.dtsi
@@ -0,0 +1,121 @@
+/* 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
+ * 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,palladium-batterydata {
+	qcom,fcc-mah = <1500>;
+	qcom,default-rbatt-mohm = <210>;
+	qcom,rbatt-capacitive-mohm = <50>;
+	qcom,flat-ocv-threshold-uv = <3800000>;
+	qcom,max-voltage-uv = <4200000>;
+	qcom,v-cutoff-uv = <3400000>;
+	qcom,chg-term-ua = <100000>;
+	qcom,batt-id-kohm = <75>;
+	qcom,battery-type = "palladium_1500mah";
+
+	qcom,fcc-temp-lut {
+		qcom,lut-col-legend = <(-20) 0 25 40 60>;
+		qcom,lut-data = <1467 1470 1473 1473 1470>;
+	};
+
+	qcom,pc-temp-ocv-lut {
+		qcom,lut-col-legend = <(-20) 0 25 40 60>;
+		qcom,lut-row-legend = <100 95 90 85 80>,
+				<75 70 65 60 55>,
+				<50 45 40 35 30>,
+				<25 20 16 13 11>,
+				<10 9 8 7 6>,
+				<5 4 3 2 1>,
+				<0>;
+		qcom,lut-data = <4175 4173 4167 4162 4157>,
+				<4097 4111 4112 4110 4107>,
+				<4039 4075 4072 4068 4064>,
+				<3963 4017 4025 4026 4025>,
+				<3920 3969 3984 3989 3988>,
+				<3887 3932 3957 3958 3955>,
+				<3856 3898 3929 3928 3925>,
+				<3830 3868 3900 3901 3898>,
+				<3808 3843 3858 3863 3862>,
+				<3793 3821 3827 3827 3827>,
+				<3779 3803 3807 3808 3807>,
+				<3768 3788 3792 3793 3792>,
+				<3757 3779 3780 3780 3779>,
+				<3746 3771 3772 3768 3768>,
+				<3734 3762 3765 3759 3749>,
+				<3722 3747 3753 3744 3730>,
+				<3707 3721 3731 3722 3709>,
+				<3693 3705 3704 3696 3683>,
+				<3678 3698 3687 3678 3667>,
+				<3664 3693 3683 3676 3665>,
+				<3656 3690 3682 3675 3664>,
+				<3646 3687 3681 3674 3662>,
+				<3634 3683 3680 3672 3661>,
+				<3618 3677 3676 3668 3656>,
+				<3599 3667 3667 3655 3639>,
+				<3573 3645 3638 3623 3603>,
+				<3541 3607 3591 3575 3554>,
+				<3496 3550 3528 3511 3490>,
+				<3428 3469 3445 3423 3400>,
+				<3312 3342 3308 3280 3250>,
+				<3000 3000 3000 3000 3000>;
+	};
+
+	qcom,rbatt-sf-lut {
+		qcom,lut-col-legend = <(-20) 0 25 40 60>;
+		qcom,lut-row-legend = <100 95 90 85 80>,
+				<75 70 65 60 55>,
+				<50 45 40 35 30>,
+				<25 20 16 13 11>,
+				<10 9 8 7 6>,
+				<5 4 3 2 1>,
+				<0>;
+		qcom,lut-data = <909 216 100 85 84>,
+				<859 238 106 88 86>,
+				<860 237 105 88 86>,
+				<808 239 107 90 88>,
+				<801 234 111 94 90>,
+				<801 230 118 97 92>,
+				<801 224 123 100 95>,
+				<807 221 128 106 99>,
+				<818 221 111 101 97>,
+				<841 225 101 88 87>,
+				<870 229 101 88 87>,
+				<906 235 103 91 90>,
+				<950 243 106 93 93>,
+				<998 253 110 93 96>,
+				<1051 263 113 94 90>,
+				<1116 272 113 91 88>,
+				<1200 275 111 91 88>,
+				<1312 298 108 90 87>,
+				<1430 329 104 88 87>,
+				<1484 351 107 91 89>,
+				<1446 345 110 93 90>,
+				<1398 344 112 94 90>,
+				<1466 358 115 96 91>,
+				<1490 357 117 96 90>,
+				<1589 365 117 94 89>,
+				<1828 379 111 91 88>,
+				<2151 399 111 93 91>,
+				<2621 436 117 98 95>,
+				<3404 496 130 106 100>,
+				<8212 616 150 1906 134>,
+				<135251 124940 59087 49820 29672>;
+	};
+
+	qcom,ibat-acc-lut {
+		qcom,lut-col-legend = <(-20) 0 25>;
+		qcom,lut-row-legend = <0 250 500 1000>;
+		qcom,lut-data = <1470 1470 1473>,
+				<601 1406 1430>,
+				<89 1247 1414>,
+				<8 764 1338>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-truly-720p-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-truly-720p-cmd.dtsi
new file mode 100644
index 0000000..db3abf1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-truly-720p-cmd.dtsi
@@ -0,0 +1,255 @@
+/* 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_truly_720_cmd: qcom,mdss_dsi_truly_720p_cmd {
+		qcom,mdss-dsi-panel-name = "truly 720p cmd mode dsi panel";
+		qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <720>;
+		qcom,mdss-dsi-panel-height = <1280>;
+		qcom,mdss-dsi-h-front-porch = <100>;
+		qcom,mdss-dsi-h-back-porch = <100>;
+		qcom,mdss-dsi-h-pulse-width = <6>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <32>;
+		qcom,mdss-dsi-v-front-porch = <32>;
+		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-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-h-sync-pulse = <0>;
+		qcom,mdss-dsi-traffic-mode = "burst_mode";
+		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 = [87 2c 12 00 40 44 16 1e 17 03
+			04 00];
+		qcom,mdss-dsi-t-clk-post = <0x04>;
+		qcom,mdss-dsi-t-clk-pre = <0x1b>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,mdss-dsi-dma-trigger = "trigger_sw";
+		qcom,mdss-dsi-mdp-trigger = "none";
+		qcom,mdss-dsi-te-pin-select = <1>;
+		qcom,mdss-dsi-te-dcs-command = <1>;
+		qcom,mdss-dsi-te-check-enable;
+		qcom,mdss-dsi-te-using-te-pin;
+		qcom,mdss-dsi-on-command = [29 01 00 00 00 00 06 f0 55 aa 52
+				08 00
+			29 01 00 00 00 00 03 b1 78 21
+			23 01 00 00 00 00 02 b6 0f
+			29 01 00 00 00 00 03 bc 00 00
+			29 01 00 00 00 00 06 bd 02 67 20 20 00
+			29 01 00 00 00 00 0b e7 f2 e6 d8 cc bf b2 a5 99 99 95
+			29 01 00 00 00 00 0b e8 f2 e6 d8 cc bf b2 a5 99 99 95
+			29 01 00 00 00 00 06 f0 55 aa 52 08 01
+			29 01 00 00 00 00 03 bc a0 00
+			29 01 00 00 00 00 03 bd a0 00
+			23 01 00 00 00 00 02 ca 01
+			23 01 00 00 00 00 02 c0 0c
+			23 01 00 00 00 00 02 be 4e
+			29 01 00 00 00 00 03 b3 38 38
+			29 01 00 00 00 00 03 b4 11 11
+			29 01 00 00 00 00 03 b6 05 05
+			29 01 00 00 00 00 03 b9 45 45
+			29 01 00 00 00 00 03 ba 25 25
+			29 01 00 00 00 00 03 c4 11 11
+			23 01 00 00 00 00 02 c6 66
+			29 01 00 00 00 00 06 f0 55 aa 52 08 02
+			23 01 00 00 00 00 02 ee 00
+			29 01 00 00 00 00 11 b0 00 37 00 48 00 69 00 8a 00 ab 00
+				cb 00 eb 01 1c
+			29 01 00 00 00 00 11 b1 01 41 01 7c 01 aa 01 f3 02 2d 02
+				2e 02 63 02 9d
+			29 01 00 00 00 00 11 b2 02 c3 02 f6 03 19 03 54 03 85 03
+				b2 03 c1 03 d1
+			29 01 00 00 00 00 05 b3 03 e0 03 e8
+			29 01 00 00 00 00 11 bc 00 37 00 48 00 69 00 8a 00 ab 00
+				cb 00 eb 01 1c
+			29 01 00 00 00 00 11 bd 01 41 01 7c 01 aa 01 f3 02 2d 02
+				2e 02 63 02 9d
+			29 01 00 00 00 00 11 be 02 c3 02 f6 03 19 03 54 03 85 03
+				b2 03 c1 03 d1
+			29 01 00 00 00 00 05 bf 03 e0 03 e8
+			29 01 00 00 00 00 11 b4 00 d1 00 d7 00 e4 00 f1 00 fe 01
+				12 01 26 01 48
+			29 01 00 00 00 00 11 b5 01 64 01 95 01 bd 02 01 02 36 02
+				38 02 6c 02 a7
+			29 01 00 00 00 00 11 b6 02 ce 03 04 03 2b 03 5b 03 89 03
+				b2 03 c1 03 d1
+			29 01 00 00 00 00 05 b7 03 e0 03 e8
+			29 01 00 00 00 00 11 c0 00 d1 00 d7 00 e4 00 f1 00 fe 01
+				12 01 26 01 48
+			29 01 00 00 00 00 11 c1 01 64 01 95 01 bd 02 01 02 36 02
+				38 02 6c 02 a7
+			29 01 00 00 00 00 11 c2 02 ce 03 04 03 2b 03 5b 03 89 03
+				b2 03 c1 03 d1
+			29 01 00 00 00 00 05 c3 03 e0 03 e8
+			29 01 00 00 00 00 11 b8 00 37 00 45 00 61 00 7d 00 9a 00
+				bb 00 dc 01 0b
+			29 01 00 00 00 00 11 b9 01 31 01 6e 01 9e 01 ea 02 24 02
+				25 02 58 02 90
+			29 01 00 00 00 00 11 ba 02 b4 02 e4 03 04 03 44 03 7f 03
+				b2 03 c1 03 d1
+			29 01 00 00 00 00 05 bb 03 e0 03 e8
+			29 01 00 00 00 00 11 c4 00 37 00 45 00 61 00 7d 00 9a 00
+				bb 00 dc 01 0b
+			29 01 00 00 00 00 11 c5 01 31 01 6e 01 9e 01 ea 02 24 02
+				25 02 58 02 90
+			29 01 00 00 00 00 11 c6 02 b4 02 e4 03 04 03 44 03 7f 03
+				b2 03 c1 03 d1
+			29 01 00 00 00 00 05 c7 03 e0 03 e8
+			29 01 00 00 00 00 06 f0 55 aa 52 08 06
+			29 01 00 00 00 00 03 b0 29 2a
+			29 01 00 00 00 00 03 b1 10 12
+			29 01 00 00 00 00 03 b2 14 16
+			29 01 00 00 00 00 03 b3 18 1a
+			29 01 00 00 00 00 03 b4 02 04
+			29 01 00 00 00 00 03 b5 34 34
+			29 01 00 00 00 00 03 b6 34 2e
+			29 01 00 00 00 00 03 b7 2e 2e
+			29 01 00 00 00 00 03 b8 34 00
+			29 01 00 00 00 00 03 b9 34 34
+			29 01 00 00 00 00 03 ba 34 34
+			29 01 00 00 00 00 03 bb 01 34
+			29 01 00 00 00 00 03 bc 2e 2e
+			29 01 00 00 00 00 03 bd 2e 34
+			29 01 00 00 00 00 03 be 34 34
+			29 01 00 00 00 00 03 bf 05 03
+			29 01 00 00 00 00 03 c0 1b 19
+			29 01 00 00 00 00 03 c1 17 15
+			29 01 00 00 00 00 03 c2 13 11
+			29 01 00 00 00 00 03 c3 2a 29
+			29 01 00 00 00 00 03 e5 2e 2e
+			29 01 00 00 00 00 03 c4 29 2a
+			29 01 00 00 00 00 03 c5 1b 19
+			29 01 00 00 00 00 03 c6 17 15
+			29 01 00 00 00 00 03 c7 13 11
+			29 01 00 00 00 00 03 c8 01 05
+			29 01 00 00 00 00 03 c9 34 34
+			29 01 00 00 00 00 03 ca 34 2e
+			29 01 00 00 00 00 03 cb 2e 2e
+			29 01 00 00 00 00 03 cc 34 03
+			29 01 00 00 00 00 03 cd 34 34
+			29 01 00 00 00 00 03 ce 34 34
+			29 01 00 00 00 00 03 cf 02 34
+			29 01 00 00 00 00 03 d0 2e 2e
+			29 01 00 00 00 00 03 d1 2e 34
+			29 01 00 00 00 00 03 d2 34 34
+			29 01 00 00 00 00 03 d3 04 00
+			29 01 00 00 00 00 03 d4 10 12
+			29 01 00 00 00 00 03 d5 14 16
+			29 01 00 00 00 00 03 d6 18 1a
+			29 01 00 00 00 00 03 d7 2a 29
+			29 01 00 00 00 00 03 e6 2e 2e
+			29 01 00 00 00 00 06 d8 00 00 00 54 00
+			29 01 00 00 00 00 06 d9 00 15 00 00 00
+			23 01 00 00 00 00 02 e7 00
+			29 01 00 00 00 00 06 f0 55 aa 52 08 03
+			29 01 00 00 00 00 03 b1 00 00
+			29 01 00 00 00 00 03 b0 00 00
+			29 01 00 00 00 00 06 b2 05 00 00 00 00
+			29 01 00 00 00 00 06 b3 05 00 00 00 00
+			29 01 00 00 00 00 06 b4 05 00 00 00 00
+			29 01 00 00 00 00 06 b5 05 00 17 00 00
+			29 01 00 00 00 00 06 b6 12 00 19 00 00
+			29 01 00 00 00 00 06 b7 12 00 19 00 00
+			29 01 00 00 00 00 06 b8 12 00 19 00 00
+			29 01 00 00 00 00 06 b9 12 00 19 00 00
+			29 01 00 00 00 00 06 ba 57 00 00 00 00
+			29 01 00 00 00 00 06 bb 57 00 00 00 00
+			29 01 00 00 00 00 06 bc 75 00 1a 00 00
+			29 01 00 00 00 00 06 bd 53 00 1a 00 00
+			29 01 00 00 00 00 05 c0 00 34 00 00
+			29 01 00 00 00 00 05 c1 00 34 00 00
+			29 01 00 00 00 00 05 c2 00 34 00 00
+			29 01 00 00 00 00 05 c3 00 34 00 00
+			23 01 00 00 00 00 02 c4 20
+			23 01 00 00 00 00 02 c5 00
+			23 01 00 00 00 00 02 c6 00
+			23 01 00 00 00 00 02 c7 00
+			29 01 00 00 00 00 06 f0 55 aa 52 08 05
+			23 01 00 00 00 00 02 ed 30
+			29 01 00 00 00 00 03 b0 17 06
+			23 01 00 00 00 00 02 b8 08
+			29 01 00 00 00 00 06 bd 03 07 00 03 00
+			29 01 00 00 00 00 03 b1 17 06
+			23 01 00 00 00 00 02 b9 00
+			29 01 00 00 00 00 03 b2 00 00
+			23 01 00 00 00 00 02 ba 00
+			29 01 00 00 00 00 03 b3 17 06
+			23 01 00 00 00 00 02 bb 0a
+			29 01 00 00 00 00 03 b4 17 06
+			29 01 00 00 00 00 03 b5 17 06
+			29 01 00 00 00 00 03 b6 14 03
+			29 01 00 00 00 00 03 b7 00 00
+			23 01 00 00 00 00 02 bc 02
+			23 01 00 00 00 00 02 e5 06
+			23 01 00 00 00 00 02 e6 06
+			23 01 00 00 00 00 02 e7 00
+			23 01 00 00 00 00 02 e8 06
+			23 01 00 00 00 00 02 e9 06
+			23 01 00 00 00 00 02 ea 06
+			23 01 00 00 00 00 02 eb 00
+			23 01 00 00 00 00 02 ec 00
+			23 01 00 00 00 00 02 c0 07
+			23 01 00 00 00 00 02 c1 80
+			23 01 00 00 00 00 02 c2 a4
+			23 01 00 00 00 00 02 c3 05
+			23 01 00 00 00 00 02 c4 00
+			23 01 00 00 00 00 02 c5 02
+			23 01 00 00 00 00 02 c6 22
+			23 01 00 00 00 00 02 c7 03
+			29 01 00 00 00 00 03 c8 05 30
+			29 01 00 00 00 00 03 c9 01 31
+			29 01 00 00 00 00 03 ca 03 21
+			29 01 00 00 00 00 03 cb 01 20
+			29 01 00 00 00 00 06 d1 00 05 09 07 10
+			29 01 00 00 00 00 06 d2 10 05 0e 03 10
+			29 01 00 00 00 00 06 d3 20 00 48 07 10
+			29 01 00 00 00 00 06 d4 30 00 43 07 10
+			23 01 00 00 00 00 02 d0 00
+			29 01 00 00 00 00 04 cc 00 00 3e
+			29 01 00 00 00 00 04 cd 00 00 3e
+			29 01 00 00 00 00 04 ce 00 00 02
+			29 01 00 00 00 00 04 cf 00 00 02
+			23 01 00 00 00 00 02 6f 11
+			23 01 00 00 00 00 02 f3 01
+			15 01 00 00 00 00 02 51 ff
+			15 01 00 00 00 00 02 53 2c
+			15 01 00 00 00 00 02 55 03
+			15 01 00 00 c8 00 02 35 00
+			05 01 00 00 78 00 02 11 00
+			05 01 00 00 0a 00 02 29 00];
+		qcom,mdss-dsi-off-command = [05 01 00 00 14 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_lp_mode";
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+		qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+		qcom,mdss-dsi-tx-eot-append;
+		qcom,mdss-dsi-lp11-init;
+		qcom,mdss-dsi-post-init-delay = <1>;
+		qcom,mdss-dsi-wr-mem-start = <0x2c>;
+		qcom,mdss-dsi-wr-mem-continue = <0x3c>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-truly-720p-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-truly-720p-video.dtsi
new file mode 100644
index 0000000..80ead08
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-truly-720p-video.dtsi
@@ -0,0 +1,249 @@
+/* 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_truly_720_vid: qcom,mdss_dsi_truly_720p_video {
+		qcom,mdss-dsi-panel-name = "truly 720p 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 = <720>;
+		qcom,mdss-dsi-panel-height = <1280>;
+		qcom,mdss-dsi-h-front-porch = <100>;
+		qcom,mdss-dsi-h-back-porch = <100>;
+		qcom,mdss-dsi-h-pulse-width = <6>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <32>;
+		qcom,mdss-dsi-v-front-porch = <32>;
+		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-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-h-sync-pulse = <0>;
+		qcom,mdss-dsi-traffic-mode = "burst_mode";
+		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 = [87 2c 12 00 40 44 16 1e 17 03
+			04 00];
+		qcom,mdss-dsi-t-clk-post = <0x04>;
+		qcom,mdss-dsi-t-clk-pre = <0x1b>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,mdss-dsi-dma-trigger = "trigger_sw";
+		qcom,mdss-dsi-mdp-trigger = "none";
+		qcom,mdss-dsi-on-command = [29 01 00 00 00 00 06 f0 55 aa 52
+				08 00
+			29 01 00 00 00 00 03 b1 78 21
+			23 01 00 00 00 00 02 b6 0f
+			29 01 00 00 00 00 03 bc 00 00
+			29 01 00 00 00 00 06 bd 02 b0 1e 1e 00
+			29 01 00 00 00 00 0b e7 f2 e6 d8 cc bf b2 a5 99 99 95
+			29 01 00 00 00 00 0b e8 f2 e6 d8 cc bf b2 a5 99 99 95
+			29 01 00 00 00 00 06 f0 55 aa 52 08 01
+			29 01 00 00 00 00 03 bc a0 00
+			29 01 00 00 00 00 03 bd a0 00
+			23 01 00 00 00 00 02 ca 01
+			23 01 00 00 00 00 02 c0 0c
+			23 01 00 00 00 00 02 be 4e
+			29 01 00 00 00 00 03 b3 38 38
+			29 01 00 00 00 00 03 b4 11 11
+			29 01 00 00 00 00 03 b6 05 05
+			29 01 00 00 00 00 03 b9 45 45
+			29 01 00 00 00 00 03 ba 25 25
+			29 01 00 00 00 00 03 c4 11 11
+			23 01 00 00 00 00 02 c6 66
+			29 01 00 00 00 00 06 f0 55 aa 52 08 02
+			23 01 00 00 00 00 02 ee 00
+			29 01 00 00 00 00 11 b0 00 37 00 48 00 69 00 8a 00 ab 00
+				cb 00 eb 01 1c
+			29 01 00 00 00 00 11 b1 01 41 01 7c 01 aa 01 f3 02 2d 02
+				2e 02 63 02 9d
+			29 01 00 00 00 00 11 b2 02 c3 02 f6 03 19 03 54 03 85 03
+				b2 03 c1 03 d1
+			29 01 00 00 00 00 05 b3 03 e0 03 e8
+			29 01 00 00 00 00 11 bc 00 37 00 48 00 69 00 8a 00 ab 00
+				cb 00 eb 01 1c
+			29 01 00 00 00 00 11 bd 01 41 01 7c 01 aa 01 f3 02 2d 02
+				2e 02 63 02 9d
+			29 01 00 00 00 00 11 be 02 c3 02 f6 03 19 03 54 03 85 03
+				b2 03 c1 03 d1
+			29 01 00 00 00 00 05 bf 03 e0 03 e8
+			29 01 00 00 00 00 11 b4 00 d1 00 d7 00 e4 00 f1 00 fe 01
+				12 01 26 01 48
+			29 01 00 00 00 00 11 b5 01 64 01 95 01 bd 02 01 02 36 02
+				38 02 6c 02 a7
+			29 01 00 00 00 00 11 b6 02 ce 03 04 03 2b 03 5b 03 89 03
+				b2 03 c1 03 d1
+			29 01 00 00 00 00 05 b7 03 e0 03 e8
+			29 01 00 00 00 00 11 c0 00 d1 00 d7 00 e4 00 f1 00 fe 01
+				12 01 26 01 48
+			29 01 00 00 00 00 11 c1 01 64 01 95 01 bd 02 01 02 36 02
+				38 02 6c 02 a7
+			29 01 00 00 00 00 11 c2 02 ce 03 04 03 2b 03 5b 03 89 03
+				b2 03 c1 03 d1
+			29 01 00 00 00 00 05 c3 03 e0 03 e8
+			29 01 00 00 00 00 11 b8 00 37 00 45 00 61 00 7d 00 9a 00
+				bb 00 dc 01 0b
+			29 01 00 00 00 00 11 b9 01 31 01 6e 01 9e 01 ea 02 24 02
+				25 02 58 02 90
+			29 01 00 00 00 00 11 ba 02 b4 02 e4 03 04 03 44 03 7f 03
+				b2 03 c1 03 d1
+			29 01 00 00 00 00 05 bb 03 e0 03 e8
+			29 01 00 00 00 00 11 c4 00 37 00 45 00 61 00 7d 00 9a 00
+				bb 00 dc 01 0b
+			29 01 00 00 00 00 11 c5 01 31 01 6e 01 9e 01 ea 02 24 02
+				25 02 58 02 90
+			29 01 00 00 00 00 11 c6 02 b4 02 e4 03 04 03 44 03 7f 03
+				b2 03 c1 03 d1
+			29 01 00 00 00 00 05 c7 03 e0 03 e8
+			29 01 00 00 00 00 06 f0 55 aa 52 08 06
+			29 01 00 00 00 00 03 b0 29 2a
+			29 01 00 00 00 00 03 b1 10 12
+			29 01 00 00 00 00 03 b2 14 16
+			29 01 00 00 00 00 03 b3 18 1a
+			29 01 00 00 00 00 03 b4 02 04
+			29 01 00 00 00 00 03 b5 34 34
+			29 01 00 00 00 00 03 b6 34 2e
+			29 01 00 00 00 00 03 b7 2e 2e
+			29 01 00 00 00 00 03 b8 34 00
+			29 01 00 00 00 00 03 b9 34 34
+			29 01 00 00 00 00 03 ba 34 34
+			29 01 00 00 00 00 03 bb 01 34
+			29 01 00 00 00 00 03 bc 2e 2e
+			29 01 00 00 00 00 03 bd 2e 34
+			29 01 00 00 00 00 03 be 34 34
+			29 01 00 00 00 00 03 bf 05 03
+			29 01 00 00 00 00 03 c0 1b 19
+			29 01 00 00 00 00 03 c1 17 15
+			29 01 00 00 00 00 03 c2 13 11
+			29 01 00 00 00 00 03 c3 2a 29
+			29 01 00 00 00 00 03 e5 2e 2e
+			29 01 00 00 00 00 03 c4 29 2a
+			29 01 00 00 00 00 03 c5 1b 19
+			29 01 00 00 00 00 03 c6 17 15
+			29 01 00 00 00 00 03 c7 13 11
+			29 01 00 00 00 00 03 c8 01 05
+			29 01 00 00 00 00 03 c9 34 34
+			29 01 00 00 00 00 03 ca 34 2e
+			29 01 00 00 00 00 03 cb 2e 2e
+			29 01 00 00 00 00 03 cc 34 03
+			29 01 00 00 00 00 03 cd 34 34
+			29 01 00 00 00 00 03 ce 34 34
+			29 01 00 00 00 00 03 cf 02 34
+			29 01 00 00 00 00 03 d0 2e 2e
+			29 01 00 00 00 00 03 d1 2e 34
+			29 01 00 00 00 00 03 d2 34 34
+			29 01 00 00 00 00 03 d3 04 00
+			29 01 00 00 00 00 03 d4 10 12
+			29 01 00 00 00 00 03 d5 14 16
+			29 01 00 00 00 00 03 d6 18 1a
+			29 01 00 00 00 00 03 d7 2a 29
+			29 01 00 00 00 00 03 e6 2e 2e
+			29 01 00 00 00 00 06 d8 00 00 00 54 00
+			29 01 00 00 00 00 06 d9 00 15 00 00 00
+			23 01 00 00 00 00 02 e7 00
+			29 01 00 00 00 00 06 f0 55 aa 52 08 03
+			29 01 00 00 00 00 03 b1 00 00
+			29 01 00 00 00 00 03 b0 00 00
+			29 01 00 00 00 00 06 b2 05 00 00 00 00
+			29 01 00 00 00 00 06 b3 05 00 00 00 00
+			29 01 00 00 00 00 06 b4 05 00 00 00 00
+			29 01 00 00 00 00 06 b5 05 00 17 00 00
+			29 01 00 00 00 00 06 b6 12 00 19 00 00
+			29 01 00 00 00 00 06 b7 12 00 19 00 00
+			29 01 00 00 00 00 06 b8 12 00 19 00 00
+			29 01 00 00 00 00 06 b9 12 00 19 00 00
+			29 01 00 00 00 00 06 ba 57 00 00 00 00
+			29 01 00 00 00 00 06 bb 57 00 00 00 00
+			29 01 00 00 00 00 06 bc 75 00 1a 00 00
+			29 01 00 00 00 00 06 bd 53 00 1a 00 00
+			29 01 00 00 00 00 05 c0 00 34 00 00
+			29 01 00 00 00 00 05 c1 00 34 00 00
+			29 01 00 00 00 00 05 c2 00 34 00 00
+			29 01 00 00 00 00 05 c3 00 34 00 00
+			23 01 00 00 00 00 02 c4 20
+			23 01 00 00 00 00 02 c5 00
+			23 01 00 00 00 00 02 c6 00
+			23 01 00 00 00 00 02 c7 00
+			29 01 00 00 00 00 06 f0 55 aa 52 08 05
+			23 01 00 00 00 00 02 ed 30
+			29 01 00 00 00 00 03 b0 17 06
+			23 01 00 00 00 00 02 b8 08
+			29 01 00 00 00 00 06 bd 03 07 00 03 00
+			29 01 00 00 00 00 03 b1 17 06
+			23 01 00 00 00 00 02 b9 00
+			29 01 00 00 00 00 03 b2 00 00
+			23 01 00 00 00 00 02 ba 00
+			29 01 00 00 00 00 03 b3 17 06
+			23 01 00 00 00 00 02 bb 0a
+			29 01 00 00 00 00 03 b4 17 06
+			29 01 00 00 00 00 03 b5 17 06
+			29 01 00 00 00 00 03 b6 14 03
+			29 01 00 00 00 00 03 b7 00 00
+			23 01 00 00 00 00 02 bc 02
+			23 01 00 00 00 00 02 e5 06
+			23 01 00 00 00 00 02 e6 06
+			23 01 00 00 00 00 02 e7 00
+			23 01 00 00 00 00 02 e8 06
+			23 01 00 00 00 00 02 e9 06
+			23 01 00 00 00 00 02 ea 06
+			23 01 00 00 00 00 02 eb 00
+			23 01 00 00 00 00 02 ec 00
+			23 01 00 00 00 00 02 c0 07
+			23 01 00 00 00 00 02 c1 80
+			23 01 00 00 00 00 02 c2 a4
+			23 01 00 00 00 00 02 c3 05
+			23 01 00 00 00 00 02 c4 00
+			23 01 00 00 00 00 02 c5 02
+			23 01 00 00 00 00 02 c6 22
+			23 01 00 00 00 00 02 c7 03
+			29 01 00 00 00 00 03 c8 05 30
+			29 01 00 00 00 00 03 c9 01 31
+			29 01 00 00 00 00 03 ca 03 21
+			29 01 00 00 00 00 03 cb 01 20
+			29 01 00 00 00 00 06 d1 00 05 09 07 10
+			29 01 00 00 00 00 06 d2 10 05 0e 03 10
+			29 01 00 00 00 00 06 d3 20 00 48 07 10
+			29 01 00 00 00 00 06 d4 30 00 43 07 10
+			23 01 00 00 00 00 02 d0 00
+			29 01 00 00 00 00 04 cc 00 00 3e
+			29 01 00 00 00 00 04 cd 00 00 3e
+			29 01 00 00 00 00 04 ce 00 00 02
+			29 01 00 00 00 00 04 cf 00 00 02
+			23 01 00 00 00 00 02 6f 11
+			23 01 00 00 00 00 02 f3 01
+			15 01 00 00 00 00 02 51 ff
+			15 01 00 00 00 00 02 53 2c
+			15 01 00 00 00 00 02 55 03
+			15 01 00 00 c8 00 02 35 00
+			05 01 00 00 78 00 02 11 00
+			05 01 00 00 0a 00 02 29 00];
+		qcom,mdss-dsi-off-command = [05 01 00 00 14 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_lp_mode";
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+		qcom,mdss-dsi-reset-sequence = <1 10>, <0 10>, <1 10>;
+		qcom,mdss-dsi-tx-eot-append;
+		qcom,mdss-dsi-lp11-init;
+		qcom,mdss-dsi-post-init-delay = <1>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-8909.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-8909.dtsi
new file mode 100644
index 0000000..a601b5f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-8909.dtsi
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/clock/msm-clocks-8909.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+&soc {
+
+	apps_iommu: qcom,iommu@1e00000 {
+		compatible = "qcom,qsmmu-v500";
+		reg = <0x1e00000 0x40000>,
+			<0x1ef2000 0x20>;
+		reg-names = "base", "tcu-base";
+		#iommu-cells = <2>;
+		qcom,tz-device-id = "APPS";
+		qcom,skip-init;
+		qcom,enable-static-cb;
+		qcom,use-3-lvl-tables;
+		qcom,disable-atos;
+		#global-interrupts = <0>;
+		#size-cells = <1>;
+		#address-cells = <1>;
+		ranges;
+		interrupts =
+				<GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 230 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+			clocks =
+				<&clock_gcc clk_gcc_smmu_cfg_clk>,
+				<&clock_gcc clk_gcc_apss_tcu_clk>;
+			clock-names = "iface_clk", "core_clk";
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-8917.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-8917.dtsi
new file mode 100644
index 0000000..603ba40
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-8917.dtsi
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	gfx_iommu: qcom,iommu@1f00000 {
+		status = "ok";
+		compatible = "qcom,qsmmu-v500";
+		reg = <0x1f00000 0x10000>,
+			<0x1ee2000 0x20>;
+		reg-names = "base", "tcu-base";
+		#iommu-cells = <1>;
+		qcom,tz-device-id = "GPU";
+		qcom,skip-init;
+		qcom,enable-static-cb;
+		qcom,dynamic;
+		qcom,use-3-lvl-tables;
+		#global-interrupts = <0>;
+		#size-cells = <1>;
+		#address-cells = <1>;
+		ranges;
+		interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clock_gcc clk_gcc_smmu_cfg_clk>,
+				<&clock_gcc clk_gcc_gfx_tcu_clk>;
+		clock-names = "iface_clk", "core_clk";
+	};
+
+	apps_iommu: qcom,iommu@1e00000 {
+		status = "okay";
+		compatible = "qcom,qsmmu-v500";
+		reg = <0x1e00000 0x40000>,
+			<0x1ee2000 0x20>;
+		reg-names = "base", "tcu-base";
+		#iommu-cells = <2>;
+		qcom,tz-device-id = "APPS";
+		qcom,skip-init;
+		qcom,disable-atos;
+		ranges;
+		qcom,enable-static-cb;
+		qcom,use-3-lvl-tables;
+		#global-interrupts = <0>;
+		#size-cells = <1>;
+		#address-cells = <1>;
+		interrupts = <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clock_gcc clk_gcc_smmu_cfg_clk>,
+				<&clock_gcc clk_gcc_apss_tcu_clk>;
+		clock-names = "iface_clk", "core_clk";
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
index 7f18173..18fc575 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
@@ -237,6 +237,14 @@
 	pinctrl-0 = <&uart_console_sleep>;
 };
 
+/ {
+	mtp_batterydata: qcom,battery-data {
+		qcom,rpull-up-kohm = <100>;
+		qcom,vref-batt-therm = <1800000>;
+		#include "batterydata-palladium.dtsi"
+	};
+};
+
 &qcom_rng {
 	status = "okay";
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pm8916-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pm8916-mtp.dtsi
new file mode 100644
index 0000000..86bee6e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-pm8916-mtp.dtsi
@@ -0,0 +1,187 @@
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
+
+&soc {
+	i2c@78b9000 {
+		synaptics@20 {
+			avdd-supply = <&pm8916_l17>;
+			vdd-supply = <&pm8916_l6>;
+		};
+	};
+
+	i2c@78b6000 {
+		nq@28 {
+			qcom,nq-clkreq = <&pm8916_gpios 2 0>;
+		};
+	};
+
+};
+
+&audio_codec_mtp {
+	qcom,model = "msm8909-pm8916-snd-card";
+	pinctrl-names =
+		"all_off",
+		"pri_i2s_act",
+		"us_eu_gpio_act",
+		"pri_i2s_us_eu_gpio_act";
+	pinctrl-0 = <&cdc_pdm_lines_sus &cross_conn_det_sus>;
+	pinctrl-1 = <&cdc_pdm_lines_act &cross_conn_det_sus>;
+	pinctrl-2 = <&cdc_pdm_lines_sus &cross_conn_det_act>;
+	pinctrl-3 = <&cdc_pdm_lines_act &cross_conn_det_act>;
+	asoc-codec = <&stub_codec>, <&pm8916_tombak_dig>;
+	asoc-codec-names = "msm-stub-codec.1", "cajon_codec";
+};
+
+&sdhc_1 {
+	vdd-supply = <&pm8916_l8>;
+	vdd-io-supply = <&pm8916_l5>;
+};
+
+&sdhc_2 {
+	vdd-supply = <&pm8916_l11>;
+	vdd-io-supply = <&pm8916_l12>;
+};
+
+&i2c_3 {
+	qcom,actuator@0 {
+		cam_vaf-supply = <&pm8916_l8>;
+	};
+
+
+	qcom,eeprom@6c{
+		cam_vdig-supply = <&pm8916_l2>;
+		cam_vana-supply = <&pm8916_l10>;
+		cam_vio-supply = <&pm8916_l6>;
+		cam_vaf-supply = <&pm8916_l8>;
+	};
+
+	qcom,camera@0 {
+		cam_vdig-supply = <&pm8916_l2>;
+		cam_vana-supply = <&pm8916_l10>;
+		cam_vio-supply = <&pm8916_l6>;
+		cam_vaf-supply = <&pm8916_l8>;
+	};
+
+	qcom,camera@1 {
+		cam_vana-supply = <&pm8916_l10>;
+		cam_vio-supply = <&pm8916_l6>;
+	};
+};
+
+&spmi_bus {
+	pm8916@0 {
+		qcom,leds@a300 {
+			status = "okay";
+			qcom,led_mpp_4 {
+				label = "mpp";
+				linux,name = "button-backlight";
+				linux,default-trigger = "none";
+				qcom,default-state = "off";
+				qcom,max-current = <40>;
+				qcom,current-setting = <5>;
+				qcom,id = <6>;
+				qcom,mode = "manual";
+				qcom,source-sel = <1>;
+				qcom,mode-ctrl = <0x60>;
+			};
+		};
+	};
+
+	pm8916@1 {
+		qcom,vibrator@c000 {
+			status = "okay";
+			qcom,vib-timeout-ms = <15000>;
+			qcom,vib-vtg-level-mV = <3100>;
+		};
+	};
+};
+
+&pm8916_mpps {
+	/* VDD_PX_BIAS_MPP_1 */
+	vdd_px_bias_mpp {
+		vdd_px_bias_mpp_default: vdd_px_bias_mpp_default {
+			pins = "mpp1";
+			function = "digital";
+			status = "disabled";
+		};
+	};
+
+	/* PMIC_MPP_2 */
+	pmic_mpp {
+		pmic_mpp_default: pmic_mpp_default {
+			pins = "mpp2";
+			function = "digital";
+			status = "disabled";
+		};
+	};
+
+	/* VREF_DAC_MPP_3 */
+	vref_dac_mpp {
+		vref_dac_mpp_default: vref_dac_mpp_default {
+			pins = "mpp3";
+			function = "digital";
+			status = "disabled";
+		};
+	};
+
+	/* WLED_PWM_MPP_4 */
+	wled_pwm_mpp {
+		wled_pwm_mpp_default: wled_pwm_mpp_default {
+			pins = "mpp3";
+			function = "digital";
+			output-enable;
+			power-source = <PM8916_MPP_VPH>;
+			status = "okay";
+		};
+	};
+};
+
+/* pm8916 gpio pinctrl configuration */
+&pm8916_gpios {
+	/* Battery UICC Alarm */
+	uim_batt_alarm { /* GPIO 1 */
+		uim_batt_alarm_default: uim_batt_alarm_default {
+			pins = "gpio1";
+			status = "disabled";
+		};
+	};
+
+	/* GPIO 2 (NFC_CLK_REQ) */
+	nfc_clk {
+		nfc_clk_default: nfc_clk_default {
+			pins = "gpio2";
+			function = "normal";
+			input-enable;
+			status = "disabled";
+		};
+	};
+
+	/*  WCN_LDO_EN_GPIO_3 */
+	wcn_ldo_en {
+		wcn_ldo_en_default: wcn_ldo_en_default {
+			pins = "gpio3";
+			function = "normal";
+			output-low;
+			qcom,drive-strength = <1>;
+			status = "disabled";
+		};
+	};
+
+	/* External regulator control for APC */
+	wcd_eldo_en { /* GPIO 4 */
+		wcd_eldo_en_default: wcd_eldo_en_default {
+			pins = "gpio4";
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pm8916-pm.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pm8916-pm.dtsi
new file mode 100644
index 0000000..3633a6a
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-pm8916-pm.dtsi
@@ -0,0 +1,515 @@
+/* Copyright (c) 2014-2016, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/msm/pm.h>
+
+&soc {
+	qcom,spm@b089000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb089000 0x1000>;
+		qcom,name = "cpu0";
+		qcom,cpu = <&CPU0>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x01>;
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0xe>;
+		qcom,mode0 {
+			qcom,label = "qcom,saw2-spm-cmd-wfi";
+			qcom,sequence = [60 03 60 0b 0f];
+			qcom,spm_en;
+		};
+		qcom,mode1 {
+			qcom,label = "qcom,saw2-spm-cmd-spc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+		qcom,mode2 {
+			qcom,label = "qcom,saw2-spm-cmd-pc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+			qcom,slp_cmd_mode;
+		};
+	};
+
+	qcom,spm@b099000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb099000 0x1000>;
+		qcom,name = "cpu1";
+		qcom,cpu = <&CPU1>;
+		qcom,core-id = <1>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x01>;
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0xe>;
+		qcom,mode0 {
+			qcom,label = "qcom,saw2-spm-cmd-wfi";
+			qcom,sequence = [60 03 60 0b 0f];
+			qcom,spm_en;
+		};
+		qcom,mode1 {
+			qcom,label = "qcom,saw2-spm-cmd-spc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+		qcom,mode2 {
+			qcom,label = "qcom,saw2-spm-cmd-pc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+			qcom,slp_cmd_mode;
+		};
+	};
+
+	qcom,spm@b0a9000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb0a9000 0x1000>;
+		qcom,name = "cpu2";
+		qcom,cpu = <&CPU2>;
+		qcom,core-id = <2>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x01>;
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0xe>;
+		qcom,mode0 {
+			qcom,label = "qcom,saw2-spm-cmd-wfi";
+			qcom,sequence = [60 03 60 0b 0f];
+			qcom,spm_en;
+		};
+		qcom,mode1 {
+			qcom,label = "qcom,saw2-spm-cmd-spc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+		qcom,mode2 {
+			qcom,label = "qcom,saw2-spm-cmd-pc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+			qcom,slp_cmd_mode;
+		};
+	};
+
+	qcom,spm@b0b9000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb0b9000 0x1000>;
+		qcom,name = "cpu3";
+		qcom,cpu = <&CPU3>;
+		qcom,core-id = <3>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x01>;
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0xe>;
+		qcom,mode0 {
+			qcom,label = "qcom,saw2-spm-cmd-wfi";
+			qcom,sequence = [60 03 60 0b 0f];
+			qcom,spm_en;
+		};
+		qcom,mode1 {
+			qcom,label = "qcom,saw2-spm-cmd-spc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+		qcom,mode2 {
+			qcom,label = "qcom,saw2-spm-cmd-pc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+			qcom,slp_cmd_mode;
+		};
+	};
+
+	qcom,spm@0xb012000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb012000 0x1000>;
+		qcom,name = "system-l2";
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x14>;
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0xe>;
+		qcom,saw2-pmic-data0 = <0x05030080>;
+		qcom,saw2-pmic-data1 = <0x00030000>;
+		qcom,saw2-pmic-data4 = <0x00010080>;
+		qcom,saw2-pmic-data5 = <0x00010000>;
+		qcom,cpu-vctl-list = <&CPU0 &CPU1 &CPU2 &CPU3>;
+		qcom,vctl-timeout-us = <500>;
+		qcom,vctl-port = <0x0>;
+		qcom,phase-port = <0x1>;
+		qcom,pfm-port = <0x2>;
+		qcom,mode0 {
+			qcom,label = "qcom,saw2-spm-cmd-ret";
+			qcom,sequence = [00 03 00 0f];
+			qcom,spm_en;
+		};
+		qcom,mode1 {
+			qcom,label = "qcom,saw2-spm-cmd-gdhs";
+			qcom,sequence = [00 20 32 6b c0 e0 d0 42 03 50 4e 02
+					02 d0 e0 c0 22 6b 02 32 50 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+		qcom,mode2 {
+			qcom,label = "qcom,saw2-spm-cmd-pc";
+			qcom,sequence = [00 32 b0 10 e0 d0 6b c0 42 f0 51 11
+				07 01 41 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
+				50 f0 0f]; /*APC_L2RAM_OFF */
+			qcom,spm_en;
+			qcom,pc_mode;
+			qcom,slp_cmd_mode;
+		};
+	};
+
+	qcom,lpm-levels {
+		compatible = "qcom,lpm-levels";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,pm-cluster@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			label = "system";
+			qcom,spm-device-names = "l2";
+			qcom,default-level = <0>;
+
+			qcom,pm-cluster-level@0 {
+				reg = <0>;
+				label = "l2-cache-active";
+				qcom,spm-l2-mode = "active";
+				qcom,latency-us = <270>;
+				qcom,ss-power = <455>;
+				qcom,energy-overhead = <250621>;
+				qcom,time-overhead = <500>;
+			};
+
+			qcom,pm-cluster-level@1{
+				reg = <1>;
+				label = "l2-gdhs";
+				qcom,spm-l2-mode = "gdhs";
+				qcom,latency-us = <500>;
+				qcom,ss-power = <427>;
+				qcom,energy-overhead = <431578>;
+				qcom,time-overhead = <900>;
+				qcom,min-child-idx = <1>;
+				qcom,reset-level = <LPM_RESET_LVL_GDHS>;
+			};
+
+			qcom,pm-cluster-level@2{
+				reg = <2>;
+				label = "l2-pc";
+				qcom,spm-l2-mode = "pc";
+				qcom,latency-us = <11530>;
+				qcom,ss-power = <400>;
+				qcom,energy-overhead = <800000>;
+				qcom,time-overhead = <2500>;
+				qcom,min-child-idx = <2>;
+				qcom,notify-rpm;
+				qcom,reset-level = <LPM_RESET_LVL_PC>;
+			};
+
+
+			qcom,pm-cpu {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				qcom,pm-cpu-level@0{
+					reg = <0>;
+					qcom,spm-cpu-mode = "wfi";
+					qcom,latency-us = <1>;
+					qcom,ss-power = <473>;
+					qcom,energy-overhead = <100000>;
+					qcom,time-overhead = <50>;
+				};
+
+				qcom,pm-cpu-level@1 {
+					reg = <1>;
+					qcom,spm-cpu-mode = "standalone_pc";
+					qcom,latency-us = <240>;
+					qcom,ss-power = <467>;
+					qcom,energy-overhead = <202781>;
+					qcom,time-overhead = <420>;
+					qcom,use-broadcast-timer;
+					qcom,reset-level =
+						<LPM_RESET_LVL_PC>;
+				};
+
+				qcom,pm-cpu-level@2 {
+					reg = <2>;
+					qcom,spm-cpu-mode = "pc";
+					qcom,latency-us = <270>;
+					qcom,ss-power = <455>;
+					qcom,energy-overhead = <250621>;
+					qcom,time-overhead = <500>;
+					qcom,use-broadcast-timer;
+					qcom,reset-level =
+						<LPM_RESET_LVL_PC>;
+				};
+			};
+		};
+	};
+
+	qcom,lpm-workarounds {
+		compatible = "qcom,lpm-workarounds";
+		qcom,lpm-wa-skip-l2-spm;
+	};
+
+	qcom,mpm@601d0 {
+		compatible = "qcom,mpm-v2";
+		reg = <0x601d0 0x1000>, /* MSM_RPM_MPM_BASE 4K */
+		    <0xb011008 0x4>;
+		reg-names = "vmpm", "ipc";
+		interrupts = <0 171 1>;
+		clocks = <&clock_rpm clk_xo_lpm_clk>;
+		clock-names = "xo";
+		qcom,ipc-bit-offset = <1>;
+		qcom,gic-parent = <&intc>;
+		qcom,gic-map = <2 216>, /* tsens_upper_lower_int */
+			<48 168>, /* usb_phy_id_irq */
+			<49 172>, /* usb1_hs_async_wakeup_irq */
+			<58 166>, /* usb_hs_irq */
+			<53 104>, /* mdss_irq */
+			<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+			<0xff 18>,  /* APC_qgicQTmrSecPhysIrptReq */
+			<0xff 19>,  /* APC_qgicQTmrNonSecPhysIrptReq */
+			<0xff 20>,  /* qgicQTmrVirtIrptReq */
+			<0xff 35>,  /* WDT_barkInt */
+			<0xff 39>,  /* arch_mem_timer */
+			<0xff 40>,  /* qtmr_phy_irq[0] */
+			<0xff 47>,  /* rbif_irq[0] */
+			<0xff 56>,  /* q6_wdog_expired_irq */
+			<0xff 57>,  /* mss_to_apps_irq(0) */
+			<0xff 58>,  /* mss_to_apps_irq(1) */
+			<0xff 59>,  /* mss_to_apps_irq(2) */
+			<0xff 60>,  /* mss_to_apps_irq(3) */
+			<0xff 61>,  /* mss_a2_bam_irq */
+			<0xff 65>,  /* o_gc_sys_irq[0] */
+			<0xff 70>,  /* smmu_bus_intr[0] */
+			<0xff 73>,  /* smmu_bus_intr[1] */
+			<0xff 74>,  /* smmu_bus_intr[2] */
+			<0xff 75>,  /* smmu_bus_intr[3] */
+			<0xff 77>,  /* smmu_bus_intr[4] */
+			<0xff 78>,  /* smmu_bus_intr[5] */
+			<0xff 79>,  /* smmu_bus_intr[6] */
+			<0xff 80>,  /* smmu_bus_intr[7] */
+			<0xff 94>,  /* smmu_bus_intr[8] */
+			<0xff 96>,  /* smmu_bus_intr[9] */
+			<0xff 97>,  /* smmu_bus_intr[10] */
+			<0xff 98>,  /* smmu_bus_intr[11] */
+			<0xff 101>, /* smmu_bus_intr[13] */
+			<0xff 102>, /* smmu_bus_intr[14] */
+			<0xff 105>, /* msm_iommu_global_cfg_irq */
+			<0xff 107>, /* msm_iommu_global_cfg_irq */
+			<0xff 114>, /* qdsd_intr_out */
+			<0xff 131>, /* qup_irq */
+			<0xff 133>, /* smmu_bus_intr[29] */
+			<0xff 134>, /* smmu_bus_intr[30] */
+			<0xff 135>, /* smmu_bus_intr[31] */
+			<0xff 136>, /* smmu_bus_intr[32] */
+			<0xff 137>, /* smmu_bus_intr[33] */
+			<0xff 138>, /* smmu_bus_intr[34] */
+			<0xff 140>, /* uart_dm_intr */
+			<0xff 141>, /* smmu_bus_intr[35] */
+			<0xff 142>, /* smmu_bus_intr[36] */
+			<0xff 143>, /* smmu_bus_intr[37] */
+			<0xff 144>, /* smmu_bus_intr[38] */
+			<0xff 145>, /* smmu_bus_intr[39] */
+			<0xff 146>, /* smmu_bus_intr[40] */
+			<0xff 147>, /* smmu_bus_intr[41] */
+			<0xff 148>, /* smmu_bus_intr[42] */
+			<0xff 149>, /* smmu_bus_intr[43] */
+			<0xff 150>, /* smmu_bus_intr[44] */
+			<0xff 151>, /* smmu_bus_intr[45] */
+			<0xff 152>, /* smmu_bus_intr[46] */
+			<0xff 153>, /* smmu_bus_intr[47] */
+			<0xff 154>, /* smmu_bus_intr[48] */
+			<0xff 155>, /* sdc1_irq(0) */
+			<0xff 157>, /* sdc2_irq(0) */
+			<0xff 170>, /* sdc1_pwr_cmd_irq */
+			<0xff 173>, /* o_wcss_apss_smd_hi */
+			<0xff 174>, /* o_wcss_apss_smd_med */
+			<0xff 175>, /* o_wcss_apss_smd_low */
+			<0xff 176>, /* o_wcss_apss_smsm_irq */
+			<0xff 177>, /* o_wcss_apss_wlan_data_xfer_done */
+			<0xff 178>, /* o_wcss_apss_wlan_rx_data_avail */
+			<0xff 179>, /* o_wcss_apss_asic_intr */
+			<0xff 181>, /* o_wcss_apss_wdog_bite_and_reset_rdy */
+			<0xff 182>, /* smmu_bus_intr[58] */
+			<0xff 183>, /* smmu_bus_intr[59] */
+			<0xff 184>, /* smmu_bus_intr[60] */
+			<0xff 188>, /* lpass_irq_out_apcs(0) */
+			<0xff 189>, /* lpass_irq_out_apcs(1) */
+			<0xff 190>, /* lpass_irq_out_apcs(2) */
+			<0xff 191>, /* lpass_irq_out_apcs(3) */
+			<0xff 192>, /* lpass_irq_out_apcs(4) */
+			<0xff 193>, /* lpass_irq_out_apcs(5) */
+			<0xff 194>, /* lpass_irq_out_apcs(6) */
+			<0xff 195>, /* lpass_irq_out_apcs(7) */
+			<0xff 196>, /* lpass_irq_out_apcs(8) */
+			<0xff 197>, /* lpass_irq_out_apcs(9) */
+			<0xff 198>, /* coresight-tmc-etr interrupt */
+			<0xff 200>, /* rpm_ipc(4) */
+			<0xff 201>, /* rpm_ipc(5) */
+			<0xff 202>, /* rpm_ipc(6) */
+			<0xff 203>, /* rpm_ipc(7) */
+			<0xff 204>, /* rpm_ipc(24) */
+			<0xff 205>, /* rpm_ipc(25) */
+			<0xff 206>, /* rpm_ipc(26) */
+			<0xff 207>, /* rpm_ipc(27) */
+			<0xff 215>, /* o_bimc_intr */
+			<0xff 239>, /* crypto_bam_irq[1]*/
+			<0xff 224>, /* spdm_realtime_irq(1) */
+			<0xff 240>, /* summary_irq_kpss */
+			<0xff 253>, /* sdc2_pwr_cmd_irq */
+			<0xff 255>, /* smmu_bus_intr[49] */
+			<0xff 256>, /* smmu_bus_intr[50] */
+			<0xff 257>, /* smmu_bus_intr[51] */
+			<0xff 260>, /* smmu_bus_intr[52] */
+			<0xff 261>, /* smmu_bus_intr[53] */
+			<0xff 262>, /* smmu_bus_intr[54] */
+			<0xff 263>, /* smmu_bus_intr[55] */
+			<0xff 264>, /* smmu_bus_intr[56] */
+			<0xff 265>, /* smmu_bus_intr[57] */
+			<0xff 269>, /* rpm_wdog_expired_irq */
+			<0xff 270>, /* blsp1_bam_irq[0] */
+			<0xff 272>, /* smmu_bus_intr[17] */
+			<0xff 273>, /* smmu_bus_intr[18] */
+			<0xff 274>, /* smmu_bus_intr[19] */
+			<0xff 275>, /* rpm_ipc(30) */
+			<0xff 276>, /* rpm_ipc(31) */
+			<0xff 277>, /* smmu_bus_intr[20] */
+			<0xff 278>, /* smmu_bus_intr[21] */
+			<0xff 279>, /* smmu_bus_intr[22] */
+			<0xff 280>, /* smmu_bus_intr[23] */
+			<0xff 281>, /* smmu_bus_intr[24] */
+			<0xff 282>, /* smmu_bus_intr[25] */
+			<0xff 283>, /* smmu_bus_intr[26] */
+			<0xff 284>, /* smmu_bus_intr[27] */
+			<0xff 285>; /* smmu_bus_intr[28] */
+
+		qcom,gpio-parent = <&msm_gpio>;
+		qcom,gpio-map = <3  65 >,
+			<4  5>,
+			<5  11>,
+			<6  12>,
+			<7  64>,
+			<8  58>,
+			<9  50>,
+			<10  13>,
+			<11  49>,
+			<12  20>,
+			<13  21>,
+			<14  25>,
+			<15  46>,
+			<16  45>,
+			<17  28>,
+			<18  44>,
+			<19  31>,
+			<20  43>,
+			<21  42>,
+			<22  34>,
+			<23  35>,
+			<24  36>,
+			<25  37>,
+			<26  38>,
+			<27  39>,
+			<28  40>,
+			<29  41>,
+			<30  90>,
+			<32  91>,
+			<33  92>,
+			<34  94>,
+			<35  95>,
+			<36  96>,
+			<37  97>,
+			<38  98>,
+			<39  110>,
+			<40  111>,
+			<41  112>,
+			<42  105>,
+			<43  107>,
+			<50  47>,
+			<51  48>;
+	};
+
+
+	qcom,pm@8600664 {
+		compatible = "qcom,pm";
+		reg = <0x8600664 0x40>;
+		clocks = <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>;
+		clock-names = "cpu0_clk", "cpu1_clk",
+			      "cpu2_clk", "cpu3_clk";
+		qcom,pc-mode = "tz_l2_int";
+		qcom,use-sync-timer;
+		qcom,synced-clocks;
+	};
+
+	qcom,cpu-sleep-status {
+		compatible = "qcom,cpu-sleep-status";
+	};
+
+	qcom,rpm-log@29dc00 {
+		compatible = "qcom,rpm-log";
+		reg = <0x29dc00 0x4000>;
+		qcom,rpm-addr-phys = <0x200000>;
+		qcom,offset-version = <4>;
+		qcom,offset-page-buffer-addr = <36>;
+		qcom,offset-log-len = <40>;
+		qcom,offset-log-len-mask = <44>;
+		qcom,offset-page-indices = <56>;
+	};
+
+	qcom,rpm-stats@29dba0 {
+		compatible = "qcom,rpm-stats";
+		reg = <0x29dba0 0x1000>;
+		reg-names = "phys_addr_base";
+		qcom,sleep-stats-version = <2>;
+	};
+
+	qcom,rpm-master-stats@60150 {
+		compatible = "qcom,rpm-master-stats";
+		reg = <0x60150 0x2030>;
+		qcom,masters = "APSS", "MPSS", "PRONTO";
+		qcom,master-stats-version = <2>;
+		qcom,master-offset = <4096>;
+	};
+
+	qcom,rpm-rbcpr-stats@0x200000  {
+		compatible = "qcom,rpmrbcpr-stats";
+		reg = <0x200000 0x1000>;
+		qcom,start-offset = <0x90010>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909.dtsi b/arch/arm64/boot/dts/qcom/msm8909.dtsi
index 7b38370..5e56c49 100644
--- a/arch/arm64/boot/dts/qcom/msm8909.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909.dtsi
@@ -334,7 +334,7 @@
 		compatible = "qcom,gcc-mdss-8909";
 		clocks = <&mdss_dsi0_pll clk_dsi_pll0_pixel_clk_src>,
 			 <&mdss_dsi0_pll clk_dsi_pll0_byte_clk_src>;
-		clock-names = "pixel_src", "byte_src";
+		clock-names = "pclk0_src", "byte0_src";
 		#clock-cells = <1>;
 	};
 
@@ -1363,6 +1363,7 @@
 		qcom,scm_core_clk_src-freq = <80000000>;
 
 		qcom,pas-id = <9>;
+		qcom,mas-crypto = <&mas_crypto>;
 		qcom,proxy-timeout-ms = <100>;
 		qcom,firmware-name = "venus";
 		memory-region = <&venus_qseecom_mem>;
@@ -1792,6 +1793,7 @@
 		qcom,sysmon-id = <6>;
 		qcom,ssctl-instance-id = <0x13>;
 		qcom,firmware-name = "wcnss";
+		qcom,mas-crypto = <&mas_crypto>;
 
 		/* GPIO inputs from wcnss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
@@ -1835,6 +1837,7 @@
 		qcom,pil-self-auth;
 		qcom,sysmon-id = <0>;
 		qcom,ssctl-instance-id = <0x12>;
+		qcom,reset-clk;
 
 		/* GPIO inputs from mss */
 		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts b/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
index 8bcbe68..24266e8 100644
--- a/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
+++ b/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
@@ -18,6 +18,7 @@
 #include "msm8909w-bg-memory.dtsi"
 #include "8909w-pm660.dtsi"
 #include "msm8909-audio-bg_codec.dtsi"
+#include "msm-arm-smmu-8909.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. MSM8909W-PM660 BLACKGHOST WTP";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-regulator.dtsi b/arch/arm64/boot/dts/qcom/msm8916-regulator.dtsi
new file mode 100644
index 0000000..0313ebd
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8916-regulator.dtsi
@@ -0,0 +1,382 @@
+/* Copyright (c) 2013-2015, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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.
+ */
+
+/* CPR controlled regulator */
+&soc {
+	mem_acc_vreg_corner: regulator@1946000 {
+		compatible = "qcom,mem-acc-regulator";
+		reg = <0x1946000 0x4>, <0x58000 0x1000>;
+		reg-names = "acc-sel-l1", "efuse_addr";
+		regulator-name = "mem_acc_corner";
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <3>;
+
+		qcom,acc-sel-l1-bit-pos = <0>;
+		qcom,acc-sel-l1-bit-size = <9>;
+		qcom,corner-acc-map = <0x0 0x100 0x101>;
+
+		qcom,override-acc-fuse-sel = <0 52 1 1 0>;
+		qcom,override-corner-acc-map = <0x0 0x100 0x100>;
+	};
+
+	apc_vreg_corner: regulator@b018000 {
+		compatible = "qcom,cpr-regulator";
+		reg = <0xb018000 0x1000>, <0xb011064 0x4>, <0x58000 0x1000>;
+		reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
+		interrupts = <0 15 0>;
+		regulator-name = "apc_corner";
+		qcom,cpr-fuse-corners = <3>;
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <9>;
+
+		qcom,cpr-voltage-ceiling = <1050000 1150000 1350000>;
+		qcom,cpr-voltage-floor = <1050000 1050000 1162500>;
+		vdd-apc-supply = <&pm8916_s2>;
+
+		qcom,vdd-mx-corner-map = <4 5 7>;
+		qcom,vdd-mx-vmin-method = <4>;
+		vdd-mx-supply = <&pm8916_l3_corner_ao>;
+		qcom,vdd-mx-vmax = <7>;
+
+		mem-acc-supply = <&mem_acc_vreg_corner>;
+
+		qcom,cpr-ref-clk = <19200>;
+		qcom,cpr-timer-delay = <5000>;
+		qcom,cpr-timer-cons-up = <0>;
+		qcom,cpr-timer-cons-down = <2>;
+		qcom,cpr-irq-line = <0>;
+		qcom,cpr-step-quotient = <26>;
+		qcom,cpr-up-threshold = <0>;
+		qcom,cpr-down-threshold = <2>;
+		qcom,cpr-idle-clocks = <15>;
+		qcom,cpr-gcnt-time = <1>;
+		qcom,vdd-apc-step-up-limit = <1>;
+		qcom,vdd-apc-step-down-limit = <1>;
+		qcom,cpr-apc-volt-step = <12500>;
+
+		qcom,cpr-fuse-row = <27 0>;
+		qcom,cpr-fuse-target-quot = <42 24 6>;
+		qcom,cpr-fuse-ro-sel = <54 54 54>;
+		qcom,cpr-fuse-bp-cpr-disable = <57>;
+		qcom,cpr-fuse-init-voltage =
+					<27 36 6 0>,
+					<27 18 6 0>,
+					<27 0 6 0>;
+		qcom,cpr-init-voltage-ref = <1050000 1150000 1350000>;
+		qcom,cpr-init-voltage-step = <10000>;
+		qcom,cpr-corner-map = <1 1 2 2 3 3 3 3 3>;
+		qcom,cpr-corner-frequency-map =
+					<1 200000000>,
+					<2 400000000>,
+					<3 533330000>,
+					<4 800000000>,
+					<5 998400000>,
+					<6 1094400000>,
+					<7 1152000000>,
+					<8 1209600000>,
+					<9 1363200000>;
+		qcom,speed-bin-fuse-sel = <1 34 3 0>;
+		qcom,pvs-version-fuse-sel = <0 55 2 0>;
+		qcom,cpr-speed-bin-max-corners =
+					<0 0 2 4 8>,
+					<0 1 2 4 7>,
+					<2 0 2 4 9>,
+					<3 0 2 4 5>,
+					<3 1 2 4 5>;
+		qcom,cpr-quot-adjust-scaling-factor-max = <650>;
+		qcom,cpr-enable;
+	};
+};
+
+/* SPM controlled regulators */
+&spmi_bus {
+	pm8916@1 {
+		pm8916_s2: spm-regulator@1700 {
+			compatible = "qcom,spm-regulator";
+			regulator-name = "8916_s2";
+			reg = <0x1700 0x100>;
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1350000>;
+		};
+	};
+};
+
+/* RPM controlled regulators */
+&rpm_bus {
+
+	/* PM8916 S1 VDD_CX supply */
+	rpm-regulator-smpa1 {
+		status = "okay";
+		pm8916_s1_corner: regulator-s1-corner {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_s1_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+		};
+		pm8916_s1_corner_ao: regulator-s1-corner-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_s1_corner_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+		};
+		pm8916_s1_floor_corner: regulator-s1-floor-corner {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_s1_floor_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-floor-corner;
+			qcom,always-send-voltage;
+		};
+	};
+
+	rpm-regulator-smpa3 {
+		status = "okay";
+		pm8916_s3: regulator-s3 {
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1300000>;
+			qcom,init-voltage = <1200000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-smpa4 {
+		status = "okay";
+		pm8916_s4: regulator-s4 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2100000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		status = "okay";
+		pm8916_l1: regulator-l1 {
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,init-voltage = <1225000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		status = "okay";
+		pm8916_l2: regulator-l2 {
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,init-voltage = <1200000>;
+			status = "okay";
+		};
+	};
+
+	/* PM8916 L3 VDD_MX supply */
+	rpm-regulator-ldoa3 {
+		status = "okay";
+		pm8916_l3: regulator-l3 {
+			regulator-min-microvolt = <500000>;
+			regulator-max-microvolt = <1287500>;
+			status = "okay";
+		};
+
+		pm8916_l3_corner_ao: regulator-l3-corner-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l3_corner_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+		};
+
+		pm8916_l3_corner_so: regulator-l3-corner-so {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l3_corner_so";
+			qcom,set = <2>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+			qcom,init-voltage = <1>;
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+		status = "okay";
+		pm8916_l4: regulator-l4 {
+			regulator-min-microvolt = <2050000>;
+			regulator-max-microvolt = <2050000>;
+			qcom,init-voltage = <2050000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		status = "okay";
+		pm8916_l5: regulator-l5 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		status = "okay";
+		pm8916_l6: regulator-l6 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		status = "okay";
+		pm8916_l7: regulator-l7 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+
+		pm8916_l7_ao: regulator-l7-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l7_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+		};
+
+		pm8916_l7_so: regulator-l7-so {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l7_so";
+			qcom,set = <2>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-enable = <0>;
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		status = "okay";
+		pm8916_l8: regulator-l8 {
+			regulator-min-microvolt = <2850000>;
+			regulator-max-microvolt = <2900000>;
+			qcom,init-voltage = <2850000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+		status = "okay";
+		pm8916_l9: regulator-l9 {
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <3300000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		status = "okay";
+		pm8916_l10: regulator-l10 {
+			regulator-min-microvolt = <2700000>;
+			regulator-max-microvolt = <2800000>;
+			qcom,init-voltage = <2700000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa11 {
+		status = "okay";
+		pm8916_l11: regulator-l11 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+		status = "okay";
+		pm8916_l12: regulator-l12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa13 {
+		status = "okay";
+		pm8916_l13: regulator-l13 {
+			regulator-min-microvolt = <3075000>;
+			regulator-max-microvolt = <3075000>;
+			qcom,init-voltage = <3075000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		status = "okay";
+		pm8916_l14: regulator-l14 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+		status = "okay";
+		pm8916_l15: regulator-l15 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa16 {
+		status = "okay";
+		pm8916_l16: regulator-l16 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		status = "okay";
+		pm8916_l17: regulator-l17 {
+			regulator-min-microvolt = <2850000>;
+			regulator-max-microvolt = <2850000>;
+			qcom,init-voltage = <2850000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa18 {
+		status = "okay";
+		pm8916_l18: regulator-l18 {
+			regulator-min-microvolt = <2700000>;
+			regulator-max-microvolt = <2700000>;
+			qcom,init-voltage = <2700000>;
+			status = "okay";
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-gpu.dtsi b/arch/arm64/boot/dts/qcom/msm8917-gpu.dtsi
new file mode 100644
index 0000000..3b12ba4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-gpu.dtsi
@@ -0,0 +1,184 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	msm_bus: qcom,kgsl-busmon {
+		label = "kgsl-busmon";
+		compatible = "qcom,kgsl-busmon";
+	};
+
+	/* Bus governor */
+	gpubw: qcom,gpubw {
+		compatible = "qcom,devbw";
+		governor = "bw_vbif";
+		qcom,src-dst-ports = <26 512>;
+		/*
+		 * Need to configure 2x Clock as BIMC
+		 * Internally Divides by 2 for Gen1 DDR PHY.
+		 */
+		qcom,active-only;
+		qcom,bw-tbl =
+			< 0 >,    /* Off */
+			< 769 >,  /* 1. DDR:100.80 MHz BIMC: 201.60 MHz */
+			< 1611 >, /* 2. DDR:211.20 MHz BIMC: 422.40 MHz */
+			< 2270 >, /* 3. DDR:297.60 MHz BIMC: 595.20 MHz */
+			< 2929 >, /* 4. DDR:384.00 MHz BIMC: 768.00 MHz */
+			< 4248 >, /* 5. DDR:556.80 MHz BIMC: 1113.60 MHz */
+			< 4541 >, /* 6. DDR:595.20 MHz BIMC: 1190.40 MHz */
+			< 5126 >, /* 7. DDR:672.00 MHz BIMC: 1344.00 MHz */
+			< 5639 >; /* 8. DDR:739.20 MHz BIMC: 1478.40 MHz */
+	};
+
+	msm_gpu: qcom,kgsl-3d0@1c00000 {
+		label = "kgsl-3d0";
+		compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
+		reg = <0x1c00000 0x10000
+		       0x1c10000 0x10000
+		       0x00a0000 0x06fff>;
+		reg-names = "kgsl_3d0_reg_memory" , "kgsl_3d0_shader_memory",
+				"qfprom_memory";
+		interrupts = <0 33 0>;
+		interrupt-names = "kgsl_3d0_irq";
+		qcom,id = <0>;
+
+		qcom,chipid = <0x03000620>;
+
+		qcom,initial-pwrlevel = <3>;
+
+		qcom,idle-timeout = <80>; //msecs
+		qcom,strtstp-sleepwake;
+		qcom,gpu-bimc-interface-clk-freq = <400000000>; //In Hz
+
+		clocks = <&clock_gcc clk_gcc_oxili_gfx3d_clk>,
+			<&clock_gcc clk_gcc_oxili_ahb_clk>,
+			<&clock_gcc clk_gcc_bimc_gfx_clk>,
+			<&clock_gcc clk_gcc_bimc_gpu_clk>,
+			<&clock_gcc clk_gcc_gtcu_ahb_clk>,
+			<&clock_gcc clk_gcc_gfx_tcu_clk>,
+			<&clock_gcc clk_gcc_gfx_tbu_clk>,
+			<&clock_gcc clk_bimc_gpu_clk>;
+
+		clock-names = "core_clk", "iface_clk", "mem_iface_clk",
+				"alt_mem_iface_clk", "gtcu_iface_clk",
+				"gtcu_clk", "gtbu_clk", "bimc_gpu_clk";
+
+		/* Bus Scale Settings */
+		qcom,gpubw-dev = <&gpubw>;
+		qcom,bus-control;
+		qcom,bus-width = <16>;
+		qcom,msm-bus,name = "grp3d";
+		qcom,msm-bus,num-cases = <9>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<26 512 0 0>,       /*    off        */
+				<26 512 0 806400>,  /* 1. 100.80 MHz */
+				<26 512 0 1689600>, /* 2. 211.20 MHz */
+				<26 512 0 2380800>, /* 3. 297.60 MHz */
+				<26 512 0 3072000>, /* 4. 384.00 MHz */
+				<26 512 0 4454400>, /* 5. 556.80 MHz */
+				<26 512 0 4761600>, /* 6. 595.20 MHz */
+				<26 512 0 5376000>, /* 7. 672.00 MHz */
+				<26 512 0 5913600>; /* 8. 739.20 MHz */
+
+		/* GDSC regulator names */
+		regulator-names = "vdd";
+		/* GDSC oxili regulators */
+		vdd-supply = <&gdsc_oxili_gx>;
+
+		/* CPU latency parameter */
+		qcom,pm-qos-active-latency = <651>;
+
+		/* Power levels */
+		qcom,gpu-pwrlevels {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			compatible = "qcom,gpu-pwrlevels";
+
+			/* TURBO */
+			qcom,gpu-pwrlevel@0 {
+				reg = <0>;
+				qcom,gpu-freq = <598000000>;
+				qcom,bus-freq = <7>;
+				qcom,bus-min = <7>;
+				qcom,bus-max = <7>;
+			};
+
+			/* NOM+ */
+			qcom,gpu-pwrlevel@1 {
+				reg = <1>;
+				qcom,gpu-freq = <523200000>;
+				qcom,bus-freq = <6>;
+				qcom,bus-min = <5>;
+				qcom,bus-max = <7>;
+			};
+
+			/* NOM */
+			qcom,gpu-pwrlevel@2 {
+				reg = <2>;
+				qcom,gpu-freq = <484800000>;
+				qcom,bus-freq = <5>;
+				qcom,bus-min = <4>;
+				qcom,bus-max = <6>;
+			};
+
+			/* SVS+ */
+			qcom,gpu-pwrlevel@3 {
+				reg = <3>;
+				qcom,gpu-freq = <400000000>;
+				qcom,bus-freq = <4>;
+				qcom,bus-min = <3>;
+				qcom,bus-max = <5>;
+			};
+
+			/* SVS */
+			qcom,gpu-pwrlevel@4 {
+				reg = <4>;
+				qcom,gpu-freq = <270000000>;
+				qcom,bus-freq = <3>;
+				qcom,bus-min = <1>;
+				qcom,bus-max = <3>;
+			};
+
+			/* XO */
+			qcom,gpu-pwrlevel@5 {
+				reg = <5>;
+				qcom,gpu-freq = <19200000>;
+				qcom,bus-freq = <0>;
+				qcom,bus-min = <0>;
+				qcom,bus-max = <0>;
+		};
+	};
+};
+
+	kgsl_msm_iommu: qcom,kgsl-iommu@1f00000 {
+		compatible = "qcom,kgsl-smmu-v2";
+		reg = <0x1f00000 0x10000>;
+		/*
+		 * The gpu can only program a single context bank
+		 * at this fixed offset.
+		 */
+		qcom,protect = <0xa000 0x1000>;
+		clocks = <&clock_gcc clk_gcc_smmu_cfg_clk>,
+			<&clock_gcc clk_gcc_gfx_tcu_clk>,
+			<&clock_gcc clk_gcc_gtcu_ahb_clk>,
+			<&clock_gcc clk_gcc_gfx_tbu_clk>;
+		clock-names = "scfg_clk", "gtcu_clk", "gtcu_iface_clk",
+				"gtbu_clk";
+		qcom,retention;
+		gfx3d_user: gfx3d_user {
+			compatible = "qcom,smmu-kgsl-cb";
+			iommus = <&gfx_iommu 0>;
+			qcom,gpu-offset = <0xa000>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-mdss-pll.dtsi b/arch/arm64/boot/dts/qcom/msm8917-mdss-pll.dtsi
new file mode 100644
index 0000000..c099044
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-mdss-pll.dtsi
@@ -0,0 +1,18 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm8937-mdss-pll.dtsi"
+
+&mdss_dsi0_pll {
+	vddio-supply = <&pm8937_l6>;
+};
+/delete-node/ &mdss_dsi1_pll;
diff --git a/arch/arm64/boot/dts/qcom/msm8917-mdss.dtsi b/arch/arm64/boot/dts/qcom/msm8917-mdss.dtsi
new file mode 100644
index 0000000..010b1e9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-mdss.dtsi
@@ -0,0 +1,96 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm8937-mdss.dtsi"
+
+&mdss_dsi {
+	vdda-supply = <&pm8937_l2>;
+	vddio-supply = <&pm8937_l6>;
+
+	ranges = <0x1a94000 0x1a94000 0x300
+		0x1a94400 0x1a94400 0x280
+		0x1a94b80 0x1a94b80 0x30
+		0x193e000 0x193e000 0x30>;
+
+	clocks = <&clock_gcc_mdss clk_mdss_mdp_vote_clk>,
+		<&clock_gcc clk_gcc_mdss_ahb_clk>,
+		<&clock_gcc clk_gcc_mdss_axi_clk>,
+		<&clock_gcc_mdss clk_ext_byte0_clk_src>,
+		<&clock_gcc_mdss clk_ext_pclk0_clk_src>;
+	clock-names = "mdp_core_clk", "iface_clk", "bus_clk",
+		"ext_byte0_clk", "ext_pixel0_clk";
+
+	/delete-property/ qcom,mdss-fb-map-sec;
+
+};
+
+&mdss_dsi0 {
+	vdd-supply = <&pm8937_l17>;
+	vddio-supply = <&pm8937_l6>;
+};
+
+/delete-node/ &mdss_dsi1;
+
+&mdss_mdp {
+	qcom,max-bandwidth-low-kbps = <1800000>;
+	qcom,max-bandwidth-high-kbps = <1800000>;
+	qcom,max-bandwidth-per-pipe-kbps = <1000000>;
+
+	qcom,mdss-intf-off = <0x00000000 0x0006B800>;
+	qcom,mdss-pingpong-off = <0x00071000>;
+	qcom,mdss-mixer-intf-off = <0x00045000>;
+	qcom,mdss-mixer-wb-off = <0x00046000>;
+	qcom,mdss-wfd-mode = "dedicated";
+	qcom,mdss-per-pipe-panic-luts = <0x000f>,
+					<0x0>,
+					<0xfffc>,
+					<0x0>;
+
+	/delete-property/ qcom,mdss-highest-bank-bit;
+	/delete-property/ qcom,vbif-settings;
+
+	qcom,regs-dump-mdp = <0x01000 0x01454>,
+			     <0x02000 0x02064>,
+			     <0x02200 0x02264>,
+			     <0x02400 0x02464>,
+			     <0x05000 0x05150>,
+			     <0x05200 0x05230>,
+			     <0x15000 0x15150>,
+			     <0x17000 0x17150>,
+			     <0x25000 0x25150>,
+			     <0x35000 0x35150>,
+			     <0x45000 0x452bc>,
+			     <0x46000 0x462bc>,
+			     <0x55000 0x5522c>,
+			     <0x65000 0x652c0>,
+			     <0x66000 0x662c0>,
+			     <0x6b800 0x6ba68>,
+			     <0x71000 0x710d4>;
+
+	qcom,regs-dump-names-mdp = "MDP",
+		"CTL_0",    "CTL_1", "CTL_2",
+		"VIG0_SSPP", "VIG0",
+		"RGB0_SSPP", "RGB1_SSPP",
+		"DMA0_SSPP",
+		"CURSOR0_SSPP",
+		"LAYER_0", "LAYER_1",
+		"DSPP_0",
+		"WB_0",    "WB_2",
+		"INTF_1",
+		"PP_0";
+};
+
+&mdss_rotator {
+	/delete-property/ qcom,mdss-has-ubwc;
+};
+
+/delete-node/ &mdss_fb2;
diff --git a/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
index a558c8e..800ea1c 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
@@ -11,6 +11,8 @@
  * GNU General Public License for more details.
  */
 
+#include "msm8917-pinctrl.dtsi"
+
 &blsp1_uart2 {
 	status = "ok";
 	pinctrl-names = "default";
@@ -65,3 +67,36 @@
 
 	status = "ok";
 };
+
+#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>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi
index a194cea..4da1384 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi
@@ -74,3 +74,8 @@
 &ibb_regulator {
 	qcom,qpnp-ibb-discharge-resistor = <32>;
 };
+
+&mdss_dsi0 {
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-thermal.dtsi b/arch/arm64/boot/dts/qcom/msm8917-thermal.dtsi
new file mode 100644
index 0000000..98ad44c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-thermal.dtsi
@@ -0,0 +1,155 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+&thermal_zones {
+	aoss0-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "user_space";
+		thermal-sensors = <&tsens0 0>;
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	mdm-core-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "user_space";
+		thermal-sensors = <&tsens0 1>;
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	mdss-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "user_space";
+		thermal-sensors = <&tsens0 2>;
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	camera-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "user_space";
+		thermal-sensors = <&tsens0 3>;
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	cpuss-0-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 4>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	apc1-cpu1-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 5>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	apc1-cpu2-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 6>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	apc1-cpu3-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 7>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	apc1-cpu4-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 8>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	gpu0-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 9>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917.dtsi b/arch/arm64/boot/dts/qcom/msm8917.dtsi
index 6f0da53..9b91fe9 100644
--- a/arch/arm64/boot/dts/qcom/msm8917.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917.dtsi
@@ -162,6 +162,10 @@
 #include "msm8917-ion.dtsi"
 #include "msm8917-smp2p.dtsi"
 #include "msm8917-bus.dtsi"
+#include "msm8917-mdss.dtsi"
+#include "msm8917-mdss-pll.dtsi"
+#include "msm-arm-smmu-8917.dtsi"
+#include "msm8917-gpu.dtsi"
 
 &soc {
 	#address-cells = <1>;
@@ -211,6 +215,20 @@
 		qcom,pipe-attr-ee;
 	};
 
+	thermal_zones: thermal-zones {};
+
+	tsens0: tsens@4a8000 {
+		compatible = "qcom,msm8937-tsens";
+		reg = <0x4a8000 0x1000>,
+			<0x4a9000 0x1000>,
+			<0xa4000  0x1000>;
+		reg-names = "tsens_srot_physical",
+				"tsens_tm_physical", "tsens_eeprom_physical";
+		interrupts = <0 184 0>;
+		interrupt-names = "tsens-upper-lower";
+		#thermal-sensor-cells = <1>;
+	};
+
 	timer@b120000 {
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -427,6 +445,14 @@
 		#clock-cells = <1>;
 	};
 
+	clock_gcc_mdss: qcom,gcc-mdss@1800000 {
+		compatible = "qcom,gcc-mdss-8917";
+		clocks = <&mdss_dsi0_pll clk_dsi_pll0_pixel_clk_src>,
+		<&mdss_dsi0_pll clk_dsi_pll0_byte_clk_src>;
+		clock-names = "pclk0_src", "byte0_src";
+		#clock-cells = <1>;
+	};
+
 	clock_cpu: qcom,cpu-clock-8939@b111050 {
 		compatible = "qcom,cpu-clock-8917";
 		reg = <0xb011050 0x8>,
@@ -1191,6 +1217,16 @@
 		memory-region = <&adsp_mem>;
 	};
 
+	qcom,msm_fastrpc {
+		compatible = "qcom,msm-fastrpc-legacy-compute";
+		qcom,msm_fastrpc_compute_cb {
+			compatible = "qcom,msm-fastrpc-legacy-compute-cb";
+			label = "adsprpc-smd";
+			iommus = <&apps_iommu 0x2008 0x7>;
+			sids = <0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf>;
+		};
+	};
+
 	spi_6: spi@7af6000 { /* BLSP2 QUP2 */
 		compatible = "qcom,spi-qup-v2";
 		#address-cells = <1>;
@@ -1223,6 +1259,7 @@
 #include "msm8917-regulator.dtsi"
 #include "pm8937.dtsi"
 #include "msm-gdsc-8916.dtsi"
+#include "msm8917-thermal.dtsi"
 
 &gdsc_venus {
 	clock-names = "bus_clk", "core_clk";
diff --git a/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8937-camera-sensor-mtp.dtsi
similarity index 67%
copy from arch/arm64/boot/dts/qcom/sdm632-camera-sensor-mtp.dtsi
copy to arch/arm64/boot/dts/qcom/msm8937-camera-sensor-mtp.dtsi
index 07b3811..d134dd1 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-camera-sensor-mtp.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -17,7 +17,7 @@
 		reg = <0x0>;
 		compatible = "qcom,actuator";
 		qcom,cci-master = <0>;
-		cam_vaf-supply = <&pm8953_l17>;
+		cam_vaf-supply = <&pm8937_l17>;
 		qcom,cam-vreg-name = "cam_vaf";
 		qcom,cam-vreg-min-voltage = <2850000>;
 		qcom,cam-vreg-max-voltage = <2850000>;
@@ -28,8 +28,8 @@
 		cell-index = <1>;
 		reg = <0x1>;
 		compatible = "qcom,actuator";
-		qcom,cci-master = <1>;
-		cam_vaf-supply = <&pm8953_l17>;
+		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>;
@@ -41,32 +41,35 @@
 		compatible = "qcom,eeprom";
 		qcom,cci-master = <0>;
 		reg = <0x0>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vdig-supply = <&pm8953_l23>;
-		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-op-mode = <0 105000 100000>;
+		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_vana>;
-		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
-				&cam_sensor_rear_vana_sleep>;
+				&cam_sensor_rear_reset
+				&cam_sensor_rear_standby
+				&cam_sensor_rear_vdig>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep
+				&cam_sensor_rear_reset_sleep
+				&cam_sensor_rear_standby_sleep
+				&cam_sensor_rear_vdig_sleep>;
 		gpios = <&tlmm 26 0>,
-			<&tlmm 40 0>,
-			<&tlmm 39 0>,
-			<&tlmm 134 0>;
+			<&tlmm 36 0>,
+			<&tlmm 35 0>,
+			<&tlmm 62 0>;
 		qcom,gpio-reset = <1>;
 		qcom,gpio-standby = <2>;
-		qcom,gpio-vana = <3>;
+		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_VANA";
+			"CAM_VDIG";
 		status = "ok";
 		clocks = <&clock_gcc clk_mclk0_clk_src>,
 				<&clock_gcc clk_gcc_camss_mclk0_clk>;
@@ -115,10 +118,10 @@
 		qcom,poll7 = <0 0x0 2 0x0 1 1>;
 		qcom,mem7 = <1536 0x7010 2 0 1 0>;
 
-		cam_vdig-supply = <&pm8953_l23>;
-		cam_vana-supply = <&pm8953_l22>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vaf-supply = <&pm8953_l17>;
+		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>;
@@ -126,12 +129,12 @@
 		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk1_default
+		pinctrl-0 = <&cam_sensor_mclk2_default
 			&cam_sensor_front1_default>;
-		pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>;
-		gpios = <&tlmm 27 0>,
-			<&tlmm 129 0>,
-			<&tlmm 130 0>;
+		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>;
@@ -148,44 +151,8 @@
 		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_mclk1_clk_src>,
-			<&clock_gcc clk_gcc_camss_mclk1_clk>;
-		clock-names = "cam_src_clk", "cam_clk";
-		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_l23>;
-		cam_vana-supply = <&pm8953_l22>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
-					"cam_vaf";
-		qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
-		qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
-		qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
-		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk2_default
-				&cam_sensor_front_default>;
-		pinctrl-1 = <&cam_sensor_mclk2_sleep
-				&cam_sensor_front_sleep>;
-		gpios = <&tlmm 28 0>,
-			<&tlmm 131 0>,
-			<&tlmm 132 0>;
-		qcom,gpio-reset = <1>;
-		qcom,gpio-standby = <2>;
-		qcom,gpio-req-tbl-num = <0 1 2>;
-		qcom,gpio-req-tbl-flags = <1 0 0>;
-		qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
-			"CAM_RESET1",
-			"CAM_STANDBY1";
-		status = "ok";
 		clocks = <&clock_gcc clk_mclk2_clk_src>,
-				<&clock_gcc clk_gcc_camss_mclk2_clk>;
+			<&clock_gcc clk_gcc_camss_mclk2_clk>;
 		clock-names = "cam_src_clk", "cam_clk";
 		qcom,clock-rates = <19200000 0>;
 	};
@@ -200,34 +167,35 @@
 		qcom,led-flash-src = <&led_flash0>;
 		qcom,eeprom-src = <&eeprom0>;
 		qcom,actuator-src = <&actuator0>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vdig-supply = <&pm8953_l23>;
-		cam_vaf-supply = <&pm8953_l17>;
-		cam_vana-supply = <&pm8953_l22>;
-		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf",
-						"cam_vana";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000 2800000>;
-		qcom,cam-vreg-op-mode = <0 105000 100000 80000>;
+		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_vana>;
-		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
-				&cam_sensor_rear_vana_sleep>;
+				&cam_sensor_rear_reset
+				&cam_sensor_rear_standby
+				&cam_sensor_rear_vdig>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep
+				&cam_sensor_rear_reset_sleep
+				&cam_sensor_rear_standby_sleep
+				&cam_sensor_rear_vdig_sleep>;
 		gpios = <&tlmm 26 0>,
-			<&tlmm 40 0>,
-			<&tlmm 39 0>,
-			<&tlmm 134 0>;
+			<&tlmm 36 0>,
+			<&tlmm 35 0>,
+			<&tlmm 62 0>;
 		qcom,gpio-reset = <1>;
 		qcom,gpio-standby = <2>;
-		qcom,gpio-vana = <3>;
+		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_VANA";
+			"CAM_VDIG";
 		qcom,sensor-position = <0>;
 		qcom,sensor-mode = <0>;
 		qcom,cci-master = <0>;
@@ -245,25 +213,23 @@
 		qcom,csiphy-sd-index = <1>;
 		qcom,csid-sd-index = <1>;
 		qcom,mount-angle = <90>;
-		qcom,eeprom-src = <&eeprom2>;
-		qcom,actuator-src = <&actuator1>;
-		cam_vdig-supply = <&pm8953_l23>;
-		cam_vana-supply = <&pm8953_l22>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vaf-supply = <&pm8953_l17>;
+		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_mclk2_default
+		pinctrl-0 = <&cam_sensor_mclk1_default
 				&cam_sensor_front_default>;
-		pinctrl-1 = <&cam_sensor_mclk2_sleep
+		pinctrl-1 = <&cam_sensor_mclk1_sleep
 				&cam_sensor_front_sleep>;
-		gpios = <&tlmm 28 0>,
-			<&tlmm 131 0>,
-			<&tlmm 132 0>;
+		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>;
@@ -274,9 +240,8 @@
 		qcom,sensor-position = <0x100>;
 		qcom,sensor-mode = <1>;
 		qcom,cci-master = <1>;
-		status = "ok";
-		clocks = <&clock_gcc clk_mclk2_clk_src>,
-				<&clock_gcc clk_gcc_camss_mclk2_clk>;
+		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>;
 	};
@@ -285,29 +250,29 @@
 		cell-index = <2>;
 		compatible = "qcom,camera";
 		reg = <0x02>;
-		qcom,csiphy-sd-index = <2>;
-		qcom,csid-sd-index = <2>;
+		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 = <&pm8953_l23>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vana-supply = <&pm8953_l22>;
-		cam_vaf-supply = <&pm8953_l17>;
+		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 = <1175000 0 2800000 2850000>;
-		qcom,cam-vreg-max-voltage = <1175000 0 2800000 2850000>;
+		qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
 		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk1_default
+		pinctrl-0 = <&cam_sensor_mclk2_default
 				&cam_sensor_front1_default>;
-		pinctrl-1 = <&cam_sensor_mclk1_sleep
+		pinctrl-1 = <&cam_sensor_mclk2_sleep
 				&cam_sensor_front1_sleep>;
-		gpios = <&tlmm 27 0>,
-			<&tlmm 129 0>,
-			<&tlmm 130 0>;
+		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>;
@@ -317,10 +282,10 @@
 					  "CAM_STANDBY2";
 		qcom,sensor-position = <1>;
 		qcom,sensor-mode = <0>;
-		qcom,cci-master = <1>;
+		qcom,cci-master = <0>;
 		status = "ok";
-		clocks = <&clock_gcc clk_mclk1_clk_src>,
-			<&clock_gcc clk_gcc_camss_mclk1_clk>;
+		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/msm8937-camera.dtsi b/arch/arm64/boot/dts/qcom/msm8937-camera.dtsi
new file mode 100644
index 0000000..b5f467e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-camera.dtsi
@@ -0,0 +1,536 @@
+/*
+ * 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.
+ */
+
+&soc {
+	qcom,msm-cam@1b00000 {
+		compatible = "qcom,msm-cam";
+		reg = <0x1b00000 0x40000>;
+		reg-names = "msm-cam";
+		status = "ok";
+		bus-vectors = "suspend", "svs", "nominal", "turbo";
+		qcom,bus-votes = <0 160000000 320000000 320000000>;
+	};
+
+	qcom,csiphy@1b34000 {
+		status = "ok";
+		cell-index = <0>;
+		compatible = "qcom,csiphy-v3.4.2", "qcom,csiphy";
+		reg = <0x1b34000 0x1000>,
+			<0x1b00030 0x4>;
+		reg-names = "csiphy", "csiphy_clk_mux";
+		interrupts = <0 78 0>;
+		interrupt-names = "csiphy";
+		clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+			<&clock_gcc clk_csi0phytimer_clk_src>,
+			<&clock_gcc clk_gcc_camss_csi0phytimer_clk>,
+			<&clock_gcc clk_camss_top_ahb_clk_src>,
+			<&clock_gcc clk_gcc_camss_ahb_clk>;
+		clock-names = "camss_top_ahb_clk", "ispif_ahb_clk",
+			"csiphy_timer_src_clk", "csiphy_timer_clk",
+			"camss_ahb_src", "camss_ahb_clk";
+		qcom,clock-rates = <0 61540000 200000000 0 0 0>;
+	};
+
+	qcom,csiphy@1b35000 {
+		status = "ok";
+		cell-index = <1>;
+		compatible = "qcom,csiphy-v3.4.2", "qcom,csiphy";
+		reg = <0x1b35000 0x1000>,
+			<0x1b00038 0x4>;
+		reg-names = "csiphy", "csiphy_clk_mux";
+		interrupts = <0 79 0>;
+		interrupt-names = "csiphy";
+		clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+			<&clock_gcc clk_csi1phytimer_clk_src>,
+			<&clock_gcc clk_gcc_camss_csi1phytimer_clk>,
+			<&clock_gcc clk_camss_top_ahb_clk_src>,
+			<&clock_gcc clk_gcc_camss_ahb_clk>;
+		clock-names = "camss_top_ahb_clk", "ispif_ahb_clk",
+			"csiphy_timer_src_clk", "csiphy_timer_clk",
+			"camss_ahb_src", "camss_ahb_clk";
+		qcom,clock-rates = <0 61540000 200000000 0 0 0>;
+	};
+
+	qcom,csid@1b30000  {
+		status = "ok";
+		cell-index = <0>;
+		compatible = "qcom,csid-v3.4.2", "qcom,csid";
+		reg = <0x1b30000 0x400>;
+		reg-names = "csid";
+		interrupts = <0 51 0>;
+		interrupt-names = "csid";
+		qcom,csi-vdd-voltage = <1200000>;
+		qcom,mipi-csi-vdd-supply = <&pm8937_l2>;
+		clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_csi0_ahb_clk>,
+			<&clock_gcc clk_csi0_clk_src>,
+			<&clock_gcc clk_gcc_camss_csi0phy_clk>,
+			<&clock_gcc clk_gcc_camss_csi0_clk>,
+			<&clock_gcc clk_gcc_camss_csi0pix_clk>,
+			<&clock_gcc clk_gcc_camss_csi0rdi_clk>,
+			<&clock_gcc clk_gcc_camss_ahb_clk>;
+		clock-names = "camss_top_ahb_clk",
+			"ispif_ahb_clk", "csi_ahb_clk", "csi_src_clk",
+			"csi0_phy_clk",
+			"csi_clk",  "csi_pix_clk",
+			"csi_rdi_clk", "camss_ahb_clk";
+		qcom,clock-rates = <0 61540000 0 200000000 0 0 0 0 0>;
+	};
+
+	qcom,csid@1b30400 {
+		status = "ok";
+		cell-index = <1>;
+		compatible = "qcom,csid-v3.4.2", "qcom,csid";
+		reg = <0x1b30400 0x400>;
+		reg-names = "csid";
+		interrupts = <0 52 0>;
+		interrupt-names = "csid";
+		qcom,csi-vdd-voltage = <1200000>;
+		qcom,mipi-csi-vdd-supply = <&pm8937_l2>;
+		clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_csi1_ahb_clk>,
+			<&clock_gcc clk_csi1_clk_src>,
+			<&clock_gcc clk_gcc_camss_csi1phy_clk>,
+			<&clock_gcc clk_gcc_camss_csi1_clk>,
+			<&clock_gcc clk_gcc_camss_csi1pix_clk>,
+			<&clock_gcc clk_gcc_camss_csi1rdi_clk>,
+			<&clock_gcc clk_gcc_camss_ahb_clk>;
+		clock-names = "camss_top_ahb_clk",
+			"ispif_ahb_clk", "csi_ahb_clk", "csi_src_clk",
+			"csi1_phy_clk",
+			"csi_clk", "csi_pix_clk",
+			"csi_rdi_clk", "camss_ahb_clk";
+		qcom,clock-rates = <0 61540000 0 200000000 0 0 0 0 0>;
+	};
+
+	qcom,csid@1b30800 {
+		status = "ok";
+		cell-index = <2>;
+		compatible = "qcom,csid-v3.4.2", "qcom,csid";
+		reg = <0x1b30800 0x400>;
+		reg-names = "csid";
+		interrupts = <0 153 0>;
+		interrupt-names = "csid";
+		qcom,csi-vdd-voltage = <1200000>;
+		qcom,mipi-csi-vdd-supply = <&pm8937_l2>;
+		clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_csi2_ahb_clk>,
+			<&clock_gcc clk_csi2_clk_src>,
+			<&clock_gcc clk_gcc_camss_csi2phy_clk>,
+			<&clock_gcc clk_gcc_camss_csi2_clk>,
+			<&clock_gcc clk_gcc_camss_csi2pix_clk>,
+			<&clock_gcc clk_gcc_camss_csi2rdi_clk>,
+			<&clock_gcc clk_gcc_camss_ahb_clk>;
+		clock-names = "camss_top_ahb_clk",
+			"ispif_ahb_clk", "csi_ahb_clk", "csi_src_clk",
+			"csi2_phy_clk",
+			"csi_clk", "csi_pix_clk",
+			"csi_rdi_clk", "camss_ahb_clk";
+		qcom,clock-rates = <0 61540000 0 200000000 0 0 0 0 0>;
+	};
+
+	qcom,ispif@1b31000 {
+		cell-index = <0>;
+		compatible = "qcom,ispif-v3.0", "qcom,ispif";
+		reg = <0x1b31000 0x500>,
+			<0x1b00020 0x10>;
+		reg-names = "ispif", "csi_clk_mux";
+		interrupts = <0 55 0>;
+		interrupt-names = "ispif";
+		qcom,num-isps = <0x2>;
+		vfe0-vdd-supply = <&gdsc_vfe>;
+		vfe1-vdd-supply = <&gdsc_vfe1>;
+		qcom,vdd-names = "vfe0-vdd", "vfe1-vdd";
+		clocks = <&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_top_ahb_clk>,
+			<&clock_gcc clk_camss_top_ahb_clk_src>,
+			<&clock_gcc clk_csi0_clk_src>,
+			<&clock_gcc clk_gcc_camss_csi0_clk>,
+			<&clock_gcc clk_gcc_camss_csi0rdi_clk>,
+			<&clock_gcc clk_gcc_camss_csi0pix_clk>,
+			<&clock_gcc clk_csi1_clk_src>,
+			<&clock_gcc clk_gcc_camss_csi1_clk>,
+			<&clock_gcc clk_gcc_camss_csi1rdi_clk>,
+			<&clock_gcc clk_gcc_camss_csi1pix_clk>,
+			<&clock_gcc clk_csi2_clk_src>,
+			<&clock_gcc clk_gcc_camss_csi2_clk>,
+			<&clock_gcc clk_gcc_camss_csi2rdi_clk>,
+			<&clock_gcc clk_gcc_camss_csi2pix_clk>,
+			<&clock_gcc clk_vfe0_clk_src>,
+			<&clock_gcc clk_gcc_camss_vfe0_clk>,
+			<&clock_gcc clk_gcc_camss_csi_vfe0_clk>,
+			<&clock_gcc clk_vfe1_clk_src>,
+			<&clock_gcc clk_gcc_camss_vfe1_clk>,
+			<&clock_gcc clk_gcc_camss_csi_vfe1_clk>;
+		clock-names = "ispif_ahb_clk",
+			"camss_ahb_clk", "camss_top_ahb_clk",
+			"camss_ahb_src",
+			"csi0_src_clk", "csi0_clk",
+			"csi0_rdi_clk", "csi0_pix_clk",
+			"csi1_src_clk", "csi1_clk",
+			"csi1_rdi_clk", "csi1_pix_clk",
+			"csi2_src_clk", "csi2_clk",
+			"csi2_rdi_clk", "csi2_pix_clk",
+			"vfe0_clk_src", "camss_vfe_vfe0_clk",
+			"camss_csi_vfe0_clk", "vfe1_clk_src",
+			"camss_vfe_vfe1_clk", "camss_csi_vfe1_clk";
+		qcom,clock-rates = <61540000 0 0 0
+			200000000 0 0 0
+			200000000 0 0 0
+			200000000 0 0 0
+			0 0 0
+			0 0 0>;
+		qcom,clock-cntl-support;
+		qcom,clock-control = "SET_RATE","NO_SET_RATE", "NO_SET_RATE",
+			"NO_SET_RATE", "SET_RATE", "NO_SET_RATE",
+			"NO_SET_RATE", "NO_SET_RATE", "SET_RATE",
+			"NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+			"SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+			"NO_SET_RATE", "INIT_RATE", "NO_SET_RATE",
+			"NO_SET_RATE", "INIT_RATE", "NO_SET_RATE",
+			"NO_SET_RATE";
+	};
+
+	vfe0: qcom,vfe0@1b10000 {
+		cell-index = <0>;
+		compatible = "qcom,vfe40";
+		reg = <0x1b10000 0x1000>,
+			<0x1b40000 0x200>;
+		reg-names = "vfe", "vfe_vbif";
+		interrupts = <0 57 0>;
+		interrupt-names = "vfe";
+		vdd-supply = <&gdsc_vfe>;
+		clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_ahb_clk>,
+			<&clock_gcc clk_vfe0_clk_src>,
+			<&clock_gcc clk_gcc_camss_vfe0_clk>,
+			<&clock_gcc clk_gcc_camss_csi_vfe0_clk>,
+			<&clock_gcc clk_gcc_camss_vfe_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_vfe_axi_clk>,
+			<&clock_gcc clk_gcc_camss_ispif_ahb_clk>;
+		clock-names = "camss_top_ahb_clk", "camss_ahb_clk",
+			"vfe_clk_src", "camss_vfe_vfe_clk",
+			"camss_csi_vfe_clk", "iface_clk",
+			"bus_clk", "iface_ahb_clk";
+		qcom,clock-rates = <0 0 266670000 0 0 0 0 0>;
+		qos-entries = <8>;
+		qos-regs = <0x2c4 0x2c8 0x2cc 0x2d0 0x2d4 0x2d8
+			0x2dc 0x2e0>;
+		qos-settings = <0xaa55aa55
+			0xaa55aa55 0xaa55aa55
+			0xaa55aa55 0xaa55aa55
+			0xaa55aa55 0xaa55aa55
+			0xaa55aa55>;
+		vbif-entries = <1>;
+		vbif-regs = <0x124>;
+		vbif-settings = <0x3>;
+		ds-entries = <17>;
+		ds-regs = <0x988 0x98c 0x990 0x994 0x998
+			0x99c 0x9a0 0x9a4 0x9a8 0x9ac 0x9b0
+			0x9b4 0x9b8 0x9bc 0x9c0 0x9c4 0x9c8>;
+		ds-settings = <0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0x00000110>;
+		max-clk-nominal = <400000000>;
+		max-clk-turbo = <432000000>;
+	};
+
+	vfe1: qcom,vfe1@1b14000 {
+		cell-index = <1>;
+		compatible = "qcom,vfe40";
+		reg = <0x1b14000 0x1000>,
+			<0x1ba0000 0x200>;
+		reg-names = "vfe", "vfe_vbif";
+		interrupts = <0 29 0>;
+		interrupt-names = "vfe";
+		vdd-supply = <&gdsc_vfe1>;
+		clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_ahb_clk>,
+			<&clock_gcc clk_vfe1_clk_src>,
+			<&clock_gcc clk_gcc_camss_vfe1_clk>,
+			<&clock_gcc clk_gcc_camss_csi_vfe1_clk>,
+			<&clock_gcc clk_gcc_camss_vfe1_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_vfe1_axi_clk>,
+			<&clock_gcc clk_gcc_camss_ispif_ahb_clk>;
+		clock-names = "camss_top_ahb_clk" , "camss_ahb_clk",
+			"vfe_clk_src", "camss_vfe_vfe_clk",
+			"camss_csi_vfe_clk", "iface_clk",
+			"bus_clk", "iface_ahb_clk";
+		qcom,clock-rates = <0 0 266670000 0 0 0 0 0>;
+		qos-entries = <8>;
+		qos-regs = <0x2c4 0x2c8 0x2cc 0x2d0 0x2d4 0x2d8
+			0x2dc 0x2e0>;
+		qos-settings = <0xaa55aa55
+			0xaa55aa55 0xaa55aa55
+			0xaa55aa55 0xaa55aa55
+			0xaa55aa55 0xaa55aa55
+			0xaa55aa55>;
+		vbif-entries = <1>;
+		vbif-regs = <0x124>;
+		vbif-settings = <0x3>;
+		ds-entries = <17>;
+		ds-regs = <0x988 0x98c 0x990 0x994 0x998
+			0x99c 0x9a0 0x9a4 0x9a8 0x9ac 0x9b0
+			0x9b4 0x9b8 0x9bc 0x9c0 0x9c4 0x9c8>;
+		ds-settings = <0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0xcccc1111
+			0xcccc1111 0x00000110>;
+		max-clk-nominal = <400000000>;
+		max-clk-turbo = <432000000>;
+	};
+
+	qcom,vfe {
+		compatible = "qcom,vfe";
+		num_child = <2>;
+	};
+
+	qcom,cam_smmu {
+		status = "ok";
+		compatible = "qcom,msm-cam-smmu";
+		msm_cam_smmu_cb1: msm_cam_smmu_cb1 {
+			compatible = "qcom,msm-cam-smmu-cb";
+			iommus = <&apps_iommu 0x400 0x00>,
+				<&apps_iommu 0x2400 0x00>;
+			label = "vfe";
+			qcom,scratch-buf-support;
+		};
+
+		msm_cam_smmu_cb2: msm_cam_smmu_cb2 {
+			compatible = "qcom,msm-cam-smmu-cb";
+			label = "vfe_secure";
+			qcom,secure-context;
+		};
+
+		msm_cam_smmu_cb3: msm_cam_smmu_cb3 {
+			compatible = "qcom,msm-cam-smmu-cb";
+			iommus = <&apps_iommu 0x1c00 0x00>;
+			label = "cpp";
+		};
+
+		msm_cam_smmu_cb4: msm_cam_smmu_cb4 {
+			compatible = "qcom,msm-cam-smmu-cb";
+			iommus = <&apps_iommu 0x1800 0x00>;
+			label = "jpeg_enc0";
+		};
+	};
+
+	qcom,jpeg@1b1c000 {
+		status = "ok";
+		cell-index = <0>;
+		compatible = "qcom,jpeg";
+		reg = <0x1b1c000 0x400>,
+			<0x1b60000 0xc30>;
+		reg-names = "jpeg_hw", "jpeg_vbif";
+		interrupts = <0 59 0>;
+		interrupt-names = "jpeg";
+		vdd-supply = <&gdsc_jpeg>;
+		qcom,vdd-names = "vdd";
+		clock-names =  "core_clk", "iface_clk", "bus_clk0",
+			"camss_top_ahb_clk", "camss_ahb_clk";
+		clocks = <&clock_gcc clk_gcc_camss_jpeg0_clk>,
+			<&clock_gcc clk_gcc_camss_jpeg_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_jpeg_axi_clk>,
+			<&clock_gcc clk_gcc_camss_top_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_ahb_clk>;
+		qcom,clock-rates = <266670000 0 0 0 0>;
+		qcom,qos-reg-settings = <0x28 0x0000555e>,
+			<0xc8 0x00005555>;
+		qcom,vbif-reg-settings = <0xc0 0x10101000>,
+			<0xb0 0x10100010>;
+		qcom,msm-bus,name = "msm_camera_jpeg0";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <62 512 0 0>,
+			<62 512 800000 800000>;
+	};
+
+	qcom,irqrouter@1b00000 {
+		status = "ok";
+		cell-index = <0>;
+		compatible = "qcom,irqrouter";
+		reg = <0x1b00000 0x100>;
+		reg-names = "irqrouter";
+	};
+
+	qcom,cpp@1b04000 {
+		status = "ok";
+		cell-index = <0>;
+		compatible = "qcom,cpp";
+		reg = <0x1b04000 0x100>,
+			<0x1b80000 0x200>,
+			<0x1b18000 0x018>,
+			<0x1858078 0x4>;
+		reg-names = "cpp", "cpp_vbif", "cpp_hw", "camss_cpp";
+		interrupts = <0 49 0>;
+		interrupt-names = "cpp";
+		vdd-supply = <&gdsc_cpp>;
+		qcom,vdd-names = "vdd";
+		clocks = <&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+			<&clock_gcc clk_cpp_clk_src>,
+			<&clock_gcc clk_gcc_camss_top_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_cpp_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_cpp_axi_clk>,
+			<&clock_gcc clk_gcc_camss_cpp_clk>,
+			<&clock_gcc clk_gcc_camss_micro_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_ahb_clk>;
+		clock-names = "ispif_ahb_clk", "cpp_core_clk",
+			"camss_top_ahb_clk", "camss_vfe_cpp_ahb_clk",
+			"camss_vfe_cpp_axi_clk", "camss_vfe_cpp_clk",
+			"micro_iface_clk", "camss_ahb_clk";
+		qcom,clock-rates = <61540000 180000000 0 0 0 180000000 0 0>;
+		qcom,min-clock-rate = <133000000>;
+		resets = <&clock_gcc GCC_CAMSS_MICRO_BCR>;
+		reset-names = "micro_iface_reset";
+		qcom,bus-master = <1>;
+		qcom,msm-bus,name = "msm_camera_cpp";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<106 512 0 0>,
+			<106 512 0 0>;
+		qcom,msm-bus-vector-dyn-vote;
+		qcom,micro-reset;
+		qcom,cpp-fw-payload-info {
+			qcom,stripe-base = <156>;
+			qcom,plane-base = <141>;
+			qcom,stripe-size = <27>;
+			qcom,plane-size = <5>;
+			qcom,fe-ptr-off = <5>;
+			qcom,we-ptr-off = <11>;
+		};
+	};
+
+	cci: qcom,cci@1b0c000 {
+		status = "ok";
+		cell-index = <0>;
+		compatible = "qcom,cci";
+		reg = <0x1b0c000 0x4000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "cci";
+		interrupts = <0 50 0>;
+		interrupt-names = "cci";
+		clocks = <&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+			<&clock_gcc clk_cci_clk_src>,
+			<&clock_gcc clk_gcc_camss_cci_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_cci_clk>,
+			<&clock_gcc clk_gcc_camss_ahb_clk>,
+			<&clock_gcc clk_gcc_camss_top_ahb_clk>;
+		clock-names = "ispif_ahb_clk", "cci_src_clk",
+			"cci_ahb_clk", "camss_cci_clk",
+			"camss_ahb_clk", "camss_top_ahb_clk";
+		qcom,clock-rates = <61540000 19200000 0 0 0 0>,
+				<61540000 37500000 0 0 0 0>;
+		pinctrl-names = "cci_default", "cci_suspend";
+			pinctrl-0 = <&cci0_active &cci1_active>;
+			pinctrl-1 = <&cci0_suspend &cci1_suspend>;
+		gpios = <&tlmm 29 0>,
+			<&tlmm 30 0>,
+			<&tlmm 31 0>,
+			<&tlmm 32 0>;
+		qcom,gpio-tbl-num = <0 1 2 3>;
+		qcom,gpio-tbl-flags = <1 1 1 1>;
+		qcom,gpio-tbl-label = "CCI_I2C_DATA0",
+						"CCI_I2C_CLK0",
+						"CCI_I2C_DATA1",
+						"CCI_I2C_CLK1";
+		i2c_freq_100Khz: qcom,i2c_standard_mode {
+			status = "disabled";
+		};
+		i2c_freq_400Khz: qcom,i2c_fast_mode {
+			status = "disabled";
+		};
+		i2c_freq_custom: qcom,i2c_custom_mode {
+			status = "disabled";
+		};
+
+		i2c_freq_1Mhz: qcom,i2c_fast_plus_mode {
+			status = "disabled";
+		};
+
+	};
+};
+
+&i2c_freq_100Khz {
+	qcom,hw-thigh = <78>;
+	qcom,hw-tlow = <114>;
+	qcom,hw-tsu-sto = <28>;
+	qcom,hw-tsu-sta = <28>;
+	qcom,hw-thd-dat = <10>;
+	qcom,hw-thd-sta = <77>;
+	qcom,hw-tbuf = <118>;
+	qcom,hw-scl-stretch-en = <0>;
+	qcom,hw-trdhld = <6>;
+	qcom,hw-tsp = <1>;
+};
+
+&i2c_freq_400Khz {
+	qcom,hw-thigh = <20>;
+	qcom,hw-tlow = <28>;
+	qcom,hw-tsu-sto = <21>;
+	qcom,hw-tsu-sta = <21>;
+	qcom,hw-thd-dat = <13>;
+	qcom,hw-thd-sta = <18>;
+	qcom,hw-tbuf = <32>;
+	qcom,hw-scl-stretch-en = <0>;
+	qcom,hw-trdhld = <6>;
+	qcom,hw-tsp = <3>;
+	status = "ok";
+};
+
+&i2c_freq_custom {
+	qcom,hw-thigh = <15>;
+	qcom,hw-tlow = <28>;
+	qcom,hw-tsu-sto = <21>;
+	qcom,hw-tsu-sta = <21>;
+	qcom,hw-thd-dat = <13>;
+	qcom,hw-thd-sta = <18>;
+	qcom,hw-tbuf = <25>;
+	qcom,hw-scl-stretch-en = <1>;
+	qcom,hw-trdhld = <6>;
+	qcom,hw-tsp = <3>;
+	status = "ok";
+};
+
+&i2c_freq_1Mhz {
+	qcom,hw-thigh = <16>;
+	qcom,hw-tlow = <22>;
+	qcom,hw-tsu-sto = <17>;
+	qcom,hw-tsu-sta = <18>;
+	qcom,hw-thd-dat = <16>;
+	qcom,hw-thd-sta = <15>;
+	qcom,hw-tbuf = <19>;
+	qcom,hw-scl-stretch-en = <1>;
+	qcom,hw-trdhld = <3>;
+	qcom,hw-tsp = <3>;
+	qcom,cci-clk-src = <37500000>;
+	status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi b/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
index 0a8c0bf..f7831c5 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
@@ -25,6 +25,7 @@
 
 		arm,buffer-size = <0x100000>;
 		arm,sg-enable;
+		qcom,force-reg-dump;
 
 		coresight-name = "coresight-tmc-etr";
 		coresight-ctis = <&cti0 &cti8>;
@@ -51,6 +52,8 @@
 		coresight-name = "coresight-tmc-etf";
 
 		arm,default-sink;
+		qcom,force-reg-dump;
+
 		coresight-ctis = <&cti0 &cti8>;
 
 		clocks = <&clock_gcc clk_qdss_clk>,
diff --git a/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi b/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi
index f72fda9..ec92805 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi
@@ -58,7 +58,7 @@
 			reg = <0x100>;
 			enable-method = "psci";
 			efficiency = <1126>;
-			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
+			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_1>;
 			#cooling-cells = <2>;
 			L2_1: l2-cache {
@@ -83,7 +83,7 @@
 			reg = <0x101>;
 			enable-method = "psci";
 			efficiency = <1126>;
-			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
+			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_1>;
 			#cooling-cells = <2>;
 			L1_I_101: l1-icache {
@@ -102,7 +102,7 @@
 			reg = <0x102>;
 			enable-method = "psci";
 			efficiency = <1126>;
-			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
+			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_1>;
 			#cooling-cells = <2>;
 			L1_I_102: l1-icache {
@@ -121,7 +121,7 @@
 			reg = <0x103>;
 			enable-method = "psci";
 			efficiency = <1126>;
-			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
+			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_1>;
 			#cooling-cells = <2>;
 			L1_I_103: l1-icache {
@@ -140,7 +140,7 @@
 			reg = <0x0>;
 			enable-method = "psci";
 			efficiency = <1024>;
-			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_0>;
+			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_1>;
 			next-level-cache = <&L2_0>;
 			#cooling-cells = <2>;
 			L2_0: l2-cache {
@@ -164,7 +164,7 @@
 			reg = <0x1>;
 			enable-method = "psci";
 			efficiency = <1024>;
-			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_0>;
+			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_1>;
 			next-level-cache = <&L2_0>;
 			#cooling-cells = <2>;
 			L1_I_1: l1-icache {
@@ -183,7 +183,7 @@
 			reg = <0x2>;
 			enable-method = "psci";
 			efficiency = <1024>;
-			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_0>;
+			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_1>;
 			next-level-cache = <&L2_0>;
 			#cooling-cells = <2>;
 			L1_I_2: l1-icache {
@@ -202,7 +202,7 @@
 			reg = <0x3>;
 			enable-method = "psci";
 			efficiency = <1024>;
-			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_0>;
+			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_1>;
 			next-level-cache = <&L2_0>;
 			#cooling-cells = <2>;
 			L1_I_3: l1-icache {
@@ -245,11 +245,11 @@
 		};
 		CLUSTER_COST_0: cluster-cost0 {
 			busy-cost-data = <
-				 500000  19
-				 800000  29
-				 900000  36
-				1000000  46
-				1100000  55
+				 700000  85
+				1000000  126
+				1100000  152
+				1250000  197
+				1400000  239
 			>;
 			idle-cost-data = <
 				4 3 2 1
@@ -257,11 +257,11 @@
 		};
 		CLUSTER_COST_1: cluster-cost1 {
 			busy-cost-data = <
-				 700000  85
-				1000000  126
-				1100000  152
-				1250000  197
-				1400000  239
+				 500000  19
+				 800000  29
+				 900000  36
+				1000000  46
+				1100000  55
 			>;
 			idle-cost-data = <
 				4 3 2 1
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi
index 477802a..fbe5ce7 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi
@@ -28,13 +28,13 @@
 
 &soc {
 	qcom,csid@1b30000 {
-		/delete-property/ qcom,mipi-csi-vdd-supply;
+		qcom,mipi-csi-vdd-supply = <&pm8953_l2>;
 	};
 	qcom,csid@1b30400 {
-		/delete-property/ qcom,mipi-csi-vdd-supply;
+		qcom,mipi-csi-vdd-supply = <&pm8953_l2>;
 	};
 	qcom,csid@1b30800 {
-		/delete-property/ qcom,mipi-csi-vdd-supply;
+		qcom,mipi-csi-vdd-supply = <&pm8953_l2>;
 	};
 
 	mem_acc_vreg_corner: regulator@01946004 {
@@ -161,4 +161,10 @@
 				<0		0	      0>;
 		qcom,cpr-enable;
 	};
+
+	qcom,cpu-clock-8939@b111050 {
+		vdd-c0-supply = <&apc_vreg_corner>;
+		vdd-c1-supply = <&apc_vreg_corner>;
+		vdd-cci-supply = <&apc_vreg_corner>;
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi
index ab2a365..bca8912 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi
@@ -14,11 +14,14 @@
 #include "dsi-panel-sim-cmd.dtsi"
 #include "dsi-panel-truly-1080p-video.dtsi"
 #include "dsi-panel-truly-1080p-cmd.dtsi"
+#include "dsi-panel-truly-720p-video.dtsi"
+#include "dsi-panel-truly-720p-cmd.dtsi"
 #include "dsi-panel-r69006-1080p-cmd.dtsi"
 #include "dsi-panel-r69006-1080p-video.dtsi"
 #include "dsi-adv7533-1080p.dtsi"
 #include "dsi-adv7533-720p.dtsi"
-
+#include "dsi-panel-hx8399c-fhd-plus-video.dtsi"
+#include "dsi-panel-hx8399c-hd-plus-video.dtsi"
 &soc {
 	dsi_panel_pwr_supply: dsi_panel_pwr_supply {
 		#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/msm8937-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8937-mtp.dtsi
index 01192af..42f1b5c 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-mtp.dtsi
@@ -11,6 +11,8 @@
  * GNU General Public License for more details.
  */
 
+#include "msm8937-camera-sensor-mtp.dtsi"
+
 #include "msm8937-pinctrl.dtsi"
 &blsp1_uart2 {
 	status = "ok";
diff --git a/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
index 1b273ef..87dd30e 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
@@ -15,7 +15,7 @@
 	tlmm: pinctrl@1000000 {
 		compatible = "qcom,msm8937-pinctrl";
 		reg = <0x1000000 0x300000>;
-		interrupts = <0 208 0>;
+		interrupts-extended = <&wakegic GIC_SPI 208 IRQ_TYPE_NONE>;
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
@@ -1376,29 +1376,57 @@
 			};
 		};
 
-		cam_sensor_rear_default: cam_sensor_rear_default {
-			/* RESET, STANDBY */
+		cam_sensor_rear_reset: cam_sensor_rear_reset {
+			/* RESET */
 			mux {
-				pins = "gpio36", "gpio35";
+				pins = "gpio36";
 				function = "gpio";
 			};
 
 			config {
-				pins = "gpio36","gpio35";
+				pins = "gpio36";
 				bias-disable; /* No PULL */
 				drive-strength = <2>; /* 2 MA */
 			};
 		};
 
-		cam_sensor_rear_sleep: cam_sensor_rear_sleep {
-			/* RESET, STANDBY */
+		cam_sensor_rear_reset_sleep: cam_sensor_rear_reset_sleep {
+			/* RESET */
 			mux {
-				pins = "gpio36","gpio35";
+				pins = "gpio36";
 				function = "gpio";
 			};
 
 			config {
-				pins = "gpio36","gpio35";
+				pins = "gpio36";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_rear_standby: cam_sensor_rear_standby {
+			/* STANDBY */
+			mux {
+				pins = "gpio35";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio35";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_rear_standby_sleep: cam_sensor_rear_standby_sleep {
+			/* STANDBY */
+			mux {
+				pins = "gpio35";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio35";
 				bias-disable; /* No PULL */
 				drive-strength = <2>; /* 2 MA */
 			};
@@ -1432,6 +1460,34 @@
 			};
 		};
 
+		cam_sensor_rear_vana: cam_sensor_rear_vana {
+			/* VANA */
+			mux {
+				pins = "gpio35";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio35";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_rear_vana_sleep: cam_sensor_rear_vana_sleep {
+			/* VANA */
+			mux {
+				pins = "gpio35";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio35";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
 		cam_sensor_mclk1_default: cam_sensor_mclk1_default {
 			/* MCLK1 */
 			mux {
diff --git a/arch/arm64/boot/dts/qcom/msm8937.dtsi b/arch/arm64/boot/dts/qcom/msm8937.dtsi
index 09890bb..8f769fe 100644
--- a/arch/arm64/boot/dts/qcom/msm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937.dtsi
@@ -124,6 +124,11 @@
 			reg = <0x0 0x90000000 0x0 0x1400000>;
 		};
 
+		dump_mem: mem_dump_region {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0 0x2400000>;
+		};
 	};
 
 	aliases {
@@ -305,6 +310,57 @@
 
 	thermal_zones: thermal-zones {};
 
+	mem_dump {
+		compatible = "qcom,mem-dump";
+		memory-region = <&dump_mem>;
+
+		rpmh_dump {
+			qcom,dump-size = <0x2000000>;
+			qcom,dump-id = <0xec>;
+		};
+
+		fcm_dump {
+			qcom,dump-size = <0x8400>;
+			qcom,dump-id = <0xee>;
+		};
+
+		rpm_sw_dump {
+			qcom,dump-size = <0x28000>;
+			qcom,dump-id = <0xea>;
+		};
+
+		pmic_dump {
+			qcom,dump-size = <0x10000>;
+			qcom,dump-id = <0xe4>;
+		};
+
+		vsense_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0xe9>;
+		};
+
+		tmc_etf_dump {
+			qcom,dump-size = <0x10000>;
+			qcom,dump-id = <0xf0>;
+		};
+
+		tmc_etr_reg_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0x100>;
+		};
+
+		tmc_etf_reg_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0x101>;
+		};
+
+		misc_data_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0xe8>;
+		};
+
+	};
+
 	tsens0: tsens@4a8000 {
 		compatible = "qcom,msm8937-tsens";
 		reg = <0x4a8000 0x1000>,
@@ -833,6 +889,10 @@
 		};
 	};
 
+	qcom,iris-fm {
+		compatible = "qcom,iris_fm";
+	};
+
 	rpm_bus: qcom,rpm-smd {
 		compatible = "qcom,rpm-smd";
 		rpm-channel-name = "rpm_requests";
@@ -935,6 +995,7 @@
 		qcom,ipi-ping;
 		qcom,wakeup-enable;
 		status = "okay";
+		qcom,scandump-size = <0x40000>;
 	};
 
 	spmi_bus: qcom,spmi@200f000 {
@@ -996,10 +1057,20 @@
 			reg = <0x6b0 32>;
 		};
 
+		kaslr_offset@6d0 {
+			compatible = "qcom,msm-imem-kaslr_offset";
+			reg = <0x6d0 12>;
+		};
+
 		pil@94c {
 			compatible = "qcom,msm-imem-pil";
 			reg = <0x94c 200>;
 		};
+
+		diag_dload@c8 {
+			compatible = "qcom,msm-imem-diag-dload";
+			reg = <0xc8 200>;
+		};
 	};
 
 	qcom,memshare {
@@ -1666,6 +1737,7 @@
 #include "msm8937-regulator.dtsi"
 #include "pm8937.dtsi"
 #include "msm8937-audio.dtsi"
+#include "msm8937-camera.dtsi"
 #include "msm-gdsc-8916.dtsi"
 #include "msm8937-coresight.dtsi"
 #include "msm8937-thermal.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-cdp.dtsi
index a46bce3..db9fb13 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-cdp.dtsi
@@ -190,7 +190,7 @@
 		qcom,clock-rates = <19200000 0>;
 	};
 
-	qcom,camera@0 {
+	camera0: qcom,camera@0 {
 		cell-index = <0>;
 		compatible = "qcom,camera";
 		reg = <0x0>;
@@ -203,10 +203,13 @@
 		cam_vio-supply = <&pm8953_l6>;
 		cam_vdig-supply = <&pm8953_l2>;
 		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-op-mode = <0 105000 100000>;
+		cam_vana-supply = <&pm8953_l22>;
+		cam_v_custom1-supply = <&pm8953_l23>;
+		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf",
+						"cam_vana", "cam_v_custom1";
+		qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000 1220000>;
+		qcom,cam-vreg-max-voltage = <0 1100000 2850000 2800000 1220000>;
+		qcom,cam-vreg-op-mode = <0 105000 100000 80000 105000>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_default
 				&cam_sensor_rear_default
diff --git a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-mtp.dtsi
index a7688f0..db9fb13 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-camera-sensor-mtp.dtsi
@@ -190,7 +190,7 @@
 		qcom,clock-rates = <19200000 0>;
 	};
 
-	qcom,camera@0 {
+	camera0: qcom,camera@0 {
 		cell-index = <0>;
 		compatible = "qcom,camera";
 		reg = <0x0>;
@@ -204,11 +204,12 @@
 		cam_vdig-supply = <&pm8953_l2>;
 		cam_vaf-supply = <&pm8953_l17>;
 		cam_vana-supply = <&pm8953_l22>;
+		cam_v_custom1-supply = <&pm8953_l23>;
 		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf",
-						"cam_vana";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000 2800000>;
-		qcom,cam-vreg-op-mode = <0 105000 100000 80000>;
+						"cam_vana", "cam_v_custom1";
+		qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000 1220000>;
+		qcom,cam-vreg-max-voltage = <0 1100000 2850000 2800000 1220000>;
+		qcom,cam-vreg-op-mode = <0 105000 100000 80000 105000>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_default
 				&cam_sensor_rear_default
diff --git a/arch/arm64/boot/dts/qcom/msm8953-camera.dtsi b/arch/arm64/boot/dts/qcom/msm8953-camera.dtsi
index 2685f5a..b125612 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-camera.dtsi
@@ -408,21 +408,21 @@
 		interrupt-names = "cpp";
 		vdd-supply = <&gdsc_cpp>;
 		qcom,vdd-names = "vdd";
-		clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+		clocks = <&clock_gcc clk_camss_top_ahb_clk_src>,
+			<&clock_gcc clk_gcc_camss_top_ahb_clk>,
 			<&clock_gcc clk_cpp_clk_src>,
 			<&clock_gcc clk_gcc_camss_cpp_ahb_clk>,
 			<&clock_gcc clk_gcc_camss_cpp_axi_clk>,
 			<&clock_gcc clk_gcc_camss_cpp_clk>,
 			<&clock_gcc clk_gcc_camss_micro_ahb_clk>,
 			<&clock_gcc clk_gcc_camss_ahb_clk>;
-		clock-names = "camss_top_ahb_clk", "cpp_core_clk",
-			"camss_vfe_cpp_ahb_clk", "camss_vfe_cpp_axi_clk",
-			"camss_vfe_cpp_clk","micro_iface_clk", "camss_ahb_clk";
-		qcom,clock-rates = <0 180000000 0 0 180000000 0 0>;
+		clock-names = "camss_ahb_src", "camss_top_ahb_clk",
+			"cpp_core_clk", "camss_vfe_cpp_ahb_clk",
+			"camss_vfe_cpp_axi_clk", "camss_vfe_cpp_clk",
+			"micro_iface_clk", "camss_ahb_clk";
+		qcom,clock-rates = <80000000 0 180000000 0 0 180000000 0 0>;
 		qcom,min-clock-rate = <100000000>;
 		qcom,bus-master = <1>;
-		resets = <&clock_gcc GCC_CAMSS_MICRO_BCR>;
-		reset-names = "micro_iface_reset";
 		qcom,msm-bus,name = "msm_camera_cpp";
 		qcom,msm-bus,num-cases = <2>;
 		qcom,msm-bus,num-paths = <1>;
@@ -430,7 +430,6 @@
 			<106 512 0 0>,
 			<106 512 0 0>;
 		qcom,msm-bus-vector-dyn-vote;
-		qcom,micro-reset;
 		qcom,cpp-fw-payload-info {
 			qcom,stripe-base = <156>;
 			qcom,plane-base = <141>;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-cdp.dts b/arch/arm64/boot/dts/qcom/msm8953-cdp.dts
index 6105b52..34c5f8f 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-cdp.dts
@@ -17,7 +17,6 @@
 #include "pmi8950.dtsi"
 #include "msm8953-cdp.dtsi"
 #include "msm8953-pmi8950.dtsi"
-#include "msm8953-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 CDP";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi
index 5680409..8782325 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi
@@ -14,6 +14,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/clock/msm-clocks-8953.h>
 #include "msm8953-audio-cdp.dtsi"
+#include "msm8953-camera-sensor-cdp.dtsi"
 
 &blsp1_uart0 {
 	status = "ok";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-coresight.dtsi b/arch/arm64/boot/dts/qcom/msm8953-coresight.dtsi
index aa00147..196a526 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-coresight.dtsi
@@ -25,8 +25,10 @@
 
 		arm,buffer-size = <0x100000>;
 		arm,sg-enable;
+		qcom,force-reg-dump;
 
 		coresight-name = "coresight-tmc-etr";
+		coresight-csr = <&csr>;
 		coresight-ctis = <&cti0 &cti8>;
 
 		clocks = <&clock_gcc clk_qdss_clk>,
@@ -49,8 +51,10 @@
 		reg-names = "tmc-base";
 
 		coresight-name = "coresight-tmc-etf";
+		coresight-csr = <&csr>;
 
 		arm,default-sink;
+		qcom,force-reg-dump;
 		coresight-ctis = <&cti0 &cti8>;
 
 		clocks = <&clock_gcc clk_qdss_clk>,
@@ -1139,6 +1143,10 @@
 		reg-names = "csr-base";
 		coresight-name = "coresight-csr";
 
+		qcom,usb-bam-support;
+		qcom,hwctrl-set-support;
+		qcom,set-byte-cntr-support;
+
 		qcom,blk-size = <1>;
 
 		clocks = <&clock_gcc clk_qdss_clk>,
@@ -1240,6 +1248,7 @@
 				"usbbam-mux", "blsp-mux";
 
 		coresight-name = "coresight-hwevent";
+		coresight-csr = <&csr>;
 
 		clocks = <&clock_gcc clk_qdss_clk>,
 			 <&clock_gcc clk_qdss_a_clk>;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts
index ee22633..e3a5b4a 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts
@@ -17,7 +17,6 @@
 #include "pmi8950.dtsi"
 #include "msm8953-mtp.dtsi"
 #include "msm8953-pmi8950.dtsi"
-#include "msm8953-camera-sensor-mtp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 Ext Codec MTP";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp.dts b/arch/arm64/boot/dts/qcom/msm8953-mtp.dts
index 82f6315..97c6db3 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp.dts
@@ -17,7 +17,6 @@
 #include "pmi8950.dtsi"
 #include "msm8953-mtp.dtsi"
 #include "msm8953-pmi8950.dtsi"
-#include "msm8953-camera-sensor-mtp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. MSM8953 + PMI8950 MTP";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
index 93565cf..a3bd5e9 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
@@ -13,6 +13,7 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/clock/msm-clocks-8953.h>
+#include "msm8953-camera-sensor-mtp.dtsi"
 
 &blsp1_uart0 {
 	status = "ok";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
index 6503b33..15be898 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
@@ -197,6 +197,34 @@
 			};
 		};
 
+		cam_sensor_ir_cut_default: cam_sensor_ir_cut_default {
+			/* RESET, STANDBY */
+			mux {
+				pins = "gpio38", "gpio39";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio38","gpio39";
+				bias-pull-up; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_ir_cut_sleep: cam_sensor_ir_cut_sleep {
+			/* RESET, STANDBY */
+			mux {
+				pins = "gpio38","gpio39";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio38","gpio39";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
 		cam_sensor_rear_vana: cam_sensor_rear_vdig {
 			/* VDIG */
 			mux {
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pmi632-cdp-s2.dts b/arch/arm64/boot/dts/qcom/msm8953-pmi632-cdp-s2.dts
index 4639f02..78ff97f 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pmi632-cdp-s2.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-pmi632-cdp-s2.dts
@@ -16,7 +16,6 @@
 #include "msm8953.dtsi"
 #include "sdm450-pmi632-cdp-s2.dtsi"
 #include "sdm450-pmi632.dtsi"
-#include "sdm632-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. msm8953 + PMI632 CDP S2";
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index 978d432..50ee0e8 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -26,7 +26,7 @@
 	interrupt-parent = <&wakegic>;
 
 	chosen {
-		bootargs = "kpti=0";
+		bootargs = "core_ctl_disable_cpumask=0-7 kpti=0";
 	};
 
 	firmware: firmware {
@@ -369,6 +369,11 @@
 			qcom,dump-id = <0xe4>;
 		};
 
+		vsense_dump {
+			qcom,dump-size = <0x10000>;
+			qcom,dump-id = <0xe9>;
+		};
+
 		tmc_etf_dump {
 			qcom,dump-size = <0x10000>;
 			qcom,dump-id = <0xf0>;
@@ -1182,6 +1187,10 @@
 		};
 	};
 
+	qcom,iris-fm {
+		compatible = "qcom,iris_fm";
+	};
+
 	rpm_bus: qcom,rpm-smd {
 		compatible = "qcom,rpm-smd";
 		rpm-channel-name = "rpm_requests";
@@ -1197,6 +1206,7 @@
 		qcom,pet-time = <10000>;
 		qcom,ipi-ping;
 		qcom,wakeup-enable;
+		qcom,scandump-size = <0x40000>;
 	};
 
 	qcom,chd_silver {
diff --git a/arch/arm64/boot/dts/qcom/pm8916-rpm-regulator.dtsi b/arch/arm64/boot/dts/qcom/pm8916-rpm-regulator.dtsi
new file mode 100644
index 0000000..42b6331
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/pm8916-rpm-regulator.dtsi
@@ -0,0 +1,365 @@
+/* Copyright (c) 2014, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&rpm_bus {
+	rpm-regulator-smpa1 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s1 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_s1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa2 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s2 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_s2";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa3 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s3 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_s3";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa4 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s4 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_s4";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l1 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l2 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l2";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l3 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l3";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l4 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l4";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <5>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l5 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l5";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <6>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l6 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l6";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <7>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l7 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l7";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <8>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l8 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l8";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <9>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l9 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l9";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <10>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l10 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l10";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa11 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <11>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l11 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l11";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <12>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l12 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l12";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa13 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <13>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l13 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l13";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <14>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l14 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l14";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <15>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l15 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l15";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa16 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <16>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l16 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l16";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <17>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l17 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l17";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa18 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <18>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l18 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "8916_l18";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi
index f71679b..7d38151 100644
--- a/arch/arm64/boot/dts/qcom/pm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi
@@ -1,4 +1,15 @@
-#include <dt-bindings/iio/qcom,spmi-vadc.h>
+/* Copyright (c) 2013-2014, 2016-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/spmi/spmi.h>
 
@@ -8,92 +19,253 @@
 		compatible = "qcom,pm8916", "qcom,spmi-pmic";
 		reg = <0x0 SPMI_USID>;
 		#address-cells = <1>;
-		#size-cells = <0>;
+		#size-cells = <1>;
 
-		rtc@6000 {
-			compatible = "qcom,pm8941-rtc";
-			reg = <0x6000>;
-			reg-names = "rtc", "alarm";
-			interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>;
+		pm8916_revid: qcom,revid@100 {
+			compatible = "qcom,qpnp-revid";
+			reg = <0x100 0x100>;
 		};
 
-		pwrkey@800 {
-			compatible = "qcom,pm8941-pwrkey";
-			reg = <0x800>;
-			interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
-			debounce = <15625>;
-			bias-pull-up;
+		pm8916_pon: qcom,power-on@800 {
+			compatible = "qcom,qpnp-power-on";
+			reg = <0x800 0x100>;
+			interrupts = <0x0 0x8 0x0 IRQ_TYPE_NONE>,
+				     <0x0 0x8 0x1 IRQ_TYPE_NONE>;
+			interrupt-names = "kpdpwr", "resin";
+			qcom,pon-dbc-delay = <15625>;
+			qcom,system-reset;
+			qcom,clear-warm-reset;
+			qcom,store-hard-reset-reason;
+
+			qcom,pon_1 {
+				qcom,pon-type = <0>;
+				qcom,support-reset = <1>;
+				qcom,pull-up = <1>;
+				qcom,s1-timer = <10256>;
+				qcom,s2-timer = <2000>;
+				qcom,s2-type = <1>;
+				linux,code = <116>;
+			};
+
+			qcom,pon_2 {
+				qcom,pon-type = <1>;
+				qcom,pull-up = <1>;
+				linux,code = <114>;
+			};
 		};
 
-		pm8916_gpios: gpios@c000 {
+		pm8916_gpios: pinctrl@c000 {
 			compatible = "qcom,pm8916-gpio";
-			reg = <0xc000>;
+			reg = <0xc000 0x400>;
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupts = <0 0xc0 0 IRQ_TYPE_NONE>,
 				     <0 0xc1 0 IRQ_TYPE_NONE>,
 				     <0 0xc2 0 IRQ_TYPE_NONE>,
 				     <0 0xc3 0 IRQ_TYPE_NONE>;
+			interrupt-names = "pm8916_gpio1", "pm8916_gpio2",
+					  "pm8916_gpio3", "pm8916_gpio4";
 		};
 
 		pm8916_mpps: mpps@a000 {
 			compatible = "qcom,pm8916-mpp";
-			reg = <0xa000>;
+			reg = <0xa000 0x400>;
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupts = <0 0xa0 0 IRQ_TYPE_NONE>,
 				     <0 0xa1 0 IRQ_TYPE_NONE>,
 				     <0 0xa2 0 IRQ_TYPE_NONE>,
 				     <0 0xa3 0 IRQ_TYPE_NONE>;
+			interrupt-names = "pm8916_mpp1", "pm8916_mpp2",
+					  "pm8916_mpp3", "pm8916_mpp4";
 		};
 
-		pm8916_temp: temp-alarm@2400 {
-			compatible = "qcom,spmi-temp-alarm";
-			reg = <0x2400>;
-			interrupts = <0 0x24 0 IRQ_TYPE_EDGE_RISING>;
-			io-channels = <&pm8916_vadc VADC_DIE_TEMP>;
-			io-channel-names = "thermal";
-			#thermal-sensor-cells = <0>;
+		pm8916_rtc: qcom,pm8916_rtc {
+			compatible = "qcom,qpnp-rtc";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			qcom,qpnp-rtc-write = <0>;
+			qcom,qpnp-rtc-alarm-pwrup = <0>;
+
+			qcom,pm8916_rtc_rw@6000 {
+				reg = <0x6000 0x100>;
+			};
+			qcom,pm8916_rtc_alarm@6100 {
+				reg = <0x6100 0x100>;
+				interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>;
+			};
 		};
 
 		pm8916_vadc: vadc@3100 {
-			compatible = "qcom,spmi-vadc";
-			reg = <0x3100>;
-			interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+			compatible = "qcom,qpnp-vadc";
+			reg = <0x3100 0x100>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			#io-channel-cells = <1>;
+			interrupts = <0x0 0x31 0x0 IRQ_TYPE_NONE>;
+			interrupt-names = "eoc-int-en-set";
+			qcom,adc-bit-resolution = <15>;
+			qcom,adc-vdd-reference = <1800>;
+			qcom,vadc-poll-eoc;
+			qcom,pmic-revid = <&pm8916_revid>;
 
-			usb_in {
-				reg = <VADC_USBIN>;
-				qcom,pre-scaling = <1 10>;
+			chan@8 {
+				label = "die_temp";
+				reg = <8>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <3>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
 			};
-			vph_pwr {
-				reg = <VADC_VSYS>;
-				qcom,pre-scaling = <1 3>;
+
+			chan@9 {
+				label = "ref_625mv";
+				reg = <9>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
 			};
-			die_temp {
-				reg = <VADC_DIE_TEMP>;
+
+			chan@a {
+				label = "ref_1250v";
+				reg = <0xa>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
 			};
-			ref_625mv {
-				reg = <VADC_REF_625MV>;
-			};
-			ref_1250v {
-				reg = <VADC_REF_1250MV>;
-			};
-			ref_gnd {
-				reg = <VADC_GND_REF>;
-			};
-			ref_vdd {
-				reg = <VADC_VDD_VADC>;
-			};
+		};
+
+		pm8916_tz: qcom,temp-alarm@2400 {
+			compatible = "qcom,qpnp-temp-alarm";
+			reg = <0x2400 0x100>;
+			interrupts = <0x0 0x24 0x0 IRQ_TYPE_NONE>;
+			label = "pm8916_tz";
+			qcom,channel-num = <8>;
+			qcom,threshold-set = <0>;
+			qcom,temp_alarm-vadc = <&pm8916_vadc>;
+		};
+
+		pm8916_adc_tm: vadc@3400 {
+			compatible = "qcom,qpnp-adc-tm";
+			reg = <0x3400 0x100>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <0x0 0x34 0x0 IRQ_TYPE_NONE>,
+				     <0x0 0x34 0x3 IRQ_TYPE_NONE>,
+				     <0x0 0x34 0x4 IRQ_TYPE_NONE>;
+			interrupt-names = "eoc-int-en-set",
+					  "high-thr-en-set",
+					  "low-thr-en-set";
+			qcom,adc-bit-resolution = <15>;
+			qcom,adc-vdd-reference = <1800>;
+			qcom,adc_tm-vadc = <&pm8916_vadc>;
+			qcom,pmic-revid = <&pm8916_revid>;
+		};
+
+		pm8916_leds: qcom,leds@a100 {
+			compatible = "qcom,leds-qpnp";
+			reg = <0xa100 0x100>;
+			label = "mpp";
 		};
 	};
 
 	pm8916_1: pm8916@1 {
-		compatible = "qcom,spmi-pmic";
+		compatible = "qcom,pm8916", "qcom,spmi-pmic";
 		reg = <0x1 SPMI_USID>;
 		#address-cells = <1>;
-		#size-cells = <0>;
+		#size-cells = <1>;
+
+		pm8916_pwm: pwm@bc00 {
+			compatible = "qcom,qpnp-pwm";
+			reg = <0xbc00 0x100>;
+			reg-names = "qpnp-lpg-channel-base";
+			qcom,channel-id = <0>;
+			qcom,supported-sizes = <6>, <9>;
+			#pwm-cells = <2>;
+		};
+
+		pm8916_vib: qcom,vibrator@c000 {
+			compatible = "qcom,qpnp-vibrator";
+			reg = <0xc000 0x100>;
+			label = "vibrator";
+			status = "disabled";
+		};
+
+		pm8916_tombak_dig: msm8x16_wcd_codec@f000{
+			compatible = "qcom,msm8x16_wcd_codec";
+			reg = <0xf000 0x100>;
+			interrupt-parent = <&spmi_bus>;
+			interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
+				     <0x1 0xf0 0x1 IRQ_TYPE_NONE>,
+				     <0x1 0xf0 0x2 IRQ_TYPE_NONE>,
+				     <0x1 0xf0 0x3 IRQ_TYPE_NONE>,
+				     <0x1 0xf0 0x4 IRQ_TYPE_NONE>,
+				     <0x1 0xf0 0x5 IRQ_TYPE_NONE>,
+				     <0x1 0xf0 0x6 IRQ_TYPE_NONE>,
+				     <0x1 0xf0 0x7 IRQ_TYPE_NONE>;
+			interrupt-names = "spk_cnp_int",
+					  "spk_clip_int",
+					  "spk_ocp_int",
+					  "ins_rem_det1",
+					  "but_rel_det",
+					  "but_press_det",
+					  "ins_rem_det",
+					  "mbhc_int";
+
+			cdc-vdda-cp-supply = <&pm8916_s4>;
+			qcom,cdc-vdda-cp-voltage = <1800000 2200000>;
+			qcom,cdc-vdda-cp-current = <770000>;
+
+			cdc-vdda-h-supply = <&pm8916_l5>;
+			qcom,cdc-vdda-h-voltage = <1800000 1800000>;
+			qcom,cdc-vdda-h-current = <20000>;
+
+			cdc-vdd-px-supply = <&pm8916_s4>;
+			qcom,cdc-vdd-px-voltage = <1800000 2200000>;
+			qcom,cdc-vdd-px-current = <770000>;
+
+			cdc-vdd-pa-supply = <&pm8916_l5>;
+			qcom,cdc-vdd-pa-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-pa-current = <5000>;
+
+			cdc-vdd-mic-bias-supply = <&pm8916_l13>;
+			qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+			qcom,cdc-vdd-mic-bias-current = <25000>;
+
+			qcom,cdc-mclk-clk-rate = <9600000>;
+
+			qcom,cdc-static-supplies = "cdc-vdda-h",
+						   "cdc-vdd-px",
+						   "cdc-vdd-pa",
+						   "cdc-vdda-cp";
+
+			qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+			qcom,subsys-name = "modem";
+		};
+
+		pm8916_tombak_analog: msm8x16_wcd_codec@f100{
+			compatible = "qcom,msm8x16_wcd_codec";
+			reg = <0xf100 0x100>;
+			interrupt-parent = <&spmi_bus>;
+			interrupts = <0x1 0xf1 0x0 IRQ_TYPE_NONE>,
+				     <0x1 0xf1 0x1 IRQ_TYPE_NONE>,
+				     <0x1 0xf1 0x2 IRQ_TYPE_NONE>,
+				     <0x1 0xf1 0x3 IRQ_TYPE_NONE>,
+				     <0x1 0xf1 0x4 IRQ_TYPE_NONE>,
+				     <0x1 0xf1 0x5 IRQ_TYPE_NONE>;
+			interrupt-names = "ear_ocp_int",
+					  "hphr_ocp_int",
+					  "hphl_ocp_det",
+					  "ear_cnp_int",
+					  "hphr_cnp_int",
+					  "hphl_cnp_int";
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/pm8937.dtsi b/arch/arm64/boot/dts/qcom/pm8937.dtsi
index cd1bddb..18a3270c 100644
--- a/arch/arm64/boot/dts/qcom/pm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8937.dtsi
@@ -35,6 +35,7 @@
 				"resin-bark", "kpdpwr-resin-bark";
 			qcom,pon-dbc-delay = <15625>;
 			qcom,system-reset;
+			qcom,store-hard-reset-reason;
 
 			qcom,pon_1 {
 				qcom,pon-type = <0>;
diff --git a/arch/arm64/boot/dts/qcom/pm8953.dtsi b/arch/arm64/boot/dts/qcom/pm8953.dtsi
index c496257..10c010e 100644
--- a/arch/arm64/boot/dts/qcom/pm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8953.dtsi
@@ -230,7 +230,6 @@
 				qcom,scale-function = <4>;
 				qcom,hw-settle-time = <2>;
 				qcom,fast-avg-setup = <0>;
-				qcom,vadc-thermal-node;
 			};
 
 			chan@3c {
@@ -285,6 +284,19 @@
 				qcom,fast-avg-setup = <0>;
 				qcom,thermal-node;
 			};
+
+			chan@32 {
+				label = "xo_therm";
+				reg = <0x32>;
+				qcom,pre-div-channel-scaling = <0>;
+				qcom,decimation = <0>;
+				qcom,calibration-type = "ratiometric";
+				qcom,scale-function = <4>;
+				qcom,hw-settle-time = <2>;
+				qcom,btm-channel-number = <0x68>;
+				qcom,fast-avg-setup = <0>;
+				qcom,thermal-node;
+			};
 		};
 
 		pm8953_rtc: qcom,pm8953_rtc {
@@ -346,7 +358,7 @@
 	xo-therm-adc {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
-		thermal-sensors = <&pm8953_vadc 0x32>;
+		thermal-sensors = <&pm8953_adc_tm 0x32>;
 		thermal-governor = "user_space";
 
 		trips {
diff --git a/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi b/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
index 5d7d0b8..aa316ba 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
@@ -47,9 +47,14 @@
 	status = "disabled";
 };
 
+&mdss_mdp {
+	bridges = <&lt9611>;
+};
+
 &qupv3_se9_i2c {
 	status = "okay";
-	lt9611@3b {
+
+	lt9611: lt,lt9611@3b {
 		compatible = "lt,lt9611";
 		reg = <0x3b>;
 		interrupt-parent = <&tlmm>;
@@ -60,6 +65,7 @@
 		lt,hdmi-ps-gpio = <&tlmm 136 0x0>;
 		lt,hdmi-en-gpio = <&tlmm 137 0x0>;
 		lt,non-pluggable;
+		lt,preferred-mode = "1920x1080";
 
 		vcc-supply = <&pm660l_l6>;
 		vdd-supply = <&pm660_l11>;
@@ -101,6 +107,21 @@
 				lt,mode-refresh-rate = <60>;
 				lt,mode-clock-in-khz = <148500>;
 			};
+
+			lt,customize-mode-id@1 {
+				lt,mode-h-active = <3840>;
+				lt,mode-h-front-porch = <176>;
+				lt,mode-h-pulse-width = <88>;
+				lt,mode-h-back-porch = <296>;
+				lt,mode-h-active-high;
+				lt,mode-v-active = <2160>;
+				lt,mode-v-front-porch = <8>;
+				lt,mode-v-pulse-width = <10>;
+				lt,mode-v-back-porch = <72>;
+				lt,mode-v-active-high;
+				lt,mode-refresh-rate = <30>;
+				lt,mode-clock-in-khz = <297000>;
+			};
 		};
 
 		ports {
diff --git a/arch/arm64/boot/dts/qcom/qcs605-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-cdp-overlay.dts
index 1429880..a479175 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-cdp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-cdp-overlay.dts
@@ -46,7 +46,7 @@
 		eeprom-src = <&eeprom_rear_aux>;
 		cam_vio-supply = <&camera_vio_ldo>;
 		cam_vana-supply = <&camera_vana_ldo>;
-		cam_vdig-supply = <&camera_ldo>;
+		cam_vdig-supply = <&camera_rear_ldo>;
 		cam_clk-supply = <&titan_top_gdsc>;
 		regulator-names = "cam_vdig", "cam_vio", "cam_vana",
 			"cam_clk";
diff --git a/arch/arm64/boot/dts/qcom/qcs605-cdp.dts b/arch/arm64/boot/dts/qcom/qcs605-cdp.dts
index 6c6012e..92453d4 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/qcs605-cdp.dts
@@ -40,7 +40,7 @@
 		eeprom-src = <&eeprom_rear_aux>;
 		cam_vio-supply = <&camera_vio_ldo>;
 		cam_vana-supply = <&camera_vana_ldo>;
-		cam_vdig-supply = <&camera_ldo>;
+		cam_vdig-supply = <&camera_rear_ldo>;
 		cam_clk-supply = <&titan_top_gdsc>;
 		regulator-names = "cam_vdig", "cam_vio", "cam_vana",
 			"cam_clk";
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-camera-sensor-mtp.dtsi
new file mode 100644
index 0000000..7ab5d1e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-camera-sensor-mtp.dtsi
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	led_flash_rear: qcom,camera-flash@0 {
+		cell-index = <0>;
+		reg = <0x00 0x00>;
+		compatible = "qcom,camera-flash";
+		status = "ok";
+	};
+};
+
+&cam_cci {
+	qcom,cam-res-mgr {
+		compatible = "qcom,cam-res-mgr";
+		status = "ok";
+	};
+
+	qcom,cam-sensor@0 {
+		cell-index = <0>;
+		compatible = "qcom,cam-sensor";
+		reg = <0x0>;
+		csiphy-sd-index = <0>;
+		sensor-position-roll = <270>;
+		sensor-position-pitch = <0>;
+		sensor-position-yaw = <180>;
+		led-flash-src = <&led_flash_rear>;
+		cam_vio-supply = <&pm660_l11>;
+		cam_vana-supply = <&pm660_l15>;
+		cam_vdig-supply = <&pm660_l5>;
+		cam_clk-supply = <&titan_top_gdsc>;
+		regulator-names = "cam_vio", "cam_vana", "cam_vdig",
+			"cam_clk";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <1800000 2900000 1200000 0>;
+		rgltr-max-voltage = <1800000 2900000 1200000 0>;
+		rgltr-load-current = <0 80000 105000 0>;
+		gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk0_active
+				&cam_sensor_rear_active>;
+		pinctrl-1 = <&cam_sensor_mclk0_suspend
+				&cam_sensor_rear_suspend>;
+		gpios = <&tlmm 13 0>,
+			<&tlmm 30 0>;
+		gpio-reset = <1>;
+		gpio-req-tbl-num = <0 1>;
+		gpio-req-tbl-flags = <1 0>;
+		gpio-req-tbl-label = "CAMIF_MCLK0",
+					"CAM_RESET0";
+		sensor-mode = <0>;
+		cci-master = <0>;
+		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-mtp.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dtsi
index f592c0e..1ae339e 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-mtp.dtsi
@@ -11,6 +11,7 @@
  */
 
 #include "qcs605-lc-pmic-overlay.dtsi"
+#include "qcs605-lc-camera-sensor-mtp.dtsi"
 
 &qupv3_se9_2uart {
 	status = "disabled";
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-pmic-overlay.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-pmic-overlay.dtsi
index 2436687..1264e08 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc-pmic-overlay.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-pmic-overlay.dtsi
@@ -258,3 +258,15 @@
 		qcom,lra-res-cal-period = <4>;
 	};
 };
+
+&pm660_pdphy {
+	vdd-pdphy-supply = <&pm660_l17>;
+	vbus-supply = <&smb2_vbus>;
+	vconn-supply = <&smb2_vconn>;
+};
+
+&usb0 {
+	extcon = <&pm660_pdphy>, <&pm660_pdphy>, <&eud>,
+				<&pm660_charger>, <&pm660_charger>;
+	vbus_dwc3-supply = <&smb2_vbus>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-sde-display.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-sde-display.dtsi
new file mode 100644
index 0000000..654f3a1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-sde-display.dtsi
@@ -0,0 +1,73 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/clock/mdss-10nm-pll-clk.h>
+
+&soc {
+	ext_dsi_bridge_display: qcom,dsi-display@0 {
+		compatible = "qcom,dsi-display";
+		label = "ext_dsi_bridge_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";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				reg = <0>;
+				ext_dsi_out: endpoint {
+				};
+			};
+		};
+	};
+
+	sde_wb: qcom,wb-display@0 {
+		compatible = "qcom,wb-display";
+		cell-index = <0>;
+		label = "wb_display";
+	};
+
+	ext_disp: qcom,msm-ext-disp {
+		compatible = "qcom,msm-ext-disp";
+
+		ext_disp_audio_codec: qcom,msm-ext-disp-audio-codec-rx {
+			compatible = "qcom,msm-ext-disp-audio-codec-rx";
+		};
+	};
+};
+
+&mdss_dsi0 {
+	vdda-1p2-supply = <&pm660_l2>;
+};
+
+&mdss_dsi1 {
+	vdda-1p2-supply = <&pm660_l2>;
+};
+
+&mdss_dsi_phy0 {
+	vdda-0p9-supply = <&pm660_l6>;
+};
+
+&mdss_dsi_phy1 {
+	vdda-0p9-supply = <&pm660_l6>;
+};
+
+&sde_dp {
+	vdda-0p9-supply = <&pm660_l6>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
index 2af6610..192bf42 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
@@ -14,6 +14,7 @@
 #include "qcs605.dtsi"
 #include "pm8005.dtsi"
 #include "qcs605-pm660-pm8005-regulator.dtsi"
+#include "qcs605-lc-sde-display.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. QCS605 SoC";
@@ -134,6 +135,13 @@
 	/delete-node/ qcom,pm660l@3;
 };
 
+&icnss {
+	/delete-property/ vdd-3.3-ch0-supply;
+	vdd-0.8-cx-mx-supply = <&pm660_l1>;
+	vdd-1.8-xo-supply = <&pm660_l9>;
+	vdd-1.3-rfa-supply = <&pm660_l3>;
+};
+
 &thermal_zones {
 	pm660l_tz {
 		/delete-property/ thermal-sensors;
@@ -201,35 +209,159 @@
 
 &clock_gfx {
 	/delete-property/ vdd_gfx-supply;
-	vdd_gfx-supply = <&pm8005_s2>;
+	vdd_gfx-supply = <&pm8005_s3_level>;
 };
 
 &gpu_gx_gdsc {
 	/delete-property/ parent-supply;
-	parent-supply = <&pm8005_s2>;
+	parent-supply = <&pm8005_s3_level>;
 };
 
-&mdss_dsi_phy0 {
-	/delete-property/ vdda-0p9-supply;
-};
-
-&mdss_dsi_phy1 {
-	/delete-property/ vdda-0p9-supply;
+&mdss_mdp {
+	connectors = <&sde_rscc &sde_wb>;
+	bridges = <&lt9611>;
 };
 
 &sde_dp {
-	/delete-property/ vdda-0p9-supply;
+	status = "disabled";
 };
 
-&qusb_phy0 {
-	/delete-property/ vdd-supply;
-	/delete-property/ vdda33-supply;
+&tlmm {
+	lt9611_vcc_eldo_default: lt9611_vcc_eldo_default {
+		mux {
+			pins = "gpio53";
+			function = "gpio";
+		};
+		config {
+			pins = "gpio53";
+			drive-strength = <8>;
+			bias-disable = <0>;
+			output-low;
+		};
+	};
 };
 
-&usb_qmp_dp_phy {
-	/delete-property/ vdd-supply;
+&soc {
+	lt9611_vcc_eldo: lt9611-gpio-regulator@0 {
+		compatible = "regulator-fixed";
+		regulator-name = "lt9611_vcc_eldo";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-enable-ramp-delay = <233>;
+		gpio = <&tlmm 53 0>;
+		enable-active-high;
+		pinctrl-names = "default";
+		pintctrl-0 = <&lt9611_vcc_eldo_default>;
+	};
+};
+
+&qupv3_se9_i2c {
+	status = "okay";
+
+	lt9611: lt,lt9611@3b {
+		compatible = "lt,lt9611";
+		reg = <0x3b>;
+		interrupt-parent = <&tlmm>;
+		interrupts = <96 0>;
+		interrupt-names = "lt_irq";
+		lt,irq-gpio = <&tlmm 96 0x0>;
+		lt,reset-gpio = <&tlmm 95 0x0>;
+		lt,non-pluggable;
+		lt,preferred-mode = "1920x1080";
+
+		vdd-supply = <&pm660_l12>;
+		vcc-supply = <&lt9611_vcc_eldo>;
+		lt,supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			lt,supply-entry@0 {
+				reg = <0>;
+				lt,supply-name = "vdd";
+				lt,supply-min-voltage = <1800000>;
+				lt,supply-max-voltage = <1800000>;
+				lt,supply-enable-load = <200000>;
+				lt,supply-post-on-sleep = <50>;
+			};
+
+			lt,supply-entry@1 {
+				reg = <1>;
+				lt,supply-name = "vcc";
+				lt,supply-min-voltage = <3300000>;
+				lt,supply-max-voltage = <3300000>;
+				lt,supply-post-on-sleep = <50>;
+			};
+		};
+
+		lt,customize-modes {
+			lt,customize-mode-id@0 {
+				lt,mode-h-active = <1920>;
+				lt,mode-h-front-porch = <88>;
+				lt,mode-h-pulse-width = <44>;
+				lt,mode-h-back-porch = <148>;
+				lt,mode-h-active-high;
+				lt,mode-v-active = <1080>;
+				lt,mode-v-front-porch = <4>;
+				lt,mode-v-pulse-width = <5>;
+				lt,mode-v-back-porch = <36>;
+				lt,mode-v-active-high;
+				lt,mode-refresh-rate = <60>;
+				lt,mode-clock-in-khz = <148500>;
+			};
+
+			lt,customize-mode-id@1 {
+				lt,mode-h-active = <3840>;
+				lt,mode-h-front-porch = <176>;
+				lt,mode-h-pulse-width = <88>;
+				lt,mode-h-back-porch = <296>;
+				lt,mode-h-active-high;
+				lt,mode-v-active = <2160>;
+				lt,mode-v-front-porch = <8>;
+				lt,mode-v-pulse-width = <10>;
+				lt,mode-v-back-porch = <72>;
+				lt,mode-v-active-high;
+				lt,mode-refresh-rate = <30>;
+				lt,mode-clock-in-khz = <297000>;
+			};
+		};
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				lt9611_in: endpoint {
+					remote-endpoint = <&ext_dsi_out>;
+				};
+			};
+		};
+	};
+};
+
+&soc {
+	qcom,dsi-display@0 {
+		qcom,dsi-display-active;
+
+		ports {
+			port@0 {
+				endpoint {
+					remote-endpoint = <&lt9611_in>;
+				};
+			};
+		};
+	};
 };
 
 &pm660_pdphy {
 	/delete-property/ vdd-pdphy-supply;
 };
+
+&qusb_phy0 {
+	vdd-supply = <&pm660_l6>;
+	vdda33-supply = <&pm660_l17>;
+};
+
+&usb_qmp_dp_phy {
+	vdd-supply = <&pm660_l6>;  /* 0.88v */
+	core-supply = <&pm660_l2>; /* 1.2v */
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi
index 5adbbb8..1e1d82c 100644
--- a/arch/arm64/boot/dts/qcom/qcs605.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi
@@ -54,6 +54,18 @@
 	reg = <0 0x91c15000 0 0x2000>;
 };
 
+&adsp_mem {
+	size = <0 0x800000>;
+};
+
+&secure_display_memory {
+	status = "disabled";
+};
+
+&sp_mem {
+	status = "disabled";
+};
+
 &soc {
 	qcom,rmnet-ipa {
 		status = "disabled";
diff --git a/arch/arm64/boot/dts/qcom/sda845-sdxpoorwills.dtsi b/arch/arm64/boot/dts/qcom/sda845-sdxpoorwills.dtsi
index 944ca3b..0b678a8 100644
--- a/arch/arm64/boot/dts/qcom/sda845-sdxpoorwills.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda845-sdxpoorwills.dtsi
@@ -15,9 +15,9 @@
 	pinctrl-0 = <&ap2mdm_pon_reset_default>;
 	pinctrl-1 = <&ap2mdm_active &mdm2ap_active>;
 	pinctrl-2 = <&ap2mdm_sleep &mdm2ap_sleep>;
-	interrupt-map = <0 &tlmm 24 0x3
+	interrupt-map = <0 &tlmm 20 0x3
 			1 &tlmm 21 0x3>;
-	qcom,mdm2ap-errfatal-gpio = <&tlmm 24 0x00>;
+	qcom,mdm2ap-errfatal-gpio = <&tlmm 20 0x00>;
 	qcom,ap2mdm-errfatal-gpio = <&tlmm 23 0x00>;
 	qcom,mdm2ap-status-gpio   = <&tlmm 22 0x00>;
 	qcom,ap2mdm-status-gpio   = <&tlmm 21 0x00>;
diff --git a/arch/arm64/boot/dts/qcom/sda845-svr.dtsi b/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
index 51dbe74..ce62781 100644
--- a/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
@@ -325,7 +325,7 @@
 };
 
 &adsp_mem {
-	size = <0 0xc800000>;
+	size = <0 0x12c00000>;
 };
 
 &qupv3_se9_2uart {
diff --git a/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi b/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi
index d2a8f3e..80f7007 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi
@@ -13,16 +13,13 @@
 
 / {
 	/delete-node/ cpus;
+	/delete-node/ energy-costs;
 
 	cpus {
 		#address-cells = <1>;
 		#size-cells = <0>;
 		cpu-map {
-
 			cluster0 {
-			};
-
-			cluster1 {
 				core0 {
 					cpu = <&CPU0>;
 				};
@@ -44,6 +41,8 @@
 			reg = <0x100>;
 			enable-method = "psci";
 			cpu-release-addr = <0x0 0x90000000>;
+			efficiency = <1024>;
+			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_1>;
 			#cooling-cells = <2>;
 			L2_1: l2-cache {
@@ -68,6 +67,8 @@
 			reg = <0x101>;
 			enable-method = "psci";
 			cpu-release-addr = <0x0 0x90000000>;
+			efficiency = <1024>;
+			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_1>;
 			#cooling-cells = <2>;
 			L1_I_101: l1-icache {
@@ -86,6 +87,8 @@
 			reg = <0x102>;
 			enable-method = "psci";
 			cpu-release-addr = <0x0 0x90000000>;
+			efficiency = <1024>;
+			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_1>;
 			#cooling-cells = <2>;
 			L1_I_102: l1-icache {
@@ -104,6 +107,8 @@
 			reg = <0x103>;
 			enable-method = "psci";
 			cpu-release-addr = <0x0 0x90000000>;
+			efficiency = <1024>;
+			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_1>;
 			#cooling-cells = <2>;
 			L1_I_103: l1-icache {
@@ -118,4 +123,34 @@
 
 	};
 
+	energy_costs: energy-costs {
+		compatible = "sched-energy";
+
+		CPU_COST_0: core-cost0 {
+			busy-cost-data = <
+				 800000	137
+				1001600	165
+				1305600	207
+				1497600	256
+				1708800	327
+				1958400	445
+			>;
+			idle-cost-data = <
+				100 80 60 40
+			>;
+		};
+		CLUSTER_COST_0: cluster-cost0 {
+			busy-cost-data = <
+				 800000	49
+				1001600	53
+				1305600	61
+				1497600	71
+				1708800	85
+				1958400	110
+			>;
+			idle-cost-data = <
+				4 3 2 1
+			>;
+		};
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm429.dtsi b/arch/arm64/boot/dts/qcom/sdm429.dtsi
index f31eb6e..a4d2a80 100644
--- a/arch/arm64/boot/dts/qcom/sdm429.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429.dtsi
@@ -20,8 +20,6 @@
 };
 
 &soc {
-	/delete-node/ qcom,spm@b1d2000;
-	/delete-node/ qcom,lpm-levels;
 	/delete-node/ etm@619c000;
 	/delete-node/ etm@619d000;
 	/delete-node/ etm@619e000;
@@ -30,6 +28,16 @@
 	/delete-node/ cti@61b9000;
 	/delete-node/ cti@61ba000;
 	/delete-node/ cti@61bb000;
+
+	qcom,spm@b1d2000 {
+		qcom,cpu-vctl-list = <&CPU0 &CPU1 &CPU2 &CPU3>;
+	};
+
+	qcom,lpm-levels {
+		qcom,pm-cluster@0 {
+			/delete-node/qcom,pm-cluster@1;
+		};
+	};
 };
 
 &funnel_apss {
diff --git a/arch/arm64/boot/dts/qcom/sdm439-audio.dtsi b/arch/arm64/boot/dts/qcom/sdm439-audio.dtsi
index fae43ba..f6751d2 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-audio.dtsi
@@ -13,6 +13,7 @@
 
 &soc {
 	int_codec: sound {
+		qcom,model = "sdm439-snd-card-mtp";
 		qcom,msm-hs-micbias-type = "internal";
 
 		asoc-codec = <&stub_codec>, <&msm_digital_codec>,
diff --git a/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi
similarity index 72%
rename from arch/arm64/boot/dts/qcom/sdm632-camera-sensor-mtp.dtsi
rename to arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi
index 07b3811..5e2c740 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -28,7 +28,7 @@
 		cell-index = <1>;
 		reg = <0x1>;
 		compatible = "qcom,actuator";
-		qcom,cci-master = <1>;
+		qcom,cci-master = <0>;
 		cam_vaf-supply = <&pm8953_l17>;
 		qcom,cam-vreg-name = "cam_vaf";
 		qcom,cam-vreg-min-voltage = <2850000>;
@@ -41,35 +41,35 @@
 		compatible = "qcom,eeprom";
 		qcom,cci-master = <0>;
 		reg = <0x0>;
+		cam_vana-supply = <&pm8953_l22>;
 		cam_vio-supply = <&pm8953_l6>;
-		cam_vdig-supply = <&pm8953_l23>;
 		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-op-mode = <0 105000 100000>;
+		cam_vdig-supply = <&pm8953_l3>;
+		qcom,cam-vreg-name = "cam_vana",
+			"cam_vio", "cam_vdig", "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000 0 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <2800000 0 1200000 2850000>;
+		qcom,cam-vreg-op-mode = <80000 0 200000 100000>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_default
-				&cam_sensor_rear_default
-				&cam_sensor_rear_vana>;
-		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
-				&cam_sensor_rear_vana_sleep>;
+				&cam_sensor_rear_reset
+			&cam_sensor_rear_vana>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep
+			&cam_sensor_rear_reset_sleep
+			&cam_sensor_rear_vana_sleep>;
 		gpios = <&tlmm 26 0>,
-			<&tlmm 40 0>,
-			<&tlmm 39 0>,
-			<&tlmm 134 0>;
+			<&tlmm 36 0>,
+			<&tlmm 35 0>;
 		qcom,gpio-reset = <1>;
-		qcom,gpio-standby = <2>;
-		qcom,gpio-vana = <3>;
-		qcom,gpio-req-tbl-num = <0 1 2 3>;
-		qcom,gpio-req-tbl-flags = <1 0 0 0>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
 		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
 			"CAM_RESET0",
-			"CAM_STANDBY0",
 			"CAM_VANA";
 		status = "ok";
 		clocks = <&clock_gcc clk_mclk0_clk_src>,
-				<&clock_gcc clk_gcc_camss_mclk0_clk>;
+			<&clock_gcc clk_gcc_camss_mclk0_clk>;
 		clock-names = "cam_src_clk", "cam_clk";
 		qcom,clock-rates = <19200000 0>;
 	};
@@ -126,12 +126,12 @@
 		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk1_default
+		pinctrl-0 = <&cam_sensor_mclk2_default
 			&cam_sensor_front1_default>;
-		pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>;
-		gpios = <&tlmm 27 0>,
-			<&tlmm 129 0>,
-			<&tlmm 130 0>;
+		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>;
@@ -148,44 +148,8 @@
 		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_mclk1_clk_src>,
-			<&clock_gcc clk_gcc_camss_mclk1_clk>;
-		clock-names = "cam_src_clk", "cam_clk";
-		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_l23>;
-		cam_vana-supply = <&pm8953_l22>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
-					"cam_vaf";
-		qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
-		qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
-		qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
-		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk2_default
-				&cam_sensor_front_default>;
-		pinctrl-1 = <&cam_sensor_mclk2_sleep
-				&cam_sensor_front_sleep>;
-		gpios = <&tlmm 28 0>,
-			<&tlmm 131 0>,
-			<&tlmm 132 0>;
-		qcom,gpio-reset = <1>;
-		qcom,gpio-standby = <2>;
-		qcom,gpio-req-tbl-num = <0 1 2>;
-		qcom,gpio-req-tbl-flags = <1 0 0>;
-		qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
-			"CAM_RESET1",
-			"CAM_STANDBY1";
-		status = "ok";
 		clocks = <&clock_gcc clk_mclk2_clk_src>,
-				<&clock_gcc clk_gcc_camss_mclk2_clk>;
+			<&clock_gcc clk_gcc_camss_mclk2_clk>;
 		clock-names = "cam_src_clk", "cam_clk";
 		qcom,clock-rates = <19200000 0>;
 	};
@@ -200,33 +164,31 @@
 		qcom,led-flash-src = <&led_flash0>;
 		qcom,eeprom-src = <&eeprom0>;
 		qcom,actuator-src = <&actuator0>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vdig-supply = <&pm8953_l23>;
-		cam_vaf-supply = <&pm8953_l17>;
 		cam_vana-supply = <&pm8953_l22>;
-		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf",
-						"cam_vana";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000 2800000>;
-		qcom,cam-vreg-op-mode = <0 105000 100000 80000>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vaf-supply = <&pm8953_l17>;
+		cam_vdig-supply = <&pm8953_l3>;
+		qcom,cam-vreg-name = "cam_vana",
+			"cam_vio", "cam_vdig", "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000 0 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <2800000 0 1200000 2850000>;
+		qcom,cam-vreg-op-mode = <80000 0 200000 100000>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_default
-				&cam_sensor_rear_default
+				&cam_sensor_rear_reset
 				&cam_sensor_rear_vana>;
-		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
+		pinctrl-1 = <&cam_sensor_mclk0_sleep
+				&cam_sensor_rear_reset_sleep
 				&cam_sensor_rear_vana_sleep>;
 		gpios = <&tlmm 26 0>,
-			<&tlmm 40 0>,
-			<&tlmm 39 0>,
-			<&tlmm 134 0>;
+			<&tlmm 36 0>,
+			<&tlmm 35 0>;
 		qcom,gpio-reset = <1>;
-		qcom,gpio-standby = <2>;
-		qcom,gpio-vana = <3>;
-		qcom,gpio-req-tbl-num = <0 1 2 3>;
-		qcom,gpio-req-tbl-flags = <1 0 0 0>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
 		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
 			"CAM_RESET0",
-			"CAM_STANDBY0",
 			"CAM_VANA";
 		qcom,sensor-position = <0>;
 		qcom,sensor-mode = <0>;
@@ -245,9 +207,7 @@
 		qcom,csiphy-sd-index = <1>;
 		qcom,csid-sd-index = <1>;
 		qcom,mount-angle = <90>;
-		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>;
@@ -257,13 +217,13 @@
 		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_mclk2_default
+		pinctrl-0 = <&cam_sensor_mclk1_default
 				&cam_sensor_front_default>;
-		pinctrl-1 = <&cam_sensor_mclk2_sleep
+		pinctrl-1 = <&cam_sensor_mclk1_sleep
 				&cam_sensor_front_sleep>;
-		gpios = <&tlmm 28 0>,
-			<&tlmm 131 0>,
-			<&tlmm 132 0>;
+		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>;
@@ -274,9 +234,8 @@
 		qcom,sensor-position = <0x100>;
 		qcom,sensor-mode = <1>;
 		qcom,cci-master = <1>;
-		status = "ok";
-		clocks = <&clock_gcc clk_mclk2_clk_src>,
-				<&clock_gcc clk_gcc_camss_mclk2_clk>;
+		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>;
 	};
@@ -285,29 +244,29 @@
 		cell-index = <2>;
 		compatible = "qcom,camera";
 		reg = <0x02>;
-		qcom,csiphy-sd-index = <2>;
-		qcom,csid-sd-index = <2>;
+		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 = <&pm8953_l23>;
-		cam_vio-supply = <&pm8953_l6>;
 		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 = <1175000 0 2800000 2850000>;
-		qcom,cam-vreg-max-voltage = <1175000 0 2800000 2850000>;
+		qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
 		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk1_default
+		pinctrl-0 = <&cam_sensor_mclk2_default
 				&cam_sensor_front1_default>;
-		pinctrl-1 = <&cam_sensor_mclk1_sleep
+		pinctrl-1 = <&cam_sensor_mclk2_sleep
 				&cam_sensor_front1_sleep>;
-		gpios = <&tlmm 27 0>,
-			<&tlmm 129 0>,
-			<&tlmm 130 0>;
+		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>;
@@ -317,10 +276,10 @@
 					  "CAM_STANDBY2";
 		qcom,sensor-position = <1>;
 		qcom,sensor-mode = <0>;
-		qcom,cci-master = <1>;
+		qcom,cci-master = <0>;
 		status = "ok";
-		clocks = <&clock_gcc clk_mclk1_clk_src>,
-			<&clock_gcc clk_gcc_camss_mclk1_clk>;
+		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/sdm632-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi
similarity index 72%
copy from arch/arm64/boot/dts/qcom/sdm632-camera-sensor-mtp.dtsi
copy to arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi
index 07b3811..5e2c740 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -28,7 +28,7 @@
 		cell-index = <1>;
 		reg = <0x1>;
 		compatible = "qcom,actuator";
-		qcom,cci-master = <1>;
+		qcom,cci-master = <0>;
 		cam_vaf-supply = <&pm8953_l17>;
 		qcom,cam-vreg-name = "cam_vaf";
 		qcom,cam-vreg-min-voltage = <2850000>;
@@ -41,35 +41,35 @@
 		compatible = "qcom,eeprom";
 		qcom,cci-master = <0>;
 		reg = <0x0>;
+		cam_vana-supply = <&pm8953_l22>;
 		cam_vio-supply = <&pm8953_l6>;
-		cam_vdig-supply = <&pm8953_l23>;
 		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-op-mode = <0 105000 100000>;
+		cam_vdig-supply = <&pm8953_l3>;
+		qcom,cam-vreg-name = "cam_vana",
+			"cam_vio", "cam_vdig", "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000 0 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <2800000 0 1200000 2850000>;
+		qcom,cam-vreg-op-mode = <80000 0 200000 100000>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_default
-				&cam_sensor_rear_default
-				&cam_sensor_rear_vana>;
-		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
-				&cam_sensor_rear_vana_sleep>;
+				&cam_sensor_rear_reset
+			&cam_sensor_rear_vana>;
+		pinctrl-1 = <&cam_sensor_mclk0_sleep
+			&cam_sensor_rear_reset_sleep
+			&cam_sensor_rear_vana_sleep>;
 		gpios = <&tlmm 26 0>,
-			<&tlmm 40 0>,
-			<&tlmm 39 0>,
-			<&tlmm 134 0>;
+			<&tlmm 36 0>,
+			<&tlmm 35 0>;
 		qcom,gpio-reset = <1>;
-		qcom,gpio-standby = <2>;
-		qcom,gpio-vana = <3>;
-		qcom,gpio-req-tbl-num = <0 1 2 3>;
-		qcom,gpio-req-tbl-flags = <1 0 0 0>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
 		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
 			"CAM_RESET0",
-			"CAM_STANDBY0",
 			"CAM_VANA";
 		status = "ok";
 		clocks = <&clock_gcc clk_mclk0_clk_src>,
-				<&clock_gcc clk_gcc_camss_mclk0_clk>;
+			<&clock_gcc clk_gcc_camss_mclk0_clk>;
 		clock-names = "cam_src_clk", "cam_clk";
 		qcom,clock-rates = <19200000 0>;
 	};
@@ -126,12 +126,12 @@
 		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk1_default
+		pinctrl-0 = <&cam_sensor_mclk2_default
 			&cam_sensor_front1_default>;
-		pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>;
-		gpios = <&tlmm 27 0>,
-			<&tlmm 129 0>,
-			<&tlmm 130 0>;
+		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>;
@@ -148,44 +148,8 @@
 		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_mclk1_clk_src>,
-			<&clock_gcc clk_gcc_camss_mclk1_clk>;
-		clock-names = "cam_src_clk", "cam_clk";
-		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_l23>;
-		cam_vana-supply = <&pm8953_l22>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
-					"cam_vaf";
-		qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
-		qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
-		qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
-		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk2_default
-				&cam_sensor_front_default>;
-		pinctrl-1 = <&cam_sensor_mclk2_sleep
-				&cam_sensor_front_sleep>;
-		gpios = <&tlmm 28 0>,
-			<&tlmm 131 0>,
-			<&tlmm 132 0>;
-		qcom,gpio-reset = <1>;
-		qcom,gpio-standby = <2>;
-		qcom,gpio-req-tbl-num = <0 1 2>;
-		qcom,gpio-req-tbl-flags = <1 0 0>;
-		qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
-			"CAM_RESET1",
-			"CAM_STANDBY1";
-		status = "ok";
 		clocks = <&clock_gcc clk_mclk2_clk_src>,
-				<&clock_gcc clk_gcc_camss_mclk2_clk>;
+			<&clock_gcc clk_gcc_camss_mclk2_clk>;
 		clock-names = "cam_src_clk", "cam_clk";
 		qcom,clock-rates = <19200000 0>;
 	};
@@ -200,33 +164,31 @@
 		qcom,led-flash-src = <&led_flash0>;
 		qcom,eeprom-src = <&eeprom0>;
 		qcom,actuator-src = <&actuator0>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vdig-supply = <&pm8953_l23>;
-		cam_vaf-supply = <&pm8953_l17>;
 		cam_vana-supply = <&pm8953_l22>;
-		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf",
-						"cam_vana";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000 2800000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000 2800000>;
-		qcom,cam-vreg-op-mode = <0 105000 100000 80000>;
+		cam_vio-supply = <&pm8953_l6>;
+		cam_vaf-supply = <&pm8953_l17>;
+		cam_vdig-supply = <&pm8953_l3>;
+		qcom,cam-vreg-name = "cam_vana",
+			"cam_vio", "cam_vdig", "cam_vaf";
+		qcom,cam-vreg-min-voltage = <2800000 0 1200000 2850000>;
+		qcom,cam-vreg-max-voltage = <2800000 0 1200000 2850000>;
+		qcom,cam-vreg-op-mode = <80000 0 200000 100000>;
 		pinctrl-names = "cam_default", "cam_suspend";
 		pinctrl-0 = <&cam_sensor_mclk0_default
-				&cam_sensor_rear_default
+				&cam_sensor_rear_reset
 				&cam_sensor_rear_vana>;
-		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
+		pinctrl-1 = <&cam_sensor_mclk0_sleep
+				&cam_sensor_rear_reset_sleep
 				&cam_sensor_rear_vana_sleep>;
 		gpios = <&tlmm 26 0>,
-			<&tlmm 40 0>,
-			<&tlmm 39 0>,
-			<&tlmm 134 0>;
+			<&tlmm 36 0>,
+			<&tlmm 35 0>;
 		qcom,gpio-reset = <1>;
-		qcom,gpio-standby = <2>;
-		qcom,gpio-vana = <3>;
-		qcom,gpio-req-tbl-num = <0 1 2 3>;
-		qcom,gpio-req-tbl-flags = <1 0 0 0>;
+		qcom,gpio-vana = <2>;
+		qcom,gpio-req-tbl-num = <0 1 2>;
+		qcom,gpio-req-tbl-flags = <1 0 0>;
 		qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
 			"CAM_RESET0",
-			"CAM_STANDBY0",
 			"CAM_VANA";
 		qcom,sensor-position = <0>;
 		qcom,sensor-mode = <0>;
@@ -245,9 +207,7 @@
 		qcom,csiphy-sd-index = <1>;
 		qcom,csid-sd-index = <1>;
 		qcom,mount-angle = <90>;
-		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>;
@@ -257,13 +217,13 @@
 		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_mclk2_default
+		pinctrl-0 = <&cam_sensor_mclk1_default
 				&cam_sensor_front_default>;
-		pinctrl-1 = <&cam_sensor_mclk2_sleep
+		pinctrl-1 = <&cam_sensor_mclk1_sleep
 				&cam_sensor_front_sleep>;
-		gpios = <&tlmm 28 0>,
-			<&tlmm 131 0>,
-			<&tlmm 132 0>;
+		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>;
@@ -274,9 +234,8 @@
 		qcom,sensor-position = <0x100>;
 		qcom,sensor-mode = <1>;
 		qcom,cci-master = <1>;
-		status = "ok";
-		clocks = <&clock_gcc clk_mclk2_clk_src>,
-				<&clock_gcc clk_gcc_camss_mclk2_clk>;
+		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>;
 	};
@@ -285,29 +244,29 @@
 		cell-index = <2>;
 		compatible = "qcom,camera";
 		reg = <0x02>;
-		qcom,csiphy-sd-index = <2>;
-		qcom,csid-sd-index = <2>;
+		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 = <&pm8953_l23>;
-		cam_vio-supply = <&pm8953_l6>;
 		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 = <1175000 0 2800000 2850000>;
-		qcom,cam-vreg-max-voltage = <1175000 0 2800000 2850000>;
+		qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+		qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
 		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
 		qcom,gpio-no-mux = <0>;
 		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk1_default
+		pinctrl-0 = <&cam_sensor_mclk2_default
 				&cam_sensor_front1_default>;
-		pinctrl-1 = <&cam_sensor_mclk1_sleep
+		pinctrl-1 = <&cam_sensor_mclk2_sleep
 				&cam_sensor_front1_sleep>;
-		gpios = <&tlmm 27 0>,
-			<&tlmm 129 0>,
-			<&tlmm 130 0>;
+		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>;
@@ -317,10 +276,10 @@
 					  "CAM_STANDBY2";
 		qcom,sensor-position = <1>;
 		qcom,sensor-mode = <0>;
-		qcom,cci-master = <1>;
+		qcom,cci-master = <0>;
 		status = "ok";
-		clocks = <&clock_gcc clk_mclk1_clk_src>,
-			<&clock_gcc clk_gcc_camss_mclk1_clk>;
+		clocks = <&clock_gcc clk_mclk2_clk_src>,
+			<&clock_gcc clk_gcc_camss_mclk2_clk>;
 		clock-names = "cam_src_clk", "cam_clk";
 		qcom,clock-rates = <24000000 0>;
 	};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
index 5512297..83a4651 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
@@ -11,6 +11,8 @@
  * GNU General Public License for more details.
  */
 
+#include "sdm439-camera-sensor-cdp.dtsi"
+
 &blsp1_uart2 {
 	status = "ok";
 };
@@ -63,3 +65,106 @@
 
 	status = "ok";
 };
+
+&soc {
+	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;
+		};
+	};
+};
+
+&pm8953_gpios {
+	bklt_en {
+		bklt_en_default: bklt_en_default {
+		pins = "gpio4";
+		function = "normal";
+		power-source = <0>;
+		output-high;
+		};
+	};
+};
+
+&pm8953_pwm {
+	status = "ok";
+};
+
+#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_hx8399c_truly_vid>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_dsi_active &mdss_te_active &bklt_en_default>;
+	pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+
+	qcom,platform-bklight-en-gpio = <&pm8953_gpios 4 0>;
+	qcom,platform-te-gpio = <&tlmm 24 0>;
+	qcom,platform-reset-gpio = <&tlmm 61 0>;
+	lab-supply = <&lcdb_ldo_vreg>;
+	ibb-supply = <&lcdb_ncp_vreg>;
+
+};
+
+&dsi_hx8399c_truly_vid {
+	qcom,mdss-dsi-panel-timings =
+		[f3 3a 26 00 6c 6e 2c 3e 2f 03 04 00];
+	qcom,mdss-dsi-t-clk-post = <0x02>;
+	qcom,mdss-dsi-t-clk-pre = <0x2d>;
+	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>;
+	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+	qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
+	qcom,mdss-dsi-pan-enable-dynamic-fps;
+	qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
+};
+
+
+&dsi_hx8399c_hd_vid {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-pan-enable-dynamic-fps;
+	qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+	qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
+	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
+	qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
index 5512297..17218a8 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
@@ -11,6 +11,8 @@
  * GNU General Public License for more details.
  */
 
+#include "sdm439-camera-sensor-mtp.dtsi"
+
 &blsp1_uart2 {
 	status = "ok";
 };
@@ -63,3 +65,105 @@
 
 	status = "ok";
 };
+
+&soc {
+	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"
+
+&pm8953_gpios {
+	bklt_en {
+		bklt_en_default: bklt_en_default {
+		pins = "gpio4";
+		function = "normal";
+		power-source = <0>;
+		output-high;
+		};
+	};
+};
+
+&pm8953_pwm {
+	status = "ok";
+};
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+	hw-config = "single_dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_hx8399c_truly_vid>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_dsi_active &mdss_te_active &bklt_en_default>;
+	pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+
+	qcom,platform-bklight-en-gpio = <&pm8953_gpios 4 0>;
+	qcom,platform-te-gpio = <&tlmm 24 0>;
+	qcom,platform-reset-gpio = <&tlmm 61 0>;
+	lab-supply = <&lcdb_ldo_vreg>;
+	ibb-supply = <&lcdb_ncp_vreg>;
+
+};
+
+&dsi_hx8399c_truly_vid {
+	qcom,mdss-dsi-panel-timings =
+		[f3 3a 26 00 6c 6e 2c 3e 2f 03 04 00];
+	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>;
+	qcom,mdss-dsi-pan-enable-dynamic-fps;
+	qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
+};
+
+&dsi_hx8399c_hd_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";
+	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>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi b/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi
index 289d5bf..3c8a298 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi
@@ -82,6 +82,11 @@
 		/delete-property/ vdd_sr2_pll-supply;
 		/delete-property/ vdd_hf_dig-supply;
 		/delete-property/ vdd_hf_pll-supply;
+		vdd_dig-supply = <&pm8953_s2_level>;
+		vdd_sr2_dig-supply = <&pm8953_s2_level_ao>;
+		vdd_sr2_pll-supply = <&pm8953_l7_ao>;
+		vdd_hf_dig-supply = <&pm8953_s2_level_ao>;
+		vdd_hf_pll-supply = <&pm8953_l7_ao>;
 	};
 
 	qcom,cpu-clock-8939@b111050 {
@@ -120,8 +125,8 @@
 };
 
 &mdss_dsi {
-	/delete-property/ vdda-supply;
-	/delete-property/ vddio-supply;
+	vdda-supply = <&pm8953_l2>; /*1.2V*/
+	vddio-supply = <&pm8953_l6>; /*1.8V*/
 };
 
 &usb_otg {
@@ -132,21 +137,22 @@
 };
 
 &mdss_dsi0_pll {
-	/delete-property/ vddio-supply;
+	vddio-supply = <&pm8953_l6>;
 };
 
 &mdss_dsi1_pll {
-	/delete-property/ vddio-supply;
+	vddio-supply = <&pm8953_l6>;
 };
 
 &mdss_dsi0 {
-	/delete-property/ vdd-supply;
-	/delete-property/ vddio-supply;
+	vdd-supply = <&pm8953_l17>;
+	vddio-supply = <&pm8953_l6>;
 };
 
 &mdss_dsi1 {
-	/delete-property/ vdd-supply;
-	/delete-property/ vddio-supply;
+	status = "disabled";
+	vdd-supply = <&pm8953_l17>;
+	vddio-supply = <&pm8953_l6>;
 };
 
 &int_codec {
@@ -251,3 +257,43 @@
 		};
 	};
 };
+
+&pm8953_vadc {
+	pinctrl-0 = <&pa_therm1_default>;
+	/delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+	/delete-node/ case_therm;
+};
+
+&pil_mss {
+	vdd_mss-supply = <&pm8953_s1>;
+	vdd_cx-supply = <&pm8953_s2_level>;
+	vdd_cx-voltage = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+	vdd_mx-supply = <&pm8953_s7_level_ao>;
+	vdd_mx-uV = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+	vdd_pll-supply = <&pm8953_l7>;
+};
+
+&soc {
+	qcom,lpass@c200000 {
+		vdd_cx-supply = <&pm8953_s2_level>;
+	};
+
+	qcom,pronto@a21b000 {
+		vdd_pronto_pll-supply = <&pm8953_l7>;
+	};
+
+	qcom,wcnss-wlan@0a000000 {
+		qcom,pronto-vddmx-supply = <&pm8953_s7_level_ao>;
+		qcom,pronto-vddcx-supply = <&pm8953_s2_level>;
+		qcom,pronto-vddpx-supply = <&pm8953_l5>;
+		qcom,iris-vddxo-supply   = <&pm8953_l7>;
+		qcom,iris-vddrfa-supply  = <&pm8953_l19>;
+		qcom,iris-vddpa-supply   = <&pm8953_l9>;
+		qcom,iris-vdddig-supply  = <&pm8953_l5>;
+		qcom,wcnss-adc_tm = <&pm8953_adc_tm>;
+	};
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
index 5512297..24748dd 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
@@ -40,6 +40,24 @@
 	status = "ok";
 };
 
+&int_codec {
+	status = "okay";
+	qcom,model = "sdm439-sku1-snd-card";
+	qcom,msm-micbias1-ext-cap;
+	qcom,msm-micbias2-ext-cap;
+	qcom,msm-mbhc-hphl-swh = <1>;
+	qcom,msm-mbhc-gnd-swh = <0>;
+	qcom,msm-hs-micbias-type = "external";
+};
+
+&wsa881x_i2c_f {
+	status = "okay";
+};
+
+&wsa881x_i2c_45 {
+	status = "okay";
+};
+
 &sdhc_2 {
 	/* device core power supply */
 	vdd-supply = <&pm8953_l11>;
@@ -63,3 +81,22 @@
 
 	status = "ok";
 };
+
+&soc {
+	gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "gpio-keys";
+		pinctrl-names = "default";
+		pinctrl-0 = <&gpio_key_active>;
+
+		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;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
index f9bef43..08c9e4f 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
@@ -174,7 +174,7 @@
 		qcom,hpm-min-load = <10000>;
 		status = "okay";
 		pm8953_l4: regulator-l4 {
-			compatible = "qcom,rpm-smd-regulator-resource";
+			compatible = "qcom,rpm-smd-regulator";
 			regulator-name = "pm8953_l4";
 			qcom,set = <3>;
 			regulator-min-microvolt = <1800000>;
@@ -291,7 +291,7 @@
 		qcom,hpm-min-load = <5000>;
 		status = "okay";
 		pm8953_l14: regulator-l14 {
-			compatible = "qcom,rpm-smd-regulator-resource";
+			compatible = "qcom,rpm-smd-regulator";
 			regulator-name = "pm8953_l14";
 			qcom,set = <3>;
 			regulator-min-microvolt = <1800000>;
@@ -309,7 +309,7 @@
 		qcom,hpm-min-load = <5000>;
 		status = "okay";
 		pm8953_l15: regulator-l15 {
-			compatible = "qcom,rpm-smd-regulator-resource";
+			compatible = "qcom,rpm-smd-regulator";
 			regulator-name = "pm8953_l15";
 			qcom,set = <3>;
 			regulator-min-microvolt = <1800000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm439.dtsi b/arch/arm64/boot/dts/qcom/sdm439.dtsi
index 13bcf1b..422a95f 100644
--- a/arch/arm64/boot/dts/qcom/sdm439.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439.dtsi
@@ -32,3 +32,58 @@
 		/delete-property/ qcom,mipi-csi-vdd-supply;
 	};
 };
+
+&energy_costs {
+	compatible = "sched-energy";
+
+	CPU_COST_0: core-cost0 {
+		busy-cost-data = <
+			8000000	137
+			1001600	165
+			1305600	207
+			1497600	256
+			1708800	327
+			1958400	445
+		>;
+		idle-cost-data = <
+			100 80 60 40
+		>;
+	};
+	CPU_COST_1: core-cost1 {
+		busy-cost-data = <
+			8000000	45
+			1001600	56
+			1171200	71
+			1305600	89
+			1459200	120
+		>;
+		idle-cost-data = <
+			40 20 10 8
+		>;
+	};
+	CLUSTER_COST_0: cluster-cost0 {
+			busy-cost-data = <
+			8000000	49
+			1001600	53
+			1305600	61
+			1497600	71
+			1708800	85
+			1958400	110
+		>;
+		idle-cost-data = <
+			4 3 2 1
+		>;
+	};
+	CLUSTER_COST_1: cluster-cost1 {
+			busy-cost-data = <
+			8000000	9
+			1001600	10
+			1171200	13
+			1305600	15
+			1459200	20
+		>;
+		idle-cost-data = <
+			4 3 2 1
+		>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-cdp.dts b/arch/arm64/boot/dts/qcom/sdm450-cdp.dts
index 0458650..c55622a 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-cdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-cdp.dts
@@ -17,7 +17,6 @@
 #include "pmi8950.dtsi"
 #include "msm8953-cdp.dtsi"
 #include "msm8953-pmi8950.dtsi"
-#include "msm8953-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM450 + PMI8950 CDP";
diff --git a/arch/arm64/boot/dts/qcom/sdm450-mtp.dts b/arch/arm64/boot/dts/qcom/sdm450-mtp.dts
index f097895..5744390 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-mtp.dts
@@ -17,7 +17,6 @@
 #include "pmi8950.dtsi"
 #include "msm8953-mtp.dtsi"
 #include "msm8953-pmi8950.dtsi"
-#include "msm8953-camera-sensor-mtp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM450 + PMI8950 MTP";
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dts b/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dts
index 004186b6be..692da7f 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dts
@@ -16,7 +16,6 @@
 #include "sdm450.dtsi"
 #include "sdm450-pmi632-cdp-s2.dtsi"
 #include "sdm450-pmi632.dtsi"
-#include "sdm632-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM450 + PMI632 CDP S2";
@@ -25,3 +24,16 @@
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
 
+&pm8953_vadc {
+	pinctrl-0 = <&pa_therm1_default>;
+	/delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+	/delete-node/ case_therm;
+};
+
+&thermal_zones {
+	/delete-node/ case-therm-adc;
+	/delete-node/ case-therm-step;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dtsi b/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dtsi
index d8a0e9d..ae8e473 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dtsi
@@ -13,6 +13,14 @@
 
 #include "msm8953-cdp.dtsi"
 
+&eeprom0 {
+	cam_vdig-supply = <&pm8953_l23>;
+};
+
+&camera0 {
+	cam_vdig-supply = <&pm8953_l23>;
+};
+
 &mdss_dsi0 {
 	qcom,dsi-pref-prim-pan = <&dsi_hx8399c_truly_vid>;
 	pinctrl-names = "mdss_default", "mdss_sleep";
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dts b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dts
index 1a2309f..02bf751 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dts
@@ -16,7 +16,6 @@
 #include "sdm450.dtsi"
 #include "sdm450-pmi632-mtp-s3.dtsi"
 #include "sdm450-pmi632.dtsi"
-#include "sdm632-camera-sensor-mtp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM450 + PMI632 MTP S3";
@@ -25,3 +24,16 @@
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
 
+&pm8953_vadc {
+	pinctrl-0 = <&pa_therm1_default>;
+	/delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+	/delete-node/ case_therm;
+};
+
+&thermal_zones {
+	/delete-node/ case-therm-adc;
+	/delete-node/ case-therm-step;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
index 129d507..64d9e64 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
@@ -13,6 +13,14 @@
 
 #include "msm8953-mtp.dtsi"
 
+&eeprom0 {
+	cam_vdig-supply = <&pm8953_l23>;
+};
+
+&camera0 {
+	cam_vdig-supply = <&pm8953_l23>;
+};
+
 &mdss_dsi0 {
 	qcom,dsi-pref-prim-pan = <&dsi_hx8399c_truly_vid>;
 	pinctrl-names = "mdss_default", "mdss_sleep";
diff --git a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dts b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dts
index 1dc8874..b0cb955 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dts
@@ -16,7 +16,6 @@
 #include "sdm450.dtsi"
 #include "sdm450-qrd-sku4.dtsi"
 #include "sdm450-pmi632.dtsi"
-#include "msm8953-camera-sensor-qrd.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM450 + PMI632 QRD SKU4";
@@ -30,3 +29,17 @@
 		qcom,scale-function = <22>;
 	};
 };
+
+&pm8953_vadc {
+	pinctrl-0 = <&pa_therm1_default>;
+	/delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+	/delete-node/ case_therm;
+};
+
+&thermal_zones {
+	/delete-node/ case-therm-adc;
+	/delete-node/ case-therm-step;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
index 4a63f9e..bdefdc9 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
@@ -13,6 +13,7 @@
 
 #include "msm8953-qrd.dtsi"
 #include "msm8953-mdss-panels.dtsi"
+#include "msm8953-camera-sensor-qrd.dtsi"
 
 &qusb_phy {
 	qcom,qusb-phy-init-seq = <0x78 0x80
diff --git a/arch/arm64/boot/dts/qcom/sdm450.dtsi b/arch/arm64/boot/dts/qcom/sdm450.dtsi
index 38eacd1..1d2abd7c 100644
--- a/arch/arm64/boot/dts/qcom/sdm450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450.dtsi
@@ -128,6 +128,7 @@
 			qcom,gpu-freq = <19200000>;
 			qcom,bus-freq = <0>;
 			qcom,bus-min = <0>;
+			qcom,bus-max = <0>;
 		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-cdp.dtsi
deleted file mode 100644
index e9295ad..0000000
--- a/arch/arm64/boot/dts/qcom/sdm632-camera-sensor-cdp.dtsi
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-&cci {
-	actuator0: qcom,actuator@0 {
-		cell-index = <0>;
-		reg = <0x0>;
-		compatible = "qcom,actuator";
-		qcom,cci-master = <0>;
-		cam_vaf-supply = <&pm8953_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 = <1>;
-		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vaf";
-		qcom,cam-vreg-min-voltage = <2850000>;
-		qcom,cam-vreg-max-voltage = <2850000>;
-		qcom,cam-vreg-op-mode = <80000>;
-	};
-
-	eeprom0: qcom,eeprom@0 {
-		cell-index = <0>;
-		compatible = "qcom,eeprom";
-		qcom,cci-master = <0>;
-		reg = <0x0>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vdig-supply = <&pm8953_l23>;
-		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-op-mode = <0 105000 100000>;
-		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk0_default
-				&cam_sensor_rear_default
-				&cam_sensor_rear_vana>;
-		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
-				&cam_sensor_rear_vana_sleep>;
-		gpios = <&tlmm 26 0>,
-			<&tlmm 40 0>,
-			<&tlmm 39 0>,
-			<&tlmm 134 0>;
-		qcom,gpio-reset = <1>;
-		qcom,gpio-standby = <2>;
-		qcom,gpio-vana = <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_VANA";
-		status = "ok";
-		clocks = <&clock_gcc clk_mclk0_clk_src>,
-				<&clock_gcc clk_gcc_camss_mclk0_clk>;
-		clock-names = "cam_src_clk", "cam_clk";
-		qcom,clock-rates = <19200000 0>;
-	};
-
-	eeprom1: qcom,eeprom@1 {
-		cell-index = <1>;
-		reg = <0x1>;
-		qcom,eeprom-name = "sunny_8865";
-		compatible = "qcom,eeprom";
-		qcom,slave-addr = <0x6c>;
-		qcom,cci-master = <0>;
-		qcom,num-blocks = <8>;
-
-		qcom,page0 = <1 0x0100 2 0x01 1 1>;
-		qcom,poll0 = <0 0x0 2 0x0 1 0>;
-		qcom,mem0 = <0 0x0 2 0x0 1 0>;
-
-		qcom,page1 = <1 0x5002 2 0x00 1 0>;
-		qcom,poll1 = <0 0x0 2 0x0 1 0>;
-		qcom,mem1 = <0 0x0 2 0x0 1 0>;
-
-		qcom,page2 = <1 0x3d84 2 0xc0 1 0>;
-		qcom,poll2 = <0 0x0 2 0x0 1 0>;
-		qcom,mem2 = <0 0x0 2 0x0 1 0>;
-
-		qcom,page3 = <1 0x3d88 2 0x70 1 0>;
-		qcom,poll3 = <0 0x0 2 0x0 1 0>;
-		qcom,mem3 = <0 0x0 2 0x0 1 0>;
-
-		qcom,page4 = <1 0x3d89 2 0x10 1 0>;
-		qcom,poll4 = <0 0x0 2 0x0 1 0>;
-		qcom,mem4 = <0 0x0 2 0x0 1 0>;
-
-		qcom,page5 = <1 0x3d8a 2 0x70 1 0>;
-		qcom,poll5 = <0 0x0 2 0x0 1 0>;
-		qcom,mem5 = <0 0x0 2 0x0 1 0>;
-
-		qcom,page6 = <1 0x3d8b 2 0xf4 1 0>;
-		qcom,poll6 = <0 0x0 2 0x0 1 0>;
-		qcom,mem6 = <0 0x0 2 0x0 1 0>;
-
-		qcom,page7 = <1 0x3d81 2 0x01 1 10>;
-		qcom,poll7 = <0 0x0 2 0x0 1 1>;
-		qcom,mem7 = <1536 0x7010 2 0 1 0>;
-
-		cam_vdig-supply = <&pm8953_l23>;
-		cam_vana-supply = <&pm8953_l22>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
-			"cam_vaf";
-		qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
-		qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
-		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
-		qcom,gpio-no-mux = <0>;
-		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk1_default
-			&cam_sensor_front1_default>;
-		pinctrl-1 = <&cam_sensor_mclk1_sleep &cam_sensor_front1_sleep>;
-		gpios = <&tlmm 27 0>,
-			<&tlmm 129 0>,
-			<&tlmm 130 0>;
-		qcom,gpio-reset = <1>;
-		qcom,gpio-standby = <2>;
-		qcom,gpio-req-tbl-num = <0 1 2>;
-		qcom,gpio-req-tbl-flags = <1 0 0>;
-		qcom,gpio-req-tbl-label = "CAMIF_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_mclk1_clk_src>,
-			<&clock_gcc clk_gcc_camss_mclk1_clk>;
-		clock-names = "cam_src_clk", "cam_clk";
-		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_l23>;
-		cam_vana-supply = <&pm8953_l22>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
-					"cam_vaf";
-		qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
-		qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
-		qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
-		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk2_default
-				&cam_sensor_front_default>;
-		pinctrl-1 = <&cam_sensor_mclk2_sleep
-				&cam_sensor_front_sleep>;
-		gpios = <&tlmm 28 0>,
-			<&tlmm 131 0>,
-			<&tlmm 132 0>;
-		qcom,gpio-reset = <1>;
-		qcom,gpio-standby = <2>;
-		qcom,gpio-req-tbl-num = <0 1 2>;
-		qcom,gpio-req-tbl-flags = <1 0 0>;
-		qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
-			"CAM_RESET1",
-			"CAM_STANDBY1";
-		status = "ok";
-		clocks = <&clock_gcc clk_mclk2_clk_src>,
-				<&clock_gcc clk_gcc_camss_mclk2_clk>;
-		clock-names = "cam_src_clk", "cam_clk";
-		qcom,clock-rates = <19200000 0>;
-	};
-
-	qcom,camera@0 {
-		cell-index = <0>;
-		compatible = "qcom,camera";
-		reg = <0x0>;
-		qcom,csiphy-sd-index = <0>;
-		qcom,csid-sd-index = <0>;
-		qcom,mount-angle = <270>;
-		qcom,led-flash-src = <&led_flash0>;
-		qcom,eeprom-src = <&eeprom0>;
-		qcom,actuator-src = <&actuator0>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vdig-supply = <&pm8953_l23>;
-		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vio", "cam_vdig", "cam_vaf";
-		qcom,cam-vreg-min-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-max-voltage = <0 1100000 2850000>;
-		qcom,cam-vreg-op-mode = <0 105000 100000>;
-		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk0_default
-				&cam_sensor_rear_default
-				&cam_sensor_rear_vana>;
-		pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep
-				&cam_sensor_rear_vana_sleep>;
-		gpios = <&tlmm 26 0>,
-			<&tlmm 40 0>,
-			<&tlmm 39 0>,
-			<&tlmm 134 0>;
-		qcom,gpio-reset = <1>;
-		qcom,gpio-standby = <2>;
-		qcom,gpio-vana = <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_VANA";
-		qcom,sensor-position = <0>;
-		qcom,sensor-mode = <0>;
-		qcom,cci-master = <0>;
-		status = "ok";
-		clocks = <&clock_gcc clk_mclk0_clk_src>,
-				<&clock_gcc clk_gcc_camss_mclk0_clk>;
-		clock-names = "cam_src_clk", "cam_clk";
-		qcom,clock-rates = <24000000 0>;
-	};
-
-	qcom,camera@1 {
-		cell-index = <1>;
-		compatible = "qcom,camera";
-		reg = <0x1>;
-		qcom,csiphy-sd-index = <1>;
-		qcom,csid-sd-index = <1>;
-		qcom,mount-angle = <90>;
-		qcom,eeprom-src = <&eeprom2>;
-		qcom,actuator-src = <&actuator1>;
-		cam_vdig-supply = <&pm8953_l23>;
-		cam_vana-supply = <&pm8953_l22>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
-							"cam_vaf";
-		qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
-		qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
-		qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
-		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk2_default
-				&cam_sensor_front_default>;
-		pinctrl-1 = <&cam_sensor_mclk2_sleep
-				&cam_sensor_front_sleep>;
-		gpios = <&tlmm 28 0>,
-			<&tlmm 131 0>,
-			<&tlmm 132 0>;
-		qcom,gpio-reset = <1>;
-		qcom,gpio-standby = <2>;
-		qcom,gpio-req-tbl-num = <0 1 2>;
-		qcom,gpio-req-tbl-flags = <1 0 0>;
-		qcom,gpio-req-tbl-label = "CAMIF_MCLK1",
-			"CAM_RESET1",
-			"CAM_STANDBY1";
-		qcom,sensor-position = <0x100>;
-		qcom,sensor-mode = <1>;
-		qcom,cci-master = <1>;
-		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>;
-	};
-
-	qcom,camera@2 {
-		cell-index = <2>;
-		compatible = "qcom,camera";
-		reg = <0x02>;
-		qcom,csiphy-sd-index = <2>;
-		qcom,csid-sd-index = <2>;
-		qcom,mount-angle = <90>;
-		qcom,eeprom-src = <&eeprom1>;
-		qcom,actuator-src = <&actuator1>;
-		cam_vdig-supply = <&pm8953_l23>;
-		cam_vio-supply = <&pm8953_l6>;
-		cam_vana-supply = <&pm8953_l22>;
-		cam_vaf-supply = <&pm8953_l17>;
-		qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
-					"cam_vaf";
-		qcom,cam-vreg-min-voltage = <1175000 0 2800000 2850000>;
-		qcom,cam-vreg-max-voltage = <1175000 0 2800000 2850000>;
-		qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
-		qcom,gpio-no-mux = <0>;
-		pinctrl-names = "cam_default", "cam_suspend";
-		pinctrl-0 = <&cam_sensor_mclk1_default
-				&cam_sensor_front1_default>;
-		pinctrl-1 = <&cam_sensor_mclk1_sleep
-				&cam_sensor_front1_sleep>;
-		gpios = <&tlmm 27 0>,
-			<&tlmm 129 0>,
-			<&tlmm 130 0>;
-		qcom,gpio-reset = <1>;
-		qcom,gpio-standby = <2>;
-		qcom,gpio-req-tbl-num = <0 1 2>;
-		qcom,gpio-req-tbl-flags = <1 0 0>;
-		qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
-					  "CAM_RESET2",
-					  "CAM_STANDBY2";
-		qcom,sensor-position = <1>;
-		qcom,sensor-mode = <0>;
-		qcom,cci-master = <1>;
-		status = "ok";
-		clocks = <&clock_gcc clk_mclk1_clk_src>,
-			<&clock_gcc clk_gcc_camss_mclk1_clk>;
-		clock-names = "cam_src_clk", "cam_clk";
-		qcom,clock-rates = <24000000 0>;
-	};
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts b/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
index 51c323c..2c3e830 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
@@ -16,7 +16,6 @@
 #include "sdm632.dtsi"
 #include "sdm450-pmi632-cdp-s2.dtsi"
 #include "sdm450-pmi632.dtsi"
-#include "sdm632-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 CDP S2";
@@ -55,3 +54,17 @@
 		};
 	};
 };
+
+&pm8953_vadc {
+	pinctrl-0 = <&pa_therm1_default>;
+	/delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+	/delete-node/ case_therm;
+};
+
+&thermal_zones {
+	/delete-node/ case-therm-adc;
+	/delete-node/ case-therm-step;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts b/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts
index f7770af..0566fbb 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-mtp-s3.dts
@@ -16,7 +16,6 @@
 #include "sdm632.dtsi"
 #include "sdm450-pmi632-mtp-s3.dtsi"
 #include "sdm450-pmi632.dtsi"
-#include "sdm632-camera-sensor-mtp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM632 + PMI632 + PMI8004 MTP S3";
@@ -25,3 +24,16 @@
 	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
 };
 
+&pm8953_vadc {
+	pinctrl-0 = <&pa_therm1_default>;
+	/delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+	/delete-node/ case_therm;
+};
+
+&thermal_zones {
+	/delete-node/ case-therm-adc;
+	/delete-node/ case-therm-step;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts b/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
index c3cc988..fe1ac73 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
@@ -50,3 +50,17 @@
 		};
 	};
 };
+
+&pm8953_vadc {
+	pinctrl-0 = <&pa_therm1_default>;
+	/delete-node/ chan@13;
+};
+
+&pm8953_mpps {
+	/delete-node/ case_therm;
+};
+
+&thermal_zones {
+	/delete-node/ case-therm-adc;
+	/delete-node/ case-therm-step;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm632-regulator.dtsi
index ed7ec2a..060b8996 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632-regulator.dtsi
@@ -13,6 +13,42 @@
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
+&pm8953_s3 {
+	regulator-min-microvolt = <984000>;
+	regulator-max-microvolt = <1240000>;
+	qcom,init-voltage = <984000>;
+};
+
+&pm8953_s4 {
+	regulator-min-microvolt = <1036000>;
+	regulator-max-microvolt = <2040000>;
+	qcom,init-voltage = <1036000>;
+};
+
+&pm8953_l1 {
+	regulator-min-microvolt = <975000>;
+	regulator-max-microvolt = <1050000>;
+	qcom,init-voltage = <975000>;
+};
+
+&pm8953_l2 {
+	regulator-min-microvolt = <975000>;
+	regulator-max-microvolt = <1175000>;
+	qcom,init-voltage = <975000>;
+};
+
+&pm8953_l10 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <3000000>;
+	qcom,init-voltage = <2800000>;
+};
+
+&pm8953_l22 {
+	regulator-min-microvolt = <2800000>;
+	regulator-max-microvolt = <2800000>;
+	qcom,init-voltage = <2800000>;
+};
+
 &rpm_bus {
 	rpm-regulator-ldoc1 {
 		status = "okay";
@@ -150,7 +186,7 @@
 				qcom,cpr-corner-fmax-map = <1 2 3 4 7>;
 
 				qcom,cpr-voltage-ceiling =
-					<720000  720000 790000 865000 920000
+					<720000  790000 865000 865000 920000
 					 990000 1065000>;
 
 				qcom,cpr-voltage-floor =
@@ -162,7 +198,7 @@
 				qcom,corner-frequencies =
 					<614400000  883200000 1036800000
 					1363200000 1536000000 1670400000
-					1785600000>;
+					1804800000>;
 
 				qcom,cpr-ro-scaling-factor =
 				      <3600 3600 3830 2430 2520 2700 1790 1760
@@ -200,7 +236,7 @@
 				qcom,cpr-corner-fmax-map = <1 2 5>;
 
 				qcom,cpr-voltage-ceiling =
-					<790000 865000 920000 990000 1065000>;
+					<865000 865000 920000 990000 1065000>;
 
 				qcom,cpr-voltage-floor =
 					<500000  500000 500000 500000 500000>;
@@ -209,7 +245,7 @@
 
 				qcom,corner-frequencies =
 					<1094400000 1401600000 1555200000
-					 1785600000 1996200000>;
+					 1804800000 2016000000>;
 
 				qcom,cpr-ro-scaling-factor =
 				      <3600 3600 3830 2430 2520 2700 1790 1760
diff --git a/arch/arm64/boot/dts/qcom/sdm632.dtsi b/arch/arm64/boot/dts/qcom/sdm632.dtsi
index e397355..813b89d 100644
--- a/arch/arm64/boot/dts/qcom/sdm632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632.dtsi
@@ -22,6 +22,10 @@
 	compatible = "qcom,sdm632";
 	qcom,msm-id = <349 0x0>;
 	qcom,msm-name = "SDM632";
+
+	chosen {
+		/delete-property/ bootargs;
+	};
 };
 
 &clock_gcc_mdss {
@@ -52,12 +56,20 @@
 	/delete-node/ gpu1-usr;
 	/delete-node/ gpu1-step;
 	/delete-node/ deca-cpu-max-step;
+	/delete-node/ apc1-cpu0-step;
+	/delete-node/ apc1-cpu1-step;
+	/delete-node/ apc1-cpu2-step;
+	/delete-node/ apc1-cpu3-step;
 	/delete-node/ apc0-cpu0-step;
 	/delete-node/ apc0-cpu1-step;
 	/delete-node/ apc0-cpu2-step;
 	/delete-node/ apc0-cpu3-step;
 	/delete-node/ camera-lowf;
 	/delete-node/ apc1-l2-lowf;
+	/delete-node/ apc1-cpu0-lowf;
+	/delete-node/ apc1-cpu1-lowf;
+	/delete-node/ apc1-cpu2-lowf;
+	/delete-node/ apc1-cpu3-lowf;
 	/delete-node/ apc0-cpu0-lowf;
 	/delete-node/ apc0-cpu1-lowf;
 	/delete-node/ apc0-cpu2-lowf;
@@ -65,6 +77,10 @@
 	/delete-node/ apc0-l2-lowf;
 	/delete-node/ gpu0-lowf;
 	/delete-node/ gpu1-lowf;
+	/delete-node/ apc1-cpu0-usr;
+	/delete-node/ apc1-cpu1-usr;
+	/delete-node/ apc1-cpu2-usr;
+	/delete-node/ apc1-cpu3-usr;
 
 	case-therm-step {
 		status = "disabled";
@@ -84,7 +100,63 @@
 		};
 	};
 
-	cpuss0-usr {
+	apc1-mhm-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 4>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	apc1-cpu0-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 5>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	apc1-cpu1-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 6>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	apc1-cpu2-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 7>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	apc1-cpu3-usr {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 8>;
@@ -98,7 +170,7 @@
 		};
 	};
 
-	cpuss1-usr {
+	apc1-l2-usr {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 9>;
@@ -112,7 +184,7 @@
 		};
 	};
 
-	cpuss3-usr {
+	cpuss0-usr {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 13>;
@@ -242,14 +314,102 @@
 		};
 	};
 
-	cpuss3-step {
+	apc1-cpu0-step {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 5>;
+		thermal-governor = "step_wise";
+		trips {
+			apc1_cpu0_trip: apc1-cpu0-trip {
+				temperature = <105000>;
+				hysteresis = <15000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu4_cdev {
+				trip = <&apc1_cpu0_trip>;
+				cooling-device =
+					<&CPU4 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+		};
+	};
+
+	apc1-cpu1-step {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 6>;
+		thermal-governor = "step_wise";
+		trips {
+			apc1_cpu1_trip: apc1-cpu1-trip {
+				temperature = <105000>;
+				hysteresis = <15000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu5_cdev {
+				trip = <&apc1_cpu1_trip>;
+				cooling-device =
+					<&CPU5 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+		};
+	};
+
+	apc1-cpu2-step {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 7>;
+		thermal-governor = "step_wise";
+		trips {
+			apc1_cpu2_trip: apc1-cpu2-trip {
+				temperature = <105000>;
+				hysteresis = <15000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu6_cdev {
+				trip = <&apc1_cpu2_trip>;
+				cooling-device =
+					<&CPU6 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+		};
+	};
+
+	apc1-cpu3-step {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 8>;
+		thermal-governor = "step_wise";
+		trips {
+			apc1_cpu3_trip: apc1-cpu3-trip {
+				temperature = <105000>;
+				hysteresis = <15000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu7_cdev {
+				trip = <&apc1_cpu3_trip>;
+				cooling-device =
+					<&CPU7 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+		};
+	};
+
+	cpuss0-step {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-sensors = <&tsens0 13>;
 		thermal-governor = "step_wise";
 
 		trips {
-			cpuss3_trip: cpuss3-trip {
+			cpuss0_trip: cpuss0-trip {
 				temperature = <105000>;
 				hysteresis = <15000>;
 				type = "passive";
@@ -257,25 +417,25 @@
 		};
 		cooling-maps {
 			cpu0_cdev {
-				trip = <&cpuss3_trip>;
+				trip = <&cpuss0_trip>;
 				cooling-device =
 					<&CPU0 THERMAL_MAX_LIMIT
 						THERMAL_MAX_LIMIT>;
 			};
 			cpu1_cdev {
-				trip = <&cpuss3_trip>;
+				trip = <&cpuss0_trip>;
 				cooling-device =
 					<&CPU1 THERMAL_MAX_LIMIT
 						THERMAL_MAX_LIMIT>;
 			};
 			cpu2_cdev {
-				trip = <&cpuss3_trip>;
+				trip = <&cpuss0_trip>;
 				cooling-device =
 					<&CPU2 THERMAL_MAX_LIMIT
 						THERMAL_MAX_LIMIT>;
 			};
 			cpu3_cdev {
-				trip = <&cpuss3_trip>;
+				trip = <&cpuss0_trip>;
 				cooling-device =
 					<&CPU3 THERMAL_MAX_LIMIT
 						THERMAL_MAX_LIMIT>;
@@ -318,46 +478,11 @@
 		};
 	};
 
-	cpuss0-lowf {
+	apc1-mhm-low {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
-		thermal-sensors = <&tsens0 8>;
-		tracks-low;
-
-		trips {
-			sdm632_cpuss0_trip: cpuss0-trip {
-				temperature = <5000>;
-				hysteresis = <5000>;
-				type = "passive";
-			};
-		};
-		cooling-maps {
-			cpu0_vdd_cdev {
-				trip = <&sdm632_cpuss0_trip>;
-				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
-						(THERMAL_MAX_LIMIT - 4)>;
-			};
-			gpu_vdd_cdev {
-				trip = <&sdm632_cpuss0_trip>;
-				cooling-device = <&msm_gpu 2 2>;
-			};
-			cx_vdd_cdev {
-				trip = <&sdm632_cpuss0_trip>;
-				cooling-device = <&cx_cdev 0 0>;
-			};
-			modem_vdd_cdev {
-				trip = <&sdm632_cpuss0_trip>;
-				cooling-device = <&modem_vdd 0 0>;
-			};
-		};
-	};
-
-	cpuss1-lowf {
-		polling-delay-passive = <0>;
-		polling-delay = <0>;
-		thermal-governor = "low_limits_floor";
-		thermal-sensors = <&tsens0 9>;
+		thermal-sensors = <&tsens0 4>;
 		tracks-low;
 
 		trips {
@@ -388,7 +513,178 @@
 		};
 	};
 
-	cpuss3-lowf {
+	apc1-cpu0-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 5>;
+		tracks-low;
+		trips {
+			cpu4_trip: apc1-cpu0-trip {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_vdd_cdev {
+				trip = <&cpu4_trip>;
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			gpu_vdd_cdev {
+				trip = <&cpu4_trip>;
+				cooling-device = <&msm_gpu 2 2>;
+			};
+			cx_vdd_cdev {
+				trip = <&cpu4_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			modem_vdd_cdev {
+				trip = <&cpu4_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+		};
+	};
+
+	apc1-cpu1-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 6>;
+		tracks-low;
+		trips {
+			cpu5_trip: apc1-cpu0-trip {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_vdd_cdev {
+				trip = <&cpu5_trip>;
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			gpu_vdd_cdev {
+				trip = <&cpu5_trip>;
+				cooling-device = <&msm_gpu 2 2>;
+			};
+			cx_vdd_cdev {
+				trip = <&cpu5_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			modem_vdd_cdev {
+				trip = <&cpu5_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+		};
+	};
+
+	apc1-cpu2-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 7>;
+		tracks-low;
+		trips {
+			cpu6_trip: apc1-cpu2-trip {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_vdd_cdev {
+				trip = <&cpu6_trip>;
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			gpu_vdd_cdev {
+				trip = <&cpu6_trip>;
+				cooling-device = <&msm_gpu 2 2>;
+			};
+			cx_vdd_cdev {
+				trip = <&cpu6_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			modem_vdd_cdev {
+				trip = <&cpu6_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+		};
+	};
+
+	apc1-cpu3-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 8>;
+		tracks-low;
+		trips {
+			cpu7_trip: apc1-cpu3-trip {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_vdd_cdev {
+				trip = <&cpu7_trip>;
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			gpu_vdd_cdev {
+				trip = <&cpu7_trip>;
+				cooling-device = <&msm_gpu 2 2>;
+			};
+			cx_vdd_cdev {
+				trip = <&cpu7_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			modem_vdd_cdev {
+				trip = <&cpu7_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+		};
+	};
+
+	apc1-l2-low {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 9>;
+		tracks-low;
+
+		trips {
+			sdm632_cpuss0_trip: cpuss0-trip {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_vdd_cdev {
+				trip = <&sdm632_cpuss0_trip>;
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			gpu_vdd_cdev {
+				trip = <&sdm632_cpuss0_trip>;
+				cooling-device = <&msm_gpu 2 2>;
+			};
+			cx_vdd_cdev {
+				trip = <&sdm632_cpuss0_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			modem_vdd_cdev {
+				trip = <&sdm632_cpuss0_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+		};
+	};
+
+	cpuss0-lowf {
 		polling-delay-passive = <0>;
 		polling-delay = <0>;
 		thermal-governor = "low_limits_floor";
@@ -496,42 +792,40 @@
 
 &clock_cpu {
 	/delete-property/ vdd-cl-supply;
-	status = "disabled";
 	compatible = "qcom,cpu-clock-sdm632";
 	reg =   <0xb114000  0x68>,
 		<0xb014000  0x68>,
-		<0xb016000  0x8>,
-		<0xb116000  0x8>,
-		<0xb1d0000  0x8>,
 		<0xb011050  0x8>,
 		<0xb111050  0x8>,
 		<0xb1d1050  0x8>,
-		<0x00a412c  0x8>;
+		<0xb011050  0x8>,
+		<0xb111050  0x8>,
+		<0x00a4124  0x8>;
 	reg-names = "rcgwr-c0-base", "rcgwr-c1-base",
-		    "apcs-c1-pll-base", "apcs-c0-pll-base",
-		    "apcs-cci-pll-base", "apcs-c1-rcg-base",
-		    "apcs-c0-rcg-base", "apcs-cci-rcg-base",
-		    "efuse";
+		    "apcs-c1-rcg-base", "apcs-c0-rcg-base",
+		    "apcs-cci-rcg-base", "c1-mux",
+		    "c0-mux", "efuse";
 	qcom,num-clusters = <2>;
+	vdd-c0-supply = <&apc0_pwrcl_vreg>;
+	vdd-c1-supply = <&apc1_perfcl_vreg>;
+	vdd-cci-supply = <&apc0_pwrcl_vreg>;
 	clocks = <&clock_gcc clk_xo_a_clk_src>;
 	clock-names = "xo_a";
 	qcom,speed0-bin-v0-c0 =
 		<          0 0>,
 		<   614400000 1>,
 		<   883200000 2>,
-		<  1036200000 3>,
+		<  1036800000 3>,
 		<  1363200000 4>,
-		<  1563000000 5>,
+		<  1536000000 5>,
 		<  1670400000 6>,
 		<  1785600000 7>;
 	qcom,speed0-bin-v0-c1 =
 		<          0 0>,
-		<   633600000 1>,
-		<   902400000 2>,
-		<  1094400000 3>,
-		<  1401600000 4>,
-		<  1555200000 5>,
-		<  1785600000 6>;
+		<  1094400000 1>,
+		<  1401600000 2>,
+		<  1555200000 3>,
+		<  1785600000 4>;
 	qcom,speed0-bin-v0-cci =
 		<          0 0>,
 		<  307200000 1>,
@@ -544,7 +838,7 @@
 };
 
 &soc {
-	/delete-node/ msm_cpufreq;
+	/delete-node/ qcom,msm-cpufreq;
 	msm_cpufreq: qcom,msm-cpufreq {
 		compatible = "qcom,msm-cpufreq";
 		clock-names =
@@ -552,9 +846,9 @@
 			"cpu0_clk",
 			"cpu4_clk";
 		clocks =
-			<&clock_cpu clk_a53_cci_clk >,
-			<&clock_cpu clk_a53_pwr_clk >,
-			<&clock_cpu clk_a53_perf_clk >;
+			<&clock_cpu clk_cci_clk >,
+			<&clock_cpu clk_pwr_clk >,
+			<&clock_cpu clk_perf_clk >;
 
 		qcom,governor-per-policy;
 
@@ -579,7 +873,7 @@
 	cci_cache: qcom,cci {
 		compatible = "devfreq-simple-dev";
 		clock-names = "devfreq_clk";
-		clocks = <&clock_cpu clk_a53_cci_clk >;
+		clocks = <&clock_cpu clk_cci_clk >;
 		governor = "cpufreq";
 		freq-tbl-khz =
 			<  307200 >,
diff --git a/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi b/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
index a77f4a0..e86117d 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
@@ -63,6 +63,7 @@
 
 		qcom,gpu-quirk-hfi-use-reg;
 		qcom,gpu-quirk-limit-uche-gbif-rw;
+		qcom,gpu-quirk-secvid-set-once;
 
 		/* <HZ/12> */
 		qcom,idle-timeout = <80>;
@@ -147,12 +148,14 @@
 				qcom,gpu-quirk-hfi-use-reg;
 				qcom,gpu-quirk-limit-uche-gbif-rw;
 				qcom,gpu-quirk-mmu-secure-cb-alt;
+				qcom,gpu-quirk-secvid-set-once;
 			};
 
 			qcom,soc-hw-revision-1 {
 				qcom,soc-hw-revision = <1>;
 				qcom,chipid = <0x06010501>;
 				qcom,gpu-quirk-hfi-use-reg;
+				qcom,gpu-quirk-secvid-set-once;
 			};
 		};
 
@@ -357,7 +360,7 @@
 					reg = <0>;
 					qcom,gpu-freq = <700000000>;
 					qcom,bus-freq = <11>;
-					qcom,bus-min = <8>;
+					qcom,bus-min = <9>;
 					qcom,bus-max = <11>;
 				};
 
@@ -365,7 +368,7 @@
 				qcom,gpu-pwrlevel@1 {
 					reg = <1>;
 					qcom,gpu-freq = <650000000>;
-					qcom,bus-freq = <11>;
+					qcom,bus-freq = <10>;
 					qcom,bus-min = <8>;
 					qcom,bus-max = <11>;
 				};
@@ -374,27 +377,27 @@
 				qcom,gpu-pwrlevel@2 {
 					reg = <2>;
 					qcom,gpu-freq = <565000000>;
-					qcom,bus-freq = <11>;
+					qcom,bus-freq = <9>;
 					qcom,bus-min = <8>;
-					qcom,bus-max = <11>;
+					qcom,bus-max = <10>;
 				};
 
 				/* SVS_L1 */
 				qcom,gpu-pwrlevel@3 {
 					reg = <3>;
 					qcom,gpu-freq = <430000000>;
-					qcom,bus-freq = <11>;
-					qcom,bus-min = <8>;
-					qcom,bus-max = <11>;
+					qcom,bus-freq = <8>;
+					qcom,bus-min = <7>;
+					qcom,bus-max = <10>;
 				};
 
 				/* SVS */
 				qcom,gpu-pwrlevel@4 {
 					reg = <4>;
 					qcom,gpu-freq = <355000000>;
-					qcom,bus-freq = <8>;
+					qcom,bus-freq = <7>;
 					qcom,bus-min = <5>;
-					qcom,bus-max = <9>;
+					qcom,bus-max = <8>;
 				};
 
 				/* LOW SVS */
@@ -403,7 +406,7 @@
 					qcom,gpu-freq = <267000000>;
 					qcom,bus-freq = <6>;
 					qcom,bus-min = <4>;
-					qcom,bus-max = <8>;
+					qcom,bus-max = <7>;
 				};
 
 				/* MIN SVS */
@@ -517,8 +520,70 @@
 				};
 			};
 
-		};
+			qcom,gpu-pwrlevels-4 {
+				#address-cells = <1>;
+				#size-cells = <0>;
 
+				qcom,speed-bin = <105>;
+
+				qcom,initial-pwrlevel = <4>;
+				qcom,ca-target-pwrlevel = <2>;
+
+				/* NOM */
+				qcom,gpu-pwrlevel@0 {
+					reg = <0>;
+					qcom,gpu-freq = <504000000>;
+					qcom,bus-freq = <11>;
+					qcom,bus-min = <9>;
+					qcom,bus-max = <11>;
+				};
+
+				/* SVS_L1 */
+				qcom,gpu-pwrlevel@1 {
+					reg = <1>;
+					qcom,gpu-freq = <430000000>;
+					qcom,bus-freq = <11>;
+					qcom,bus-min = <8>;
+					qcom,bus-max = <11>;
+				};
+
+				/* SVS */
+				qcom,gpu-pwrlevel@2 {
+					reg = <2>;
+					qcom,gpu-freq = <355000000>;
+					qcom,bus-freq = <8>;
+					qcom,bus-min = <5>;
+					qcom,bus-max = <9>;
+				};
+
+				/* LOW SVS */
+				qcom,gpu-pwrlevel@3 {
+					reg = <3>;
+					qcom,gpu-freq = <267000000>;
+					qcom,bus-freq = <6>;
+					qcom,bus-min = <4>;
+					qcom,bus-max = <8>;
+				};
+
+				/* MIN SVS */
+				qcom,gpu-pwrlevel@4 {
+					reg = <4>;
+					qcom,gpu-freq = <180000000>;
+					qcom,bus-freq = <4>;
+					qcom,bus-min = <3>;
+					qcom,bus-max = <4>;
+				};
+
+				/* XO */
+				qcom,gpu-pwrlevel@5 {
+					reg = <5>;
+					qcom,gpu-freq = <0>;
+					qcom,bus-freq = <0>;
+					qcom,bus-min = <0>;
+					qcom,bus-max = <0>;
+				};
+			};
+		};
 	};
 
 	kgsl_msm_iommu: qcom,kgsl-iommu {
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 152b760..4d4e918 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -2469,6 +2469,7 @@
 		compatible = "qcom,msm-fastrpc-compute";
 		qcom,adsp-remoteheap-vmid = <22 37>;
 		qcom,fastrpc-adsp-audio-pdr;
+		qcom,fastrpc-adsp-sensors-pdr;
 
 		qcom,msm_fastrpc_compute_cb1 {
 			compatible = "qcom,msm-fastrpc-compute-cb";
@@ -2543,6 +2544,7 @@
 			label = "adsprpc-smd";
 			iommus = <&apps_smmu 0x1806 0x0>;
 			dma-coherent;
+			shared-cb;
 		};
 	};
 
@@ -2561,7 +2563,7 @@
 		qca,bt-vdd-ldo-current-level = <1>; /* LPM/PFM */
 	};
 
-	qcom,icnss@18800000 {
+	icnss: qcom,icnss@18800000 {
 		compatible = "qcom,icnss";
 		reg = <0x18800000 0x800000>,
 		      <0xa0000000 0x10000000>,
diff --git a/arch/arm64/boot/dts/qcom/sdm710-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-cdp-overlay.dts
new file mode 100644
index 0000000..a61d714
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-cdp-overlay.dts
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+#include "sdm670-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm710-cdp.dts b/arch/arm64/boot/dts/qcom/sdm710-cdp.dts
new file mode 100644
index 0000000..a39ee9e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-cdp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sdm710.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "sdm670-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-external-codec-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-external-codec-cdp-overlay.dts
new file mode 100644
index 0000000..c64e623
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-external-codec-cdp-overlay.dts
@@ -0,0 +1,37 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L Ext. Audio Codec CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <1 1>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
+
+&tavil_snd {
+	qcom,us-euro-gpios = <&tavil_us_euro_sw>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-external-codec-cdp.dts b/arch/arm64/boot/dts/qcom/sdm710-external-codec-cdp.dts
new file mode 100644
index 0000000..0b4c3af
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-external-codec-cdp.dts
@@ -0,0 +1,31 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sdm710.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM 710 PM660 + PM660L Ext. Audio Codec CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,board-id = <1 1>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
+
+&tavil_snd {
+	qcom,us-euro-gpios = <&tavil_us_euro_sw>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-external-codec-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-external-codec-mtp-overlay.dts
new file mode 100644
index 0000000..058a3f1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-external-codec-mtp-overlay.dts
@@ -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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-mtp.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L Ext. Audio Codec MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <8 1>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-external-codec-mtp.dts b/arch/arm64/boot/dts/qcom/sdm710-external-codec-mtp.dts
new file mode 100644
index 0000000..3920d78
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-external-codec-mtp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sdm710.dtsi"
+#include "sdm670-mtp.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM 710 PM660 + PM660L Ext. Audio Codec MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,board-id = <8 1>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-external-codec-pm660a-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-external-codec-pm660a-cdp-overlay.dts
new file mode 100644
index 0000000..408a376
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-external-codec-pm660a-cdp-overlay.dts
@@ -0,0 +1,38 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660A Ext. Audio Codec CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <1 1>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
+
+&tavil_snd {
+	qcom,us-euro-gpios = <&tavil_us_euro_sw>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-external-codec-pm660a-cdp.dts b/arch/arm64/boot/dts/qcom/sdm710-external-codec-pm660a-cdp.dts
new file mode 100644
index 0000000..1257c64
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-external-codec-pm660a-cdp.dts
@@ -0,0 +1,32 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sdm710.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM 710 PM660 + PM660A Ext. Audio Codec CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,board-id = <1 1>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
+
+&tavil_snd {
+	qcom,us-euro-gpios = <&tavil_us_euro_sw>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-external-codec-pm660a-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-external-codec-pm660a-mtp-overlay.dts
new file mode 100644
index 0000000..9a41edd
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-external-codec-pm660a-mtp-overlay.dts
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-mtp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660A Ext. Audio Codec MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <8 1>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-external-codec-pm660a-mtp.dts b/arch/arm64/boot/dts/qcom/sdm710-external-codec-pm660a-mtp.dts
new file mode 100644
index 0000000..e519095
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-external-codec-pm660a-mtp.dts
@@ -0,0 +1,28 @@
+/* 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 "sdm710.dtsi"
+#include "sdm670-mtp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-external-codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM 710 PM660 + PM660A Ext. Audio Codec MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,board-id = <8 1>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-mtp-overlay.dts
new file mode 100644
index 0000000..aa8ba6a
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-mtp-overlay.dts
@@ -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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-mtp.dtsi"
+#include "sdm670-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-mtp.dts b/arch/arm64/boot/dts/qcom/sdm710-mtp.dts
new file mode 100644
index 0000000..c081d00
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-mtp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sdm710.dtsi"
+#include "sdm670-mtp.dtsi"
+#include "sdm670-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-pm660a-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-pm660a-cdp-overlay.dts
new file mode 100644
index 0000000..66afaad
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-pm660a-cdp-overlay.dts
@@ -0,0 +1,74 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660A CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+	/delete-property/ qcom,dsi-display-active;
+};
+
+&dsi_panel_pwr_supply_labibb_amoled {
+	qcom,panel-supply-entry@2 {
+		reg = <2>;
+		qcom,supply-name = "lab";
+		qcom,supply-min-voltage = <4600000>;
+		qcom,supply-max-voltage = <6100000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+
+	qcom,panel-supply-entry@3 {
+		reg = <3>;
+		qcom,supply-name = "ibb";
+		qcom,supply-min-voltage = <4000000>;
+		qcom,supply-max-voltage = <6300000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+
+	qcom,panel-supply-entry@4 {
+		reg = <4>;
+		qcom,supply-name = "oledb";
+		qcom,supply-min-voltage = <5000000>;
+		qcom,supply-max-voltage = <8100000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+};
+
+&dsi_rm67195_amoled_fhd_cmd_display {
+	qcom,dsi-display-active;
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+	oledb-supply = <&pm660a_oledb>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-pm660a-cdp.dts b/arch/arm64/boot/dts/qcom/sdm710-pm660a-cdp.dts
new file mode 100644
index 0000000..2786717
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-pm660a-cdp.dts
@@ -0,0 +1,68 @@
+/* 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 "sdm710.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660A CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+	/delete-property/ qcom,dsi-display-active;
+};
+
+&dsi_panel_pwr_supply_labibb_amoled {
+	qcom,panel-supply-entry@2 {
+		reg = <2>;
+		qcom,supply-name = "lab";
+		qcom,supply-min-voltage = <4600000>;
+		qcom,supply-max-voltage = <6100000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+
+	qcom,panel-supply-entry@3 {
+		reg = <3>;
+		qcom,supply-name = "ibb";
+		qcom,supply-min-voltage = <4000000>;
+		qcom,supply-max-voltage = <6300000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+
+	qcom,panel-supply-entry@4 {
+		reg = <4>;
+		qcom,supply-name = "oledb";
+		qcom,supply-min-voltage = <5000000>;
+		qcom,supply-max-voltage = <8100000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+};
+
+&dsi_rm67195_amoled_fhd_cmd_display {
+	qcom,dsi-display-active;
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+	oledb-supply = <&pm660a_oledb>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-pm660a-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-pm660a-mtp-overlay.dts
new file mode 100644
index 0000000..d9b055d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-pm660a-mtp-overlay.dts
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-mtp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660A MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-pm660a-mtp.dts b/arch/arm64/boot/dts/qcom/sdm710-pm660a-mtp.dts
new file mode 100644
index 0000000..97bbf2b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-pm660a-mtp.dts
@@ -0,0 +1,28 @@
+/* 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 "sdm710.dtsi"
+#include "sdm670-mtp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660A MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-pm660a-tasha-codec-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-pm660a-tasha-codec-cdp-overlay.dts
new file mode 100644
index 0000000..7e9eaa7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-pm660a-tasha-codec-cdp-overlay.dts
@@ -0,0 +1,74 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-tasha-codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660A + Tasha Codec CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <1 5>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+	/delete-property/ qcom,dsi-display-active;
+};
+
+&dsi_panel_pwr_supply_labibb_amoled {
+	qcom,panel-supply-entry@2 {
+		reg = <2>;
+		qcom,supply-name = "lab";
+		qcom,supply-min-voltage = <4600000>;
+		qcom,supply-max-voltage = <6100000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+
+	qcom,panel-supply-entry@3 {
+		reg = <3>;
+		qcom,supply-name = "ibb";
+		qcom,supply-min-voltage = <4000000>;
+		qcom,supply-max-voltage = <6300000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+
+	qcom,panel-supply-entry@4 {
+		reg = <4>;
+		qcom,supply-name = "oledb";
+		qcom,supply-min-voltage = <5000000>;
+		qcom,supply-max-voltage = <8100000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+};
+
+&dsi_rm67195_amoled_fhd_cmd_display {
+	qcom,dsi-display-active;
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+	oledb-supply = <&pm660a_oledb>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-pm660a-tasha-codec-cdp.dts b/arch/arm64/boot/dts/qcom/sdm710-pm660a-tasha-codec-cdp.dts
new file mode 100644
index 0000000..f7c654d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-pm660a-tasha-codec-cdp.dts
@@ -0,0 +1,68 @@
+/* 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 "sdm710.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-tasha-codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660A Tasha Codec CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,board-id = <1 5>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
+
+&dsi_dual_nt35597_truly_video_display {
+	/delete-property/ qcom,dsi-display-active;
+};
+
+&dsi_panel_pwr_supply_labibb_amoled {
+	qcom,panel-supply-entry@2 {
+		reg = <2>;
+		qcom,supply-name = "lab";
+		qcom,supply-min-voltage = <4600000>;
+		qcom,supply-max-voltage = <6100000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+
+	qcom,panel-supply-entry@3 {
+		reg = <3>;
+		qcom,supply-name = "ibb";
+		qcom,supply-min-voltage = <4000000>;
+		qcom,supply-max-voltage = <6300000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+
+	qcom,panel-supply-entry@4 {
+		reg = <4>;
+		qcom,supply-name = "oledb";
+		qcom,supply-min-voltage = <5000000>;
+		qcom,supply-max-voltage = <8100000>;
+		qcom,supply-enable-load = <100000>;
+		qcom,supply-disable-load = <100>;
+	};
+};
+
+&dsi_rm67195_amoled_fhd_cmd_display {
+	qcom,dsi-display-active;
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+	oledb-supply = <&pm660a_oledb>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-qrd-overlay.dts
new file mode 100644
index 0000000..803616d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-qrd-overlay.dts
@@ -0,0 +1,32 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/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.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L QRD";
+	compatible = "qcom,sdm670-qrd", "qcom,sdm670", "qcom,qrd";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <0x0002000b 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2-overlay.dts
new file mode 100644
index 0000000..ab3ce4d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2-overlay.dts
@@ -0,0 +1,51 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-qrd.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L QRD SKU2";
+	compatible = "qcom,sdm670-qrd", "qcom,sdm670", "qcom,qrd";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <0x0012000b 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
+
+&dsi_dual_nt36850_truly_cmd_display {
+	/delete-property/ qcom,dsi-display-active;
+};
+
+&dsi_hx8399_truly_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,panel-mode-gpio = <&tlmm 76 0>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+};
+
+&dsi_hx8399_truly_cmd_display {
+	qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2.dts b/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2.dts
new file mode 100644
index 0000000..76b2862
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-qrd-sku2.dts
@@ -0,0 +1,45 @@
+/* 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 "sdm710.dtsi"
+#include "sdm670-qrd.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L QRD SKU2";
+	compatible = "qcom,sdm670-qrd", "qcom,sdm670", "qcom,qrd";
+	qcom,board-id = <0x0012000b 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
+
+&dsi_dual_nt36850_truly_cmd_display {
+	/delete-property/ qcom,dsi-display-active;
+};
+
+&dsi_hx8399_truly_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+	qcom,mdss-dsi-bl-min-level = <1>;
+	qcom,mdss-dsi-bl-max-level = <4095>;
+	qcom,panel-mode-gpio = <&tlmm 76 0>;
+	qcom,mdss-dsi-mode-sel-gpio-state = "single_port";
+	qcom,platform-reset-gpio = <&tlmm 75 0>;
+	qcom,platform-te-gpio = <&tlmm 10 0>;
+};
+
+&dsi_hx8399_truly_cmd_display {
+	qcom,dsi-display-active;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-qrd.dts b/arch/arm64/boot/dts/qcom/sdm710-qrd.dts
new file mode 100644
index 0000000..e3cb7cc
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-qrd.dts
@@ -0,0 +1,26 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sdm710.dtsi"
+#include "sdm670-qrd.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L QRD";
+	compatible = "qcom,sdm670-qrd", "qcom,sdm670", "qcom,qrd";
+	qcom,board-id = <0x0002000b 0>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-tasha-codec-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-tasha-codec-cdp-overlay.dts
new file mode 100644
index 0000000..1632ebf
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-tasha-codec-cdp-overlay.dts
@@ -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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+#include "sdm670-tasha-codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L Tasha Codec CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <1 5>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-tasha-codec-cdp.dts b/arch/arm64/boot/dts/qcom/sdm710-tasha-codec-cdp.dts
new file mode 100644
index 0000000..456e3d2
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-tasha-codec-cdp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sdm710.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "sdm670-tasha-codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L Tasha Codec CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,board-id = <1 5>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-cdp-overlay.dts
new file mode 100644
index 0000000..fe05472
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-cdp-overlay.dts
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+#include "sdm670-int-cdc-usbc-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L, USB-C Audio, CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <1 2>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-cdp.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-cdp.dts
new file mode 100644
index 0000000..ac7f59a
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-cdp.dts
@@ -0,0 +1,26 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sdm710.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "sdm670-int-cdc-usbc-audio-overlay.dtsi"
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L, USB-C Audio, CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,board-id = <1 2>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-cdp-overlay.dts
new file mode 100644
index 0000000..846bee4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-cdp-overlay.dts
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+#include "sdm670-external-codec.dtsi"
+#include "sdm670-ext-cdc-usbc-audio.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660+PM660L, USB-C Audio, Ext. Audio Codec CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <1 3>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-cdp.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-cdp.dts
new file mode 100644
index 0000000..b3b8254
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-cdp.dts
@@ -0,0 +1,28 @@
+/* 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 "sdm710.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "sdm670-external-codec.dtsi"
+#include "sdm670-ext-cdc-usbc-audio.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM 710 PM660+PM660L, USB-C Audio, Ext. Audio Codec CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,board-id = <1 3>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-mtp-overlay.dts
new file mode 100644
index 0000000..bfc9a7f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-mtp-overlay.dts
@@ -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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-mtp.dtsi"
+#include "sdm670-external-codec.dtsi"
+#include "sdm670-ext-cdc-usbc-audio.dtsi"
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660+PM660L, USB-C Audio, Ext. Audio Codec MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <8 3>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-mtp.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-mtp.dts
new file mode 100644
index 0000000..011e6ae
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-mtp.dts
@@ -0,0 +1,28 @@
+/* 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 "sdm710.dtsi"
+#include "sdm670-mtp.dtsi"
+#include "sdm670-external-codec.dtsi"
+#include "sdm670-ext-cdc-usbc-audio.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM 710 PM660+PM660L, USB-C Audio, Ext. Audio Codec MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,board-id = <8 3>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-pm660a-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-pm660a-cdp-overlay.dts
new file mode 100644
index 0000000..f8642bb
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-pm660a-cdp-overlay.dts
@@ -0,0 +1,36 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-external-codec.dtsi"
+#include "sdm670-ext-cdc-usbc-audio.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660+PM660A, USB-C Audio, Ext. Audio Codec CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <1 3>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-pm660a-cdp.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-pm660a-cdp.dts
new file mode 100644
index 0000000..6e9d9d9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-pm660a-cdp.dts
@@ -0,0 +1,29 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sdm710.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-external-codec.dtsi"
+#include "sdm670-ext-cdc-usbc-audio.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM 710 PM660+PM660A, USB-C Audio, Ext. Audio Codec CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,board-id = <1 3>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-pm660a-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-pm660a-mtp-overlay.dts
new file mode 100644
index 0000000..c820950
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-pm660a-mtp-overlay.dts
@@ -0,0 +1,35 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-mtp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-external-codec.dtsi"
+#include "sdm670-ext-cdc-usbc-audio.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660+PM660A, USB-C Audio, Ext. Audio Codec MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <8 3>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-pm660a-mtp.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-pm660a-mtp.dts
new file mode 100644
index 0000000..11e7243
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-external-codec-pm660a-mtp.dts
@@ -0,0 +1,29 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sdm710.dtsi"
+#include "sdm670-mtp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-external-codec.dtsi"
+#include "sdm670-ext-cdc-usbc-audio.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM 710 PM660+PM660A, USB-C Audio, Ext. Audio Codec MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,board-id = <8 3>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-mtp-overlay.dts
new file mode 100644
index 0000000..a40ab83
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-mtp-overlay.dts
@@ -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.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-mtp.dtsi"
+#include "sdm670-int-cdc-usbc-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L, USB-C Audio, MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <8 2>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-mtp.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-mtp.dts
new file mode 100644
index 0000000..1c8ab48
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-mtp.dts
@@ -0,0 +1,27 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sdm710.dtsi"
+#include "sdm670-mtp.dtsi"
+#include "sdm670-int-cdc-usbc-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660L, USB-C Audio, MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,board-id = <8 2>;
+	qcom,pmic-id = <0x0001001b 0x0101011a 0x0 0x0>,
+		       <0x0001001b 0x0102001a 0x0 0x0>,
+		       <0x0001001b 0x0201011a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-pm660a-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-pm660a-cdp-overlay.dts
new file mode 100644
index 0000000..df4c2b9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-pm660a-cdp-overlay.dts
@@ -0,0 +1,35 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-int-cdc-usbc-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660A, USB-C Audio, CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <1 2>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-pm660a-cdp.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-pm660a-cdp.dts
new file mode 100644
index 0000000..2f484b5
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-pm660a-cdp.dts
@@ -0,0 +1,28 @@
+/* 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 "sdm710.dtsi"
+#include "sdm670-cdp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-int-cdc-usbc-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660A, USB-C Audio, CDP";
+	compatible = "qcom,sdm670-cdp", "qcom,sdm670", "qcom,cdp";
+	qcom,board-id = <1 2>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-pm660a-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-pm660a-mtp-overlay.dts
new file mode 100644
index 0000000..35f9570
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-pm660a-mtp-overlay.dts
@@ -0,0 +1,34 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sdm670-mtp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-int-cdc-usbc-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660A, USB-C Audio, MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,msm-id = <360 0x0>;
+	qcom,board-id = <8 2>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710-usbc-pm660a-mtp.dts b/arch/arm64/boot/dts/qcom/sdm710-usbc-pm660a-mtp.dts
new file mode 100644
index 0000000..f71b77a
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710-usbc-pm660a-mtp.dts
@@ -0,0 +1,28 @@
+/* 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 "sdm710.dtsi"
+#include "sdm670-mtp.dtsi"
+#include "pm660a.dtsi"
+#include "sdm670-int-cdc-usbc-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 PM660 + PM660A, USB-C Audio, MTP";
+	compatible = "qcom,sdm670-mtp", "qcom,sdm670", "qcom,mtp";
+	qcom,board-id = <8 2>;
+	qcom,pmic-id = <0x0001001b 0x0001011a 0x0 0x0>,
+		       <0x0001001b 0x0002001a 0x0 0x0>,
+		       <0x0001001b 0x0202001a 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710.dts b/arch/arm64/boot/dts/qcom/sdm710.dts
new file mode 100644
index 0000000..da971a3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710.dts
@@ -0,0 +1,21 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm710.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710 SoC";
+	compatible = "qcom,sdm670";
+	qcom,board-id = <0 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm710.dtsi b/arch/arm64/boot/dts/qcom/sdm710.dtsi
new file mode 100644
index 0000000..4a051b0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm710.dtsi
@@ -0,0 +1,26 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "sdm670.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM710";
+	compatible = "qcom,sdm670";
+	qcom,msm-id = <360 0x0>;
+};
+
+&msm_gpu {
+	qcom,chipid = <0x06010500>;
+	/delete-property/qcom,gpu-quirk-limit-uche-gbif-rw;
+	/delete-property/qcom,soc-hw-rev-efuse;
+	/delete-node/qcom,soc-hw-revisions;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
index 8d4d7df..6e0bb861 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde-display.dtsi
@@ -562,6 +562,7 @@
 &dsi_dual_nt35597_truly_cmd {
 	qcom,mdss-dsi-t-clk-post = <0x0D>;
 	qcom,mdss-dsi-t-clk-pre = <0x2D>;
+	qcom,ulps-enabled;
 	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];
@@ -576,6 +577,8 @@
 			qcom,display-topology = <2 0 2>,
 						<1 0 2>;
 			qcom,default-topology-index = <0>;
+			qcom,partial-update-enabled = "single_roi";
+			qcom,panel-roi-alignment = <720 128 720 128 1440 128>;
 		};
 	};
 };
@@ -829,6 +832,7 @@
 &dsi_dual_nt35597_cmd {
 	qcom,mdss-dsi-t-clk-post = <0x0d>;
 	qcom,mdss-dsi-t-clk-pre = <0x2d>;
+	qcom,ulps-enabled;
 	qcom,mdss-dsi-display-timings {
 		 timing@0 {
 			qcom,mdss-dsi-panel-timings = [00 1c 08 07 23 22 07 07
@@ -836,6 +840,8 @@
 			qcom,display-topology = <2 0 2>,
 						<1 0 2>;
 			qcom,default-topology-index = <0>;
+			qcom,partial-update-enabled = "single_roi";
+			qcom,panel-roi-alignment = <720 128 720 128 1440 128>;
 		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index aa16a77..82e55c4 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -2641,7 +2641,7 @@
 			<0 432 0>;
 		interrupt-names = "ipa-irq", "gsi-irq";
 		qcom,ipa-hw-ver = <13>; /* IPA core version = IPAv3.5.1 */
-		qcom,ipa-hw-mode = <1>;
+		qcom,ipa-hw-mode = <0>;
 		qcom,ee = <0>;
 		qcom,use-ipa-tethering-bridge;
 		qcom,modem-cfg-emb-pipe-flt;
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index f5410c1..a77f39f 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -33,7 +33,6 @@
 # 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
@@ -53,6 +52,7 @@
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_MSM8953=y
 CONFIG_ARCH_MSM8937=y
+CONFIG_ARCH_MSM8917=y
 CONFIG_ARCH_SDM450=y
 CONFIG_ARCH_SDM632=y
 CONFIG_ARCH_SDM429=y
@@ -293,6 +293,8 @@
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_VT is not set
 # CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_MSM_HS=y
 CONFIG_SERIAL_MSM_SMD=y
 CONFIG_DIAG_CHAR=y
@@ -395,6 +397,8 @@
 CONFIG_MSM_VIDC_3X_GOVERNORS=y
 CONFIG_MSM_SDE_ROTATOR=y
 CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=y
 CONFIG_QCOM_KGSL=y
 CONFIG_DRM=y
 CONFIG_DRM_SDE_EVTLOG_DEBUG=y
@@ -517,6 +521,7 @@
 CONFIG_QPNP_COINCELL=y
 CONFIG_QPNP_REVID=y
 CONFIG_USB_BAM=y
+CONFIG_MSM_RMNET_BAM=y
 CONFIG_MSM_MDSS_PLL=y
 CONFIG_REMOTE_SPINLOCK_MSM=y
 CONFIG_MAILBOX=y
@@ -558,6 +563,7 @@
 CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
 CONFIG_QCOM_BIMC_BWMON=y
 CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_SIMPLE_DEV=y
 CONFIG_QCOM_DEVFREQ_DEVBW=y
 CONFIG_SPDM_SCM=y
 CONFIG_DEVFREQ_SPDM=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index b9d1c38..569a69c 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -37,7 +37,6 @@
 # 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
@@ -57,6 +56,7 @@
 CONFIG_ARCH_QCOM=y
 CONFIG_ARCH_MSM8953=y
 CONFIG_ARCH_MSM8937=y
+CONFIG_ARCH_MSM8917=y
 CONFIG_ARCH_SDM450=y
 CONFIG_ARCH_SDM632=y
 CONFIG_ARCH_SDM429=y
@@ -303,6 +303,8 @@
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_VT is not set
 # CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
 CONFIG_SERIAL_MSM_HS=y
@@ -407,6 +409,8 @@
 CONFIG_MSM_VIDC_3X_GOVERNORS=y
 CONFIG_MSM_SDE_ROTATOR=y
 CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_RADIO_IRIS=y
+CONFIG_RADIO_IRIS_TRANSPORT=y
 CONFIG_QCOM_KGSL=y
 CONFIG_DRM=y
 CONFIG_DRM_SDE_EVTLOG_DEBUG=y
@@ -531,6 +535,7 @@
 CONFIG_QPNP_COINCELL=y
 CONFIG_QPNP_REVID=y
 CONFIG_USB_BAM=y
+CONFIG_MSM_RMNET_BAM=y
 CONFIG_MSM_MDSS_PLL=y
 CONFIG_REMOTE_SPINLOCK_MSM=y
 CONFIG_MAILBOX=y
@@ -539,6 +544,7 @@
 CONFIG_IOMMU_DEBUG=y
 CONFIG_IOMMU_DEBUG_TRACKING=y
 CONFIG_IOMMU_TESTS=y
+CONFIG_QCOM_CPUSS_DUMP=y
 CONFIG_QCOM_RUN_QUEUE_STATS=y
 CONFIG_MSM_SPM=y
 CONFIG_MSM_L2_SPM=y
@@ -548,6 +554,7 @@
 CONFIG_QCOM_EUD=y
 CONFIG_QCOM_WATCHDOG_V2=y
 CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_MSM_DEBUG_LAR_UNLOCK=y
 CONFIG_MSM_RPM_SMD=y
 CONFIG_QCOM_BUS_SCALING=y
 CONFIG_QCOM_SECURE_BUFFER=y
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index c2a9aa5..5297e3f 100644
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -328,6 +328,7 @@
 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_WRITABLE_TRIPS=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index 961864b..ad75f53 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -334,6 +334,7 @@
 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_WRITABLE_TRIPS=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index b8f98df..8f213f4 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -331,6 +331,7 @@
 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_WRITABLE_TRIPS=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 7868efe..d3ae4a5 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -336,6 +336,7 @@
 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_WRITABLE_TRIPS=y
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index b4e526d..d8cdb16 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -67,7 +67,10 @@
 	unsigned long size;
 };
 
-static struct dma_contig_early_reserve dma_mmu_remap[MAX_CMA_AREAS];
+/* allocate the memory for the fixup regions as well */
+#define MAX_FIXUP_AREAS MAX_CMA_AREAS
+static struct dma_contig_early_reserve
+			dma_mmu_remap[MAX_CMA_AREAS + MAX_FIXUP_AREAS];
 static int dma_mmu_remap_num;
 
 void __init dma_contiguous_early_fixup(phys_addr_t base, unsigned long size)
diff --git a/block/ioctl.c b/block/ioctl.c
index c4555b1..d4a78d0 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -564,6 +564,8 @@
 		if ((size >> 9) > ~0UL)
 			return -EFBIG;
 		return put_ulong(arg, size >> 9);
+	case BLKGETSTPART:
+		return put_ulong(arg, bdev->bd_part->start_sect);
 	case BLKGETSIZE64:
 		return put_u64(arg, i_size_read(bdev->bd_inode));
 	case BLKTRACESTART:
diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c
index 0f07483..2868dd3 100644
--- a/drivers/char/adsprpc_compat.c
+++ b/drivers/char/adsprpc_compat.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -77,13 +77,13 @@
 struct compat_fastrpc_ioctl_mmap {
 	compat_int_t fd;	/* ion fd */
 	compat_uint_t flags;	/* flags for dsp to map with */
-	compat_uptr_t vaddrin;	/* optional virtual address */
+	compat_u64 vaddrin;	/* optional virtual address */
 	compat_size_t size;	/* size */
-	compat_uptr_t vaddrout;	/* dsps virtual address */
+	compat_u64 vaddrout;	/* dsps virtual address */
 };
 
 struct compat_fastrpc_ioctl_munmap {
-	compat_uptr_t vaddrout;	/* address to unmap */
+	compat_u64 vaddrout;	/* address to unmap */
 	compat_size_t size;	/* size */
 };
 
@@ -191,7 +191,7 @@
 	compat_uint_t u;
 	compat_int_t i;
 	compat_size_t s;
-	compat_uptr_t p;
+	compat_u64 p;
 	int err;
 
 	err = get_user(i, &map32->fd);
@@ -199,7 +199,7 @@
 	err |= get_user(u, &map32->flags);
 	err |= put_user(u, &map->flags);
 	err |= get_user(p, &map32->vaddrin);
-	err |= put_user(p, (uintptr_t *)&map->vaddrin);
+	err |= put_user(p, &map->vaddrin);
 	err |= get_user(s, &map32->size);
 	err |= put_user(s, &map->size);
 
@@ -210,7 +210,7 @@
 			struct compat_fastrpc_ioctl_mmap __user *map32,
 			struct fastrpc_ioctl_mmap __user *map)
 {
-	compat_uptr_t p;
+	compat_u64 p;
 	int err;
 
 	err = get_user(p, &map->vaddrout);
@@ -223,7 +223,7 @@
 			struct compat_fastrpc_ioctl_munmap __user *unmap32,
 			struct fastrpc_ioctl_munmap __user *unmap)
 {
-	compat_uptr_t p;
+	compat_u64 p;
 	compat_size_t s;
 	int err;
 
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index bb7b654..37f3e63 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -199,16 +199,16 @@
 };
 
 struct fastrpc_ioctl_munmap {
-	uintptr_t vaddrout;	/* address to unmap */
+	uint64_t vaddrout;	/* address to unmap */
 	size_t size;		/* size */
 };
 
 struct fastrpc_ioctl_mmap {
 	int fd;				/* ion fd */
 	uint32_t flags;			/* flags for dsp to map with */
-	uintptr_t vaddrin;		/* optional virtual address */
+	uint64_t vaddrin;		/* optional virtual address */
 	size_t size;			/* size */
-	uintptr_t vaddrout;		/* dsps virtual address */
+	uint64_t vaddrout;		/* dsps virtual address */
 };
 
 struct fastrpc_ioctl_munmap_fd {
diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c
index 060f03f..ae2e00d 100644
--- a/drivers/char/diag/diag_usb.c
+++ b/drivers/char/diag/diag_usb.c
@@ -308,23 +308,25 @@
 	if (!ch || !req)
 		return;
 
+	spin_lock_irqsave(&ch->write_lock, flags);
 	ch->write_cnt++;
 	entry = diag_usb_buf_tbl_get(ch, req->context);
 	if (!entry) {
 		pr_err_ratelimited("diag: In %s, unable to find entry %pK in the table\n",
 				   __func__, req->context);
+		spin_unlock_irqrestore(&ch->write_lock, flags);
 		return;
 	}
 	if (atomic_read(&entry->ref_count) != 0) {
 		DIAG_LOG(DIAG_DEBUG_MUX, "partial write_done ref %d\n",
 			 atomic_read(&entry->ref_count));
 		diag_ws_on_copy_complete(DIAG_WS_MUX);
+		spin_unlock_irqrestore(&ch->write_lock, flags);
 		diagmem_free(driver, req, ch->mempool);
 		return;
 	}
 	DIAG_LOG(DIAG_DEBUG_MUX, "full write_done, ctxt: %d\n",
 		 ctxt);
-	spin_lock_irqsave(&ch->write_lock, flags);
 	list_del(&entry->track);
 	ctxt = entry->ctxt;
 	buf = entry->buf;
diff --git a/drivers/clk/msm/clock-cpu-sdm632.c b/drivers/clk/msm/clock-cpu-sdm632.c
index b59739a..357c49c 100644
--- a/drivers/clk/msm/clock-cpu-sdm632.c
+++ b/drivers/clk/msm/clock-cpu-sdm632.c
@@ -56,7 +56,9 @@
 static struct clk_ops clk_ops_variable_rate;
 
 DEFINE_EXT_CLK(xo_a_clk, NULL);
-DEFINE_VDD_REGS_INIT(vdd_cpu, 1);
+static DEFINE_VDD_REGS_INIT(vdd_cpu_perf, 1);
+static DEFINE_VDD_REGS_INIT(vdd_cpu_pwr, 1);
+static DEFINE_VDD_REGS_INIT(vdd_cci, 1);
 
 enum {
 	APCS_C0_PLL_BASE,
@@ -70,6 +72,7 @@
 	VDD_MX_MIN,
 	VDD_MX_LOWER,
 	VDD_MX_SVS,
+	VDD_MX_TUR,
 	VDD_MX_NUM,
 };
 
@@ -78,6 +81,7 @@
 	RPM_REGULATOR_LEVEL_MIN_SVS,    /* VDD_PLL_MIN */
 	RPM_REGULATOR_LEVEL_LOW_SVS,    /* VDD_PLL_LOW_SVS */
 	RPM_REGULATOR_LEVEL_SVS,	/* VDD_PLL_SVS */
+	RPM_REGULATOR_LEVEL_TURBO,	/* VDD_PLL_TUR */
 };
 
 static DEFINE_VDD_REGULATORS(vdd_mx, VDD_MX_NUM, 1,
@@ -124,7 +128,7 @@
 		.test_ctl_hi_val = 0x00004000,
 		.test_ctl_lo_val = 0x1C000000,
 	},
-	.max_rate = 1785600000UL,
+	.max_rate = 2016000000UL,
 	.min_rate = 614400000UL,
 	.src_rate =  19200000UL,
 	.base = &virt_bases[APCS_C0_PLL_BASE],
@@ -132,7 +136,7 @@
 		.parent = &xo_a_clk.c,
 		.dbg_name = "apcs_c0_pll",
 		.ops = &clk_ops_variable_rate,
-		VDD_MX_FMAX_MAP2(MIN, 1200000000UL, LOWER, 2400000000UL),
+		VDD_MX_FMAX_MAP2(MIN, 1200000000UL, LOWER, 2016000000UL),
 		CLK_INIT(apcs_c0_pll.c),
 	},
 };
@@ -161,7 +165,7 @@
 		.test_ctl_hi_val = 0x00004000,
 		.test_ctl_lo_val = 0x1C000000,
 	},
-	.max_rate = 2054400000UL,
+	.max_rate = 2016000000UL,
 	.min_rate = 633600000UL,
 	.src_rate =  19200000UL,
 	.base = &virt_bases[APCS_C1_PLL_BASE],
@@ -169,7 +173,7 @@
 		.parent = &xo_a_clk.c,
 		.dbg_name = "apcs_c1_pll",
 		.ops = &clk_ops_variable_rate,
-		VDD_MX_FMAX_MAP2(MIN, 1200000000UL, LOWER, 2400000000UL),
+		VDD_MX_FMAX_MAP2(MIN, 1200000000UL, LOWER, 2016000000UL),
 		CLK_INIT(apcs_c1_pll.c),
 	},
 };
@@ -190,7 +194,7 @@
 
 static struct alpha_pll_clk apcs_cci_pll = {
 	.masks = &pll_masks_p,
-	.offset = 0x1D0000,
+	.offset = 0x00,
 	.vco_tbl = apcs_cci_pll_vco,
 	.num_vco = ARRAY_SIZE(apcs_cci_pll_vco),
 	.enable_config = 0x8,  /* Early output */
@@ -203,7 +207,6 @@
 		.rate = 787200000,
 		.dbg_name = "apcs_cci_pll",
 		.ops = &clk_ops_dyna_alpha_pll,
-		/* TODO: FMAX */
 		VDD_MX_FMAX_MAP1(SVS, 1000000000UL),
 		CLK_INIT(apcs_cci_pll.c),
 	},
@@ -229,7 +232,7 @@
 	s32 cpu_latency_no_l2_pc_us;
 };
 
-static struct mux_div_clk a53ssmux_perf = {
+static struct mux_div_clk perf_cpussmux = {
 	.ops = &rcg_mux_div_ops,
 	.data = {
 		.max_div = 32,
@@ -237,9 +240,9 @@
 		.is_half_divider = true,
 	},
 	.c = {
-		.dbg_name = "a53ssmux_perf",
+		.dbg_name = "perf_cpussmux",
 		.ops = &clk_ops_mux_div_clk,
-		CLK_INIT(a53ssmux_perf.c),
+		CLK_INIT(perf_cpussmux.c),
 	},
 	.div_mask = BM(4, 0),
 	.src_mask = BM(10, 8) >> 8,
@@ -249,7 +252,7 @@
 	),
 };
 
-static struct mux_div_clk a53ssmux_pwr = {
+static struct mux_div_clk pwr_cpussmux = {
 	.ops = &rcg_mux_div_ops,
 	.data = {
 		.max_div = 32,
@@ -257,9 +260,9 @@
 		.is_half_divider = true,
 	},
 	.c = {
-		.dbg_name = "a53ssmux_pwr",
+		.dbg_name = "pwr_cpussmux",
 		.ops = &clk_ops_mux_div_clk,
-		CLK_INIT(a53ssmux_pwr.c),
+		CLK_INIT(pwr_cpussmux.c),
 	},
 	.div_mask = BM(4, 0),
 	.src_mask = BM(10, 8) >> 8,
@@ -269,17 +272,18 @@
 	),
 };
 
-static struct mux_div_clk a53ssmux_cci = {
+static struct mux_div_clk cci_cpussmux = {
 	.ops = &rcg_mux_div_ops,
 	.data = {
+		.skip_odd_div = true,
 		.max_div = 32,
 		.min_div = 2,
 		.is_half_divider = true,
 	},
 	.c = {
-		.dbg_name = "a53ssmux_cci",
+		.dbg_name = "cci_cpussmux",
 		.ops = &clk_ops_mux_div_clk,
-		CLK_INIT(a53ssmux_cci.c),
+		CLK_INIT(cci_cpussmux.c),
 	},
 	.div_mask = BM(4, 0),
 	.src_mask = BM(10, 8) >> 8,
@@ -289,9 +293,9 @@
 	),
 };
 
-static struct a53_cpu_clk a53_pwr_clk;
-static struct a53_cpu_clk a53_perf_clk;
-static struct a53_cpu_clk a53_cci_clk;
+static struct a53_cpu_clk pwr_clk;
+static struct a53_cpu_clk perf_clk;
+static struct a53_cpu_clk cci_clk;
 
 static void do_nothing(void *unused) { }
 
@@ -370,7 +374,7 @@
 	.handoff = a53_cpu_clk_handoff,
 };
 
-static struct a53_cpu_clk a53_perf_clk = {
+static struct a53_cpu_clk perf_clk = {
 	.cpu_reg_mask = 0x103,
 	.latency_lvl = {
 		.affinity_level = LPM_AFF_LVL_L2,
@@ -379,15 +383,15 @@
 	},
 	.cpu_latency_no_l2_pc_us = 280,
 	.c = {
-		.parent = &a53ssmux_perf.c,
+		.parent = &perf_cpussmux.c,
 		.ops = &clk_ops_cpu,
-		.vdd_class = &vdd_cpu,
-		.dbg_name = "a53_perf_clk",
-		CLK_INIT(a53_perf_clk.c),
+		.vdd_class = &vdd_cpu_perf,
+		.dbg_name = "perf_clk",
+		CLK_INIT(perf_clk.c),
 	},
 };
 
-static struct a53_cpu_clk a53_pwr_clk = {
+static struct a53_cpu_clk pwr_clk = {
 	.cpu_reg_mask = 0x3,
 	.latency_lvl = {
 		.affinity_level = LPM_AFF_LVL_L2,
@@ -396,21 +400,21 @@
 	},
 	.cpu_latency_no_l2_pc_us = 280,
 	.c = {
-		.parent = &a53ssmux_pwr.c,
+		.parent = &pwr_cpussmux.c,
 		.ops = &clk_ops_cpu,
-		.vdd_class = &vdd_cpu,
-		.dbg_name = "a53_pwr_clk",
-		CLK_INIT(a53_pwr_clk.c),
+		.vdd_class = &vdd_cpu_pwr,
+		.dbg_name = "pwr_clk",
+		CLK_INIT(pwr_clk.c),
 	},
 };
 
-static struct a53_cpu_clk a53_cci_clk = {
+static struct a53_cpu_clk cci_clk = {
 	.c = {
-		.parent = &a53ssmux_cci.c,
+		.parent = &cci_cpussmux.c,
 		.ops = &clk_ops_cpu,
-		.vdd_class = &vdd_cpu,
-		.dbg_name = "a53_cci_clk",
-		CLK_INIT(a53_cci_clk.c),
+		.vdd_class = &vdd_cci,
+		.dbg_name = "cci_clk",
+		CLK_INIT(cci_clk.c),
 	},
 };
 
@@ -500,14 +504,14 @@
 	CLK_LIST(apcs_cci_pll),
 
 	/* Muxes */
-	CLK_LIST(a53ssmux_pwr),
-	CLK_LIST(a53ssmux_perf),
-	CLK_LIST(a53ssmux_cci),
+	CLK_LIST(pwr_cpussmux),
+	CLK_LIST(perf_cpussmux),
+	CLK_LIST(cci_cpussmux),
 
 	/* CPU clocks */
-	CLK_LIST(a53_pwr_clk),
-	CLK_LIST(a53_perf_clk),
-	CLK_LIST(a53_cci_clk),
+	CLK_LIST(pwr_clk),
+	CLK_LIST(perf_clk),
+	CLK_LIST(cci_clk),
 
 	/* debug clocks */
 	CLK_LIST(apc0_m_clk),
@@ -516,13 +520,11 @@
 	CLK_LIST(cpu_debug_pri_mux),
 };
 
-static struct pll_clk *a53sspll[] = { &apcs_c1_pll, &apcs_c0_pll };
+static struct mux_div_clk *a53ssmux[] = { &perf_cpussmux, &pwr_cpussmux,
+						&cci_cpussmux };
 
-static struct mux_div_clk *a53ssmux[] = { &a53ssmux_perf, &a53ssmux_pwr,
-						&a53ssmux_cci };
-
-static struct a53_cpu_clk *cpuclk[] = { &a53_perf_clk, &a53_pwr_clk,
-						&a53_cci_clk };
+static struct a53_cpu_clk *cpuclk[] = { &perf_clk, &pwr_clk,
+						&cci_clk };
 
 static struct clk *logical_cpu_to_clk(int cpu)
 {
@@ -530,12 +532,12 @@
 	u32 reg;
 
 	if (cpu_node && !of_property_read_u32(cpu_node, "reg", &reg)) {
-		if ((reg | a53_pwr_clk.cpu_reg_mask) ==
-						a53_pwr_clk.cpu_reg_mask)
-			return &a53_pwr_clk.c;
-		if ((reg | a53_perf_clk.cpu_reg_mask) ==
-						a53_perf_clk.cpu_reg_mask)
-			return &a53_perf_clk.c;
+		if ((reg | pwr_clk.cpu_reg_mask) ==
+						pwr_clk.cpu_reg_mask)
+			return &pwr_clk.c;
+		if ((reg | perf_clk.cpu_reg_mask) ==
+						perf_clk.cpu_reg_mask)
+			return &perf_clk.c;
 	}
 
 	return NULL;
@@ -629,54 +631,6 @@
 								*version);
 }
 
-static int cpu_parse_pll_data(struct platform_device *pdev, int pll_count)
-{
-	int pll_num;
-	struct resource *res;
-	struct clk *c;
-	char pll_name[] = "apcs-xxx-pll-base";
-
-	for (pll_num = 0; pll_num < pll_count; pll_num++) {
-		snprintf(pll_name, ARRAY_SIZE(pll_name), "apcs-%s-pll-base",
-						pll_names[pll_num]);
-
-		res = platform_get_resource_byname(pdev,
-						IORESOURCE_MEM, pll_name);
-		if (!res) {
-			dev_err(&pdev->dev, "missing %s\n", pll_name);
-			return -EINVAL;
-		}
-
-		if (pll_num < APCS_CCI_PLL_BASE) {
-			a53sspll[pll_num]->base = devm_ioremap(&pdev->dev,
-					res->start, resource_size(res));
-			if (!a53sspll[pll_num]->base) {
-				dev_err(&pdev->dev, "ioremap failed for %s\n",
-								pll_name);
-				return -ENOMEM;
-			}
-		} else {
-			apcs_cci_pll.base = devm_ioremap(&pdev->dev,
-				res->start, resource_size(res));
-			if (!apcs_cci_pll.base) {
-				dev_err(&pdev->dev, "ioremap failed for %s\n",
-					pll_name);
-				return -ENOMEM;
-			}
-		}
-	}
-
-	c = devm_clk_get(&pdev->dev, "xo_a");
-	if (IS_ERR(c)) {
-		if (PTR_ERR(c) != -EPROBE_DEFER)
-			dev_err(&pdev->dev, "Unable to get xo clock\n");
-		return PTR_ERR(c);
-	}
-	xo_a_clk.c.parent = c;
-
-	return 0;
-}
-
 static int cpu_parse_devicetree(struct platform_device *pdev, int mux_id)
 {
 	struct resource *res;
@@ -714,7 +668,7 @@
 	return 0;
 }
 
-static int add_opp(struct clk *c, struct device *cpudev, struct device *vregdev,
+static int add_opp(struct clk *c, struct device *cpudev,
 			unsigned long max_rate)
 {
 	unsigned long rate = 0;
@@ -756,13 +710,6 @@
 			return ret;
 		}
 
-		ret = dev_pm_opp_add(vregdev, rate, uv);
-		if (ret) {
-			pr_warn("clock-cpu: couldn't add OPP for %lu\n",
-				rate);
-			return ret;
-		}
-
 		if (rate >= max_rate)
 			break;
 	}
@@ -775,10 +722,10 @@
 	struct dev_pm_opp *oppfmax, *oppfmin;
 	unsigned long apc0_fmax, apc1_fmax, apc0_fmin, apc1_fmin;
 
-	apc0_fmax = a53_pwr_clk.c.fmax[a53_pwr_clk.c.num_fmax - 1];
-	apc0_fmin = a53_pwr_clk.c.fmax[1];
-	apc1_fmax = a53_perf_clk.c.fmax[a53_perf_clk.c.num_fmax - 1];
-	apc1_fmin = a53_perf_clk.c.fmax[1];
+	apc0_fmax = pwr_clk.c.fmax[pwr_clk.c.num_fmax - 1];
+	apc0_fmin = pwr_clk.c.fmax[1];
+	apc1_fmax = perf_clk.c.fmax[perf_clk.c.num_fmax - 1];
+	apc1_fmin = perf_clk.c.fmax[1];
 
 	rcu_read_lock();
 	oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu),
@@ -808,51 +755,36 @@
 
 static void populate_opp_table(struct platform_device *pdev)
 {
-	struct platform_device *apc0_dev, *apc1_dev;
-	struct device_node *apc0_node = NULL, *apc1_node;
 	unsigned long apc0_fmax, apc1_fmax;
 	int cpu, a53_c0_cpu = 0, a53_c1_cpu = 0;
+	struct device *dev;
 
-	apc0_node = of_parse_phandle(pdev->dev.of_node,
-						"vdd-c0-supply", 0);
-	if (!apc0_node) {
-		pr_err("can't find the apc0 dt node.\n");
-		return;
-	}
+	apc0_fmax = pwr_clk.c.fmax[pwr_clk.c.num_fmax - 1];
 
-	apc1_node = of_parse_phandle(pdev->dev.of_node, "vdd-c1-supply", 0);
-	if (!apc1_node) {
-		pr_err("can't find the apc1 dt node.\n");
-		return;
-	}
-
-	apc0_dev = of_find_device_by_node(apc0_node);
-	if (!apc0_dev) {
-		pr_err("can't find the apc0 device node.\n");
-		return;
-	}
-
-	apc1_dev = of_find_device_by_node(apc1_node);
-	if (!apc1_dev) {
-		pr_err("can't find the apc1 device node.\n");
-		return;
-	}
-
-	apc0_fmax = a53_pwr_clk.c.fmax[a53_pwr_clk.c.num_fmax - 1];
-
-	apc1_fmax = a53_perf_clk.c.fmax[a53_perf_clk.c.num_fmax - 1];
+	apc1_fmax = perf_clk.c.fmax[perf_clk.c.num_fmax - 1];
 
 	for_each_possible_cpu(cpu) {
-		if (logical_cpu_to_clk(cpu) == &a53_pwr_clk.c) {
+		if (logical_cpu_to_clk(cpu) == &pwr_clk.c) {
 			a53_c0_cpu = cpu;
-			WARN(add_opp(&a53_pwr_clk.c, get_cpu_device(cpu),
-			&apc0_dev->dev,		apc0_fmax),
+			dev = get_cpu_device(cpu);
+			if (!dev) {
+				pr_err("can't find cpu device for attaching OPPs\n");
+				return;
+			}
+
+			WARN(add_opp(&pwr_clk.c, dev, apc0_fmax),
 				"Failed to add OPP levels for %d\n", cpu);
 		}
-		if (logical_cpu_to_clk(cpu) == &a53_perf_clk.c) {
+
+		if (logical_cpu_to_clk(cpu) == &perf_clk.c) {
 			a53_c1_cpu = cpu;
-			WARN(add_opp(&a53_perf_clk.c, get_cpu_device(cpu),
-			&apc1_dev->dev,		apc1_fmax),
+			dev = get_cpu_device(cpu);
+			if (!dev) {
+				pr_err("can't find cpu device for attaching OPPs\n");
+				return;
+			}
+
+			WARN(add_opp(&perf_clk.c, dev, apc1_fmax),
 				"Failed to add OPP levels for %d\n", cpu);
 		}
 	}
@@ -870,15 +802,15 @@
 	switch (event) {
 	case PM_POST_HIBERNATION:
 	case PM_POST_SUSPEND:
-		clk_unprepare(&a53_pwr_clk.c);
-		clk_unprepare(&a53_perf_clk.c);
-		clk_unprepare(&a53_cci_clk.c);
+		clk_unprepare(&pwr_clk.c);
+		clk_unprepare(&perf_clk.c);
+		clk_unprepare(&cci_clk.c);
 		break;
 	case PM_HIBERNATION_PREPARE:
 	case PM_SUSPEND_PREPARE:
-		clk_prepare(&a53_pwr_clk.c);
-		clk_prepare(&a53_perf_clk.c);
-		clk_prepare(&a53_cci_clk.c);
+		clk_prepare(&pwr_clk.c);
+		clk_prepare(&perf_clk.c);
+		clk_prepare(&cci_clk.c);
 		break;
 	default:
 		break;
@@ -904,11 +836,11 @@
 {
 	unsigned long rate;
 
-	rate  = (a53_perf_clk.c.count) ? a53_perf_clk.c.rate : 0;
-	pr_err("%s frequency: %10lu Hz\n", a53_perf_clk.c.dbg_name, rate);
+	rate  = (perf_clk.c.count) ? perf_clk.c.rate : 0;
+	pr_err("%s frequency: %10lu Hz\n", perf_clk.c.dbg_name, rate);
 
-	rate  = (a53_pwr_clk.c.count) ? a53_pwr_clk.c.rate : 0;
-	pr_err("%s frequency: %10lu Hz\n", a53_pwr_clk.c.dbg_name, rate);
+	rate  = (pwr_clk.c.count) ? pwr_clk.c.rate : 0;
+	pr_err("%s frequency: %10lu Hz\n", pwr_clk.c.dbg_name, rate);
 
 	return NOTIFY_OK;
 }
@@ -928,12 +860,17 @@
 	int speed_bin, version, rc, cpu, mux_id;
 	char prop_name[] = "qcom,speedX-bin-vX-XXX";
 	int mux_num = A53SS_MUX_NUM;
+	struct clk *xo_clk;
 
 	get_speed_bin(pdev, &speed_bin, &version);
 
-	rc = cpu_parse_pll_data(pdev, N_PLL_BASES);
-	if (rc)
-		return rc;
+	xo_clk = devm_clk_get(&pdev->dev, "xo_a");
+	if (IS_ERR(xo_clk)) {
+		if (PTR_ERR(xo_clk) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Unable to get xo clock\n");
+		return PTR_ERR(xo_clk);
+	}
+	xo_a_clk.c.parent = xo_clk;
 
 	/* PLL core logic */
 	vdd_mx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd-mx");
@@ -990,16 +927,16 @@
 	}
 
 	/* Force to move to PLL configuartion */
-	rc = clk_set_rate(&a53_cci_clk.c, cci_early_boot_rate);
+	rc = clk_set_rate(&cci_clk.c, cci_early_boot_rate);
 	if (rc)
 		dev_err(&pdev->dev, "Can't set CCI PLL rate for CCI\n");
 
-	rc = clk_set_rate(&a53_pwr_clk.c, pwrcl_early_boot_rate);
+	rc = clk_set_rate(&pwr_clk.c, pwrcl_early_boot_rate);
 	if (rc)
 		dev_err(&pdev->dev, "Can't set pwr PLL rate for Cluster-0 %ld\n",
 					pwrcl_early_boot_rate);
 
-	rc = clk_set_rate(&a53_perf_clk.c, perfcl_early_boot_rate);
+	rc = clk_set_rate(&perf_clk.c, perfcl_early_boot_rate);
 	if (rc)
 		dev_err(&pdev->dev, "Can't set perf PLL rate for Cluster-1 %ld\n",
 					perfcl_early_boot_rate);
@@ -1019,20 +956,20 @@
 	for_each_online_cpu(cpu) {
 		WARN(clk_prepare_enable(&cpuclk[cpu/4]->c),
 				"Unable to turn on CPU clock");
-		WARN(clk_prepare_enable(&a53_cci_clk.c),
+		WARN(clk_prepare_enable(&cci_clk.c),
 				"Unable to turn on CCI clock");
 	}
 	put_online_cpus();
 
 	for_each_possible_cpu(cpu) {
-		if (logical_cpu_to_clk(cpu) == &a53_perf_clk.c)
-			cpumask_set_cpu(cpu, &a53_perf_clk.cpumask);
-		if (logical_cpu_to_clk(cpu) == &a53_pwr_clk.c)
-			cpumask_set_cpu(cpu, &a53_pwr_clk.cpumask);
+		if (logical_cpu_to_clk(cpu) == &perf_clk.c)
+			cpumask_set_cpu(cpu, &perf_clk.cpumask);
+		if (logical_cpu_to_clk(cpu) == &pwr_clk.c)
+			cpumask_set_cpu(cpu, &pwr_clk.cpumask);
 	}
 
-	a53_pwr_clk.hw_low_power_ctrl = true;
-	a53_perf_clk.hw_low_power_ctrl = true;
+	pwr_clk.hw_low_power_ctrl = true;
+	perf_clk.hw_low_power_ctrl = true;
 
 	register_pm_notifier(&clock_sdm632_pm_notifier);
 
@@ -1073,19 +1010,19 @@
 	if (!ofnode)
 		return 0;
 
-	rc = lpm_get_latency(&a53_perf_clk.latency_lvl,
-			&a53_perf_clk.cpu_latency_no_l2_pc_us);
+	rc = lpm_get_latency(&perf_clk.latency_lvl,
+			&perf_clk.cpu_latency_no_l2_pc_us);
 	if (rc < 0)
 		pr_err("Failed to get the L2 PC value for perf\n");
 
-	rc = lpm_get_latency(&a53_pwr_clk.latency_lvl,
-			&a53_pwr_clk.cpu_latency_no_l2_pc_us);
+	rc = lpm_get_latency(&pwr_clk.latency_lvl,
+			&pwr_clk.cpu_latency_no_l2_pc_us);
 	if (rc < 0)
 		pr_err("Failed to get the L2 PC value for pwr\n");
 
 	pr_debug("Latency for pwr/perf cluster %d : %d\n",
-		a53_pwr_clk.cpu_latency_no_l2_pc_us,
-		a53_perf_clk.cpu_latency_no_l2_pc_us);
+		pwr_clk.cpu_latency_no_l2_pc_us,
+		perf_clk.cpu_latency_no_l2_pc_us);
 
 	return rc;
 }
@@ -1100,6 +1037,9 @@
 #define SRC_SEL				0x4
 #define SRC_DIV				0x1
 
+/* Dummy clock for setting the rate of CCI PLL in early_init*/
+DEFINE_CLK_DUMMY(p_clk, 19200000);
+
 static int __init cpu_clock_init(void)
 {
 	void __iomem  *base;
@@ -1127,6 +1067,7 @@
 	apcs_c1_pll.c.ops->set_rate(&apcs_c1_pll.c, perfcl_early_boot_rate);
 	clk_ops_variable_rate_pll.enable(&apcs_c1_pll.c);
 
+	apcs_cci_pll.c.parent = (struct clk *)&p_clk;
 	apcs_cci_pll.c.ops->set_rate(&apcs_cci_pll.c, cci_early_boot_rate);
 	clk_ops_dyna_alpha_pll.enable(&apcs_cci_pll.c);
 
diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c b/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c
index 20b8e34..7121261 100644
--- a/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c
+++ b/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c
@@ -424,8 +424,8 @@
 	pdb->in.pll_ip_trim = 4;	/* 4, reg: 0x0404 */
 	pdb->in.pll_cpcset_cur = 1;	/* 1, reg: 0x04f0, bit 0 - 2 */
 	pdb->in.pll_cpmset_cur = 1;	/* 1, reg: 0x04f0, bit 3 - 5 */
-	pdb->in.pll_icpmset = 4;	/* 4, reg: 0x04fc, bit 3 - 5 */
-	pdb->in.pll_icpcset = 4;	/* 4, reg: 0x04fc, bit 0 - 2 */
+	pdb->in.pll_icpmset = 7;	/* 7, reg: 0x04fc, bit 3 - 5 */
+	pdb->in.pll_icpcset = 7;	/* 7, reg: 0x04fc, bit 0 - 2 */
 	pdb->in.pll_icpmset_p = 0;	/* 0, reg: 0x04f4, bit 0 - 2 */
 	pdb->in.pll_icpmset_m = 0;	/* 0, reg: 0x04f4, bit 3 - 5 */
 	pdb->in.pll_icpcset_p = 0;	/* 0, reg: 0x04f8, bit 0 - 2 */
diff --git a/drivers/clk/qcom/gpucc-sdm845.c b/drivers/clk/qcom/gpucc-sdm845.c
index 53446a2..8dfdf85 100644
--- a/drivers/clk/qcom/gpucc-sdm845.c
+++ b/drivers/clk/qcom/gpucc-sdm845.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -290,6 +290,7 @@
 	F(267000000, P_CRC_DIV,  1, 0, 0),
 	F(355000000, P_CRC_DIV,  1, 0, 0),
 	F(430000000, P_CRC_DIV,  1, 0, 0),
+	F(504000000, P_CRC_DIV,  1, 0, 0),
 	F(565000000, P_CRC_DIV,  1, 0, 0),
 	F(650000000, P_CRC_DIV,  1, 0, 0),
 	F(700000000, P_CRC_DIV,  1, 0, 0),
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 7fca843..013b0c8 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -1256,13 +1256,13 @@
 				&cluster->child_cpus))
 		goto unlock_and_return;
 
-	state_id |= get_cluster_id(cluster->parent, aff_lvl, from_idle);
+	state_id += get_cluster_id(cluster->parent, aff_lvl, from_idle);
 
 	if (cluster->last_level != cluster->default_level) {
 		struct lpm_cluster_level *level
 			= &cluster->levels[cluster->last_level];
 
-		state_id |= (level->psci_id & cluster->psci_mode_mask)
+		state_id += (level->psci_id & cluster->psci_mode_mask)
 					<< cluster->psci_mode_shift;
 
 		/*
@@ -1272,7 +1272,7 @@
 		if (level->notify_rpm)
 			if (sys_pm_ops && sys_pm_ops->update_wakeup)
 				sys_pm_ops->update_wakeup(from_idle);
-		if (level->psci_id)
+		if (cluster->psci_mode_shift)
 			(*aff_lvl)++;
 	}
 unlock_and_return:
@@ -1303,7 +1303,7 @@
 	state_id = get_cluster_id(cpu->parent, &affinity_level, from_idle);
 	power_state = PSCI_POWER_STATE(cpu->levels[idx].is_reset);
 	affinity_level = PSCI_AFFINITY_LEVEL(affinity_level);
-	state_id |= power_state | affinity_level | cpu->levels[idx].psci_id;
+	state_id += power_state + affinity_level + cpu->levels[idx].psci_id;
 
 	update_debug_pc_event(CPU_ENTER, state_id,
 			0xdeaffeed, 0xdeaffeed, from_idle);
diff --git a/drivers/gpu/drm/bridge/lt9611.c b/drivers/gpu/drm/bridge/lt9611.c
index 887dd6f..dd2d54f 100644
--- a/drivers/gpu/drm/bridge/lt9611.c
+++ b/drivers/gpu/drm/bridge/lt9611.c
@@ -24,6 +24,7 @@
 #include <linux/i2c.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
+#include <linux/component.h>
 #include <linux/of_gpio.h>
 #include <linux/of_graph.h>
 #include <linux/of_irq.h>
@@ -1687,6 +1688,22 @@
 	return 0;
 }
 
+static void lt9611_set_preferred_mode(struct drm_connector *connector)
+{
+	struct lt9611 *pdata = connector_to_lt9611(connector);
+	struct drm_display_mode *mode;
+	const char *string;
+
+	/* use specified mode as preferred */
+	if (!of_property_read_string(pdata->dev->of_node,
+			"lt,preferred-mode", &string)) {
+		list_for_each_entry(mode, &connector->probed_modes, head) {
+			if (!strcmp(mode->name, string))
+				mode->type |= DRM_MODE_TYPE_PREFERRED;
+		}
+	}
+}
+
 static int lt9611_connector_get_modes(struct drm_connector *connector)
 {
 	struct lt9611 *pdata = connector_to_lt9611(connector);
@@ -1719,12 +1736,11 @@
 		pdata->hdmi_mode = drm_detect_hdmi_monitor(edid);
 		pr_debug("hdmi_mode = %d\n", pdata->hdmi_mode);
 
-		/* TODO: this should not be hard coded */
-		drm_set_preferred_mode(connector, 1920, 1080);
-
 		kfree(edid);
 	}
 
+	lt9611_set_preferred_mode(connector);
+
 	return count;
 }
 
@@ -1997,6 +2013,20 @@
 	sysfs_remove_group(&dev->kobj, &lt9611_sysfs_attr_grp);
 }
 
+static int lt9611_bind(struct device *dev, struct device *master, void *data)
+{
+	return 0;
+}
+
+static void lt9611_unbind(struct device *dev, struct device *master, void *data)
+{
+}
+
+static const struct component_ops lt9611_comp_ops = {
+	.bind = lt9611_bind,
+	.unbind = lt9611_unbind,
+};
+
 static int lt9611_probe(struct i2c_client *client,
 	 const struct i2c_device_id *id)
 {
@@ -2078,6 +2108,10 @@
 
 	drm_bridge_add(&pdata->bridge);
 
+	ret = component_add(&client->dev, &lt9611_comp_ops);
+	if (ret)
+		pr_err("component add failed, rc=%d\n", ret);
+
 	return ret;
 
 err_sysfs_init:
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
index 189a5c3..434d383 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_clk_manager.c
@@ -1078,12 +1078,7 @@
 	struct dsi_clk_mngr *mngr;
 	struct dsi_link_clks *l_clks;
 
-	if (!client) {
-		pr_err("%s: Invalid arg\n", __func__);
-		return -EINVAL;
-	}
 	mngr = c->mngr;
-
 	mutex_lock(&mngr->clk_mutex);
 
 	l_clks = mngr->link_clks;
@@ -1133,8 +1128,6 @@
 	mutex_lock(&dsi_mngr_clk_mutex);
 
 	rc = dsi_display_link_clk_force_update(handle);
-	if (rc && (rc != -EAGAIN))
-		pr_err("%s: failed set clk state, rc = %d\n", __func__, rc);
 
 	mutex_unlock(&dsi_mngr_clk_mutex);
 
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index c9e8a01..1ab1de6 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -1333,6 +1333,9 @@
 	u32 dlen, diff, rlen = msg->rx_len;
 	unsigned char *buff;
 	char cmd;
+	struct dsi_cmd_desc *of_cmd;
+
+	of_cmd = container_of(msg, struct dsi_cmd_desc, msg);
 
 	if (msg->rx_len <= 2) {
 		short_resp = true;
@@ -1366,6 +1369,13 @@
 			pr_err("Message transmission failed, rc=%d\n", rc);
 			goto error;
 		}
+		/*
+		 * wait before reading rdbk_data register, if any delay is
+		 * required after sending the read command.
+		 */
+		if (of_cmd && of_cmd->post_wait_ms)
+			usleep_range(of_cmd->post_wait_ms * 1000,
+				     ((of_cmd->post_wait_ms * 1000) + 10));
 
 		dlen = dsi_ctrl->hw.ops.get_cmd_read_data(&dsi_ctrl->hw,
 					buff, total_bytes_read,
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 f0e7ba6..c1af52f 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
@@ -1487,7 +1487,7 @@
 	rc = readl_poll_timeout(ctrl->base + DSI_STATUS, val,
 			!(val & cmd_mode_mdp_busy_mask), sleep_us, timeout_us);
 	if (rc)
-		pr_err("%s: waiting failed, ret=%d\n", __func__, rc);
+		pr_err("%s: timed out waiting for idle\n", __func__);
 
 	return rc;
 }
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 5b19aee..c79a72a 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -349,7 +349,7 @@
 
 static void dsi_display_register_te_irq(struct dsi_display *display)
 {
-	int rc;
+	int rc = 0;
 	struct platform_device *pdev;
 	struct device *dev;
 
@@ -365,18 +365,31 @@
 		return;
 	}
 
+	if (!gpio_is_valid(display->disp_te_gpio)) {
+		rc = -EINVAL;
+		goto error;
+	}
+
+	init_completion(&display->esd_te_gate);
+
 	rc = devm_request_irq(dev, gpio_to_irq(display->disp_te_gpio),
 			dsi_display_panel_te_irq_handler, IRQF_TRIGGER_FALLING,
 			"TE_GPIO", display);
 	if (rc) {
 		pr_err("TE request_irq failed for ESD rc:%d\n", rc);
-		return;
+		goto error;
 	}
 
-	init_completion(&display->esd_te_gate);
-
 	disable_irq(gpio_to_irq(display->disp_te_gpio));
 	display->is_te_irq_enabled = false;
+
+	return;
+
+error:
+	/* disable the TE based ESD check */
+	pr_warn("Unable to register for TE IRQ\n");
+	if (display->panel->esd_config.status_mode == ESD_MODE_PANEL_TE)
+		display->panel->esd_config.esd_enabled = false;
 }
 
 static bool dsi_display_is_te_based_esd(struct dsi_display *display)
@@ -555,14 +568,14 @@
 	lenp = config->status_valid_params ?: config->status_cmds_rlen;
 	count = config->status_cmd.count;
 	cmds = config->status_cmd.cmds;
-	if (cmds->last_command) {
-		cmds->msg.flags |= MIPI_DSI_MSG_LASTCOMMAND;
-		flags |= DSI_CTRL_CMD_LAST_COMMAND;
-	}
 	flags |= (DSI_CTRL_CMD_FETCH_MEMORY | DSI_CTRL_CMD_READ);
 
 	for (i = 0; i < count; ++i) {
 		memset(config->status_buf, 0x0, SZ_4K);
+		if (cmds[i].last_command) {
+			cmds[i].msg.flags |= MIPI_DSI_MSG_LASTCOMMAND;
+			flags |= DSI_CTRL_CMD_LAST_COMMAND;
+		}
 		cmds[i].msg.rx_buf = config->status_buf;
 		cmds[i].msg.rx_len = config->status_cmds_rlen[i];
 		rc = dsi_ctrl_cmd_transfer(ctrl->ctrl, &cmds[i].msg, flags);
@@ -646,7 +659,7 @@
 
 		rc = dsi_display_validate_status(ctrl, display->panel);
 		if (rc <= 0) {
-			pr_err("[%s] read status failed on master,rc=%d\n",
+			pr_err("[%s] read status failed on slave,rc=%d\n",
 			       display->name, rc);
 			goto exit;
 		}
@@ -1791,7 +1804,8 @@
 	enum dsi_engine_state host_state = DSI_CTRL_ENGINE_ON;
 
 	/* Sequence does not matter for split dsi usecases */
-	for (i = 0; i < display->ctrl_count; i++) {
+	for (i = 0; (i < display->ctrl_count) &&
+			(i < MAX_DSI_CTRLS_PER_DISPLAY); i++) {
 		ctrl = &display->ctrl[i];
 		if (!ctrl->ctrl)
 			continue;
@@ -3958,8 +3972,13 @@
 	struct dsi_display *display = dsi_display;
 	int rc = 0;
 
+	if (!display) {
+		pr_err("Invalid display\n");
+		return -EINVAL;
+	}
+
 	/* Continuous splash not supported by external bridge */
-	if (!display || dsi_display_has_ext_bridge(display)) {
+	if (dsi_display_has_ext_bridge(display)) {
 		display->is_cont_splash_enabled = false;
 		return 0;
 	}
@@ -4073,11 +4092,6 @@
 {
 	int rc = 0;
 
-	if (!display || !display->panel) {
-		pr_err("Invalid params\n");
-		return -EINVAL;
-	}
-
 	rc = dsi_display_link_clk_force_update_ctrl(display->dsi_clk_handle);
 
 	if (!rc) {
@@ -4085,8 +4099,6 @@
 			display->cached_clk_rate);
 
 		atomic_set(&display->clkrate_change_pending, 0);
-	} else if (rc == -EAGAIN) {
-		pr_info("Clock is disabled, update it next time\n");
 	} else {
 		pr_err("Failed to configure dsi bit clock '%d'. rc = %d\n",
 			display->cached_clk_rate, rc);
@@ -4102,7 +4114,7 @@
 	int i;
 
 	pr_debug("%s:bit rate:%d\n", __func__, bit_clk_rate);
-	if (!display || !display->panel) {
+	if (!display->panel) {
 		pr_err("Invalid params\n");
 		return -EINVAL;
 	}
@@ -4181,11 +4193,6 @@
 	struct dsi_display_ctrl *m_ctrl;
 	struct dsi_ctrl *ctrl;
 
-	if (!dev) {
-		pr_err("Invalid device\n");
-		return -EINVAL;
-	}
-
 	display = dev_get_drvdata(dev);
 	if (!display) {
 		pr_err("Invalid display\n");
@@ -4201,7 +4208,7 @@
 					byte_clk_rate * 8;
 
 	rc = snprintf(buf, PAGE_SIZE, "%d\n", display->cached_clk_rate);
-	pr_info("%s: read dsi clk rate %d\n", __func__,
+	pr_debug("%s: read dsi clk rate %d\n", __func__,
 		display->cached_clk_rate);
 
 	mutex_unlock(&display->display_lock);
@@ -4216,11 +4223,6 @@
 	int clk_rate;
 	struct dsi_display *display;
 
-	if (!dev) {
-		pr_err("Invalid device\n");
-		return -EINVAL;
-	}
-
 	display = dev_get_drvdata(dev);
 	if (!display) {
 		pr_err("Invalid display\n");
@@ -5184,6 +5186,53 @@
 	return rc;
 }
 
+int dsi_display_get_panel_vfp(void *dsi_display,
+	int h_active, int v_active)
+{
+	int i, rc = 0;
+	u32 count, refresh_rate = 0;
+	struct dsi_dfps_capabilities dfps_caps;
+	struct dsi_display *display = (struct dsi_display *)dsi_display;
+
+	if (!display)
+		return -EINVAL;
+
+	rc = dsi_display_get_mode_count(display, &count);
+	if (rc)
+		return rc;
+
+	mutex_lock(&display->display_lock);
+
+	if (display->panel && display->panel->cur_mode)
+		refresh_rate = display->panel->cur_mode->timing.refresh_rate;
+
+	dsi_panel_get_dfps_caps(display->panel, &dfps_caps);
+	if (dfps_caps.dfps_support)
+		refresh_rate = dfps_caps.max_refresh_rate;
+
+	if (!refresh_rate) {
+		mutex_unlock(&display->display_lock);
+		pr_err("Null Refresh Rate\n");
+		return -EINVAL;
+	}
+
+	h_active *= display->ctrl_count;
+
+	for (i = 0; i < count; i++) {
+		struct dsi_display_mode *m = &display->modes[i];
+
+		if (m && v_active == m->timing.v_active &&
+			h_active == m->timing.h_active &&
+			refresh_rate == m->timing.refresh_rate) {
+			rc = m->timing.v_front_porch;
+			break;
+		}
+	}
+	mutex_unlock(&display->display_lock);
+
+	return rc;
+}
+
 int dsi_display_find_mode(struct dsi_display *display,
 		const struct dsi_display_mode *cmp,
 		struct dsi_display_mode **out_mode)
@@ -5835,18 +5884,19 @@
 		goto error_host_engine_off;
 	}
 
-	rc = dsi_display_soft_reset(display);
-	if (rc) {
-		pr_err("[%s] failed soft reset, rc=%d\n", display->name, rc);
-		goto error_ctrl_link_off;
-	}
-
 	if (!display->is_cont_splash_enabled) {
 		/*
-		 * For continuous splash usecase we skip panel
-		 * prepare since the pnael is already in
-		 * active state and panel on commands are not needed
+		 * For continuous splash usecase, skip panel prepare and
+		 * ctl reset since the pnael and ctrl is already in active
+		 * state and panel on commands are not needed
 		 */
+		rc = dsi_display_soft_reset(display);
+		if (rc) {
+			pr_err("[%s] failed soft reset, rc=%d\n",
+					display->name, rc);
+			goto error_ctrl_link_off;
+		}
+
 		rc = dsi_panel_prepare(display->panel);
 		if (rc) {
 			pr_err("[%s] panel prepare failed, rc=%d\n",
@@ -6023,11 +6073,8 @@
 			int ret = 0;
 
 			ret = dsi_ctrl_wait_for_cmd_mode_mdp_idle(ctrl);
-			if (ret) {
-				pr_info("Failed to wait for cmd engine not to be busy sending data from MDP, rc: %d\n",
-					ret);
+			if (ret)
 				goto wait_failure;
-			}
 		}
 
 		/*
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
index 0a84c6f..85fd65c1 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
@@ -647,4 +647,14 @@
  * Return: Zero on Success
  */
 int dsi_display_cont_splash_config(void *display);
+/*
+ * dsi_display_get_panel_vfp - get panel vsync
+ * @display: Pointer to private display structure
+ * @h_active: width
+ * @v_active: height
+ * Returns: v_front_porch on success error code on failure
+ */
+int dsi_display_get_panel_vfp(void *display,
+	int h_active, int v_active);
+
 #endif /* _DSI_DISPLAY_H_ */
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index d5437d0..19df8be 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1434,9 +1434,10 @@
 	struct drm_minor *minor = file_priv->minor;
 	struct drm_device *dev = minor->dev;
 	struct msm_drm_private *priv = dev->dev_private;
-	struct msm_drm_event *node, *temp;
+	struct msm_drm_event *node, *temp, *tmp_node;
 	u32 count;
 	unsigned long flags;
+	LIST_HEAD(tmp_head);
 
 	spin_lock_irqsave(&dev->event_lock, flags);
 	list_for_each_entry_safe(node, temp, &priv->client_event_list,
@@ -1444,14 +1445,25 @@
 		if (node->base.file_priv != file_priv)
 			continue;
 		list_del(&node->base.link);
-		spin_unlock_irqrestore(&dev->event_lock, flags);
-		count = msm_event_client_count(dev, &node->info, true);
+		list_add_tail(&node->base.link, &tmp_head);
+	}
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	list_for_each_entry_safe(node, temp, &tmp_head,
+			base.link) {
+		list_del(&node->base.link);
+		count = msm_event_client_count(dev, &node->info, false);
+
+		list_for_each_entry(tmp_node, &tmp_head, base.link) {
+			if (tmp_node->event.type == node->info.event &&
+				tmp_node->info.object_id ==
+					node->info.object_id)
+				count++;
+		}
 		if (!count)
 			msm_register_event(dev, &node->info, file_priv, false);
 		kfree(node);
-		spin_lock_irqsave(&dev->event_lock, flags);
 	}
-	spin_unlock_irqrestore(&dev->event_lock, flags);
 
 	return drm_release(inode, filp);
 }
@@ -1806,6 +1818,27 @@
 	return ret;
 }
 
+static int add_bridge_components(struct device *dev,
+				  struct component_match **matchptr)
+{
+	struct device_node *node;
+
+	if (of_device_is_compatible(dev->of_node, "qcom,sde-kms")) {
+		struct device_node *np = dev->of_node;
+		unsigned int i;
+
+		for (i = 0; ; i++) {
+			node = of_parse_phandle(np, "bridges", i);
+			if (!node)
+				break;
+
+			component_match_add(dev, matchptr, compare_of, node);
+		}
+	}
+
+	return 0;
+}
+
 struct msm_gem_address_space *
 msm_gem_smmu_address_space_get(struct drm_device *dev,
 		unsigned int domain)
@@ -1897,6 +1930,10 @@
 	if (ret)
 		return ret;
 
+	ret = add_bridge_components(&pdev->dev, &match);
+	if (ret)
+		return ret;
+
 	pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
 	return component_master_add_with_match(&pdev->dev, &msm_drm_ops, match);
 }
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index f908e7f..e59c5f0 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -414,6 +414,10 @@
 	if (!c_conn)
 		return;
 
+	/* Return if there is no change in ESD status check condition */
+	if (en == c_conn->esd_status_check)
+		return;
+
 	sde_connector_get_info(connector, &info);
 	if (c_conn->ops.check_status &&
 		(info.capabilities & MSM_DISPLAY_ESD_ENABLED)) {
@@ -430,9 +434,11 @@
 			/* Schedule ESD status check */
 			schedule_delayed_work(&c_conn->status_work,
 				msecs_to_jiffies(interval));
+			c_conn->esd_status_check = true;
 		} else {
 			/* Cancel any pending ESD status check */
 			cancel_delayed_work_sync(&c_conn->status_work);
+			c_conn->esd_status_check = false;
 		}
 	}
 }
@@ -482,11 +488,12 @@
 	}
 	c_conn->last_panel_power_mode = mode;
 
-	if (mode != SDE_MODE_DPMS_ON) {
-		mutex_unlock(&c_conn->lock);
+	mutex_unlock(&c_conn->lock);
+	if (mode != SDE_MODE_DPMS_ON)
 		sde_connector_schedule_status_work(connector, false);
-		mutex_lock(&c_conn->lock);
-	}
+	else
+		sde_connector_schedule_status_work(connector, true);
+	mutex_lock(&c_conn->lock);
 
 	return rc;
 }
@@ -1404,6 +1411,28 @@
 	return 0;
 }
 
+int sde_connector_get_panel_vfp(struct drm_connector *connector,
+	struct drm_display_mode *mode)
+{
+	struct sde_connector *c_conn;
+	int vfp = -EINVAL;
+
+	if (!connector || !mode) {
+		SDE_ERROR("invalid connector\n");
+		return vfp;
+	}
+	c_conn = to_sde_connector(connector);
+	if (!c_conn->ops.get_panel_vfp)
+		return vfp;
+
+	vfp = c_conn->ops.get_panel_vfp(c_conn->display,
+		mode->hdisplay, mode->vdisplay);
+	if (vfp <= 0)
+		SDE_ERROR("Failed get_panel_vfp %d\n", vfp);
+
+	return vfp;
+}
+
 static int _sde_debugfs_conn_cmd_tx_open(struct inode *inode, struct file *file)
 {
 	/* non-seekable */
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index 1495622..ef2385e 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -257,6 +257,15 @@
 	 * Returns: zero for success, negetive for failure
 	 */
 	int (*cont_splash_config)(void *display);
+
+	/**
+	 * get_panel_vfp - returns original panel vfp
+	 * @display: Pointer to private display handle
+	 * @h_active: width
+	 * @v_active: height
+	 * Returns: v_front_porch on success error-code on failure
+	 */
+	int (*get_panel_vfp)(void *display, int h_active, int v_active);
 };
 
 /**
@@ -356,6 +365,8 @@
 	u32 force_panel_dead;
 	u32 esd_status_interval;
 
+	bool esd_status_check;
+
 	bool bl_scale_dirty;
 	u32 bl_scale;
 	u32 bl_scale_ad;
@@ -750,4 +761,13 @@
  */
 void sde_connector_helper_bridge_disable(struct drm_connector *connector);
 
+/**
+ * sde_connector_get_panel_vfp - helper to get panel vfp
+ * @connector: pointer to drm connector
+ * @h_active: panel width
+ * @v_active: panel heigth
+ * Returns: v_front_porch on success error-code on failure
+ */
+int sde_connector_get_panel_vfp(struct drm_connector *connector,
+	struct drm_display_mode *mode);
 #endif /* _SDE_CONNECTOR_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 7649012..7bc01c3 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -4080,6 +4080,7 @@
 
 static void sde_crtc_disable(struct drm_crtc *crtc)
 {
+	struct sde_kms *sde_kms;
 	struct sde_crtc *sde_crtc;
 	struct sde_crtc_state *cstate;
 	struct drm_encoder *encoder;
@@ -4095,6 +4096,12 @@
 		return;
 	}
 
+	sde_kms = _sde_crtc_get_kms(crtc);
+	if (!sde_kms) {
+		SDE_ERROR("invalid kms\n");
+		return;
+	}
+
 	if (!sde_kms_power_resource_is_enabled(crtc->dev)) {
 		SDE_ERROR("power resource is not enabled\n");
 		return;
@@ -4160,7 +4167,9 @@
 	}
 	spin_unlock_irqrestore(&sde_crtc->spin_lock, flags);
 
-	sde_core_perf_crtc_update(crtc, 0, true);
+	/* avoid clk/bw downvote if cont-splash is enabled */
+	if (!sde_kms->splash_data.cont_splash_en)
+		sde_core_perf_crtc_update(crtc, 0, true);
 
 	drm_for_each_encoder(encoder, crtc->dev) {
 		if (encoder->crtc != crtc)
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 1614c83..3021496 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -2723,8 +2723,11 @@
 	sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_STOP);
 
 	for (i = 0; i < sde_enc->num_phys_encs; i++) {
-		if (sde_enc->phys_encs[i])
+		if (sde_enc->phys_encs[i]) {
+			sde_enc->phys_encs[i]->cont_splash_settings = false;
+			sde_enc->phys_encs[i]->cont_splash_single_flush = 0;
 			sde_enc->phys_encs[i]->connector = NULL;
+		}
 	}
 
 	sde_enc->cur_master = NULL;
@@ -4793,14 +4796,18 @@
 			return -EINVAL;
 		}
 
+		/* update connector for master and slave phys encoders */
+		phys->connector = conn;
+		phys->cont_splash_single_flush =
+			sde_kms->splash_data.single_flush_en;
+		phys->cont_splash_settings = true;
+
 		phys->hw_pp = sde_enc->hw_pp[i];
 		if (phys->ops.cont_splash_mode_set)
 			phys->ops.cont_splash_mode_set(phys, drm_mode);
 
-		if (phys->ops.is_master && phys->ops.is_master(phys)) {
-			phys->connector = conn;
+		if (phys->ops.is_master && phys->ops.is_master(phys))
 			sde_enc->cur_master = phys;
-		}
 	}
 
 	return ret;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index a877eb5..9557d41 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.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
@@ -261,6 +261,10 @@
  *                              fences that have to be signalled.
  * @pending_kickoff_wq:		Wait queue for blocking until kickoff completes
  * @irq:			IRQ tracking structures
+ * @cont_splash_single_flush	Variable to check if single flush is enabled.
+ * @cont_splash_settings	Variable to store continuous splash settings.
+ * @vfp_cached:			cached vertical front porch to be used for
+ *				programming ROT and MDP fetch start
  */
 struct sde_encoder_phys {
 	struct drm_encoder *parent;
@@ -288,6 +292,9 @@
 	atomic_t pending_retire_fence_cnt;
 	wait_queue_head_t pending_kickoff_wq;
 	struct sde_encoder_irq irq[INTR_IDX_MAX];
+	u32 cont_splash_single_flush;
+	bool cont_splash_settings;
+	int vfp_cached;
 };
 
 static inline int sde_encoder_phys_inc_pending(struct sde_encoder_phys *phys)
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index 792654d..3edaed3 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -382,6 +382,13 @@
 	phys_enc->cached_mode = *adj_mode;
 	phys_enc->enable_state = SDE_ENC_ENABLED;
 
+	if (!phys_enc->hw_ctl || !phys_enc->hw_pp) {
+		SDE_DEBUG("invalid ctl:%d pp:%d\n",
+			(phys_enc->hw_ctl == NULL),
+			(phys_enc->hw_pp == NULL));
+		return;
+	}
+
 	_sde_encoder_phys_cmd_setup_irq_hw_idx(phys_enc);
 }
 
@@ -845,9 +852,8 @@
 	struct sde_encoder_phys_cmd *cmd_enc =
 		to_sde_encoder_phys_cmd(phys_enc);
 
-	if (!phys_enc || !phys_enc->hw_ctl || !phys_enc->hw_pp
-			|| !phys_enc->hw_ctl->ops.setup_intf_cfg) {
-		SDE_ERROR("invalid arg(s), enc %d\n", phys_enc != 0);
+	if (!phys_enc || !phys_enc->hw_pp) {
+		SDE_ERROR("invalid arg(s), enc %d\n", phys_enc != NULL);
 		return;
 	}
 
@@ -866,7 +872,9 @@
 	if (!phys_enc)
 		return false;
 
-	return _sde_encoder_phys_is_ppsplit(phys_enc);
+	return phys_enc->cont_splash_settings ?
+		phys_enc->cont_splash_single_flush :
+		_sde_encoder_phys_is_ppsplit(phys_enc);
 }
 
 static void sde_encoder_phys_cmd_enable_helper(
@@ -875,7 +883,7 @@
 	struct sde_hw_ctl *ctl;
 	u32 flush_mask = 0;
 
-	if (!phys_enc || !phys_enc->hw_ctl || !phys_enc->hw_pp) {
+	if (!phys_enc || !phys_enc->hw_pp) {
 		SDE_ERROR("invalid arg(s), encoder %d\n", phys_enc != 0);
 		return;
 	}
@@ -892,6 +900,11 @@
 		!sde_encoder_phys_cmd_is_master(phys_enc))
 		goto skip_flush;
 
+	if (!phys_enc->hw_ctl) {
+		SDE_ERROR("invalid ctl\n");
+		return;
+	}
+
 	ctl = phys_enc->hw_ctl;
 	ctl->ops.get_bitmask_intf(ctl, &flush_mask, phys_enc->intf_idx);
 	ctl->ops.update_pending_flush(ctl, flush_mask);
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 a3f09b6..dd72665 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -101,6 +101,7 @@
 	timing->border_clr = 0;
 	timing->underflow_clr = 0xff;
 	timing->hsync_skew = mode->hskew;
+	timing->v_front_porch_fixed = vid_enc->base.vfp_cached;
 
 	/* DSI controller cannot handle active-low sync signals. */
 	if (vid_enc->hw_intf->cap->type == INTF_DSI) {
@@ -130,12 +131,16 @@
 	return active + inactive;
 }
 
-static inline u32 get_vertical_total(const struct intf_timing_params *timing)
+static inline u32 get_vertical_total(const struct intf_timing_params *timing,
+	bool use_fixed_vfp)
 {
+	u32 inactive;
 	u32 active = timing->yres;
-	u32 inactive =
-	    timing->v_back_porch + timing->v_front_porch +
-	    timing->vsync_pulse_width;
+	u32 v_front_porch = use_fixed_vfp ?
+		timing->v_front_porch_fixed : timing->v_front_porch;
+
+	inactive = timing->v_back_porch + v_front_porch +
+			    timing->vsync_pulse_width;
 	return active + inactive;
 }
 
@@ -155,7 +160,8 @@
  */
 static u32 programmable_fetch_get_num_lines(
 		struct sde_encoder_phys_vid *vid_enc,
-		const struct intf_timing_params *timing)
+		const struct intf_timing_params *timing,
+		bool use_fixed_vfp)
 {
 	u32 worst_case_needed_lines =
 	    vid_enc->hw_intf->cap->prog_fetch_lines_worst_case;
@@ -163,19 +169,21 @@
 	    timing->v_back_porch + timing->vsync_pulse_width;
 	u32 needed_vfp_lines = worst_case_needed_lines - start_of_frame_lines;
 	u32 actual_vfp_lines = 0;
+	u32 v_front_porch = use_fixed_vfp ?
+		timing->v_front_porch_fixed : timing->v_front_porch;
 
 	/* Fetch must be outside active lines, otherwise undefined. */
 	if (start_of_frame_lines >= worst_case_needed_lines) {
 		SDE_DEBUG_VIDENC(vid_enc,
 				"prog fetch is not needed, large vbp+vsw\n");
 		actual_vfp_lines = 0;
-	} else if (timing->v_front_porch < needed_vfp_lines) {
+	} else if (v_front_porch < needed_vfp_lines) {
 		/* Warn fetch needed, but not enough porch in panel config */
 		pr_warn_once
 			("low vbp+vfp may lead to perf issues in some cases\n");
 		SDE_DEBUG_VIDENC(vid_enc,
 				"less vfp than fetch req, using entire vfp\n");
-		actual_vfp_lines = timing->v_front_porch;
+		actual_vfp_lines = v_front_porch;
 	} else {
 		SDE_DEBUG_VIDENC(vid_enc, "room in vfp for needed prefetch\n");
 		actual_vfp_lines = needed_vfp_lines;
@@ -183,7 +191,7 @@
 
 	SDE_DEBUG_VIDENC(vid_enc,
 		"v_front_porch %u v_back_porch %u vsync_pulse_width %u\n",
-		timing->v_front_porch, timing->v_back_porch,
+		v_front_porch, timing->v_back_porch,
 		timing->vsync_pulse_width);
 	SDE_DEBUG_VIDENC(vid_enc,
 		"wc_lines %u needed_vfp_lines %u actual_vfp_lines %u\n",
@@ -217,9 +225,10 @@
 	if (WARN_ON_ONCE(!vid_enc->hw_intf->ops.setup_prg_fetch))
 		return;
 
-	vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc, timing);
+	vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc,
+							   timing, true);
 	if (vfp_fetch_lines) {
-		vert_total = get_vertical_total(timing);
+		vert_total = get_vertical_total(timing, true);
 		horiz_total = get_horizontal_total(timing);
 		vfp_fetch_start_vsync_counter =
 		    (vert_total - vfp_fetch_lines) * horiz_total + 1;
@@ -270,9 +279,10 @@
 		return;
 
 	timing = &vid_enc->timing_params;
-	vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc, timing);
+	vfp_fetch_lines = programmable_fetch_get_num_lines(vid_enc,
+							   timing, true);
 	if (rot_fetch_lines) {
-		vert_total = get_vertical_total(timing);
+		vert_total = get_vertical_total(timing, true);
 		horiz_total = get_horizontal_total(timing);
 		if (vert_total >= (vfp_fetch_lines + rot_fetch_lines)) {
 			rot_fetch_start_vsync_counter =
@@ -372,6 +382,13 @@
 			mode.hsync_start, mode.hsync_end);
 	}
 
+	if (!phys_enc->vfp_cached) {
+		phys_enc->vfp_cached =
+			sde_connector_get_panel_vfp(phys_enc->connector, &mode);
+		if (phys_enc->vfp_cached <= 0)
+			phys_enc->vfp_cached = mode.vsync_start - mode.vdisplay;
+	}
+
 	drm_mode_to_intf_timing_params(vid_enc, &mode, &timing_params);
 
 	vid_enc->timing_params = timing_params;
@@ -511,8 +528,11 @@
 static bool sde_encoder_phys_vid_needs_single_flush(
 		struct sde_encoder_phys *phys_enc)
 {
-	return phys_enc && (_sde_encoder_phys_is_ppsplit(phys_enc) ||
-		_sde_encoder_phys_is_dual_ctl(phys_enc));
+	return phys_enc && (
+		phys_enc->cont_splash_settings ?
+		phys_enc->cont_splash_single_flush :
+		(_sde_encoder_phys_is_ppsplit(phys_enc) ||
+		_sde_encoder_phys_is_dual_ctl(phys_enc)));
 }
 
 static void _sde_encoder_phys_vid_setup_irq_hw_idx(
@@ -956,6 +976,7 @@
 		sde_encoder_phys_vid_control_vblank_irq(phys_enc, false);
 	}
 exit:
+	phys_enc->vfp_cached = 0;
 	phys_enc->enable_state = SDE_ENC_DISABLED;
 }
 
diff --git a/drivers/gpu/drm/msm/sde/sde_formats.c b/drivers/gpu/drm/msm/sde/sde_formats.c
index d09054e..719b8c1 100644
--- a/drivers/gpu/drm/msm/sde/sde_formats.c
+++ b/drivers/gpu/drm/msm/sde/sde_formats.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -275,97 +275,97 @@
 
 	INTERLEAVED_RGB_FMT(ARGB1555,
 		COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
-		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
+		C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
 		true, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(ABGR1555,
 		COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
-		C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
+		C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
 		true, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(RGBA5551,
 		COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
-		C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
+		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
 		true, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(BGRA5551,
 		COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
-		C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
+		C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
 		true, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(XRGB1555,
 		COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
-		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
+		C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
 		false, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(XBGR1555,
 		COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
-		C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
+		C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
 		false, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(RGBX5551,
 		COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
-		C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
+		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
 		false, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(BGRX5551,
 		COLOR_ALPHA_1BIT, COLOR_5BIT, COLOR_5BIT, COLOR_5BIT,
-		C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
+		C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
 		false, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(ARGB4444,
 		COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
-		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
+		C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
 		true, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(ABGR4444,
 		COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
-		C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
+		C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
 		true, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(RGBA4444,
 		COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
-		C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
+		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
 		true, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(BGRA4444,
 		COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
-		C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
+		C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
 		true, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(XRGB4444,
 		COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
-		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
+		C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
 		false, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(XBGR4444,
 		COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
-		C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
+		C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
 		false, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(RGBX4444,
 		COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
-		C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
+		C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
 		false, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
 	INTERLEAVED_RGB_FMT(BGRX4444,
 		COLOR_ALPHA_4BIT, COLOR_4BIT, COLOR_4BIT, COLOR_4BIT,
-		C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
+		C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
 		false, 2, 0,
 		SDE_FETCH_LINEAR, 1),
 
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_intf.h b/drivers/gpu/drm/msm/sde/sde_hw_intf.h
index 89068bc..28b8108 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_intf.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_intf.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
@@ -38,6 +38,7 @@
 	u32 border_clr;
 	u32 underflow_clr;
 	u32 hsync_skew;
+	u32 v_front_porch_fixed;
 };
 
 struct intf_prog_fetch {
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
index 7977294..8022f23 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_mdss.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
@@ -582,6 +582,7 @@
  * @lm_cnt:	stores the active number of MDSS "LM" blks for the current mode
  * @dsc_cnt:	stores the active number of MDSS "dsc" blks for the current mode
  * @cont_splash_en:	Stores the cont_splash status (enabled/disbled)
+ * @single_flush_en: Stores if the single flush is enabled.
  */
 struct sde_splash_data {
 	bool smmu_handoff_pending;
@@ -595,6 +596,7 @@
 	u8 lm_cnt;
 	u8 dsc_cnt;
 	bool cont_splash_en;
+	bool single_flush_en;
 };
 
 #endif  /* _SDE_HW_MDSS_H */
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_top.c b/drivers/gpu/drm/msm/sde/sde_hw_top.c
index 51e4ba2..8b89ebb 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_top.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_top.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -106,6 +106,18 @@
 	SDE_REG_WRITE(c, SPLIT_DISPLAY_EN, cfg->en & 0x1);
 }
 
+static u32 sde_hw_get_split_flush(struct sde_hw_mdp *mdp)
+{
+	struct sde_hw_blk_reg_map *c;
+
+	if (!mdp)
+	return 0;
+
+	c = &mdp->hw;
+
+	return (SDE_REG_READ(c, SSPP_SPARE) & 0x1);
+}
+
 static void sde_hw_setup_pp_split(struct sde_hw_mdp *mdp,
 		struct split_pipe_cfg *cfg)
 {
@@ -374,6 +386,7 @@
 	ops->get_danger_status = sde_hw_get_danger_status;
 	ops->setup_vsync_source = sde_hw_setup_vsync_source;
 	ops->get_safe_status = sde_hw_get_safe_status;
+	ops->get_split_flush_status = sde_hw_get_split_flush;
 	ops->setup_dce = sde_hw_setup_dce;
 	ops->reset_ubwc = sde_hw_reset_ubwc;
 	ops->intf_audio_select = sde_hw_intf_audio_select;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_top.h b/drivers/gpu/drm/msm/sde/sde_hw_top.h
index 0ca5af9..950a62c 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_top.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_top.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
@@ -177,6 +177,12 @@
 			struct sde_danger_safe_status *status);
 
 	/**
+	 * get_split_flush_status - get split flush status
+	 * @mdp: mdp top context driver
+	 */
+	u32 (*get_split_flush_status)(struct sde_hw_mdp *mdp);
+
+	/**
 	 * reset_ubwc - reset top level UBWC configuration
 	 * @mdp: mdp top context driver
 	 * @m: pointer to mdss catalog data
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index ca205c8..0412fc6 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -1228,6 +1228,7 @@
 		.enable_event = dsi_conn_enable_event,
 		.cmd_transfer = dsi_display_cmd_transfer,
 		.cont_splash_config = dsi_display_cont_splash_config,
+		.get_panel_vfp = dsi_display_get_panel_vfp,
 	};
 	static const struct sde_connector_ops wb_ops = {
 		.post_init =    sde_wb_connector_post_init,
@@ -1242,6 +1243,7 @@
 		.check_status = NULL,
 		.cmd_transfer = NULL,
 		.cont_splash_config = NULL,
+		.get_panel_vfp = NULL,
 	};
 	static const struct sde_connector_ops dp_ops = {
 		.post_init  = dp_connector_post_init,
@@ -1255,6 +1257,7 @@
 		.config_hdr = dp_connector_config_hdr,
 		.cmd_transfer = NULL,
 		.cont_splash_config = NULL,
+		.get_panel_vfp = NULL,
 	};
 	static const struct sde_connector_ops ext_bridge_ops = {
 		.set_info_blob = dsi_conn_set_info_blob,
diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c
index 52a5bc9..90c05e6 100644
--- a/drivers/gpu/drm/msm/sde/sde_rm.c
+++ b/drivers/gpu/drm/msm/sde/sde_rm.c
@@ -1407,6 +1407,7 @@
 	struct sde_rm_hw_iter iter_c;
 	int index = 0, ctl_top_cnt;
 	struct sde_kms *sde_kms = NULL;
+	struct sde_hw_mdp *hw_mdp;
 
 	if (!priv || !rm || !cat || !splash_data) {
 		SDE_ERROR("invalid input parameters\n");
@@ -1462,9 +1463,16 @@
 				sde_kms,
 				cat->dsc_count,
 				splash_data->dsc_ids);
-	SDE_DEBUG("splash_data: ctl_top_cnt=%d, lm_cnt=%d, dsc_cnt=%d\n",
+
+	hw_mdp = sde_rm_get_mdp(rm);
+	if (hw_mdp && hw_mdp->ops.get_split_flush_status) {
+		splash_data->single_flush_en =
+			hw_mdp->ops.get_split_flush_status(hw_mdp);
+	}
+
+	SDE_DEBUG("splash_data: ctl_top_cnt=%d, lm_cnt=%d, dsc_cnt=%d sf=%d\n",
 		splash_data->ctl_top_cnt, splash_data->lm_cnt,
-		splash_data->dsc_cnt);
+		splash_data->dsc_cnt, splash_data->single_flush_en);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index ca4f0da..8179b10 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.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
@@ -882,23 +882,22 @@
 int sde_rsc_client_vote(struct sde_rsc_client *caller_client,
 		u32 bus_id, u64 ab_vote, u64 ib_vote)
 {
-	int rc = 0;
+	int rc = 0, rsc_index;
 	struct sde_rsc_priv *rsc;
 
-	if (!caller_client) {
-		pr_err("invalid client for ab/ib vote\n");
-		return -EINVAL;
-	} else if (caller_client->rsc_index >= MAX_RSC_COUNT) {
+	if (caller_client && caller_client->rsc_index >= MAX_RSC_COUNT) {
 		pr_err("invalid rsc index\n");
 		return -EINVAL;
 	}
 
-	rsc = rsc_prv_list[caller_client->rsc_index];
+	rsc_index = caller_client ? caller_client->rsc_index : SDE_RSC_INDEX;
+	rsc = rsc_prv_list[rsc_index];
 	if (!rsc)
 		return -EINVAL;
 
 	pr_debug("client:%s ab:%llu ib:%llu\n",
-			caller_client->name, ab_vote, ib_vote);
+			caller_client ? caller_client->name : "unknown",
+			ab_vote, ib_vote);
 
 	mutex_lock(&rsc->client_lock);
 	rc = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
diff --git a/drivers/gpu/drm/msm/sde_rsc_hw.c b/drivers/gpu/drm/msm/sde_rsc_hw.c
index d40b0ad..5049758 100644
--- a/drivers/gpu/drm/msm/sde_rsc_hw.c
+++ b/drivers/gpu/drm/msm/sde_rsc_hw.c
@@ -405,6 +405,9 @@
 	if (rc)
 		pr_err("vdd reg is not enabled yet\n");
 
+	dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0,
+						0x3, rsc->debug_mode);
+
 	rsc_event_trigger(rsc, SDE_RSC_EVENT_POST_CORE_RESTORE);
 
 	return rc;
@@ -477,19 +480,33 @@
 
 	if (seq_busy && (current_mode == SDE_RSC_MODE_0_VAL ||
 			current_mode == SDE_RSC_MODE_1_VAL)) {
-		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F1_QTMR_V1_CNTP_CVAL_LO,
-						0xffffffff, rsc->debug_mode);
 		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F1_QTMR_V1_CNTP_CVAL_HI,
+						0xffffff, rsc->debug_mode);
+		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F1_QTMR_V1_CNTP_CVAL_LO,
 						0xffffffff, rsc->debug_mode);
 		/* unstick f1 qtimer */
 		wmb();
 
-		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F1_QTMR_V1_CNTP_CVAL_LO,
-						0x0, rsc->debug_mode);
 		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F1_QTMR_V1_CNTP_CVAL_HI,
 						0x0, rsc->debug_mode);
+		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F1_QTMR_V1_CNTP_CVAL_LO,
+						0x0, rsc->debug_mode);
 		/* manually trigger f1 qtimer interrupt */
 		wmb();
+
+		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F0_QTMR_V1_CNTP_CVAL_HI,
+						0xffffff, rsc->debug_mode);
+		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F0_QTMR_V1_CNTP_CVAL_LO,
+						0xffffffff, rsc->debug_mode);
+		/* unstick f0 qtimer */
+		wmb();
+
+		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F0_QTMR_V1_CNTP_CVAL_HI,
+						0x0, rsc->debug_mode);
+		dss_reg_w(&rsc->wrapper_io, SDE_RSCC_F0_QTMR_V1_CNTP_CVAL_LO,
+						0x0, rsc->debug_mode);
+		/* manually trigger f0 qtimer interrupt */
+		wmb();
 	}
 }
 
@@ -506,6 +523,8 @@
 		return rc;
 	}
 
+	dss_reg_w(&rsc->drv_io, SDE_RSC_SOLVER_SOLVER_MODES_ENABLED_DRV0,
+						0x7, rsc->debug_mode);
 	rsc_event_trigger(rsc, SDE_RSC_EVENT_PRE_CORE_PC);
 
 	for (i = 0; i <= MAX_MODE2_ENTRY_TRY; i++) {
diff --git a/drivers/gpu/msm/adreno-gpulist.h b/drivers/gpu/msm/adreno-gpulist.h
index 2aff383..1fb76dd 100644
--- a/drivers/gpu/msm/adreno-gpulist.h
+++ b/drivers/gpu/msm/adreno-gpulist.h
@@ -379,4 +379,22 @@
 		.gpmu_major = 0x1,
 		.gpmu_minor = 0x003,
 	},
+	{
+		.gpurev = ADRENO_REV_A616,
+		.core = 6,
+		.major = 1,
+		.minor = 6,
+		.patchid = ANY_ID,
+		.features = ADRENO_64BIT | ADRENO_RPMH | ADRENO_PREEMPTION |
+			ADRENO_GPMU | ADRENO_CONTENT_PROTECTION | ADRENO_IFPC,
+		.sqefw_name = "a630_sqe.fw",
+		.zap_name = "a615_zap",
+		.gpudev = &adreno_a6xx_gpudev,
+		.gmem_size = SZ_512K,
+		.num_protected_regs = 0x20,
+		.busy_mask = 0xFFFFFFFE,
+		.gpmufw_name = "a630_gmu.bin",
+		.gpmu_major = 0x1,
+		.gpmu_minor = 0x003,
+	},
 };
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 8785d62..9ca22fd 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -211,6 +211,7 @@
 	ADRENO_REV_A530 = 530,
 	ADRENO_REV_A540 = 540,
 	ADRENO_REV_A615 = 615,
+	ADRENO_REV_A616 = 616,
 	ADRENO_REV_A630 = 630,
 };
 
@@ -1251,6 +1252,7 @@
 }
 
 ADRENO_TARGET(a615, ADRENO_REV_A615)
+ADRENO_TARGET(a616, ADRENO_REV_A616)
 ADRENO_TARGET(a630, ADRENO_REV_A630)
 
 static inline int adreno_is_a630v1(struct adreno_device *adreno_dev)
@@ -1878,7 +1880,7 @@
 
 static inline bool adreno_has_gbif(struct adreno_device *adreno_dev)
 {
-	if (adreno_is_a615(adreno_dev))
+	if (adreno_is_a615(adreno_dev) || adreno_is_a616(adreno_dev))
 		return true;
 	else
 		return false;
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index daf314d..7096d7c 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -61,6 +61,7 @@
 static const struct adreno_vbif_platform a6xx_vbif_platforms[] = {
 	{ adreno_is_a630, a630_vbif },
 	{ adreno_is_a615, a615_gbif },
+	{ adreno_is_a616, a615_gbif },
 };
 
 
@@ -251,6 +252,7 @@
 } a6xx_hwcg_registers[] = {
 	{adreno_is_a630, a630_hwcg_regs, ARRAY_SIZE(a630_hwcg_regs)},
 	{adreno_is_a615, a615_hwcg_regs, ARRAY_SIZE(a615_hwcg_regs)},
+	{adreno_is_a616, a615_hwcg_regs, ARRAY_SIZE(a615_hwcg_regs)},
 };
 
 static struct a6xx_protected_regs {
@@ -499,7 +501,7 @@
 static inline unsigned int
 __get_rbbm_clock_cntl_on(struct adreno_device *adreno_dev)
 {
-	if (adreno_is_a615(adreno_dev))
+	if (adreno_is_a615(adreno_dev) || adreno_is_a616(adreno_dev))
 		return 0x8AA8AA82;
 	else
 		return 0x8AA8AA02;
@@ -508,7 +510,7 @@
 static inline unsigned int
 __get_gmu_ao_cgc_mode_cntl(struct adreno_device *adreno_dev)
 {
-	if (adreno_is_a615(adreno_dev))
+	if (adreno_is_a615(adreno_dev) || adreno_is_a616(adreno_dev))
 		return 0x00000222;
 	else
 		return 0x00020202;
@@ -517,7 +519,7 @@
 static inline unsigned int
 __get_gmu_ao_cgc_delay_cntl(struct adreno_device *adreno_dev)
 {
-	if (adreno_is_a615(adreno_dev))
+	if (adreno_is_a615(adreno_dev) || adreno_is_a616(adreno_dev))
 		return 0x00000111;
 	else
 		return 0x00010111;
@@ -526,7 +528,7 @@
 static inline unsigned int
 __get_gmu_ao_cgc_hyst_cntl(struct adreno_device *adreno_dev)
 {
-	if (adreno_is_a615(adreno_dev))
+	if (adreno_is_a615(adreno_dev) || adreno_is_a616(adreno_dev))
 		return 0x00000555;
 	else
 		return 0x00005555;
@@ -643,7 +645,7 @@
 		+ sizeof(a6xx_ifpc_pwrup_reglist), a6xx_pwrup_reglist,
 		sizeof(a6xx_pwrup_reglist));
 
-	if (adreno_is_a615(adreno_dev)) {
+	if (adreno_is_a615(adreno_dev) || adreno_is_a616(adreno_dev)) {
 		for (i = 0; i < ARRAY_SIZE(a615_pwrup_reglist); i++) {
 			r = &a615_pwrup_reglist[i];
 			kgsl_regread(KGSL_DEVICE(adreno_dev),
@@ -3587,6 +3589,7 @@
 	void (*func)(struct adreno_device *adreno_dev);
 } a6xx_efuse_funcs[] = {
 	{ adreno_is_a615, a6xx_efuse_speed_bin },
+	{ adreno_is_a616, a6xx_efuse_speed_bin },
 };
 
 static void a6xx_check_features(struct adreno_device *adreno_dev)
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index afd1be5..7376a38 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -1169,7 +1169,8 @@
 
 	block_id = block->block_id;
 	/* GMU_GX data is read using the GMU_CX block id on A630 */
-	if ((adreno_is_a630(adreno_dev) || adreno_is_a615(adreno_dev)) &&
+	if ((adreno_is_a630(adreno_dev) || adreno_is_a615(adreno_dev) ||
+		adreno_is_a616(adreno_dev)) &&
 		(block_id == A6XX_DBGBUS_GMU_GX))
 		block_id = A6XX_DBGBUS_GMU_CX;
 
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index a9c2252..3702893 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.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
@@ -716,6 +716,18 @@
 
 	align = (memdesc->flags & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT;
 
+	/*
+	 * As 1MB is the max supported page size, use the alignment
+	 * corresponding to 1MB page to make sure higher order pages
+	 * are used if possible for a given memory size. Also, we
+	 * don't need to update alignment in memdesc flags in case
+	 * higher order page is used, as memdesc flags represent the
+	 * virtual alignment specified by the user which is anyways
+	 * getting satisfied.
+	 */
+	if (align < ilog2(SZ_1M))
+		align = ilog2(SZ_1M);
+
 	page_size = kgsl_get_page_size(size, align);
 
 	/*
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 5e41611..0ed17d8 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -719,8 +719,6 @@
 
 		if (device->ftbl->snapshot)
 			device->ftbl->snapshot(device, snapshot, context);
-		if (device->ftbl->snapshot_gmu)
-			device->ftbl->snapshot_gmu(device, snapshot);
 	}
 
 	/*
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 59ca208..1f38574 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -109,7 +109,7 @@
 #define QPNP_VADC_CONV_TIME_MIN					1000
 #define QPNP_VADC_CONV_TIME_MAX					1100
 #define QPNP_ADC_COMPLETION_TIMEOUT				HZ
-#define QPNP_VADC_ERR_COUNT					50
+#define QPNP_VADC_ERR_COUNT					20
 #define QPNP_OP_MODE_SHIFT					3
 
 #define QPNP_VADC_THR_LSB_MASK(val)				(val & 0xff)
@@ -277,42 +277,6 @@
 	return -EINVAL;
 }
 
-static int32_t qpnp_vadc_warm_rst_configure(struct qpnp_vadc_chip *vadc)
-{
-	int rc = 0;
-	u8 data = 0, buf = 0;
-
-	buf = QPNP_VADC_ACCESS_DATA;
-	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ACCESS, &buf, 1);
-	if (rc < 0) {
-		pr_err("VADC write access failed\n");
-		return rc;
-	}
-
-	rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_PERH_RESET_CTL3, &data, 1);
-	if (rc < 0) {
-		pr_err("VADC perh reset ctl3 read failed\n");
-		return rc;
-	}
-
-	buf = QPNP_VADC_ACCESS_DATA;
-	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_ACCESS, &buf, 1);
-	if (rc < 0) {
-		pr_err("VADC write access failed\n");
-		return rc;
-	}
-
-	data |= QPNP_FOLLOW_WARM_RB;
-
-	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_PERH_RESET_CTL3, &data, 1);
-	if (rc < 0) {
-		pr_err("VADC perh reset ctl3 write failed\n");
-		return rc;
-	}
-
-	return 0;
-}
-
 static int32_t qpnp_vadc_mode_select(struct qpnp_vadc_chip *vadc, u8 mode_ctl)
 {
 	int rc;
@@ -422,20 +386,7 @@
 static int qpnp_vadc_hc_read_data(struct qpnp_vadc_chip *vadc, int *data)
 {
 	int rc = 0;
-	u8 buf = 0, rslt_lsb = 0, rslt_msb = 0;
-
-	/* Set hold bit */
-	rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_HC1_DATA_HOLD_CTL, &buf, 1);
-	if (rc) {
-		pr_err("debug register dump failed\n");
-		return rc;
-	}
-	buf |= QPNP_VADC_HC1_DATA_HOLD_CTL_FIELD;
-	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_HC1_DATA_HOLD_CTL, &buf, 1);
-	if (rc) {
-		pr_err("debug register dump failed\n");
-		return rc;
-	}
+	u8 rslt_lsb = 0, rslt_msb = 0;
 
 	rc = qpnp_vadc_read_reg(vadc, QPNP_VADC_HC1_DATA0, &rslt_lsb, 1);
 	if (rc < 0) {
@@ -462,11 +413,6 @@
 		return rc;
 	}
 
-	/* De-assert hold bit */
-	buf &= ~QPNP_VADC_HC1_DATA_HOLD_CTL_FIELD;
-	rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_HC1_DATA_HOLD_CTL, &buf, 1);
-	if (rc)
-		pr_err("de-asserting hold bit failed\n");
 
 	return rc;
 }
@@ -2757,12 +2703,6 @@
 		goto err_setup;
 	}
 
-	rc = qpnp_vadc_warm_rst_configure(vadc);
-	if (rc < 0) {
-		pr_err("Setting perp reset on warm reset failed %d\n", rc);
-		goto err_setup;
-	}
-
 	INIT_WORK(&vadc->trigger_completion_work, qpnp_vadc_work);
 
 	vadc->vadc_recalib_check = of_property_read_bool(node,
diff --git a/drivers/hwtracing/coresight/coresight-byte-cntr.c b/drivers/hwtracing/coresight/coresight-byte-cntr.c
index 5173770..9fa3e0f 100644
--- a/drivers/hwtracing/coresight/coresight-byte-cntr.c
+++ b/drivers/hwtracing/coresight/coresight-byte-cntr.c
@@ -162,7 +162,7 @@
 				goto err0;
 		}
 
-		if (tmcdrvdata->mem_type == TMC_ETR_MEM_TYPE_CONTIG)
+		if (tmcdrvdata->memtype == TMC_ETR_MEM_TYPE_CONTIG)
 			tmc_etr_read_bytes(byte_cntr_data, ppos,
 					   byte_cntr_data->block_size, &len,
 					   &bufp);
@@ -172,7 +172,7 @@
 
 	} else {
 		if (!atomic_read(&byte_cntr_data->irq_cnt)) {
-			if (tmcdrvdata->mem_type == TMC_ETR_MEM_TYPE_CONTIG)
+			if (tmcdrvdata->memtype == TMC_ETR_MEM_TYPE_CONTIG)
 				tmc_etr_flush_bytes(ppos,
 						    byte_cntr_data->block_size,
 						    &len);
@@ -184,7 +184,7 @@
 			if (!len)
 				goto err0;
 		} else {
-			if (tmcdrvdata->mem_type == TMC_ETR_MEM_TYPE_CONTIG)
+			if (tmcdrvdata->memtype == TMC_ETR_MEM_TYPE_CONTIG)
 				tmc_etr_read_bytes(byte_cntr_data, ppos,
 						   byte_cntr_data->block_size,
 						   &len, &bufp);
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 6597fd6..3948a50 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -28,10 +28,13 @@
 #include <linux/of.h>
 #include <linux/coresight.h>
 #include <linux/amba/bus.h>
+#include <soc/qcom/memory_dump.h>
 
 #include "coresight-priv.h"
 #include "coresight-tmc.h"
 
+#define TMC_REG_DUMP_MAGIC 0x42445953
+
 void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
 {
 	/* Ensure formatter, unformatter and hardware fifo are empty */
@@ -61,11 +64,85 @@
 	tmc_wait_for_tmcready(drvdata);
 }
 
+static void __tmc_reg_dump(struct tmc_drvdata *drvdata)
+{
+	struct dump_vaddr_entry *dump_entry;
+	struct msm_dump_data *dump_data;
+	uint32_t *reg_buf;
+
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+		dump_entry = get_msm_dump_ptr(MSM_DUMP_DATA_TMC_ETR_REG);
+		dev_dbg(drvdata->dev, "%s: TMC ETR dump entry ptr is %pK\n",
+			__func__, dump_entry);
+	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETB ||
+			drvdata->config_type == TMC_CONFIG_TYPE_ETF) {
+		dump_entry = get_msm_dump_ptr(MSM_DUMP_DATA_TMC_ETF_REG);
+		dev_dbg(drvdata->dev, "%s: TMC ETF dump entry ptr is %pK\n",
+			__func__, dump_entry);
+	} else
+		return;
+
+	if (dump_entry == NULL)
+		return;
+
+	reg_buf = (uint32_t *)(dump_entry->dump_vaddr);
+	dump_data = dump_entry->dump_data_vaddr;
+
+	if (reg_buf == NULL || dump_data == NULL)
+		return;
+
+	dev_dbg(drvdata->dev, "%s: TMC dump reg ptr is %pK, dump_data is %pK\n",
+		__func__, reg_buf, dump_data);
+
+	reg_buf[1] = readl_relaxed(drvdata->base + TMC_RSZ);
+	reg_buf[3] = readl_relaxed(drvdata->base + TMC_STS);
+	reg_buf[5] = readl_relaxed(drvdata->base + TMC_RRP);
+	reg_buf[6] = readl_relaxed(drvdata->base + TMC_RWP);
+	reg_buf[7] = readl_relaxed(drvdata->base + TMC_TRG);
+	reg_buf[8] = readl_relaxed(drvdata->base + TMC_CTL);
+	reg_buf[10] = readl_relaxed(drvdata->base + TMC_MODE);
+	reg_buf[11] = readl_relaxed(drvdata->base + TMC_LBUFLEVEL);
+	reg_buf[12] = readl_relaxed(drvdata->base + TMC_CBUFLEVEL);
+	reg_buf[13] = readl_relaxed(drvdata->base + TMC_BUFWM);
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+		reg_buf[14] = readl_relaxed(drvdata->base + TMC_RRPHI);
+		reg_buf[15] = readl_relaxed(drvdata->base + TMC_RWPHI);
+		reg_buf[68] = readl_relaxed(drvdata->base + TMC_AXICTL);
+		reg_buf[70] = readl_relaxed(drvdata->base + TMC_DBALO);
+		reg_buf[71] = readl_relaxed(drvdata->base + TMC_DBAHI);
+	}
+	reg_buf[192] = readl_relaxed(drvdata->base + TMC_FFSR);
+	reg_buf[193] = readl_relaxed(drvdata->base + TMC_FFCR);
+	reg_buf[194] = readl_relaxed(drvdata->base + TMC_PSCR);
+	reg_buf[1000] = readl_relaxed(drvdata->base + CORESIGHT_CLAIMSET);
+	reg_buf[1001] = readl_relaxed(drvdata->base + CORESIGHT_CLAIMCLR);
+	reg_buf[1005] = readl_relaxed(drvdata->base + CORESIGHT_LSR);
+	reg_buf[1006] = readl_relaxed(drvdata->base + CORESIGHT_AUTHSTATUS);
+	reg_buf[1010] = readl_relaxed(drvdata->base + CORESIGHT_DEVID);
+	reg_buf[1011] = readl_relaxed(drvdata->base + CORESIGHT_DEVTYPE);
+	reg_buf[1012] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR4);
+	reg_buf[1013] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR5);
+	reg_buf[1014] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR6);
+	reg_buf[1015] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR7);
+	reg_buf[1016] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR0);
+	reg_buf[1017] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR1);
+	reg_buf[1018] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR2);
+	reg_buf[1019] = readl_relaxed(drvdata->base + CORESIGHT_PERIPHIDR3);
+	reg_buf[1020] = readl_relaxed(drvdata->base + CORESIGHT_COMPIDR0);
+	reg_buf[1021] = readl_relaxed(drvdata->base + CORESIGHT_COMPIDR1);
+	reg_buf[1022] = readl_relaxed(drvdata->base + CORESIGHT_COMPIDR2);
+	reg_buf[1023] = readl_relaxed(drvdata->base + CORESIGHT_COMPIDR3);
+
+	dump_data->magic = TMC_REG_DUMP_MAGIC;
+}
+
 void tmc_enable_hw(struct tmc_drvdata *drvdata)
 {
 	drvdata->enable = true;
 	drvdata->sticky_enable = true;
 	writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
+	if (drvdata->force_reg_dump)
+		__tmc_reg_dump(drvdata);
 }
 
 void tmc_disable_hw(struct tmc_drvdata *drvdata)
@@ -316,6 +393,12 @@
 		return -EINVAL;
 	}
 
+	if (drvdata->enable) {
+		mutex_unlock(&drvdata->mem_lock);
+		pr_err("ETR is in use, disable it to change the mem_size\n");
+		return -EINVAL;
+	}
+
 	drvdata->mem_size = val;
 	mutex_unlock(&drvdata->mem_lock);
 	return size;
@@ -446,6 +529,11 @@
 		return -EINVAL;
 
 	mutex_lock(&drvdata->mem_lock);
+	if (drvdata->enable) {
+		mutex_unlock(&drvdata->mem_lock);
+		pr_err("ETR is in use, disable it to switch the mode\n");
+		return -EINVAL;
+	}
 	if (!strcmp(str, str_tmc_etr_mem_type[TMC_ETR_MEM_TYPE_CONTIG]))
 		drvdata->mem_type = TMC_ETR_MEM_TYPE_CONTIG;
 	else if (!strcmp(str, str_tmc_etr_mem_type[TMC_ETR_MEM_TYPE_SG]))
@@ -626,6 +714,8 @@
 			return -EPROBE_DEFER;
 		}
 	}
+	if (of_property_read_bool(drvdata->dev->of_node, "qcom,force-reg-dump"))
+		drvdata->force_reg_dump = true;
 
 	desc.pdata = pdata;
 	desc.dev = dev;
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 0a271e5..2372be6 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -192,6 +192,7 @@
 	struct coresight_csr	*csr;
 	const char		*csr_name;
 	struct byte_cntr	*byte_cntr;
+	bool			force_reg_dump;
 };
 
 /* Generic functions */
diff --git a/drivers/hwtracing/coresight/coresight-tpdm.c b/drivers/hwtracing/coresight/coresight-tpdm.c
index 0bc9439..7cdb459 100644
--- a/drivers/hwtracing/coresight/coresight-tpdm.c
+++ b/drivers/hwtracing/coresight/coresight-tpdm.c
@@ -3898,6 +3898,8 @@
 
 static int tpdm_datasets_alloc(struct tpdm_drvdata *drvdata)
 {
+	struct dump_vaddr_entry *dump_entry;
+
 	if (test_bit(TPDM_DS_GPR, drvdata->datasets)) {
 		drvdata->gpr = devm_kzalloc(drvdata->dev, sizeof(*drvdata->gpr),
 					    GFP_KERNEL);
@@ -3939,10 +3941,13 @@
 			return -ENOMEM;
 
 		if (of_property_read_bool(drvdata->dev->of_node,
-						    "qcom,dump-enable"))
-			drvdata->cmb->mcmb->mcmb_msr_dump_ptr =
-				(uint32_t *)get_msm_dump_ptr(
-						MSM_DUMP_DATA_TPDM_SWAO_MCMB);
+						    "qcom,dump-enable")) {
+			dump_entry = get_msm_dump_ptr(
+				MSM_DUMP_DATA_TPDM_SWAO_MCMB);
+			if (dump_entry)
+				drvdata->cmb->mcmb->mcmb_msr_dump_ptr =
+					(uint32_t *)(dump_entry->dump_vaddr);
+		}
 	}
 	return 0;
 }
diff --git a/drivers/i2c/busses/i2c-msm-v2.c b/drivers/i2c/busses/i2c-msm-v2.c
index ad77697..99e7c97 100644
--- a/drivers/i2c/busses/i2c-msm-v2.c
+++ b/drivers/i2c/busses/i2c-msm-v2.c
@@ -3027,7 +3027,7 @@
 {
 	return platform_driver_register(&i2c_msm_driver);
 }
-arch_initcall(i2c_msm_init);
+subsys_initcall(i2c_msm_init);
 
 static void i2c_msm_exit(void)
 {
diff --git a/drivers/input/misc/qpnp-power-on.c b/drivers/input/misc/qpnp-power-on.c
index 5fa0d4b..36d07c5 100644
--- a/drivers/input/misc/qpnp-power-on.c
+++ b/drivers/input/misc/qpnp-power-on.c
@@ -229,6 +229,7 @@
 	bool			kpdpwr_dbc_enable;
 	bool			resin_pon_reset;
 	ktime_t			kpdpwr_last_release_time;
+	bool			legacy_hard_reset_offset;
 };
 
 static int pon_ship_mode_en;
@@ -353,7 +354,7 @@
 	if (!pon->store_hard_reset_reason)
 		return 0;
 
-	if (is_pon_gen2(pon))
+	if (is_pon_gen2(pon) && !pon->legacy_hard_reset_offset)
 		rc = qpnp_pon_masked_write(pon, QPNP_PON_SOFT_RB_SPARE(pon),
 					   GENMASK(7, 1), (reason << 1));
 	else
@@ -2524,6 +2525,9 @@
 	pon->store_hard_reset_reason = of_property_read_bool(pdev->dev.of_node,
 					"qcom,store-hard-reset-reason");
 
+	pon->legacy_hard_reset_offset = of_property_read_bool(pdev->dev.of_node,
+					"qcom,use-legacy-hard-reset-offset");
+
 	qpnp_pon_debugfs_init(pdev);
 	return 0;
 
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 86168b9..bcb861ec 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -1225,5 +1225,6 @@
           If unsure, say N.
 
 source "drivers/input/touchscreen/synaptics_dsx/Kconfig"
+source "drivers/input/touchscreen/focaltech_touch/Kconfig"
 
 endif
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 7ac5a98..f2749e4 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -101,3 +101,4 @@
 obj-$(CONFIG_TOUCHSCREEN_ZFORCE)	+= zforce_ts.o
 obj-$(CONFIG_TOUCHSCREEN_COLIBRI_VF50)	+= colibri-vf50-ts.o
 obj-$(CONFIG_TOUCHSCREEN_ROHM_BU21023)	+= rohm_bu21023.o
+obj-$(CONFIG_TOUCHSCREEN_FTS)		+= focaltech_touch/
diff --git a/drivers/input/touchscreen/focaltech_touch/Kconfig b/drivers/input/touchscreen/focaltech_touch/Kconfig
new file mode 100644
index 0000000..00deec7
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/Kconfig
@@ -0,0 +1,18 @@
+#
+# Focaltech Touchscreen driver configuration
+#
+menuconfig TOUCHSCREEN_FTS
+	bool "Focaltech Touchscreen"
+	depends on I2C
+	default n
+	help
+	  Say Y here if you have Focaltech touch panel.
+	  If unsure, say N.
+
+config TOUCHSCREEN_FTS_DIRECTORY
+	string "Focaltech ts directory name"
+	default "focaltech_touch"
+	depends on TOUCHSCREEN_FTS
+	help
+	  Specify the path for the driver directory.
+	  Path should be relative to driver/input/touchscreen/.
diff --git a/drivers/input/touchscreen/focaltech_touch/Makefile b/drivers/input/touchscreen/focaltech_touch/Makefile
new file mode 100644
index 0000000..c582416
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for the focaltech touchscreen drivers.
+#
+
+# Each configuration option enables a list of files.
+
+obj-$(CONFIG_TOUCHSCREEN_FTS)	+=  focaltech_core.o
+obj-$(CONFIG_TOUCHSCREEN_FTS)	+=  focaltech_ex_fun.o
+obj-$(CONFIG_TOUCHSCREEN_FTS)	+=  focaltech_ex_mode.o
+obj-$(CONFIG_TOUCHSCREEN_FTS)	+=  focaltech_flash.o
+obj-$(CONFIG_TOUCHSCREEN_FTS)	+=  focaltech_gesture.o
+obj-$(CONFIG_TOUCHSCREEN_FTS)	+=  focaltech_esdcheck.o
+obj-$(CONFIG_TOUCHSCREEN_FTS)	+=  focaltech_i2c.o
+obj-$(CONFIG_TOUCHSCREEN_FTS)	+=  focaltech_sensor.o
+obj-$(CONFIG_TOUCHSCREEN_FTS)	+=  focaltech_point_report_check.o
+obj-$(CONFIG_TOUCHSCREEN_FTS)	+=  focaltech_flash/
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_common.h b/drivers/input/touchscreen/focaltech_touch/focaltech_common.h
new file mode 100644
index 0000000..209f0a9
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_common.h
@@ -0,0 +1,217 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+/*****************************************************************************
+ *
+ * File Name: focaltech_common.h
+ *
+ * Author: Focaltech Driver Team
+ *
+ * Created: 2016-08-16
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+#ifndef __LINUX_FOCALTECH_COMMON_H__
+#define __LINUX_FOCALTECH_COMMON_H__
+
+#include "focaltech_config.h"
+
+/*****************************************************************************
+ * Macro definitions using #define
+ *****************************************************************************/
+#define FTS_DRIVER_VERSION                  "Focaltech V1.3 20170306"
+
+#define FLAGBIT(x)              (0x00000001 << (x))
+#define FLAGBITS(x, y)          ((0xFFFFFFFF >> (32 - (y) - 1)) << (x))
+
+#define FLAG_ICSERIALS_LEN      5
+#define FLAG_IDC_BIT            11
+
+#define IC_SERIALS              (FTS_CHIP_TYPE & \
+					FLAGBITS(0, FLAG_ICSERIALS_LEN-1))
+#define FTS_CHIP_IDC            ((FTS_CHIP_TYPE & FLAGBIT(FLAG_IDC_BIT)) \
+						== FLAGBIT(FLAG_IDC_BIT))
+
+#define FTS_CHIP_TYPE_MAPPING   { \
+	{0x01, 0x58, 0x22, 0x58, 0x22, 0x00, 0x00, 0x58, 0x2C}, \
+	{0x02, 0x54, 0x22, 0x54, 0x22, 0x00, 0x00, 0x54, 0x2C}, \
+	{0x03, 0x64, 0x26, 0x64, 0x26, 0x00, 0x00, 0x79, 0x1C}, \
+	{0x04, 0x33, 0x67, 0x64, 0x26, 0x00, 0x00, 0x79, 0x1C}, \
+	{0x05, 0x87, 0x16, 0x87, 0x16, 0x87, 0xA6, 0x00, 0x00}, \
+	{0x06, 0x87, 0x36, 0x87, 0x36, 0x87, 0xC6, 0x00, 0x00}, \
+	{0x07, 0x80, 0x06, 0x80, 0x06, 0x80, 0xC6, 0x80, 0xB6}, \
+	{0x08, 0x86, 0x06, 0x86, 0x06, 0x86, 0xA6, 0x00, 0x00}, \
+	{0x09, 0x86, 0x07, 0x86, 0x07, 0x86, 0xA7, 0x00, 0x00}, \
+	{0x0A, 0xE7, 0x16, 0x87, 0x16, 0xE7, 0xA6, 0x87, 0xB6}, \
+}
+
+#define I2C_BUFFER_LENGTH_MAXINUM           256
+#define FILE_NAME_LENGTH                    128
+#define ENABLE                              1
+#define DISABLE                             0
+/*register address*/
+#define FTS_REG_INT_CNT                     0x8F
+#define FTS_REG_FLOW_WORK_CNT               0x91
+#define FTS_REG_WORKMODE                    0x00
+#define FTS_REG_WORKMODE_FACTORY_VALUE      0x40
+#define FTS_REG_WORKMODE_WORK_VALUE         0x00
+#define FTS_REG_CHIP_ID                     0xA3
+#define FTS_REG_CHIP_ID2                    0x9F
+#define FTS_REG_POWER_MODE                  0xA5
+#define FTS_REG_POWER_MODE_SLEEP_VALUE      0x03
+#define FTS_REG_FW_VER                      0xA6
+#define FTS_REG_VENDOR_ID                   0xA8
+#define FTS_REG_LCD_BUSY_NUM                0xAB
+#define FTS_REG_FACE_DEC_MODE_EN            0xB0
+#define FTS_REG_GLOVE_MODE_EN               0xC0
+#define FTS_REG_COVER_MODE_EN               0xC1
+#define FTS_REG_CHARGER_MODE_EN             0x8B
+#define FTS_REG_GESTURE_EN                  0xD0
+#define FTS_REG_GESTURE_OUTPUT_ADDRESS      0xD3
+#define FTS_REG_ESD_SATURATE                0xED
+
+
+
+/*****************************************************************************
+ *  Alternative mode (When something goes wrong,
+ *  the modules may be able to solve the problem.)
+ *****************************************************************************/
+/*
+ * point report check
+ * default: disable
+ */
+#define FTS_POINT_REPORT_CHECK_EN               0
+
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+struct ft_chip_t {
+	unsigned long type;
+	unsigned char chip_idh;
+	unsigned char chip_idl;
+	unsigned char rom_idh;
+	unsigned char rom_idl;
+	unsigned char pramboot_idh;
+	unsigned char pramboot_idl;
+	unsigned char bootloader_idh;
+	unsigned char bootloader_idl;
+};
+
+/* i2c communication*/
+int fts_i2c_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue);
+int fts_i2c_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue);
+int fts_i2c_read(struct i2c_client *client, char *writebuf, int writelen,
+						char *readbuf, int readlen);
+int fts_i2c_write(struct i2c_client *client, char *writebuf, int writelen);
+int fts_i2c_init(void);
+int fts_i2c_exit(void);
+
+/* Gesture functions */
+#if FTS_GESTURE_EN
+int fts_gesture_init(struct input_dev *input_dev, struct i2c_client *client);
+int fts_gesture_exit(struct i2c_client *client);
+void fts_gesture_recovery(struct i2c_client *client);
+int fts_gesture_readdata(struct i2c_client *client);
+int fts_gesture_suspend(struct i2c_client *i2c_client);
+int fts_gesture_resume(struct i2c_client *client);
+#endif
+
+/* Apk and functions */
+#if FTS_APK_NODE_EN
+int fts_create_apk_debug_channel(struct i2c_client *client);
+void fts_release_apk_debug_channel(void);
+#endif
+
+/* ADB functions */
+#if FTS_SYSFS_NODE_EN
+int fts_create_sysfs(struct i2c_client *client);
+int fts_remove_sysfs(struct i2c_client *client);
+#endif
+
+/* ESD */
+#if FTS_ESDCHECK_EN
+int fts_esdcheck_init(void);
+int fts_esdcheck_exit(void);
+int fts_esdcheck_switch(bool enable);
+int fts_esdcheck_proc_busy(bool proc_debug);
+int fts_esdcheck_set_intr(bool intr);
+int fts_esdcheck_suspend(void);
+int fts_esdcheck_resume(void);
+int fts_esdcheck_get_status(void);
+#endif
+
+/* Production test */
+#if FTS_TEST_EN
+int fts_test_init(struct i2c_client *client);
+int fts_test_exit(struct i2c_client *client);
+#endif
+
+/* Point Report Check*/
+#if FTS_POINT_REPORT_CHECK_EN
+int fts_point_report_check_init(void);
+int fts_point_report_check_exit(void);
+void fts_point_report_check_queue_work(void);
+#endif
+
+/* Other */
+extern int g_show_log;
+int fts_reset_proc(int hdelayms);
+int fts_wait_tp_to_valid(struct i2c_client *client);
+void fts_tp_state_recovery(struct i2c_client *client);
+int fts_ex_mode_init(struct i2c_client *client);
+int fts_ex_mode_exit(struct i2c_client *client);
+int fts_ex_mode_recovery(struct i2c_client *client);
+
+void fts_irq_disable(void);
+void fts_irq_enable(void);
+
+/*****************************************************************************
+ * DEBUG function define here
+ *****************************************************************************/
+#if FTS_DEBUG_EN
+#define FTS_DEBUG_LEVEL     1
+
+#if (FTS_DEBUG_LEVEL == 2)
+#define FTS_DEBUG(fmt, args...) pr_err("[FTS][%s]"fmt"\n", __func__, ##args)
+#else
+#define FTS_DEBUG(fmt, args...) pr_err("[FTS]"fmt"\n", ##args)
+#endif
+
+#define FTS_FUNC_ENTER() pr_err("[FTS]%s: Enter\n", __func__)
+#define FTS_FUNC_EXIT()  pr_err("[FTS]%s: Exit(%d)\n", __func__, __LINE__)
+#else
+#define FTS_DEBUG(fmt, args...)
+#define FTS_FUNC_ENTER()
+#define FTS_FUNC_EXIT()
+#endif
+
+#define FTS_INFO(fmt, args...) do { \
+		if (g_show_log) \
+			pr_err("[FTS][Info]"fmt"\n", ##args); \
+	}  while (0)
+
+#define FTS_ERROR(fmt, args...)  do { \
+		if (g_show_log) \
+			pr_err("[FTS][Error]"fmt"\n", ##args); \
+	}  while (0)
+
+
+#endif /* __LINUX_FOCALTECH_COMMON_H__ */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_config.h b/drivers/input/touchscreen/focaltech_touch/focaltech_config.h
new file mode 100644
index 0000000..5ab6bda
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_config.h
@@ -0,0 +1,248 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+/************************************************************************
+ *
+ * File Name: focaltech_config.h
+ *
+ *    Author: Focaltech Driver Team
+ *
+ *   Created: 2016-08-08
+ *
+ *  Abstract: global configurations
+ *
+ *   Version: v1.0
+ *
+ ************************************************************************/
+#ifndef _LINUX_FOCLATECH_CONFIG_H_
+#define _LINUX_FOCLATECH_CONFIG_H_
+
+/**************************************************/
+/****** G: A, I: B, S: C, U: D  ******************/
+/****** chip type defines, do not modify *********/
+#define _FT8716     0x87160805
+#define _FT8736     0x87360806
+#define _FT8006     0x80060807
+#define _FT8606     0x86060808
+#define _FT8607     0x86070809
+#define _FTE716     0xE716080a
+
+#define _FT5416     0x54160002
+#define _FT5426     0x54260002
+#define _FT5435     0x54350002
+#define _FT5436     0x54360002
+#define _FT5526     0x55260002
+#define _FT5526I    0x5526B002
+#define _FT5446     0x54460002
+#define _FT5346     0x53460002
+#define _FT5446I    0x5446B002
+#define _FT5346I    0x5346B002
+#define _FT7661     0x76610002
+#define _FT7511     0x75110002
+#define _FT7421     0x74210002
+#define _FT7681     0x76810002
+#define _FT3C47U    0x3C47D002
+#define _FT3417     0x34170002
+#define _FT3517     0x35170002
+#define _FT3327     0x33270002
+#define _FT3427     0x34270002
+
+#define _FT5626     0x56260001
+#define _FT5726     0x57260001
+#define _FT5826B    0x5826B001
+#define _FT5826S    0x5826C001
+#define _FT7811     0x78110001
+#define _FT3D47     0x3D470001
+#define _FT3617     0x36170001
+#define _FT3717     0x37170001
+#define _FT3817B    0x3817B001
+
+#define _FT6236U    0x6236D003
+#define _FT6336G    0x6336A003
+#define _FT6336U    0x6336D003
+#define _FT6436U    0x6436D003
+
+#define _FT3267     0x32670004
+#define _FT3367     0x33670004
+
+
+
+/*************************************************/
+
+/*
+ * choose your ic chip type of focaltech
+ */
+#define FTS_CHIP_TYPE   _FT3267
+
+/******************* Enables *********************/
+/*********** 1 to enable, 0 to disable ***********/
+
+/*
+ * show debug log info
+ * enable it for debug, disable it for release
+ */
+#define FTS_DEBUG_EN                            0
+
+/*
+ * Linux MultiTouch Protocol
+ * 1: Protocol B(default), 0: Protocol A
+ */
+#define FTS_MT_PROTOCOL_B_EN                    1
+
+
+/*
+ * Report Pressure in multitouch
+ * 1:enable(default),0:disable
+ */
+#define FTS_REPORT_PRESSURE_EN                  1
+
+/*
+ * Force touch support
+ * different pressure for multitouch
+ * 1: true pressure for force touch
+ * 0: constant pressure(default)
+ */
+#define FTS_FORCE_TOUCH_EN                      0
+
+/*
+ * Gesture function enable
+ * default: disable
+ */
+#define FTS_GESTURE_EN                          1
+
+/*
+ * ESD check & protection
+ * default: disable
+ */
+#define FTS_ESDCHECK_EN                         0
+
+/*
+ * Production test enable
+ * 1: enable, 0:disable(default)
+ */
+#define FTS_TEST_EN                             0
+
+/*
+ * Glove mode enable
+ * 1: enable, 0:disable(default)
+ */
+#define FTS_GLOVE_EN                            0
+/*
+ * cover enable
+ * 1: enable, 0:disable(default)
+ */
+#define FTS_COVER_EN                            0
+/*
+ * Charger enable
+ * 1: enable, 0:disable(default)
+ */
+#define FTS_CHARGER_EN                          0
+
+/*
+ * Proximity sensor
+ * default: disable
+ */
+#define FTS_PSENSOR_EN                          0
+
+/*
+ * Nodes for tools, please keep enable
+ */
+#define FTS_SYSFS_NODE_EN                       1
+#define FTS_APK_NODE_EN                         1
+
+/*
+ * Customer power enable
+ * enable it when customer need control TP power
+ * default: disable
+ */
+#define FTS_POWER_SOURCE_CUST_EN                1
+
+/****************************************************/
+
+/********************** Upgrade ****************************/
+/*
+ * auto upgrade, please keep enable
+ */
+#define FTS_AUTO_UPGRADE_EN                     1
+
+/*
+ * auto upgrade for lcd cfg
+ * default: 0
+ */
+#define FTS_AUTO_UPGRADE_FOR_LCD_CFG_EN         0
+
+/* auto cb check
+ * default: disable
+ */
+#define FTS_AUTO_CLB_EN                         0
+
+/*
+ * Check vendor_id number
+ * 0:No check vendor_id (default)
+ * 1/2/3: Check vendor_id for vendor compatibility
+ */
+#define FTS_GET_VENDOR_ID_NUM                   0
+
+/*
+ * vendor_id(s) for vendor(s) to be compatible with.
+ * a confirmation of vendor_id(s) is recommended.
+ * FTS_GET_VENDOR_ID_NUM == 0, no check vendor id, you may ignore them
+ * FTS_GET_VENDOR_ID_NUM >= 1, compatible with FTS_VENDOR_1_ID
+ * FTS_GET_VENDOR_ID_NUM >= 2, compatible with FTS_VENDOR_2_ID
+ * FTS_GET_VENDOR_ID_NUM == 3, compatible with FTS_VENDOR_3_ID
+ */
+#define FTS_VENDOR_1_ID                         0x00
+#define FTS_VENDOR_2_ID                         0x00
+#define FTS_VENDOR_3_ID                         0x00
+
+/*
+ * FW_APP.i file for auto upgrade, you must replace it with your own
+ * define your own fw_app, the sample one to be replaced is invalid
+ * NOTE: if FTS_GET_VENDOR_ID_NUM >= 1,
+ *       it's the fw corresponding with FTS_VENDOR_1_ID
+ */
+#define FTS_UPGRADE_FW_APP		"include/firmware/FT8716_app_sample.i"
+
+/*
+ * if FTS_GET_VENDOR_ID_NUM >= 2, fw corrsponding with FTS_VENDOR_2_ID
+ * define your own fw_app, the sample one is invalid
+ */
+#define FTS_UPGRADE_FW2_APP		"include/firmware/FT8716_app_sample.i"
+
+/*
+ * if FTS_GET_VENDOR_ID_NUM == 3, fw corrsponding with FTS_VENDOR_3_ID
+ * define your own fw_app, the sample one is invalid
+ */
+#define FTS_UPGRADE_FW3_APP		"include/firmware/FT8716_app_sample.i"
+
+/*
+ * lcd_cfg.i file for lcd cfg upgrade
+ * define your own lcd_cfg.i, the sample one is invalid
+ */
+#define FTS_UPGRADE_LCD_CFG		"include/firmware/lcd_cfg.i"
+
+/*
+ * upgrade stress test for debug
+ * enable it for upgrade debug if needed
+ * default: disable
+ */
+#define FTS_UPGRADE_STRESS_TEST                 0
+/* stress test times, default: 1000 */
+#define FTS_UPGRADE_TEST_NUMBER                 1000
+
+/*********************************************************/
+
+#endif /* _LINUX_FOCLATECH_CONFIG_H_ */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_core.c b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c
new file mode 100644
index 0000000..b3d7322
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_core.c
@@ -0,0 +1,1476 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+/*****************************************************************************
+ *
+ * File Name: focaltech_core.c
+ *
+ * Author: Focaltech Driver Team
+ *
+ * Created: 2016-08-08
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+
+#if defined(CONFIG_FB)
+#include <linux/notifier.h>
+#include <linux/fb.h>
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+#include <linux/earlysuspend.h>
+#define FTS_SUSPEND_LEVEL 1	 /* Early-suspend level */
+#endif
+
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+#define FTS_DRIVER_NAME		"fts_ts"
+#define INTERVAL_READ_REG	20  /* interval time per read reg unit:ms */
+#define TIMEOUT_READ_REG	300 /* timeout of read reg unit:ms */
+#if FTS_POWER_SOURCE_CUST_EN
+#define FTS_VTG_MIN_UV		2600000
+#define FTS_VTG_MAX_UV		3300000
+#define FTS_I2C_VTG_MIN_UV	1800000
+#define FTS_I2C_VTG_MAX_UV	1800000
+#endif
+#define FTS_READ_TOUCH_BUFFER_DIVIDED	   0
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ ******************************************************************************/
+struct i2c_client *fts_i2c_client;
+struct fts_ts_data *fts_wq_data;
+struct input_dev *fts_input_dev;
+
+#if FTS_DEBUG_EN
+int g_show_log = 1;
+#else
+int g_show_log;
+#endif
+
+#if (FTS_DEBUG_EN && (FTS_DEBUG_LEVEL == 2))
+char g_sz_debug[1024] = {0};
+#endif
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+static void fts_release_all_finger(void);
+static int fts_ts_suspend(struct device *dev);
+static int fts_ts_resume(struct device *dev);
+
+
+/*****************************************************************************
+ *  Name: fts_wait_tp_to_valid
+ *  Brief:   Read chip id until TP FW become valid,
+ *           need call when reset/power on/resume...
+ *           1. Read Chip ID per INTERVAL_READ_REG(20ms)
+ *           2. Timeout: TIMEOUT_READ_REG(300ms)
+ *  Input:
+ *  Output:
+ *  Return: 0 - Get correct Device ID
+ *****************************************************************************/
+int fts_wait_tp_to_valid(struct i2c_client *client)
+{
+	int ret = 0;
+	int cnt = 0;
+	u8  reg_value = 0;
+
+	do {
+		ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID, &reg_value);
+		if ((ret < 0) || (reg_value != chip_types.chip_idh)) {
+			FTS_INFO("TP Not Ready, ReadData = 0x%x", reg_value);
+		} else if (reg_value == chip_types.chip_idh) {
+			FTS_INFO("TP Ready, Device ID = 0x%x", reg_value);
+			return 0;
+		}
+		cnt++;
+		msleep(INTERVAL_READ_REG);
+	} while ((cnt * INTERVAL_READ_REG) < TIMEOUT_READ_REG);
+
+	/* error: not get correct reg data */
+	return -EINVAL;
+}
+
+/*****************************************************************************
+ *  Name: fts_recover_state
+ *  Brief: Need execute this function when reset
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+void fts_tp_state_recovery(struct i2c_client *client)
+{
+	/* wait tp stable */
+	fts_wait_tp_to_valid(client);
+	/* recover TP charger state 0x8B */
+	/* recover TP glove state 0xC0 */
+	/* recover TP cover state 0xC1 */
+	fts_ex_mode_recovery(client);
+	/* recover TP gesture state 0xD0 */
+#if FTS_GESTURE_EN
+	fts_gesture_recovery(client);
+#endif
+}
+
+
+/*****************************************************************************
+ *  Name: fts_reset_proc
+ *  Brief: Execute reset operation
+ *  Input: hdelayms - delay time unit:ms
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+int fts_reset_proc(int hdelayms)
+{
+	gpio_direction_output(fts_wq_data->pdata->reset_gpio, 0);
+	msleep(20);
+	gpio_direction_output(fts_wq_data->pdata->reset_gpio, 1);
+	msleep(hdelayms);
+
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: fts_irq_disable
+ *  Brief: disable irq
+ *  Input:
+ *   sync:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+void fts_irq_disable(void)
+{
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&fts_wq_data->irq_lock, irqflags);
+
+	if (!fts_wq_data->irq_disable) {
+		disable_irq_nosync(fts_wq_data->client->irq);
+		fts_wq_data->irq_disable = 1;
+	}
+
+	spin_unlock_irqrestore(&fts_wq_data->irq_lock, irqflags);
+}
+
+/*****************************************************************************
+ *  Name: fts_irq_enable
+ *  Brief: enable irq
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+void fts_irq_enable(void)
+{
+	unsigned long irqflags = 0;
+
+	spin_lock_irqsave(&fts_wq_data->irq_lock, irqflags);
+
+	if (fts_wq_data->irq_disable) {
+		enable_irq(fts_wq_data->client->irq);
+		fts_wq_data->irq_disable = 0;
+	}
+
+	spin_unlock_irqrestore(&fts_wq_data->irq_lock, irqflags);
+}
+
+/*****************************************************************************
+ *  Name: fts_input_dev_init
+ *  Brief: input dev init
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int fts_input_dev_init(struct i2c_client *client,
+			struct fts_ts_data *data, struct input_dev *input_dev,
+			struct fts_ts_platform_data *pdata)
+{
+	int  err, len;
+
+	FTS_FUNC_ENTER();
+
+	/* Init and register Input device */
+	input_dev->name = FTS_DRIVER_NAME;
+	input_dev->id.bustype = BUS_I2C;
+	input_dev->dev.parent = &client->dev;
+
+	input_set_drvdata(input_dev, data);
+	i2c_set_clientdata(client, data);
+
+	__set_bit(EV_KEY, input_dev->evbit);
+	if (data->pdata->have_key) {
+		FTS_DEBUG("set key capabilities");
+		for (len = 0; len < data->pdata->key_number; len++)
+			input_set_capability(input_dev, EV_KEY,
+					data->pdata->keys[len]);
+	}
+	__set_bit(EV_ABS, input_dev->evbit);
+	__set_bit(BTN_TOUCH, input_dev->keybit);
+	__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
+
+#if FTS_MT_PROTOCOL_B_EN
+	input_mt_init_slots(input_dev, pdata->max_touch_number,
+			INPUT_MT_DIRECT);
+#else
+	input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, 0x0f, 0, 0);
+#endif
+	input_set_abs_params(input_dev, ABS_MT_POSITION_X, pdata->x_min,
+				pdata->x_max, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, pdata->y_min,
+				pdata->y_max, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, 0xFF, 0, 0);
+#if FTS_REPORT_PRESSURE_EN
+	input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, 0xFF, 0, 0);
+#endif
+
+	err = input_register_device(input_dev);
+	if (err) {
+		FTS_ERROR("Input device registration failed");
+		goto free_inputdev;
+	}
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+
+free_inputdev:
+	input_free_device(input_dev);
+	FTS_FUNC_EXIT();
+	return err;
+
+}
+
+/*****************************************************************************
+ * Power Control
+ *****************************************************************************/
+#if FTS_POWER_SOURCE_CUST_EN
+static int fts_power_source_init(struct fts_ts_data *data)
+{
+	int rc;
+
+	FTS_FUNC_ENTER();
+
+	data->vdd = regulator_get(&data->client->dev, "vdd");
+	if (IS_ERR(data->vdd)) {
+		rc = PTR_ERR(data->vdd);
+		FTS_ERROR("Regulator get failed vdd rc=%d", rc);
+	}
+
+	if (regulator_count_voltages(data->vdd) > 0) {
+		rc = regulator_set_voltage(data->vdd, FTS_VTG_MIN_UV,
+				FTS_VTG_MAX_UV);
+		if (rc) {
+			FTS_ERROR("Regulator set_vtg failed vdd rc=%d", rc);
+			goto reg_vdd_put;
+		}
+	}
+
+	data->vcc_i2c = regulator_get(&data->client->dev, "vcc-i2c");
+	if (IS_ERR(data->vcc_i2c)) {
+		rc = PTR_ERR(data->vcc_i2c);
+		FTS_ERROR("Regulator get failed vcc-i2c rc=%d", rc);
+		goto reg_vdd_set_vtg;
+	}
+
+	if (regulator_count_voltages(data->vcc_i2c) > 0) {
+		rc = regulator_set_voltage(data->vcc_i2c, FTS_I2C_VTG_MIN_UV,
+				FTS_I2C_VTG_MAX_UV);
+		if (rc) {
+			FTS_ERROR("Regulator set_vtg failed vcc-i2c rc=%d",
+					rc);
+			goto reg_vcc_i2c_put;
+		}
+	}
+
+	FTS_FUNC_EXIT();
+	return 0;
+
+reg_vcc_i2c_put:
+	regulator_put(data->vcc_i2c);
+reg_vdd_set_vtg:
+	if (regulator_count_voltages(data->vdd) > 0)
+		regulator_set_voltage(data->vdd, 0, FTS_VTG_MAX_UV);
+reg_vdd_put:
+	regulator_put(data->vdd);
+	FTS_FUNC_EXIT();
+	return rc;
+}
+
+static int fts_power_source_ctrl(struct fts_ts_data *data, int enable)
+{
+	int rc;
+
+	FTS_FUNC_ENTER();
+	if (enable) {
+		rc = regulator_enable(data->vdd);
+		if (rc)
+			FTS_ERROR("Regulator vdd enable failed rc=%d", rc);
+
+		rc = regulator_enable(data->vcc_i2c);
+		if (rc)
+			FTS_ERROR("Regulator vcc_i2c enable failed rc=%d", rc);
+	} else {
+		rc = regulator_disable(data->vdd);
+		if (rc)
+			FTS_ERROR("Regulator vdd disable failed rc=%d", rc);
+
+		rc = regulator_disable(data->vcc_i2c);
+		if (rc)
+			FTS_ERROR("Regulator vcc_i2c disable failed rc=%d",
+							rc);
+	}
+	FTS_FUNC_EXIT();
+	return 0;
+}
+
+#endif
+
+
+/*****************************************************************************
+ *  Reprot related
+ *****************************************************************************/
+/*****************************************************************************
+ *  Name: fts_release_all_finger
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static void fts_release_all_finger(void)
+{
+#if FTS_MT_PROTOCOL_B_EN
+	unsigned int finger_count = 0;
+#endif
+
+	mutex_lock(&fts_wq_data->report_mutex);
+#if FTS_MT_PROTOCOL_B_EN
+	for (finger_count = 0;
+		finger_count < fts_wq_data->pdata->max_touch_number;
+		finger_count++) {
+		input_mt_slot(fts_input_dev, finger_count);
+		input_mt_report_slot_state(fts_input_dev, MT_TOOL_FINGER,
+						false);
+	}
+#else
+	input_mt_sync(fts_input_dev);
+#endif
+	input_report_key(fts_input_dev, BTN_TOUCH, 0);
+	input_sync(fts_input_dev);
+	mutex_unlock(&fts_wq_data->report_mutex);
+}
+
+
+#if (FTS_DEBUG_EN && (FTS_DEBUG_LEVEL == 2))
+static void fts_show_touch_buffer(u8 *buf, int point_num)
+{
+	int len = point_num * FTS_ONE_TCH_LEN;
+	int count = 0;
+	int i;
+
+	memset(g_sz_debug, 0, 1024);
+	if (len > (POINT_READ_BUF-3))
+		len = POINT_READ_BUF-3;
+	else if (len == 0) {
+		len += FTS_ONE_TCH_LEN;
+
+	count += snprintf(g_sz_debug, 1024, "%02X,%02X,%02X",
+			buf[0], buf[1], buf[2]);
+	for (i = 0; i < len; i++)
+		count += snprintf(g_sz_debug+count, 1024-count,
+				",%02X", buf[i+3]);
+
+	FTS_DEBUG("buffer: %s", g_sz_debug);
+}
+#endif
+
+static int fts_input_dev_report_key_event(struct ts_event *event,
+					struct fts_ts_data *data)
+{
+	int i;
+
+	if (!data->pdata->have_key)
+		return -EINVAL;
+
+	if ((1 == event->touch_point || 1 == event->point_num) &&
+		 (event->au16_y[0] == data->pdata->key_y_coord)) {
+
+		if (event->point_num == 0) {
+			FTS_DEBUG("Keys All Up!");
+			for (i = 0; i < data->pdata->key_number; i++) {
+				input_report_key(data->input_dev,
+					data->pdata->keys[i], 0);
+			}
+
+			input_sync(data->input_dev);
+			return 0;
+		}
+		for (i = 0; i < data->pdata->key_number; i++) {
+			if (event->au16_x[0] >  (data->pdata->key_x_coords[i]
+					- FTS_KEY_WIDTH) && (event->au16_x[0] <
+					(data->pdata->key_x_coords[i]
+					+ FTS_KEY_WIDTH))) {
+				if (event->au8_touch_event[i] == 0 ||
+					event->au8_touch_event[i] == 2) {
+					input_report_key(data->input_dev,
+						data->pdata->keys[i], 1);
+					FTS_DEBUG("Key%d(%d, %d) DOWN!",
+							i, event->au16_x[0],
+							event->au16_y[0]);
+				} else {
+					input_report_key(data->input_dev,
+						data->pdata->keys[i], 0);
+					FTS_DEBUG("Key%d(%d, %d) Up!",
+							i, event->au16_x[0],
+							event->au16_y[0]);
+				}
+				break;
+			}
+		}
+		input_sync(data->input_dev);
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+#if FTS_MT_PROTOCOL_B_EN
+static int fts_input_dev_report_b(struct ts_event *event,
+			struct fts_ts_data *data)
+{
+	int i = 0;
+	int uppoint = 0;
+	int touchs = 0;
+
+	for (i = 0; i < event->touch_point; i++) {
+		if (event->au8_finger_id[i] >= data->pdata->max_touch_number)
+			break;
+
+		input_mt_slot(data->input_dev, event->au8_finger_id[i]);
+
+		if (event->au8_touch_event[i] == FTS_TOUCH_DOWN ||
+			event->au8_touch_event[i] == FTS_TOUCH_CONTACT) {
+			input_mt_report_slot_state(data->input_dev,
+						MT_TOOL_FINGER, true);
+
+#if FTS_REPORT_PRESSURE_EN
+#if FTS_FORCE_TOUCH_EN
+			if (event->pressure[i] <= 0) {
+				FTS_ERROR("[B]Illegal pressure: %d",
+						event->pressure[i]);
+				event->pressure[i] = 1;
+			}
+#else
+			event->pressure[i] = 0x3f;
+#endif
+			input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+					event->pressure[i]);
+#endif
+
+			if (event->area[i] <= 0) {
+				FTS_ERROR("[B]Illegal touch-major: %d",
+						event->area[i]);
+				event->area[i] = 1;
+			}
+			input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
+						event->area[i]);
+
+			input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+					event->au16_x[i]);
+			input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+					event->au16_y[i]);
+			touchs |= BIT(event->au8_finger_id[i]);
+			data->touchs |= BIT(event->au8_finger_id[i]);
+
+#if FTS_REPORT_PRESSURE_EN
+			FTS_DEBUG("[B]P%d(%d, %d)[p:%d,tm:%d] DOWN!",
+					event->au8_finger_id[i],
+					event->au16_x[i], event->au16_y[i],
+					event->pressure[i], event->area[i]);
+#else
+			FTS_DEBUG("[B]P%d(%d, %d)[tm:%d] DOWN!",
+					event->au8_finger_id[i],
+					event->au16_x[i], event->au16_y[i],
+					event->area[i]);
+#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
+			data->touchs &= ~BIT(event->au8_finger_id[i]);
+			FTS_DEBUG("[B]P%d UP!", event->au8_finger_id[i]);
+		}
+	}
+
+	if (unlikely(data->touchs ^ touchs)) {
+		for (i = 0; i < data->pdata->max_touch_number; i++) {
+			if (BIT(i) & (data->touchs ^ touchs)) {
+				FTS_DEBUG("[B]P%d UP!", i);
+				input_mt_slot(data->input_dev, i);
+				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
+			}
+		}
+	}
+
+	data->touchs = touchs;
+	if (event->touch_point == uppoint) {
+		FTS_DEBUG("Points All Up!");
+		input_report_key(data->input_dev, BTN_TOUCH, 0);
+	} else {
+		input_report_key(data->input_dev, BTN_TOUCH,
+				event->touch_point > 0);
+	}
+
+	input_sync(data->input_dev);
+
+	return 0;
+
+}
+
+#else
+static int fts_input_dev_report_a(struct ts_event *event,
+				struct fts_ts_data *data)
+{
+	int i = 0;
+	int uppoint = 0;
+	int touchs = 0;
+
+	for (i = 0; i < event->touch_point; i++) {
+
+		if (event->au8_touch_event[i] == FTS_TOUCH_DOWN ||
+			event->au8_touch_event[i] == FTS_TOUCH_CONTACT) {
+			input_report_abs(data->input_dev, ABS_MT_TRACKING_ID,
+					event->au8_finger_id[i]);
+#if FTS_REPORT_PRESSURE_EN
+#if FTS_FORCE_TOUCH_EN
+			if (event->pressure[i] <= 0) {
+				FTS_ERROR("[B]Illegal pressure: %d",
+						event->pressure[i]);
+				event->pressure[i] = 1;
+			}
+#else
+			event->pressure[i] = 0x3f;
+#endif
+			input_report_abs(data->input_dev, ABS_MT_PRESSURE,
+					event->pressure[i]);
+#endif
+
+			if (event->area[i] <= 0) {
+				FTS_ERROR("[B]Illegal touch-major: %d",
+						event->area[i]);
+				event->area[i] = 1;
+			}
+
+			input_report_abs(data->input_dev, ABS_MT_TOUCH_MAJOR,
+						event->area[i]);
+
+			input_report_abs(data->input_dev, ABS_MT_POSITION_X,
+						event->au16_x[i]);
+			input_report_abs(data->input_dev, ABS_MT_POSITION_Y,
+						event->au16_y[i]);
+
+			input_mt_sync(data->input_dev);
+
+#if FTS_REPORT_PRESSURE_EN
+			FTS_DEBUG("[B]P%d(%d, %d)[p:%d,tm:%d] DOWN!",
+					event->au8_finger_id[i],
+					event->au16_x[i], event->au16_y[i],
+					event->pressure[i], event->area[i]);
+#else
+			FTS_DEBUG("[B]P%d(%d, %d)[tm:%d] DOWN!",
+					event->au8_finger_id[i],
+					event->au16_x[i], event->au16_y[i],
+					event->area[i]);
+#endif
+		} else {
+			uppoint++;
+		}
+	}
+
+	data->touchs = touchs;
+	if (event->touch_point == uppoint) {
+		FTS_DEBUG("Points All Up!");
+		input_report_key(data->input_dev, BTN_TOUCH, 0);
+		input_mt_sync(data->input_dev);
+	} else {
+		input_report_key(data->input_dev, BTN_TOUCH,
+				event->touch_point > 0);
+	}
+
+	input_sync(data->input_dev);
+
+	return 0;
+}
+#endif
+
+/*****************************************************************************
+ *  Name: fts_read_touchdata
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int fts_read_touchdata(struct fts_ts_data *data)
+{
+	u8 buf[POINT_READ_BUF] = { 0 };
+	u8 pointid = FTS_MAX_ID;
+	int ret = -1;
+	int i;
+	struct ts_event *event = &(data->event);
+
+#if FTS_GESTURE_EN
+	u8 state;
+
+	if (data->suspended && data->pdata->wakeup_gestures_en) {
+		fts_i2c_read_reg(data->client, FTS_REG_GESTURE_EN, &state);
+		if (state == 1) {
+			fts_gesture_readdata(data->client);
+			return 1;
+		}
+	}
+#endif
+
+#if FTS_PSENSOR_EN
+	if ((fts_sensor_read_data(data) != 0) && (data->suspended == 1))
+		return 1;
+#endif
+
+
+#if FTS_READ_TOUCH_BUFFER_DIVIDED
+	memset(buf, 0xFF, POINT_READ_BUF);
+	memset(event, 0, sizeof(struct ts_event));
+
+	buf[0] = 0x00;
+	ret = fts_i2c_read(data->client, buf, 1, buf, (3 + FTS_ONE_TCH_LEN));
+	if (ret < 0) {
+		FTS_ERROR("%s read touchdata failed.", __func__);
+		return ret;
+	}
+	event->touch_point = 0;
+	event->point_num = buf[FTS_TOUCH_POINT_NUM] & 0x0F;
+	if (event->point_num > data->pdata->max_touch_number)
+		event->point_num = data->pdata->max_touch_number;
+
+	if (event->point_num > 1) {
+		buf[9] = 0x09;
+		fts_i2c_read(data->client, buf+9, 1, buf+9,
+				(event->point_num - 1) * FTS_ONE_TCH_LEN);
+	}
+#else
+	ret = fts_i2c_read(data->client, buf, 1, buf, POINT_READ_BUF);
+	if (ret < 0) {
+		FTS_ERROR("[B]Read touchdata failed, ret: %d", ret);
+		return ret;
+	}
+
+#if FTS_POINT_REPORT_CHECK_EN
+	fts_point_report_check_queue_work();
+#endif
+
+	memset(event, 0, sizeof(struct ts_event));
+	event->point_num = buf[FTS_TOUCH_POINT_NUM] & 0x0F;
+	if (event->point_num > data->pdata->max_touch_number)
+		event->point_num = data->pdata->max_touch_number;
+	event->touch_point = 0;
+#endif
+
+#if (FTS_DEBUG_EN && (FTS_DEBUG_LEVEL == 2))
+	fts_show_touch_buffer(buf, event->point_num);
+#endif
+
+	for (i = 0; i < data->pdata->max_touch_number; i++) {
+		pointid = (buf[FTS_TOUCH_ID_POS + FTS_ONE_TCH_LEN * i]) >> 4;
+		if (pointid >= FTS_MAX_ID)
+			break;
+
+		event->touch_point++;
+
+		event->au16_x[i] =
+			(s16) (buf[FTS_TOUCH_X_H_POS + FTS_ONE_TCH_LEN * i]
+				& 0x0F) << 8 | (s16) buf[FTS_TOUCH_X_L_POS +
+				FTS_ONE_TCH_LEN * i];
+		event->au16_y[i] =
+			(s16) (buf[FTS_TOUCH_Y_H_POS + FTS_ONE_TCH_LEN * i]
+				& 0x0F) << 8 | (s16) buf[FTS_TOUCH_Y_L_POS +
+				FTS_ONE_TCH_LEN * i];
+		event->au8_touch_event[i] =
+			buf[FTS_TOUCH_EVENT_POS + FTS_ONE_TCH_LEN * i] >> 6;
+		event->au8_finger_id[i] =
+			(buf[FTS_TOUCH_ID_POS + FTS_ONE_TCH_LEN * i]) >> 4;
+		event->area[i] =
+			(buf[FTS_TOUCH_AREA_POS + FTS_ONE_TCH_LEN * i]) >> 4;
+		event->pressure[i] =
+			(s16) buf[FTS_TOUCH_PRE_POS + FTS_ONE_TCH_LEN * i];
+
+		if (event->area[i] == 0)
+			event->area[i] = 0x09;
+
+		if (event->pressure[i] == 0)
+			event->pressure[i] = 0x3f;
+
+		if ((event->au8_touch_event[i] == 0 ||
+			event->au8_touch_event[i] == 2) &&
+			(event->point_num == 0)) {
+			FTS_DEBUG("abnormal touch data from fw");
+			return -EINVAL;
+		}
+	}
+
+	if (event->touch_point == 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: fts_report_value
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static void fts_report_value(struct fts_ts_data *data)
+{
+	struct ts_event *event = &data->event;
+
+
+	FTS_DEBUG("point number: %d, touch point: %d", event->point_num,
+			  event->touch_point);
+
+	if (fts_input_dev_report_key_event(event, data) == 0)
+		return;
+
+#if FTS_MT_PROTOCOL_B_EN
+	fts_input_dev_report_b(event, data);
+#else
+	fts_input_dev_report_a(event, data);
+#endif
+
+
+	return;
+
+}
+
+/*****************************************************************************
+ *  Name: fts_ts_interrupt
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static irqreturn_t fts_ts_interrupt(int irq, void *dev_id)
+{
+	struct fts_ts_data *fts_ts = dev_id;
+	int ret = -1;
+
+	if (!fts_ts) {
+		FTS_ERROR("[INTR]: Invalid fts_ts");
+		return IRQ_HANDLED;
+	}
+
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_set_intr(1);
+#endif
+
+	ret = fts_read_touchdata(fts_wq_data);
+
+	if (ret == 0) {
+		mutex_lock(&fts_wq_data->report_mutex);
+		fts_report_value(fts_wq_data);
+		mutex_unlock(&fts_wq_data->report_mutex);
+	}
+
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_set_intr(0);
+#endif
+
+	return IRQ_HANDLED;
+}
+
+/*****************************************************************************
+ *  Name: fts_gpio_configure
+ *  Brief: Configure IRQ&RESET GPIO
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int fts_gpio_configure(struct fts_ts_data *data)
+{
+	int err = 0;
+
+	FTS_FUNC_ENTER();
+	/* request irq gpio */
+	if (gpio_is_valid(data->pdata->irq_gpio)) {
+		err = gpio_request(data->pdata->irq_gpio, "fts_irq_gpio");
+		if (err) {
+			FTS_ERROR("[GPIO]irq gpio request failed");
+			goto err_irq_gpio_req;
+		}
+
+		err = gpio_direction_input(data->pdata->irq_gpio);
+		if (err) {
+			FTS_ERROR("[GPIO]set_direction for irq gpio failed");
+			goto err_irq_gpio_dir;
+		}
+	}
+	/* request reset gpio */
+	if (gpio_is_valid(data->pdata->reset_gpio)) {
+		err = gpio_request(data->pdata->reset_gpio, "fts_reset_gpio");
+		if (err) {
+			FTS_ERROR("[GPIO]reset gpio request failed");
+			goto err_irq_gpio_dir;
+		}
+
+		err = gpio_direction_output(data->pdata->reset_gpio, 1);
+		if (err) {
+			FTS_ERROR("[GPIO]set_direction for reset gpio failed");
+			goto err_reset_gpio_dir;
+		}
+	}
+
+	FTS_FUNC_EXIT();
+	return 0;
+
+err_reset_gpio_dir:
+	if (gpio_is_valid(data->pdata->reset_gpio))
+		gpio_free(data->pdata->reset_gpio);
+err_irq_gpio_dir:
+	if (gpio_is_valid(data->pdata->irq_gpio))
+		gpio_free(data->pdata->irq_gpio);
+err_irq_gpio_req:
+	FTS_FUNC_EXIT();
+	return err;
+}
+
+
+/*****************************************************************************
+ *  Name: fts_get_dt_coords
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int fts_get_dt_coords(struct device *dev, char *name,
+				struct fts_ts_platform_data *pdata)
+{
+	u32 coords[FTS_COORDS_ARR_SIZE];
+	struct property *prop;
+	struct device_node *np = dev->of_node;
+	int coords_size, rc;
+
+	prop = of_find_property(np, name, NULL);
+	if (!prop)
+		return -EINVAL;
+	if (!prop->value)
+		return -ENODATA;
+
+
+	coords_size = prop->length / sizeof(u32);
+	if (coords_size != FTS_COORDS_ARR_SIZE) {
+		FTS_ERROR("invalid %s", name);
+		return -EINVAL;
+	}
+
+	rc = of_property_read_u32_array(np, name, coords, coords_size);
+	if (rc && (rc != -EINVAL)) {
+		FTS_ERROR("Unable to read %s", name);
+		return rc;
+	}
+
+	if (!strcmp(name, "focaltech,display-coords")) {
+		pdata->x_min = coords[0];
+		pdata->y_min = coords[1];
+		pdata->x_max = coords[2];
+		pdata->y_max = coords[3];
+	} else {
+		FTS_ERROR("unsupported property %s", name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: fts_parse_dt
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int fts_parse_dt(struct device *dev, struct fts_ts_platform_data *pdata)
+{
+	int rc;
+	struct device_node *np = dev->of_node;
+	u32 temp_val;
+
+	FTS_FUNC_ENTER();
+
+	rc = fts_get_dt_coords(dev, "focaltech,display-coords", pdata);
+	if (rc)
+		FTS_ERROR("Unable to get display-coords");
+
+	/* key */
+	pdata->have_key = of_property_read_bool(np, "focaltech,have-key");
+	if (pdata->have_key) {
+		rc = of_property_read_u32(np, "focaltech,key-number",
+					&pdata->key_number);
+		if (rc)
+			FTS_ERROR("Key number undefined!");
+
+		rc = of_property_read_u32_array(np, "focaltech,keys",
+					pdata->keys, pdata->key_number);
+		if (rc)
+			FTS_ERROR("Keys undefined!");
+
+		rc = of_property_read_u32(np, "focaltech,key-y-coord",
+					&pdata->key_y_coord);
+		if (rc)
+			FTS_ERROR("Key Y Coord undefined!");
+
+		rc = of_property_read_u32_array(np, "focaltech,key-x-coords",
+				pdata->key_x_coords, pdata->key_number);
+		if (rc)
+			FTS_ERROR("Key X Coords undefined!");
+
+		FTS_DEBUG("%d: (%d, %d, %d), [%d, %d, %d][%d]",
+				  pdata->key_number, pdata->keys[0],
+				  pdata->keys[1], pdata->keys[2],
+				  pdata->key_x_coords[0],
+				  pdata->key_x_coords[1],
+				  pdata->key_x_coords[2],
+				  pdata->key_y_coord);
+	}
+
+	/* reset, irq gpio info */
+	pdata->reset_gpio = of_get_named_gpio_flags(np,
+					"focaltech,reset-gpio", 0,
+					&pdata->reset_gpio_flags);
+	if (pdata->reset_gpio < 0)
+		FTS_ERROR("Unable to get reset_gpio");
+
+	pdata->irq_gpio = of_get_named_gpio_flags(np, "focaltech,irq-gpio",
+					0, &pdata->irq_gpio_flags);
+	if (pdata->irq_gpio < 0)
+		FTS_ERROR("Unable to get irq_gpio");
+
+	rc = of_property_read_u32(np, "focaltech,max-touch-number", &temp_val);
+	if (!rc) {
+		pdata->max_touch_number = temp_val;
+		FTS_DEBUG("max_touch_number=%d", pdata->max_touch_number);
+	} else {
+		FTS_ERROR("Unable to get max-touch-number");
+		pdata->max_touch_number = FTS_MAX_POINTS;
+	}
+
+	pdata->wakeup_gestures_en = of_property_read_bool(np,
+			"focaltech,wakeup-gestures-en");
+
+	FTS_FUNC_EXIT();
+	return 0;
+}
+
+#if defined(CONFIG_FB)
+/*****************************************************************************
+ *  Name: fb_notifier_callback
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int fb_notifier_callback(struct notifier_block *self,
+				unsigned long event, void *data)
+{
+	struct fb_event *evdata = data;
+	int *blank;
+	struct fts_ts_data *fts_data =
+		container_of(self, struct fts_ts_data, fb_notif);
+
+	if (evdata && evdata->data && event == FB_EVENT_BLANK &&
+		fts_data && fts_data->client) {
+		blank = evdata->data;
+		if (*blank == FB_BLANK_UNBLANK)
+			fts_ts_resume(&fts_data->client->dev);
+		else if (*blank == FB_BLANK_POWERDOWN ||
+				*blank == FB_BLANK_VSYNC_SUSPEND)
+			fts_ts_suspend(&fts_data->client->dev);
+	}
+
+	return 0;
+}
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+/*****************************************************************************
+ *  Name: fts_ts_early_suspend
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static void fts_ts_early_suspend(struct early_suspend *handler)
+{
+	struct fts_ts_data *data = container_of(handler,
+					struct fts_ts_data,
+					early_suspend);
+
+	fts_ts_suspend(&data->client->dev);
+}
+
+/*****************************************************************************
+ *  Name: fts_ts_late_resume
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static void fts_ts_late_resume(struct early_suspend *handler)
+{
+	struct fts_ts_data *data = container_of(handler,
+					struct fts_ts_data,
+					early_suspend);
+
+	fts_ts_resume(&data->client->dev);
+}
+#endif
+
+/*****************************************************************************
+ *  Name: fts_ts_probe
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int fts_ts_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	struct fts_ts_platform_data *pdata;
+	struct fts_ts_data *data;
+	struct input_dev *input_dev;
+	int err;
+
+	FTS_FUNC_ENTER();
+	/* 1. Get Platform data */
+	if (client->dev.of_node) {
+		pdata = devm_kzalloc(&client->dev,
+				sizeof(struct fts_ts_platform_data),
+				GFP_KERNEL);
+		if (!pdata) {
+			FTS_ERROR("[MEMORY]Failed to allocate memory");
+			FTS_FUNC_EXIT();
+			return -ENOMEM;
+		}
+
+		err = fts_parse_dt(&client->dev, pdata);
+		if (err)
+			FTS_ERROR("[DTS]DT parsing failed");
+	} else {
+		pdata = client->dev.platform_data;
+	}
+
+	if (!pdata) {
+		FTS_ERROR("Invalid pdata");
+		FTS_FUNC_EXIT();
+		return -EINVAL;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		FTS_ERROR("I2C not supported");
+		FTS_FUNC_EXIT();
+		return -ENODEV;
+	}
+
+	data = devm_kzalloc(&client->dev, sizeof(struct fts_ts_data),
+				GFP_KERNEL);
+	if (!data) {
+		FTS_ERROR("[MEMORY]Failed to allocate memory");
+		FTS_FUNC_EXIT();
+		return -ENOMEM;
+	}
+
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		FTS_ERROR("[INPUT]Failed to allocate input device");
+		FTS_FUNC_EXIT();
+		return -ENOMEM;
+	}
+
+	data->input_dev = input_dev;
+	data->client = client;
+	data->pdata = pdata;
+
+	fts_wq_data = data;
+	fts_i2c_client = client;
+	fts_input_dev = input_dev;
+
+	spin_lock_init(&fts_wq_data->irq_lock);
+	mutex_init(&fts_wq_data->report_mutex);
+
+	fts_input_dev_init(client, data, input_dev, pdata);
+
+#if FTS_POWER_SOURCE_CUST_EN
+	fts_power_source_init(data);
+	fts_power_source_ctrl(data, 1);
+#endif
+
+	fts_ctpm_get_upgrade_array();
+
+	err = fts_gpio_configure(data);
+	if (err < 0) {
+		FTS_ERROR("[GPIO]Failed to configure the gpios");
+		goto free_gpio;
+	}
+
+	fts_reset_proc(200);
+	fts_wait_tp_to_valid(client);
+
+	err = request_threaded_irq(client->irq, NULL, fts_ts_interrupt,
+				pdata->irq_gpio_flags | IRQF_ONESHOT |
+				IRQF_TRIGGER_FALLING,
+				client->dev.driver->name, data);
+	if (err) {
+		FTS_ERROR("Request irq failed!");
+		goto free_gpio;
+	}
+
+	fts_irq_disable();
+
+#if FTS_PSENSOR_EN
+	if (fts_sensor_init(data) != 0) {
+		FTS_ERROR("fts_sensor_init failed!");
+		FTS_FUNC_EXIT();
+		return 0;
+	}
+#endif
+
+#if FTS_APK_NODE_EN
+	fts_create_apk_debug_channel(client);
+#endif
+
+#if FTS_SYSFS_NODE_EN
+	fts_create_sysfs(client);
+#endif
+
+#if FTS_POINT_REPORT_CHECK_EN
+	fts_point_report_check_init();
+#endif
+
+	fts_ex_mode_init(client);
+
+#if FTS_GESTURE_EN
+	fts_gesture_init(input_dev, client);
+#endif
+
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_init();
+#endif
+
+	fts_irq_enable();
+
+#if FTS_AUTO_UPGRADE_EN
+	fts_ctpm_upgrade_init();
+#endif
+
+#if FTS_TEST_EN
+	fts_test_init(client);
+#endif
+
+#if defined(CONFIG_FB)
+	data->fb_notif.notifier_call = fb_notifier_callback;
+	err = fb_register_client(&data->fb_notif);
+	if (err)
+		FTS_ERROR("[FB]Unable to register fb_notifier: %d", err);
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
+				FTS_SUSPEND_LEVEL;
+	data->early_suspend.suspend = fts_ts_early_suspend;
+	data->early_suspend.resume = fts_ts_late_resume;
+	register_early_suspend(&data->early_suspend);
+#endif
+
+	FTS_FUNC_EXIT();
+	return 0;
+
+free_gpio:
+	if (gpio_is_valid(pdata->reset_gpio))
+		gpio_free(pdata->reset_gpio);
+	if (gpio_is_valid(pdata->irq_gpio))
+		gpio_free(pdata->irq_gpio);
+	return err;
+
+}
+
+/*****************************************************************************
+ *  Name: fts_ts_remove
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int fts_ts_remove(struct i2c_client *client)
+{
+	struct fts_ts_data *data = i2c_get_clientdata(client);
+
+	FTS_FUNC_ENTER();
+	cancel_work_sync(&data->touch_event_work);
+
+#if FTS_PSENSOR_EN
+	fts_sensor_remove(data);
+#endif
+
+#if FTS_POINT_REPORT_CHECK_EN
+	fts_point_report_check_exit();
+#endif
+
+#if FTS_APK_NODE_EN
+	fts_release_apk_debug_channel();
+#endif
+
+#if FTS_SYSFS_NODE_EN
+	fts_remove_sysfs(client);
+#endif
+
+	fts_ex_mode_exit(client);
+
+#if FTS_AUTO_UPGRADE_EN
+	cancel_work_sync(&fw_update_work);
+#endif
+
+#if defined(CONFIG_FB)
+	if (fb_unregister_client(&data->fb_notif))
+		FTS_ERROR("Error occurred while unregistering fb_notifier.");
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	unregister_early_suspend(&data->early_suspend);
+#endif
+	free_irq(client->irq, data);
+
+	if (gpio_is_valid(data->pdata->reset_gpio))
+		gpio_free(data->pdata->reset_gpio);
+
+	if (gpio_is_valid(data->pdata->irq_gpio))
+		gpio_free(data->pdata->irq_gpio);
+
+	input_unregister_device(data->input_dev);
+
+#if FTS_TEST_EN
+	fts_test_exit(client);
+#endif
+
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_exit();
+#endif
+
+	FTS_FUNC_EXIT();
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: fts_ts_suspend
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int fts_ts_suspend(struct device *dev)
+{
+	struct fts_ts_data *data = dev_get_drvdata(dev);
+	int retval = 0;
+
+	FTS_FUNC_ENTER();
+	if (data->suspended) {
+		FTS_INFO("Already in suspend state");
+		FTS_FUNC_EXIT();
+		return -EINVAL;
+	}
+
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_suspend();
+#endif
+
+#if FTS_GESTURE_EN
+	if (data->pdata->wakeup_gestures_en) {
+		retval = fts_gesture_suspend(data->client);
+		if (retval == 0) {
+			/* Enter into gesture mode(suspend) */
+			retval = enable_irq_wake(fts_wq_data->client->irq);
+			if (retval)
+				FTS_ERROR("%s: set_irq_wake failed", __func__);
+			data->suspended = true;
+			FTS_FUNC_EXIT();
+			return 0;
+		}
+	}
+#endif
+
+#if FTS_PSENSOR_EN
+	if (fts_sensor_suspend(data) != 0) {
+		enable_irq_wake(data->client->irq);
+		data->suspended = true;
+		return 0;
+	}
+#endif
+
+	fts_irq_disable();
+
+	/* TP enter sleep mode */
+	retval = fts_i2c_write_reg(data->client, FTS_REG_POWER_MODE,
+				FTS_REG_POWER_MODE_SLEEP_VALUE);
+	if (retval < 0)
+		FTS_ERROR("Set TP to sleep mode fail, ret=%d!", retval);
+
+	data->suspended = true;
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: fts_ts_resume
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int fts_ts_resume(struct device *dev)
+{
+	struct fts_ts_data *data = dev_get_drvdata(dev);
+
+	FTS_FUNC_ENTER();
+	if (!data->suspended) {
+		FTS_DEBUG("Already in awake state");
+		FTS_FUNC_EXIT();
+		return -EINVAL;
+	}
+
+	fts_release_all_finger();
+
+#if (!FTS_CHIP_IDC)
+	fts_reset_proc(200);
+#endif
+
+	fts_tp_state_recovery(data->client);
+
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_resume();
+#endif
+
+#if FTS_GESTURE_EN
+	if (data->pdata->wakeup_gestures_en) {
+		if (fts_gesture_resume(data->client) == 0) {
+			int err;
+
+			err = disable_irq_wake(data->client->irq);
+			if (err)
+				FTS_ERROR("%s: disable_irq_wake failed",
+						__func__);
+			data->suspended = false;
+			FTS_FUNC_EXIT();
+			return 0;
+		}
+	}
+#endif
+
+#if FTS_PSENSOR_EN
+	if (fts_sensor_resume(data) != 0) {
+		disable_irq_wake(data->client->irq);
+		data->suspended = false;
+		FTS_FUNC_EXIT();
+		return 0;
+	}
+#endif
+
+	data->suspended = false;
+
+	fts_irq_enable();
+
+	FTS_FUNC_EXIT();
+	return 0;
+}
+
+/*****************************************************************************
+ * I2C Driver
+ *****************************************************************************/
+static const struct i2c_device_id fts_ts_id[] = {
+	{FTS_DRIVER_NAME, 0},
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, fts_ts_id);
+
+static const struct of_device_id fts_match_table[] = {
+	{ .compatible = "focaltech,fts", },
+	{ },
+};
+
+static struct i2c_driver fts_ts_driver = {
+	.probe = fts_ts_probe,
+	.remove = fts_ts_remove,
+	.driver = {
+		.name = FTS_DRIVER_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = fts_match_table,
+	},
+	.id_table = fts_ts_id,
+};
+
+/*****************************************************************************
+ *  Name: fts_ts_init
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int __init fts_ts_init(void)
+{
+	int ret = 0;
+
+	FTS_FUNC_ENTER();
+	ret = i2c_add_driver(&fts_ts_driver);
+	if (ret != 0)
+		FTS_ERROR("Focaltech touch screen driver init failed!");
+
+	FTS_FUNC_EXIT();
+	return ret;
+}
+
+/*****************************************************************************
+ *  Name: fts_ts_exit
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static void __exit fts_ts_exit(void)
+{
+	i2c_del_driver(&fts_ts_driver);
+}
+
+module_init(fts_ts_init);
+module_exit(fts_ts_exit);
+
+MODULE_DESCRIPTION("FocalTech Touchscreen Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_core.h b/drivers/input/touchscreen/focaltech_touch/focaltech_core.h
new file mode 100644
index 0000000..a3c64f9
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_core.h
@@ -0,0 +1,195 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+/*****************************************************************************
+ *
+ * File Name: focaltech_core.h
+ *
+ * Author: Focaltech Driver Team
+ *
+ * Created: 2016-08-08
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+#ifndef __LINUX_FOCALTECH_CORE_H__
+#define __LINUX_FOCALTECH_CORE_H__
+/*****************************************************************************
+ * Included header files
+ *****************************************************************************/
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/input/mt.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/firmware.h>
+#include <linux/debugfs.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/time.h>
+#include <linux/workqueue.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/uaccess.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/mount.h>
+#include <linux/netdevice.h>
+#include <linux/unistd.h>
+#include <linux/ioctl.h>
+#include "focaltech_common.h"
+#include "focaltech_flash.h"
+#if FTS_PSENSOR_EN
+#include <linux/sensors.h>
+#endif
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+#define LEN_FLASH_ECC_MAX                   0xFFFE
+
+#define FTS_WORKQUEUE_NAME                  "fts_wq"
+
+#define FTS_MAX_POINTS                      10
+#define FTS_KEY_WIDTH                       50
+#define FTS_ONE_TCH_LEN                     6
+#define POINT_READ_BUF  (3 + FTS_ONE_TCH_LEN * FTS_MAX_POINTS)
+
+#define FTS_MAX_ID                          0x0F
+#define FTS_TOUCH_X_H_POS                   3
+#define FTS_TOUCH_X_L_POS                   4
+#define FTS_TOUCH_Y_H_POS                   5
+#define FTS_TOUCH_Y_L_POS                   6
+#define FTS_TOUCH_PRE_POS                   7
+#define FTS_TOUCH_AREA_POS                  8
+#define FTS_TOUCH_POINT_NUM                 2
+#define FTS_TOUCH_EVENT_POS                 3
+#define FTS_TOUCH_ID_POS                    5
+#define FTS_COORDS_ARR_SIZE                 4
+
+#define FTS_TOUCH_DOWN      0
+#define FTS_TOUCH_UP        1
+#define FTS_TOUCH_CONTACT   2
+
+#define FTS_SYSFS_ECHO_ON(buf)      ((strncasecmp(buf, "1", 1)  == 0) || \
+					(strncasecmp(buf, "on", 2) == 0))
+#define FTS_SYSFS_ECHO_OFF(buf)     ((strncasecmp(buf, "0", 1)  == 0) || \
+					(strncasecmp(buf, "off", 3) == 0))
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+
+
+struct fts_ts_platform_data {
+	int irq_gpio;
+	u32 irq_gpio_flags;
+	int reset_gpio;
+	u32 reset_gpio_flags;
+	bool have_key;
+	u32 key_number;
+	u32 keys[4];
+	u32 key_y_coord;
+	u32 key_x_coords[4];
+	u32 x_max;
+	u32 y_max;
+	u32 x_min;
+	u32 y_min;
+	u32 max_touch_number;
+	bool wakeup_gestures_en;
+};
+
+struct ts_event {
+	u16 au16_x[FTS_MAX_POINTS]; /*x coordinate */
+	u16 au16_y[FTS_MAX_POINTS]; /*y coordinate */
+	u16 pressure[FTS_MAX_POINTS];
+	u8 au8_touch_event[FTS_MAX_POINTS]; /* touch event:
+					     * 0 -- down;
+					     * 1 -- up;
+					     * 2 -- contact
+					     */
+	u8 au8_finger_id[FTS_MAX_POINTS];   /* touch ID */
+	u8 area[FTS_MAX_POINTS];
+	u8 touch_point;
+	u8 point_num;
+};
+
+struct fts_ts_data {
+	struct i2c_client *client;
+	struct input_dev *input_dev;
+	struct ts_event event;
+	const struct fts_ts_platform_data *pdata;
+#if FTS_PSENSOR_EN
+	struct fts_psensor_platform_data *psensor_pdata;
+#endif
+	struct work_struct  touch_event_work;
+	struct workqueue_struct *ts_workqueue;
+	struct regulator *vdd;
+	struct regulator *vcc_i2c;
+	spinlock_t irq_lock;
+	struct mutex report_mutex;
+	u16 addr;
+	bool suspended;
+	u8 fw_ver[3];
+	u8 fw_vendor_id;
+	int touchs;
+	int irq_disable;
+
+#if defined(CONFIG_FB)
+	struct notifier_block fb_notif;
+#elif defined(CONFIG_HAS_EARLYSUSPEND)
+	struct early_suspend early_suspend;
+#endif
+};
+
+
+#if FTS_PSENSOR_EN
+struct fts_psensor_platform_data {
+	struct input_dev *input_psensor_dev;
+	struct sensors_classdev ps_cdev;
+	int tp_psensor_opened;
+	char tp_psensor_data; /* 0 near, 1 far */
+	struct fts_ts_data *data;
+};
+
+int fts_sensor_init(struct fts_ts_data *data);
+int fts_sensor_read_data(struct fts_ts_data *data);
+int fts_sensor_suspend(struct fts_ts_data *data);
+int fts_sensor_resume(struct fts_ts_data *data);
+int fts_sensor_remove(struct fts_ts_data *data);
+#endif
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+extern struct i2c_client *fts_i2c_client;
+extern struct fts_ts_data *fts_wq_data;
+extern struct input_dev *fts_input_dev;
+
+#endif /* __LINUX_FOCALTECH_CORE_H__ */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_esdcheck.c b/drivers/input/touchscreen/focaltech_touch/focaltech_esdcheck.c
new file mode 100644
index 0000000..0b2fc53
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_esdcheck.c
@@ -0,0 +1,478 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_esdcheck.c
+ *
+ *    Author: luoguojin
+ *
+ *   Created: 2016-08-03
+ *
+ *  Abstract: ESD check function
+ *
+ *   Version: v1.0
+ *
+ * Revision History:
+ *        v1.0:
+ *            First release. By luougojin 2016-08-03
+ *        v1.1: By luougojin 2017-02-15
+ *            1. Add LCD_ESD_PATCH to control idc_esdcheck_lcderror
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+#if FTS_ESDCHECK_EN
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+#define ESDCHECK_WAIT_TIME              1000    /* ms */
+#define LCD_ESD_PATCH                   0
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+struct fts_esdcheck_st {
+	u8  active              : 1;    /* 1- esd check active, need check esd
+					 * 0- no esd check
+					 */
+	u8  suspend             : 1;
+	u8  proc_debug          : 1;    /* apk or adb is accessing I2C */
+	u8  intr                : 1;    /* 1- Interrupt trigger */
+	u8  unused              : 4;
+	u8  flow_work_hold_cnt;		/* Flow Work Cnt(reg0x91)
+					 * keep a same value for x times.
+					 * >=5 times is ESD, need reset
+					 */
+	u8  flow_work_cnt_last;       /* Save Flow Work Cnt(reg0x91) value */
+	u32 hardware_reset_cnt;
+	u32 i2c_nack_cnt;
+	u32 i2c_dataerror_cnt;
+};
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+static struct delayed_work fts_esdcheck_work;
+static struct workqueue_struct *fts_esdcheck_workqueue;
+static struct fts_esdcheck_st fts_esdcheck_data;
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+
+/*****************************************************************************
+ * functions body
+ *****************************************************************************/
+#if LCD_ESD_PATCH
+/*****************************************************************************
+ *  Name: lcd_esdcheck
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+int lcd_need_reset;
+static int tp_need_recovery; /* LCD reset cause Tp reset */
+int idc_esdcheck_lcderror(void)
+{
+	u8 val;
+	int ret;
+
+	FTS_DEBUG("[ESD]Check LCD ESD");
+	if ((tp_need_recovery == 1) && (lcd_need_reset == 0)) {
+		tp_need_recovery = 0;
+		/* LCD reset, need recover TP state */
+		fts_tp_state_recovery(fts_i2c_client);
+	}
+
+	ret = fts_i2c_read_reg(fts_i2c_client, FTS_REG_ESD_SATURATE, &val);
+	if (ret < 0) {
+		FTS_ERROR("[ESD]: Read ESD_SATURATE(0xED) failed ret=%d", ret);
+		return -EIO;
+	}
+
+	if (val == 0xAA) {
+		/*
+		 * 1. Set flag lcd_need_reset = 1;
+		 * 2. LCD driver need reset(recovery) LCD and
+		 *	set lcd_need_reset to 0
+		 * 3. recover TP state
+		 */
+		FTS_INFO("LCD ESD, Execute LCD reset!");
+		lcd_need_reset = 1;
+		tp_need_recovery = 1;
+	}
+
+	return 0;
+}
+#endif
+
+/*****************************************************************************
+ *  Name: fts_esdcheck_tp_reset
+ *  Brief: esd check algorithm
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int fts_esdcheck_tp_reset(void)
+{
+	FTS_FUNC_ENTER();
+
+	fts_esdcheck_data.flow_work_hold_cnt = 0;
+	fts_esdcheck_data.hardware_reset_cnt++;
+
+	fts_reset_proc(200);
+	fts_tp_state_recovery(fts_i2c_client);
+
+	FTS_FUNC_EXIT();
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: get_chip_id
+ *  Brief: Read Chip Id 3 times
+ *  Input:
+ *  Output:
+ *  Return:  1 - Read Chip Id 3 times failed
+ *	    0 - Read Chip Id pass
+ *****************************************************************************/
+static bool get_chip_id(void)
+{
+	int err = 0;
+	int i = 0;
+	u8  reg_value = 0;
+	u8  reg_addr = 0;
+
+	for (i = 0; i < 3; i++) {
+		reg_addr = FTS_REG_CHIP_ID;
+		err = fts_i2c_read(fts_i2c_client, &reg_addr, 1,
+				&reg_value, 1);
+
+		if (err < 0) {
+			FTS_ERROR("[ESD]: Read Reg 0xA3 failed ret = %d!!",
+					err);
+			fts_esdcheck_data.i2c_nack_cnt++;
+		} else {
+			/* Upgrade sometimes can't detect */
+			if ((reg_value == chip_types.chip_idh)
+				|| (reg_value == 0xEF))
+				break;
+
+			fts_esdcheck_data.i2c_dataerror_cnt++;
+		}
+	}
+
+	/* if can't get correct data in 3 times, then need hardware reset */
+	if (i >= 3) {
+		FTS_ERROR("[ESD]: Read Chip id failed, need TP reset!!");
+		return 1;
+	}
+
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: get_flow_cnt
+ *  Brief: Read flow cnt(0x91)
+ *  Input:
+ *  Output:
+ *  Return:  1 - Reg 0x91(flow cnt) abnormal: hold a value for 5 times
+ *	    0 - Reg 0x91(flow cnt) normal
+ *****************************************************************************/
+static bool get_flow_cnt(void)
+{
+	int err = 0;
+	u8  reg_value = 0;
+	u8  reg_addr = 0;
+
+	reg_addr = FTS_REG_FLOW_WORK_CNT;
+	err = fts_i2c_read(fts_i2c_client, &reg_addr, 1, &reg_value, 1);
+	if (err < 0) {
+		FTS_ERROR("[ESD]: Read Reg 0x91 failed ret = %d!!", err);
+		fts_esdcheck_data.i2c_nack_cnt++;
+	} else {
+		if (reg_value == fts_esdcheck_data.flow_work_cnt_last)
+			fts_esdcheck_data.flow_work_hold_cnt++;
+		else
+			fts_esdcheck_data.flow_work_hold_cnt = 0;
+
+		fts_esdcheck_data.flow_work_cnt_last = reg_value;
+	}
+
+	/* if read flow work cnt 5 times and the value are all the same,
+	 * then need hardware_reset.
+	 */
+	if (fts_esdcheck_data.flow_work_hold_cnt >= 5) {
+		FTS_DEBUG("[ESD]: Flow Work Cnt, need execute TP reset!!");
+		return 1;
+	}
+
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: esdcheck_algorithm
+ *  Brief: esd check algorithm
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int esdcheck_algorithm(void)
+{
+	int err = 0;
+	u8  reg_value = 0;
+	u8  reg_addr = 0;
+	bool hardware_reset = 0;
+
+	/* 1. esdcheck is interrupt, then return */
+	if (fts_esdcheck_data.intr == 1) {
+		FTS_INFO("[ESD]: In interrupt state, not check esd, return!!");
+		return 0;
+	}
+
+	/* 2. check power state, if suspend, no need check esd */
+	if (fts_esdcheck_data.suspend == 1) {
+		FTS_INFO("[ESD]: In suspend, not check esd, return!!");
+		/* because in suspend state, adb can be used, when upgrade FW,
+		 * will active ESD check(active = 1).
+		 * But in suspend, then will don't queue_delayed_work,
+		 * when resume, don't check ESD again
+		 */
+		fts_esdcheck_data.active = 0;
+		return 0;
+	}
+
+	/* 3. check fts_esdcheck_data.proc_debug state,
+	 *	if 1-proc busy, no need check esd
+	 */
+	if (fts_esdcheck_data.proc_debug == 1) {
+		FTS_INFO("[ESD]: In cmd mode, not check esd, return!!");
+		return 0;
+	}
+
+	/* 4. In factory mode, can't check esd */
+	reg_addr = FTS_REG_WORKMODE;
+	err = fts_i2c_read(fts_i2c_client, &reg_addr, 1, &reg_value, 1);
+	if (err < 0) {
+		fts_esdcheck_data.i2c_nack_cnt++;
+	} else if ((reg_value & 0x70) ==  FTS_REG_WORKMODE_FACTORY_VALUE) {
+		FTS_INFO("[ESD]: In factory mode, not check esd, return!!");
+		return 0;
+	}
+
+	/* 5. IDC esd check lcd  default:close */
+#if LCD_ESD_PATCH
+	idc_esdcheck_lcderror();
+#endif
+
+	/* 6. Get Chip ID */
+	hardware_reset = get_chip_id();
+
+	/* 7. get Flow work cnt: 0x91 If no change for 5 times,
+	 *	then ESD and reset
+	 */
+	if (!hardware_reset)
+		hardware_reset = get_flow_cnt();
+
+	/* 8. If need hardware reset, then handle it here */
+	if (hardware_reset == 1)
+		fts_esdcheck_tp_reset();
+
+	FTS_INFO("[ESD]: NoACK=%d, Error Data=%d, Hardware Reset=%d\n",
+			fts_esdcheck_data.i2c_nack_cnt,
+			fts_esdcheck_data.i2c_dataerror_cnt,
+			fts_esdcheck_data.hardware_reset_cnt);
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: fts_esdcheck_func
+ *  Brief: fts_esdcheck_func
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static void esdcheck_func(struct work_struct *work)
+{
+	FTS_FUNC_ENTER();
+
+	esdcheck_algorithm();
+
+	if (fts_esdcheck_data.suspend == 0) {
+		queue_delayed_work(fts_esdcheck_workqueue,
+				&fts_esdcheck_work,
+				msecs_to_jiffies(ESDCHECK_WAIT_TIME));
+	}
+
+	FTS_FUNC_EXIT();
+}
+
+/*****************************************************************************
+ *  Name: fts_esdcheck_set_intr
+ *  Brief: interrupt flag (main used in interrupt tp report)
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+int fts_esdcheck_set_intr(bool intr)
+{
+	/* interrupt don't add debug message */
+	fts_esdcheck_data.intr = intr;
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: fts_esdcheck_get_status(void)
+ *  Brief: get current status
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+int fts_esdcheck_get_status(void)
+{
+	/* interrupt don't add debug message */
+	return fts_esdcheck_data.active;
+}
+
+/*****************************************************************************
+ *  Name: fts_esdcheck_proc_busy
+ *  Brief: When APK or ADB command access TP via driver, then need
+ *		set proc_debug, then will not check ESD.
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+int fts_esdcheck_proc_busy(bool proc_debug)
+{
+	fts_esdcheck_data.proc_debug = proc_debug;
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: fts_esdcheck_switch
+ *  Brief: FTS esd check function switch.
+ *  Input:   enable: 1 - Enable esd check
+ *		    0 - Disable esd check
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+int fts_esdcheck_switch(bool enable)
+{
+	FTS_FUNC_ENTER();
+	if (enable == 1) {
+		if (fts_esdcheck_data.active == 0) {
+			FTS_INFO("[ESD]: ESD check start!!");
+			fts_esdcheck_data.active = 1;
+			queue_delayed_work(fts_esdcheck_workqueue,
+					&fts_esdcheck_work,
+					msecs_to_jiffies(ESDCHECK_WAIT_TIME));
+		}
+	} else {
+		if (fts_esdcheck_data.active == 1) {
+			FTS_INFO("[ESD]: ESD check stop!!");
+			fts_esdcheck_data.active = 0;
+			cancel_delayed_work_sync(&fts_esdcheck_work);
+		}
+	}
+
+	FTS_FUNC_EXIT();
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: fts_esdcheck_suspend
+ *  Brief: Run when tp enter into suspend
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+int fts_esdcheck_suspend(void)
+{
+	FTS_FUNC_ENTER();
+	fts_esdcheck_switch(DISABLE);
+	fts_esdcheck_data.suspend = 1;
+	FTS_FUNC_EXIT();
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: fts_esdcheck_resume
+ *  Brief: Run when tp resume
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+int fts_esdcheck_resume(void)
+{
+	FTS_FUNC_ENTER();
+	fts_esdcheck_switch(ENABLE);
+	fts_esdcheck_data.suspend = 0;
+	FTS_FUNC_EXIT();
+	return 0;
+}
+
+
+/*****************************************************************************
+ *  Name: fts_esdcheck_init
+ *  Brief: Init and create a queue work to check esd
+ *  Input:
+ *  Output:
+ *  Return: < 0: Fail to create esd check queue
+ *****************************************************************************/
+int fts_esdcheck_init(void)
+{
+	FTS_FUNC_ENTER();
+
+	INIT_DELAYED_WORK(&fts_esdcheck_work, esdcheck_func);
+	fts_esdcheck_workqueue = create_workqueue("fts_esdcheck_wq");
+	if (fts_esdcheck_workqueue == NULL)
+		FTS_INFO("[ESD]: Failed to create esd work queue!!");
+
+	memset((u8 *)&fts_esdcheck_data, 0, sizeof(struct fts_esdcheck_st));
+
+	fts_esdcheck_switch(ENABLE);
+	FTS_FUNC_EXIT();
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: fts_esdcheck_exit
+ *  Brief: When FTS TP driver is removed, then call this function
+ *		to destroy work queue
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+int fts_esdcheck_exit(void)
+{
+	FTS_FUNC_ENTER();
+
+	destroy_workqueue(fts_esdcheck_workqueue);
+
+	FTS_FUNC_EXIT();
+	return 0;
+}
+#endif /* FTS_ESDCHECK_EN */
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_ex_fun.c b/drivers/input/touchscreen/focaltech_touch/focaltech_ex_fun.c
new file mode 100644
index 0000000..6b21aca
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_ex_fun.c
@@ -0,0 +1,1145 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: Focaltech_ex_fun.c
+ *
+ * Author: Focaltech Driver Team
+ *
+ * Created: 2016-08-08
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+/*create apk debug channel*/
+#define PROC_UPGRADE                            0
+#define PROC_READ_REGISTER                      1
+#define PROC_WRITE_REGISTER                     2
+#define PROC_AUTOCLB                            4
+#define PROC_UPGRADE_INFO                       5
+#define PROC_WRITE_DATA                         6
+#define PROC_READ_DATA                          7
+#define PROC_SET_TEST_FLAG                      8
+#define PROC_SET_SLAVE_ADDR                     10
+#define PROC_HW_RESET                           11
+#define PROC_NAME                               "ftxxxx-debug"
+#define WRITE_BUF_SIZE                          512
+#define READ_BUF_SIZE                           512
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+static unsigned char proc_operate_mode = PROC_UPGRADE;
+static struct proc_dir_entry *fts_proc_entry;
+static struct
+{
+	int op;         /*  0: read, 1: write */
+	int reg;        /*  register */
+	int value;      /*  read: return value, write: op return */
+	int result;     /*  0: success, otherwise: fail */
+} g_rwreg_result;
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if FTS_ESDCHECK_EN
+static void esd_process(u8 *writebuf, int buflen, bool flag)
+{
+	if (flag) {
+		if ((writebuf[1] == 0xFC) && (writebuf[2] == 0x55)
+			&& (buflen == 0x03)) {
+			/* Upgrade command */
+			FTS_DEBUG("[ESD]: Upgrade command(%x %x %x)!!",
+					writebuf[0], writebuf[1], writebuf[2]);
+			fts_esdcheck_switch(DISABLE);
+		} else if ((writebuf[1] == 0x00) && (writebuf[2] == 0x40)
+				&& (buflen == 0x03)) {
+			/* factory mode bit 4 5 6 */
+			FTS_DEBUG("[ESD]: Entry factory mode(%x %x %x)!!",
+					writebuf[0], writebuf[1], writebuf[2]);
+			fts_esdcheck_switch(DISABLE);
+		} else if ((writebuf[1] == 0x00) && (writebuf[2] == 0x00)
+				&& (buflen == 0x03)) {
+			/* normal mode bit 4 5 6 */
+			FTS_DEBUG("[ESD]: Exit factory mode(%x %x %x)!!",
+					writebuf[0], writebuf[1], writebuf[2]);
+			fts_esdcheck_switch(ENABLE);
+		} else {
+			fts_esdcheck_proc_busy(1);
+		}
+	} else {
+		if ((writebuf[1] == 0x07) && (buflen == 0x02)) {
+			FTS_DEBUG("[ESD]: Upgrade finish-trigger (07)(%x %x)!!",
+					writebuf[0], writebuf[1]);
+			fts_esdcheck_switch(ENABLE);
+		} else {
+			fts_esdcheck_proc_busy(0);
+		}
+	}
+}
+#endif
+
+/*interface of write proc*/
+/************************************************************************
+ *   Name: fts_debug_write
+ *  Brief:interface of write proc
+ * Input: file point, data buf, data len, no use
+ * Output: no
+ * Return: data len
+ ***********************************************************************/
+static ssize_t fts_debug_write(struct file *filp, const char __user *buff,
+			size_t count, loff_t *ppos)
+{
+	unsigned char writebuf[WRITE_BUF_SIZE];
+	char upgrade_file_path[FILE_NAME_LENGTH];
+	int buflen = count;
+	int writelen = 0;
+	int ret = 0;
+	char tmp[25];
+
+	if (copy_from_user(&writebuf, buff, buflen)) {
+		FTS_DEBUG("[APK]: copy from user error!!");
+		return -EFAULT;
+	}
+#if FTS_ESDCHECK_EN
+	esd_process(writebuf, buflen, 1);
+#endif
+	proc_operate_mode = writebuf[0];
+	switch (proc_operate_mode) {
+	case PROC_UPGRADE:
+
+		memset(upgrade_file_path, 0, sizeof(upgrade_file_path));
+		snprintf(upgrade_file_path, FILE_NAME_LENGTH,
+				"%s", writebuf + 1);
+		upgrade_file_path[buflen-1] = '\0';
+		FTS_DEBUG("%s\n", upgrade_file_path);
+		fts_irq_disable();
+#if FTS_ESDCHECK_EN
+		fts_esdcheck_switch(DISABLE);
+#endif
+		if (fts_updatefun_curr.upgrade_with_app_bin_file)
+			ret = fts_updatefun_curr.
+				upgrade_with_app_bin_file(fts_i2c_client,
+						upgrade_file_path);
+#if FTS_ESDCHECK_EN
+		fts_esdcheck_switch(ENABLE);
+#endif
+		fts_irq_enable();
+		if (ret < 0)
+			FTS_ERROR("[APK]: upgrade failed!!");
+		break;
+
+	case PROC_SET_TEST_FLAG:
+		FTS_DEBUG("[APK]: PROC_SET_TEST_FLAG = %x!!", writebuf[1]);
+#if FTS_ESDCHECK_EN
+		if (writebuf[1] == 0)
+			fts_esdcheck_switch(DISABLE);
+		else
+			fts_esdcheck_switch(ENABLE);
+#endif
+		break;
+	case PROC_READ_REGISTER:
+		writelen = 1;
+		ret = fts_i2c_write(fts_i2c_client, writebuf + 1, writelen);
+		if (ret < 0)
+			FTS_ERROR("[APK]: write iic error!!");
+		break;
+	case PROC_WRITE_REGISTER:
+		writelen = 2;
+		ret = fts_i2c_write(fts_i2c_client, writebuf + 1, writelen);
+		if (ret < 0)
+			FTS_ERROR("[APK]: write iic error!!");
+		break;
+	case PROC_SET_SLAVE_ADDR:
+		ret = fts_i2c_client->addr;
+		FTS_DEBUG("Original i2c addr 0x%x ", ret << 1);
+		if (writebuf[1] != fts_i2c_client->addr) {
+			fts_i2c_client->addr = writebuf[1];
+			FTS_DEBUG("Change i2c addr 0x%x to 0x%x", ret << 1,
+					writebuf[1] << 1);
+
+		}
+		break;
+
+	case PROC_HW_RESET:
+
+		snprintf(tmp, 25, "%s", writebuf + 1);
+		tmp[buflen - 1] = '\0';
+		if (memcmp(tmp, "focal_driver", 12) == 0) {
+			FTS_DEBUG("Begin HW Reset");
+			fts_reset_proc(1);
+		}
+
+		break;
+
+	case PROC_AUTOCLB:
+		FTS_DEBUG("[APK]: autoclb!!");
+		fts_ctpm_auto_clb(fts_i2c_client);
+		break;
+	case PROC_READ_DATA:
+	case PROC_WRITE_DATA:
+		writelen = count - 1;
+		if (writelen > 0) {
+			ret = fts_i2c_write(fts_i2c_client, writebuf + 1,
+						writelen);
+			if (ret < 0)
+				FTS_ERROR("[APK]: write iic error!!");
+		}
+		break;
+	default:
+			break;
+	}
+
+#if FTS_ESDCHECK_EN
+	esd_process(writebuf, buflen, 0);
+#endif
+
+	if (ret < 0)
+		return ret;
+	else
+		return count;
+}
+
+/* interface of read proc */
+/************************************************************************
+ *   Name: fts_debug_read
+ *  Brief:interface of read proc
+ * Input: point to the data, no use, no use, read len, no use, no use
+ * Output: page point to data
+ * Return: read char number
+ ***********************************************************************/
+static ssize_t fts_debug_read(struct file *filp, char __user *buff,
+		size_t count, loff_t *ppos)
+{
+	int ret = 0;
+	int num_read_chars = 0;
+	int readlen = 0;
+	u8 regvalue = 0x00, regaddr = 0x00;
+	unsigned char buf[READ_BUF_SIZE];
+
+	memset(buf, 0, READ_BUF_SIZE);
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_proc_busy(1);
+#endif
+	switch (proc_operate_mode) {
+	case PROC_UPGRADE:
+		/*  after calling fts_debug_write to upgrade */
+		regaddr = FTS_REG_FW_VER;
+		ret = fts_i2c_read_reg(fts_i2c_client, regaddr, &regvalue);
+		if (ret < 0)
+			num_read_chars = snprintf(buf, READ_BUF_SIZE, "%s",
+					"get fw version failed.\n");
+		else
+			num_read_chars = snprintf(buf, READ_BUF_SIZE,
+					"current fw ver:0x%02x\n", regvalue);
+		break;
+	case PROC_READ_REGISTER:
+		readlen = 1;
+		ret = fts_i2c_read(fts_i2c_client, NULL, 0, buf, readlen);
+		if (ret < 0) {
+#if FTS_ESDCHECK_EN
+			fts_esdcheck_proc_busy(0);
+#endif
+			FTS_ERROR("[APK]: read iic error!!");
+			return ret;
+		}
+		num_read_chars = 1;
+		break;
+	case PROC_READ_DATA:
+		readlen = count;
+		ret = fts_i2c_read(fts_i2c_client, NULL, 0, buf, readlen);
+		if (ret < 0) {
+#if FTS_ESDCHECK_EN
+			fts_esdcheck_proc_busy(0);
+#endif
+			FTS_ERROR("[APK]: read iic error!!");
+			return ret;
+		}
+
+		num_read_chars = readlen;
+		break;
+	case PROC_WRITE_DATA:
+		break;
+	default:
+		break;
+	}
+
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_proc_busy(0);
+#endif
+
+	if (copy_to_user(buff, buf, num_read_chars)) {
+		FTS_ERROR("[APK]: copy to user error!!");
+		return -EFAULT;
+	}
+
+	return num_read_chars;
+}
+
+static const struct file_operations fts_proc_fops = {
+	.owner  = THIS_MODULE,
+	.read   = fts_debug_read,
+	.write  = fts_debug_write,
+};
+
+/************************************************************************
+ * Name: fts_create_apk_debug_channel
+ * Brief:  create apk debug channel
+ * Input: i2c info
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+int fts_create_apk_debug_channel(struct i2c_client *client)
+{
+	fts_proc_entry = proc_create(PROC_NAME, 0644, NULL, &fts_proc_fops);
+	if (fts_proc_entry == NULL) {
+		FTS_ERROR("Couldn't create proc entry!");
+		return -ENOMEM;
+	}
+
+	FTS_INFO("Create proc entry success!");
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_release_apk_debug_channel
+ * Brief:  release apk debug channel
+ * Input: no
+ * Output: no
+ * Return: no
+ ***********************************************************************/
+void fts_release_apk_debug_channel(void)
+{
+	if (fts_proc_entry)
+		proc_remove(fts_proc_entry);
+}
+
+/*
+ * fts_hw_reset interface
+ */
+static ssize_t fts_hw_reset_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	return -EPERM;
+}
+static ssize_t fts_hw_reset_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	ssize_t count = 0;
+
+	fts_reset_proc(200);
+
+	count = snprintf(buf, PAGE_SIZE, "hw reset executed\n");
+
+	return count;
+}
+
+/*
+ * fts_irq interface
+ */
+static ssize_t fts_irq_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	if (FTS_SYSFS_ECHO_ON(buf)) {
+		FTS_INFO("[EX-FUN]enable irq");
+		fts_irq_enable();
+	} else if (FTS_SYSFS_ECHO_OFF(buf)) {
+		FTS_INFO("[EX-FUN]disable irq");
+		fts_irq_disable();
+	}
+
+	return count;
+}
+
+static ssize_t fts_irq_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return -EPERM;
+}
+
+/************************************************************************
+ * Name: fts_tpfwver_show
+ * Brief:  show tp fw vwersion
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: char number
+ ***********************************************************************/
+static ssize_t fts_tpfwver_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	ssize_t num_read_chars = 0;
+	u8 fwver = 0;
+
+	mutex_lock(&fts_input_dev->mutex);
+
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_proc_busy(1);
+#endif
+	if (fts_i2c_read_reg(fts_i2c_client, FTS_REG_FW_VER, &fwver) < 0)
+		num_read_chars = snprintf(buf, PAGE_SIZE,
+					"I2c transfer error!\n");
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_proc_busy(0);
+#endif
+	if (fwver == 255)
+		num_read_chars = snprintf(buf, PAGE_SIZE,
+					"get tp fw version fail!\n");
+	else
+		num_read_chars = snprintf(buf, PAGE_SIZE, "%02X\n", fwver);
+
+	mutex_unlock(&fts_input_dev->mutex);
+
+	return num_read_chars;
+}
+/************************************************************************
+ * Name: fts_tpfwver_store
+ * Brief:  no
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_tpfwver_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	/* place holder for future use */
+	return -EPERM;
+}
+
+static int fts_is_hex_char(const char ch)
+{
+	int result = 0;
+
+	if (ch >= '0' && ch <= '9')
+		result = 1;/* (int)(ch - '0'); */
+	else if (ch >= 'a' && ch <= 'f')
+		result = 1;/* (int)(ch - 'a') + 10; */
+	else if (ch >= 'A' && ch <= 'F')
+		result = 1;/* (int)(ch - 'A') + 10; */
+	else
+		result = 0;
+
+	return result;
+}
+
+static int fts_hex_char_to_int(const char ch)
+{
+	int result = 0;
+
+	if (ch >= '0' && ch <= '9')
+		result = (int)(ch - '0');
+	else if (ch >= 'a' && ch <= 'f')
+		result = (int)(ch - 'a') + 10;
+	else if (ch >= 'A' && ch <= 'F')
+		result = (int)(ch - 'A') + 10;
+	else
+		result = -1;
+
+	return result;
+}
+
+static int fts_hex_to_str(char *hex, int iHexLen, char *ch, int *iChLen)
+{
+	int high = 0;
+	int low = 0;
+	int tmp = 0;
+	int i = 0;
+	int iCharLen = 0;
+
+	if (hex == NULL || ch == NULL)
+		return -EINVAL;
+
+	FTS_DEBUG("iHexLen: %d in function:%s!!\n\n", iHexLen, __func__);
+
+	if (iHexLen % 2 == 1)
+		return -EINVAL;
+
+	for (i = 0; i < iHexLen; i += 2) {
+		high = fts_hex_char_to_int(hex[i]);
+		if (high < 0) {
+			ch[iCharLen] = '\0';
+			return -EINVAL;
+		}
+
+		low = fts_hex_char_to_int(hex[i+1]);
+		if (low < 0) {
+			ch[iCharLen] = '\0';
+			return -EINVAL;
+		}
+
+		tmp = (high << 4) + low;
+		ch[iCharLen++] = (char)tmp;
+	}
+
+	ch[iCharLen] = '\0';
+	*iChLen = iCharLen;
+	FTS_DEBUG("iCharLen: %d, iChLen: %d in function:%s!!\n\n", iCharLen,
+				*iChLen, __func__);
+
+	return 0;
+}
+
+static void fts_str_to_bytes(char *bufStr, int iLen,
+		char *uBytes, int *iBytesLen)
+{
+	int i = 0;
+	int iNumChLen = 0;
+
+	*iBytesLen = 0;
+
+	for (i = 0; i < iLen; i++) {
+		if (fts_is_hex_char(bufStr[i])) /* filter illegal chars */
+			bufStr[iNumChLen++] = bufStr[i];
+	}
+
+	bufStr[iNumChLen] = '\0';
+
+	fts_hex_to_str(bufStr, iNumChLen, uBytes, iBytesLen);
+}
+/************************************************************************
+ * Name: fts_tprwreg_show
+ * Brief:  no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_tprwreg_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int count;
+
+	mutex_lock(&fts_input_dev->mutex);
+
+	if (!g_rwreg_result.op) {
+		if (g_rwreg_result.result == 0)
+			count = snprintf(buf, PAGE_SIZE, "Read %02X: %02X\n",
+					g_rwreg_result.reg,
+					g_rwreg_result.value);
+		else
+			count = snprintf(buf, PAGE_SIZE,
+					"Read %02X failed, ret: %d\n",
+					g_rwreg_result.reg,
+					g_rwreg_result.result);
+	} else {
+		if (g_rwreg_result.result == 0)
+			count = snprintf(buf, PAGE_SIZE,
+					"Write %02X, %02X success\n",
+					g_rwreg_result.reg,
+					g_rwreg_result.value);
+		else
+			count = snprintf(buf, PAGE_SIZE,
+					"Write %02X failed, ret: %d\n",
+					g_rwreg_result.reg,
+					g_rwreg_result.result);
+	}
+
+	mutex_unlock(&fts_input_dev->mutex);
+
+	return count;
+}
+/************************************************************************
+ * Name: fts_tprwreg_store
+ * Brief:  read/write register
+ * Input: device, device attribute, char buf, char count
+ * Output: print register value
+ * Return: char count
+ ***********************************************************************/
+static ssize_t fts_tprwreg_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	ssize_t num_read_chars = 0;
+	int retval;
+	unsigned long int wmreg = 0;
+	u8 regaddr = 0xff, regvalue = 0xff;
+	u8 valbuf[5] = {0};
+
+	memset(valbuf, 0, sizeof(valbuf));
+	mutex_lock(&fts_input_dev->mutex);
+	num_read_chars = count - 1;
+	if (num_read_chars != 2) {
+		if (num_read_chars != 4) {
+			FTS_ERROR("please input 2 or 4 character");
+			goto error_return;
+		}
+	}
+	memcpy(valbuf, buf, num_read_chars);
+	retval = kstrtoul(valbuf, 16, &wmreg);
+	fts_str_to_bytes((char *)buf, num_read_chars, valbuf, &retval);
+
+	if (retval == 1) {
+		regaddr = valbuf[0];
+		retval = 0;
+	} else if (retval == 2) {
+		regaddr = valbuf[0];
+		regvalue = valbuf[1];
+		retval = 0;
+	} else
+		retval = -1;
+
+	if (retval != 0) {
+		FTS_ERROR("ERROR: Can't convert to number %s", buf);
+		goto error_return;
+	}
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_proc_busy(1);
+#endif
+	if (num_read_chars == 2) {
+		g_rwreg_result.op = 0;
+		g_rwreg_result.reg = regaddr;
+		/*read register*/
+		regaddr = wmreg;
+		g_rwreg_result.result = fts_i2c_read_reg(client, regaddr,
+						&regvalue);
+		if (g_rwreg_result.result < 0) {
+			FTS_ERROR("Could not read the register(0x%02x)",
+						regaddr);
+		} else {
+			FTS_INFO("the register(0x%02x) is 0x%02x", regaddr,
+						regvalue);
+			g_rwreg_result.value = regvalue;
+			g_rwreg_result.result = 0;
+		}
+	} else {
+		regaddr = wmreg>>8;
+		regvalue = wmreg;
+
+		g_rwreg_result.op = 1;
+		g_rwreg_result.reg = regaddr;
+		g_rwreg_result.value = regvalue;
+		g_rwreg_result.result = fts_i2c_write_reg(client, regaddr,
+							regvalue);
+		if (g_rwreg_result.result < 0) {
+			FTS_ERROR("Could not write the register(0x%02x)",
+							regaddr);
+
+		} else {
+			FTS_INFO("Write 0x%02x to (0x%02x) successful",
+					regvalue, regaddr);
+			g_rwreg_result.result = 0;
+		}
+	}
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_proc_busy(0);
+#endif
+error_return:
+	mutex_unlock(&fts_input_dev->mutex);
+
+	return count;
+}
+/************************************************************************
+ * Name: fts_fwupdate_show
+ * Brief:  no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_fwupdate_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	/* place holder for future use */
+	return -EPERM;
+}
+
+/************************************************************************
+ * Name: fts_fwupdate_store
+ * Brief:  upgrade from *.i
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: char count
+ ***********************************************************************/
+static ssize_t fts_fwupdate_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	mutex_lock(&fts_input_dev->mutex);
+	fts_irq_disable();
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_switch(DISABLE);
+#endif
+	if (fts_updatefun_curr.upgrade_with_app_i_file)
+		fts_updatefun_curr.upgrade_with_app_i_file(client);
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_switch(ENABLE);
+#endif
+	fts_irq_enable();
+	mutex_unlock(&fts_input_dev->mutex);
+
+	return count;
+}
+/************************************************************************
+ * Name: fts_fwupgradeapp_show
+ * Brief:  no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_fwupgradeapp_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	/* place holder for future use */
+	return -EPERM;
+}
+
+/************************************************************************
+ * Name: fts_fwupgradeapp_store
+ * Brief:  upgrade from app.bin
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: char count
+ ***********************************************************************/
+static ssize_t fts_fwupgradeapp_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	char fwname[FILE_NAME_LENGTH];
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	memset(fwname, 0, sizeof(fwname));
+	snprintf(fwname, FILE_NAME_LENGTH,  "%s", buf);
+	fwname[count-1] = '\0';
+
+	mutex_lock(&fts_input_dev->mutex);
+	fts_irq_disable();
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_switch(DISABLE);
+#endif
+	if (fts_updatefun_curr.upgrade_with_app_bin_file)
+		fts_updatefun_curr.upgrade_with_app_bin_file(client, fwname);
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_switch(ENABLE);
+#endif
+	fts_irq_enable();
+	mutex_unlock(&fts_input_dev->mutex);
+
+	return count;
+}
+/************************************************************************
+ * Name: fts_driverversion_show
+ * Brief:  no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_driverversion_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	int count;
+
+	mutex_lock(&fts_input_dev->mutex);
+
+	count = snprintf(buf, PAGE_SIZE, FTS_DRIVER_VERSION "\n");
+
+	mutex_unlock(&fts_input_dev->mutex);
+
+	return count;
+}
+/************************************************************************
+ * Name: fts_driverversion_store
+ * Brief:  no
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_driverversion_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	/* place holder for future use */
+	return -EPERM;
+}
+
+#if FTS_ESDCHECK_EN
+/************************************************************************
+ * Name: fts_esdcheck_store
+ * Brief:  no
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_esdcheck_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	mutex_lock(&fts_input_dev->mutex);
+
+	if (FTS_SYSFS_ECHO_ON(buf)) {
+		FTS_DEBUG("enable esdcheck");
+		fts_esdcheck_switch(ENABLE);
+	} else if (FTS_SYSFS_ECHO_OFF(buf)) {
+		FTS_DEBUG("disable esdcheck");
+		fts_esdcheck_switch(DISABLE);
+	}
+
+	mutex_unlock(&fts_input_dev->mutex);
+
+	return -EPERM;
+}
+
+/************************************************************************
+ * Name: fts_esdcheck_show
+ * Brief:  no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_esdcheck_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int count;
+
+	mutex_lock(&fts_input_dev->mutex);
+
+	count = snprintf(buf, PAGE_SIZE, "Esd check: %s\n",
+			fts_esdcheck_get_status() ? "On" : "Off");
+
+	mutex_unlock(&fts_input_dev->mutex);
+
+	return count;
+}
+#endif
+/************************************************************************
+ * Name: fts_module_config_show
+ * Brief:  no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_module_config_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int count = 0;
+
+	mutex_lock(&fts_input_dev->mutex);
+
+	count += snprintf(buf, PAGE_SIZE, "FTS_CHIP_TYPE: \t\t\t%04X\n",
+				FTS_CHIP_TYPE);
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_DEBUG_EN: \t\t\t%s\n",
+				FTS_DEBUG_EN ? "ON" : "OFF");
+#if defined(FTS_MT_PROTOCOL_B_EN)
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_MT_PROTOCOL_B_EN: \t\t%s\n",
+				FTS_MT_PROTOCOL_B_EN ? "ON" : "OFF");
+#endif
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_GESTURE_EN: \t\t%s\n",
+				FTS_GESTURE_EN ? "ON" : "OFF");
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_ESDCHECK_EN: \t\t%s\n",
+				FTS_ESDCHECK_EN ? "ON" : "OFF");
+#if defined(FTS_PSENSOR_EN)
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_PSENSOR_EN: \t\t%s\n",
+				FTS_PSENSOR_EN ? "ON" : "OFF");
+#endif
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_GLOVE_EN: \t\t\t%s\n",
+				FTS_GLOVE_EN ? "ON" : "OFF");
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_COVER_EN: \t\t%s\n",
+				FTS_COVER_EN ? "ON" : "OFF");
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_CHARGER_EN: \t\t\t%s\n",
+				FTS_CHARGER_EN ? "ON" : "OFF");
+
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_REPORT_PRESSURE_EN: \t\t%s\n",
+				FTS_REPORT_PRESSURE_EN ? "ON" : "OFF");
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_FORCE_TOUCH_EN: \t\t%s\n",
+				FTS_FORCE_TOUCH_EN ? "ON" : "OFF");
+
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_TEST_EN: \t\t\t%s\n",
+				FTS_TEST_EN ? "ON" : "OFF");
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_APK_NODE_EN: \t\t%s\n",
+				FTS_APK_NODE_EN ? "ON" : "OFF");
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_POWER_SOURCE_CUST_EN: \t%s\n",
+				FTS_POWER_SOURCE_CUST_EN ? "ON" : "OFF");
+	count += snprintf(buf+count, PAGE_SIZE - count,
+				"FTS_AUTO_UPGRADE_EN: \t\t%s\n",
+				FTS_AUTO_UPGRADE_EN ? "ON" : "OFF");
+
+	mutex_unlock(&fts_input_dev->mutex);
+
+	return count;
+}
+/************************************************************************
+ * Name: fts_module_config_store
+ * Brief:  no
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_module_config_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	/* place holder for future use */
+	return -EPERM;
+}
+
+/************************************************************************
+ * Name: fts_show_log_show
+ * Brief:  no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_show_log_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int count;
+
+	mutex_lock(&fts_input_dev->mutex);
+
+	count = snprintf(buf, PAGE_SIZE,
+			"Log: %s\n", g_show_log ? "On" : "Off");
+
+	mutex_unlock(&fts_input_dev->mutex);
+
+	return count;
+}
+/************************************************************************
+ * Name: fts_show_log_store
+ * Brief:  no
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_show_log_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	/* place holder for future use */
+
+	mutex_lock(&fts_input_dev->mutex);
+
+	if (FTS_SYSFS_ECHO_ON(buf)) {
+		FTS_DEBUG("enable show log info/error");
+		g_show_log = 1;
+	} else if (FTS_SYSFS_ECHO_OFF(buf)) {
+		FTS_DEBUG("disable show log info/error");
+		g_show_log = 0;
+	}
+
+	mutex_unlock(&fts_input_dev->mutex);
+	return count;
+}
+/************************************************************************
+ * Name: fts_dumpreg_store
+ * Brief:  no
+ * Input: device, device attribute, char buf, char count
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_dumpreg_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	/* place holder for future use */
+	return -EPERM;
+}
+
+/************************************************************************
+ * Name: fts_dumpreg_show
+ * Brief:  no
+ * Input: device, device attribute, char buf
+ * Output: no
+ * Return: EPERM
+ ***********************************************************************/
+static ssize_t fts_dumpreg_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	char tmp[256];
+	int count = 0;
+	u8 regvalue = 0;
+	struct i2c_client *client;
+
+	mutex_lock(&fts_input_dev->mutex);
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_proc_busy(1);
+#endif
+	client = container_of(dev, struct i2c_client, dev);
+	/* power mode 0:active 1:monitor 3:sleep */
+	fts_i2c_read_reg(client, FTS_REG_POWER_MODE, &regvalue);
+	count += snprintf(tmp + count, PAGE_SIZE - count,
+			"Power Mode:0x%02x\n", regvalue);
+
+	/* FWver */
+	fts_i2c_read_reg(client, FTS_REG_FW_VER, &regvalue);
+	count += snprintf(tmp + count, PAGE_SIZE - count,
+				"FW Ver:0x%02x\n", regvalue);
+
+	/* Vendor ID */
+	fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &regvalue);
+	count += snprintf(tmp + count, PAGE_SIZE - count,
+				"Vendor ID:0x%02x\n", regvalue);
+
+	/* LCD Busy number */
+	fts_i2c_read_reg(client, FTS_REG_LCD_BUSY_NUM, &regvalue);
+	count += snprintf(tmp + count, PAGE_SIZE - count,
+				"LCD Busy Number:0x%02x\n", regvalue);
+
+	/*  1 Gesture mode,0 Normal mode */
+	fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &regvalue);
+	count += snprintf(tmp + count, PAGE_SIZE - count,
+				"Gesture Mode:0x%02x\n", regvalue);
+
+	/*  3 charge in */
+	fts_i2c_read_reg(client, FTS_REG_CHARGER_MODE_EN, &regvalue);
+	count += snprintf(tmp + count, PAGE_SIZE - count,
+				"charge stat:0x%02x\n", regvalue);
+
+	/* Interrupt counter */
+	fts_i2c_read_reg(client, FTS_REG_INT_CNT, &regvalue);
+	count += snprintf(tmp + count, PAGE_SIZE - count,
+				"INT count:0x%02x\n", regvalue);
+
+	/* Flow work counter */
+	fts_i2c_read_reg(client, FTS_REG_FLOW_WORK_CNT, &regvalue);
+	count += snprintf(tmp + count, PAGE_SIZE - count,
+				"ESD count:0x%02x\n", regvalue);
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_proc_busy(0);
+#endif
+	memcpy(buf, tmp, count);
+	mutex_unlock(&fts_input_dev->mutex);
+	return count;
+}
+
+/****************************************/
+/* sysfs */
+/* get the fw version
+ *   example:cat fw_version
+ */
+static DEVICE_ATTR(fts_fw_version, 0644,
+		fts_tpfwver_show, fts_tpfwver_store);
+
+/* upgrade from *.i
+ *   example: echo 1 > fw_update
+ */
+static DEVICE_ATTR(fts_fw_update, 0644,
+		fts_fwupdate_show, fts_fwupdate_store);
+
+/* read and write register
+ *   read example: echo 88 > rw_reg ---read register 0x88
+ *   write example:echo 8807 > rw_reg ---write 0x07 into register 0x88
+ *
+ *   note:the number of input must be 2 or 4.if it not enough,
+ *	 please fill in the 0.
+ */
+static DEVICE_ATTR(fts_rw_reg, 0644,
+		fts_tprwreg_show, fts_tprwreg_store);
+
+/*  upgrade from app.bin
+ *	example:echo "*_app.bin" > upgrade_app
+ */
+static DEVICE_ATTR(fts_upgrade_app, 0644,
+		fts_fwupgradeapp_show, fts_fwupgradeapp_store);
+static DEVICE_ATTR(fts_driver_version, 0644,
+		fts_driverversion_show, fts_driverversion_store);
+static DEVICE_ATTR(fts_dump_reg, 0644,
+		fts_dumpreg_show, fts_dumpreg_store);
+static DEVICE_ATTR(fts_show_log, 0644,
+		fts_show_log_show, fts_show_log_store);
+static DEVICE_ATTR(fts_module_config, 0644,
+		fts_module_config_show, fts_module_config_store);
+static DEVICE_ATTR(fts_hw_reset, 0644,
+		fts_hw_reset_show, fts_hw_reset_store);
+static DEVICE_ATTR(fts_irq, 0644,
+		fts_irq_show, fts_irq_store);
+
+#if FTS_ESDCHECK_EN
+static DEVICE_ATTR(fts_esd_check, 0644,
+		fts_esdcheck_show, fts_esdcheck_store);
+#endif
+
+/* add your attr in here*/
+static struct attribute *fts_attributes[] = {
+	&dev_attr_fts_fw_version.attr,
+	&dev_attr_fts_fw_update.attr,
+	&dev_attr_fts_rw_reg.attr,
+	&dev_attr_fts_dump_reg.attr,
+	&dev_attr_fts_upgrade_app.attr,
+	&dev_attr_fts_driver_version.attr,
+	&dev_attr_fts_show_log.attr,
+	&dev_attr_fts_module_config.attr,
+	&dev_attr_fts_hw_reset.attr,
+	&dev_attr_fts_irq.attr,
+#if FTS_ESDCHECK_EN
+	&dev_attr_fts_esd_check.attr,
+#endif
+	NULL
+};
+
+static struct attribute_group fts_attribute_group = {
+	.attrs = fts_attributes
+};
+
+/************************************************************************
+ * Name: fts_create_sysfs
+ * Brief:  create sysfs for debug
+ * Input: i2c info
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+int fts_create_sysfs(struct i2c_client *client)
+{
+	int err;
+
+	err = sysfs_create_group(&client->dev.kobj, &fts_attribute_group);
+	if (err != 0) {
+		FTS_ERROR("[EX]: sysfs_create_group() failed!!");
+		sysfs_remove_group(&client->dev.kobj, &fts_attribute_group);
+		return -EIO;
+	}
+
+	FTS_INFO("[EX]: sysfs_create_group() succeeded!!");
+
+	return err;
+}
+/************************************************************************
+ * Name: fts_remove_sysfs
+ * Brief:  remove sys
+ * Input: i2c info
+ * Output: no
+ * Return: no
+ ***********************************************************************/
+int fts_remove_sysfs(struct i2c_client *client)
+{
+	sysfs_remove_group(&client->dev.kobj, &fts_attribute_group);
+	return 0;
+}
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_ex_mode.c b/drivers/input/touchscreen/focaltech_touch/focaltech_ex_mode.c
new file mode 100644
index 0000000..6e007f6
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_ex_mode.c
@@ -0,0 +1,347 @@
+/*
+ *
+ * FocalTech ftxxxx TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_ex_mode.c
+ *
+ *    Author: Liu WeiGuang
+ *
+ *   Created: 2016-08-31
+ *
+ *  Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+/*****************************************************************************
+ * 2.Private constant and macro definitions using #define
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 3.Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+struct fts_mode_flag {
+	int  fts_glove_mode_flag;
+	int  fts_cover_mode_flag;
+	int  fts_charger_mode_flag;
+};
+
+static struct fts_mode_flag g_fts_mode_flag;
+
+/*****************************************************************************
+ * 4.Static variables
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 5.Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 6.Static function prototypes
+ *****************************************************************************/
+
+#if FTS_GLOVE_EN
+static ssize_t fts_touch_glove_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "Glove: %s\n",
+			g_fts_mode_flag.fts_glove_mode_flag ? "On" : "Off");
+}
+
+static ssize_t fts_touch_glove_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret;
+
+	if (FTS_SYSFS_ECHO_ON(buf)) {
+		if (!g_fts_mode_flag.fts_glove_mode_flag) {
+			FTS_INFO("[Mode]enter glove mode");
+			ret = fts_enter_glove_mode(fts_i2c_client, true);
+			if (ret >= 0)
+				g_fts_mode_flag.fts_glove_mode_flag = true;
+		}
+	} else if (FTS_SYSFS_ECHO_OFF(buf)) {
+		if (g_fts_mode_flag.fts_glove_mode_flag) {
+			FTS_INFO("[Mode]exit glove mode");
+			ret = fts_enter_glove_mode(fts_i2c_client, false);
+			if (ret >= 0)
+				g_fts_mode_flag.fts_glove_mode_flag = false;
+		}
+	}
+
+	FTS_INFO("[Mode]glove mode status:  %d",
+			g_fts_mode_flag.fts_glove_mode_flag);
+	return count;
+}
+
+/************************************************************************
+ * Name: fts_enter_glove_mode
+ * Brief:  change glove mode
+ * Input:  glove mode
+ * Output: no
+ * Return: success >=0, otherwise failed
+ ***********************************************************************/
+int fts_enter_glove_mode(struct i2c_client *client, int mode)
+{
+	int ret = 0;
+	static u8 buf_addr[2] = { 0 };
+	static u8 buf_value[2] = { 0 };
+
+	buf_addr[0] = FTS_REG_GLOVE_MODE_EN; /* glove control */
+
+	if (mode)
+		buf_value[0] = 0x01;
+	else
+		buf_value[0] = 0x00;
+
+	ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]);
+	if (ret < 0)
+		FTS_ERROR("[Mode]fts_enter_glove_mode write value fail");
+
+	return ret;
+
+}
+
+/* read and write glove mode
+ *   read example: cat  fts_touch_glove_mode---read  glove mode
+ *   write example:echo 01 > fts_touch_glove_mode ---write glove mode to 01
+ *
+ */
+static DEVICE_ATTR(fts_glove_mode, 0644,
+		fts_touch_glove_show, fts_touch_glove_store);
+
+#endif
+
+#if FTS_COVER_EN
+static ssize_t fts_touch_cover_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "Cover: %s\n",
+			g_fts_mode_flag.fts_cover_mode_flag ? "On" : "Off");
+}
+
+static ssize_t fts_touch_cover_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret;
+
+	if (FTS_SYSFS_ECHO_ON(buf)) {
+		if (!g_fts_mode_flag.fts_cover_mode_flag) {
+			FTS_INFO("[Mode]enter cover mode");
+			ret = fts_enter_cover_mode(fts_i2c_client, true);
+			if (ret >= 0)
+				g_fts_mode_flag.fts_cover_mode_flag = true;
+		}
+	} else if (FTS_SYSFS_ECHO_OFF(buf)) {
+		if (g_fts_mode_flag.fts_cover_mode_flag) {
+			FTS_INFO("[Mode]exit cover mode");
+			ret = fts_enter_cover_mode(fts_i2c_client, false);
+			if (ret >= 0)
+				g_fts_mode_flag.fts_cover_mode_flag = false;
+		}
+	}
+
+	FTS_INFO("[Mode]cover mode status:  %d",
+			g_fts_mode_flag.fts_cover_mode_flag);
+	return count;
+}
+
+/************************************************************************
+ * Name: fts_enter_cover_mode
+ * Brief:  change cover mode
+ * Input:  cover mode
+ * Output: no
+ * Return: success >=0, otherwise failed
+ ***********************************************************************/
+int  fts_enter_cover_mode(struct i2c_client *client, int mode)
+{
+	int ret = 0;
+	static u8 buf_addr[2] = { 0 };
+	static u8 buf_value[2] = { 0 };
+
+	buf_addr[0] = FTS_REG_COVER_MODE_EN; /* cover control */
+
+	if (mode)
+		buf_value[0] = 0x01;
+	else
+		buf_value[0] = 0x00;
+
+	ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]);
+	if (ret < 0)
+		FTS_ERROR("[Mode] fts_enter_cover_mode write value fail\n");
+
+	return ret;
+
+}
+
+/* read and write cover mode
+ *   read example: cat  fts_touch_cover_mode---read  cover mode
+ *   write example:echo 01 > fts_touch_cover_mode ---write cover mode to 01
+ *
+ */
+static DEVICE_ATTR(fts_cover_mode, 0644,
+		fts_touch_cover_show, fts_touch_cover_store);
+
+#endif
+
+#if FTS_CHARGER_EN
+static ssize_t fts_touch_charger_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "Charger: %s\n",
+			g_fts_mode_flag.fts_charger_mode_flag ? "On" : "Off");
+}
+
+static ssize_t fts_touch_charger_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret;
+
+	if (FTS_SYSFS_ECHO_ON(buf)) {
+		if (!g_fts_mode_flag.fts_charger_mode_flag) {
+			FTS_INFO("[Mode]enter charger mode");
+			ret = fts_enter_charger_mode(fts_i2c_client, true);
+			if (ret >= 0)
+				g_fts_mode_flag.fts_charger_mode_flag = true;
+		}
+	} else if (FTS_SYSFS_ECHO_OFF(buf)) {
+		if (g_fts_mode_flag.fts_charger_mode_flag) {
+			FTS_INFO("[Mode]exit charger mode");
+			ret = fts_enter_charger_mode(fts_i2c_client, false);
+			if (ret >= 0)
+				g_fts_mode_flag.fts_charger_mode_flag = false;
+		}
+	}
+
+	FTS_INFO("[Mode]charger mode status: %d",
+			g_fts_mode_flag.fts_charger_mode_flag);
+	return count;
+}
+
+/************************************************************************
+ * Name: fts_enter_charger_mode
+ * Brief:  change charger mode
+ * Input:  charger mode
+ * Output: no
+ * Return: success >=0, otherwise failed
+ ***********************************************************************/
+int  fts_enter_charger_mode(struct i2c_client *client, int mode)
+{
+	int ret = 0;
+	static u8 buf_addr[2] = { 0 };
+	static u8 buf_value[2] = { 0 };
+
+	buf_addr[0] = FTS_REG_CHARGER_MODE_EN; /* charger control */
+
+	if (mode)
+		buf_value[0] = 0x01;
+	else
+		buf_value[0] = 0x00;
+
+	ret = fts_i2c_write_reg(client, buf_addr[0], buf_value[0]);
+	if (ret < 0)
+		FTS_DEBUG("[Mode]fts_enter_charger_mode write value fail");
+
+	return ret;
+
+}
+
+/* read and write charger mode
+ *   read example: cat  fts_touch_charger_mode---read  charger mode
+ *   write example:echo 01 > fts_touch_charger_mode ---write charger mode to 01
+ *
+ */
+static DEVICE_ATTR(fts_charger_mode, 0644,
+		fts_touch_charger_show, fts_touch_charger_store);
+
+#endif
+
+static struct attribute *fts_touch_mode_attrs[] = {
+#if FTS_GLOVE_EN
+	&dev_attr_fts_glove_mode.attr,
+#endif
+
+#if FTS_COVER_EN
+	&dev_attr_fts_cover_mode.attr,
+#endif
+
+#if FTS_CHARGER_EN
+	&dev_attr_fts_charger_mode.attr,
+#endif
+
+	NULL,
+};
+
+static struct attribute_group fts_touch_mode_group = {
+	.attrs = fts_touch_mode_attrs,
+};
+
+int fts_ex_mode_init(struct i2c_client *client)
+{
+	int err = 0;
+
+	g_fts_mode_flag.fts_glove_mode_flag = false;
+	g_fts_mode_flag.fts_cover_mode_flag = false;
+	g_fts_mode_flag.fts_charger_mode_flag = false;
+
+	err = sysfs_create_group(&client->dev.kobj, &fts_touch_mode_group);
+	if (err != 0) {
+		FTS_ERROR("[Mode]create sysfs failed.");
+		sysfs_remove_group(&client->dev.kobj, &fts_touch_mode_group);
+		return -EIO;
+	}
+
+	FTS_DEBUG("[Mode]create sysfs succeeded");
+
+	return err;
+
+}
+
+int fts_ex_mode_exit(struct i2c_client *client)
+{
+	sysfs_remove_group(&client->dev.kobj, &fts_touch_mode_group);
+	return 0;
+}
+
+int fts_ex_mode_recovery(struct i2c_client *client)
+{
+	int ret = 0;
+#if FTS_GLOVE_EN
+	if (g_fts_mode_flag.fts_glove_mode_flag)
+		ret = fts_enter_glove_mode(client, true);
+#endif
+
+#if FTS_COVER_EN
+	if (g_fts_mode_flag.fts_cover_mode_flag)
+		ret = fts_enter_cover_mode(client, true);
+#endif
+
+#if FTS_CHARGER_EN
+	if (g_fts_mode_flag.fts_charger_mode_flag)
+		ret = fts_enter_charger_mode(client, true);
+#endif
+
+	return ret;
+}
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash.c
new file mode 100644
index 0000000..ed2148f
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash.c
@@ -0,0 +1,665 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_flash.c
+ *
+ * Author:    fupeipei
+ *
+ * Created:    2016-08-08
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+#include "focaltech_flash.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+struct ft_chip_t chip_types;
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+/* Upgrade FW/PRAMBOOT/LCD CFG */
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+u8 CTPM_FW[] = {
+#include FTS_UPGRADE_FW_APP
+};
+#endif
+
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+u8 CTPM_FW2[] = {
+#include FTS_UPGRADE_FW2_APP
+};
+#endif
+
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+u8 CTPM_FW3[] = {
+#include FTS_UPGRADE_FW3_APP
+};
+#endif
+
+u8 aucFW_PRAM_BOOT[] = {
+#ifdef FTS_UPGRADE_PRAMBOOT
+#include FTS_UPGRADE_PRAMBOOT
+#endif
+};
+
+#if (FTS_CHIP_TYPE == _FT8006)
+u8 CTPM_LCD_CFG[] = {
+#ifdef FTS_UPGRADE_LCD_CFG
+#include FTS_UPGRADE_LCD_CFG
+#endif
+};
+#endif
+
+struct fts_upgrade_fun  fts_updatefun_curr;
+struct workqueue_struct *touch_wq;
+struct work_struct fw_update_work;
+u8 *g_fw_file;
+int g_fw_len;
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+
+/************************************************************************
+ * Name: fts_ctpm_upgrade_delay
+ * Brief: 0
+ * Input: 0
+ * Output: 0
+ * Return: 0
+ ***********************************************************************/
+void fts_ctpm_upgrade_delay(u32 i)
+{
+	do {
+		i--;
+	} while (i > 0);
+}
+
+/************************************************************************
+ * Name: fts_ctpm_i2c_hid2std
+ * Brief:  HID to I2C
+ * Input: i2c info
+ * Output: no
+ * Return: fail =0
+ ***********************************************************************/
+int fts_ctpm_i2c_hid2std(struct i2c_client *client)
+{
+#if (FTS_CHIP_IDC)
+	return 0;
+#else
+	u8 buf[5] = {0};
+	int bRet = 0;
+
+	buf[0] = 0xeb;
+	buf[1] = 0xaa;
+	buf[2] = 0x09;
+	bRet = fts_i2c_write(client, buf, 3);
+	msleep(20);
+	buf[0] = buf[1] = buf[2] = 0;
+	fts_i2c_read(client, buf, 0, buf, 3);
+
+	if ((buf[0] == 0xeb) && (buf[1] == 0xaa) && (buf[2] == 0x08)) {
+		FTS_DEBUG("hidi2c change to stdi2c successful!!");
+		bRet = 1;
+	} else {
+		FTS_ERROR("hidi2c change to stdi2c error!!");
+		bRet = 0;
+	}
+
+	return bRet;
+#endif
+}
+
+/************************************************************************
+ * Name: fts_get_chip_types
+ * Brief: get correct chip information
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static void fts_get_chip_types(void)
+{
+	struct ft_chip_t ctype[] = FTS_CHIP_TYPE_MAPPING;
+	int ic_type = 0;
+
+	if (sizeof(ctype) != sizeof(struct ft_chip_t)) /* only one array */
+		ic_type = IC_SERIALS - 1;
+
+	chip_types = ctype[ic_type];
+
+	FTS_INFO("CHIP TYPE ID = 0x%02x%02x",
+			chip_types.chip_idh, chip_types.chip_idl);
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_upgrade_array
+ * Brief: decide which ic
+ * Input: no
+ * Output: get ic info in fts_updateinfo_curr
+ * Return: no
+ ***********************************************************************/
+void fts_ctpm_get_upgrade_array(void)
+{
+
+	FTS_FUNC_ENTER();
+
+	fts_get_chip_types();
+
+	fts_ctpm_i2c_hid2std(fts_i2c_client);
+
+	/* Get functin pointer */
+	memcpy(&fts_updatefun_curr, &fts_updatefun,
+			sizeof(struct fts_upgrade_fun));
+
+	FTS_FUNC_EXIT();
+}
+
+/************************************************************************
+ * Name: fts_ctpm_rom_or_pram_reset
+ * Brief: RST CMD(07), reset to romboot(maybe->bootloader)
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+void fts_ctpm_rom_or_pram_reset(struct i2c_client *client)
+{
+	u8 rst_cmd = FTS_REG_RESET_FW;
+
+	FTS_INFO("[UPGRADE]******Reset to romboot/bootloader******");
+	fts_i2c_write(client, &rst_cmd, 1);
+	/* The delay can't be changed */
+	msleep(300);
+}
+
+/************************************************************************
+ * Name: fts_ctpm_auto_clb
+ * Brief:  auto calibration
+ * Input: i2c info
+ * Output: no
+ * Return: 0
+ ***********************************************************************/
+int fts_ctpm_auto_clb(struct i2c_client *client)
+{
+#if FTS_AUTO_CLB_EN
+	u8 uc_temp = 0x00;
+	u8 i = 0;
+
+	/*start auto CLB */
+	msleep(200);
+
+	fts_i2c_write_reg(client, 0, FTS_REG_WORKMODE_FACTORY_VALUE);
+	/*make sure already enter factory mode */
+	msleep(100);
+	/*write command to start calibration */
+	fts_i2c_write_reg(client, 2, 0x4);
+	msleep(300);
+	if ((chip_types.chip_idh == 0x11) || (chip_types.chip_idh == 0x12)
+		|| (chip_types.chip_idh == 0x13)
+		|| (chip_types.chip_idh == 0x14)) {
+		/* 5x36,5x36i */
+		for (i = 0; i < 100; i++) {
+			fts_i2c_read_reg(client, 0x02, &uc_temp);
+			if ((uc_temp == 0x02) ||
+				(uc_temp == 0xFF))
+				break;
+			msleep(20);
+		}
+	} else {
+		for (i = 0; i < 100; i++) {
+			fts_i2c_read_reg(client, 0, &uc_temp);
+			if (((uc_temp&0x70)>>4) == 0x0)
+				break;
+			msleep(20);
+		}
+	}
+
+	fts_i2c_write_reg(client, 0, 0x40);
+	msleep(200);
+	fts_i2c_write_reg(client, 2, 0x5);
+	msleep(300);
+	fts_i2c_write_reg(client, 0, FTS_REG_WORKMODE_WORK_VALUE);
+	msleep(300);
+#endif
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_getsize
+ * Brief: Get different file's size
+ * Input:
+ * Output:
+ * Return: file's size
+ ***********************************************************************/
+u32 fts_getsize(u8 fw_type)
+{
+	int fw_len = 0;
+
+#if FTS_CHIP_IDC
+	if (fw_type == PRAMBOOT_SIZE)
+		fw_len = sizeof(aucFW_PRAM_BOOT);
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+	else if (fw_type == FW_SIZE)
+		fw_len = sizeof(CTPM_FW);
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+	else if (fw_type == FW2_SIZE)
+		fw_len = sizeof(CTPM_FW2);
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+	else if (fw_type == FW3_SIZE)
+		fw_len = sizeof(CTPM_FW3);
+#endif
+#if (FTS_CHIP_TYPE == _FT8006)
+	else if (fw_type == LCD_CFG_SIZE)
+		fw_len = sizeof(CTPM_LCD_CFG);
+#endif
+
+	return fw_len;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_pram_or_rom_id
+ * Brief: 0
+ * Input: 0
+ * Output: 0
+ * Return: 0
+ ***********************************************************************/
+enum FW_STATUS fts_ctpm_get_pram_or_rom_id(struct i2c_client *client)
+{
+	u8 buf[4];
+	u8 reg_val[2] = {0};
+	enum FW_STATUS inRomBoot = FTS_RUN_IN_ERROR;
+
+	fts_ctpm_i2c_hid2std(client);
+
+	/*Enter upgrade mode*/
+	/*send 0x55 in time windows*/
+	buf[0] = FTS_UPGRADE_55;
+	buf[1] = FTS_UPGRADE_AA;
+	fts_i2c_write(client, buf, 2);
+
+	msleep(20);
+
+	buf[0] = 0x90;
+	buf[1] = buf[2] = buf[3] = 0x00;
+	fts_i2c_read(client, buf, 4, reg_val, 2);
+
+	FTS_DEBUG("[UPGRADE] Read ROM/PRAM/Bootloader id:0x%02x%02x",
+				reg_val[0], reg_val[1]);
+	if ((reg_val[0] == 0x00) || (reg_val[0] == 0xFF))
+		inRomBoot = FTS_RUN_IN_ERROR;
+	else if (reg_val[0] == chip_types.pramboot_idh
+			&& reg_val[1] == chip_types.pramboot_idl)
+		inRomBoot = FTS_RUN_IN_PRAM;
+	else if (reg_val[0] == chip_types.rom_idh
+			&& reg_val[1] == chip_types.rom_idl)
+		inRomBoot = FTS_RUN_IN_ROM;
+	else if (reg_val[0] == chip_types.bootloader_idh
+			&& reg_val[1] == chip_types.bootloader_idl)
+		inRomBoot = FTS_RUN_IN_BOOTLOADER;
+
+	return inRomBoot;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_file
+ * Brief: get app file by Vendor ID
+ * Input:
+ * Output:
+ * Return: <0: vendor id not correct,not upgrade
+ ***********************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid)
+{
+	int ret;
+
+	if (fts_updatefun_curr.get_i_file)
+		ret = fts_updatefun_curr.get_i_file(client, fw_valid);
+	else
+		ret = -EIO;
+
+	return ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_ver
+ * Brief:  get app file version
+ * Input:
+ * Output:
+ * Return: fw version
+ ***********************************************************************/
+int fts_ctpm_get_app_ver(void)
+{
+	int i_ret = 0;
+
+	if (fts_updatefun_curr.get_app_i_file_ver)
+		i_ret = fts_updatefun_curr.get_app_i_file_ver();
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade
+ * Brief:  fw upgrade entry funciotn
+ * Input:
+ * Output:
+ * Return: 0  - upgrade successfully
+ *		 <0 - upgrade failed
+ ***********************************************************************/
+int fts_ctpm_fw_upgrade(struct i2c_client *client)
+{
+	int i_ret = 0;
+
+	if (fts_updatefun_curr.upgrade_with_app_i_file)
+		i_ret = fts_updatefun_curr.upgrade_with_app_i_file(client);
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade
+ * Brief:  fw upgrade entry funciotn
+ * Input:
+ * Output:
+ * Return: 0  - upgrade successfully
+ *		 <0 - upgrade failed
+ ***********************************************************************/
+int fts_ctpm_lcd_cfg_upgrade(struct i2c_client *client)
+{
+	int i_ret = 0;
+
+	if (fts_updatefun_curr.upgrade_with_lcd_cfg_i_file)
+		i_ret = fts_updatefun_curr.upgrade_with_lcd_cfg_i_file(client);
+
+	return i_ret;
+}
+
+#if (!(FTS_UPGRADE_STRESS_TEST))
+/************************************************************************
+ * Name: fts_ctpm_check_fw_status
+ * Brief: Check App is valid or not
+ * Input:
+ * Output:
+ * Return: -EIO - I2C communication error
+ *		 FTS_RUN_IN_APP - APP valid
+ *		 0 - APP invalid
+ ***********************************************************************/
+static int fts_ctpm_check_fw_status(struct i2c_client *client)
+{
+	u8 chip_id1 = 0;
+	u8 chip_id2 = 0;
+	int fw_status = FTS_RUN_IN_ERROR;
+	int i = 0;
+	int ret = 0;
+	int i2c_noack_retry = 0;
+
+	for (i = 0; i < 5; i++) {
+		ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID, &chip_id1);
+		if (ret < 0) {
+			i2c_noack_retry++;
+			continue;
+		}
+
+		ret = fts_i2c_read_reg(client, FTS_REG_CHIP_ID2, &chip_id2);
+		if (ret < 0) {
+			i2c_noack_retry++;
+			continue;
+		}
+
+		if ((chip_id1 == chip_types.chip_idh)
+#if FTS_CHIP_IDC
+			&& (chip_id2 == chip_types.chip_idl)
+#endif
+		   ) {
+			fw_status = FTS_RUN_IN_APP;
+			break;
+		}
+	}
+
+	FTS_DEBUG("[UPGRADE]: chip_id = %02x%02x", chip_id1, chip_id2);
+	FTS_DEBUG("[UPGRADE]:chip_types.chip_idh = %02x%02x",
+				chip_types.chip_idh, chip_types.chip_idl);
+
+	/* I2C No ACK 5 times, then return -EIO */
+	if (i2c_noack_retry >= 5)
+		return -EIO;
+
+	/* I2C communication ok, but not get correct ID,
+	 * need check pram/rom/bootloader
+	 */
+	if (i >= 5)
+		fw_status = fts_ctpm_get_pram_or_rom_id(client);
+
+	return fw_status;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_check_fw_ver
+ * Brief: Check vendor id is valid or not
+ * Input:
+ * Output:
+ * Return: 1 - vendor id valid
+ *		 0 - vendor id invalid
+ ***********************************************************************/
+static int fts_ctpm_check_fw_ver(struct i2c_client *client)
+{
+	u8 uc_tp_fm_ver = 0;
+	u8 uc_host_fm_ver = 0;
+
+	fts_i2c_read_reg(client, FTS_REG_FW_VER, &uc_tp_fm_ver);
+	uc_host_fm_ver = fts_ctpm_get_app_ver();
+
+	FTS_DEBUG("[UPGRADE]: uc_tp_fm_ver = 0x%x, uc_host_fm_ver = 0x%x!!",
+			uc_tp_fm_ver, uc_host_fm_ver);
+	if (uc_tp_fm_ver < uc_host_fm_ver)
+		return 1;
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_check_need_upgrade
+ * Brief:
+ * Input:
+ * Output:
+ * Return: 1 - Need upgrade
+ *		 0 - No upgrade
+ ***********************************************************************/
+static int fts_ctpm_check_need_upgrade(struct i2c_client *client)
+{
+	int fw_status = 0;
+	int bUpgradeFlag = false;
+
+	FTS_FUNC_ENTER();
+
+	/* 1. veriry FW APP is valid or not */
+	fw_status = fts_ctpm_check_fw_status(client);
+	FTS_DEBUG("[UPGRADE]: fw_status = %d!!", fw_status);
+	if (fw_status < 0) {
+		/* I2C no ACK, return immediately */
+		FTS_ERROR("[UPGRADE]******I2C NO ACK,exit upgrade******");
+		return -EIO;
+	} else if (fw_status == FTS_RUN_IN_ERROR) {
+		FTS_ERROR("[UPGRADE]******IC Type Fail******");
+	} else if (fw_status == FTS_RUN_IN_APP) {
+		FTS_INFO("[UPGRADE]**********FW APP valid**********");
+
+		if (fts_ctpm_get_i_file(client, 1) != 0) {
+			FTS_DEBUG("[UPGRADE]***Get upgrade file(fw) fail***");
+			return -EIO;
+		}
+
+		if (fts_ctpm_check_fw_ver(client) == 1) {
+			FTS_DEBUG("[UPGRADE]******need upgrade fw******");
+			bUpgradeFlag = true;
+		} else {
+			FTS_DEBUG("[UPGRADE]****Don't need upgrade fw****");
+			bUpgradeFlag = false;
+		}
+	} else {
+		/* if app is invalid, reset to run ROM */
+		FTS_INFO("[UPGRADE]**********FW APP invalid**********");
+		fts_ctpm_rom_or_pram_reset(client);
+		if (fts_ctpm_get_i_file(client, 0) != 0) {
+			FTS_DEBUG("[UPGRADE]**Get upgrade file(flash) fail**");
+			fts_ctpm_rom_or_pram_reset(client);
+			return -EIO;
+		}
+		fts_ctpm_rom_or_pram_reset(client);
+		bUpgradeFlag = true;
+	}
+
+	FTS_FUNC_EXIT();
+
+	return bUpgradeFlag;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_auto_upgrade
+ * Brief:  auto upgrade
+ * Input:
+ * Output:
+ * Return: 0 - no upgrade
+ ***********************************************************************/
+int fts_ctpm_auto_upgrade(struct i2c_client *client)
+{
+	u8 uc_tp_fm_ver = 0;
+	int i_ret = 0;
+	int bUpgradeFlag = false;
+	u8 uc_upgrade_times = 0;
+
+	FTS_DEBUG("[UPGRADE]**********check upgrade need or not**********");
+	bUpgradeFlag = fts_ctpm_check_need_upgrade(client);
+	FTS_DEBUG("[UPGRADE]**********bUpgradeFlag = 0x%x**********",
+			bUpgradeFlag);
+
+	if (bUpgradeFlag <= 0) {
+		FTS_DEBUG("[UPGRADE]**********No Upgrade, exit**********");
+		return 0;
+	}
+
+	/* FW Upgrade */
+	do {
+		uc_upgrade_times++;
+		FTS_DEBUG("[UPGRADE]*********star upgrade(%d)*************",
+						uc_upgrade_times);
+
+		i_ret = fts_ctpm_fw_upgrade(client);
+		if (i_ret == 0) {
+			/* upgrade success */
+			fts_i2c_read_reg(client, FTS_REG_FW_VER, &uc_tp_fm_ver);
+			FTS_DEBUG("[UPGRADE] Success upgrade to ver 0x%x",
+					uc_tp_fm_ver);
+
+			fts_ctpm_auto_clb(client);
+			break;
+		}
+
+		/* upgrade fail, reset to run ROM BOOT..
+		 * if app in flash is ok, TP will work success
+		 */
+		FTS_ERROR("[UPGRADE]*****upgrade fail, reset now*****");
+		fts_ctpm_rom_or_pram_reset(client);
+
+		/* if upgrade fail, upgrade again. then return */
+	} while (uc_upgrade_times < 2);
+
+	return i_ret;
+}
+#endif
+
+#if FTS_AUTO_UPGRADE_EN
+static void fts_ctpm_update_work_func(struct work_struct *work)
+{
+	int i_ret = 0;
+
+	FTS_DEBUG("[UPGRADE]*****FTS enter upgrade*******");
+	fts_irq_disable();
+
+	/* esd check */
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_switch(DISABLE);
+#endif
+
+	i_ret = fts_ctpm_auto_upgrade(fts_i2c_client);
+	if (i_ret < 0)
+		FTS_ERROR("[UPGRADE]**********TP FW upgrade failed**********");
+
+#if FTS_AUTO_UPGRADE_FOR_LCD_CFG_EN
+	msleep(2000);
+
+	/* lcd_cfg upgrade */
+	i_ret = fts_ctpm_lcd_cfg_upgrade(fts_i2c_client);
+	if (i_ret < 0)
+		FTS_ERROR("[UPGRADE]**********LCD cfg upgrade failed*********");
+#endif
+
+#if FTS_ESDCHECK_EN
+	fts_esdcheck_switch(ENABLE);
+#endif
+	fts_irq_enable();
+
+	FTS_DEBUG("[UPGRADE]**********FTS exit upgrade*************");
+}
+
+/*****************************************************************************
+ *  Name: fts_ctpm_upgrade_init
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+void fts_ctpm_upgrade_init(void)
+{
+	FTS_FUNC_ENTER();
+
+	touch_wq = create_singlethread_workqueue("touch_wq");
+	if (touch_wq) {
+		INIT_WORK(&fw_update_work, fts_ctpm_update_work_func);
+		queue_work(touch_wq, &fw_update_work);
+	} else
+		FTS_ERROR("[UPGRADE]create_singlethread_workqueue failed\n");
+
+	FTS_FUNC_EXIT();
+}
+
+/*****************************************************************************
+ *  Name: fts_ctpm_upgrade_exit
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+void fts_ctpm_upgrade_exit(void)
+{
+	FTS_FUNC_ENTER();
+	destroy_workqueue(touch_wq);
+	FTS_FUNC_EXIT();
+}
+
+#endif  /* #if FTS_AUTO_UPGRADE_EN */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash.h b/drivers/input/touchscreen/focaltech_touch/focaltech_flash.h
new file mode 100644
index 0000000..d1acff2
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash.h
@@ -0,0 +1,137 @@
+/************************************************************************
+ * Copyright (C) 2010-2017, Focaltech Systems (R)£¬All Rights Reserved.
+ *
+ * File Name: focaltech_flash.h
+ *
+ *    Author: fupeipei
+ *
+ *   Created: 2016-08-07
+ *
+ *  Abstract:
+ *
+ ************************************************************************/
+#ifndef __LINUX_FOCALTECH_FLASH_H__
+#define __LINUX_FOCALTECH_FLASH_H__
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "focaltech_flash/focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+#define FTS_REG_ECC                                  0xCC
+#define FTS_RST_CMD_REG2                             0xBC
+#define FTS_READ_ID_REG                              0x90
+#define FTS_ERASE_APP_REG                            0x61
+#define FTS_ERASE_PARAMS_CMD                         0x63
+#define FTS_FW_WRITE_CMD                             0xBF
+#define FTS_REG_RESET_FW                             0x07
+#define FTS_RST_CMD_REG1                             0xFC
+#define LEN_FLASH_ECC_MAX                            0xFFFE
+
+#define FTS_PACKET_LENGTH                            128
+#define FTS_SETTING_BUF_LEN                          128
+
+#define FTS_UPGRADE_LOOP                             30
+#define AUTO_CLB_NEED                                1
+#define AUTO_CLB_NONEED                              0
+#define FTS_UPGRADE_AA                               0xAA
+#define FTS_UPGRADE_55                               0x55
+#define FTXXXX_INI_FILEPATH_CONFIG                   "/sdcard/"
+
+enum FW_STATUS {
+	FTS_RUN_IN_ERROR,
+	FTS_RUN_IN_APP,
+	FTS_RUN_IN_ROM,
+	FTS_RUN_IN_PRAM,
+	FTS_RUN_IN_BOOTLOADER
+};
+
+enum FILE_SIZE_TYPE {
+	FW_SIZE,
+	FW2_SIZE,
+	FW3_SIZE,
+	PRAMBOOT_SIZE,
+	LCD_CFG_SIZE
+};
+
+/* pramboot */
+#define FTS_PRAMBOOT_8716   "include/pramboot/FT8716_Pramboot_V0.5_20160723.i"
+#define FTS_PRAMBOOT_E716   "include/pramboot/FT8716_Pramboot_V0.5_20160723.i"
+#define FTS_PRAMBOOT_8736   "include/pramboot/FT8736_Pramboot_V0.4_20160627.i"
+#define FTS_PRAMBOOT_8607   "include/pramboot/FT8607_Pramboot_V0.3_20160727.i"
+#define FTS_PRAMBOOT_8606   "include/pramboot/FT8606_Pramboot_V0.7_20150507.i"
+
+/* ic types */
+#if (FTS_CHIP_TYPE == _FT8716)
+#define FTS_UPGRADE_PRAMBOOT    FTS_PRAMBOOT_8716
+#elif (FTS_CHIP_TYPE == _FTE716)
+#define FTS_UPGRADE_PRAMBOOT    FTS_PRAMBOOT_E716
+#elif (FTS_CHIP_TYPE == _FT8736)
+#define FTS_UPGRADE_PRAMBOOT    FTS_PRAMBOOT_8736
+#elif (FTS_CHIP_TYPE == _FT8607)
+#define FTS_UPGRADE_PRAMBOOT    FTS_PRAMBOOT_8607
+#elif (FTS_CHIP_TYPE == _FT8606)
+#define FTS_UPGRADE_PRAMBOOT    FTS_PRAMBOOT_8606
+#endif
+
+/* remove pramboot */
+#undef FTS_UPGRADE_PRAMBOOT
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+/* IC info */
+
+struct fts_upgrade_fun {
+	int (*get_i_file)(struct i2c_client *, int);
+	int (*get_app_bin_file_ver)(struct i2c_client *, char *);
+	int (*get_app_i_file_ver)(void);
+	int (*upgrade_with_app_i_file)(struct i2c_client *);
+	int (*upgrade_with_app_bin_file)(struct i2c_client *, char *);
+	int (*upgrade_with_lcd_cfg_i_file)(struct i2c_client *);
+	int (*upgrade_with_lcd_cfg_bin_file)(struct i2c_client *, char *);
+};
+extern struct fts_upgrade_fun fts_updatefun;
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+extern u8 CTPM_FW[];
+extern u8 CTPM_FW2[];
+extern u8 CTPM_FW3[];
+extern u8 aucFW_PRAM_BOOT[];
+extern u8 CTPM_LCD_CFG[];
+extern u8 *g_fw_file;
+extern int g_fw_len;
+extern struct fts_upgrade_fun  fts_updatefun_curr;
+extern struct ft_chip_t chip_types;
+
+#if FTS_AUTO_UPGRADE_EN
+extern struct workqueue_struct *touch_wq;
+extern struct work_struct fw_update_work;
+#endif
+
+void fts_ctpm_upgrade_init(void);
+void fts_ctpm_upgrade_exit(void);
+void fts_ctpm_upgrade_delay(u32 i);
+void fts_ctpm_get_upgrade_array(void);
+int fts_ctpm_auto_upgrade(struct i2c_client *client);
+int fts_fw_upgrade(struct device *dev, bool force);
+int fts_ctpm_auto_clb(struct i2c_client *client);
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+u32 fts_getsize(u8 fw_type);
+int fts_ctpm_i2c_hid2std(struct i2c_client *client);
+void fts_ctpm_rom_or_pram_reset(struct i2c_client *client);
+enum FW_STATUS fts_ctpm_get_pram_or_rom_id(struct i2c_client *client);
+#endif
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/Makefile b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/Makefile
new file mode 100644
index 0000000..9b3a4bb
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/Makefile
@@ -0,0 +1,17 @@
+#
+# Makefile for the focaltech touchscreen drivers.
+#
+
+# Each configuration option enables a list of files.
+
+
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft5x46.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft5822.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft6336gu.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft8006.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft8606.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft8607.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft8716.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_ft8736.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_idc.o
+obj-$(CONFIG_TOUCHSCREEN_FTS) += focaltech_upgrade_test.o
\ No newline at end of file
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h
new file mode 100644
index 0000000..e3b00e5
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_common.h
@@ -0,0 +1,60 @@
+/************************************************************************
+ * Copyright (C) 2010-2017, Focaltech Systems (R)£¬All Rights Reserved.
+ *
+ * File Name: focaltech_upgrade_common.h
+ *
+ *    Author: fupeipei
+ *
+ *   Created: 2016-08-16
+ *
+ *  Abstract:
+ *
+ ************************************************************************/
+#ifndef __LINUX_FOCALTECH_UPGRADE_COMMON_H__
+#define __LINUX_FOCALTECH_UPGRADE_COMMON_H__
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_flash.h"
+
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+int fts_ctpm_erase_flash(struct i2c_client *client);
+int fts_ctpm_pramboot_ecc(struct i2c_client *client);
+bool fts_ctpm_check_run_state(struct i2c_client *client, int state);
+void fts_ctpm_start_pramboot(struct i2c_client *client);
+int fts_ctpm_start_fw_upgrade(struct i2c_client *client);
+bool fts_ctpm_check_in_pramboot(struct i2c_client *client);
+int fts_ctpm_upgrade_idc_init(struct i2c_client *client);
+int fts_ctpm_write_app_for_idc(struct i2c_client *client,
+			u32 length, u8 *readbuf);
+int fts_ctpm_upgrade_ecc(struct i2c_client *client, u32 startaddr, u32 length);
+int fts_ctpm_write_pramboot_for_idc(struct i2c_client *client,
+			u32 length, u8 *readbuf);
+int fts_writeflash(struct i2c_client *client, u32 writeaddr,
+			u32 length, u8 *readbuf, u32 cnt);
+bool fts_check_app_bin_valid_idc(u8 *pbt_buf);
+
+int fts_ctpm_get_app_ver(void);
+int fts_ctpm_fw_upgrade(struct i2c_client *client);
+int fts_ctpm_lcd_cfg_upgrade(struct i2c_client *client);
+
+#endif
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft5822.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft5822.c
new file mode 100644
index 0000000..2133c06
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft5822.c
@@ -0,0 +1,645 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft5822.c
+ *
+ * Author:    fupeipei
+ *
+ * Created:    2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (IC_SERIALS == 0x01)
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE           (60 * 1024)
+#define APP_FILE_MIN_SIZE           (8)
+#define APP_FILE_VER_MAPPING        (0x10A)
+#define APP_FILE_VENDORID_MAPPING   (0x108)
+#define APP_FILE_CHIPID_MAPPING     (0x11E)
+#define CONFIG_START_ADDR           (0xFFB0)
+#define CONFIG_VENDOR_ID_OFFSET     (0x4)
+#define CONFIG_PROJECT_ID_OFFSET    (0x20)
+#define CONFIG_VENDOR_ID_ADDR       (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR      (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ft5822_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ft5822_get_app_i_file_ver(void);
+static int fts_ft5822_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name);
+static int fts_ft5822_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ft5822_upgrade_with_app_bin_file(struct i2c_client *client,
+					char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+
+	.get_i_file = fts_ft5822_get_i_file,
+	.get_app_bin_file_ver = fts_ft5822_get_app_bin_file_ver,
+	.get_app_i_file_ver = fts_ft5822_get_app_i_file_ver,
+	.upgrade_with_app_i_file = fts_ft5822_upgrade_with_app_i_file,
+	.upgrade_with_app_bin_file = fts_ft5822_upgrade_with_app_bin_file,
+	.upgrade_with_lcd_cfg_i_file = NULL,
+	.upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ft5822_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ft5822_get_vendor_id_flash(struct i2c_client *client,
+					u8 *vendor_id)
+{
+	u8 reg_val[2] = {0};
+	u32 i = 0;
+	u8 rw_buf[10];
+	int i_ret;
+
+	fts_ctpm_i2c_hid2std(client);
+
+	for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+		rw_buf[0] = FTS_UPGRADE_55;
+		rw_buf[1] = FTS_UPGRADE_AA;
+		i_ret = fts_i2c_write(client, rw_buf, 2);
+		if (i_ret < 0) {
+			FTS_ERROR("[UPGRADE]: failed writing  0x55 and 0xaa!!");
+			continue;
+		}
+
+		/*check run in bootloader or not*/
+		usleep_range(1000, 2000);
+		rw_buf[0] = FTS_READ_ID_REG;
+		rw_buf[1] = rw_buf[2] = rw_buf[3] = 0x00;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, rw_buf, 4, reg_val, 2);
+
+		FTS_DEBUG("[UPGRADE]: ID1 = 0x%x,ID2 = 0x%x!!",
+				reg_val[0], reg_val[1]);
+		if ((reg_val[0] == chip_types.bootloader_idh)
+			&& (reg_val[1] == chip_types.bootloader_idl)) {
+			FTS_DEBUG("[UPGRADE]: read bootloader id ok!!");
+			break;
+		}
+
+		FTS_ERROR("[UPGRADE]: read bootloader id fail!!");
+	}
+
+	if (i >= FTS_UPGRADE_LOOP)
+		return -EIO;
+
+	/*read vendor id*/
+	rw_buf[0] = 0x03;
+	rw_buf[1] = 0x00;
+	rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+	rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+	i_ret = fts_i2c_write(client, rw_buf, 4);
+	usleep_range(10000, 20000); /*must wait, otherwise read vendor id fail*/
+	i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+	if (i_ret < 0)
+		return -EIO;
+
+	FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+
+	return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ft5822_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0   - ok
+ *		 <0 - fail
+ ***********************************************************************/
+static int fts_ft5822_get_i_file(struct i2c_client *client, int fw_valid)
+{
+	int ret = 0;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+	u8 vendor_id = 0;
+
+	if (fw_valid)
+		ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+	else
+		ret = fts_ft5822_get_vendor_id_flash(client, &vendor_id);
+
+	FTS_DEBUG("[UPGRADE] tp_vendor_id=%x", vendor_id);
+	if (ret < 0) {
+		FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+		return ret;
+	}
+
+	FTS_INFO("[UPGRADE]tp vendor id:%x, FTS_VENDOR_ID:%02x %02x %02x",
+		vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+	ret = 0;
+	switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+	case FTS_VENDOR_1_ID:
+		g_fw_file = CTPM_FW;
+		g_fw_len = fts_getsize(FW_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+	case FTS_VENDOR_2_ID:
+		g_fw_file = CTPM_FW2;
+		g_fw_len = fts_getsize(FW2_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+	case FTS_VENDOR_3_ID:
+		g_fw_file = CTPM_FW3;
+		g_fw_len = fts_getsize(FW3_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+		break;
+#endif
+	default:
+		FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+		ret = -EIO;
+		break;
+	}
+#else
+	/* (FTS_GET_VENDOR_ID_NUM == 0) */
+	g_fw_file = CTPM_FW;
+	g_fw_len = fts_getsize(FW_SIZE);
+	FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+#endif
+
+	return ret;
+}
+
+/************************************************************************
+ * Name: fts_ft5822_get_app_bin_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ft5822_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	int fw_ver = 0;
+	int ret;
+
+	FTS_FUNC_ENTER();
+
+	ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return ret;
+	}
+
+	if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE)
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw->size);
+	else
+		fw_ver = fw->data[APP_FILE_VER_MAPPING];
+
+	release_firmware(fw);
+	FTS_FUNC_EXIT();
+
+	return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ft5822_get_app_i_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ft5822_get_app_i_file_ver(void)
+{
+	int fwsize = g_fw_len;
+
+	if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+		return 0;
+	}
+
+	return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+#define AL2_FCS_COEF	((1 << 7) + (1 << 6) + (1 << 5))
+/*****************************************************************************
+ *   Name: ecc_calc
+ *  Brief:
+ *  Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static u8 ecc_calc(u8 *pbt_buf, u16 start, u16 length)
+{
+	u8 cFcs = 0;
+	u16 i, j;
+
+	for (i = 0; i < length; i++) {
+		cFcs ^= pbt_buf[start++];
+		for (j = 0; j < 8; j++) {
+			if (cFcs & 1)
+				cFcs = (u8)((cFcs >> 1) ^ AL2_FCS_COEF);
+			else
+				cFcs >>= 1;
+		}
+	}
+	return cFcs;
+}
+
+/*****************************************************************************
+ * Name: fts_check_app_bin_valid
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static bool fts_check_app_bin_valid(u8 *pbt_buf)
+{
+	u8 ecc1;
+	u8 ecc2;
+	u8 ecc3;
+	u8 ecc4;
+	u16 len1;
+	u16 len2;
+	u8 cal_ecc1;
+	u8 cal_ecc2;
+	u16 usAddrInfo;
+
+	/* 1. First Byte */
+	if (pbt_buf[0] != 0x02) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- the first byte(%x) error",
+					pbt_buf[0]);
+		return false;
+	}
+
+	usAddrInfo = 0x100;
+
+	/* 2.len */
+	len1  = pbt_buf[usAddrInfo++] << 8;
+	len1 += pbt_buf[usAddrInfo++];
+
+	len2  = pbt_buf[usAddrInfo++] << 8;
+	len2 += pbt_buf[usAddrInfo++];
+
+	if ((len1 + len2) != 0xFFFF) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- LENGTH(%04x) XOR error",
+				len1);
+		return false;
+	}
+
+	/* 3.ecc */
+	ecc1 = pbt_buf[usAddrInfo++];
+	ecc2 = pbt_buf[usAddrInfo++];
+	ecc3 = pbt_buf[usAddrInfo++];
+	ecc4 = pbt_buf[usAddrInfo++];
+
+	if (((ecc1 + ecc2) != 0xFF) || ((ecc3 + ecc4) != 0xFF)) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC(%x %x) XOR error",
+				ecc1, ecc2);
+		return false;
+	}
+
+	cal_ecc1 = ecc_calc(pbt_buf, 0x0, 0x100);
+	cal_ecc2 = ecc_calc(pbt_buf, 0x100 + 0x20, len1 - (0x100 + 0x20));
+	if ((ecc1 != cal_ecc1) || (ecc3 != cal_ecc2)) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC calc error");
+		return false;
+	}
+	return true;
+}
+
+/************************************************************************
+ * Name: fts_ft5822_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ft5822_upgrade_use_buf(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length)
+{
+	u8 reg_val[4] = {0};
+	u32 i = 0;
+	u32 packet_number;
+	u32 j = 0;
+	u32 temp;
+	u32 length;
+	u8 packet_buf[FTS_PACKET_LENGTH + 6];
+	u8 auc_i2c_write_buf[10];
+	u8 upgrade_ecc;
+	int i_ret;
+
+	fts_ctpm_i2c_hid2std(client);
+
+	for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+		/*********Step 1:Reset  CTPM *****/
+		fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_AA);
+		usleep_range(10000, 20000);
+		fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_55);
+		msleep(200);
+
+		/*********Step 2:Enter upgrade mode *****/
+		fts_ctpm_i2c_hid2std(client);
+		usleep_range(5000, 10000);
+
+		auc_i2c_write_buf[0] = FTS_UPGRADE_55;
+		auc_i2c_write_buf[1] = FTS_UPGRADE_AA;
+		i_ret = fts_i2c_write(client, auc_i2c_write_buf, 2);
+		if (i_ret < 0) {
+			FTS_ERROR("[UPGRADE]: failed writing  0x55 and 0xaa!!");
+			continue;
+		}
+
+		/*********Step 3:Check bootloader ID *****/
+		usleep_range(1000, 2000);
+		auc_i2c_write_buf[0] = FTS_READ_ID_REG;
+		auc_i2c_write_buf[1] = auc_i2c_write_buf[2] =
+						auc_i2c_write_buf[3] = 0x00;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+		FTS_DEBUG("[UPGRADE]:ID1 = 0x%x,ID2 = 0x%x!!",
+				reg_val[0], reg_val[1]);
+		if ((reg_val[0] == chip_types.bootloader_idh)
+			&& (reg_val[1] == chip_types.bootloader_idl)) {
+			FTS_DEBUG("[UPGRADE]: read bootload id ok!!");
+			break;
+		}
+
+		FTS_ERROR("[UPGRADE]: read bootload id fail!!");
+	}
+
+	if (i >= FTS_UPGRADE_LOOP) {
+		FTS_ERROR("[UPGRADE]:failed writing 0x55 and 0xaa:i = %d!!", i);
+		return -EIO;
+	}
+
+	/*Step 4:erase app and panel paramenter area*/
+	FTS_DEBUG("[UPGRADE]: erase app and panel paramenter area!!");
+	auc_i2c_write_buf[0] = FTS_ERASE_APP_REG;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(1350);
+	for (i = 0; i < 15; i++) {
+		auc_i2c_write_buf[0] = 0x6a;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+		if ((reg_val[0] == 0xF0) && (reg_val[1] == 0xAA))
+			break;
+		msleep(50);
+	}
+	FTS_DEBUG("[UPGRADE]:erase app area reg_val[0] = %x reg_val[1] = %x!!",
+					reg_val[0], reg_val[1]);
+
+	auc_i2c_write_buf[0] = 0xB0;
+	auc_i2c_write_buf[1] = (u8) ((dw_length >> 16) & 0xFF);
+	auc_i2c_write_buf[2] = (u8) ((dw_length >> 8) & 0xFF);
+	auc_i2c_write_buf[3] = (u8) (dw_length & 0xFF);
+	fts_i2c_write(client, auc_i2c_write_buf, 4);
+
+	/*********Step 5:write firmware(FW) to ctpm flash*********/
+	upgrade_ecc = 0;
+	FTS_DEBUG("[UPGRADE]: write FW to ctpm flash!!");
+	temp = 0;
+	packet_number = (dw_length) / FTS_PACKET_LENGTH;
+	packet_buf[0] = FTS_FW_WRITE_CMD;
+	packet_buf[1] = 0x00;
+
+	for (j = 0; j < packet_number; j++) {
+		temp = j * FTS_PACKET_LENGTH;
+		packet_buf[2] = (u8) (temp >> 8);
+		packet_buf[3] = (u8) temp;
+		length = FTS_PACKET_LENGTH;
+		packet_buf[4] = (u8) (length >> 8);
+		packet_buf[5] = (u8) length;
+		for (i = 0; i < FTS_PACKET_LENGTH; i++) {
+			packet_buf[6 + i] = pbt_buf[j * FTS_PACKET_LENGTH + i];
+			upgrade_ecc ^= packet_buf[6 + i];
+		}
+
+		fts_i2c_write(client, packet_buf, FTS_PACKET_LENGTH + 6);
+		usleep_range(10000, 20000);
+
+		for (i = 0; i < 30; i++) {
+			auc_i2c_write_buf[0] = 0x6a;
+			reg_val[0] = reg_val[1] = 0x00;
+			fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+			if ((j + 0x1000) == (((reg_val[0]) << 8) | reg_val[1]))
+				break;
+			FTS_DEBUG("[UPGRADE]: reg_val[0] = %x reg_val[1] = %x",
+					reg_val[0], reg_val[1]);
+			/* msleep(1); */
+			fts_ctpm_upgrade_delay(1000);
+		}
+	}
+
+	if ((dw_length) % FTS_PACKET_LENGTH > 0) {
+		temp = packet_number * FTS_PACKET_LENGTH;
+		packet_buf[2] = (u8) (temp >> 8);
+		packet_buf[3] = (u8) temp;
+		temp = (dw_length) % FTS_PACKET_LENGTH;
+		packet_buf[4] = (u8) (temp >> 8);
+		packet_buf[5] = (u8) temp;
+		for (i = 0; i < temp; i++) {
+			packet_buf[6 + i] = pbt_buf[packet_number
+						* FTS_PACKET_LENGTH + i];
+			upgrade_ecc ^= packet_buf[6 + i];
+		}
+		fts_i2c_write(client, packet_buf, temp + 6);
+		usleep_range(10000, 20000);
+
+		for (i = 0; i < 30; i++) {
+			auc_i2c_write_buf[0] = 0x6a;
+			reg_val[0] = reg_val[1] = 0x00;
+			fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+			if ((0x1000 + ((packet_number * FTS_PACKET_LENGTH)
+				/((dw_length) % FTS_PACKET_LENGTH)))
+				== (((reg_val[0]) << 8) | reg_val[1]))
+				break;
+			FTS_DEBUG("[UPGRADE]: reg_val[0] = %x!!", reg_val[0]);
+			FTS_DEBUG("[UPGRADE]: reg_val[1] = %x!!", reg_val[1]);
+			FTS_DEBUG("[UPGRADE]: reg_val[2] = %x!!",
+				(((packet_number * FTS_PACKET_LENGTH)
+				  /((dw_length) % FTS_PACKET_LENGTH))+0x1000));
+			/* msleep(1); */
+			fts_ctpm_upgrade_delay(1000);
+		}
+	}
+
+	msleep(50);
+
+	/*********Step 6: read out checksum***********************/
+	/*send the opration head */
+	FTS_DEBUG("[UPGRADE]: read out checksum!!");
+	auc_i2c_write_buf[0] = 0x64;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(300);
+
+	temp = 0;
+	auc_i2c_write_buf[0] = 0x65;
+	auc_i2c_write_buf[1] = (u8)(temp >> 16);
+	auc_i2c_write_buf[2] = (u8)(temp >> 8);
+	auc_i2c_write_buf[3] = (u8)(temp);
+	temp = dw_length;
+	auc_i2c_write_buf[4] = (u8)(temp >> 8);
+	auc_i2c_write_buf[5] = (u8)(temp);
+	i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+	msleep(dw_length/256);
+
+	for (i = 0; i < 100; i++) {
+		auc_i2c_write_buf[0] = 0x6a;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+		FTS_DEBUG("[UPGRADE]: reg_val[0]=%02x reg_val[0]=%02x!!",
+					reg_val[0], reg_val[1]);
+		if ((reg_val[0] == 0xF0) && (reg_val[1] == 0x55))
+			break;
+		usleep_range(1000, 2000);
+	}
+	auc_i2c_write_buf[0] = 0x66;
+	fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+	if (reg_val[0] != upgrade_ecc) {
+		FTS_ERROR("[UPGRADE]: ecc error! FW=%02x upgrade_ecc=%02x!!",
+				reg_val[0], upgrade_ecc);
+		return -EIO;
+	}
+
+	FTS_DEBUG("[UPGRADE]: checksum %x %x!!", reg_val[0], upgrade_ecc);
+
+	FTS_DEBUG("[UPGRADE]: reset the new FW!!");
+	auc_i2c_write_buf[0] = FTS_REG_RESET_FW;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(200);
+
+	fts_ctpm_i2c_hid2std(client);
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ft5822_upgrade_with_app_i_file
+ * Brief:  upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ft5822_upgrade_with_app_i_file(struct i2c_client *client)
+{
+	int i_ret = 0;
+	u32 fw_len;
+	u8 *fw_buf;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+	fw_len = g_fw_len;
+	fw_buf = g_fw_file;
+	if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+		return -EIO;
+	}
+
+	i_ret = fts_ft5822_upgrade_use_buf(client, fw_buf, fw_len);
+	if (i_ret != 0)
+		FTS_ERROR("[UPGRADE] upgrade app.i failed");
+	else
+		FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ft5822_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ft5822_upgrade_with_app_bin_file(struct i2c_client *client,
+					char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	u8 *pbt_buf = NULL;
+	int i_ret = 0;
+	bool ecc_ok = false;
+	int fwsize = 0;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+	i_ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (i_ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return i_ret;
+	}
+
+	if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+							fwsize);
+		goto ERROR_BIN;
+	}
+
+	/*check the app.bin invalid or not*/
+	pbt_buf = (u8 *)fw->data;
+	if (pbt_buf[APP_FILE_CHIPID_MAPPING] != chip_types.chip_idh) {
+		FTS_ERROR("[UPGRADE]: chip id error, app.bin upgrade failed!!");
+		goto ERROR_BIN;
+	}
+
+	/*check the app.bin invalid or not*/
+	ecc_ok = fts_check_app_bin_valid(pbt_buf);
+	if (ecc_ok) {
+		FTS_INFO("[UPGRADE] app.bin ecc ok");
+		i_ret = fts_ft5822_upgrade_use_buf(client, pbt_buf, fw->size);
+		if (i_ret != 0) {
+			FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+			goto ERROR_BIN;
+		} else {
+			FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+		}
+	} else {
+		FTS_ERROR("[UPGRADE] app.bin ecc failed");
+		goto ERROR_BIN;
+	}
+
+ERROR_BIN:
+	release_firmware(fw);
+	return i_ret;
+}
+#endif  /* FT5822 */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft5x46.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft5x46.c
new file mode 100644
index 0000000..77f3c58
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft5x46.c
@@ -0,0 +1,625 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft5x46.c
+ *
+ * Author:    fupeipei
+ *
+ * Created:    2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (IC_SERIALS == 0x02)
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE           (60 * 1024)
+#define APP_FILE_MIN_SIZE           (8)
+#define CONFIG_START_ADDR           (0xD780)
+#define CONFIG_VENDOR_ID_OFFSET     (0x04)
+#define CONFIG_PROJECT_ID_OFFSET    (0x20)
+#define CONFIG_VENDOR_ID_ADDR       (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR      (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ft5x46_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ft5x46_get_app_i_file_ver(void);
+static int fts_ft5x46_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name);
+static int fts_ft5x46_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ft5x46_upgrade_with_app_bin_file(struct i2c_client *client,
+					char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+
+	.get_i_file = fts_ft5x46_get_i_file,
+	.get_app_bin_file_ver = fts_ft5x46_get_app_bin_file_ver,
+	.get_app_i_file_ver = fts_ft5x46_get_app_i_file_ver,
+	.upgrade_with_app_i_file = fts_ft5x46_upgrade_with_app_i_file,
+	.upgrade_with_app_bin_file = fts_ft5x46_upgrade_with_app_bin_file,
+	.upgrade_with_lcd_cfg_i_file = NULL,
+	.upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ft5x46_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ft5x46_get_vendor_id_flash(struct i2c_client *client,
+					u8 *vendor_id)
+{
+	u8 reg_val[2] = {0};
+	u32 i = 0;
+	u8 rw_buf[10];
+	int i_ret;
+
+	fts_ctpm_i2c_hid2std(client);
+
+	for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+		rw_buf[0] = FTS_UPGRADE_55;
+		rw_buf[1] = FTS_UPGRADE_AA;
+		i_ret = fts_i2c_write(client, rw_buf, 2);
+		if (i_ret < 0) {
+			FTS_ERROR("[UPGRADE]: failed writing  0x55 and 0xaa!!");
+			continue;
+		}
+
+		/*check run in bootloader or not*/
+		usleep_range(1000, 2000);
+		rw_buf[0] = FTS_READ_ID_REG;
+		rw_buf[1] = rw_buf[2] = rw_buf[3] = 0x00;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, rw_buf, 4, reg_val, 2);
+
+		FTS_DEBUG("[UPGRADE]:ID1 = 0x%x,ID2 = 0x%x!!",
+					reg_val[0], reg_val[1]);
+		if ((reg_val[0] == chip_types.bootloader_idh)
+			&& (reg_val[1] == chip_types.bootloader_idl)) {
+			FTS_DEBUG("[UPGRADE]: read bootloader id ok!!");
+			break;
+		}
+
+		FTS_ERROR("[UPGRADE]: read bootloader id fail!!");
+	}
+
+	if (i >= FTS_UPGRADE_LOOP)
+		return -EIO;
+
+	/*read vendor id*/
+	rw_buf[0] = 0x03;
+	rw_buf[1] = 0x00;
+	rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+	rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+	i_ret = fts_i2c_write(client, rw_buf, 4);
+	usleep_range(10000, 20000); /*must wait, otherwise read vendor id fail*/
+	i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+	if (i_ret < 0)
+		return -EIO;
+	FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+	return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ft5x46_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0   - ok
+ *		 <0 - fail
+ ***********************************************************************/
+static int fts_ft5x46_get_i_file(struct i2c_client *client, int fw_valid)
+{
+	int ret = 0;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+	u8 vendor_id = 0;
+
+	if (fw_valid)
+		ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+	else
+		ret = fts_ft5x46_get_vendor_id_flash(client, &vendor_id);
+
+	FTS_DEBUG("[UPGRADE] tp_vendor_id=%x", vendor_id);
+	if (ret < 0) {
+		FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+		return ret;
+	}
+
+	FTS_INFO("[UPGRADE]tp vendor id:%x, FTS_VENDOR_ID:%02x %02x %02x",
+		 vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+	ret = 0;
+	switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+	case FTS_VENDOR_1_ID:
+		g_fw_file = CTPM_FW;
+		g_fw_len = fts_getsize(FW_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+	case FTS_VENDOR_2_ID:
+		g_fw_file = CTPM_FW2;
+		g_fw_len = fts_getsize(FW2_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+	case FTS_VENDOR_3_ID:
+		g_fw_file = CTPM_FW3;
+		g_fw_len = fts_getsize(FW3_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+		break;
+#endif
+	default:
+		FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+		ret = -EIO;
+		break;
+	}
+#else
+	/* (FTS_GET_VENDOR_ID_NUM == 0) */
+	g_fw_file = CTPM_FW;
+	g_fw_len = fts_getsize(FW_SIZE);
+	FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+#endif
+
+	return ret;
+}
+
+/************************************************************************
+ * Name: fts_ft5x46_get_app_bin_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ft5x46_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	int fw_ver = 0;
+	int ret;
+
+	FTS_FUNC_ENTER();
+
+	ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return ret;
+	}
+
+	if (fw->size > 2)
+		fw_ver = fw->data[fw->size - 2];
+
+	release_firmware(fw);
+	FTS_FUNC_EXIT();
+
+	return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ft5x46_get_app_i_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ft5x46_get_app_i_file_ver(void)
+{
+	int fwsize = g_fw_len;
+
+	if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+		return 0;
+	}
+
+	return g_fw_file[fwsize-2];
+}
+
+#define AL2_FCS_COEF	((1 << 7) + (1 << 6) + (1 << 5))
+/*****************************************************************************
+ *   Name: ecc_calc
+ *  Brief:
+ *  Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static u8 ecc_calc(u8 *pbt_buf, u16 start, u16 length)
+{
+	u8 cFcs = 0;
+	u16 i, j;
+
+	for (i = 0; i < length; i++) {
+		cFcs ^= pbt_buf[start++];
+		for (j = 0; j < 8; j++) {
+			if (cFcs & 1)
+				cFcs = (u8)((cFcs >> 1) ^ AL2_FCS_COEF);
+			else
+				cFcs >>= 1;
+		}
+	}
+	return cFcs;
+}
+
+/*****************************************************************************
+ * Name: fts_check_app_bin_valid
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static bool fts_check_app_bin_valid(u8 *pbt_buf, u32 dw_length)
+{
+	u8 ecc1;
+	u8 ecc2;
+	u16 len1;
+	u16 len2;
+	u8 cal_ecc;
+	u16 usAddrInfo;
+
+	/* 1. First Byte */
+	if (pbt_buf[0] != 0x02) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- the first byte(%x) error",
+							pbt_buf[0]);
+		return false;
+	}
+
+	usAddrInfo = dw_length - 8;
+
+	/* 2.len */
+	len1  = pbt_buf[usAddrInfo++] << 8;
+	len1 += pbt_buf[usAddrInfo++];
+
+	len2  = pbt_buf[usAddrInfo++] << 8;
+	len2 += pbt_buf[usAddrInfo++];
+
+	if ((len1 + len2) != 0xFFFF) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- LENGTH(%04x) XOR error",
+							len1);
+		return false;
+	}
+
+	/* 3.ecc */
+	ecc1 = pbt_buf[usAddrInfo++];
+	ecc2 = pbt_buf[usAddrInfo++];
+
+	if ((ecc1 + ecc2) != 0xFF) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC(%x) XOR error", ecc1);
+		return false;
+	}
+
+	cal_ecc = ecc_calc(pbt_buf, 0x0, len1);
+
+	if (ecc1 != cal_ecc) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC calc error");
+		return false;
+	}
+	return true;
+}
+
+
+/************************************************************************
+ * Name: fts_ft5x46_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ft5x46_upgrade_use_buf(struct i2c_client *client,
+				u8 *pbt_buf, u32 dw_length)
+{
+	u8 reg_val[4] = {0};
+	u32 i = 0;
+	u32 packet_number;
+	u32 j = 0;
+	u32 temp;
+	u32 length;
+	u8 packet_buf[FTS_PACKET_LENGTH + 6];
+	u8 auc_i2c_write_buf[10];
+	u8 upgrade_ecc;
+	int i_ret;
+
+	fts_ctpm_i2c_hid2std(client);
+
+	for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+		/*********Step 1:Reset  CTPM *****/
+		fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_AA);
+		usleep_range(10000, 20000);
+		fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_55);
+		msleep(200);
+
+		/*********Step 2:Enter upgrade mode *****/
+		fts_ctpm_i2c_hid2std(client);
+		usleep_range(5000, 10000);
+
+		auc_i2c_write_buf[0] = FTS_UPGRADE_55;
+		auc_i2c_write_buf[1] = FTS_UPGRADE_AA;
+		i_ret = fts_i2c_write(client, auc_i2c_write_buf, 2);
+		if (i_ret < 0) {
+			FTS_ERROR("[UPGRADE]: failed writing  0x55 and 0xaa!!");
+			continue;
+		}
+
+		/*********Step 3:Check bootloader ID *****/
+		usleep_range(1000, 2000);
+		auc_i2c_write_buf[0] = FTS_READ_ID_REG;
+		auc_i2c_write_buf[1] = auc_i2c_write_buf[2] =
+						auc_i2c_write_buf[3] = 0x00;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+		FTS_DEBUG("[UPGRADE]: ID1 = 0x%x,ID2 = 0x%x!!",
+					reg_val[0], reg_val[1]);
+		if ((reg_val[0] == chip_types.bootloader_idh)
+			&& (reg_val[1] == chip_types.bootloader_idl)) {
+			FTS_DEBUG("[UPGRADE]: read bootload id ok!!");
+			break;
+		}
+
+		FTS_ERROR("[UPGRADE]: read bootload id fail!!");
+	}
+
+	if (i >= FTS_UPGRADE_LOOP) {
+		FTS_ERROR("[UPGRADE]:failed writing 0x55 and 0xaa:i = %d!!", i);
+		return -EIO;
+	}
+
+	/*Step 4:erase app and panel paramenter area*/
+	FTS_DEBUG("[UPGRADE]: erase app and panel paramenter area!!");
+	auc_i2c_write_buf[0] = FTS_ERASE_APP_REG;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(1350);
+	for (i = 0; i < 15; i++) {
+		auc_i2c_write_buf[0] = 0x6a;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+		if ((reg_val[0] == 0xF0) && (reg_val[1] == 0xAA))
+			break;
+		msleep(50);
+	}
+	FTS_DEBUG("[UPGRADE]:erase app area reg_val[0] = %x reg_val[1] = %x!!",
+				reg_val[0], reg_val[1]);
+
+	auc_i2c_write_buf[0] = 0xB0;
+	auc_i2c_write_buf[1] = (u8) ((dw_length >> 16) & 0xFF);
+	auc_i2c_write_buf[2] = (u8) ((dw_length >> 8) & 0xFF);
+	auc_i2c_write_buf[3] = (u8) (dw_length & 0xFF);
+	fts_i2c_write(client, auc_i2c_write_buf, 4);
+
+	/*********Step 5:write firmware(FW) to ctpm flash*********/
+	upgrade_ecc = 0;
+	FTS_DEBUG("[UPGRADE]: write FW to ctpm flash!!");
+	temp = 0;
+	packet_number = (dw_length) / FTS_PACKET_LENGTH;
+	packet_buf[0] = FTS_FW_WRITE_CMD;
+	packet_buf[1] = 0x00;
+
+	for (j = 0; j < packet_number; j++) {
+		temp = j * FTS_PACKET_LENGTH;
+		packet_buf[2] = (u8) (temp >> 8);
+		packet_buf[3] = (u8) temp;
+		length = FTS_PACKET_LENGTH;
+		packet_buf[4] = (u8) (length >> 8);
+		packet_buf[5] = (u8) length;
+		for (i = 0; i < FTS_PACKET_LENGTH; i++) {
+			packet_buf[6 + i] = pbt_buf[j * FTS_PACKET_LENGTH + i];
+			upgrade_ecc ^= packet_buf[6 + i];
+		}
+		fts_i2c_write(client, packet_buf, FTS_PACKET_LENGTH + 6);
+		usleep_range(10000, 20000);
+
+		for (i = 0; i < 30; i++) {
+			auc_i2c_write_buf[0] = 0x6a;
+			reg_val[0] = reg_val[1] = 0x00;
+			fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+			if ((j + 0x1000) == (((reg_val[0]) << 8) | reg_val[1]))
+				break;
+			FTS_DEBUG("[UPGRADE]:reg_val[0] = %x reg_val[1] = %x!!",
+						reg_val[0], reg_val[1]);
+			/* usleep_range(1000, 2000); */
+			fts_ctpm_upgrade_delay(1000);
+		}
+	}
+
+	if ((dw_length) % FTS_PACKET_LENGTH > 0) {
+		temp = packet_number * FTS_PACKET_LENGTH;
+		packet_buf[2] = (u8) (temp >> 8);
+		packet_buf[3] = (u8) temp;
+		temp = (dw_length) % FTS_PACKET_LENGTH;
+		packet_buf[4] = (u8) (temp >> 8);
+		packet_buf[5] = (u8) temp;
+		for (i = 0; i < temp; i++) {
+			packet_buf[6 + i] = pbt_buf[packet_number
+						* FTS_PACKET_LENGTH + i];
+			upgrade_ecc ^= packet_buf[6 + i];
+		}
+		fts_i2c_write(client, packet_buf, temp + 6);
+		usleep_range(10000, 20000);
+
+		for (i = 0; i < 30; i++) {
+			auc_i2c_write_buf[0] = 0x6a;
+			reg_val[0] = reg_val[1] = 0x00;
+			fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+			if ((0x1000 + ((packet_number * FTS_PACKET_LENGTH)
+				/((dw_length) % FTS_PACKET_LENGTH))) ==
+				(((reg_val[0]) << 8) | reg_val[1]))
+				break;
+			FTS_DEBUG("[UPGRADE]: reg_val[0] = %x!!", reg_val[0]);
+			FTS_DEBUG("[UPGRADE]: reg_val[1] = %x!!", reg_val[1]);
+			FTS_DEBUG("[UPGRADE]: reg_val[2] = 0x%x!!",
+				(((packet_number * FTS_PACKET_LENGTH)
+				  /((dw_length) % FTS_PACKET_LENGTH))+0x1000));
+			/* usleep_range(1000, 2000); */
+			fts_ctpm_upgrade_delay(1000);
+		}
+	}
+
+	msleep(50);
+
+	/*********Step 6: read out checksum***********************/
+	/*send the opration head */
+	FTS_DEBUG("[UPGRADE]: read out checksum!!");
+	auc_i2c_write_buf[0] = 0x64;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(300);
+
+	temp = 0;
+	auc_i2c_write_buf[0] = 0x65;
+	auc_i2c_write_buf[1] = (u8)(temp >> 16);
+	auc_i2c_write_buf[2] = (u8)(temp >> 8);
+	auc_i2c_write_buf[3] = (u8)(temp);
+	temp = dw_length;
+	auc_i2c_write_buf[4] = (u8)(temp >> 8);
+	auc_i2c_write_buf[5] = (u8)(temp);
+	i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+	msleep(dw_length/256);
+
+	for (i = 0; i < 100; i++) {
+		auc_i2c_write_buf[0] = 0x6a;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+		FTS_DEBUG("[UPGRADE]: reg_val[0]=%02x reg_val[0]=%02x!!",
+					reg_val[0], reg_val[1]);
+		if ((reg_val[0] == 0xF0) && (reg_val[1] == 0x55))
+			break;
+		usleep_range(1000, 2000);
+	}
+	auc_i2c_write_buf[0] = 0x66;
+	fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+	if (reg_val[0] != upgrade_ecc) {
+		FTS_ERROR("[UPGRADE]: ecc error! FW=%02x upgrade_ecc=%02x!!",
+					reg_val[0], upgrade_ecc);
+		return -EIO;
+	}
+	FTS_DEBUG("[UPGRADE]: checksum %x %x!!", reg_val[0], upgrade_ecc);
+
+	FTS_DEBUG("[UPGRADE]: reset the new FW!!");
+	auc_i2c_write_buf[0] = FTS_REG_RESET_FW;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(200);
+
+	fts_ctpm_i2c_hid2std(client);
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ft5x46_upgrade_with_app_i_file
+ * Brief:  upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ft5x46_upgrade_with_app_i_file(struct i2c_client *client)
+{
+	int i_ret = 0;
+	u32 fw_len;
+	u8 *fw_buf;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+	fw_len = g_fw_len;
+	fw_buf = g_fw_file;
+	if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+		return -EIO;
+	}
+
+	i_ret = fts_ft5x46_upgrade_use_buf(client, fw_buf, fw_len);
+	if (i_ret != 0)
+		FTS_ERROR("[UPGRADE] upgrade app.i failed");
+	else
+		FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ft5x46_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ft5x46_upgrade_with_app_bin_file(struct i2c_client *client,
+					char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	u8 *pbt_buf = NULL;
+	int i_ret = 0;
+	bool ecc_ok = false;
+	int fwsize = 0;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+	i_ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (i_ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return i_ret;
+	}
+
+	if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+							fwsize);
+		goto ERROR_BIN;
+	}
+
+	/*check the app.bin invalid or not*/
+	pbt_buf = (u8 *)fw->data;
+	ecc_ok = fts_check_app_bin_valid(pbt_buf, fw->size);
+
+	if (ecc_ok) {
+		FTS_INFO("[UPGRADE] app.bin ecc ok");
+		i_ret = fts_ft5x46_upgrade_use_buf(client, pbt_buf, fw->size);
+		if (i_ret != 0) {
+			FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+			goto ERROR_BIN;
+		} else {
+			FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+		}
+	} else {
+		FTS_ERROR("[UPGRADE] app.bin ecc failed");
+		goto ERROR_BIN;
+	}
+
+ERROR_BIN:
+	release_firmware(fw);
+	return i_ret;
+}
+#endif /* FT5X46 */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft6336gu.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft6336gu.c
new file mode 100644
index 0000000..7516ab2
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft6336gu.c
@@ -0,0 +1,606 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft6336GU.c
+ *
+ * Author:    fupeipei
+ *
+ * Created:    2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if ((IC_SERIALS == 0x03) || (IC_SERIALS == 0x04))
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE           (60 * 1024)
+#define APP_FILE_MIN_SIZE           (8)
+#define APP_FILE_VER_MAPPING        (0x10A)
+#define APP_FILE_VENDORID_MAPPING   (0x10C)
+#define CONFIG_START_ADDR           (0x7B0)
+#define CONFIG_VENDOR_ID_OFFSET     (0x4)
+#define CONFIG_PROJECT_ID_OFFSET    (0x20)
+#define CONFIG_VENDOR_ID_ADDR       (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR      (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+
+#define APP_LEN         0x00
+#define APP_LEN_NE      0x02
+#define APP_P1_ECC      0x04
+#define APP_P1_ECC_NE   0x05
+#define APP_P2_ECC      0x06
+#define APP_P2_ECC_NE   0x07
+
+#define APP1_START          0x00
+#define APP1_LEN            0x100
+#define APP_VERIF_ADDR      (APP1_START + APP1_LEN)
+#define APP_VERIF_LEN       0x20
+#define APP1_ECC_ADDR       (APP_VERIF_ADDR + APP_P1_ECC)
+#define APP2_START          (APP_VERIF_ADDR + APP_VERIF_LEN)
+#define APP2_ECC_ADDR       (APP_VERIF_ADDR + APP_P2_ECC)
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ft6x36gu_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ft6x36gu_get_app_i_file_ver(void);
+static int fts_ft6x36gu_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name);
+static int fts_ft6x36gu_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ft6x36gu_upgrade_with_app_bin_file(struct i2c_client *client,
+					char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+
+	.get_i_file = fts_ft6x36gu_get_i_file,
+	.get_app_bin_file_ver = fts_ft6x36gu_get_app_bin_file_ver,
+	.get_app_i_file_ver = fts_ft6x36gu_get_app_i_file_ver,
+	.upgrade_with_app_i_file = fts_ft6x36gu_upgrade_with_app_i_file,
+	.upgrade_with_app_bin_file = fts_ft6x36gu_upgrade_with_app_bin_file,
+	.upgrade_with_lcd_cfg_i_file = NULL,
+	.upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ft6x36gu_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ft6x36gu_get_vendor_id_flash(struct i2c_client *client,
+					u8 *vendor_id)
+{
+	u8 reg_val[2] = {0};
+	u32 i = 0;
+	u8 rw_buf[10];
+	int i_ret;
+
+	for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+		rw_buf[0] = FTS_UPGRADE_55;
+		rw_buf[1] = FTS_UPGRADE_AA;
+		i_ret = fts_i2c_write(client, rw_buf, 2);
+		if (i_ret < 0) {
+			FTS_ERROR("[UPGRADE]: failed writing  0x55 and 0xaa!!");
+			continue;
+		}
+
+		/*check run in bootloader or not*/
+		usleep_range(1000, 2000);
+		rw_buf[0] = FTS_READ_ID_REG;
+		rw_buf[1] = rw_buf[2] = rw_buf[3] = 0x00;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, rw_buf, 4, reg_val, 2);
+
+		FTS_DEBUG("[UPGRADE]: ID1 = 0x%x,ID2 = 0x%x!!",
+					reg_val[0], reg_val[1]);
+		if ((reg_val[0] == chip_types.bootloader_idh)
+			&& (reg_val[1] == chip_types.bootloader_idl)) {
+			FTS_DEBUG("[UPGRADE]: read bootloader id ok!! ");
+			break;
+		}
+		FTS_ERROR("[UPGRADE]: read bootloader id fail!!");
+	}
+
+	if (i >= FTS_UPGRADE_LOOP)
+		return -EIO;
+
+	/*read vendor id*/
+	rw_buf[0] = 0x03;
+	rw_buf[1] = 0x00;
+	rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+	rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+	i_ret = fts_i2c_write(client, rw_buf, 4);
+	usleep_range(10000, 20000); /*must wait, otherwise read vendor id fail*/
+	i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+	if (i_ret < 0)
+		return -EIO;
+	FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+	return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ft6x36gu_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0   - ok
+ *		 <0 - fail
+ ***********************************************************************/
+static int fts_ft6x36gu_get_i_file(struct i2c_client *client, int fw_valid)
+{
+	int ret = -EIO;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+	u8 vendor_id = 0;
+
+	if (fw_valid)
+		ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+	else
+		ret = fts_ft6x36gu_get_vendor_id_flash(client, &vendor_id);
+
+	FTS_DEBUG("[UPGRADE] tp_vendor_id=%x", vendor_id);
+	if (ret < 0) {
+		FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+		return ret;
+	}
+
+	FTS_INFO("[UPGRADE]tp vendor id:%x, FTS_VENDOR_ID:%02x %02x %02x",
+		 vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+	ret = 0;
+	switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+	case FTS_VENDOR_1_ID:
+		g_fw_file = CTPM_FW;
+		g_fw_len = fts_getsize(FW_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+	case FTS_VENDOR_2_ID:
+		g_fw_file = CTPM_FW2;
+		g_fw_len = fts_getsize(FW2_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+	case FTS_VENDOR_3_ID:
+		g_fw_file = CTPM_FW3;
+		g_fw_len = fts_getsize(FW3_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+		break;
+#endif
+	default:
+		FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+		ret = -EIO;
+		break;
+	}
+#endif
+
+	return ret;
+}
+
+/************************************************************************
+ * Name: fts_ft6x36gu_get_app_bin_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ft6x36gu_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	int fw_ver = 0;
+	int ret;
+
+	FTS_FUNC_ENTER();
+
+	ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return ret;
+	}
+
+	if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE)
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw->size);
+	else
+		fw_ver = fw->data[APP_FILE_VER_MAPPING];
+
+	release_firmware(fw);
+	FTS_FUNC_EXIT();
+
+	return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ft6x36gu_get_app_i_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ft6x36gu_get_app_i_file_ver(void)
+{
+	int fwsize = g_fw_len;
+
+	if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+		return 0;
+	}
+
+	return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+/*****************************************************************************
+ * Name: fts_check_app_bin_valid
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static bool fts_check_app_bin_valid(u8 *buf)
+{
+	int i;
+	u16 len;
+	u16 len_neg;
+	u16 ecc2_len = 0;
+	u8 cal_ecc = 0;
+	u8 cal_ecc2 = 0;
+
+	FTS_INFO("[UPGRADE] Check APP.BIN ECC");
+
+	/* 1. start code byte */
+	if (buf[0] != 0x02) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- the first byte(%x) error",
+						buf[0]);
+		return false;
+	}
+
+	/* 2. len */
+	len = ((u16)buf[APP_VERIF_ADDR + APP_LEN] << 8)
+		+ buf[APP_VERIF_ADDR + APP_LEN + 1];
+	len_neg = (u16)(buf[APP_VERIF_ADDR + APP_LEN_NE] << 8)
+		+ buf[APP_VERIF_ADDR + APP_LEN_NE + 1];
+	if ((len ^ len_neg) != 0xFFFF) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- LENGTH(%04x) XOR error",
+						len);
+		return false;
+	}
+
+	/* 3. ecc */
+	if (((buf[APP1_ECC_ADDR] ^ buf[APP1_ECC_ADDR+1]) != 0xFF)
+		|| ((buf[APP2_ECC_ADDR] ^ buf[APP2_ECC_ADDR+1]) != 0xFF)) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC(%x %x) XOR error",
+				buf[APP1_ECC_ADDR], buf[APP2_ECC_ADDR]);
+		return false;
+	}
+
+	/* APP1 */
+	for (i = 0; i < APP1_LEN; i++)
+		cal_ecc ^= buf[APP1_START+i];
+	/* APP2 */
+	ecc2_len = ((u16)buf[APP_VERIF_ADDR+0x10] << 8)
+			+ buf[APP_VERIF_ADDR+0x11];
+	ecc2_len = len - APP1_LEN - APP_VERIF_LEN - ecc2_len;
+	for (i = 0; i < ecc2_len; i++)
+		cal_ecc2 ^= buf[APP2_START+i];
+
+	if ((cal_ecc != buf[APP1_ECC_ADDR])
+		|| (cal_ecc2 != buf[APP2_ECC_ADDR])) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC(%x %x) calc error",
+					cal_ecc, cal_ecc2);
+		return false;
+	}
+
+	return true;
+}
+
+
+/************************************************************************
+ * Name: fts_ft6x36gu_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ft6x36gu_upgrade_use_buf(struct i2c_client *client,
+				u8 *pbt_buf, u32 dw_length)
+{
+	u8 reg_val[2] = {0};
+	u32 i = 0;
+	u32 packet_number;
+	u32 j;
+	u32 temp;
+	u32 length;
+	u32 fw_length;
+	u8 packet_buf[FTS_PACKET_LENGTH + 6];
+	u8 auc_i2c_write_buf[10];
+	u8 upgrade_ecc;
+
+	FTS_FUNC_ENTER();
+
+	/*if the first byte of app is not 0x02,
+	 *the app is invaild, can not upgrade
+	 */
+	if (pbt_buf[0] != 0x02) {
+		FTS_ERROR("[UPGRADE]: app first byte != 0x02. cannot upgrade!");
+		return -EINVAL;
+	}
+
+	/*check app length*/
+	if (dw_length > 0x11f) {
+		fw_length = ((u32)pbt_buf[0x100]<<8) + pbt_buf[0x101];
+		if (dw_length < fw_length) {
+			FTS_ERROR("[UPGRADE]: Fw length error!!");
+			return -EINVAL;
+		}
+	} else {
+		FTS_ERROR("[UPGRADE]: Fw length error!!");
+		return -EINVAL;
+	}
+
+	/*send upgrade commond*/
+	for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+		/*send 0xAA and 0x55 to fw(0xFC reg), and start upgrade*/
+		fts_i2c_write_reg(client, FTS_RST_CMD_REG2, FTS_UPGRADE_AA);
+		usleep_range(10000, 20000);
+		fts_i2c_write_reg(client, FTS_RST_CMD_REG2, FTS_UPGRADE_55);
+		usleep_range(10000, 20000);
+
+		/*upgrade init in ROM*/
+		auc_i2c_write_buf[0] = FTS_UPGRADE_55;
+		fts_i2c_write(client, auc_i2c_write_buf, 1);
+		auc_i2c_write_buf[0] = FTS_UPGRADE_AA;
+		fts_i2c_write(client, auc_i2c_write_buf, 1);
+		usleep_range(10000, 20000);
+
+		/*check run in ROM now*/
+		auc_i2c_write_buf[0] = FTS_READ_ID_REG;
+		auc_i2c_write_buf[1] = auc_i2c_write_buf[2]
+					= auc_i2c_write_buf[3] = 0x00;
+		reg_val[0] = 0x00;
+		reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+
+		if (reg_val[0] == chip_types.bootloader_idh
+			&& reg_val[1] == chip_types.bootloader_idl)
+			break;
+	}
+
+	if (i >= FTS_UPGRADE_LOOP) {
+		FTS_ERROR("[UPGRADE]: get bootload id error !!");
+		return -EIO;
+	}
+
+	/*erase app in flash*/
+	FTS_INFO("[UPGRADE]: erase app!!");
+	auc_i2c_write_buf[0] = FTS_ERASE_APP_REG;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(2000);
+
+	for (i = 0; i < 200; i++) {
+		auc_i2c_write_buf[0] = 0x6a;
+		auc_i2c_write_buf[1] = 0x00;
+		auc_i2c_write_buf[2] = 0x00;
+		auc_i2c_write_buf[3] = 0x00;
+		reg_val[0] = 0x00;
+		reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+		if (0xb0 == reg_val[0] && 0x02 == reg_val[1]) {
+			FTS_INFO("[UPGRADE]: erase app finished!!");
+			break;
+		}
+		msleep(50);
+	}
+
+	/*write app to flash*/
+	upgrade_ecc = 0;
+	FTS_INFO("[UPGRADE]: write app to flash!!");
+
+	dw_length = fw_length;
+	packet_number = (dw_length) / FTS_PACKET_LENGTH;
+	packet_buf[0] = FTS_FW_WRITE_CMD;
+	packet_buf[1] = 0x00;
+
+	for (j = 0; j < packet_number; j++) {
+		temp = j * FTS_PACKET_LENGTH;
+		packet_buf[2] = (u8) (temp >> 8);
+		packet_buf[3] = (u8) temp;
+		length = FTS_PACKET_LENGTH;
+		packet_buf[4] = (u8) (length >> 8);
+		packet_buf[5] = (u8) length;
+
+		for (i = 0; i < FTS_PACKET_LENGTH; i++) {
+			packet_buf[6 + i] = pbt_buf[j * FTS_PACKET_LENGTH + i];
+			upgrade_ecc ^= packet_buf[6 + i];
+		}
+
+		fts_i2c_write(client, packet_buf, FTS_PACKET_LENGTH + 6);
+
+		for (i = 0; i < 30; i++) {
+			auc_i2c_write_buf[0] = 0x6a;
+			auc_i2c_write_buf[1] = 0x00;
+			auc_i2c_write_buf[2] = 0x00;
+			auc_i2c_write_buf[3] = 0x00;
+			reg_val[0] = 0x00;
+			reg_val[1] = 0x00;
+			fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+			if (0xb0 == (reg_val[0] & 0xf0) && (0x03 + (j % 0x0ffd))
+				== (((reg_val[0] & 0x0f) << 8) | reg_val[1]))
+				break;
+			/* usleep_range(1000, 2000); */
+			fts_ctpm_upgrade_delay(1000);
+		}
+	}
+
+	if ((dw_length) % FTS_PACKET_LENGTH > 0) {
+		temp = packet_number * FTS_PACKET_LENGTH;
+		packet_buf[2] = (u8) (temp >> 8);
+		packet_buf[3] = (u8) temp;
+		temp = (dw_length) % FTS_PACKET_LENGTH;
+		packet_buf[4] = (u8) (temp >> 8);
+		packet_buf[5] = (u8) temp;
+
+		for (i = 0; i < temp; i++) {
+			packet_buf[6 + i] = pbt_buf[packet_number
+						* FTS_PACKET_LENGTH + i];
+			upgrade_ecc ^= packet_buf[6 + i];
+		}
+
+		fts_i2c_write(client, packet_buf, temp + 6);
+
+		for (i = 0; i < 30; i++) {
+			auc_i2c_write_buf[0] = 0x6a;
+			auc_i2c_write_buf[1] = 0x00;
+			auc_i2c_write_buf[2] = 0x00;
+			auc_i2c_write_buf[3] = 0x00;
+			reg_val[0] = 0x00;
+			reg_val[1] = 0x00;
+			fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+			if (0xb0 == (reg_val[0] & 0xf0) && (0x03 + (j % 0x0ffd))
+				== (((reg_val[0] & 0x0f) << 8) | reg_val[1]))
+				break;
+			/* usleep_range(1000, 2000); */
+			fts_ctpm_upgrade_delay(1000);
+		}
+	}
+
+	/*read out checksum*/
+	FTS_INFO("[UPGRADE]: read out checksum!!");
+	auc_i2c_write_buf[0] = FTS_REG_ECC;
+	fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+	/*check sum error, upgrade fail*/
+	if (reg_val[0] != upgrade_ecc) {
+		FTS_ERROR("[UPGRADE]: ecc error : FW=%02x upgrade_ecc=%02x!!",
+				reg_val[0], upgrade_ecc);
+		return -EIO;
+	}
+	FTS_INFO("[UPGRADE]: ecc ok!!");
+
+	/*upgrade success, reset the new FW*/
+	FTS_INFO("[UPGRADE]: reset the new FW!!");
+	auc_i2c_write_buf[0] = 0x07;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(300);
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ft6x36gu_upgrade_with_app_i_file
+ * Brief:  upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ft6x36gu_upgrade_with_app_i_file(struct i2c_client *client)
+{
+	int i_ret = 0;
+	u32 fw_len;
+	u8 *fw_buf;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+	fw_len = g_fw_len;
+	fw_buf = g_fw_file;
+	if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+		return -EIO;
+	}
+
+	i_ret = fts_ft6x36gu_upgrade_use_buf(client, fw_buf, fw_len);
+	if (i_ret != 0)
+		FTS_ERROR("[UPGRADE] upgrade app.i failed");
+	else
+		FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ft6x36gu_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ft6x36gu_upgrade_with_app_bin_file(struct i2c_client *client,
+					char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	u8 *pbt_buf = NULL;
+	int i_ret = 0;
+	bool ecc_ok = false;
+	int fwsize = 0;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+	i_ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (i_ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return i_ret;
+	}
+
+	if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+							fwsize);
+		goto ERROR_BIN;
+	}
+
+	/*check the app.bin invalid or not*/
+	pbt_buf = (u8 *)fw->data;
+	ecc_ok = fts_check_app_bin_valid(pbt_buf);
+
+	if (ecc_ok) {
+		FTS_INFO("[UPGRADE] app.bin ecc ok");
+		i_ret = fts_ft6x36gu_upgrade_use_buf(client, pbt_buf, fw->size);
+		if (i_ret != 0) {
+			FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+			goto ERROR_BIN;
+		} else {
+			FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+		}
+	} else {
+		FTS_ERROR("[UPGRADE] app.bin ecc failed");
+		goto ERROR_BIN;
+	}
+
+ERROR_BIN:
+	release_firmware(fw);
+	return i_ret;
+}
+#endif  /* FT6x36GU */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8006.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8006.c
new file mode 100644
index 0000000..246d2b9
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8006.c
@@ -0,0 +1,895 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft8006.c
+ *
+ * Author:    fupeipei
+ *
+ * Created:    2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (FTS_CHIP_TYPE == _FT8006)
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE           (93 * 1024)
+#define APP_FILE_MIN_SIZE           (8)
+#define APP_FILE_VER_MAPPING        (0x10E)
+#define APP_FILE_VENDORID_MAPPING   (0x10C)
+#define APP_FILE_CHIPID_MAPPING     (0x11E)
+#define CONFIG_START_ADDR           (0xF80)
+#define CONFIG_START_ADDR_LEN       (0x80)
+#define CONFIG_VENDOR_ID_OFFSET     (0x04)
+#define CONFIG_PROJECT_ID_OFFSET    (0x20)
+#define CONFIG_VENDOR_ID_ADDR       (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR      (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+#define LCD_CFG_MAX_SIZE            (4 * 1024)
+#define LCD_CFG_MIN_SIZE            (8)
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ctpm_get_app_i_file_ver(void);
+static int fts_ctpm_get_app_bin_file_ver(char *firmware_name);
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+					char *firmware_name);
+static int fts_ctpm_fw_upgrade_with_lcd_cfg_i_file(struct i2c_client *client);
+static int fts_ctpm_fw_upgrade_with_lcd_cfg_bin_file(struct i2c_client *client,
+					char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+
+	.get_i_file = fts_ctpm_get_i_file,
+	.get_app_bin_file_ver = fts_ctpm_get_app_bin_file_ver,
+	.get_app_i_file_ver = fts_ctpm_get_app_i_file_ver,
+	.upgrade_with_app_i_file = fts_ctpm_fw_upgrade_with_app_i_file,
+	.upgrade_with_app_bin_file = fts_ctpm_fw_upgrade_with_app_bin_file,
+	.upgrade_with_lcd_cfg_i_file = fts_ctpm_fw_upgrade_with_lcd_cfg_i_file,
+	.upgrade_with_lcd_cfg_bin_file =
+				fts_ctpm_fw_upgrade_with_lcd_cfg_bin_file,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ctpm_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ctpm_get_vendor_id_flash(struct i2c_client *client,
+				u8 *vendor_id)
+{
+	bool inbootloader = false;
+	u8 rw_buf[10];
+	int i_ret;
+
+	fts_ctpm_i2c_hid2std(client);
+
+	i_ret = fts_ctpm_start_fw_upgrade(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: send upgrade cmd to FW error!!");
+		return i_ret;
+	}
+
+	/*Enter upgrade mode*/
+	fts_ctpm_i2c_hid2std(client);
+	usleep_range(10000, 20000);
+
+	inbootloader = fts_ctpm_check_run_state(client, FTS_RUN_IN_BOOTLOADER);
+	if (!inbootloader) {
+		FTS_ERROR("[UPGRADE]: not run in bootloader, upgrade fail!!");
+		return -EIO;
+	}
+
+	/*read vendor id*/
+	rw_buf[0] = 0x03;
+	rw_buf[1] = 0x00;
+	rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+	rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+	i_ret = fts_i2c_write(client, rw_buf, 4);
+	/* must wait, otherwise read vendor id wrong */
+	usleep_range(10000, 20000);
+	i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+	if (i_ret < 0)
+		return -EIO;
+	FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+	return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ft5x46_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0   - ok
+ *		 <0 - fail
+ ***********************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid)
+{
+	int ret = 0;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+	u8 vendor_id = 0;
+
+	if (fw_valid)
+		ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+	else
+		ret = fts_ctpm_get_vendor_id_flash(client, &vendor_id);
+	if (ret < 0) {
+		FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+		return ret;
+	}
+	FTS_INFO("[UPGRADE] vendor id tp=%x", vendor_id);
+	FTS_INFO("[UPGRADE] vendor id driver:%x, FTS_VENDOR_ID:%02x %02x %02x",
+		vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+
+	ret = 0;
+	switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+	case FTS_VENDOR_1_ID:
+		g_fw_file = CTPM_FW;
+		g_fw_len = fts_getsize(FW_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+	case FTS_VENDOR_2_ID:
+		g_fw_file = CTPM_FW2;
+		g_fw_len = fts_getsize(FW2_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+	case FTS_VENDOR_3_ID:
+		g_fw_file = CTPM_FW3;
+		g_fw_len = fts_getsize(FW3_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+		break;
+#endif
+	default:
+		FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+		ret = -EIO;
+		break;
+	}
+#else
+	/* (FTS_GET_VENDOR_ID_NUM == 0) */
+	g_fw_file = CTPM_FW;
+	g_fw_len = fts_getsize(FW_SIZE);
+	FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+#endif
+
+	return ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_bin_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_bin_file_ver(char *firmware_name)
+{
+	u8 *pbt_buf = NULL;
+	int fwsize = 0;
+	int fw_ver = 0;
+
+	FTS_FUNC_ENTER();
+
+	fwsize = fts_GetFirmwareSize(firmware_name);
+	if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+		return -EIO;
+	}
+
+	pbt_buf = kmalloc(fwsize + 1, GFP_KERNEL);
+	if (fts_ReadFirmware(firmware_name, pbt_buf)) {
+		FTS_ERROR("[UPGRADE]: request_firmware failed!!");
+		kfree(pbt_buf);
+		return -EIO;
+	}
+
+	fw_ver = pbt_buf[APP_FILE_VER_MAPPING];
+
+	kfree(pbt_buf);
+	FTS_FUNC_EXIT();
+
+	return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_i_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_i_file_ver(void)
+{
+	int fwsize = g_fw_len;
+
+	if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+		return 0;
+	}
+
+	return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_use_buf(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length)
+{
+	u8 reg_val[4] = {0};
+	u32 i = 0;
+	u32 packet_number;
+	u32 j = 0;
+	u32 temp;
+	u32 length;
+	u8 packet_buf[FTS_PACKET_LENGTH + 6];
+	u8 auc_i2c_write_buf[10];
+	u8 upgrade_ecc;
+	int i_ret = 0;
+	bool inbootloader = false;
+
+	fts_ctpm_i2c_hid2std(client);
+
+	i_ret = fts_ctpm_start_fw_upgrade(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: send upgrade cmd to FW error!!");
+		return i_ret;
+	}
+
+	/*Enter upgrade mode*/
+	fts_ctpm_i2c_hid2std(client);
+	usleep_range(10000, 20000);
+
+	inbootloader = fts_ctpm_check_run_state(client, FTS_RUN_IN_BOOTLOADER);
+	if (!inbootloader) {
+		FTS_ERROR("[UPGRADE]: not run in bootloader, upgrade fail!!");
+		return -EIO;
+	}
+
+	/*send upgrade type to reg 0x09: 0x0B: upgrade; 0x0A: download*/
+	auc_i2c_write_buf[0] = 0x09;
+	auc_i2c_write_buf[1] = 0x0B;
+	fts_i2c_write(client, auc_i2c_write_buf, 2);
+
+	/*
+	 * All.bin <= 128K
+	 * APP.bin <= 94K
+	 * LCD_CFG <= 4K
+	 */
+	auc_i2c_write_buf[0] = 0xB0;
+	auc_i2c_write_buf[1] = (u8) ((dw_length >> 16) & 0xFF);
+	auc_i2c_write_buf[2] = (u8) ((dw_length >> 8) & 0xFF);
+	auc_i2c_write_buf[3] = (u8) (dw_length & 0xFF);
+	fts_i2c_write(client, auc_i2c_write_buf, 4);
+
+
+	/*erase the app erea in flash*/
+	i_ret = fts_ctpm_erase_flash(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: erase flash error!!");
+		return i_ret;
+	}
+
+	/*write FW to ctpm flash*/
+	upgrade_ecc = 0;
+	FTS_DEBUG("[UPGRADE]: write FW to ctpm flash!!");
+	temp = 0;
+	packet_number = (dw_length) / FTS_PACKET_LENGTH;
+	packet_buf[0] = FTS_FW_WRITE_CMD;
+
+	for (j = 0; j < packet_number; j++) {
+		temp = 0x5000 + j * FTS_PACKET_LENGTH;
+		packet_buf[1] = (u8) (temp >> 16);
+		packet_buf[2] = (u8) (temp >> 8);
+		packet_buf[3] = (u8) temp;
+		length = FTS_PACKET_LENGTH;
+		packet_buf[4] = (u8) (length >> 8);
+		packet_buf[5] = (u8) length;
+		for (i = 0; i < FTS_PACKET_LENGTH; i++) {
+			packet_buf[6 + i] = pbt_buf[j * FTS_PACKET_LENGTH + i];
+			upgrade_ecc ^= packet_buf[6 + i];
+		}
+		fts_i2c_write(client, packet_buf, FTS_PACKET_LENGTH + 6);
+		/* usleep_range(1000, 2000); */
+
+		for (i = 0; i < 30; i++) {
+			auc_i2c_write_buf[0] = 0x6a;
+			reg_val[0] = reg_val[1] = 0x00;
+			fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+			if ((j + 0x1000 + (0x5000/FTS_PACKET_LENGTH))
+					== (((reg_val[0]) << 8) | reg_val[1]))
+				break;
+
+			if (i > 15) {
+				usleep_range(1000, 2000);
+				FTS_DEBUG("[UPGRADE]: write flash:host :%x!!",
+					(j + 0x1000
+					 + (0x5000/FTS_PACKET_LENGTH)));
+				FTS_DEBUG("[UPGRADE]: write flash:status :%x!!",
+					(((reg_val[0]) << 8) | reg_val[1]));
+			}
+			/* usleep_range(1000, 2000); */
+			fts_ctpm_upgrade_delay(10000);
+		}
+	}
+
+	if ((dw_length) % FTS_PACKET_LENGTH > 0) {
+		temp = 0x5000 + packet_number * FTS_PACKET_LENGTH;
+		packet_buf[1] = (u8) (temp >> 16);
+		packet_buf[2] = (u8) (temp >> 8);
+		packet_buf[3] = (u8) temp;
+		temp = (dw_length) % FTS_PACKET_LENGTH;
+		packet_buf[4] = (u8) (temp >> 8);
+		packet_buf[5] = (u8) temp;
+		for (i = 0; i < temp; i++) {
+			packet_buf[6 + i] = pbt_buf[packet_number
+						* FTS_PACKET_LENGTH + i];
+			upgrade_ecc ^= packet_buf[6 + i];
+		}
+		fts_i2c_write(client, packet_buf, temp + 6);
+		/* usleep_range(1000, 2000); */
+
+		for (i = 0; i < 30; i++) {
+			auc_i2c_write_buf[0] = 0x6a;
+			reg_val[0] = reg_val[1] = 0x00;
+			fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+			if ((0x1000 + ((0x5000 + packet_number
+				* FTS_PACKET_LENGTH)/((dw_length)
+				% FTS_PACKET_LENGTH)))
+				== (((reg_val[0]) << 8) | reg_val[1]))
+				break;
+
+			if (i > 15) {
+				usleep_range(1000, 2000);
+				FTS_DEBUG("[UPGRADE]: write flash:host :%x!!",
+					(j + 0x1000
+					 + (0x5000/FTS_PACKET_LENGTH)));
+				FTS_DEBUG("[UPGRADE]: write flash:status :%x!!",
+					(((reg_val[0]) << 8) | reg_val[1]));
+			}
+			/* usleep_range(1000, 2000); */
+			fts_ctpm_upgrade_delay(10000);
+		}
+	}
+
+	msleep(50);
+
+	/*********Step 6: read out checksum***********************/
+	/*send the opration head */
+	FTS_DEBUG("[UPGRADE]: read out checksum!!");
+	auc_i2c_write_buf[0] = 0x64;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(300);
+
+	temp = 0x5000;
+	auc_i2c_write_buf[0] = 0x65;
+	auc_i2c_write_buf[1] = (u8)(temp >> 16);
+	auc_i2c_write_buf[2] = (u8)(temp >> 8);
+	auc_i2c_write_buf[3] = (u8)(temp);
+	temp = (64*1024-1);
+	auc_i2c_write_buf[4] = (u8)(temp >> 8);
+	auc_i2c_write_buf[5] = (u8)(temp);
+	i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+	msleep(dw_length/256);
+
+	temp = (0x5000+(64*1024-1));
+	auc_i2c_write_buf[0] = 0x65;
+	auc_i2c_write_buf[1] = (u8)(temp >> 16);
+	auc_i2c_write_buf[2] = (u8)(temp >> 8);
+	auc_i2c_write_buf[3] = (u8)(temp);
+	temp = (dw_length-(64*1024-1));
+	auc_i2c_write_buf[4] = (u8)(temp >> 8);
+	auc_i2c_write_buf[5] = (u8)(temp);
+	i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+	msleep(dw_length/256);
+
+	for (i = 0; i < 100; i++) {
+		auc_i2c_write_buf[0] = 0x6a;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+		if (0xF0 == reg_val[0] && 0x55 == reg_val[1]) {
+			FTS_DEBUG("[UPGRADE]: reg_val[0]=%02x reg_val[0]=%02x!",
+					reg_val[0], reg_val[1]);
+			break;
+		}
+		usleep_range(1000, 2000);
+
+	}
+	auc_i2c_write_buf[0] = 0x66;
+	fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+	if (reg_val[0] != upgrade_ecc) {
+		FTS_ERROR("[UPGRADE]: ecc error! FW=%02x upgrade_ecc=%02x!!",
+				reg_val[0], upgrade_ecc);
+		return -EIO;
+	}
+	FTS_DEBUG("[UPGRADE]: checksum %x %x!!", reg_val[0], upgrade_ecc);
+
+	FTS_DEBUG("[UPGRADE]: reset the new FW!!");
+	auc_i2c_write_buf[0] = FTS_REG_RESET_FW;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(1000);
+
+	fts_ctpm_i2c_hid2std(client);
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_lcd_cfg_upgrade_use_buf(struct i2c_client *client,
+				u8 *pbt_buf, u32 dw_length)
+{
+	u8 reg_val[4] = {0};
+	u8 cfg_backup[CONFIG_START_ADDR_LEN+1] = { 0 };
+	u32 i = 0;
+	u32 packet_number;
+	u32 j = 0;
+	u32 temp;
+	u32 length;
+	u8 packet_buf[FTS_PACKET_LENGTH + 6];
+	u8 auc_i2c_write_buf[10];
+	u8 upgrade_ecc;
+	int i_ret;
+
+	fts_ctpm_i2c_hid2std(client);
+
+	for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+		/*write 0xaa to register FTS_RST_CMD_REG1 */
+		fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_AA);
+		usleep_range(10000, 20000);
+
+		/*write 0x55 to register FTS_RST_CMD_REG1*/
+		fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_55);
+		msleep(200);
+
+		/*Enter upgrade mode*/
+		fts_ctpm_i2c_hid2std(client);
+
+		usleep_range(10000, 20000);
+		auc_i2c_write_buf[0] = FTS_UPGRADE_55;
+		auc_i2c_write_buf[1] = FTS_UPGRADE_AA;
+		i_ret = fts_i2c_write(client, auc_i2c_write_buf, 2);
+		if (i_ret < 0) {
+			FTS_ERROR("[UPGRADE]: failed writing  0x55 and 0xaa!!");
+			continue;
+		}
+
+		/*check run in bootloader or not*/
+		usleep_range(1000, 2000);
+		auc_i2c_write_buf[0] = FTS_READ_ID_REG;
+		auc_i2c_write_buf[1] = auc_i2c_write_buf[2]
+					= auc_i2c_write_buf[3] = 0x00;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 4, reg_val, 2);
+		FTS_DEBUG("[UPGRADE]:ID1 = 0x%x,ID2 = 0x%x!!",
+					reg_val[0], reg_val[1]);
+
+		if (reg_val[0] == chip_types.bootloader_idh
+			&& reg_val[1] == chip_types.bootloader_idl) {
+			FTS_DEBUG("[UPGRADE]: read bootloader id ok!!");
+			break;
+		}
+		FTS_DEBUG("[UPGRADE]: read bootloader id fail!!");
+	}
+
+	if (i >= FTS_UPGRADE_LOOP)
+		return -EIO;
+
+	/* Backup FW configuratin area */
+	reg_val[0] = 0x03;
+	reg_val[1] = (u8)((CONFIG_START_ADDR-1) >> 16);
+	reg_val[2] = (u8)((CONFIG_START_ADDR-1) >> 8);
+	reg_val[3] = (u8)((CONFIG_START_ADDR-1));
+	i_ret = fts_i2c_read(client, reg_val, 4,
+			cfg_backup, CONFIG_START_ADDR_LEN+1);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE] Read Config area error, don't upgrade");
+		return -EIO;
+	}
+
+	/*send upgrade type to reg 0x09: 0x0B: upgrade; 0x0A: download*/
+	auc_i2c_write_buf[0] = 0x09;
+	auc_i2c_write_buf[1] = 0x0C;
+	fts_i2c_write(client, auc_i2c_write_buf, 2);
+
+	/*Step 4:erase app and panel paramenter area*/
+	FTS_DEBUG("[UPGRADE]: erase app and panel paramenter area!!");
+	auc_i2c_write_buf[0] = FTS_ERASE_APP_REG;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(1000);
+
+	for (i = 0; i < 15; i++) {
+		auc_i2c_write_buf[0] = 0x6a;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+		if (0xF0 == reg_val[0] && 0xAA == reg_val[1])
+			break;
+		msleep(50);
+	}
+	FTS_DEBUG("[UPGRADE]: erase app area reg_val = %x %x!!",
+					reg_val[0], reg_val[1]);
+
+	auc_i2c_write_buf[0] = 0xB0;
+	auc_i2c_write_buf[1] = 0;
+	auc_i2c_write_buf[2] = (u8) ((dw_length >> 8) & 0xFF);
+	auc_i2c_write_buf[3] = (u8) (dw_length & 0xFF);
+	fts_i2c_write(client, auc_i2c_write_buf, 4);
+
+	/*write FW to ctpm flash*/
+	upgrade_ecc = 0;
+	FTS_DEBUG("[UPGRADE]: write FW to ctpm flash!!");
+	temp = 0;
+	packet_number = (dw_length) / FTS_PACKET_LENGTH;
+	packet_buf[0] = FTS_FW_WRITE_CMD;
+	packet_buf[1] = 0;
+	for (j = 0; j < packet_number; j++) {
+		temp = j * FTS_PACKET_LENGTH;
+		packet_buf[2] = (u8) (temp >> 8);
+		packet_buf[3] = (u8) temp;
+		length = FTS_PACKET_LENGTH;
+		packet_buf[4] = (u8) (length >> 8);
+		packet_buf[5] = (u8) length;
+		for (i = 0; i < FTS_PACKET_LENGTH; i++) {
+			packet_buf[6 + i] = pbt_buf[j * FTS_PACKET_LENGTH + i];
+			upgrade_ecc ^= packet_buf[6 + i];
+		}
+		fts_i2c_write(client, packet_buf, FTS_PACKET_LENGTH + 6);
+		/* usleep_range(1000, 2000); */
+
+		for (i = 0; i < 30; i++) {
+			auc_i2c_write_buf[0] = 0x6a;
+			reg_val[0] = reg_val[1] = 0x00;
+			fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+			if ((j + 0x1000) == (((reg_val[0]) << 8) | reg_val[1]))
+				break;
+
+			if (i > 15) {
+				usleep_range(1000, 2000);
+				FTS_DEBUG("[UPGRADE]: write flash:host : %x!",
+					(j + 0x1000 +
+					 (0x5000/FTS_PACKET_LENGTH)),
+					(((reg_val[0]) << 8) | reg_val[1]));
+				FTS_DEBUG("[UPGRADE]: write flash:status : %x!",
+					(((reg_val[0]) << 8) | reg_val[1]));
+			}
+			/* usleep_range(1000, 2000); */
+			fts_ctpm_upgrade_delay(10000);
+		}
+	}
+
+	if ((dw_length) % FTS_PACKET_LENGTH > 0) {
+		temp = packet_number * FTS_PACKET_LENGTH;
+		packet_buf[2] = (u8) (temp >> 8);
+		packet_buf[3] = (u8) temp;
+		temp = (dw_length) % FTS_PACKET_LENGTH;
+		packet_buf[4] = (u8) (temp >> 8);
+		packet_buf[5] = (u8) temp;
+		for (i = 0; i < temp; i++) {
+			packet_buf[6 + i] = pbt_buf[packet_number
+						* FTS_PACKET_LENGTH + i];
+			upgrade_ecc ^= packet_buf[6 + i];
+		}
+		fts_i2c_write(client, packet_buf, temp + 6);
+		/* usleep_range(1000, 2000); */
+
+		for (i = 0; i < 30; i++) {
+			auc_i2c_write_buf[0] = 0x6a;
+			reg_val[0] = reg_val[1] = 0x00;
+			fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+			if ((0x1000 + ((packet_number * FTS_PACKET_LENGTH)
+				/((dw_length) % FTS_PACKET_LENGTH)))
+				== (((reg_val[0]) << 8) | reg_val[1]))
+				break;
+
+			if (i > 15) {
+				usleep_range(1000, 2000);
+				FTS_DEBUG("[UPGRADE]: write flash:host : %x!",
+					(j + 0x1000 +
+					 (0x5000/FTS_PACKET_LENGTH)),
+					(((reg_val[0]) << 8) | reg_val[1]));
+				FTS_DEBUG("[UPGRADE]: write flash:status : %x!",
+					(((reg_val[0]) << 8) | reg_val[1]));
+			}
+			/* usleep_range(1000, 2000); */
+			fts_ctpm_upgrade_delay(10000);
+		}
+	}
+
+	/* Write Back FW configuratin area */
+	packet_buf[0] = FTS_FW_WRITE_CMD;
+	packet_buf[1] = (u8)(CONFIG_START_ADDR >> 16);
+	packet_buf[2] = (u8)(CONFIG_START_ADDR >> 8);
+	packet_buf[3] = (u8)(CONFIG_START_ADDR);
+	packet_buf[4] = (u8)(CONFIG_START_ADDR_LEN >> 8);
+	packet_buf[5] = (u8)(CONFIG_START_ADDR_LEN);
+	memcpy(&packet_buf[6], &cfg_backup[1], CONFIG_START_ADDR_LEN);
+	i_ret = fts_i2c_write(client, packet_buf, CONFIG_START_ADDR_LEN + 6);
+	if (i_ret < 0)
+		FTS_ERROR("[UPGRADE] Write Configuration area error");
+
+	msleep(50);
+
+	/*********Step 6: read out checksum***********************/
+	/*send the opration head */
+	FTS_DEBUG("[UPGRADE]: read out checksum!!");
+	auc_i2c_write_buf[0] = 0x64;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(300);
+
+	temp = 0x00;
+	auc_i2c_write_buf[0] = 0x65;
+	auc_i2c_write_buf[1] = 0;
+	auc_i2c_write_buf[2] = (u8)(temp >> 8);
+	auc_i2c_write_buf[3] = (u8)(temp);
+	temp = dw_length;
+	auc_i2c_write_buf[4] = (u8)(temp >> 8);
+	auc_i2c_write_buf[5] = (u8)(temp);
+	i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+	msleep(dw_length/256);
+
+	for (i = 0; i < 100; i++) {
+		auc_i2c_write_buf[0] = 0x6a;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+		if (0xF0 == reg_val[0] && 0x55 == reg_val[1]) {
+			FTS_DEBUG("[UPGRADE]:reg_val[0]=%02x reg_val[0]=%02x!",
+						reg_val[0], reg_val[1]);
+			break;
+		}
+		usleep_range(1000, 2000);
+
+	}
+	auc_i2c_write_buf[0] = 0x66;
+	fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+	if (reg_val[0] != upgrade_ecc) {
+		FTS_ERROR("[UPGRADE]: ecc error! FW=%02x upgrade_ecc=%02x!!",
+					reg_val[0], upgrade_ecc);
+		return -EIO;
+	}
+	FTS_DEBUG("[UPGRADE]: checksum %x %x!!", reg_val[0], upgrade_ecc);
+
+	FTS_DEBUG("[UPGRADE]: reset the new FW!!");
+	auc_i2c_write_buf[0] = FTS_REG_RESET_FW;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(1000);
+
+	fts_ctpm_i2c_hid2std(client);
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_i_file
+ * Brief:  upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client)
+{
+	int i_ret = 0;
+	u32 fw_len;
+	u8 *fw_buf;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+	fw_len = g_fw_len;
+	fw_buf = g_fw_file;
+	if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+		return -EIO;
+	}
+
+	i_ret = fts_ctpm_fw_upgrade_use_buf(client, fw_buf, fw_len);
+	if (i_ret != 0)
+		FTS_ERROR("[UPGRADE] upgrade app.i failed");
+	else
+		FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+					char *firmware_name)
+{
+	u8 *pbt_buf = NULL;
+	int i_ret = 0;
+	bool ecc_ok = false;
+	int fwsize = 0;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+	fwsize = fts_GetFirmwareSize(firmware_name);
+	if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+					fwsize);
+		return -EIO;
+	}
+
+	pbt_buf = kmalloc(fwsize + 1, GFP_KERNEL);
+	if (pbt_buf == NULL) {
+		FTS_ERROR(" malloc pbt_buf failed ");
+		goto ERROR_BIN;
+	}
+
+	if (fts_ReadFirmware(firmware_name, pbt_buf)) {
+		FTS_ERROR("[UPGRADE]: request_firmware failed!!");
+		goto ERROR_BIN;
+	}
+
+	/*check the app.bin invalid or not*/
+	ecc_ok = fts_check_app_bin_valid_idc(pbt_buf);
+
+	if (ecc_ok) {
+		FTS_INFO("[UPGRADE] app.bin ecc ok");
+		i_ret = fts_ctpm_fw_upgrade_use_buf(client, pbt_buf, fwsize);
+		if (i_ret != 0) {
+			FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+			goto ERROR_BIN;
+		} else {
+			FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+		}
+	} else {
+		FTS_ERROR("[UPGRADE] app.bin ecc failed");
+		goto ERROR_BIN;
+	}
+
+	kfree(pbt_buf);
+	return i_ret;
+ERROR_BIN:
+	kfree(pbt_buf);
+	return -EIO;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_lcd_cfg_i_file
+ * Brief:  upgrade with *.i file
+ * Input: i2c info
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_lcd_cfg_i_file(struct i2c_client *client)
+{
+	int i_ret = 0;
+	int lcd_cfg_size = 0;
+
+	FTS_DEBUG("[UPGRADE]**********upgrade with lcd_cfg.i**********");
+
+	lcd_cfg_size = fts_getsize(LCD_CFG_SIZE);
+	if (lcd_cfg_size < LCD_CFG_MIN_SIZE
+		|| lcd_cfg_size > LCD_CFG_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE] lcd_cfg.i length(%x) error", lcd_cfg_size);
+		return -EIO;
+	}
+
+	/*FW upgrade*/
+	i_ret = fts_ctpm_lcd_cfg_upgrade_use_buf(client,
+					CTPM_LCD_CFG, lcd_cfg_size);
+	if (i_ret != 0)
+		FTS_ERROR("[UPGRADE] lcd_cfg.i upgrade fail, ret=%d", i_ret);
+	else
+		FTS_INFO("[UPGRADE] lcd_cfg.i upgrade succeed");
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_lcd_cfg_bin_file
+ * Brief:  upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_lcd_cfg_bin_file(struct i2c_client *client,
+						char *firmware_name)
+{
+	u8 *pbt_buf = NULL;
+	int i_ret = 0;
+	bool ecc_ok = false;
+	int lcd_cfg_size = fts_GetFirmwareSize(firmware_name);
+
+	FTS_DEBUG("[UPGRADE]**********upgrade with lcd_cfg.bin**********");
+
+	if (lcd_cfg_size < LCD_CFG_MIN_SIZE
+			|| lcd_cfg_size > LCD_CFG_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE] lcd_cfg.bin length(%x) error",
+				lcd_cfg_size);
+		return -EIO;
+	}
+
+	pbt_buf = kmalloc(lcd_cfg_size + 1, GFP_KERNEL);
+	if (fts_ReadFirmware(firmware_name, pbt_buf)) {
+		FTS_ERROR("[UPGRADE]: request_firmware failed!!");
+		goto ERROR_LCD_CFG_BIN;
+	}
+
+	/*check the app.bin invalid or not*/
+	ecc_ok = 1;
+
+	if (ecc_ok) {
+		FTS_INFO("[UPGRADE]: lcd_cfg.bin ecc ok!!");
+		i_ret = fts_ctpm_lcd_cfg_upgrade_use_buf(client,
+						pbt_buf, lcd_cfg_size);
+		if (i_ret != 0) {
+			FTS_ERROR("[UPGRADE]: lcd_cfg.bin upgrade failed!!");
+			goto ERROR_LCD_CFG_BIN;
+		} else {
+			FTS_INFO("[UPGRADE]: lcd_cfg.bin upgrade succeed!!");
+		}
+	} else {
+		FTS_ERROR("[UPGRADE]: lcd_cfg.bin ecc failed!!");
+
+	}
+
+	kfree(pbt_buf);
+	return i_ret;
+
+ERROR_LCD_CFG_BIN:
+	kfree(pbt_buf);
+	return -EIO;
+}
+#endif  /* #if (FTS_CHIP_TYPE == _FT8006) */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8606.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8606.c
new file mode 100644
index 0000000..3589ba5
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8606.c
@@ -0,0 +1,587 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft8606.c
+ *
+ * Author:    fupeipei
+ *
+ * Created:    2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (FTS_CHIP_TYPE == _FT8606)
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE           (64 * 1024)
+#define APP_FILE_MIN_SIZE           (8)
+#define APP_FILE_VER_MAPPING        (0x10A)
+#define APP_FILE_VENDORID_MAPPING   (0x108)
+#define APP_FILE_CHIPID_MAPPING     (0x11E)
+#define CONFIG_START_ADDR           (0x0780)
+#define CONFIG_VENDOR_ID_OFFSET     (0x04)
+#define CONFIG_PROJECT_ID_OFFSET    (0x20)
+#define CONFIG_VENDOR_ID_ADDR       (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR      (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+#define AL2_FCS_COEF    ((1 << 7) + (1 << 6) + (1 << 5))
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ctpm_get_app_i_file_ver(void);
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name);
+static int fts_ctpm_write_pram(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length);
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+			char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+	.get_i_file = fts_ctpm_get_i_file,
+	.get_app_bin_file_ver = fts_ctpm_get_app_bin_file_ver,
+	.get_app_i_file_ver = fts_ctpm_get_app_i_file_ver,
+	.upgrade_with_app_i_file = fts_ctpm_fw_upgrade_with_app_i_file,
+	.upgrade_with_app_bin_file = fts_ctpm_fw_upgrade_with_app_bin_file,
+	.upgrade_with_lcd_cfg_i_file = NULL,
+	.upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ctpm_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ctpm_get_vendor_id_flash(struct i2c_client *client,
+				u8 *vendor_id)
+{
+	u8 rw_buf[10];
+	int i_ret;
+	int fw_len;
+	bool inpram = false;
+
+	FTS_FUNC_ENTER();
+
+	/*write pramboot*/
+	fw_len = fts_getsize(PRAMBOOT_SIZE);
+	FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+	i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+	if (i_ret != 0) {
+		FTS_ERROR("[UPGRADE]: write pram failed!!");
+		return -EIO;
+	}
+
+	/*check run in pramboot or not!
+	 *if not rum in pramboot, cannot upgrade
+	 */
+	inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+	if (!inpram) {
+		FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+		return -EIO;
+	}
+
+	/*read vendor id*/
+	rw_buf[0] = 0x03;
+	rw_buf[1] = 0x00;
+	rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+	rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+	i_ret = fts_i2c_write(client, rw_buf, 4);
+	/* must wait, otherwise read vendor id wrong */
+	usleep_range(10000, 20000);
+	i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+	if (i_ret < 0)
+		return -EIO;
+	FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+	return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ctpm_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0   - ok
+ *		 <0 - fail
+ ***********************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid)
+{
+	int ret = 0;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+	u8 vendor_id = 0;
+
+	if (fw_valid) {
+		ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+	} else {
+		ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+		if ((ret < 0) || (vendor_id == 0xEF) || (vendor_id == 0xED)) {
+			/* 8736 can't read vendor id from A8 command */
+			ret = fts_ctpm_get_vendor_id_flash(client, &vendor_id);
+		}
+	}
+	if (ret < 0) {
+		FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+		return ret;
+	}
+	FTS_INFO("[UPGRADE] vendor id tp=%x", vendor_id);
+	FTS_INFO("[UPGRADE] vendor id driver:%x, FTS_VENDOR_ID:%02x %02x %02x",
+		 vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+
+	ret = 0;
+	switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+	case FTS_VENDOR_1_ID:
+		g_fw_file = CTPM_FW;
+		g_fw_len = fts_getsize(FW_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+	case FTS_VENDOR_2_ID:
+		g_fw_file = CTPM_FW2;
+		g_fw_len = fts_getsize(FW2_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+	case FTS_VENDOR_3_ID:
+		g_fw_file = CTPM_FW3;
+		g_fw_len = fts_getsize(FW3_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+		break;
+#endif
+	default:
+		FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+		ret = -EIO;
+		break;
+	}
+#else
+	/* (FTS_GET_VENDOR_ID_NUM == 0) */
+	g_fw_file = CTPM_FW;
+	g_fw_len = fts_getsize(FW_SIZE);
+	FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+#endif
+
+	return ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_bin_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	int fw_ver = 0;
+	int ret;
+
+	FTS_FUNC_ENTER();
+
+	ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return ret;
+	}
+
+	if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE)
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw->size);
+	else
+		fw_ver = fw->data[APP_FILE_VER_MAPPING];
+
+	release_firmware(fw);
+	FTS_FUNC_EXIT();
+
+	return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_i_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_i_file_ver(void)
+{
+	int fwsize = g_fw_len;
+
+	if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+		return 0;
+	}
+
+	return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_pram
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_pram(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length)
+{
+	int i_ret;
+	bool inrom = false;
+
+	FTS_FUNC_ENTER();
+
+	/*check the length of the pramboot*/
+	if (dw_length > APP_FILE_MAX_SIZE || dw_length < APP_FILE_MIN_SIZE) {
+		FTS_ERROR("[UPGRADE] pramboot length(%d) fail", dw_length);
+		return -EIO;
+	}
+
+	/*send comond to FW, reset and start write pramboot*/
+	i_ret = fts_ctpm_start_fw_upgrade(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: send upgrade cmd to FW error!!");
+		return i_ret;
+	}
+
+	/*check run in rom or not! if run in rom, will write pramboot*/
+	inrom = fts_ctpm_check_run_state(client, FTS_RUN_IN_ROM);
+	if (!inrom) {
+		FTS_ERROR("[UPGRADE]: not run in rom, write pramboot fail!!");
+		return -EIO;
+	}
+
+	/*write pramboot to pram*/
+	i_ret = fts_ctpm_write_pramboot_for_idc(client,
+					dw_length, aucFW_PRAM_BOOT);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: write pramboot fail!!");
+		return i_ret;
+	}
+
+	/*read out checksum*/
+	i_ret = fts_ctpm_pramboot_ecc(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: write pramboot ecc error!!");
+		return i_ret;
+	}
+
+	/*start pram*/
+	fts_ctpm_start_pramboot(client);
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_app
+ * Brief:  fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_app(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length)
+{
+	u32 temp;
+	int i_ret;
+	bool inpram = false;
+
+	FTS_FUNC_ENTER();
+
+	/*check run in pramboot or not!
+	 *if not rum in pramboot, can not upgrade
+	 */
+	inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+	if (!inpram) {
+		FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+		return -EIO;
+	}
+
+	/*upgrade init*/
+	i_ret = fts_ctpm_upgrade_idc_init(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: upgrade init error, upgrade fail!!");
+		return i_ret;
+	}
+
+	/*erase the app erea in flash*/
+	i_ret = fts_ctpm_erase_flash(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: erase flash error!!");
+		return i_ret;
+	}
+
+	/*start to write app*/
+	i_ret = fts_ctpm_write_app_for_idc(client, dw_length, pbt_buf);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: write app error!!");
+		return i_ret;
+	}
+
+	/*read check sum*/
+	temp = 0x1000;
+	i_ret = fts_ctpm_upgrade_ecc(client, temp, dw_length);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: ecc error!!");
+		return i_ret;
+	}
+
+	/*upgrade success, reset the FW*/
+	fts_ctpm_rom_or_pram_reset(client);
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/*****************************************************************************
+ *   Name: ecc_calc
+ *  Brief:
+ *  Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static u8 ecc_calc(u8 *pbt_buf, u16 start, u16 length)
+{
+	u8 cFcs = 0;
+	u16 i, j;
+
+	for (i = 0; i < length; i++) {
+		cFcs ^= pbt_buf[start++];
+		for (j = 0; j < 8; j++) {
+			if (cFcs & 1)
+				cFcs = (u8)((cFcs >> 1) ^ AL2_FCS_COEF);
+			else
+				cFcs >>= 1;
+		}
+	}
+	return cFcs;
+}
+
+
+/*****************************************************************************
+ * Name: fts_8606_check_app_bin_valid
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static bool fts_8606_check_app_bin_valid(u8 *pbt_buf)
+{
+	u8 ecc1;
+	u8 ecc2;
+	u8 ecc3;
+	u8 ecc4;
+	u16 len1;
+	u16 len2;
+	u8 cal_ecc1;
+	u8 cal_ecc2;
+	u16 usAddrInfo;
+
+	/* 1. First Byte */
+	if (pbt_buf[0] != 0x02) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- the first byte(%x) error",
+							pbt_buf[0]);
+		return false;
+	}
+
+	usAddrInfo = 0x100;
+
+	/* 2.len */
+	len1  = pbt_buf[usAddrInfo++] << 8;
+	len1 += pbt_buf[usAddrInfo++];
+
+	len2  = pbt_buf[usAddrInfo++] << 8;
+	len2 += pbt_buf[usAddrInfo++];
+
+	if ((len1 + len2) != 0xFFFF) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- LENGTH(%04x) XOR error",
+							len1);
+		return false;
+	}
+
+	/* 3.ecc */
+	ecc1 = pbt_buf[usAddrInfo++];
+	ecc2 = pbt_buf[usAddrInfo++];
+	ecc3 = pbt_buf[usAddrInfo++];
+	ecc4 = pbt_buf[usAddrInfo++];
+
+	if (((ecc1 + ecc2) != 0xFF) || ((ecc3 + ecc4) != 0xFF)) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC(%x %x) XOR error",
+							ecc1, ecc2);
+		return false;
+	}
+
+	cal_ecc1 = ecc_calc(pbt_buf, 0x0, 0x100);
+	cal_ecc2 = ecc_calc(pbt_buf, 0x100 + 0x20, len1 - (0x100 + 0x20));
+	if ((ecc1 != cal_ecc1) || (ecc3 != cal_ecc2)) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- ECC calc error");
+		return false;
+	}
+	return true;
+}
+
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ *		 success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_use_buf(struct i2c_client *client,
+				u8 *pbt_buf, u32 fwsize)
+{
+	int i_ret = 0;
+	int fw_len;
+
+	FTS_FUNC_ENTER();
+
+	/*write pramboot*/
+	fw_len = fts_getsize(PRAMBOOT_SIZE);
+	FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+	i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+	if (i_ret != 0) {
+		FTS_ERROR("[UPGRADE]: write pram failed!!");
+		return -EIO;
+	}
+
+	/*write app*/
+	i_ret =  fts_ctpm_write_app(client, pbt_buf, fwsize);
+
+	FTS_FUNC_EXIT();
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_i_file
+ * Brief:  upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client)
+{
+	int i_ret = 0;
+	u32 fw_len;
+	u8 *fw_buf;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+	fw_len = g_fw_len;
+	fw_buf = g_fw_file;
+	if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+		return -EIO;
+	}
+
+	i_ret = fts_ctpm_fw_upgrade_use_buf(client, fw_buf, fw_len);
+	if (i_ret != 0)
+		FTS_ERROR("[UPGRADE] upgrade app.i failed");
+	else
+		FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+					char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	u8 *pbt_buf = NULL;
+	int i_ret = 0;
+	bool ecc_ok = false;
+	int fwsize = 0;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+	i_ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (i_ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return i_ret;
+	}
+
+	if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+							fwsize);
+		goto ERROR_BIN;
+	}
+
+	pbt_buf = (u8 *)fw->data;
+	if ((pbt_buf[APP_FILE_CHIPID_MAPPING] != chip_types.pramboot_idh)
+		|| (pbt_buf[APP_FILE_CHIPID_MAPPING+1]
+			!= chip_types.pramboot_idl)) {
+		FTS_ERROR("[UPGRADE]: chip id error, app.bin upgrade failed!");
+		goto ERROR_BIN;
+	}
+
+	/*check the app.bin invalid or not*/
+	ecc_ok = fts_8606_check_app_bin_valid(pbt_buf);
+
+	if (ecc_ok) {
+		FTS_INFO("[UPGRADE] app.bin ecc ok");
+		i_ret = fts_ctpm_fw_upgrade_use_buf(client, pbt_buf, fw->size);
+		if (i_ret != 0) {
+			FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+			goto ERROR_BIN;
+		} else {
+			FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+		}
+	} else {
+		FTS_ERROR("[UPGRADE] app.bin ecc failed");
+		goto ERROR_BIN;
+	}
+
+ERROR_BIN:
+	release_firmware(fw);
+	return i_ret;
+}
+#endif  /* #if (FTS_CHIP_TYPE == _FT8606) */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8607.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8607.c
new file mode 100644
index 0000000..604edbd
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8607.c
@@ -0,0 +1,499 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft8607.c
+ *
+ * Author:    fupeipei
+ *
+ * Created:    2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (FTS_CHIP_TYPE == _FT8607)
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE           (64 * 1024)
+#define APP_FILE_MIN_SIZE           (8)
+#define APP_FILE_VER_MAPPING        (0x10E)
+#define APP_FILE_VENDORID_MAPPING   (0x10C)
+#define APP_FILE_CHIPID_MAPPING     (0x11E)
+#define CONFIG_START_ADDR           (0x0780)
+#define CONFIG_VENDOR_ID_OFFSET     (0x04)
+#define CONFIG_PROJECT_ID_OFFSET    (0x20)
+#define CONFIG_VENDOR_ID_ADDR       (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR      (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ctpm_get_app_i_file_ver(void);
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name);
+static int fts_ctpm_write_pram(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length);
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+			char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+	.get_i_file = fts_ctpm_get_i_file,
+	.get_app_bin_file_ver = fts_ctpm_get_app_bin_file_ver,
+	.get_app_i_file_ver = fts_ctpm_get_app_i_file_ver,
+	.upgrade_with_app_i_file = fts_ctpm_fw_upgrade_with_app_i_file,
+	.upgrade_with_app_bin_file = fts_ctpm_fw_upgrade_with_app_bin_file,
+	.upgrade_with_lcd_cfg_i_file = NULL,
+	.upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ctpm_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ctpm_get_vendor_id_flash(struct i2c_client *client,
+				u8 *vendor_id)
+{
+	u8 rw_buf[10];
+	int i_ret;
+	int fw_len;
+	bool inpram = false;
+
+	FTS_FUNC_ENTER();
+
+	/*write pramboot*/
+	fw_len = fts_getsize(PRAMBOOT_SIZE);
+	FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+	i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+	if (i_ret != 0) {
+		FTS_ERROR("[UPGRADE]: write pram failed!!");
+		return -EIO;
+	}
+
+	/*check run in pramboot or not!
+	 *if not rum in pramboot, can not upgrade
+	 */
+	inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+	if (!inpram) {
+		FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+		return -EIO;
+	}
+
+	/*read vendor id*/
+	rw_buf[0] = 0x03;
+	rw_buf[1] = 0x00;
+	rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+	rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+	i_ret = fts_i2c_write(client, rw_buf, 4);
+	/* must wait, otherwise read vendor id wrong */
+	usleep_range(10000, 20000);
+	i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+	if (i_ret < 0)
+		return -EIO;
+	FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+	return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ctpm_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0   - ok
+ *		 <0 - fail
+ ***********************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid)
+{
+	int ret = 0;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+	u8 vendor_id = 0;
+
+	if (fw_valid) {
+		ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+	} else {
+		ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+		if ((ret < 0) || (vendor_id == 0xEF) || (vendor_id == 0xED)) {
+			/* 8736 can't read vendor id from A8 command */
+			ret = fts_ctpm_get_vendor_id_flash(client, &vendor_id);
+		}
+	}
+
+	if (ret < 0) {
+		FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+		return ret;
+	}
+	FTS_INFO("[UPGRADE] vendor id tp=%x", vendor_id);
+	FTS_INFO("[UPGRADE] vendor id driver:%x, FTS_VENDOR_ID:%02x %02x %02x",
+		 vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+
+	ret = 0;
+	switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+	case FTS_VENDOR_1_ID:
+		g_fw_file = CTPM_FW;
+		g_fw_len = fts_getsize(FW_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+	case FTS_VENDOR_2_ID:
+		g_fw_file = CTPM_FW2;
+		g_fw_len = fts_getsize(FW2_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+	case FTS_VENDOR_3_ID:
+		g_fw_file = CTPM_FW3;
+		g_fw_len = fts_getsize(FW3_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+		break;
+#endif
+	default:
+		FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+		ret = -EIO;
+		break;
+	}
+#else
+	/* (FTS_GET_VENDOR_ID_NUM == 0) */
+	g_fw_file = CTPM_FW;
+	g_fw_len = fts_getsize(FW_SIZE);
+	FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+#endif
+
+	return ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_bin_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	int fw_ver = 0;
+	int ret;
+
+	FTS_FUNC_ENTER();
+
+	ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return ret;
+	}
+
+	if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE)
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw->size);
+	else
+		fw_ver = fw->data[APP_FILE_VER_MAPPING];
+
+	release_firmware(fw);
+	FTS_FUNC_EXIT();
+
+	return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_i_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_i_file_ver(void)
+{
+	int fwsize = g_fw_len;
+
+	if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+		return 0;
+	}
+
+	return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_pram
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_pram(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length)
+{
+	int i_ret;
+	bool inrom = false;
+
+	FTS_FUNC_ENTER();
+
+	/*check the length of the pramboot*/
+	if (dw_length > APP_FILE_MAX_SIZE || dw_length < APP_FILE_MIN_SIZE) {
+		FTS_ERROR("[UPGRADE] pramboot length(%d) fail", dw_length);
+		return -EIO;
+	}
+
+	/*send comond to FW, reset and start write pramboot*/
+	i_ret = fts_ctpm_start_fw_upgrade(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: send upgrade cmd to FW error!!");
+		return i_ret;
+	}
+
+	/*check run in rom or not! if run in rom, will write pramboot*/
+	inrom = fts_ctpm_check_run_state(client, FTS_RUN_IN_ROM);
+	if (!inrom) {
+		FTS_ERROR("[UPGRADE]: not run in rom, write pramboot fail!!");
+		return -EIO;
+	}
+
+	/*write pramboot to pram*/
+	i_ret = fts_ctpm_write_pramboot_for_idc(client,
+					dw_length, aucFW_PRAM_BOOT);
+	if (i_ret < 0) {
+		return i_ret;
+		FTS_ERROR("[UPGRADE]: write pramboot fail!!");
+	}
+
+	/*read out checksum*/
+	i_ret = fts_ctpm_pramboot_ecc(client);
+	if (i_ret < 0) {
+		return i_ret;
+		FTS_ERROR("[UPGRADE]: write pramboot ecc error!!");
+	}
+
+	/*start pram*/
+	fts_ctpm_start_pramboot(client);
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_app
+ * Brief:  fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_app(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length)
+{
+	u32 temp;
+	int i_ret;
+	bool inpram = false;
+
+	FTS_FUNC_ENTER();
+
+	/*check run in pramboot or not!
+	 *if not rum in pramboot, can not upgrade
+	 */
+	inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+	if (!inpram) {
+		FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+		return -EIO;
+	}
+
+	/*upgrade init*/
+	i_ret = fts_ctpm_upgrade_idc_init(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: upgrade init error, upgrade fail!!");
+		return i_ret;
+	}
+
+	/*erase the app erea in flash*/
+	i_ret = fts_ctpm_erase_flash(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: erase flash error!!");
+		return i_ret;
+	}
+
+	/*start to write app*/
+	i_ret = fts_ctpm_write_app_for_idc(client, dw_length, pbt_buf);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: write app error!!");
+		return i_ret;
+	}
+
+	/*read check sum*/
+	temp = 0x1000;
+	i_ret = fts_ctpm_upgrade_ecc(client, temp, dw_length);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: ecc error!!");
+		return i_ret;
+	}
+
+	/*upgrade success, reset the FW*/
+	fts_ctpm_rom_or_pram_reset(client);
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ *		 success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_use_buf(struct i2c_client *client,
+				u8 *pbt_buf, u32 fwsize)
+{
+	int i_ret = 0;
+	int fw_len;
+
+	FTS_FUNC_ENTER();
+
+	/*write pramboot*/
+	fw_len = fts_getsize(PRAMBOOT_SIZE);
+	FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+	i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+	if (i_ret != 0) {
+		FTS_ERROR("[UPGRADE]: write pram failed!!");
+		return -EIO;
+	}
+
+	/*write app*/
+	i_ret =  fts_ctpm_write_app(client, pbt_buf, fwsize);
+
+	FTS_FUNC_EXIT();
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_i_file
+ * Brief:  upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client)
+{
+	int i_ret = 0;
+	u32 fw_len;
+	u8 *fw_buf;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+	fw_len = g_fw_len;
+	fw_buf = g_fw_file;
+	if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+		return -EIO;
+	}
+
+	i_ret = fts_ctpm_fw_upgrade_use_buf(client, fw_buf, fw_len);
+	if (i_ret != 0)
+		FTS_ERROR("[UPGRADE] upgrade app.i failed");
+	else
+		FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+					char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	u8 *pbt_buf = NULL;
+	int i_ret = 0;
+	bool ecc_ok = false;
+	int fwsize = 0;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+	i_ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (i_ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return i_ret;
+	}
+
+	if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+							fwsize);
+		goto ERROR_BIN;
+	}
+
+	pbt_buf = (u8 *)fw->data;
+	if ((pbt_buf[APP_FILE_CHIPID_MAPPING] != chip_types.pramboot_idh)
+		 || (pbt_buf[APP_FILE_CHIPID_MAPPING+1]
+			 != chip_types.pramboot_idl)) {
+		FTS_ERROR("[UPGRADE]: chip id error, app.bin upgrade failed!");
+		goto ERROR_BIN;
+	}
+
+	/*check the app.bin invalid or not*/
+	ecc_ok = fts_check_app_bin_valid_idc(pbt_buf);
+
+	if (ecc_ok) {
+		FTS_INFO("[UPGRADE] app.bin ecc ok");
+		i_ret = fts_ctpm_fw_upgrade_use_buf(client, pbt_buf, fw->size);
+		if (i_ret != 0) {
+			FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+			goto ERROR_BIN;
+		} else {
+			FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+		}
+	} else {
+		FTS_ERROR("[UPGRADE] app.bin ecc failed");
+		goto ERROR_BIN;
+	}
+
+ERROR_BIN:
+	release_firmware(fw);
+	return i_ret;
+}
+#endif  /* #if (FTS_CHIP_TYPE == _FT8607) */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8716.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8716.c
new file mode 100644
index 0000000..0df248b
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8716.c
@@ -0,0 +1,487 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft8716.c
+ *
+ * Author:    fupeipei
+ *
+ * Created:    2016-08-15
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if ((FTS_CHIP_TYPE == _FT8716) || (FTS_CHIP_TYPE == _FTE716))
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE           (64 * 1024)
+#define APP_FILE_MIN_SIZE           (8)
+#define APP_FILE_VER_MAPPING        (0x10E)
+#define APP_FILE_VENDORID_MAPPING   (0x10C)
+#define APP_FILE_CHIPID_MAPPING     (0x11E)
+#define CONFIG_START_ADDR           (0x0000)
+#define CONFIG_VENDOR_ID_OFFSET     (0x04)
+#define CONFIG_PROJECT_ID_OFFSET    (0x20)
+#define CONFIG_VENDOR_ID_ADDR       (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR      (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ctpm_get_app_i_file_ver(void);
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name);
+static int fts_ctpm_write_pram(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length);
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+			char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+	.get_i_file = fts_ctpm_get_i_file,
+	.get_app_bin_file_ver = fts_ctpm_get_app_bin_file_ver,
+	.get_app_i_file_ver = fts_ctpm_get_app_i_file_ver,
+	.upgrade_with_app_i_file = fts_ctpm_fw_upgrade_with_app_i_file,
+	.upgrade_with_app_bin_file = fts_ctpm_fw_upgrade_with_app_bin_file,
+	.upgrade_with_lcd_cfg_i_file = NULL,
+	.upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ctpm_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ctpm_get_vendor_id_flash(struct i2c_client *client,
+				u8 *vendor_id)
+{
+	u8 rw_buf[10];
+	int i_ret;
+	int fw_len;
+	bool inpram = false;
+
+	FTS_FUNC_ENTER();
+
+	/*write pramboot*/
+	fw_len = fts_getsize(PRAMBOOT_SIZE);
+	FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+	i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+	if (i_ret != 0) {
+		FTS_ERROR("[UPGRADE]: write pram failed!!");
+		return -EIO;
+	}
+
+	/*check run in pramboot or not!
+	 *if not rum in pramboot, can not upgrade
+	 */
+	inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+	if (!inpram) {
+		FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+		return -EIO;
+	}
+
+	/*read vendor id*/
+	rw_buf[0] = 0x03;
+	rw_buf[1] = 0x00;
+	rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+	rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+	i_ret = fts_i2c_write(client, rw_buf, 4);
+	/* must wait, otherwise read vendor id wrong */
+	usleep_range(10000, 20000);
+	i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+	if (i_ret < 0)
+		return -EIO;
+	FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+	return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ctpm_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0   - ok
+ *		 <0 - fail
+ ***********************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid)
+{
+	int ret = -EIO;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+	u8 vendor_id = 0;
+
+	if (fw_valid) {
+		ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+	} else {
+		ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+		if ((ret < 0) || (vendor_id == 0xEF) || (vendor_id == 0xED)) {
+			/* 8736 can't read vendor id from A8 command */
+			ret = fts_ctpm_get_vendor_id_flash(client, &vendor_id);
+		}
+	}
+
+	if (ret < 0) {
+		FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+		return ret;
+	}
+	FTS_INFO("[UPGRADE] vendor id tp=%x", vendor_id);
+	FTS_INFO("[UPGRADE] vendor id driver:%x, FTS_VENDOR_ID:%02x %02x %02x",
+		 vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+
+	ret = 0;
+	switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+	case FTS_VENDOR_1_ID:
+		g_fw_file = CTPM_FW;
+		g_fw_len = fts_getsize(FW_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+	case FTS_VENDOR_2_ID:
+		g_fw_file = CTPM_FW2;
+		g_fw_len = fts_getsize(FW2_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+	case FTS_VENDOR_3_ID:
+		g_fw_file = CTPM_FW3;
+		g_fw_len = fts_getsize(FW3_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+		break;
+#endif
+	default:
+		FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+		ret = -EIO;
+		break;
+	}
+#endif
+
+	return ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_bin_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	int fw_ver = 0;
+	int ret;
+
+	FTS_FUNC_ENTER();
+
+	ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return ret;
+	}
+
+	if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE)
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw->size);
+	else
+		fw_ver = fw->data[APP_FILE_VER_MAPPING];
+
+	release_firmware(fw);
+	FTS_FUNC_EXIT();
+
+	return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_i_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_i_file_ver(void)
+{
+	int fwsize = g_fw_len;
+
+	if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+		return 0;
+	}
+
+	return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_pram
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_pram(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length)
+{
+	int i_ret;
+	bool inrom = false;
+
+	FTS_FUNC_ENTER();
+
+	/*check the length of the pramboot*/
+	if (dw_length > APP_FILE_MAX_SIZE || dw_length < APP_FILE_MIN_SIZE) {
+		FTS_ERROR("[UPGRADE] pramboot length(%d) fail", dw_length);
+		return -EIO;
+	}
+
+	/*send comond to FW, reset and start write pramboot*/
+	i_ret = fts_ctpm_start_fw_upgrade(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: send upgrade cmd to FW error!!");
+		return i_ret;
+	}
+
+	/*check run in rom or not! if run in rom, will write pramboot*/
+	inrom = fts_ctpm_check_run_state(client, FTS_RUN_IN_ROM);
+	if (!inrom) {
+		FTS_ERROR("[UPGRADE]: not run in rom, write pramboot fail!!");
+		return -EIO;
+	}
+
+	/*write pramboot to pram*/
+	i_ret = fts_ctpm_write_pramboot_for_idc(client,
+					dw_length, aucFW_PRAM_BOOT);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: write pramboot fail!!");
+		return i_ret;
+	}
+
+	/*read out checksum*/
+	i_ret = fts_ctpm_pramboot_ecc(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: write pramboot ecc error!!");
+		return i_ret;
+	}
+
+	/*start pram*/
+	fts_ctpm_start_pramboot(client);
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_app
+ * Brief:  fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_app(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length)
+{
+	u32 temp;
+	int i_ret;
+	bool inpram = false;
+
+	FTS_FUNC_ENTER();
+
+	/*check run in pramboot or not!
+	 *if not rum in pramboot, can not upgrade
+	 */
+	inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+	if (!inpram) {
+		FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+		return -EIO;
+	}
+
+	/*upgrade init*/
+	i_ret = fts_ctpm_upgrade_idc_init(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: upgrade init error, upgrade fail!!");
+		return i_ret;
+	}
+
+	/*erase the app erea in flash*/
+	i_ret = fts_ctpm_erase_flash(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: erase flash error!!");
+		return i_ret;
+	}
+
+	/*start to write app*/
+	i_ret = fts_ctpm_write_app_for_idc(client, dw_length, pbt_buf);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: write app error!!");
+		return i_ret;
+	}
+
+	/*read check sum*/
+	temp = 0x1000;
+	i_ret = fts_ctpm_upgrade_ecc(client, temp, dw_length);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: ecc error!!");
+		return i_ret;
+	}
+
+	/*upgrade success, reset the FW*/
+	fts_ctpm_rom_or_pram_reset(client);
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ *		 success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_use_buf(struct i2c_client *client,
+				u8 *pbt_buf, u32 fwsize)
+{
+	int i_ret = 0;
+	int fw_len;
+
+	FTS_FUNC_ENTER();
+
+	/*write pramboot*/
+	fw_len = fts_getsize(PRAMBOOT_SIZE);
+	FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+	i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+	if (i_ret != 0) {
+		FTS_ERROR("[UPGRADE]: write pram failed!!");
+		return -EIO;
+	}
+
+	/*write app*/
+	i_ret =  fts_ctpm_write_app(client, pbt_buf, fwsize);
+
+	FTS_FUNC_EXIT();
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_i_file
+ * Brief:  upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client)
+{
+	int i_ret = 0;
+	u32 fw_len;
+	u8 *fw_buf;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+	fw_len = g_fw_len;
+	fw_buf = g_fw_file;
+	if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+		return -EIO;
+	}
+
+	i_ret = fts_ctpm_fw_upgrade_use_buf(client, fw_buf, fw_len);
+	if (i_ret != 0)
+		FTS_ERROR("[UPGRADE] upgrade app.i failed");
+	else
+		FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+					char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	u8 *pbt_buf = NULL;
+	int i_ret = 0;
+	bool ecc_ok = false;
+	int fwsize = 0;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+	i_ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (i_ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return i_ret;
+	}
+
+	if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+							fwsize);
+		goto ERROR_BIN;
+	}
+
+	/*check the app.bin invalid or not*/
+	pbt_buf = (u8 *)fw->data;
+	ecc_ok = fts_check_app_bin_valid_idc(pbt_buf);
+
+	if (ecc_ok) {
+		FTS_INFO("[UPGRADE] app.bin ecc ok");
+		i_ret = fts_ctpm_fw_upgrade_use_buf(client, pbt_buf, fw->size);
+		if (i_ret != 0) {
+			FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+			goto ERROR_BIN;
+		} else {
+			FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+		}
+	} else {
+		FTS_ERROR("[UPGRADE] app.bin ecc failed");
+		goto ERROR_BIN;
+	}
+
+ERROR_BIN:
+	release_firmware(fw);
+	return i_ret;
+}
+#endif  /* #if (FTS_CHIP_TYPE == _FT8716) */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8736.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8736.c
new file mode 100644
index 0000000..6f6544e
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_ft8736.c
@@ -0,0 +1,506 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_ft8736.c
+ *
+ * Author:    fupeipei
+ *
+ * Created:    2016-10-25
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (FTS_CHIP_TYPE == _FT8736)
+#include "../focaltech_flash.h"
+#include "focaltech_upgrade_common.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define APP_FILE_MAX_SIZE           (64 * 1024)
+#define APP_FILE_MIN_SIZE           (8)
+#define APP_FILE_VER_MAPPING        (0x10E)
+#define APP_FILE_VENDORID_MAPPING   (0x10C)
+#define APP_FILE_CHIPID_MAPPING     (0x11E)
+#define CONFIG_START_ADDR           (0x0F80)
+#define CONFIG_VENDOR_ID_OFFSET     (0x4)
+#define CONFIG_PROJECT_ID_OFFSET    (0x20)
+#define CONFIG_VENDOR_ID_ADDR       (CONFIG_START_ADDR+CONFIG_VENDOR_ID_OFFSET)
+#define CONFIG_PROJECT_ID_ADDR      (CONFIG_START_ADDR+CONFIG_PROJECT_ID_OFFSET)
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid);
+static int fts_ctpm_get_app_i_file_ver(void);
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name);
+static int fts_ctpm_write_pram(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length);
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client);
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+			char *firmware_name);
+
+struct fts_upgrade_fun fts_updatefun = {
+	.get_i_file = fts_ctpm_get_i_file,
+	.get_app_bin_file_ver = fts_ctpm_get_app_bin_file_ver,
+	.get_app_i_file_ver = fts_ctpm_get_app_i_file_ver,
+	.upgrade_with_app_i_file = fts_ctpm_fw_upgrade_with_app_i_file,
+	.upgrade_with_app_bin_file = fts_ctpm_fw_upgrade_with_app_bin_file,
+	.upgrade_with_lcd_cfg_i_file = NULL,
+	.upgrade_with_lcd_cfg_bin_file = NULL,
+};
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+/************************************************************************
+ * Name: fts_ctpm_get_vendor_id_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+static int fts_ctpm_get_vendor_id_flash(struct i2c_client *client,
+				u8 *vendor_id)
+{
+	u8 rw_buf[10];
+	int i_ret;
+	int fw_len;
+	bool inpram = false;
+
+	FTS_FUNC_ENTER();
+
+	/*write pramboot*/
+	fw_len = fts_getsize(PRAMBOOT_SIZE);
+	FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+	i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+	if (i_ret != 0) {
+		FTS_ERROR("[UPGRADE]: write pram failed!!");
+		return -EIO;
+	}
+
+	/*check run in pramboot or not!
+	 *if not rum in pramboot, can not upgrade
+	 */
+	inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+	if (!inpram) {
+		FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+		return -EIO;
+	}
+
+	/* initialization 0x05 0x80 */
+	i_ret = fts_ctpm_upgrade_idc_init(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: upgrade init error, upgrade fail!!");
+		return i_ret;
+	}
+
+	/*read vendor id*/
+	rw_buf[0] = 0x03;
+	rw_buf[1] = 0x00;
+	rw_buf[2] = (u8)(CONFIG_VENDOR_ID_ADDR >> 8);
+	rw_buf[3] = (u8)(CONFIG_VENDOR_ID_ADDR);
+	i_ret = fts_i2c_write(client, rw_buf, 4);
+	/* must wait, otherwise read vendor id wrong */
+	usleep_range(10000, 20000);
+	i_ret = fts_i2c_read(client, NULL, 0, vendor_id, 1);
+	if (i_ret < 0)
+		return -EIO;
+	FTS_DEBUG("Vendor ID from Flash:%x", *vendor_id);
+	return 0;
+}
+#endif
+
+/************************************************************************
+ * Name: fts_ctpm_get_i_file
+ * Brief: get .i file
+ * Input:
+ * Output:
+ * Return: 0   - ok
+ *		 <0 - fail
+ ***********************************************************************/
+static int fts_ctpm_get_i_file(struct i2c_client *client, int fw_valid)
+{
+	int ret = 0;
+
+#if (FTS_GET_VENDOR_ID_NUM != 0)
+	u8 vendor_id = 0;
+
+	if (fw_valid) {
+		ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+	} else {
+		ret = fts_i2c_read_reg(client, FTS_REG_VENDOR_ID, &vendor_id);
+		if ((ret < 0) || (vendor_id == 0xEF) || (vendor_id == 0xED)) {
+			/* 8736 can't read vendor id from A8 command */
+			ret = fts_ctpm_get_vendor_id_flash(client, &vendor_id);
+		}
+	}
+
+	if (ret < 0) {
+		FTS_ERROR("Get upgrade file fail because of Vendor ID wrong");
+		return ret;
+	}
+	FTS_INFO("[UPGRADE] vendor id tp=%x", vendor_id);
+	FTS_INFO("[UPGRADE] vendor id driver:%x, FTS_VENDOR_ID:%02x %02x %02x",
+		 vendor_id, FTS_VENDOR_1_ID, FTS_VENDOR_2_ID, FTS_VENDOR_3_ID);
+
+	ret = 0;
+	switch (vendor_id) {
+#if (FTS_GET_VENDOR_ID_NUM >= 1)
+	case FTS_VENDOR_1_ID:
+		g_fw_file = CTPM_FW;
+		g_fw_len = fts_getsize(FW_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 2)
+	case FTS_VENDOR_2_ID:
+		g_fw_file = CTPM_FW2;
+		g_fw_len = fts_getsize(FW2_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW2, SIZE:%x", g_fw_len);
+		break;
+#endif
+#if (FTS_GET_VENDOR_ID_NUM >= 3)
+	case FTS_VENDOR_3_ID:
+		g_fw_file = CTPM_FW3;
+		g_fw_len = fts_getsize(FW3_SIZE);
+		FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW3, SIZE:%x", g_fw_len);
+		break;
+#endif
+	default:
+		FTS_ERROR("[UPGRADE]Vendor ID check fail, get fw file fail");
+		ret = -EIO;
+		break;
+	}
+#else
+	/* (FTS_GET_VENDOR_ID_NUM == 0) */
+	g_fw_file = CTPM_FW;
+	g_fw_len = fts_getsize(FW_SIZE);
+	FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+#endif
+
+	return ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_bin_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_bin_file_ver(struct i2c_client *client,
+				char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	int fw_ver = 0;
+	int ret;
+
+	FTS_FUNC_ENTER();
+
+	ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return ret;
+	}
+
+	if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE)
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw->size);
+	else
+		fw_ver = fw->data[APP_FILE_VER_MAPPING];
+
+	release_firmware(fw);
+	FTS_FUNC_EXIT();
+
+	return fw_ver;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_get_app_i_file_ver
+ * Brief:  get .i file version
+ * Input: no
+ * Output: no
+ * Return: fw version
+ ***********************************************************************/
+static int fts_ctpm_get_app_i_file_ver(void)
+{
+	int fwsize = g_fw_len;
+
+	if (fwsize < APP_FILE_MIN_SIZE || fwsize > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fwsize);
+		return 0;
+	}
+
+	return g_fw_file[APP_FILE_VER_MAPPING];
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_pram
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_pram(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length)
+{
+	int i_ret;
+	bool inrom = false;
+
+	FTS_FUNC_ENTER();
+
+	/*check the length of the pramboot*/
+	if (dw_length > APP_FILE_MAX_SIZE || dw_length < APP_FILE_MIN_SIZE) {
+		FTS_ERROR("[UPGRADE] pramboot length(%d) fail", dw_length);
+		return -EIO;
+	}
+
+	/*send comond to FW, reset and start write pramboot*/
+	i_ret = fts_ctpm_start_fw_upgrade(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: send upgrade cmd to FW error!!");
+		return i_ret;
+	}
+
+	/*check run in rom or not! if run in rom, will write pramboot*/
+	inrom = fts_ctpm_check_run_state(client, FTS_RUN_IN_ROM);
+	if (!inrom) {
+		FTS_ERROR("[UPGRADE]: not run in rom, write pramboot fail!!");
+		return -EIO;
+	}
+
+	/*write pramboot to pram*/
+	i_ret = fts_ctpm_write_pramboot_for_idc(client,
+					dw_length, aucFW_PRAM_BOOT);
+	if (i_ret < 0) {
+		return i_ret;
+		FTS_ERROR("[UPGRADE]: write pramboot fail!!");
+	}
+
+	/*read out checksum*/
+	i_ret = fts_ctpm_pramboot_ecc(client);
+	if (i_ret < 0) {
+		return i_ret;
+		FTS_ERROR("[UPGRADE]: write pramboot ecc error!!");
+	}
+
+	/*start pram*/
+	fts_ctpm_start_pramboot(client);
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_app
+ * Brief:  fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_ctpm_write_app(struct i2c_client *client,
+			u8 *pbt_buf, u32 dw_length)
+{
+	u32 temp;
+	int i_ret;
+	bool inpram = false;
+
+	FTS_FUNC_ENTER();
+
+	/*check run in pramboot or not!
+	 *if not rum in pramboot, can not upgrade
+	 */
+	inpram = fts_ctpm_check_run_state(client, FTS_RUN_IN_PRAM);
+	if (!inpram) {
+		FTS_ERROR("[UPGRADE]: not run in pram, upgrade fail!!");
+		return -EIO;
+	}
+
+	/*upgrade init*/
+	i_ret = fts_ctpm_upgrade_idc_init(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: upgrade init error, upgrade fail!!");
+		return i_ret;
+	}
+
+	/*erase the app erea in flash*/
+	i_ret = fts_ctpm_erase_flash(client);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: erase flash error!!");
+		return i_ret;
+	}
+
+	/*start to write app*/
+	i_ret = fts_ctpm_write_app_for_idc(client, dw_length, pbt_buf);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: write app error!!");
+		return i_ret;
+	}
+
+	/*read check sum*/
+	temp = 0x1000;
+	i_ret = fts_ctpm_upgrade_ecc(client, temp, dw_length);
+	if (i_ret < 0) {
+		FTS_ERROR("[UPGRADE]: ecc error!!");
+		return i_ret;
+	}
+
+	/*upgrade success, reset the FW*/
+	fts_ctpm_rom_or_pram_reset(client);
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_use_buf
+ * Brief: fw upgrade
+ * Input: i2c info, file buf, file len
+ * Output: no
+ * Return: fail <0
+ *		 success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_use_buf(struct i2c_client *client,
+				u8 *pbt_buf, u32 fwsize)
+{
+	int i_ret = 0;
+	int fw_len;
+
+	FTS_FUNC_ENTER();
+
+	/*write pramboot*/
+	fw_len = fts_getsize(PRAMBOOT_SIZE);
+	FTS_DEBUG("[UPGRADE]: pramboot size : %d!!", fw_len);
+	i_ret = fts_ctpm_write_pram(client, aucFW_PRAM_BOOT, fw_len);
+	if (i_ret != 0) {
+		FTS_ERROR("[UPGRADE]: write pram failed!!");
+		return -EIO;
+	}
+
+	/*write app*/
+	i_ret =  fts_ctpm_write_app(client, pbt_buf, fwsize);
+
+	FTS_FUNC_EXIT();
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_i_file
+ * Brief:  upgrade with *.i file
+ * Input: i2c info
+ * Output:
+ * Return: fail < 0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_i_file(struct i2c_client *client)
+{
+	int i_ret = 0;
+	u32 fw_len;
+	u8 *fw_buf;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.i**********");
+
+	fw_len = g_fw_len;
+	fw_buf = g_fw_file;
+	if (fw_len < APP_FILE_MIN_SIZE || fw_len > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: FW length(%x) error", fw_len);
+		return -EIO;
+	}
+
+	i_ret = fts_ctpm_fw_upgrade_use_buf(client, fw_buf, fw_len);
+	if (i_ret != 0)
+		FTS_ERROR("[UPGRADE] upgrade app.i failed");
+	else
+		FTS_INFO("[UPGRADE]: upgrade app.i succeed");
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_fw_upgrade_with_app_bin_file
+ * Brief: upgrade with *.bin file
+ * Input: i2c info, file name
+ * Output: no
+ * Return: success =0
+ ***********************************************************************/
+static int fts_ctpm_fw_upgrade_with_app_bin_file(struct i2c_client *client,
+					char *firmware_name)
+{
+	const struct firmware *fw = NULL;
+	u8 *pbt_buf = NULL;
+	int i_ret = 0;
+	bool ecc_ok = false;
+	int fwsize = 0;
+
+	FTS_INFO("[UPGRADE]**********start upgrade with app.bin**********");
+
+	i_ret = request_firmware(&fw, firmware_name, &client->dev);
+	if (i_ret) {
+		FTS_ERROR("[UPGRADE]: failed to get fw %s\n", firmware_name);
+		return i_ret;
+	}
+
+	if (fw->size < APP_FILE_MIN_SIZE || fw->size > APP_FILE_MAX_SIZE) {
+		FTS_ERROR("[UPGRADE]: app.bin length(%x) error, upgrade fail",
+							fwsize);
+		goto ERROR_BIN;
+	}
+
+	pbt_buf = (u8 *)fw->data;
+	if ((pbt_buf[APP_FILE_CHIPID_MAPPING] != chip_types.pramboot_idh)
+		 || (pbt_buf[APP_FILE_CHIPID_MAPPING+1]
+			 != chip_types.pramboot_idl)) {
+		FTS_ERROR("[UPGRADE]: chip id error, app.bin upgrade failed!");
+		goto ERROR_BIN;
+	}
+
+	/*check the app.bin invalid or not*/
+	ecc_ok = fts_check_app_bin_valid_idc(pbt_buf);
+
+	if (ecc_ok) {
+		FTS_INFO("[UPGRADE] app.bin ecc ok");
+		i_ret = fts_ctpm_fw_upgrade_use_buf(client, pbt_buf, fw->size);
+		if (i_ret != 0) {
+			FTS_ERROR("[UPGRADE]: upgrade app.bin failed");
+			goto ERROR_BIN;
+		} else {
+			FTS_INFO("[UPGRADE]: upgrade app.bin succeed");
+		}
+	} else {
+		FTS_ERROR("[UPGRADE] app.bin ecc failed");
+		goto ERROR_BIN;
+	}
+
+ERROR_BIN:
+	release_firmware(fw);
+	return i_ret;
+}
+#endif  /* #if (FTS_CHIP_TYPE == _FT8736) */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_idc.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_idc.c
new file mode 100644
index 0000000..c91d7c80
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_idc.c
@@ -0,0 +1,592 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_idc.c
+ *
+ * Author:    fupeipei
+ *
+ * Created:    2016-08-22
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+
+#if (FTS_CHIP_IDC == 1)
+#include "../focaltech_flash.h"
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+static u8 upgrade_ecc;
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+
+/************************************************************************
+ * Name: fts_ctpm_upgrade_idc_init
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_upgrade_idc_init(struct i2c_client *client)
+{
+	int i_ret = 0;
+	u8 reg_val_id[4] = {0};
+	u8 auc_i2c_write_buf[10];
+
+	FTS_INFO("[UPGRADE]**********Upgrade setting Init**********");
+
+	/*read flash ID*/
+	auc_i2c_write_buf[0] = 0x05;
+	reg_val_id[0] = 0x00;
+	i_ret = fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val_id, 1);
+	if (i_ret < 0)
+		return -EIO;
+
+	/*set flash clk*/
+	auc_i2c_write_buf[0] = 0x05;
+	auc_i2c_write_buf[1] = reg_val_id[0];/* 0x80; */
+	auc_i2c_write_buf[2] = 0x00;
+	fts_i2c_write(client, auc_i2c_write_buf, 3);
+
+	/*send upgrade type to reg 0x09: 0x0B: upgrade; 0x0A: download*/
+	auc_i2c_write_buf[0] = 0x09;
+	auc_i2c_write_buf[1] = 0x0B;
+	fts_i2c_write(client, auc_i2c_write_buf, 2);
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_start_pramboot
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+void fts_ctpm_start_pramboot(struct i2c_client *client)
+{
+	u8 auc_i2c_write_buf[10];
+
+	FTS_INFO("[UPGRADE]**********start pramboot**********");
+	auc_i2c_write_buf[0] = 0x08;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(20);
+}
+
+/************************************************************************
+ * Name: fts_ctpm_start_fw_upgrade
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_start_fw_upgrade(struct i2c_client *client)
+{
+	int i_ret = 0;
+
+	/*send the soft upgrade commond to FW, and start upgrade*/
+	FTS_INFO("[UPGRADE]***send 0xAA and 0x55 to FW, start upgrade***\n");
+
+	i_ret = fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_AA);
+	msleep(20);
+	i_ret = fts_i2c_write_reg(client, FTS_RST_CMD_REG1, FTS_UPGRADE_55);
+	msleep(200);
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_check_run_state
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+bool fts_ctpm_check_run_state(struct i2c_client *client, int rstate)
+{
+	int i = 0;
+	enum FW_STATUS cstate = FTS_RUN_IN_ERROR;
+
+	for (i = 0; i < FTS_UPGRADE_LOOP; i++) {
+		cstate = fts_ctpm_get_pram_or_rom_id(client);
+		FTS_DEBUG("[UPGRADE]: run state = %d", cstate);
+
+		if (cstate == rstate)
+			return true;
+		msleep(20);
+	}
+
+	return false;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_pramboot_ecc
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_pramboot_ecc(struct i2c_client *client)
+{
+	u8 auc_i2c_write_buf[10];
+	u8 reg_val[4] = {0};
+
+	FTS_FUNC_ENTER();
+
+	/* read out checksum,
+	 * if pramboot checksum != host checksum, upgrade fail
+	 */
+	FTS_INFO("[UPGRADE]******read out pramboot checksum******");
+	auc_i2c_write_buf[0] = 0xcc;
+	usleep_range(2000, 4000);
+	fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+	/*pramboot checksum != host checksum, upgrade fail*/
+	if (reg_val[0] != upgrade_ecc) {
+		FTS_ERROR("[UPGRADE]: checksum fail:pramboot = %X, host = %X!",
+				reg_val[0], upgrade_ecc);
+		return -EIO;
+	}
+
+	FTS_DEBUG("[UPGRADE]: checksum success:pramboot = %X, host = %X!!",
+			reg_val[0], upgrade_ecc);
+	msleep(100);
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_upgrade_ecc
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_upgrade_ecc(struct i2c_client *client, u32 startaddr, u32 length)
+{
+	u32 i = 0;
+	u8 auc_i2c_write_buf[10];
+	u32 temp;
+	u8 reg_val[4] = {0};
+	int i_ret = 0;
+
+	FTS_INFO("[UPGRADE]**********read out checksum**********");
+
+	/*check sum init*/
+	auc_i2c_write_buf[0] = 0x64;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(300);
+
+	/*send commond to pramboot to start checksum*/
+	auc_i2c_write_buf[0] = 0x65;
+	auc_i2c_write_buf[1] = (u8)(startaddr >> 16);
+	auc_i2c_write_buf[2] = (u8)(startaddr >> 8);
+	auc_i2c_write_buf[3] = (u8)(startaddr);
+
+	if (length > LEN_FLASH_ECC_MAX)
+		temp = LEN_FLASH_ECC_MAX;
+	else
+		temp = length;
+
+	auc_i2c_write_buf[4] = (u8)(temp >> 8);
+	auc_i2c_write_buf[5] = (u8)(temp);
+	i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+	msleep(length/256);
+
+	/*read status : if check sum is finished?*/
+	for (i = 0; i < 100; i++) {
+		auc_i2c_write_buf[0] = 0x6a;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+		if (0xF0 == reg_val[0] && 0x55 == reg_val[1])
+			break;
+		usleep_range(1000, 2000);
+
+	}
+
+	if (length > LEN_FLASH_ECC_MAX) {
+		temp = LEN_FLASH_ECC_MAX;
+		auc_i2c_write_buf[0] = 0x65;
+		auc_i2c_write_buf[1] = (u8)(temp >> 16);
+		auc_i2c_write_buf[2] = (u8)(temp >> 8);
+		auc_i2c_write_buf[3] = (u8)(temp);
+		temp = length-LEN_FLASH_ECC_MAX;
+		auc_i2c_write_buf[4] = (u8)(temp >> 8);
+		auc_i2c_write_buf[5] = (u8)(temp);
+		i_ret = fts_i2c_write(client, auc_i2c_write_buf, 6);
+
+		msleep(length/256);
+
+		for (i = 0; i < 100; i++) {
+			auc_i2c_write_buf[0] = 0x6a;
+			reg_val[0] = reg_val[1] = 0x00;
+			fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+			if (0xF0 == reg_val[0] && 0x55 == reg_val[1])
+				break;
+			usleep_range(1000, 2000);
+		}
+	}
+
+	/*read out check sum*/
+	auc_i2c_write_buf[0] = 0x66;
+	i_ret = fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 1);
+	/*if check sum fail, upgrade fail*/
+	if (reg_val[0] != upgrade_ecc) {
+		FTS_ERROR("[UPGRADE]: ecc error! FW=%02x upgrade_ecc=%02x!!",
+				reg_val[0], upgrade_ecc);
+		return -EIO;
+	}
+
+	FTS_DEBUG("[UPGRADE]: ecc success : FW=%02x upgrade_ecc=%02x!!",
+				reg_val[0], upgrade_ecc);
+
+	upgrade_ecc = 0;
+
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_erase_flash
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_erase_flash(struct i2c_client *client)
+{
+	u32 i = 0;
+	u8 auc_i2c_write_buf[10];
+	u8 reg_val[4] = {0};
+
+	FTS_INFO("[UPGRADE]**********erase app now**********");
+
+	/*send to erase flash*/
+	auc_i2c_write_buf[0] = 0x61;
+	fts_i2c_write(client, auc_i2c_write_buf, 1);
+	msleep(1350);
+
+	for (i = 0; i < 15; i++) {
+		/* get the erase app status,
+		 * if get 0xF0AA£¬erase flash success
+		 */
+		auc_i2c_write_buf[0] = 0x6a;
+		reg_val[0] = reg_val[1] = 0x00;
+		fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+		/*erase flash success*/
+		if (0xF0 == reg_val[0] && 0xAA == reg_val[1])
+			break;
+		msleep(50);
+	}
+
+	/*erase flash fail*/
+	if ((0xF0 != reg_val[0] || 0xAA != reg_val[1]) && (i >= 15)) {
+		FTS_ERROR("[UPGRADE]: erase app error.reset tp and reload FW!");
+		return -EIO;
+	}
+
+	FTS_DEBUG("[UPGRADE]: erase app ok!!");
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_pramboot_for_idc
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_write_pramboot_for_idc(struct i2c_client *client,
+		u32 length, u8 *readbuf)
+{
+	u32 i = 0;
+	u32 j;
+	u32 temp;
+	u32 packet_number;
+	u8 packet_buf[FTS_PACKET_LENGTH + 6];
+
+	upgrade_ecc = 0;
+	FTS_INFO("[UPGRADE]**********write pramboot to pram**********");
+
+	temp = 0;
+	packet_number = (length) / FTS_PACKET_LENGTH;
+	if ((length) % FTS_PACKET_LENGTH > 0)
+		packet_number++;
+
+	packet_buf[0] = 0xae;
+	packet_buf[1] = 0x00;
+
+	for (j = 0; j < packet_number; j++) {
+		temp = j * FTS_PACKET_LENGTH;
+		packet_buf[2] = (u8) (temp >> 8);
+		packet_buf[3] = (u8) temp;
+		if (j < (packet_number-1))
+			temp = FTS_PACKET_LENGTH;
+		else
+			temp = (length) % FTS_PACKET_LENGTH;
+
+		packet_buf[4] = (u8) (temp >> 8);
+		packet_buf[5] = (u8) temp;
+
+		for (i = 0; i < temp; i++) {
+			packet_buf[6 + i] = readbuf[j * FTS_PACKET_LENGTH + i];
+			upgrade_ecc ^= packet_buf[6 + i];
+		}
+		fts_i2c_write(client, packet_buf, temp + 6);
+	}
+
+	return 0;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_write_app_for_idc
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_ctpm_write_app_for_idc(struct i2c_client *client,
+			u32 length, u8 *readbuf)
+{
+	u32 j;
+	u32 i = 0;
+	u32 packet_number;
+	u32 temp;
+	u32 writelenght;
+	u8 packet_buf[FTS_PACKET_LENGTH + 6];
+	u8 auc_i2c_write_buf[10];
+	u8 reg_val[4] = {0};
+
+	FTS_INFO("[UPGRADE]**********write app to flash**********");
+
+	upgrade_ecc = 0;
+
+	packet_number = (length) / FTS_PACKET_LENGTH;
+	if (((length) % FTS_PACKET_LENGTH) > 0)
+		packet_number++;
+
+	packet_buf[0] = 0xbf;
+
+	for (j = 0; j < packet_number; j++) {
+		temp = 0x1000+j * FTS_PACKET_LENGTH;
+
+		if (j < (packet_number-1))
+			writelenght = FTS_PACKET_LENGTH;
+		else
+			writelenght = ((length) % FTS_PACKET_LENGTH);
+
+		packet_buf[1] = (u8) (temp >> 16);
+		packet_buf[2] = (u8) (temp >> 8);
+		packet_buf[3] = (u8) temp;
+		packet_buf[4] = (u8) (writelenght >> 8);
+		packet_buf[5] = (u8) writelenght;
+
+		for (i = 0; i < writelenght; i++) {
+			packet_buf[6 + i] = readbuf[(temp - 0x1000+i)];
+			upgrade_ecc ^= packet_buf[6 + i];
+		}
+
+		fts_i2c_write(client, packet_buf, (writelenght + 6));
+
+		for (i = 0; i < 30; i++) {
+			/* read status and check
+			 * if the app writing is finished
+			 */
+			auc_i2c_write_buf[0] = 0x6a;
+			reg_val[0] = reg_val[1] = 0x00;
+			fts_i2c_read(client, auc_i2c_write_buf, 1, reg_val, 2);
+
+			if ((j + 0x20+0x1000) == (((reg_val[0]) << 8)
+						| reg_val[1]))
+				break;
+
+			fts_ctpm_upgrade_delay(1000);
+		}
+	}
+
+	msleep(50);
+
+	return 0;
+}
+
+#define APP_LEN		 0x00
+#define APP_LEN_NE	 0x02
+#define APP_P1_ECC	 0x04
+#define APP_P1_ECC_NE	 0x06
+#define APP_P2_ECC	 0x08
+#define APP_P2_ECC_NE	 0x0A
+#define APP_LEN_H	 0x12
+#define APP_LEN_H_NE	 0x14
+#define APP_BLR_ID	 0x1C
+#define APP_BLR_ID_NE	 0x1D
+#define PBOOT_ID_H	 0x1E
+#define PBOOT_ID_L	 0x1F
+
+#define AL2_FCS_COEF		  ((1 << 15) + (1 << 10) + (1 << 3))
+
+#if ((FTS_CHIP_TYPE == _FT8006) || (FTS_CHIP_TYPE == _FT8736))
+#define FW_CFG_TOTAL_SIZE   0x80
+#else
+#define FW_CFG_TOTAL_SIZE   0x00
+#endif
+#define APP1_START	0x00
+#define APP1_LEN	0x100
+#define APP_VERIF_ADDR	(APP1_START + APP1_LEN)
+#define APP_VERIF_LEN	0x20
+#define APP1_ECC_ADDR	(APP_VERIF_ADDR + APP_P1_ECC)
+#define APP2_START	(APP_VERIF_ADDR + APP_VERIF_LEN + FW_CFG_TOTAL_SIZE)
+#define APP2_ECC_ADDR	(APP_VERIF_ADDR + APP_P2_ECC)
+/*****************************************************************************
+ * Name: DrvReadPram16
+ * Brief: Get Word
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static u16 data_word(u8 *pbt_buf, u32 addr)
+{
+	return (((u16)pbt_buf[addr]<<8) + pbt_buf[addr+1]);
+}
+
+/******************************************************************************
+ * Name: GetCrc16
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static u16 crc_calc(u8 *pbt_buf, u32 addr, u16 length)
+{
+	u16 cFcs = 0;
+	u16 i, j;
+
+	FTS_DEBUG("[UPGRADE][ECC] : %04x  data:%04x, len:%04x!!",
+			(addr), data_word(pbt_buf, (addr)), length);
+	for (i = 0; i < length; i++) {
+		cFcs ^= data_word(pbt_buf, (addr+i*2));
+		for (j = 0; j < 16; j++) {
+			if (cFcs & 1)
+				cFcs = (u16)((cFcs >> 1) ^ AL2_FCS_COEF);
+			else
+				cFcs >>= 1;
+		}
+	}
+
+	return cFcs;
+}
+
+/*****************************************************************************
+ *   Name: task_check_mem
+ *  Brief:
+ *  Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static bool ecc_check(u8 *pbt_buf, u32 star_addr, u32 len, u16 ecc_addr)
+{
+	u16 ecc1;
+	u16 ecc2;
+	u16 cal_ecc;
+
+	ecc1 = data_word(pbt_buf, ecc_addr);
+	ecc2 = data_word(pbt_buf, ecc_addr+2);
+
+	if ((ecc1 + ecc2) != 0xFFFF)
+		return false;
+
+	cal_ecc = crc_calc(pbt_buf, star_addr, (len/2));
+
+	FTS_DEBUG("[UPGRADE][ECC] : ecc1 = %x, cal_ecc = %x", ecc1, cal_ecc);
+	if (ecc1 != cal_ecc) {
+		FTS_DEBUG("[UPGRADE][ECC] : ecc error!!");
+		return false;
+	}
+
+	return true;
+}
+
+/*****************************************************************************
+ * Name: fts_check_app_bin_valid_idc
+ * Brief:
+ * Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+bool fts_check_app_bin_valid_idc(u8 *pbt_buf)
+{
+	u32 len;
+#if (FTS_CHIP_TYPE != _FT8006)
+	/* 1. First Byte */
+	if (pbt_buf[0] != 0x02) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- the first byte(%x) error",
+						pbt_buf[0]);
+		return false;
+	}
+#endif
+	/* 2 PART1 ECC */
+	if (!ecc_check(pbt_buf, APP1_START, APP1_LEN, APP1_ECC_ADDR)) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- ecc1 error");
+		return false;
+	}
+
+	/* 3. PART2 ECC */
+	if ((data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN)
+		+ data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_NE)) != 0xFFFF) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- Length XOR error");
+		return false;
+	}
+
+	len = data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN);
+#if (FTS_CHIP_TYPE == _FT8006)
+	if ((data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_H)
+		+ data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_H_NE)) != 0xFFFF) {
+		FTS_DEBUG("[UPGRADE]APP.BIN Verify- Length2 XOR error");
+		return false;
+	}
+
+	len +=  ((u32)data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_H) << 16);
+#endif
+	FTS_DEBUG("%x %x %x %x", APP2_START, len,
+		((u32)data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN_H) << 16),
+		data_word(pbt_buf, APP_VERIF_ADDR+APP_LEN));
+
+	len -= APP2_START;
+
+	return ecc_check(pbt_buf, APP2_START, len, APP2_ECC_ADDR);
+}
+
+
+#endif /* IDC */
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_test.c b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_test.c
new file mode 100644
index 0000000..aa4c9cf
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_flash/focaltech_upgrade_test.c
@@ -0,0 +1,174 @@
+/*
+ *
+ * FocalTech fts TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_upgrade_test.c
+ *
+ * Author:    fupeipei
+ *
+ * Created:    2016-08-22
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "../focaltech_core.h"
+#include "../focaltech_flash.h"
+#include <linux/timer.h>
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+#define FTS_GET_UPGRADE_TIME                    0
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+#define FTS_DEBUG_UPGRADE(fmt, args...) do {\
+			pr_err("[FTS][UPGRADE]:################\n");\
+			pr_err("[FTS][UPGRADE]: "fmt"\n", ##args);\
+			pr_err("[FTS][UPGRADE]:################\n");\
+		} while (0)\
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+#if (FTS_UPGRADE_STRESS_TEST)
+/************************************************************************
+ * Name: fts_ctpm_auto_upgrade_pingpong
+ * Brief:  0
+ * Input:  0
+ * Output: 0
+ * Return: 0
+ ***********************************************************************/
+static int fts_ctpm_auto_upgrade_pingpong(struct i2c_client *client)
+{
+	u8 uc_tp_fm_ver;
+	int i_ret = 0;
+	u8 uc_upgrade_times = 0;
+
+	FTS_FUNC_ENTER();
+
+	/* pingpong test mode, need upgrade */
+	FTS_INFO("[UPGRADE]: pingpong test mode, need upgrade!!");
+	do {
+		uc_upgrade_times++;
+
+		/* fw upgrade */
+		i_ret = fts_ctpm_fw_upgrade(client);
+
+		if (i_ret == 0) {
+			/* upgrade success */
+			fts_i2c_read_reg(client, FTS_REG_FW_VER, &uc_tp_fm_ver);
+			FTS_DEBUG("[UPGRADE]: upgrade to new version 0x%x",
+					uc_tp_fm_ver);
+		} else {
+			/* upgrade fail */
+			/* if upgrade fail, reset to run ROM.
+			 * if app in flash is ok. TP will work success
+			 */
+			FTS_INFO("[UPGRADE]: upgrade fail, reset now!!");
+			fts_ctpm_rom_or_pram_reset(client);
+		}
+		/* if upgrade fail, upgrade again. then return */
+	} while ((i_ret != 0) && (uc_upgrade_times < 2));
+
+	FTS_FUNC_EXIT();
+	return i_ret;
+}
+
+/************************************************************************
+ * Name: fts_ctpm_auto_upgrade
+ * Brief:  0
+ * Input:  0
+ * Output: 0
+ * Return: 0
+ ***********************************************************************/
+void fts_ctpm_display_upgrade_time(bool start_time)
+{
+#if FTS_GET_UPGRADE_TIME
+	static struct timeval tpend;
+	static struct timeval tpstart;
+	static int timeuse;
+
+	if (start_time) {
+		do_gettimeofday(&tpstart);
+	} else {
+		do_gettimeofday(&tpend);
+		timeuse = 1000000 * (tpend.tv_sec-tpstart.tv_sec)
+				+ tpend.tv_usec-tpstart.tv_usec;
+		timeuse /= 1000000;
+		FTS_DEBUG("[UPGRADE]: upgrade success : Use time: %d Seconds!!",
+							timeuse);
+	}
+#endif
+}
+
+/************************************************************************
+ * Name: fts_ctpm_auto_upgrade
+ * Brief:  0
+ * Input:  0
+ * Output: 0
+ * Return: 0
+ ***********************************************************************/
+int fts_ctpm_auto_upgrade(struct i2c_client *client)
+{
+	int i_ret = 0;
+	static int uc_ErrorTimes;
+	static int uc_UpgradeTimes;
+
+
+	device_init_wakeup(&client->dev, 1);
+	pm_stay_awake(&client->dev);
+
+	/* (FTS_GET_VENDOR_ID_NUM == 0) */
+	g_fw_file = CTPM_FW;
+	g_fw_len = fts_getsize(FW_SIZE);
+	FTS_DEBUG("[UPGRADE]FW FILE:CTPM_FW, SIZE:%x", g_fw_len);
+
+	do {
+		uc_UpgradeTimes++;
+
+		FTS_DEBUG_UPGRADE("start to upgrade %d times !!",
+				uc_UpgradeTimes);
+
+		fts_ctpm_display_upgrade_time(true);
+
+		i_ret = fts_ctpm_auto_upgrade_pingpong(client);
+		if (i_ret == 0)
+			fts_ctpm_display_upgrade_time(false);
+		else
+			uc_ErrorTimes++;
+
+		FTS_DEBUG_UPGRADE("upgrade %d times, error %d times!!",
+				uc_UpgradeTimes, uc_ErrorTimes);
+	} while (uc_UpgradeTimes < (FTS_UPGRADE_TEST_NUMBER));
+
+	pm_relax(&client->dev);
+	device_init_wakeup(&client->dev, 0);
+
+	return 0;
+}
+#endif
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c b/drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c
new file mode 100644
index 0000000..d24cd8a
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_gesture.c
@@ -0,0 +1,650 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, Focaltech Ltd. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_gestrue.c
+ *
+ * Author: Focaltech Driver Team
+ *
+ * Created: 2016-08-08
+ *
+ * Abstract:
+ *
+ * Reference:
+ *
+ *****************************************************************************/
+
+/*****************************************************************************
+ * 1.Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+#if FTS_GESTURE_EN
+/******************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+#define KEY_GESTURE_U                           KEY_U
+#define KEY_GESTURE_UP                          KEY_UP
+#define KEY_GESTURE_DOWN                        KEY_DOWN
+#define KEY_GESTURE_LEFT                        KEY_LEFT
+#define KEY_GESTURE_RIGHT                       KEY_RIGHT
+#define KEY_GESTURE_O                           KEY_O
+#define KEY_GESTURE_E                           KEY_E
+#define KEY_GESTURE_M                           KEY_M
+#define KEY_GESTURE_L                           KEY_L
+#define KEY_GESTURE_W                           KEY_W
+#define KEY_GESTURE_S                           KEY_S
+#define KEY_GESTURE_V                           KEY_V
+#define KEY_GESTURE_C                           KEY_C
+#define KEY_GESTURE_Z                           KEY_Z
+
+#define GESTURE_LEFT                            0x20
+#define GESTURE_RIGHT                           0x21
+#define GESTURE_UP                              0x22
+#define GESTURE_DOWN                            0x23
+#define GESTURE_DOUBLECLICK                     0x24
+#define GESTURE_O                               0x30
+#define GESTURE_W                               0x31
+#define GESTURE_M                               0x32
+#define GESTURE_E                               0x33
+#define GESTURE_L                               0x44
+#define GESTURE_S                               0x46
+#define GESTURE_V                               0x54
+#define GESTURE_Z                               0x41
+#define GESTURE_C                               0x34
+#define FTS_GESTRUE_POINTS                      255
+#define FTS_GESTRUE_POINTS_HEADER               8
+
+#define GESTURE_SMALL_AREA      0x25    /* TP Coverage < 50% */
+#define GESTURE_LARGE_AREA      0x26    /* TP Coverage > 50% */
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+/*
+ * header        -   byte0:gesture id
+ *                   byte1:pointnum
+ *                   byte2~7:reserved
+ * coordinate_x  -   All gesture point x coordinate
+ * coordinate_y  -   All gesture point y coordinate
+ * mode          -   1:enable gesture function(default)
+ *               -   0:disable
+ * active        -   1:enter into gesture(suspend)
+ *                   0:gesture disable or resume
+ */
+struct fts_gesture_st {
+	u8 header[FTS_GESTRUE_POINTS_HEADER];
+	u16 coordinate_x[FTS_GESTRUE_POINTS];
+	u16 coordinate_y[FTS_GESTRUE_POINTS];
+	u8 mode;
+	u8 active;
+};
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+static struct fts_gesture_st fts_gesture_data;
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+static ssize_t fts_gesture_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+static ssize_t fts_gesture_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t fts_gesture_buf_show(struct device *dev,
+		struct device_attribute *attr, char *buf);
+static ssize_t fts_gesture_buf_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count);
+
+/* sysfs gesture node
+ *   read example: cat  fts_gesture_mode        ---read gesture mode
+ *   write example:echo 01 > fts_gesture_mode   ---write gesture mode to 01
+ *
+ */
+static DEVICE_ATTR(fts_gesture_mode, 0644,
+		fts_gesture_show, fts_gesture_store);
+/*
+ *   read example: cat fts_gesture_buf        ---read gesture buf
+ */
+static DEVICE_ATTR(fts_gesture_buf, 0644,
+		fts_gesture_buf_show, fts_gesture_buf_store);
+static struct attribute *fts_gesture_mode_attrs[] = {
+
+
+	&dev_attr_fts_gesture_mode.attr,
+	&dev_attr_fts_gesture_buf.attr,
+	NULL,
+};
+
+static struct attribute_group fts_gesture_group = {
+
+	.attrs = fts_gesture_mode_attrs,
+};
+
+/************************************************************************
+ * Name: fts_gesture_show
+ *  Brief:
+ *  Input: device, device attribute, char buf
+ * Output:
+ * Return:
+ ***********************************************************************/
+static ssize_t fts_gesture_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int count;
+	u8 val;
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+
+	mutex_lock(&fts_input_dev->mutex);
+	fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &val);
+	count = snprintf(buf, PAGE_SIZE, "Gesture Mode: %s\n",
+			fts_gesture_data.mode ? "On" : "Off");
+	count += snprintf(buf + count, PAGE_SIZE - count,
+				"Reg(0xD0) = %d\n", val);
+	mutex_unlock(&fts_input_dev->mutex);
+
+	return count;
+}
+
+/************************************************************************
+ * Name: fts_gesture_store
+ *  Brief:
+ *  Input: device, device attribute, char buf, char count
+ * Output:
+ * Return:
+ ***********************************************************************/
+static ssize_t fts_gesture_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	mutex_lock(&fts_input_dev->mutex);
+
+	if (FTS_SYSFS_ECHO_ON(buf)) {
+		FTS_INFO("[GESTURE]enable gesture");
+		fts_gesture_data.mode = ENABLE;
+	} else if (FTS_SYSFS_ECHO_OFF(buf)) {
+		FTS_INFO("[GESTURE]disable gesture");
+		fts_gesture_data.mode = DISABLE;
+	}
+
+	mutex_unlock(&fts_input_dev->mutex);
+
+	return count;
+}
+
+/************************************************************************
+ * Name: fts_gesture_buf_show
+ *  Brief:
+ *  Input: device, device attribute, char buf
+ * Output:
+ * Return:
+ ***********************************************************************/
+static ssize_t fts_gesture_buf_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int count;
+	int i = 0;
+
+	mutex_lock(&fts_input_dev->mutex);
+	count = snprintf(buf, PAGE_SIZE, "Gesture ID: 0x%x\n",
+			fts_gesture_data.header[0]);
+	count += snprintf(buf + count, PAGE_SIZE, "Gesture PointNum: %d\n",
+			fts_gesture_data.header[1]);
+	count += snprintf(buf + count, PAGE_SIZE, "Gesture Point Buf:\n");
+
+	for (i = 0; i < fts_gesture_data.header[1]; i++) {
+		count += snprintf(buf + count, PAGE_SIZE, "%3d(%4d,%4d) ",
+				i, fts_gesture_data.coordinate_x[i],
+				fts_gesture_data.coordinate_y[i]);
+		if ((i + 1)%4 == 0)
+			count += snprintf(buf + count, PAGE_SIZE, "\n");
+	}
+	count += snprintf(buf + count, PAGE_SIZE, "\n");
+	mutex_unlock(&fts_input_dev->mutex);
+
+	return count;
+}
+
+/************************************************************************
+ * Name: fts_gesture_buf_store
+ *  Brief:
+ *  Input: device, device attribute, char buf, char count
+ * Output:
+ * Return:
+ ***********************************************************************/
+static ssize_t fts_gesture_buf_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	/* place holder for future use */
+	return -EPERM;
+}
+
+/*****************************************************************************
+ *   Name: fts_create_gesture_sysfs
+ *  Brief:
+ *  Input:
+ * Output:
+ * Return: 0-success or others-error
+ *****************************************************************************/
+int fts_create_gesture_sysfs(struct i2c_client *client)
+{
+	int ret = 0;
+
+	ret = sysfs_create_group(&client->dev.kobj, &fts_gesture_group);
+	if (ret != 0) {
+		FTS_ERROR("[GESTURE]fts_gesture_group(sysfs) create failed!");
+		sysfs_remove_group(&client->dev.kobj, &fts_gesture_group);
+		return ret;
+	}
+	return 0;
+}
+
+/*****************************************************************************
+ *   Name: fts_gesture_report
+ *  Brief:
+ *  Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+static void fts_gesture_report(struct input_dev *input_dev, int gesture_id)
+{
+	int gesture;
+
+	FTS_FUNC_ENTER();
+	FTS_DEBUG("fts gesture_id==0x%x ", gesture_id);
+	switch (gesture_id) {
+	case GESTURE_LEFT:
+		gesture = KEY_GESTURE_LEFT;
+		break;
+	case GESTURE_RIGHT:
+		gesture = KEY_GESTURE_RIGHT;
+		break;
+	case GESTURE_UP:
+		gesture = KEY_GESTURE_UP;
+		break;
+	case GESTURE_DOWN:
+		gesture = KEY_GESTURE_DOWN;
+		break;
+	case GESTURE_DOUBLECLICK:
+		gesture = KEY_GESTURE_U;
+		break;
+	case GESTURE_O:
+		gesture = KEY_GESTURE_O;
+		break;
+	case GESTURE_W:
+		gesture = KEY_GESTURE_W;
+		break;
+	case GESTURE_M:
+		gesture = KEY_GESTURE_M;
+		break;
+	case GESTURE_E:
+		gesture = KEY_GESTURE_E;
+		break;
+	case GESTURE_L:
+		gesture = KEY_GESTURE_L;
+		break;
+	case GESTURE_S:
+		gesture = KEY_GESTURE_S;
+		break;
+	case GESTURE_V:
+		gesture = KEY_GESTURE_V;
+		break;
+	case GESTURE_Z:
+		gesture = KEY_GESTURE_Z;
+		break;
+	case  GESTURE_C:
+		gesture = KEY_GESTURE_C;
+		break;
+	default:
+		gesture = -1;
+		break;
+	}
+
+	/* report event key */
+	if (gesture != -1) {
+		FTS_DEBUG("Gesture Code=%d", gesture);
+		input_report_key(input_dev, gesture, 1);
+		input_sync(input_dev);
+		input_report_key(input_dev, gesture, 0);
+		input_sync(input_dev);
+	}
+
+	FTS_FUNC_EXIT();
+}
+
+/************************************************************************
+ *   Name: fts_gesture_readdata
+ *  Brief: read data from TP register
+ *  Input:
+ * Output:
+ * Return: fail <0
+ ***********************************************************************/
+static int fts_gesture_read_buffer(struct i2c_client *client,
+				u8 *buf, int read_bytes)
+{
+	int remain_bytes;
+	int ret;
+	int i;
+
+	if (read_bytes <= I2C_BUFFER_LENGTH_MAXINUM) {
+		ret = fts_i2c_read(client, buf, 1, buf, read_bytes);
+	} else {
+		ret = fts_i2c_read(client, buf, 1,
+				buf, I2C_BUFFER_LENGTH_MAXINUM);
+		remain_bytes = read_bytes - I2C_BUFFER_LENGTH_MAXINUM;
+		for (i = 1; remain_bytes > 0; i++) {
+			if (remain_bytes <= I2C_BUFFER_LENGTH_MAXINUM)
+				ret = fts_i2c_read(client, buf, 0, buf
+						+ I2C_BUFFER_LENGTH_MAXINUM * i,
+						remain_bytes);
+			else
+				ret = fts_i2c_read(client, buf, 0, buf
+						+ I2C_BUFFER_LENGTH_MAXINUM * i,
+						I2C_BUFFER_LENGTH_MAXINUM);
+			remain_bytes -= I2C_BUFFER_LENGTH_MAXINUM;
+		}
+	}
+
+	return ret;
+}
+
+/************************************************************************
+ *   Name: fts_gesture_fw
+ *  Brief: Check IC's gesture recognise by FW or not
+ *  Input:
+ * Output:
+ * Return: 1- FW  0- Driver
+ ***********************************************************************/
+static int fts_gesture_fw(void)
+{
+	int ret = 0;
+
+	switch (chip_types.chip_idh) {
+	case 0x54:
+	case 0x58:
+	case 0x64:
+	case 0x87:
+	case 0x86:
+	case 0x80:
+	case 0xE7:
+		ret = 1;
+		break;
+	default:
+		ret = 0;
+		break;
+	}
+	return ret;
+}
+
+/************************************************************************
+ *   Name: fts_gesture_readdata
+ *  Brief: read data from TP register
+ *  Input:
+ * Output:
+ * Return: fail <0
+ ***********************************************************************/
+int fts_gesture_readdata(struct i2c_client *client)
+{
+	u8 buf[FTS_GESTRUE_POINTS * 4] = { 0 };
+	int ret = -1;
+	int i = 0;
+	int gestrue_id = 0;
+	int read_bytes = 0;
+	u8 pointnum;
+
+	FTS_FUNC_ENTER();
+	/* init variable before read gesture point */
+	memset(fts_gesture_data.header, 0, FTS_GESTRUE_POINTS_HEADER);
+	memset(fts_gesture_data.coordinate_x, 0,
+			FTS_GESTRUE_POINTS * sizeof(u16));
+	memset(fts_gesture_data.coordinate_y, 0,
+			FTS_GESTRUE_POINTS * sizeof(u16));
+
+	buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
+	ret = fts_i2c_read(client, buf, 1, buf, FTS_GESTRUE_POINTS_HEADER);
+	if (ret < 0) {
+		FTS_ERROR("[GESTURE]Read gesture header data failed!!");
+		FTS_FUNC_EXIT();
+		return ret;
+	}
+
+	memcpy(fts_gesture_data.header, buf, FTS_GESTRUE_POINTS_HEADER);
+	gestrue_id = buf[0];
+	pointnum = buf[1];
+
+	if (gestrue_id == GESTURE_SMALL_AREA) {
+		FTS_INFO("[GESTURE] Wakeup gesture.");
+		input_report_key(fts_input_dev, KEY_POWER, 1);
+		input_sync(fts_input_dev);
+		input_report_key(fts_input_dev, KEY_POWER, 0);
+		input_sync(fts_input_dev);
+
+	} else if (gestrue_id == GESTURE_LARGE_AREA) {
+		FTS_INFO("[GESTURE] Large object detected.");
+	} else if (fts_gesture_fw()) {
+		/* FW recognize gesture */
+		read_bytes = ((int)pointnum) * 4 + 2;
+		buf[0] = FTS_REG_GESTURE_OUTPUT_ADDRESS;
+		FTS_DEBUG("[GESTURE]PointNum=%d", pointnum);
+		ret = fts_gesture_read_buffer(client, buf, read_bytes);
+		if (ret < 0) {
+			FTS_ERROR("[GESTURE]Read gesture touch data failed!!");
+			FTS_FUNC_EXIT();
+			return ret;
+		}
+
+		fts_gesture_report(fts_input_dev, gestrue_id);
+		for (i = 0; i < pointnum; i++) {
+			fts_gesture_data.coordinate_x[i] =
+				(((s16) buf[0 + (4 * i + 2)]) & 0x0F) << 8
+				| (((s16) buf[1 + (4 * i + 2)]) & 0xFF);
+			fts_gesture_data.coordinate_y[i] =
+				(((s16) buf[2 + (4 * i + 2)]) & 0x0F) << 8
+				| (((s16) buf[3 + (4 * i + 2)]) & 0xFF);
+		}
+
+
+	} else {
+		FTS_ERROR("[GESTURE]IC 0x%x need lib to support gestures.",
+							chip_types.chip_idh);
+	}
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/*****************************************************************************
+ *   Name: fts_gesture_recovery
+ *  Brief: recovery gesture state when reset or power on
+ *  Input:
+ * Output:
+ * Return:
+ *****************************************************************************/
+void fts_gesture_recovery(struct i2c_client *client)
+{
+	if (fts_gesture_data.mode && fts_gesture_data.active) {
+		fts_i2c_write_reg(client, 0xD1, 0xff);
+		fts_i2c_write_reg(client, 0xD2, 0xff);
+		fts_i2c_write_reg(client, 0xD5, 0xff);
+		fts_i2c_write_reg(client, 0xD6, 0xff);
+		fts_i2c_write_reg(client, 0xD7, 0xff);
+		fts_i2c_write_reg(client, 0xD8, 0xff);
+		fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, ENABLE);
+	}
+}
+
+/*****************************************************************************
+ *   Name: fts_gesture_suspend
+ *  Brief:
+ *  Input:
+ * Output: None
+ * Return: None
+ *****************************************************************************/
+int fts_gesture_suspend(struct i2c_client *i2c_client)
+{
+	int i;
+	u8 state;
+
+	FTS_FUNC_ENTER();
+
+	/* gesture not enable, return immediately */
+	if (fts_gesture_data.mode == 0) {
+		FTS_DEBUG("gesture is disabled");
+		FTS_FUNC_EXIT();
+		return -EINVAL;
+	}
+
+	for (i = 0; i < 5; i++) {
+		fts_i2c_write_reg(i2c_client, 0xd1, 0xff);
+		fts_i2c_write_reg(i2c_client, 0xd2, 0xff);
+		fts_i2c_write_reg(i2c_client, 0xd5, 0xff);
+		fts_i2c_write_reg(i2c_client, 0xd6, 0xff);
+		fts_i2c_write_reg(i2c_client, 0xd7, 0xff);
+		fts_i2c_write_reg(i2c_client, 0xd8, 0xff);
+		fts_i2c_write_reg(i2c_client, FTS_REG_GESTURE_EN, 0x01);
+		usleep_range(1000, 2000);
+		fts_i2c_read_reg(i2c_client, FTS_REG_GESTURE_EN, &state);
+		if (state == 1)
+			break;
+	}
+
+	if (i >= 5) {
+		FTS_ERROR("[GESTURE]Enter into gesture(suspend) failed!\n");
+		FTS_FUNC_EXIT();
+		return -EAGAIN;
+	}
+
+	fts_gesture_data.active = 1;
+	FTS_DEBUG("[GESTURE]Enter into gesture(suspend) successfully!");
+	FTS_FUNC_EXIT();
+	return 0;
+}
+
+/*****************************************************************************
+ *   Name: fts_gesture_resume
+ *  Brief:
+ *  Input:
+ * Output: None
+ * Return: None
+ *****************************************************************************/
+int fts_gesture_resume(struct i2c_client *client)
+{
+	int i;
+	u8 state;
+
+	FTS_FUNC_ENTER();
+
+	/* gesture not enable, return immediately */
+	if (fts_gesture_data.mode == 0) {
+		FTS_DEBUG("gesture is disabled");
+		FTS_FUNC_EXIT();
+		return -EINVAL;
+	}
+
+	if (fts_gesture_data.active == 0) {
+		FTS_DEBUG("gesture is unactive");
+		FTS_FUNC_EXIT();
+		return -EINVAL;
+	}
+
+	fts_gesture_data.active = 0;
+	for (i = 0; i < 5; i++) {
+		fts_i2c_write_reg(client, FTS_REG_GESTURE_EN, 0x00);
+		usleep_range(1000, 2000);
+		fts_i2c_read_reg(client, FTS_REG_GESTURE_EN, &state);
+		if (state == 0)
+			break;
+	}
+
+	if (i >= 5)
+		FTS_ERROR("[GESTURE]Clear gesture(resume) failed!\n");
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/*****************************************************************************
+ *   Name: fts_gesture_init
+ *  Brief:
+ *  Input:
+ * Output: None
+ * Return: None
+ *****************************************************************************/
+int fts_gesture_init(struct input_dev *input_dev, struct i2c_client *client)
+{
+	FTS_FUNC_ENTER();
+	input_set_capability(input_dev, EV_KEY, KEY_POWER);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_U);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_UP);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_DOWN);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_LEFT);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_RIGHT);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_O);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_E);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_M);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_L);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_W);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_S);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_V);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_Z);
+	input_set_capability(input_dev, EV_KEY, KEY_GESTURE_C);
+
+	__set_bit(KEY_GESTURE_RIGHT, input_dev->keybit);
+	__set_bit(KEY_GESTURE_LEFT, input_dev->keybit);
+	__set_bit(KEY_GESTURE_UP, input_dev->keybit);
+	__set_bit(KEY_GESTURE_DOWN, input_dev->keybit);
+	__set_bit(KEY_GESTURE_U, input_dev->keybit);
+	__set_bit(KEY_GESTURE_O, input_dev->keybit);
+	__set_bit(KEY_GESTURE_E, input_dev->keybit);
+	__set_bit(KEY_GESTURE_M, input_dev->keybit);
+	__set_bit(KEY_GESTURE_W, input_dev->keybit);
+	__set_bit(KEY_GESTURE_L, input_dev->keybit);
+	__set_bit(KEY_GESTURE_S, input_dev->keybit);
+	__set_bit(KEY_GESTURE_V, input_dev->keybit);
+	__set_bit(KEY_GESTURE_C, input_dev->keybit);
+	__set_bit(KEY_GESTURE_Z, input_dev->keybit);
+
+	fts_create_gesture_sysfs(client);
+	fts_gesture_data.mode = 1;
+	fts_gesture_data.active = 0;
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/************************************************************************
+ *   Name: fts_gesture_exit
+ *  Brief: call when driver removed
+ *  Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_gesture_exit(struct i2c_client *client)
+{
+	FTS_FUNC_ENTER();
+	sysfs_remove_group(&client->dev.kobj, &fts_gesture_group);
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+#endif
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c b/drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c
new file mode 100644
index 0000000..fabedbf
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_i2c.c
@@ -0,0 +1,206 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/************************************************************************
+ *
+ * File Name: focaltech_i2c.c
+ *
+ *    Author: fupeipei
+ *
+ *   Created: 2016-08-04
+ *
+ *  Abstract: i2c communication with TP
+ *
+ *   Version: v1.0
+ *
+ * Revision History:
+ *        v1.0:
+ *            First release. By fupeipei 2016-08-04
+ ************************************************************************/
+
+/*****************************************************************************
+ * Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+static DEFINE_MUTEX(i2c_rw_access);
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+
+/*****************************************************************************
+ * functions body
+ *****************************************************************************/
+
+/************************************************************************
+ * Name: fts_i2c_read
+ * Brief: i2c read
+ * Input: i2c info, write buf, write len, read buf, read len
+ * Output: get data in the 3rd buf
+ * Return: fail <0
+ ***********************************************************************/
+int fts_i2c_read(struct i2c_client *client, char *writebuf,
+		int writelen, char *readbuf, int readlen)
+{
+	int ret = -EIO;
+
+	mutex_lock(&i2c_rw_access);
+
+	if (readlen > 0) {
+		if (writelen > 0) {
+			struct i2c_msg msgs[] = {
+				{
+					.addr = client->addr,
+					.flags = 0,
+					.len = writelen,
+					.buf = writebuf,
+				},
+				{
+					.addr = client->addr,
+					.flags = I2C_M_RD,
+					.len = readlen,
+					.buf = readbuf,
+				},
+			};
+			ret = i2c_transfer(client->adapter, msgs, 2);
+			if (ret < 0)
+				FTS_ERROR("[IIC]: i2c_write error %d!!", ret);
+		} else {
+			struct i2c_msg msgs[] = {
+				{
+					.addr = client->addr,
+					.flags = I2C_M_RD,
+					.len = readlen,
+					.buf = readbuf,
+				},
+			};
+			ret = i2c_transfer(client->adapter, msgs, 1);
+			if (ret < 0)
+				FTS_ERROR("[IIC]: i2c_read error %d!!", ret);
+		}
+	}
+
+	mutex_unlock(&i2c_rw_access);
+
+	return ret;
+}
+
+/************************************************************************
+ * Name: fts_i2c_write
+ * Brief: i2c write
+ * Input: i2c info, write buf, write len
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+int fts_i2c_write(struct i2c_client *client, char *writebuf, int writelen)
+{
+	int ret = 0;
+
+	mutex_lock(&i2c_rw_access);
+
+	if (writelen > 0) {
+		struct i2c_msg msgs[] = {
+			{
+				.addr = client->addr,
+				.flags = 0,
+				.len = writelen,
+				.buf = writebuf,
+			},
+		};
+		ret = i2c_transfer(client->adapter, msgs, 1);
+		if (ret < 0)
+			FTS_ERROR("[IIC]: i2c_write error, ret=%d", ret);
+	}
+
+	mutex_unlock(&i2c_rw_access);
+
+	return ret;
+}
+
+/************************************************************************
+ * Name: fts_i2c_write_reg
+ * Brief: write register
+ * Input: i2c info, reg address, reg value
+ * Output: no
+ * Return: fail <0
+ ***********************************************************************/
+int fts_i2c_write_reg(struct i2c_client *client, u8 regaddr, u8 regvalue)
+{
+	u8 buf[2] = {0};
+
+	buf[0] = regaddr;
+	buf[1] = regvalue;
+	return fts_i2c_write(client, buf, sizeof(buf));
+}
+
+/************************************************************************
+ * Name: fts_i2c_read_reg
+ * Brief: read register
+ * Input: i2c info, reg address, reg value
+ * Output: get reg value
+ * Return: fail <0
+ ***********************************************************************/
+int fts_i2c_read_reg(struct i2c_client *client, u8 regaddr, u8 *regvalue)
+{
+	return fts_i2c_read(client, &regaddr, 1, regvalue, 1);
+}
+
+/************************************************************************
+ * Name: fts_i2c_init
+ * Brief: fts i2c init
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_i2c_init(void)
+{
+	FTS_FUNC_ENTER();
+
+	FTS_FUNC_EXIT();
+	return 0;
+}
+/************************************************************************
+ * Name: fts_i2c_exit
+ * Brief: fts i2c exit
+ * Input:
+ * Output:
+ * Return:
+ ***********************************************************************/
+int fts_i2c_exit(void)
+{
+	FTS_FUNC_ENTER();
+
+	FTS_FUNC_EXIT();
+	return 0;
+}
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_point_report_check.c b/drivers/input/touchscreen/focaltech_touch/focaltech_point_report_check.c
new file mode 100644
index 0000000..eca1c2b
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_point_report_check.c
@@ -0,0 +1,155 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_point_report_check.c
+ *
+ *    Author: WangTao
+ *
+ *   Created: 2016-11-16
+ *
+ *  Abstract: point report check function
+ *
+ *   Version: v1.0
+ *
+ * Revision History:
+ *        v1.0:
+ *            First release. By WangTao 2016-11-16
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+#if FTS_POINT_REPORT_CHECK_EN
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+#define POINT_REPORT_CHECK_WAIT_TIME              200    /* ms */
+
+/*****************************************************************************
+ * Private enumerations, structures and unions using typedef
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+static struct delayed_work fts_point_report_check_work;
+static struct workqueue_struct *fts_point_report_check_workqueue;
+
+/*****************************************************************************
+ * Global variable or extern global variabls/functions
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Static function prototypes
+ *****************************************************************************/
+
+/*****************************************************************************
+ * functions body
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ *  Name: fts_point_report_check_func
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static void fts_point_report_check_func(struct work_struct *work)
+{
+
+#if FTS_MT_PROTOCOL_B_EN
+	unsigned int finger_count = 0;
+#endif
+
+	FTS_FUNC_ENTER();
+	mutex_lock(&fts_wq_data->report_mutex);
+
+#if FTS_MT_PROTOCOL_B_EN
+	for (finger_count = 0;
+		finger_count < fts_wq_data->pdata->max_touch_number;
+		finger_count++) {
+		input_mt_slot(fts_input_dev, finger_count);
+		input_mt_report_slot_state(fts_input_dev,
+				MT_TOOL_FINGER, false);
+	}
+#else
+	input_mt_sync(fts_input_dev);
+#endif
+	input_report_key(fts_input_dev, BTN_TOUCH, 0);
+	input_sync(fts_input_dev);
+
+	mutex_unlock(&fts_wq_data->report_mutex);
+
+	FTS_FUNC_EXIT();
+}
+
+void fts_point_report_check_queue_work(void)
+{
+	cancel_delayed_work(&fts_point_report_check_work);
+	queue_delayed_work(fts_point_report_check_workqueue,
+			&fts_point_report_check_work,
+			msecs_to_jiffies(POINT_REPORT_CHECK_WAIT_TIME));
+}
+
+/*****************************************************************************
+ *  Name: fts_point_report_check_init
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return: < 0: Fail to create esd check queue
+ *****************************************************************************/
+int fts_point_report_check_init(void)
+{
+	FTS_FUNC_ENTER();
+
+	INIT_DELAYED_WORK(&fts_point_report_check_work,
+			fts_point_report_check_func);
+	fts_point_report_check_workqueue =
+		create_workqueue("fts_point_report_check_func_wq");
+	if (fts_point_report_check_workqueue == NULL)
+		FTS_ERROR("[POINT_REPORT]: Failed to create workqueue!!");
+	else
+		FTS_DEBUG("[POINT_REPORT]: Success to create workqueue!!");
+
+	FTS_FUNC_EXIT();
+
+	return 0;
+}
+
+/*****************************************************************************
+ *  Name: fts_point_report_check_exit
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+int fts_point_report_check_exit(void)
+{
+	FTS_FUNC_ENTER();
+
+	destroy_workqueue(fts_point_report_check_workqueue);
+
+	FTS_FUNC_EXIT();
+	return 0;
+}
+#endif /* FTS_POINT_REPORT_CHECK_EN */
+
diff --git a/drivers/input/touchscreen/focaltech_touch/focaltech_sensor.c b/drivers/input/touchscreen/focaltech_touch/focaltech_sensor.c
new file mode 100644
index 0000000..e8e86b5
--- /dev/null
+++ b/drivers/input/touchscreen/focaltech_touch/focaltech_sensor.c
@@ -0,0 +1,326 @@
+/*
+ *
+ * FocalTech TouchScreen driver.
+ *
+ * Copyright (c) 2010-2017, FocalTech Systems, Ltd., all rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*****************************************************************************
+ *
+ * File Name: focaltech_esdcheck.c
+ *
+ *    Author: Focaltech Driver Team
+ *
+ *   Created: 2016-08-03
+ *
+ *  Abstract: Sensor
+ *
+ *   Version: v1.0
+ *
+ * Revision History:
+ *        v1.0:
+ *            First release. By luougojin 2016-08-03
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Included header files
+ *****************************************************************************/
+#include "focaltech_core.h"
+
+#if FTS_PSENSOR_EN
+/*****************************************************************************
+ * Private constant and macro definitions using #define
+ *****************************************************************************/
+/* psensor register address*/
+#define FTS_REG_PSENSOR_ENABLE                  0xB0
+#define FTS_REG_PSENSOR_STATUS                  0x01
+
+/* psensor register bits*/
+#define FTS_PSENSOR_ENABLE_MASK                 0x01
+#define FTS_PSENSOR_STATUS_NEAR                 0xC0
+#define FTS_PSENSOR_STATUS_FAR                  0xE0
+#define FTS_PSENSOR_FAR_TO_NEAR                 0
+#define FTS_PSENSOR_NEAR_TO_FAR                 1
+#define FTS_PSENSOR_ORIGINAL_STATE_FAR          1
+#define FTS_PSENSOR_WAKEUP_TIMEOUT              500
+
+/*****************************************************************************
+ * Static variables
+ *****************************************************************************/
+static struct sensors_classdev __maybe_unused sensors_proximity_cdev = {
+
+	.name = "fts-proximity",
+	.vendor = "FocalTech",
+	.version = 1,
+	.handle = SENSORS_PROXIMITY_HANDLE,
+	.type = SENSOR_TYPE_PROXIMITY,
+	.max_range = "5.0",
+	.resolution = "5.0",
+	.sensor_power = "0.1",
+	.min_delay = 0,
+	.fifo_reserved_event_count = 0,
+	.fifo_max_event_count = 0,
+	.enabled = 0,
+	.delay_msec = 200,
+	.sensors_enable = NULL,
+	.sensors_poll_delay = NULL,
+};
+
+/*****************************************************************************
+ * functions body
+ *****************************************************************************/
+/*****************************************************************************
+ *  Name: fts_psensor_support_enabled
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static inline bool fts_psensor_support_enabled(void)
+{
+	/*return config_enabled(CONFIG_TOUCHSCREEN_FTS_PSENSOR);*/
+	return FTS_PSENSOR_EN;
+}
+
+/*****************************************************************************
+ *  Name: fts_psensor_enable
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static void fts_psensor_enable(struct fts_ts_data *data, int enable)
+{
+	u8 state;
+	int ret = -1;
+
+	if (data->client == NULL)
+		return;
+
+	fts_i2c_read_reg(data->client, FTS_REG_PSENSOR_ENABLE, &state);
+	if (enable)
+		state |= FTS_PSENSOR_ENABLE_MASK;
+	else
+		state &= ~FTS_PSENSOR_ENABLE_MASK;
+
+	ret = fts_i2c_write_reg(data->client, FTS_REG_PSENSOR_ENABLE, state);
+	if (ret < 0)
+		FTS_ERROR("write psensor switch command failed");
+
+}
+
+/*****************************************************************************
+ *  Name: fts_psensor_enable_set
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int fts_psensor_enable_set(struct sensors_classdev *sensors_cdev,
+			unsigned int enable)
+{
+	struct fts_psensor_platform_data *psensor_pdata =
+			container_of(sensors_cdev,
+			struct fts_psensor_platform_data, ps_cdev);
+	struct fts_ts_data *data = psensor_pdata->data;
+	struct input_dev *input_dev = data->psensor_pdata->input_psensor_dev;
+
+	mutex_lock(&input_dev->mutex);
+	fts_psensor_enable(data, enable);
+	psensor_pdata->tp_psensor_data = FTS_PSENSOR_ORIGINAL_STATE_FAR;
+	if (enable)
+		psensor_pdata->tp_psensor_opened = 1;
+	else
+		psensor_pdata->tp_psensor_opened = 0;
+
+	mutex_unlock(&input_dev->mutex);
+
+	return enable;
+}
+
+/*****************************************************************************
+ *  Name: fts_read_tp_psensor_data
+ *  Brief:
+ *  Input:
+ *  Output:
+ *  Return:
+ *****************************************************************************/
+static int fts_read_tp_psensor_data(struct fts_ts_data *data)
+{
+	u8 psensor_status;
+	char tmp;
+	int ret = 1;
+
+	fts_i2c_read_reg(data->client,
+			FTS_REG_PSENSOR_STATUS, &psensor_status);
+
+	tmp = data->psensor_pdata->tp_psensor_data;
+	if (psensor_status == FTS_PSENSOR_STATUS_NEAR)
+		data->psensor_pdata->tp_psensor_data =
+			FTS_PSENSOR_FAR_TO_NEAR;
+	else if (psensor_status == FTS_PSENSOR_STATUS_FAR)
+		data->psensor_pdata->tp_psensor_data =
+			FTS_PSENSOR_NEAR_TO_FAR;
+
+	if (tmp != data->psensor_pdata->tp_psensor_data) {
+		FTS_ERROR("%s sensor data changed", __func__);
+		ret = 0;
+	}
+
+	return ret;
+}
+
+
+int fts_sensor_read_data(struct fts_ts_data *data)
+{
+	int ret = 0;
+
+	if (fts_psensor_support_enabled()
+			&& data->psensor_pdata->tp_psensor_opened) {
+		ret = fts_read_tp_psensor_data(data);
+		if (!ret) {
+			if (data->suspended)
+				pm_wakeup_event(&data->client->dev,
+						FTS_PSENSOR_WAKEUP_TIMEOUT);
+
+			input_report_abs(data->psensor_pdata->input_psensor_dev,
+					ABS_DISTANCE,
+					data->psensor_pdata->tp_psensor_data);
+			input_sync(data->psensor_pdata->input_psensor_dev);
+		}
+
+		return 1;
+	}
+
+	return 0;
+}
+
+int fts_sensor_suspend(struct fts_ts_data *data)
+{
+	int ret = 0;
+
+	if (fts_psensor_support_enabled()  &&
+		 device_may_wakeup(&data->client->dev) &&
+		 data->psensor_pdata->tp_psensor_opened) {
+		ret = enable_irq_wake(data->client->irq);
+		if (ret != 0)
+			FTS_ERROR("%s: set_irq_wake failed", __func__);
+
+		data->suspended = true;
+		return 1;
+	}
+
+	return 0;
+}
+
+
+int fts_sensor_resume(struct fts_ts_data *data)
+{
+	int ret = 0;
+
+	if (fts_psensor_support_enabled()
+			&& device_may_wakeup(&data->client->dev)
+			&& data->psensor_pdata->tp_psensor_opened) {
+		ret = disable_irq_wake(data->client->irq);
+		if (ret)
+			FTS_ERROR("%s: disable_irq_wake failed",  __func__);
+
+		data->suspended = false;
+		return 1;
+	}
+
+	return 0;
+}
+
+
+int fts_sensor_init(struct fts_ts_data *data)
+{
+	struct fts_psensor_platform_data *psensor_pdata;
+	struct input_dev *psensor_input_dev;
+	int err;
+
+	if (fts_psensor_support_enabled()) {
+		device_init_wakeup(&data->client->dev, 1);
+		psensor_pdata = devm_kzalloc(&data->client->dev,
+				sizeof(struct fts_psensor_platform_data),
+				GFP_KERNEL);
+		if (!psensor_pdata) {
+			FTS_ERROR("Failed to allocate memory");
+			goto irq_free;
+		}
+
+		data->psensor_pdata = psensor_pdata;
+
+		psensor_input_dev = input_allocate_device();
+		if (!psensor_input_dev) {
+			FTS_ERROR("Failed to allocate device");
+			goto free_psensor_pdata;
+		}
+
+		__set_bit(EV_ABS, psensor_input_dev->evbit);
+		input_set_abs_params(psensor_input_dev, ABS_DISTANCE,
+				0, 1, 0, 0);
+		psensor_input_dev->name = "proximity";
+		psensor_input_dev->id.bustype = BUS_I2C;
+		psensor_input_dev->dev.parent = &data->client->dev;
+		data->psensor_pdata->input_psensor_dev = psensor_input_dev;
+
+		err = input_register_device(psensor_input_dev);
+		if (err) {
+			FTS_ERROR("Unable to register device, err=%d", err);
+			goto free_psensor_input_dev;
+		}
+
+		psensor_pdata->ps_cdev = sensors_proximity_cdev;
+		psensor_pdata->ps_cdev.sensors_enable = fts_psensor_enable_set;
+		psensor_pdata->data = data;
+
+		err = sensors_classdev_register(&data->client->dev,
+					&psensor_pdata->ps_cdev);
+		if (err)
+			goto unregister_psensor_input_device;
+	}
+
+	return 0;
+
+unregister_psensor_input_device:
+	if (fts_psensor_support_enabled())
+		input_unregister_device(data->psensor_pdata->input_psensor_dev);
+free_psensor_input_dev:
+	if (fts_psensor_support_enabled())
+		input_free_device(data->psensor_pdata->input_psensor_dev);
+free_psensor_pdata:
+	if (fts_psensor_support_enabled()) {
+		devm_kfree(&data->client->dev, psensor_pdata);
+		data->psensor_pdata = NULL;
+	}
+irq_free:
+	if (fts_psensor_support_enabled())
+		device_init_wakeup(&data->client->dev, 0);
+	free_irq(data->client->irq, data);
+
+	return 1;
+}
+
+int fts_sensor_remove(struct fts_ts_data *data)
+{
+	if (fts_psensor_support_enabled()) {
+		device_init_wakeup(&data->client->dev, 0);
+		sensors_classdev_unregister(&data->psensor_pdata->ps_cdev);
+		input_unregister_device(data->psensor_pdata->input_psensor_dev);
+		devm_kfree(&data->client->dev, data->psensor_pdata);
+		data->psensor_pdata = NULL;
+	}
+	return 0;
+}
+#endif  /* FTS_PSENSOR_EN */
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index bc6d121..6c9446e 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -229,7 +229,7 @@
 
 static void gic_eoi_irq(struct irq_data *d)
 {
-	writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
+	writel_relaxed_no_log(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
 }
 
 static void gic_eoimode1_eoi_irq(struct irq_data *d)
@@ -340,8 +340,8 @@
 	gic_lock_irqsave(flags);
 	mask = 0xff << shift;
 	bit = gic_cpu_map[cpu] << shift;
-	val = readl_relaxed(reg) & ~mask;
-	writel_relaxed(val | bit, reg);
+	val = readl_relaxed_no_log(reg) & ~mask;
+	writel_relaxed_no_log(val | bit, reg);
 	gic_unlock_irqrestore(flags);
 
 	return IRQ_SET_MASK_OK_DONE;
@@ -355,19 +355,21 @@
 	void __iomem *cpu_base = gic_data_cpu_base(gic);
 
 	do {
-		irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
+		irqstat = readl_relaxed_no_log(cpu_base + GIC_CPU_INTACK);
 		irqnr = irqstat & GICC_IAR_INT_ID_MASK;
 
 		if (likely(irqnr > 15 && irqnr < 1020)) {
 			if (static_key_true(&supports_deactivate))
-				writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
+				writel_relaxed_no_log(irqstat,
+						cpu_base + GIC_CPU_EOI);
 			handle_domain_irq(gic->domain, irqnr, regs);
 			continue;
 		}
 		if (irqnr < 16) {
-			writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
+			writel_relaxed_no_log(irqstat, cpu_base + GIC_CPU_EOI);
 			if (static_key_true(&supports_deactivate))
-				writel_relaxed(irqstat, cpu_base + GIC_CPU_DEACTIVATE);
+				writel_relaxed_no_log(irqstat,
+						cpu_base + GIC_CPU_DEACTIVATE);
 #ifdef CONFIG_SMP
 			/*
 			 * Ensure any shared data written by the CPU sending
@@ -656,16 +658,18 @@
 
 	ptr = raw_cpu_ptr(gic->saved_ppi_enable);
 	for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
-		ptr[i] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
+		ptr[i] = readl_relaxed_no_log(dist_base +
+				GIC_DIST_ENABLE_SET + i * 4);
 
 	ptr = raw_cpu_ptr(gic->saved_ppi_active);
 	for (i = 0; i < DIV_ROUND_UP(32, 32); i++)
-		ptr[i] = readl_relaxed(dist_base + GIC_DIST_ACTIVE_SET + i * 4);
+		ptr[i] = readl_relaxed_no_log(dist_base +
+				GIC_DIST_ACTIVE_SET + i * 4);
 
 	ptr = raw_cpu_ptr(gic->saved_ppi_conf);
 	for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
-		ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
-
+		ptr[i] = readl_relaxed_no_log(dist_base +
+				GIC_DIST_CONFIG + i * 4);
 }
 
 void gic_cpu_restore(struct gic_chip_data *gic)
@@ -686,27 +690,31 @@
 
 	ptr = raw_cpu_ptr(gic->saved_ppi_enable);
 	for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
-		writel_relaxed(GICD_INT_EN_CLR_X32,
+		writel_relaxed_no_log(GICD_INT_EN_CLR_X32,
 			       dist_base + GIC_DIST_ENABLE_CLEAR + i * 4);
-		writel_relaxed(ptr[i], dist_base + GIC_DIST_ENABLE_SET + i * 4);
+		writel_relaxed_no_log(ptr[i], dist_base +
+				GIC_DIST_ENABLE_SET + i * 4);
 	}
 
 	ptr = raw_cpu_ptr(gic->saved_ppi_active);
 	for (i = 0; i < DIV_ROUND_UP(32, 32); i++) {
-		writel_relaxed(GICD_INT_EN_CLR_X32,
+		writel_relaxed_no_log(GICD_INT_EN_CLR_X32,
 			       dist_base + GIC_DIST_ACTIVE_CLEAR + i * 4);
-		writel_relaxed(ptr[i], dist_base + GIC_DIST_ACTIVE_SET + i * 4);
+		writel_relaxed_no_log(ptr[i], dist_base +
+				GIC_DIST_ACTIVE_SET + i * 4);
 	}
 
 	ptr = raw_cpu_ptr(gic->saved_ppi_conf);
 	for (i = 0; i < DIV_ROUND_UP(32, 16); i++)
-		writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
+		writel_relaxed_no_log(ptr[i], dist_base +
+				GIC_DIST_CONFIG + i * 4);
 
 	for (i = 0; i < DIV_ROUND_UP(32, 4); i++)
-		writel_relaxed(GICD_INT_DEF_PRI_X4,
+		writel_relaxed_no_log(GICD_INT_DEF_PRI_X4,
 					dist_base + GIC_DIST_PRI + i * 4);
 
-	writel_relaxed(GICC_INT_PRI_THRESHOLD, cpu_base + GIC_CPU_PRIMASK);
+	writel_relaxed_no_log(GICC_INT_PRI_THRESHOLD,
+				cpu_base + GIC_CPU_PRIMASK);
 	gic_cpu_if_up(gic);
 }
 
@@ -799,7 +807,7 @@
 
 	if (unlikely(nr_cpu_ids == 1)) {
 		/* Only one CPU? let's do a self-IPI... */
-		writel_relaxed(2 << 24 | irq,
+		writel_relaxed_no_log(2 << 24 | irq,
 			       gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
 		return;
 	}
@@ -817,7 +825,8 @@
 	dmb(ishst);
 
 	/* this always happens on GIC0 */
-	writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+	writel_relaxed_no_log(map << 16 | irq,
+			gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
 
 	gic_unlock_irqrestore(flags);
 }
diff --git a/drivers/irqchip/qcom/mpm.c b/drivers/irqchip/qcom/mpm.c
index 72bd7fd..a8b8b9b 100644
--- a/drivers/irqchip/qcom/mpm.c
+++ b/drivers/irqchip/qcom/mpm.c
@@ -162,13 +162,26 @@
 	}
 }
 
-static inline void msm_mpm_set_type(struct irq_data *d,
+static void msm_mpm_program_set_type(bool set, unsigned int reg,
+					unsigned int index, unsigned int mask)
+{
+	u32 type;
+
+	type = msm_mpm_read(reg, index);
+	if (set)
+		type = ENABLE_TYPE(type, mask);
+	else
+		type = CLEAR_TYPE(type, mask);
+
+	msm_mpm_write(reg, index, type);
+}
+
+static void msm_mpm_set_type(struct irq_data *d,
 					unsigned int flowtype)
 {
 	int mpm_pin[MAX_MPM_PIN_PER_IRQ] = {-1, -1};
 	unsigned long flags;
 	int i = 0;
-	u32 type;
 	unsigned int index, mask;
 	unsigned int reg = 0;
 
@@ -180,24 +193,24 @@
 		index = mpm_pin[i]/32;
 		mask = mpm_pin[i]%32;
 
-		if (flowtype & IRQ_TYPE_LEVEL_HIGH)
-			reg = MPM_REG_FALLING_EDGE;
-
-		if (flowtype & IRQ_TYPE_EDGE_RISING)
-			reg = MPM_REG_RISING_EDGE;
-
-		if (flowtype & IRQ_TYPE_EDGE_FALLING)
-			reg = MPM_REG_POLARITY;
-
 		spin_lock_irqsave(&mpm_lock, flags);
-		type = msm_mpm_read(reg, index);
-
-		if (flowtype)
-			type = ENABLE_TYPE(type, mask);
+		reg = MPM_REG_RISING_EDGE;
+		if (flowtype & IRQ_TYPE_EDGE_RISING)
+			msm_mpm_program_set_type(1, reg, index, mask);
 		else
-			type = CLEAR_TYPE(type, mask);
+			msm_mpm_program_set_type(0, reg, index, mask);
 
-		msm_mpm_write(reg, index, type);
+		reg = MPM_REG_FALLING_EDGE;
+		if (flowtype & IRQ_TYPE_EDGE_FALLING)
+			msm_mpm_program_set_type(1, reg, index, mask);
+		else
+			msm_mpm_program_set_type(0, reg, index, mask);
+
+		reg = MPM_REG_POLARITY;
+		if (flowtype & IRQ_TYPE_LEVEL_HIGH)
+			msm_mpm_program_set_type(1, reg, index, mask);
+		else
+			msm_mpm_program_set_type(0, reg, index, mask);
 		spin_unlock_irqrestore(&mpm_lock, flags);
 	}
 }
@@ -512,6 +525,8 @@
 						IRQCHIP_STATE_PENDING, true);
 
 		}
+
+		msm_mpm_write(MPM_REG_STATUS, i, 0);
 	}
 	return IRQ_HANDLED;
 }
diff --git a/drivers/mailbox/msm_qmp.c b/drivers/mailbox/msm_qmp.c
index d6e41ae..9e898b8 100644
--- a/drivers/mailbox/msm_qmp.c
+++ b/drivers/mailbox/msm_qmp.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
@@ -893,7 +893,7 @@
 								mdev->name);
 
 	ret = devm_request_irq(&pdev->dev, mdev->rx_irq_line, qmp_irq_handler,
-		IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND | IRQF_SHARED,
+		IRQF_TRIGGER_RISING | IRQF_SHARED,
 		edge_node->name, mdev);
 	if (ret < 0) {
 		qmp_mbox_remove(pdev);
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 85e9058..b4f83f7 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
@@ -535,10 +535,9 @@
 					CAM_SYNC_STATE_SIGNALED_ERROR);
 				if (rc == -EALREADY) {
 					CAM_ERR(CAM_CTXT,
-						"Req: %llu already signalled, sync_id:%d",
-						req->request_id,
-						req->out_map_entries[i].
-						sync_id);
+					"Req: %llu already signalled, sync_id:%d",
+					req->request_id,
+					req->out_map_entries[i].sync_id);
 					break;
 				}
 			}
@@ -629,6 +628,7 @@
 	struct cam_ctx_request *req = NULL;
 	struct cam_hw_flush_args flush_args;
 	uint32_t i;
+	int32_t sync_id = 0;
 	int rc = 0;
 
 	CAM_DBG(CAM_CTXT, "[%s] E: NRT flush req", ctx->dev_name);
@@ -683,20 +683,20 @@
 
 	if (req) {
 		if (flush_args.num_req_pending || flush_args.num_req_active) {
-			for (i = 0; i < req->num_out_map_entries; i++)
-				if (req->out_map_entries[i].sync_id != -1) {
-					rc = cam_sync_signal(
-						req->out_map_entries[i].sync_id,
+			for (i = 0; i < req->num_out_map_entries; i++) {
+				sync_id =
+					req->out_map_entries[i].sync_id;
+				if (sync_id != -1) {
+					rc = cam_sync_signal(sync_id,
 						CAM_SYNC_STATE_SIGNALED_ERROR);
 					if (rc == -EALREADY) {
 						CAM_ERR(CAM_CTXT,
-							"Req: %llu already signalled, sync_id:%d",
-							req->request_id,
-							req->out_map_entries[i].
-							sync_id);
+						"Req: %llu already signalled, sync_id:%d",
+						req->request_id, sync_id);
 						break;
 					}
 				}
+			}
 			if (flush_args.num_req_active) {
 				spin_lock(&ctx->lock);
 				list_add_tail(&req->list, &ctx->free_req_list);
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_hw.c
index e7de207..5e4ff0d 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
@@ -873,6 +873,7 @@
 	if (!CAM_CPAS_CLIENT_VALID(client_indx))
 		return -EINVAL;
 
+	mutex_lock(&cpas_hw->hw_mutex);
 	mutex_lock(&cpas_core->client_mutex[client_indx]);
 
 	if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
@@ -892,6 +893,7 @@
 
 unlock_client:
 	mutex_unlock(&cpas_core->client_mutex[client_indx]);
+	mutex_unlock(&cpas_hw->hw_mutex);
 	return rc;
 }
 
@@ -907,6 +909,7 @@
 	struct cam_axi_vote *axi_vote;
 	enum cam_vote_level applied_level = CAM_SVS_VOTE;
 	int rc;
+	struct cam_cpas_private_soc *soc_private = NULL;
 
 	if (!hw_priv || !start_args) {
 		CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK",
@@ -922,6 +925,8 @@
 
 	cpas_hw = (struct cam_hw_info *)hw_priv;
 	cpas_core = (struct cam_cpas *) cpas_hw->core_info;
+	soc_private = (struct cam_cpas_private_soc *)
+		cpas_hw->soc_info.soc_private;
 	cmd_hw_start = (struct cam_cpas_hw_cmd_start *)start_args;
 	client_indx = CAM_CPAS_GET_CLIENT_IDX(cmd_hw_start->client_handle);
 	ahb_vote = cmd_hw_start->ahb_vote;
@@ -1005,8 +1010,9 @@
 	cpas_client->started = true;
 	cpas_core->streamon_clients++;
 
-	CAM_DBG(CAM_CPAS, "client_indx=%d, streamon_clients=%d",
-		client_indx, cpas_core->streamon_clients);
+	CAM_DBG(CAM_CPAS, "client=%s, streamon_clients=%d",
+		soc_private->client_name[client_indx],
+		cpas_core->streamon_clients);
 done:
 	mutex_unlock(&cpas_core->client_mutex[client_indx]);
 	mutex_unlock(&cpas_hw->hw_mutex);
@@ -1028,6 +1034,7 @@
 	struct cam_cpas_client *cpas_client;
 	struct cam_ahb_vote ahb_vote;
 	struct cam_axi_vote axi_vote;
+	struct cam_cpas_private_soc *soc_private = NULL;
 	int rc = 0;
 	long result;
 
@@ -1045,6 +1052,8 @@
 
 	cpas_hw = (struct cam_hw_info *)hw_priv;
 	cpas_core = (struct cam_cpas *) cpas_hw->core_info;
+	soc_private = (struct cam_cpas_private_soc *)
+		cpas_hw->soc_info.soc_private;
 	cmd_hw_stop = (struct cam_cpas_hw_cmd_stop *)stop_args;
 	client_indx = CAM_CPAS_GET_CLIENT_IDX(cmd_hw_stop->client_handle);
 
@@ -1054,8 +1063,9 @@
 	mutex_lock(&cpas_hw->hw_mutex);
 	mutex_lock(&cpas_core->client_mutex[client_indx]);
 
-	CAM_DBG(CAM_CPAS, "client_indx=%d, streamon_clients=%d",
-		client_indx, cpas_core->streamon_clients);
+	CAM_DBG(CAM_CPAS, "client=%s, streamon_clients=%d",
+		soc_private->client_name[client_indx],
+		cpas_core->streamon_clients);
 
 	if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
 		CAM_ERR(CAM_CPAS, "Client %d is not started", client_indx);
diff --git a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_session_defs.h b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_session_defs.h
index 7b2cb8b..69e6ccf 100644
--- a/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_session_defs.h
+++ b/drivers/media/platform/msm/camera/cam_icp/fw_inc/hfi_session_defs.h
@@ -261,8 +261,8 @@
 };
 
 struct frame_buffer {
-	uint32_t buffer_ptr[MAX_NUM_OF_IMAGE_PLANES];
-	uint32_t meta_buffer_ptr[MAX_NUM_OF_IMAGE_PLANES];
+	uint32_t buf_ptr[MAX_NUM_OF_IMAGE_PLANES];
+	uint32_t meta_buf_ptr[MAX_NUM_OF_IMAGE_PLANES];
 } __packed;
 
 struct bps_frame_process_data {
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 0e36ec0..feb0bd8 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
@@ -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
@@ -33,6 +33,40 @@
 };
 EXPORT_SYMBOL(cam_bps_hw_info);
 
+static bool cam_bps_cpas_cb(uint32_t client_handle, void *userdata,
+	struct cam_cpas_irq_data *irq_data)
+{
+	bool error_handled = false;
+
+	if (!irq_data)
+		return error_handled;
+
+	switch (irq_data->irq_type) {
+	case CAM_CAMNOC_IRQ_IPE_BPS_UBWC_DECODE_ERROR:
+		CAM_ERR_RATE_LIMIT(CAM_ICP,
+			"IPE/BPS UBWC Decode error type=%d status=%x thr_err=%d, fcl_err=%d, len_md_err=%d, format_err=%d",
+			irq_data->irq_type,
+			irq_data->u.dec_err.decerr_status.value,
+			irq_data->u.dec_err.decerr_status.thr_err,
+			irq_data->u.dec_err.decerr_status.fcl_err,
+			irq_data->u.dec_err.decerr_status.len_md_err,
+			irq_data->u.dec_err.decerr_status.format_err);
+		error_handled = true;
+		break;
+	case CAM_CAMNOC_IRQ_IPE_BPS_UBWC_ENCODE_ERROR:
+		CAM_ERR_RATE_LIMIT(CAM_ICP,
+			"IPE/BPS UBWC Encode error type=%d status=%x",
+			irq_data->irq_type,
+			irq_data->u.enc_err.encerr_status.value);
+		error_handled = true;
+		break;
+	default:
+		break;
+	}
+
+	return error_handled;
+}
+
 int cam_bps_register_cpas(struct cam_hw_soc_info *soc_info,
 			struct cam_bps_device_core_info *core_info,
 			uint32_t hw_idx)
@@ -42,7 +76,7 @@
 
 	cpas_register_params.dev = &soc_info->pdev->dev;
 	memcpy(cpas_register_params.identifier, "bps", sizeof("bps"));
-	cpas_register_params.cam_cpas_client_cb = NULL;
+	cpas_register_params.cam_cpas_client_cb = cam_bps_cpas_cb;
 	cpas_register_params.cell_index = hw_idx;
 	cpas_register_params.userdata = NULL;
 
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 c6c9b85..9ed71d2 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
@@ -308,8 +308,9 @@
 		ctx_data = &hw_mgr->ctx_data[i];
 		mutex_lock(&ctx_data->ctx_mutex);
 		if ((ctx_data->state == CAM_ICP_CTX_STATE_ACQUIRED) &&
-			(ICP_DEV_TYPE_TO_CLK_TYPE(ctx_data->
-			icp_dev_acquire_info->dev_type) == clk_info->hw_type)) {
+			(ICP_DEV_TYPE_TO_CLK_TYPE(
+			ctx_data->icp_dev_acquire_info->dev_type)
+			== clk_info->hw_type)) {
 			busy = cam_icp_frame_pending(ctx_data);
 			if (busy) {
 				mutex_unlock(&ctx_data->ctx_mutex);
@@ -2994,6 +2995,8 @@
 	uint64_t cpu_addr = 0;
 	struct ipe_frame_process_data *frame_process_data = NULL;
 	struct bps_frame_process_data *bps_frame_process_data = NULL;
+	struct frame_set *ipe_set = NULL;
+	struct frame_buffer *bps_bufs = NULL;
 
 	cmd_desc = (struct cam_cmd_buf_desc *)
 		((uint32_t *) &packet->payload + packet->cmd_buf_offset/4);
@@ -3042,14 +3045,11 @@
 		frame_process_data->cdm_buffer_addr = 0;
 		frame_process_data->cdm_prog_base = 0;
 		for (i = 0; i < frame_process_data->frames_in_batch; i++) {
+			ipe_set = &frame_process_data->framesets[i];
 			for (j = 0; j < IPE_IO_IMAGES_MAX; j++) {
 				for (k = 0; k < MAX_NUM_OF_IMAGE_PLANES; k++) {
-					frame_process_data->
-					framesets[i].buffers[j].
-					buffer_ptr[k] = 0;
-					frame_process_data->
-					framesets[i].buffers[j].
-					meta_buffer_ptr[k] = 0;
+					ipe_set->buffers[j].buf_ptr[k] = 0;
+					ipe_set->buffers[j].meta_buf_ptr[k] = 0;
 				}
 			}
 		}
@@ -3066,11 +3066,10 @@
 		bps_frame_process_data->strip_lib_out_addr = 0;
 		bps_frame_process_data->cdm_prog_addr = 0;
 		for (i = 0; i < BPS_IO_IMAGES_MAX; i++) {
+			bps_bufs = &bps_frame_process_data->buffers[i];
 			for (j = 0; j < MAX_NUM_OF_IMAGE_PLANES; j++) {
-				bps_frame_process_data->
-				buffers[i].buffer_ptr[j] = 0;
-				bps_frame_process_data->
-				buffers[i].meta_buffer_ptr[j] = 0;
+				bps_bufs->buf_ptr[j] = 0;
+				bps_bufs->meta_buf_ptr[j] = 0;
 			}
 		}
 	}
@@ -4028,8 +4027,8 @@
 		CAM_ERR(CAM_ICP, "read num bps devices failed");
 		goto num_bps_failed;
 	}
-	icp_hw_mgr.devices[CAM_ICP_DEV_BPS] = kzalloc(
-		sizeof(struct cam_hw_intf *) * num_dev, GFP_KERNEL);
+	icp_hw_mgr.devices[CAM_ICP_DEV_BPS] = kcalloc(num_dev,
+		sizeof(struct cam_hw_intf *), GFP_KERNEL);
 	if (!icp_hw_mgr.devices[CAM_ICP_DEV_BPS]) {
 		rc = -ENOMEM;
 		goto num_bps_failed;
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 8753bbb..1106453 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
@@ -26,6 +26,97 @@
 
 static const char isp_dev_name[] = "isp";
 
+#define INC_STATE_MONITOR_HEAD(head) \
+	(atomic64_add_return(1, head) % \
+	CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES)
+
+static void __cam_isp_ctx_update_state_monitor_array(
+	struct cam_isp_context *ctx_isp,
+	enum cam_isp_state_change_trigger trigger_type,
+	uint32_t req_id)
+{
+	int iterator = 0;
+
+	iterator = INC_STATE_MONITOR_HEAD(&ctx_isp->state_monitor_head);
+	ctx_isp->cam_isp_ctx_state_monitor[iterator].curr_state =
+		ctx_isp->substate_activated;
+	ctx_isp->cam_isp_ctx_state_monitor[iterator].trigger =
+		trigger_type;
+	ctx_isp->cam_isp_ctx_state_monitor[iterator].req_id =
+		req_id;
+	ctx_isp->cam_isp_ctx_state_monitor[iterator].evt_time_stamp =
+		jiffies_to_msecs(jiffies);
+}
+
+static const char *__cam_isp_ctx_substate_val_to_type(
+	uint32_t type)
+{
+	switch (type) {
+	case CAM_ISP_CTX_ACTIVATED_SOF:
+		return "SOF";
+	case CAM_ISP_CTX_ACTIVATED_APPLIED:
+		return "APPLIED";
+	case CAM_ISP_CTX_ACTIVATED_EPOCH:
+		return "EPOCH";
+	case CAM_ISP_CTX_ACTIVATED_BUBBLE:
+		return "BUBBLE";
+	case CAM_ISP_CTX_ACTIVATED_BUBBLE_APPLIED:
+		return "BUBBLE_APPLIED";
+	case CAM_ISP_CTX_ACTIVATED_HALT:
+		return "HALT";
+	default:
+		return "CAM_ISP_CTX_INVALID_STATE";
+	}
+}
+
+static const char *__cam_isp_hw_evt_val_to_type(
+	uint32_t evt_id)
+{
+	switch (evt_id) {
+	case CAM_ISP_STATE_CHANGE_TRIGGER_ERROR:
+		return "ERROR";
+	case CAM_ISP_STATE_CHANGE_TRIGGER_SOF:
+		return "SOF";
+	case CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE:
+		return "REG_UPDATE";
+	case CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH:
+		return "EPOCH";
+	case CAM_ISP_STATE_CHANGE_TRIGGER_EOF:
+		return "EOF";
+	case CAM_ISP_STATE_CHANGE_TRIGGER_DONE:
+		return "DONE";
+	default:
+		return "CAM_ISP_EVENT_INVALID";
+	}
+}
+
+static void __cam_isp_ctx_dump_state_monitor_array(
+	struct cam_isp_context *ctx_isp)
+{
+	int i = 0;
+	uint64_t state_head = 0;
+	uint64_t index;
+
+	state_head = atomic64_read(&ctx_isp->state_monitor_head);
+	CAM_ERR_RATE_LIMIT(CAM_ISP,
+		"Dumping state information for preceding requests");
+
+	for (i = CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES - 1; i >= 0;
+		i--) {
+		index = (((state_head - i) +
+			CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES) %
+			CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES);
+		CAM_ERR_RATE_LIMIT(CAM_ISP,
+		"time[0x%llx] req_id[%u] state[%s] evt_type[%s]",
+		ctx_isp->cam_isp_ctx_state_monitor[index].evt_time_stamp,
+		ctx_isp->cam_isp_ctx_state_monitor[index].req_id,
+		__cam_isp_ctx_substate_val_to_type(
+		ctx_isp->cam_isp_ctx_state_monitor[index].curr_state),
+		__cam_isp_hw_evt_val_to_type(
+		ctx_isp->cam_isp_ctx_state_monitor[index].trigger));
+	}
+}
+
 static int __cam_isp_ctx_enqueue_request_in_order(
 	struct cam_context *ctx, struct cam_ctx_request *req)
 {
@@ -134,46 +225,46 @@
 	return rc;
 }
 
-static const char *__cam_isp_resource_handle_id_to_type
-	(uint32_t resource_handle)
+static const char *__cam_isp_resource_handle_id_to_type(
+	uint32_t resource_handle)
 {
 	switch (resource_handle) {
 	case CAM_ISP_IFE_OUT_RES_FULL:
-		return "CAM_ISP_IFE_OUT_RES_FULL";
+		return "FULL";
 	case CAM_ISP_IFE_OUT_RES_DS4:
-		return "CAM_ISP_IFE_OUT_RES_DS4";
+		return "DS4";
 	case CAM_ISP_IFE_OUT_RES_DS16:
-		return "CAM_ISP_IFE_OUT_RES_DS16";
+		return "DS16";
 	case CAM_ISP_IFE_OUT_RES_RAW_DUMP:
-		return "CAM_ISP_IFE_OUT_RES_RAW_DUMP";
+		return "RAW_DUMP";
 	case CAM_ISP_IFE_OUT_RES_FD:
-		return "CAM_ISP_IFE_OUT_RES_FD";
+		return "FD";
 	case CAM_ISP_IFE_OUT_RES_PDAF:
-		return "CAM_ISP_IFE_OUT_RES_PDAF";
+		return "PDAF";
 	case CAM_ISP_IFE_OUT_RES_RDI_0:
-		return "CAM_ISP_IFE_OUT_RES_RDI_0";
+		return "RDI_0";
 	case CAM_ISP_IFE_OUT_RES_RDI_1:
-		return "CAM_ISP_IFE_OUT_RES_RDI_1";
+		return "RDI_1";
 	case CAM_ISP_IFE_OUT_RES_RDI_2:
-		return "CAM_ISP_IFE_OUT_RES_RDI_2";
+		return "RDI_2";
 	case CAM_ISP_IFE_OUT_RES_RDI_3:
-		return "CAM_ISP_IFE_OUT_RES_RDI_3";
+		return "RDI_3";
 	case CAM_ISP_IFE_OUT_RES_STATS_HDR_BE:
-		return "CAM_ISP_IFE_OUT_RES_STATS_HDR_BE";
+		return "STATS_HDR_BE";
 	case CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST:
-		return "CAM_ISP_IFE_OUT_RES_STATS_HDR_BHIST";
+		return "STATS_HDR_BHIST";
 	case CAM_ISP_IFE_OUT_RES_STATS_TL_BG:
-		return "CAM_ISP_IFE_OUT_RES_STATS_TL_BG";
+		return "STATS_TL_BG";
 	case CAM_ISP_IFE_OUT_RES_STATS_BF:
-		return "CAM_ISP_IFE_OUT_RES_STATS_BF";
+		return "STATS_BF";
 	case CAM_ISP_IFE_OUT_RES_STATS_AWB_BG:
-		return "CAM_ISP_IFE_OUT_RES_STATS_AWB_BG";
+		return "STATS_AWB_BG";
 	case CAM_ISP_IFE_OUT_RES_STATS_BHIST:
-		return "CAM_ISP_IFE_OUT_RES_STATS_BHIST";
+		return "STATS_BHIST";
 	case CAM_ISP_IFE_OUT_RES_STATS_RS:
-		return "CAM_ISP_IFE_OUT_RES_STATS_RS";
+		return "STATS_RS";
 	case CAM_ISP_IFE_OUT_RES_STATS_CS:
-		return "CAM_ISP_IFE_OUT_RES_STATS_CS";
+		return "STATS_CS";
 	default:
 		return "CAM_ISP_Invalid_Resource_Type";
 	}
@@ -350,6 +441,9 @@
 	}
 
 end:
+	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
+		CAM_ISP_STATE_CHANGE_TRIGGER_DONE,
+		ctx_isp->base->req_list->request_id);
 	return rc;
 }
 
@@ -510,6 +604,11 @@
 {
 	int rc = 0;
 	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
+	struct cam_ctx_request *req;
+	struct cam_context *ctx = ctx_isp->base;
+
+	req = list_last_entry(&ctx->pending_req_list,
+		struct cam_ctx_request, list);
 
 	if (!evt_data) {
 		CAM_ERR(CAM_ISP, "in valid sof event data");
@@ -518,6 +617,8 @@
 
 	ctx_isp->frame_id++;
 	ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
+	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
+		CAM_ISP_STATE_CHANGE_TRIGGER_SOF, req->request_id);
 	CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
 		ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
 
@@ -528,11 +629,11 @@
 	void *evt_data)
 {
 	int rc = 0;
-	struct cam_ctx_request *req;
+	struct cam_ctx_request *req = NULL;
 	struct cam_isp_ctx_req *req_isp;
 	struct cam_context *ctx = ctx_isp->base;
 
-	if (ctx->state != CAM_CTX_ACTIVATED) {
+	if (ctx->state != CAM_CTX_ACTIVATED && ctx_isp->frame_id > 1) {
 		CAM_DBG(CAM_ISP, "invalid RUP");
 		goto end;
 	}
@@ -560,6 +661,11 @@
 				CAM_ISP_CTX_ACTIVATED_EPOCH;
 		}
 	}
+	if (req != NULL) {
+		__cam_isp_ctx_update_state_monitor_array(ctx_isp,
+			CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE,
+			req->request_id);
+	}
 end:
 	return rc;
 }
@@ -627,6 +733,15 @@
 	CAM_DBG(CAM_ISP, "next substate %d",
 		ctx_isp->substate_activated);
 end:
+	if (request_id == 0) {
+		req = list_last_entry(&ctx->active_req_list,
+			struct cam_ctx_request, list);
+		__cam_isp_ctx_update_state_monitor_array(ctx_isp,
+			CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, req->request_id);
+	} else {
+		__cam_isp_ctx_update_state_monitor_array(ctx_isp,
+			CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, request_id);
+	}
 	return 0;
 }
 
@@ -649,6 +764,7 @@
 	int rc = 0;
 	struct cam_context                    *ctx = ctx_isp->base;
 	struct cam_isp_hw_sof_event_data      *sof_event_data = evt_data;
+	struct cam_ctx_request *req;
 
 	if (!evt_data) {
 		CAM_ERR(CAM_ISP, "in valid sof event data");
@@ -663,6 +779,10 @@
 	else
 		CAM_DBG(CAM_ISP, "Still need to wait for the buf done");
 
+	req = list_last_entry(&ctx->active_req_list,
+		struct cam_ctx_request, list);
+	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
+		CAM_ISP_STATE_CHANGE_TRIGGER_SOF, ctx->req_list->request_id);
 	CAM_DBG(CAM_ISP, "next substate %d",
 		ctx_isp->substate_activated);
 
@@ -761,6 +881,10 @@
 	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
 	CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
 end:
+	req = list_last_entry(&ctx->active_req_list, struct cam_ctx_request,
+		list);
+	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
+		CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, req->request_id);
 	return 0;
 }
 
@@ -772,6 +896,9 @@
 		(struct cam_isp_hw_done_event_data *) evt_data;
 
 	rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 1);
+	__cam_isp_ctx_update_state_monitor_array(ctx_isp,
+		CAM_ISP_STATE_CHANGE_TRIGGER_DONE,
+		ctx_isp->base->req_list->request_id);
 	return rc;
 }
 
@@ -786,6 +913,7 @@
 	struct cam_isp_ctx_req          *req_isp = NULL;
 	struct cam_req_mgr_error_notify  notify;
 	uint64_t                         error_request_id;
+	struct cam_hw_fence_map_entry   *fence_map_out = NULL;
 
 	struct cam_context *ctx = ctx_isp->base;
 	struct cam_isp_hw_error_event_data  *error_event_data =
@@ -814,18 +942,18 @@
 			if (!req_isp->bubble_report) {
 				for (i = 0; i < req_isp->num_fence_map_out;
 					i++) {
+					fence_map_out =
+						&req_isp->fence_map_out[i];
 					CAM_ERR(CAM_ISP, "req %llu, Sync fd %x",
-						req->request_id,
-						req_isp->fence_map_out[i].
-						sync_id);
+					req->request_id,
+					req_isp->fence_map_out[i].sync_id);
 					if (req_isp->fence_map_out[i].sync_id
 						!= -1) {
 						rc = cam_sync_signal(
-						req_isp->fence_map_out[i].
-						sync_id,
+						fence_map_out->sync_id,
 						CAM_SYNC_STATE_SIGNALED_ERROR);
-						req_isp->fence_map_out[i].
-						sync_id = -1;
+						fence_map_out->sync_id =
+						-1;
 					}
 				}
 				list_del_init(&req->list);
@@ -893,6 +1021,14 @@
 		rc = -EFAULT;
 	}
 
+
+	list_del_init(&req->list);
+	list_add(&req->list, &ctx->pending_req_list);
+	/* might need to check if active list is empty */
+	if (req != NULL) {
+		__cam_isp_ctx_update_state_monitor_array(ctx_isp,
+			CAM_ISP_STATE_CHANGE_TRIGGER_ERROR, req->request_id);
+	}
 	CAM_DBG(CAM_ISP, "Exit");
 	return rc;
 }
@@ -1013,7 +1149,7 @@
 	struct cam_ctx_request          *active_req;
 	struct cam_isp_ctx_req          *req_isp;
 	struct cam_isp_ctx_req          *active_req_isp;
-	struct cam_isp_context          *ctx_isp;
+	struct cam_isp_context          *ctx_isp = NULL;
 	struct cam_hw_config_args        cfg;
 
 	if (list_empty(&ctx->pending_req_list)) {
@@ -1087,6 +1223,11 @@
 		spin_unlock_bh(&ctx->lock);
 	}
 end:
+	if (ctx_isp != NULL) {
+		__cam_isp_ctx_update_state_monitor_array(ctx_isp,
+			CAM_ISP_STATE_CHANGE_TRIGGER_SOF,
+			ctx->req_list->request_id);
+	}
 	return rc;
 }
 
@@ -2390,16 +2531,16 @@
 	struct cam_req_mgr_apply_request *apply)
 {
 	int rc = 0;
+	struct cam_ctx_ops *ctx_ops = NULL;
 	struct cam_isp_context *ctx_isp =
 		(struct cam_isp_context *) ctx->ctx_priv;
 
 	trace_cam_apply_req("ISP", apply->request_id);
 	CAM_DBG(CAM_ISP, "Enter: apply req in Substate %d request _id:%lld",
 		 ctx_isp->substate_activated, apply->request_id);
-	if (ctx_isp->substate_machine[ctx_isp->substate_activated].
-		crm_ops.apply_req) {
-		rc = ctx_isp->substate_machine[ctx_isp->substate_activated].
-			crm_ops.apply_req(ctx, apply);
+	ctx_ops = &ctx_isp->substate_machine[ctx_isp->substate_activated];
+	if (ctx_ops->crm_ops.apply_req) {
+		rc = ctx_ops->crm_ops.apply_req(ctx, apply);
 	} else {
 		CAM_ERR_RATE_LIMIT(CAM_ISP,
 			"No handle function in activated substate %d",
@@ -2420,6 +2561,7 @@
 	uint32_t evt_id, void *evt_data)
 {
 	int rc = 0;
+	struct cam_isp_ctx_irq_ops *irq_ops = NULL;
 	struct cam_context *ctx = (struct cam_context *)context;
 	struct cam_isp_context *ctx_isp =
 		(struct cam_isp_context *)ctx->ctx_priv;
@@ -2431,13 +2573,13 @@
 
 	CAM_DBG(CAM_ISP, "Enter: State %d, Substate %d, evt id %d",
 		 ctx->state, ctx_isp->substate_activated, evt_id);
-	if (ctx_isp->substate_machine_irq[ctx_isp->substate_activated].
-		irq_ops[evt_id]) {
-		rc = ctx_isp->substate_machine_irq[ctx_isp->substate_activated].
-			irq_ops[evt_id](ctx_isp, evt_data);
+	irq_ops = &ctx_isp->substate_machine_irq[ctx_isp->substate_activated];
+	if (irq_ops->irq_ops[evt_id]) {
+		rc = irq_ops->irq_ops[evt_id](ctx_isp, evt_data);
 	} else {
 		CAM_DBG(CAM_ISP, "No handle function for substate %d",
 			ctx_isp->substate_activated);
+		__cam_isp_ctx_dump_state_monitor_array(ctx_isp);
 	}
 	CAM_DBG(CAM_ISP, "Exit: State %d Substate %d",
 		 ctx->state, ctx_isp->substate_activated);
@@ -2551,6 +2693,12 @@
 	ctx_base->state_machine = cam_isp_ctx_top_state_machine;
 	ctx_base->ctx_priv = ctx;
 
+	/* initializing current state for error logging */
+	for (i = 0; i < CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES; i++) {
+		ctx->cam_isp_ctx_state_monitor[i].curr_state =
+		CAM_ISP_CTX_ACTIVATED_MAX;
+	}
+	atomic64_set(&ctx->state_monitor_head, -1);
 err:
 	return rc;
 }
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
index 38ea58d..1eae89f 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.h
@@ -28,11 +28,16 @@
 #define CAM_ISP_CTX_RES_MAX                     20
 
 /*
- * Maxiimum configuration entry size  - This is based on the
+ * Maximum configuration entry size  - This is based on the
  * worst case DUAL IFE use case plus some margin.
  */
 #define CAM_ISP_CTX_CFG_MAX                     22
 
+/*
+ * Maximum entries in state monitoring array for error logging
+ */
+#define CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES   20
+
 /* forward declaration */
 struct cam_isp_context;
 
@@ -56,6 +61,19 @@
 	CAM_ISP_CTX_ACTIVATED_MAX,
 };
 
+/**
+ * enum cam_isp_state_change_trigger - Different types of ISP events
+ *
+ */
+enum cam_isp_state_change_trigger {
+	CAM_ISP_STATE_CHANGE_TRIGGER_ERROR,
+	CAM_ISP_STATE_CHANGE_TRIGGER_SOF,
+	CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE,
+	CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH,
+	CAM_ISP_STATE_CHANGE_TRIGGER_EOF,
+	CAM_ISP_STATE_CHANGE_TRIGGER_DONE,
+	CAM_ISP_STATE_CHANGE_TRIGGER_MAX
+};
 
 /**
  * struct cam_isp_ctx_irq_ops - Function table for handling IRQ callbacks
@@ -101,23 +119,44 @@
 };
 
 /**
- * struct cam_isp_context  - ISP context object
+ * struct cam_isp_context_state_monitor - ISP context state
+ *                                        monitoring for
+ *                                        debug purposes
  *
- * @base:                  Common context object pointer
- * @frame_id:              Frame id tracking for the isp context
- * @substate_actiavted:    Current substate for the activated state.
- * @substate_machine:      ISP substate machine for external interface
- * @substate_machine_irq:  ISP substate machine for irq handling
- * @req_base:              Common request object storage
- * @req_isp:               ISP private request object storage
- * @hw_ctx:                HW object returned by the acquire device command
- * @sof_timestamp_val:     Captured time stamp value at sof hw event
- * @active_req_cnt:        Counter for the active request
- * @reported_req_id:       Last reported request id
- * @subscribe_event:       The irq event mask that CRM subscribes to, IFE will
- *                         invoke CRM cb at those event.
- * @last_applied_req_id:   Last applied request id
- * @frame_skip_count:      Number of frame to skip before change state
+ *@curr_state:          Current sub state that received req
+ *@req_type:            Event type of incoming req
+ *@req_id:              Request id
+ *@evt_time_stamp       Current time stamp
+ *
+ */
+struct cam_isp_context_state_monitor {
+	enum cam_isp_ctx_activated_substate  curr_state;
+	enum cam_isp_state_change_trigger    trigger;
+	uint32_t                             req_id;
+	int64_t                              frame_id;
+	uint64_t                             evt_time_stamp;
+};
+
+/**
+ * struct cam_isp_context   -  ISP context object
+ *
+ * @base:                      Common context object pointer
+ * @frame_id:                  Frame id tracking for the isp context
+ * @substate_actiavted:        Current substate for the activated state.
+ * @substate_machine:          ISP substate machine for external interface
+ * @substate_machine_irq:      ISP substate machine for irq handling
+ * @req_base:                  Common request object storage
+ * @req_isp:                   ISP private request object storage
+ * @hw_ctx:                    HW object returned by the acquire device command
+ * @sof_timestamp_val:         Captured time stamp value at sof hw event
+ * @active_req_cnt:            Counter for the active request
+ * @reported_req_id:           Last reported request id
+ * @subscribe_event:           The irq event mask that CRM subscribes to, IFE
+ *                             will invoke CRM cb at those event.
+ * @last_applied_req_id:       Last applied request id
+ * @frame_skip_count:          Number of frame to skip before change state
+ * @state_monitor_head:        Write index to the state monitoring array
+ * @cam_isp_ctx_state_monitor: State monitoring array
  *
  */
 struct cam_isp_context {
@@ -138,6 +177,9 @@
 	uint32_t                         subscribe_event;
 	int64_t                          last_applied_req_id;
 	uint32_t                         frame_skip_count;
+	atomic64_t                       state_monitor_head;
+	struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[
+		CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES];
 };
 
 /**
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 4628172..6e140e2 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
@@ -1809,7 +1809,6 @@
 	if (cam_cdm_stream_off(ctx->cdm_handle))
 		CAM_ERR(CAM_ISP, "CDM stream off failed %d",
 			ctx->cdm_handle);
-	cam_tasklet_stop(ctx->common.tasklet_info);
 
 	CAM_DBG(CAM_ISP, "Going to stop IFE Mux");
 
@@ -1831,6 +1830,8 @@
 		}
 	}
 
+	cam_tasklet_stop(ctx->common.tasklet_info);
+
 	/*
 	 * If Context does not have PIX resources and has only RDI resource
 	 * then take the first base index.
@@ -4031,6 +4032,8 @@
 	int rc = -EFAULT;
 	int i, j;
 	struct cam_iommu_handle cdm_handles;
+	struct cam_ife_hw_mgr_ctx *ctx_pool;
+	struct cam_ife_hw_mgr_res *res_list_ife_out;
 
 	CAM_DBG(CAM_ISP, "Enter");
 
@@ -4135,9 +4138,10 @@
 		INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_cid);
 		INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_csid);
 		INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].res_list_ife_src);
+		ctx_pool = &g_ife_hw_mgr.ctx_pool[i];
 		for (j = 0; j < CAM_IFE_HW_OUT_RES_MAX; j++) {
-			INIT_LIST_HEAD(&g_ife_hw_mgr.ctx_pool[i].
-				res_list_ife_out[j].list);
+			res_list_ife_out = &ctx_pool->res_list_ife_out[j];
+			INIT_LIST_HEAD(&res_list_ife_out->list);
 		}
 
 		/* init context pool */
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 3606af9..1d38f3b 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
@@ -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
@@ -414,6 +414,8 @@
 	struct cam_ife_hw_mgr_res          *hw_mgr_res;
 	struct cam_isp_hw_get_cmd_update    update_buf;
 	struct cam_isp_hw_get_wm_update     wm_update;
+	struct cam_hw_fence_map_entry      *out_map_entries;
+	struct cam_hw_fence_map_entry      *in_map_entries;
 	uint32_t                            kmd_buf_remain_size;
 	uint32_t                            i, j, num_out_buf, num_in_buf;
 	uint32_t                            res_id_out, res_id_in, plane_id;
@@ -458,14 +460,15 @@
 			CAM_DBG(CAM_ISP,
 				"configure output io with fill fence %d",
 				fill_fence);
+			out_map_entries =
+				&prepare->out_map_entries[num_out_buf];
 			if (fill_fence) {
 				if (num_out_buf <
 					prepare->max_out_map_entries) {
-					prepare->out_map_entries[num_out_buf].
-						resource_handle =
-							io_cfg[i].resource_type;
-					prepare->out_map_entries[num_out_buf].
-						sync_id = io_cfg[i].fence;
+					out_map_entries->resource_handle =
+						io_cfg[i].resource_type;
+					out_map_entries->sync_id =
+						io_cfg[i].fence;
 					num_out_buf++;
 				} else {
 					CAM_ERR(CAM_ISP, "ln_out:%d max_ln:%d",
@@ -486,14 +489,14 @@
 			CAM_DBG(CAM_ISP,
 				"configure input io with fill fence %d",
 				fill_fence);
+			in_map_entries =
+				&prepare->in_map_entries[num_in_buf];
 			if (fill_fence) {
 				if (num_in_buf < prepare->max_in_map_entries) {
-					prepare->in_map_entries[num_in_buf].
-						resource_handle =
-							io_cfg[i].resource_type;
-					prepare->in_map_entries[num_in_buf].
-						sync_id =
-							io_cfg[i].fence;
+					in_map_entries->resource_handle =
+						io_cfg[i].resource_type;
+					in_map_entries->sync_id =
+						io_cfg[i].fence;
 					num_in_buf++;
 				} else {
 					CAM_ERR(CAM_ISP, "ln_in:%d imax_ln:%d",
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 24df4ce..feb79cc 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
@@ -336,9 +336,11 @@
 
 int cam_irq_controller_enable_irq(void *irq_controller, uint32_t handle)
 {
-	struct cam_irq_controller  *controller  = irq_controller;
-	struct cam_irq_evt_handler *evt_handler = NULL;
-	struct cam_irq_evt_handler *evt_handler_temp;
+	struct cam_irq_controller   *controller  = irq_controller;
+	struct cam_irq_evt_handler  *evt_handler = NULL;
+	struct cam_irq_evt_handler  *evt_handler_temp;
+	struct cam_irq_register_obj *irq_register = NULL;
+	enum cam_irq_priority_level priority;
 	unsigned long               flags = 0;
 	unsigned int                i;
 	uint32_t                    irq_mask;
@@ -369,14 +371,14 @@
 		return rc;
 	}
 
+	priority = evt_handler->priority;
 	for (i = 0; i < controller->num_registers; i++) {
-		controller->irq_register_arr[i].
-		top_half_enable_mask[evt_handler->priority] |=
+		irq_register = &controller->irq_register_arr[i];
+		irq_register->top_half_enable_mask[priority] |=
 			evt_handler->evt_bit_mask_arr[i];
 
 		irq_mask = cam_io_r_mb(controller->mem_base +
-			controller->irq_register_arr[i].
-			mask_reg_offset);
+			irq_register->mask_reg_offset);
 		irq_mask |= evt_handler->evt_bit_mask_arr[i];
 
 		cam_io_w_mb(irq_mask, controller->mem_base +
@@ -390,9 +392,11 @@
 
 int cam_irq_controller_disable_irq(void *irq_controller, uint32_t handle)
 {
-	struct cam_irq_controller  *controller  = irq_controller;
-	struct cam_irq_evt_handler *evt_handler = NULL;
-	struct cam_irq_evt_handler *evt_handler_temp;
+	struct cam_irq_controller   *controller  = irq_controller;
+	struct cam_irq_evt_handler  *evt_handler = NULL;
+	struct cam_irq_evt_handler  *evt_handler_temp;
+	struct cam_irq_register_obj *irq_register;
+	enum cam_irq_priority_level priority;
 	unsigned long               flags = 0;
 	unsigned int                i;
 	uint32_t                    irq_mask;
@@ -423,31 +427,27 @@
 		return rc;
 	}
 
+	priority = evt_handler->priority;
 	for (i = 0; i < controller->num_registers; i++) {
-		controller->irq_register_arr[i].
-		top_half_enable_mask[evt_handler->priority] &=
+		irq_register = &controller->irq_register_arr[i];
+		irq_register->top_half_enable_mask[priority] &=
 			~(evt_handler->evt_bit_mask_arr[i]);
 
 		irq_mask = cam_io_r_mb(controller->mem_base +
-			controller->irq_register_arr[i].
-			mask_reg_offset);
+			irq_register->mask_reg_offset);
 		CAM_DBG(CAM_ISP, "irq_mask 0x%x before disable 0x%x",
-			controller->irq_register_arr[i].mask_reg_offset,
-			irq_mask);
+			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 +
-			controller->irq_register_arr[i].
-			mask_reg_offset);
+			irq_register->mask_reg_offset);
 		CAM_DBG(CAM_ISP, "irq_mask 0x%x after disable 0x%x",
-			controller->irq_register_arr[i].mask_reg_offset,
-			irq_mask);
+			irq_register->mask_reg_offset, irq_mask);
 
 		/* Clear the IRQ bits of this handler */
 		cam_io_w_mb(evt_handler->evt_bit_mask_arr[i],
 			controller->mem_base +
-			controller->irq_register_arr[i].
-			clear_reg_offset);
+			irq_register->clear_reg_offset);
 
 		if (controller->global_clear_offset)
 			cam_io_w_mb(
@@ -464,9 +464,11 @@
 int cam_irq_controller_unsubscribe_irq(void *irq_controller,
 	uint32_t handle)
 {
-	struct cam_irq_controller  *controller  = irq_controller;
-	struct cam_irq_evt_handler *evt_handler = NULL;
-	struct cam_irq_evt_handler *evt_handler_temp;
+	struct cam_irq_controller   *controller  = irq_controller;
+	struct cam_irq_evt_handler  *evt_handler = NULL;
+	struct cam_irq_evt_handler  *evt_handler_temp;
+	struct cam_irq_register_obj *irq_register;
+	enum cam_irq_priority_level priority;
 	uint32_t                    i;
 	uint32_t                    found = 0;
 	uint32_t                    irq_mask;
@@ -490,26 +492,24 @@
 		}
 	}
 
+	priority = evt_handler->priority;
 	if (found) {
 		for (i = 0; i < controller->num_registers; i++) {
-			controller->irq_register_arr[i].
-				top_half_enable_mask[evt_handler->priority] &=
+			irq_register = &controller->irq_register_arr[i];
+			irq_register->top_half_enable_mask[priority] &=
 				~(evt_handler->evt_bit_mask_arr[i]);
 
 			irq_mask = cam_io_r_mb(controller->mem_base +
-				controller->irq_register_arr[i].
-				mask_reg_offset);
+				irq_register->mask_reg_offset);
 			irq_mask &= ~(evt_handler->evt_bit_mask_arr[i]);
 
 			cam_io_w_mb(irq_mask, controller->mem_base +
-				controller->irq_register_arr[i].
-				mask_reg_offset);
+				irq_register->mask_reg_offset);
 
 			/* Clear the IRQ bits of this handler */
 			cam_io_w_mb(evt_handler->evt_bit_mask_arr[i],
 				controller->mem_base +
-				controller->irq_register_arr[i].
-				clear_reg_offset);
+				irq_register->clear_reg_offset);
 			if (controller->global_clear_offset)
 				cam_io_w_mb(
 					controller->global_clear_bitmask,
@@ -642,7 +642,8 @@
 
 irqreturn_t cam_irq_controller_handle_irq(int irq_num, void *priv)
 {
-	struct cam_irq_controller  *controller  = priv;
+	struct cam_irq_controller   *controller  = priv;
+	struct cam_irq_register_obj *irq_register;
 	bool         need_th_processing[CAM_IRQ_PRIORITY_MAX] = {false};
 	int          i;
 	int          j;
@@ -654,6 +655,7 @@
 		controller, controller->name, &controller->lock);
 	spin_lock(&controller->lock);
 	for (i = 0; i < controller->num_registers; i++) {
+		irq_register = &controller->irq_register_arr[i];
 		controller->irq_status_arr[i] = cam_io_r_mb(
 			controller->mem_base +
 			controller->irq_register_arr[i].status_reg_offset);
@@ -664,8 +666,7 @@
 			controller->irq_register_arr[i].status_reg_offset,
 			controller->irq_status_arr[i]);
 		for (j = 0; j < CAM_IRQ_PRIORITY_MAX; j++) {
-			if (controller->irq_register_arr[i].
-				top_half_enable_mask[j] &
+			if (irq_register->top_half_enable_mask[j] &
 				controller->irq_status_arr[i])
 				need_th_processing[j] = true;
 				CAM_DBG(CAM_ISP,
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 328aaaf..34f8c41 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
@@ -356,6 +356,8 @@
 	struct cam_ife_csid_reg_offset  *csid_reg;
 	int rc = 0;
 	uint32_t val = 0, i;
+	uint32_t status;
+
 
 	soc_info = &csid_hw->hw_info->soc_info;
 	csid_reg = csid_hw->csid_info->csid_reg;
@@ -370,8 +372,6 @@
 	CAM_DBG(CAM_ISP, "CSID:%d Csid reset",
 		csid_hw->hw_intf->hw_idx);
 
-	init_completion(&csid_hw->csid_top_complete);
-
 	/* Mask all interrupts */
 	cam_io_w_mb(0, soc_info->reg_map[0].mem_base +
 		csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr);
@@ -417,21 +417,19 @@
 		cam_io_w_mb(0x2, soc_info->reg_map[0].mem_base +
 			csid_reg->rdi_reg[i]->csid_rdi_cfg0_addr);
 
-	/* perform the top CSID HW reset */
-	cam_io_w_mb(csid_reg->cmn_reg->csid_rst_stb,
+	/* perform the top CSID HW and SW registers reset */
+	cam_io_w_mb(csid_reg->cmn_reg->csid_rst_stb_sw_all,
 		soc_info->reg_map[0].mem_base +
 		csid_reg->cmn_reg->csid_rst_strobes_addr);
 
-	CAM_DBG(CAM_ISP, " Waiting for reset complete from irq handler");
-	rc = wait_for_completion_timeout(&csid_hw->csid_top_complete,
-		msecs_to_jiffies(IFE_CSID_TIMEOUT));
-	if (rc <= 0) {
-		CAM_ERR(CAM_ISP, "CSID:%d reset completion in fail rc = %d",
-			 csid_hw->hw_intf->hw_idx, rc);
-		if (rc == 0)
-			rc = -ETIMEDOUT;
-	} else {
-		rc = 0;
+	rc = readl_poll_timeout(soc_info->reg_map[0].mem_base +
+		csid_reg->cmn_reg->csid_top_irq_status_addr,
+			status, (status & 0x1) == 0x1,
+		CAM_IFE_CSID_TIMEOUT_SLEEP_US, CAM_IFE_CSID_TIMEOUT_ALL_US);
+	if (rc < 0) {
+		CAM_ERR(CAM_ISP, "CSID:%d csid_reset fail rc = %d",
+			  csid_hw->hw_intf->hw_idx, rc);
+		rc = -ETIMEDOUT;
 	}
 
 	val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
@@ -858,6 +856,11 @@
 	path_data->height  = reserve->in_port->height;
 	path_data->start_line = reserve->in_port->line_start;
 	path_data->end_line = reserve->in_port->line_stop;
+	path_data->crop_enable = true;
+	CAM_DBG(CAM_ISP, "Res id: %d height:%d line_start %d line_stop %d",
+		reserve->res_id, reserve->in_port->height,
+		reserve->in_port->line_start, reserve->in_port->line_stop);
+
 	if (reserve->in_port->res_type == CAM_ISP_IFE_IN_RES_TPG) {
 		path_data->dt = CAM_IFE_CSID_TPG_DT_VAL;
 		path_data->vc = CAM_IFE_CSID_TPG_VC_VAL;
@@ -867,7 +870,6 @@
 	}
 
 	if (reserve->sync_mode == CAM_ISP_HW_SYNC_MASTER) {
-		path_data->crop_enable = 1;
 		path_data->start_pixel = reserve->in_port->left_start;
 		path_data->end_pixel = reserve->in_port->left_stop;
 		path_data->width  = reserve->in_port->left_width;
@@ -878,7 +880,6 @@
 			csid_hw->hw_intf->hw_idx, path_data->start_line,
 			path_data->end_line);
 	} else if (reserve->sync_mode == CAM_ISP_HW_SYNC_SLAVE) {
-		path_data->crop_enable = 1;
 		path_data->start_pixel = reserve->in_port->right_start;
 		path_data->end_pixel = reserve->in_port->right_stop;
 		path_data->width  = reserve->in_port->right_width;
@@ -889,9 +890,13 @@
 			csid_hw->hw_intf->hw_idx, path_data->start_line,
 			path_data->end_line);
 	} else {
-		path_data->crop_enable = 0;
 		path_data->width  = reserve->in_port->left_width;
 		path_data->start_pixel = reserve->in_port->left_start;
+		path_data->end_pixel = reserve->in_port->left_stop;
+		CAM_DBG(CAM_ISP, "Res id: %d left width %d start: %d stop:%d",
+			reserve->res_id, reserve->in_port->left_width,
+			reserve->in_port->left_start,
+			reserve->in_port->left_stop);
 	}
 
 	CAM_DBG(CAM_ISP, "Res %d width %d height %d", reserve->res_id,
@@ -907,7 +912,7 @@
 	int rc = 0;
 	struct cam_ife_csid_reg_offset      *csid_reg;
 	struct cam_hw_soc_info              *soc_info;
-	uint32_t i, status, val;
+	uint32_t i, val;
 
 	csid_reg = csid_hw->csid_info->csid_reg;
 	soc_info = &csid_hw->hw_info->soc_info;
@@ -936,42 +941,10 @@
 		goto err;
 	}
 
-
-	CAM_DBG(CAM_ISP, "CSID:%d enable top irq interrupt",
-		csid_hw->hw_intf->hw_idx);
-
 	csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_UP;
-	/* Enable the top IRQ interrupt */
-	cam_io_w_mb(1, soc_info->reg_map[0].mem_base +
-		csid_reg->cmn_reg->csid_top_irq_mask_addr);
-
+	/* Reset CSID top */
 	rc = cam_ife_csid_global_reset(csid_hw);
 	if (rc) {
-		CAM_ERR(CAM_ISP, "CSID:%d csid_reset fail rc = %d",
-			  csid_hw->hw_intf->hw_idx, rc);
-		rc = -ETIMEDOUT;
-		goto disable_soc;
-	}
-
-	/*
-	 * Reset the SW registers
-	 * SW register reset also reset the mask irq, so poll the irq status
-	 * to check the reset complete.
-	 */
-	CAM_DBG(CAM_ISP, "CSID:%d Reset Software registers",
-			csid_hw->hw_intf->hw_idx);
-
-	cam_io_w_mb(csid_reg->cmn_reg->csid_rst_stb_sw_all,
-		soc_info->reg_map[0].mem_base +
-		csid_reg->cmn_reg->csid_rst_strobes_addr);
-
-	rc = readl_poll_timeout(soc_info->reg_map[0].mem_base +
-		csid_reg->cmn_reg->csid_top_irq_status_addr,
-			status, (status & 0x1) == 0x1,
-		CAM_IFE_CSID_TIMEOUT_SLEEP_US, CAM_IFE_CSID_TIMEOUT_ALL_US);
-	if (rc < 0) {
-		CAM_ERR(CAM_ISP, "software register reset timeout.....");
-		rc = -ETIMEDOUT;
 		goto disable_soc;
 	}
 
@@ -1065,6 +1038,7 @@
 	int rc = 0;
 	uint32_t  val = 0;
 	struct cam_hw_soc_info    *soc_info;
+	struct cam_ife_csid_reg_offset *csid_reg = NULL;
 
 	csid_hw->tpg_start_cnt++;
 	if (csid_hw->tpg_start_cnt == 1) {
@@ -1109,10 +1083,10 @@
 		}
 
 		/* Enable the IFE force clock on for dual isp case */
+		csid_reg = csid_hw->csid_info->csid_reg;
 		if (csid_hw->tpg_cfg.usage_type) {
 			rc = cam_ife_csid_enable_ife_force_clock_on(soc_info,
-				csid_hw->csid_info->csid_reg->tpg_reg->
-				tpg_cpas_ife_reg_offset);
+				csid_reg->tpg_reg->tpg_cpas_ife_reg_offset);
 			if (rc)
 				return rc;
 		}
@@ -1122,10 +1096,9 @@
 		val |= (0x80 << 8);
 		val |= (((csid_hw->csi2_rx_cfg.lane_num - 1) & 0x3) << 4);
 		val |= 7;
-		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
-			csid_hw->csid_info->csid_reg->tpg_reg->
-			csid_tpg_ctrl_addr);
 
+		cam_io_w_mb(val, soc_info->reg_map[0].mem_base +
+			csid_reg->tpg_reg->csid_tpg_ctrl_addr);
 		val = cam_io_r_mb(soc_info->reg_map[0].mem_base + 0x600);
 		CAM_DBG(CAM_ISP, "reg 0x%x = 0x%x", 0x600, val);
 	}
@@ -1138,6 +1111,7 @@
 {
 	int rc = 0;
 	struct cam_hw_soc_info    *soc_info;
+	struct cam_ife_csid_reg_offset *csid_reg = NULL;
 
 	if (csid_hw->tpg_start_cnt)
 		csid_hw->tpg_start_cnt--;
@@ -1146,6 +1120,7 @@
 		return 0;
 
 	soc_info = &csid_hw->hw_info->soc_info;
+	csid_reg = csid_hw->csid_info->csid_reg;
 
 	/* disable the TPG */
 	if (!csid_hw->tpg_start_cnt) {
@@ -1155,8 +1130,7 @@
 		/* Disable the IFE force clock on for dual isp case */
 		if (csid_hw->tpg_cfg.usage_type)
 			rc = cam_ife_csid_disable_ife_force_clock_on(soc_info,
-				csid_hw->csid_info->csid_reg->tpg_reg->
-				tpg_cpas_ife_reg_offset);
+				csid_reg->tpg_reg->tpg_cpas_ife_reg_offset);
 
 		/*stop the TPG */
 		cam_io_w_mb(0,  soc_info->reg_map[0].mem_base +
@@ -1669,6 +1643,10 @@
 	if (rc)
 		return rc;
 
+	/* if path decode format is payload only then RDI crop is not applied */
+	if (path_format == 0xF)
+		path_data->crop_enable = 0;
+
 	/*
 	 * RDI path config and enable the time stamp capture
 	 * Enable the measurement blocks
@@ -1905,6 +1883,7 @@
 	struct cam_isp_resource_node         *res;
 	struct cam_ife_csid_reg_offset       *csid_reg;
 	struct cam_hw_soc_info               *soc_info;
+	struct cam_ife_csid_rdi_reg_offset   *rdi_reg;
 	uint32_t  time_32, id;
 
 	time_stamp = (struct cam_csid_get_time_stamp_args  *)cmd_args;
@@ -1937,15 +1916,14 @@
 		time_stamp->time_stamp_val |= time_32;
 	} else {
 		id = res->res_id;
+		rdi_reg = csid_reg->rdi_reg[id];
 		time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
-			csid_reg->rdi_reg[id]->
-			csid_rdi_timestamp_curr1_sof_addr);
+			rdi_reg->csid_rdi_timestamp_curr1_sof_addr);
 		time_stamp->time_stamp_val = time_32;
 		time_stamp->time_stamp_val = time_stamp->time_stamp_val << 32;
 
 		time_32 = cam_io_r_mb(soc_info->reg_map[0].mem_base +
-			csid_reg->rdi_reg[id]->
-			csid_rdi_timestamp_curr0_sof_addr);
+			rdi_reg->csid_rdi_timestamp_curr0_sof_addr);
 		time_stamp->time_stamp_val |= time_32;
 	}
 
@@ -2171,6 +2149,7 @@
 	struct cam_ife_csid_reg_offset *csid_reg =
 		csid_hw->csid_info->csid_reg;
 
+	init_completion(&csid_hw->csid_top_complete);
 	cam_io_w_mb(csid_reg->cmn_reg->csid_rst_stb,
 		csid_hw->hw_info->soc_info.reg_map[0].mem_base +
 		csid_reg->cmn_reg->csid_rst_strobes_addr);
@@ -2490,6 +2469,7 @@
 	struct cam_ife_csid_hw          *csid_hw;
 	struct cam_hw_soc_info          *soc_info;
 	struct cam_ife_csid_reg_offset  *csid_reg;
+	struct cam_ife_csid_csi2_rx_reg_offset *csi2_reg;
 	uint32_t i, irq_status_top, irq_status_rx, irq_status_ipp = 0;
 	uint32_t irq_status_rdi[4] = {0, 0, 0, 0};
 	uint32_t val;
@@ -2505,6 +2485,7 @@
 
 	csid_reg = csid_hw->csid_info->csid_reg;
 	soc_info = &csid_hw->hw_info->soc_info;
+	csi2_reg = csid_reg->csi2_reg;
 
 	/* read */
 	irq_status_top = cam_io_r_mb(soc_info->reg_map[0].mem_base +
@@ -2653,19 +2634,16 @@
 		CAM_ERR(CAM_ISP, "CSID:%d LONG_PKT_CAPTURED",
 			csid_hw->hw_intf->hw_idx);
 		val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
-			csid_reg->csi2_reg->
-			csid_csi2_rx_captured_long_pkt_0_addr);
+			csi2_reg->csid_csi2_rx_captured_long_pkt_0_addr);
 		CAM_ERR(CAM_ISP, "CSID:%d long packet VC :%d DT:%d WC:%d",
 			csid_hw->hw_intf->hw_idx,
 			(val >> 22), ((val >> 16) & 0x3F), (val & 0xFFFF));
 		val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
-			csid_reg->csi2_reg->
-			csid_csi2_rx_captured_long_pkt_1_addr);
+			csi2_reg->csid_csi2_rx_captured_long_pkt_1_addr);
 		CAM_ERR(CAM_ISP, "CSID:%d long packet ECC :%d",
 			csid_hw->hw_intf->hw_idx, val);
 		val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
-			csid_reg->csi2_reg->
-			csid_csi2_rx_captured_long_pkt_ftr_addr);
+			csi2_reg->csid_csi2_rx_captured_long_pkt_ftr_addr);
 		CAM_ERR(CAM_ISP, "CSID:%d long pkt cal CRC:%d expected CRC:%d",
 			csid_hw->hw_intf->hw_idx, (val >> 16), (val & 0xFFFF));
 	}
@@ -2674,14 +2652,12 @@
 		CAM_ERR(CAM_ISP, "CSID:%d SHORT_PKT_CAPTURED",
 			csid_hw->hw_intf->hw_idx);
 		val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
-			csid_reg->csi2_reg->
-			csid_csi2_rx_captured_short_pkt_0_addr);
+			csi2_reg->csid_csi2_rx_captured_short_pkt_0_addr);
 		CAM_ERR(CAM_ISP, "CSID:%d short pkt VC :%d DT:%d LC:%d",
 			csid_hw->hw_intf->hw_idx,
 			(val >> 22), ((val >> 16) & 0x1F), (val & 0xFFFF));
 		val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
-			csid_reg->csi2_reg->
-			csid_csi2_rx_captured_short_pkt_1_addr);
+			csi2_reg->csid_csi2_rx_captured_short_pkt_1_addr);
 		CAM_ERR(CAM_ISP, "CSID:%d short packet ECC :%d",
 			csid_hw->hw_intf->hw_idx, val);
 	}
@@ -2691,8 +2667,7 @@
 		CAM_ERR(CAM_ISP, "CSID:%d CPHY_PKT_HDR_CAPTURED",
 			csid_hw->hw_intf->hw_idx);
 		val = cam_io_r_mb(soc_info->reg_map[0].mem_base +
-			csid_reg->csi2_reg->
-			csid_csi2_rx_captured_cphy_pkt_hdr_addr);
+			csi2_reg->csid_csi2_rx_captured_cphy_pkt_hdr_addr);
 		CAM_ERR(CAM_ISP, "CSID:%d cphy packet VC :%d DT:%d WC:%d",
 			csid_hw->hw_intf->hw_idx,
 			(val >> 22), ((val >> 16) & 0x1F), (val & 0xFFFF));
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 2c4fe9d..fd38a96 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
@@ -32,17 +32,17 @@
 };
 
 static uint32_t camif_irq_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
-	0x0003FD1F,
+	0x00000017,
 	0x00000000,
 };
 
 static uint32_t camif_irq_err_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
-	0x00000000,
+	0x0003FC00,
 	0x0FFF7EBC,
 };
 
 static uint32_t rdi_irq_reg_mask[CAM_IFE_IRQ_REGISTERS_MAX] = {
-	0x780000e0,
+	0x780001e0,
 	0x00000000,
 };
 
@@ -89,9 +89,10 @@
 	spin_lock_irqsave(&vfe_core_info->spin_lock, flags);
 	(*evt_payload)->error_type = 0;
 	list_add_tail(&(*evt_payload)->list, &vfe_core_info->free_payload_list);
+	*evt_payload = NULL;
 	spin_unlock_irqrestore(&vfe_core_info->spin_lock, flags);
 
-	*evt_payload = NULL;
+
 	return 0;
 }
 
@@ -156,6 +157,7 @@
 	struct cam_vfe_irq_handler_priv     *handler_priv;
 	struct cam_vfe_top_irq_evt_payload  *evt_payload;
 	struct cam_vfe_hw_core_info         *core_info;
+	bool                                 error_flag = false;
 
 	CAM_DBG(CAM_ISP, "IRQ status_0 = %x, IRQ status_1 = %x",
 		th_payload->evt_status_arr[0], th_payload->evt_status_arr[1]);
@@ -166,14 +168,20 @@
 	 *  need to handle overflow condition here, otherwise irq storm
 	 *  will block everything
 	 */
-
-	if (th_payload->evt_status_arr[1]) {
-		CAM_ERR(CAM_ISP, "IRQ status_1: %x, Masking all interrupts",
+	if (th_payload->evt_status_arr[1] ||
+		(th_payload->evt_status_arr[0] & camif_irq_err_reg_mask[0])) {
+		CAM_ERR(CAM_ISP,
+			"Encountered Error: vfe:%d:  Irq_status0=0x%x Status1=0x%x",
+			handler_priv->core_index, th_payload->evt_status_arr[0],
 			th_payload->evt_status_arr[1]);
+		CAM_ERR(CAM_ISP,
+			"Stopping further IRQ processing from this HW index=%d",
+			handler_priv->core_index);
 		cam_irq_controller_disable_irq(core_info->vfe_irq_controller,
 			core_info->irq_err_handle);
 		cam_irq_controller_clear_and_mask(evt_id,
 			core_info->vfe_irq_controller);
+		error_flag = true;
 	}
 
 	rc  = cam_vfe_get_evt_payload(handler_priv->core_info, &evt_payload);
@@ -200,7 +208,9 @@
 			irq_reg_offset[i]);
 	}
 
-	CAM_DBG(CAM_ISP, "Violation status = %x", evt_payload->irq_reg_val[2]);
+	if (error_flag)
+		CAM_INFO(CAM_ISP, "Violation status = %x",
+			evt_payload->irq_reg_val[2]);
 
 	th_payload->evt_payload_priv = evt_payload;
 
@@ -291,6 +301,8 @@
 	struct cam_vfe_hw_core_info       *core_info = NULL;
 	struct cam_isp_resource_node      *isp_res = NULL;
 	int rc = 0;
+	uint32_t                           reset_core_args =
+					CAM_VFE_HW_RESET_HW_AND_REG;
 
 	CAM_DBG(CAM_ISP, "Enter");
 	if (!hw_priv) {
@@ -327,6 +339,8 @@
 			CAM_ERR(CAM_ISP, "deinit failed");
 	}
 
+	rc = cam_vfe_reset(hw_priv, &reset_core_args, sizeof(uint32_t));
+
 	/* Turn OFF Regulators, Clocks and other SOC resources */
 	CAM_DBG(CAM_ISP, "Disable SOC resource");
 	rc = cam_vfe_disable_soc_resources(soc_info);
@@ -373,7 +387,7 @@
 
 	reinit_completion(&vfe_hw->hw_complete);
 
-	CAM_DBG(CAM_ISP, "calling RESET");
+	CAM_DBG(CAM_ISP, "calling RESET on vfe %d", soc_info->index);
 	core_info->vfe_top->hw_ops.reset(core_info->vfe_top->top_priv,
 		reset_core_args, arg_size);
 	CAM_DBG(CAM_ISP, "waiting for vfe reset complete");
@@ -416,23 +430,6 @@
 	CAM_DBG(CAM_ISP, "IRQ status_0 = %x", th_payload->evt_status_arr[0]);
 	CAM_DBG(CAM_ISP, "IRQ status_1 = %x", th_payload->evt_status_arr[1]);
 
-	/*
-	 *  need to handle non-recoverable condition here, otherwise irq storm
-	 *  will block everything.
-	 */
-	if (th_payload->evt_status_arr[0] & 0x3FC00) {
-		CAM_ERR(CAM_ISP,
-			"Encountered Error Irq_status0=0x%x Status1=0x%x",
-			th_payload->evt_status_arr[0],
-			th_payload->evt_status_arr[1]);
-		CAM_ERR(CAM_ISP,
-			"Stopping further IRQ processing from this HW index=%d",
-			handler_priv->core_index);
-		cam_io_w(0, handler_priv->mem_base + 0x60);
-		cam_io_w(0, handler_priv->mem_base + 0x5C);
-		return 0;
-	}
-
 	rc  = cam_vfe_get_evt_payload(handler_priv->core_info, &evt_payload);
 	if (rc) {
 		CAM_ERR_RATE_LIMIT(CAM_ISP,
@@ -705,6 +702,7 @@
 	case CAM_ISP_HW_CMD_GET_BUF_UPDATE:
 	case CAM_ISP_HW_CMD_GET_HFR_UPDATE:
 	case CAM_ISP_HW_CMD_STRIPE_UPDATE:
+	case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ:
 		rc = core_info->vfe_bus->hw_ops.process_cmd(
 			core_info->vfe_bus->bus_priv, cmd_type, cmd_args,
 			arg_size);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_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 ed728f5..969b75a 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
@@ -2291,6 +2291,7 @@
 	struct cam_buf_io_cfg                    *io_cfg;
 	struct cam_vfe_bus_ver2_vfe_out_data     *vfe_out_data = NULL;
 	struct cam_vfe_bus_ver2_wm_resource_data *wm_data = NULL;
+	struct cam_vfe_bus_ver2_reg_offset_ubwc_client *ubwc_client = NULL;
 	uint32_t *reg_val_pair;
 	uint32_t  i, j, size = 0;
 	uint32_t  frame_inc = 0, ubwc_bw_limit = 0, camera_hw_version, val;
@@ -2326,7 +2327,7 @@
 		}
 
 		wm_data = vfe_out_data->wm_res[i]->res_priv;
-
+		ubwc_client = wm_data->hw_regs->ubwc_regs;
 		/* update width register */
 		CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
 			wm_data->hw_regs->buffer_width_cfg,
@@ -2398,9 +2399,8 @@
 					 * update offset value.
 					 */
 					CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair,
-						j,
-						wm_data->hw_regs->ubwc_regs->
-						h_init, wm_data->offset);
+						j, ubwc_client->h_init,
+						wm_data->offset);
 					wm_data->h_init = wm_data->offset;
 				}
 			} else if (wm_data->h_init !=
@@ -2428,8 +2428,7 @@
 				io_cfg->planes[i].meta_stride ||
 				!wm_data->init_cfg_done) {
 				CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
-					wm_data->hw_regs->ubwc_regs->
-					meta_stride,
+					ubwc_client->meta_stride,
 					io_cfg->planes[i].meta_stride);
 				wm_data->ubwc_meta_stride =
 					io_cfg->planes[i].meta_stride;
@@ -2453,8 +2452,7 @@
 				io_cfg->planes[i].meta_offset ||
 				!wm_data->init_cfg_done) {
 				CAM_VFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
-					wm_data->hw_regs->ubwc_regs->
-					meta_offset,
+					ubwc_client->meta_offset,
 					io_cfg->planes[i].meta_offset);
 				wm_data->ubwc_meta_offset =
 					io_cfg->planes[i].meta_offset;
@@ -2849,7 +2847,7 @@
 	case CAM_ISP_HW_CMD_STOP_BUS_ERR_IRQ:
 		bus_priv = (struct cam_vfe_bus_ver2_priv  *) priv;
 		if (bus_priv->error_irq_handle) {
-			CAM_INFO(CAM_ISP, "Mask off bus error irq handler");
+			CAM_DBG(CAM_ISP, "Mask off bus error irq handler");
 			rc = cam_irq_controller_unsubscribe_irq(
 				bus_priv->common_data.bus_irq_controller,
 				bus_priv->error_irq_handle);
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 976e6d2..5d6045b 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
@@ -275,7 +275,7 @@
 	}
 
 	if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
-		CAM_ERR_RATE_LIMIT(CAM_ISP,
+		CAM_DBG(CAM_ISP,
 			"VFE:%d Not ready to set clocks yet :%d",
 			res->hw_intf->hw_idx,
 			hw_info->hw_state);
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 32f11a7..f172a79 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
@@ -145,8 +145,7 @@
 	}
 
 	rc = cam_mem_get_cpu_buf(
-		p_cfg_req->hw_cfg_args.
-		hw_update_entries[CAM_JPEG_PARAM].handle,
+		p_cfg_req->hw_cfg_args.hw_update_entries[CAM_JPEG_PARAM].handle,
 		(uint64_t *)&kaddr, &cmd_buf_len);
 	if (rc) {
 		CAM_ERR(CAM_JPEG, "unable to get info for cmd buf: %x %d",
@@ -157,20 +156,20 @@
 	cmd_buf_kaddr = (uint32_t *)kaddr;
 
 	cmd_buf_kaddr =
-		(cmd_buf_kaddr + (p_cfg_req->hw_cfg_args.
-		hw_update_entries[CAM_JPEG_PARAM].offset / sizeof(uint32_t)));
+		(cmd_buf_kaddr +
+		(p_cfg_req->hw_cfg_args.hw_update_entries[CAM_JPEG_PARAM].offset
+			/ sizeof(uint32_t)));
 
 	p_params = (struct cam_jpeg_config_inout_param_info *)cmd_buf_kaddr;
 
 	p_params->output_size = task_data->result_size;
 	CAM_DBG(CAM_JPEG, "Encoded Size %d", task_data->result_size);
 
-	buf_data.num_handles = p_cfg_req->
-		hw_cfg_args.num_out_map_entries;
+	buf_data.num_handles =
+		p_cfg_req->hw_cfg_args.num_out_map_entries;
 	for (i = 0; i < buf_data.num_handles; i++) {
 		buf_data.resource_handle[i] =
-			p_cfg_req->hw_cfg_args.
-			out_map_entries[i].resource_handle;
+		p_cfg_req->hw_cfg_args.out_map_entries[i].resource_handle;
 	}
 	buf_data.request_id =
 		(uint64_t)p_cfg_req->hw_cfg_args.priv;
@@ -267,8 +266,8 @@
 	uint32_t *ch_base_iova_addr;
 	size_t ch_base_len;
 
-	rc = cam_mem_get_cpu_buf(config_args->
-		hw_update_entries[CAM_JPEG_CHBASE].handle,
+	rc = cam_mem_get_cpu_buf(
+		config_args->hw_update_entries[CAM_JPEG_CHBASE].handle,
 		&iova_addr, &ch_base_len);
 	if (rc) {
 		CAM_ERR(CAM_JPEG,
@@ -285,10 +284,10 @@
 
 	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
 	mem_cam_base = hw_mgr->cdm_reg_map[dev_type][0]->mem_cam_base;
-	size = hw_mgr->cdm_info[dev_type][0].cdm_ops->
-		cdm_required_size_changebase();
-	hw_mgr->cdm_info[dev_type][0].cdm_ops->
-		cdm_write_changebase(ch_base_iova_addr, mem_cam_base);
+	size =
+	hw_mgr->cdm_info[dev_type][0].cdm_ops->cdm_required_size_changebase();
+	hw_mgr->cdm_info[dev_type][0].cdm_ops->cdm_write_changebase(
+		ch_base_iova_addr, mem_cam_base);
 
 	cdm_cmd = ctx_data->cdm_cmd;
 	cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].bl_addr.mem_handle =
@@ -322,6 +321,7 @@
 	struct cam_jpeg_set_irq_cb irq_cb;
 	struct cam_jpeg_hw_cfg_req *p_cfg_req = NULL;
 	struct cam_hw_done_event_data buf_data;
+	struct cam_hw_config_args *hw_cfg_args = NULL;
 
 	if (!hw_mgr || !task_data) {
 		CAM_ERR(CAM_JPEG, "Invalid arguments %pK %pK",
@@ -444,8 +444,8 @@
 	for (i = CAM_JPEG_CFG; i < (config_args->num_hw_update_entries - 1);
 		i++) {
 		cmd = (config_args->hw_update_entries + i);
-		cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].
-			bl_addr.mem_handle = cmd->handle;
+		cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].bl_addr.mem_handle
+			= cmd->handle;
 		cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].offset =
 			cmd->offset;
 		cdm_cmd->cmd[cdm_cmd->cmd_arrary_count].len =
@@ -456,8 +456,7 @@
 	}
 
 	rc = cam_cdm_submit_bls(
-		hw_mgr->cdm_info[dev_type][0].cdm_handle,
-		cdm_cmd);
+		hw_mgr->cdm_info[dev_type][0].cdm_handle, cdm_cmd);
 	if (rc) {
 		CAM_ERR(CAM_JPEG, "Failed to apply the configs %d", rc);
 		goto end_callcb;
@@ -483,15 +482,14 @@
 end_callcb:
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 	if (p_cfg_req) {
-		buf_data.num_handles = p_cfg_req->
-			hw_cfg_args.num_out_map_entries;
+		hw_cfg_args = &p_cfg_req->hw_cfg_args;
+		buf_data.num_handles =
+			hw_cfg_args->num_out_map_entries;
 		for (i = 0; i < buf_data.num_handles; i++) {
 			buf_data.resource_handle[i] =
-				p_cfg_req->hw_cfg_args.
-				out_map_entries[i].resource_handle;
+			hw_cfg_args->out_map_entries[i].resource_handle;
 		}
-		buf_data.request_id =
-			(uint64_t)p_cfg_req->hw_cfg_args.priv;
+		buf_data.request_id = (uint64_t)p_cfg_req->hw_cfg_args.priv;
 		ctx_data->ctxt_event_cb(ctx_data->context_priv, 0, &buf_data);
 	}
 
@@ -753,8 +751,8 @@
 	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) {
+		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;
@@ -811,8 +809,8 @@
 
 	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 ((cfg_req) && ((struct cam_jpeg_hw_ctx_data *)
+			cfg_req->hw_cfg_args.ctxt_to_hw_map != ctx_data))
 			continue;
 
 		list_del_init(&cfg_req->list);
@@ -1091,8 +1089,8 @@
 		hw_mgr->cdm_info[dev_type][0].ref_cnt++;
 	}
 
-	size = hw_mgr->cdm_info[dev_type][0].
-		cdm_ops->cdm_required_size_changebase();
+	size =
+	hw_mgr->cdm_info[dev_type][0].cdm_ops->cdm_required_size_changebase();
 
 	if (hw_mgr->cdm_info[dev_type][0].ref_cnt == 1)
 		if (cam_cdm_stream_on(
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c
index 2d343dd..bc6dce9 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_core.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/jpeg_dma_hw/jpeg_dma_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
@@ -47,9 +47,8 @@
 	}
 
 	soc_info = &jpeg_dma_dev->soc_info;
-	core_info =
-		(struct cam_jpeg_dma_device_core_info *)jpeg_dma_dev->
-		core_info;
+	core_info = (struct cam_jpeg_dma_device_core_info *)
+		jpeg_dma_dev->core_info;
 
 	if (!soc_info || !core_info) {
 		CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK",
@@ -159,9 +158,8 @@
 		return -EINVAL;
 	}
 
-	core_info =
-		(struct cam_jpeg_dma_device_core_info *)jpeg_dma_dev->
-		core_info;
+	core_info = (struct cam_jpeg_dma_device_core_info *)
+		jpeg_dma_dev->core_info;
 
 	switch (cmd_type) {
 	case CAM_JPEG_CMD_SET_IRQ_CB:
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 05ae7cc..ef10406 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
@@ -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
@@ -153,8 +153,8 @@
 		rc = -ENOMEM;
 		goto error_alloc_core;
 	}
-	core_info = (struct cam_jpeg_dma_device_core_info *)jpeg_dma_dev->
-		core_info;
+	core_info = (struct cam_jpeg_dma_device_core_info *)
+		jpeg_dma_dev->core_info;
 
 	match_dev = of_match_device(pdev->dev.driver->of_match_table,
 		&pdev->dev);
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 934b911..9fa691b 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
@@ -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
@@ -58,9 +58,8 @@
 	}
 
 	soc_info = &jpeg_enc_dev->soc_info;
-	core_info =
-		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
-		core_info;
+	core_info = (struct cam_jpeg_enc_device_core_info *)
+		jpeg_enc_dev->core_info;
 
 	if (!soc_info || !core_info) {
 		CAM_ERR(CAM_JPEG, "soc_info = %pK core_info = %pK",
@@ -168,9 +167,8 @@
 		return IRQ_HANDLED;
 	}
 	soc_info = &jpeg_enc_dev->soc_info;
-	core_info =
-		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
-		core_info;
+	core_info = (struct cam_jpeg_enc_device_core_info *)
+		jpeg_enc_dev->core_info;
 	hw_info = core_info->jpeg_enc_hw_info;
 	mem_base = soc_info->reg_map[0].mem_base;
 
@@ -188,8 +186,7 @@
 		spin_lock(&jpeg_enc_dev->hw_lock);
 		if (core_info->core_state == CAM_JPEG_ENC_CORE_READY) {
 			encoded_size = cam_io_r_mb(mem_base +
-				core_info->jpeg_enc_hw_info->reg_offset.
-				encode_size);
+			core_info->jpeg_enc_hw_info->reg_offset.encode_size);
 			if (core_info->irq_cb.jpeg_hw_mgr_cb) {
 				core_info->irq_cb.jpeg_hw_mgr_cb(irq_status,
 					encoded_size,
@@ -263,9 +260,8 @@
 	}
 	/* maskdisable.clrirq.maskenable.resetcmd */
 	soc_info = &jpeg_enc_dev->soc_info;
-	core_info =
-		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
-		core_info;
+	core_info = (struct cam_jpeg_enc_device_core_info *)
+		jpeg_enc_dev->core_info;
 	hw_info = core_info->jpeg_enc_hw_info;
 	mem_base = soc_info->reg_map[0].mem_base;
 
@@ -348,9 +344,8 @@
 		return -EINVAL;
 	}
 	soc_info = &jpeg_enc_dev->soc_info;
-	core_info =
-		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
-		core_info;
+	core_info = (struct cam_jpeg_enc_device_core_info *)
+		jpeg_enc_dev->core_info;
 	hw_info = core_info->jpeg_enc_hw_info;
 	mem_base = soc_info->reg_map[0].mem_base;
 
@@ -398,9 +393,8 @@
 		return -EINVAL;
 	}
 
-	core_info =
-		(struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
-		core_info;
+	core_info = (struct cam_jpeg_enc_device_core_info *)
+		jpeg_enc_dev->core_info;
 
 	switch (cmd_type) {
 	case CAM_JPEG_CMD_SET_IRQ_CB:
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 2180448..d1eb526 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
@@ -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
@@ -152,8 +152,8 @@
 		rc = -ENOMEM;
 		goto error_alloc_core;
 	}
-	core_info = (struct cam_jpeg_enc_device_core_info *)jpeg_enc_dev->
-		core_info;
+	core_info = (struct cam_jpeg_enc_device_core_info *)
+		jpeg_enc_dev->core_info;
 
 	match_dev = of_match_device(pdev->dev.driver->of_match_table,
 		&pdev->dev);
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 20b8586..898997a 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
@@ -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
@@ -391,13 +391,14 @@
 	work_data = (struct cam_lrme_mgr_work_data *)data;
 	hw_device = work_data->hw_device;
 
-	rc = cam_lrme_mgr_util_get_frame_req(&hw_device->
-		frame_pending_list_high, &frame_req, &hw_device->high_req_lock);
+	rc = cam_lrme_mgr_util_get_frame_req(
+		&hw_device->frame_pending_list_high, &frame_req,
+		&hw_device->high_req_lock);
 
 	if (!frame_req) {
-		rc = cam_lrme_mgr_util_get_frame_req(&hw_device->
-				frame_pending_list_normal, &frame_req,
-				&hw_device->normal_req_lock);
+		rc = cam_lrme_mgr_util_get_frame_req(
+			&hw_device->frame_pending_list_normal, &frame_req,
+			&hw_device->normal_req_lock);
 		if (frame_req)
 			req_prio = 1;
 	}
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 21e66a2..6f98354 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
@@ -449,8 +449,8 @@
 		cb_args.cb_type = CAM_LRME_CB_PUT_FRAME;
 		cb_args.frame_req = req_submit;
 		if (lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb)
-			lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb(lrme_core->
-				hw_mgr_cb.data, &cb_args);
+			lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb(
+				lrme_core->hw_mgr_cb.data, &cb_args);
 	} else if (req_submit) {
 		submit_args.frame_req = req_submit;
 		submit_args.hw_update_entries = req_submit->hw_update_entries;
@@ -468,8 +468,8 @@
 		cb_args.cb_type = CAM_LRME_CB_PUT_FRAME;
 		cb_args.frame_req = req_proc;
 		if (lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb)
-			lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb(lrme_core->
-				hw_mgr_cb.data, &cb_args);
+			lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb(
+				lrme_core->hw_mgr_cb.data, &cb_args);
 	} else if (req_proc) {
 		submit_args.frame_req = req_proc;
 		submit_args.hw_update_entries = req_proc->hw_update_entries;
@@ -511,8 +511,8 @@
 		cb_args.cb_type = CAM_LRME_CB_PUT_FRAME;
 		cb_args.frame_req = req_submit;
 		if (lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb)
-			lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb(lrme_core->
-				hw_mgr_cb.data, &cb_args);
+			lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb(
+				lrme_core->hw_mgr_cb.data, &cb_args);
 	} else if (req_submit) {
 		submit_args.frame_req = req_submit;
 		submit_args.hw_update_entries = req_submit->hw_update_entries;
@@ -530,8 +530,8 @@
 		cb_args.cb_type = CAM_LRME_CB_PUT_FRAME;
 		cb_args.frame_req = req_proc;
 		if (lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb)
-			lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb(lrme_core->
-				hw_mgr_cb.data, &cb_args);
+			lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb(
+				lrme_core->hw_mgr_cb.data, &cb_args);
 	} else if (req_proc) {
 		submit_args.frame_req = req_proc;
 		submit_args.hw_update_entries = req_proc->hw_update_entries;
@@ -745,8 +745,8 @@
 	}
 
 	if (lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb) {
-		lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb(lrme_core->
-			hw_mgr_cb.data, &cb_args);
+		lrme_core->hw_mgr_cb.cam_lrme_hw_mgr_cb(
+			lrme_core->hw_mgr_cb.data, &cb_args);
 	} else {
 		CAM_ERR(CAM_LRME, "No hw mgr cb");
 		rc = -EINVAL;
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 e66d21d..aaba481 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
@@ -1684,8 +1684,8 @@
 					evt_data.u.error = err_info->error;
 					if (device->ops &&
 						device->ops->process_evt)
-						rc = device->ops->
-							process_evt(&evt_data);
+						rc = device->ops->process_evt(
+							&evt_data);
 				}
 			}
 			/* Bring processing pointer to bubbled req id */
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 079f5bb..9f26635 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
@@ -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
@@ -193,16 +193,12 @@
 		for (i = 0; i < size; i++) {
 			rc = camera_io_dev_poll(
 			io_master_info,
-			i2c_list->i2c_settings.
-				reg_setting[i].reg_addr,
-			i2c_list->i2c_settings.
-				reg_setting[i].reg_data,
-			i2c_list->i2c_settings.
-				reg_setting[i].data_mask,
+			i2c_list->i2c_settings.reg_setting[i].reg_addr,
+			i2c_list->i2c_settings.reg_setting[i].reg_data,
+			i2c_list->i2c_settings.reg_setting[i].data_mask,
 			i2c_list->i2c_settings.addr_type,
-				i2c_list->i2c_settings.data_type,
-			i2c_list->i2c_settings.
-				reg_setting[i].delay);
+			i2c_list->i2c_settings.data_type,
+			i2c_list->i2c_settings.reg_setting[i].delay);
 			if (rc < 0) {
 				CAM_ERR(CAM_ACTUATOR,
 					"i2c poll apply setting Fail: %d", rc);
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 b975418..fe69fcb 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
@@ -94,8 +94,8 @@
 	CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR %d len %d max %d",
 		read_val, len,
 		cci_dev->cci_i2c_queue_info[master][queue].max_queue_size);
-	if ((read_val + len + 1) > cci_dev->
-		cci_i2c_queue_info[master][queue].max_queue_size) {
+	if ((read_val + len + 1) >
+		cci_dev->cci_i2c_queue_info[master][queue].max_queue_size) {
 		uint32_t reg_val = 0;
 		uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8);
 
@@ -113,16 +113,18 @@
 		CAM_DBG(CAM_CCI, "CCI_QUEUE_START_ADDR");
 		spin_lock_irqsave(
 			&cci_dev->cci_master_info[master].lock_q[queue], flags);
-		atomic_set(&cci_dev->cci_master_info[master].
-						done_pending[queue], 1);
+		atomic_set(
+			&cci_dev->cci_master_info[master].done_pending[queue],
+			1);
 		cam_io_w_mb(reg_val, base +
 			CCI_QUEUE_START_ADDR);
 		CAM_DBG(CAM_CCI, "wait_for_completion_timeout");
 		atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
 		spin_unlock_irqrestore(
 			&cci_dev->cci_master_info[master].lock_q[queue], flags);
-		rc = wait_for_completion_timeout(&cci_dev->
-			cci_master_info[master].report_q[queue], CCI_TIMEOUT);
+		rc = wait_for_completion_timeout(
+			&cci_dev->cci_master_info[master].report_q[queue],
+			CCI_TIMEOUT);
 		if (rc <= 0) {
 			CAM_ERR(CAM_CCI, "Wait_for_completion_timeout: rc: %d",
 				rc);
@@ -244,8 +246,8 @@
 		return -EINVAL;
 	}
 
-	rc = wait_for_completion_timeout(&cci_dev->
-		cci_master_info[master].report_q[queue], CCI_TIMEOUT);
+	rc = wait_for_completion_timeout(
+		&cci_dev->cci_master_info[master].report_q[queue], CCI_TIMEOUT);
 	CAM_DBG(CAM_CCI, "wait DONE_for_completion_timeout");
 
 	if (rc <= 0) {
@@ -338,8 +340,9 @@
 			return rc;
 		}
 	} else {
-		atomic_set(&cci_dev->cci_master_info[master].
-						done_pending[queue], 1);
+		atomic_set(
+			&cci_dev->cci_master_info[master].done_pending[queue],
+			1);
 		spin_unlock_irqrestore(
 			&cci_dev->cci_master_info[master].lock_q[queue], flags);
 		rc = cam_cci_wait(cci_dev, master, queue);
@@ -376,9 +379,8 @@
 		CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
 	CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR %d max %d", read_val,
 		cci_dev->cci_i2c_queue_info[master][queue].max_queue_size);
-	return (cci_dev->
-		cci_i2c_queue_info[master][queue].max_queue_size) -
-		read_val;
+	return ((cci_dev->cci_i2c_queue_info[master][queue].max_queue_size) -
+			read_val);
 }
 
 static void cam_cci_process_half_q(struct cci_device *cci_dev,
@@ -414,8 +416,9 @@
 	spin_lock_irqsave(&cci_dev->cci_master_info[master].lock_q[queue],
 		flags);
 	if (atomic_read(&cci_dev->cci_master_info[master].q_free[queue]) == 1) {
-		atomic_set(&cci_dev->cci_master_info[master].
-						done_pending[queue], 1);
+		atomic_set(
+			&cci_dev->cci_master_info[master].done_pending[queue],
+			1);
 		spin_unlock_irqrestore(
 			&cci_dev->cci_master_info[master].lock_q[queue], flags);
 		rc = cam_cci_wait(cci_dev, master, queue);
@@ -682,8 +685,8 @@
 	spin_unlock_irqrestore(&cci_dev->cci_master_info[master].lock_q[queue],
 		flags);
 
-	max_queue_size = cci_dev->cci_i2c_queue_info[master][queue].
-			max_queue_size;
+	max_queue_size =
+		cci_dev->cci_i2c_queue_info[master][queue].max_queue_size;
 
 	if (c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ)
 		queue_size = max_queue_size;
@@ -993,8 +996,8 @@
 	cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR);
 	CAM_DBG(CAM_CCI, "wait_for_completion_timeout");
 
-	rc = wait_for_completion_timeout(&cci_dev->
-		cci_master_info[master].reset_complete, CCI_TIMEOUT);
+	rc = wait_for_completion_timeout(
+		&cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT);
 	if (rc <= 0) {
 #ifdef DUMP_CCI_REGISTERS
 		cam_cci_dump_registers(cci_dev, master, queue);
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 8fb2468..fb37526 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
@@ -74,14 +74,14 @@
 		if (cci_dev->cci_master_info[MASTER_0].reset_pending == TRUE) {
 			cci_dev->cci_master_info[MASTER_0].reset_pending =
 				FALSE;
-			complete(&cci_dev->cci_master_info[MASTER_0].
-				reset_complete);
+			complete(
+			&cci_dev->cci_master_info[MASTER_0].reset_complete);
 		}
 		if (cci_dev->cci_master_info[MASTER_1].reset_pending == TRUE) {
 			cci_dev->cci_master_info[MASTER_1].reset_pending =
 				FALSE;
-			complete(&cci_dev->cci_master_info[MASTER_1].
-				reset_complete);
+			complete(
+			&cci_dev->cci_master_info[MASTER_1].reset_complete);
 		}
 	}
 	if (irq & CCI_IRQ_STATUS_0_I2C_M0_RD_DONE_BMSK) {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c
index 14737f9..295259d 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c
@@ -53,11 +53,11 @@
 			mutex_lock(&cci_dev->cci_master_info[master].mutex);
 			flush_workqueue(cci_dev->write_wq[master]);
 			/* Re-initialize the completion */
-			reinit_completion(&cci_dev->
-				cci_master_info[master].reset_complete);
+			reinit_completion(
+			&cci_dev->cci_master_info[master].reset_complete);
 			for (i = 0; i < NUM_QUEUES; i++)
-				reinit_completion(&cci_dev->
-					cci_master_info[master].report_q[i]);
+				reinit_completion(
+				&cci_dev->cci_master_info[master].report_q[i]);
 			/* Set reset pending flag to TRUE */
 			cci_dev->cci_master_info[master].reset_pending = TRUE;
 			/* Set proper mask to RESET CMD address */
@@ -69,8 +69,7 @@
 					base + CCI_RESET_CMD_ADDR);
 			/* wait for reset done irq */
 			rc = wait_for_completion_timeout(
-				&cci_dev->cci_master_info[master].
-				reset_complete,
+			&cci_dev->cci_master_info[master].reset_complete,
 				CCI_TIMEOUT);
 			if (rc <= 0)
 				CAM_ERR(CAM_CCI, "wait failed %d", rc);
@@ -94,8 +93,8 @@
 	/* Re-initialize the completion */
 	reinit_completion(&cci_dev->cci_master_info[master].reset_complete);
 	for (i = 0; i < NUM_QUEUES; i++)
-		reinit_completion(&cci_dev->cci_master_info[master].
-			report_q[i]);
+		reinit_completion(
+			&cci_dev->cci_master_info[master].report_q[i]);
 
 	/* Enable Regulators and IRQ*/
 	rc = cam_soc_util_enable_platform_resource(soc_info, true,
@@ -116,19 +115,15 @@
 	for (i = 0; i < NUM_MASTERS; i++) {
 		for (j = 0; j < NUM_QUEUES; j++) {
 			if (j == QUEUE_0)
-				cci_dev->cci_i2c_queue_info[i][j].
-					max_queue_size =
-						CCI_I2C_QUEUE_0_SIZE;
+				cci_dev->cci_i2c_queue_info[i][j].max_queue_size
+					= CCI_I2C_QUEUE_0_SIZE;
 			else
-				cci_dev->cci_i2c_queue_info[i][j].
-					max_queue_size =
-						CCI_I2C_QUEUE_1_SIZE;
+				cci_dev->cci_i2c_queue_info[i][j].max_queue_size
+					= CCI_I2C_QUEUE_1_SIZE;
 
-			CAM_DBG(CAM_CCI, "CCI Master[%d] :: Q0 : %d Q1 : %d", i
-				, cci_dev->cci_i2c_queue_info[i][j].
-					max_queue_size,
-				cci_dev->cci_i2c_queue_info[i][j].
-					max_queue_size);
+			CAM_DBG(CAM_CCI, "CCI Master[%d] :: Q0 : %d Q1 : %d", i,
+			cci_dev->cci_i2c_queue_info[i][j].max_queue_size,
+			cci_dev->cci_i2c_queue_info[i][j].max_queue_size);
 		}
 	}
 
@@ -191,13 +186,13 @@
 	for (i = 0; i < NUM_MASTERS; i++) {
 		new_cci_dev->cci_master_info[i].status = 0;
 		mutex_init(&new_cci_dev->cci_master_info[i].mutex);
-		init_completion(&new_cci_dev->
-			cci_master_info[i].reset_complete);
+		init_completion(
+			&new_cci_dev->cci_master_info[i].reset_complete);
 
 		for (j = 0; j < NUM_QUEUES; j++) {
 			mutex_init(&new_cci_dev->cci_master_info[i].mutex_q[j]);
-			init_completion(&new_cci_dev->
-				cci_master_info[i].report_q[j]);
+			init_completion(
+				&new_cci_dev->cci_master_info[i].report_q[j]);
 			spin_lock_init(
 				&new_cci_dev->cci_master_info[i].lock_q[j]);
 		}
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 4f30f56..e978a40 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
@@ -64,16 +64,14 @@
 
 	for (i = 0; i < size; i++) {
 		cam_io_w_mb(
-			csiphy_dev->ctrl_reg->
-			csiphy_reset_reg[i].reg_data,
+			csiphy_dev->ctrl_reg->csiphy_reset_reg[i].reg_data,
 			base +
-			csiphy_dev->ctrl_reg->
-			csiphy_reset_reg[i].reg_addr);
+			csiphy_dev->ctrl_reg->csiphy_reset_reg[i].reg_addr);
 
 		usleep_range(csiphy_dev->ctrl_reg->
 			csiphy_reset_reg[i].delay * 1000,
-			csiphy_dev->ctrl_reg->
-			csiphy_reset_reg[i].delay * 1000 + 10);
+			csiphy_dev->ctrl_reg->csiphy_reset_reg[i].delay * 1000
+			+ 10);
 	}
 }
 
@@ -150,11 +148,10 @@
 		csiphy_dev->soc_info.reg_map[0].mem_base;
 
 	for (i = 0; i < csiphy_dev->num_irq_registers; i++)
-		cam_io_w_mb(csiphy_dev->ctrl_reg->
-			csiphy_irq_reg[i].reg_data,
+		cam_io_w_mb(
+			csiphy_dev->ctrl_reg->csiphy_irq_reg[i].reg_data,
 			csiphybase +
-			csiphy_dev->ctrl_reg->
-			csiphy_irq_reg[i].reg_addr);
+			csiphy_dev->ctrl_reg->csiphy_irq_reg[i].reg_addr);
 }
 
 void cam_csiphy_cphy_irq_disable(struct csiphy_device *csiphy_dev)
@@ -164,10 +161,8 @@
 		csiphy_dev->soc_info.reg_map[0].mem_base;
 
 	for (i = 0; i < csiphy_dev->num_irq_registers; i++)
-		cam_io_w_mb(0x0,
-			csiphybase +
-			csiphy_dev->ctrl_reg->
-			csiphy_irq_reg[i].reg_addr);
+		cam_io_w_mb(0x0, csiphybase +
+			csiphy_dev->ctrl_reg->csiphy_irq_reg[i].reg_addr);
 }
 
 irqreturn_t cam_csiphy_irq(int irq_num, void *data)
@@ -177,6 +172,7 @@
 	struct csiphy_device *csiphy_dev =
 		(struct csiphy_device *)data;
 	struct cam_hw_soc_info *soc_info = NULL;
+	struct csiphy_reg_parms_t *csiphy_reg = NULL;
 	void __iomem *base = NULL;
 
 	if (!csiphy_dev) {
@@ -186,30 +182,24 @@
 
 	soc_info = &csiphy_dev->soc_info;
 	base =  csiphy_dev->soc_info.reg_map[0].mem_base;
+	csiphy_reg = &csiphy_dev->ctrl_reg->csiphy_reg;
 
 	for (i = 0; i < csiphy_dev->num_irq_registers; i++) {
-		irq = cam_io_r(
-			base +
-			csiphy_dev->ctrl_reg->csiphy_reg.
-			mipi_csiphy_interrupt_status0_addr + 0x4*i);
-		cam_io_w_mb(irq,
-			base +
-			csiphy_dev->ctrl_reg->csiphy_reg.
-			mipi_csiphy_interrupt_clear0_addr + 0x4*i);
+		irq = cam_io_r(base +
+			csiphy_reg->mipi_csiphy_interrupt_status0_addr +
+			(0x4 * i));
+		cam_io_w_mb(irq, base +
+			csiphy_reg->mipi_csiphy_interrupt_clear0_addr +
+			(0x4 * i));
 		CAM_ERR_RATE_LIMIT(CAM_CSIPHY,
 			"CSIPHY%d_IRQ_STATUS_ADDR%d = 0x%x",
 			soc_info->index, i, irq);
-		cam_io_w_mb(0x0,
-			base +
-			csiphy_dev->ctrl_reg->csiphy_reg.
-			mipi_csiphy_interrupt_clear0_addr + 0x4*i);
+		cam_io_w_mb(0x0, base +
+			csiphy_reg->mipi_csiphy_interrupt_clear0_addr +
+			(0x4 * i));
 	}
-	cam_io_w_mb(0x1, base +
-		csiphy_dev->ctrl_reg->
-		csiphy_reg.mipi_csiphy_glbl_irq_cmd_addr);
-	cam_io_w_mb(0x0, base +
-		csiphy_dev->ctrl_reg->
-		csiphy_reg.mipi_csiphy_glbl_irq_cmd_addr);
+	cam_io_w_mb(0x1, base + csiphy_reg->mipi_csiphy_glbl_irq_cmd_addr);
+	cam_io_w_mb(0x0, base + csiphy_reg->mipi_csiphy_glbl_irq_cmd_addr);
 
 	return IRQ_HANDLED;
 }
@@ -222,6 +212,7 @@
 	uint8_t      lane_cnt, lane_pos = 0;
 	uint16_t     settle_cnt = 0;
 	void __iomem *csiphybase;
+	struct csiphy_reg_t *csiphy_common_reg = NULL;
 	struct csiphy_reg_t (*reg_array)[MAX_SETTINGS_PER_LANE];
 
 	lane_cnt = csiphy_dev->csiphy_info.lane_cnt;
@@ -240,8 +231,8 @@
 			reg_array =
 				csiphy_dev->ctrl_reg->csiphy_2ph_reg;
 		csiphy_dev->num_irq_registers = 11;
-		cfg_size = csiphy_dev->ctrl_reg->csiphy_reg.
-			csiphy_2ph_config_array_size;
+		cfg_size =
+		csiphy_dev->ctrl_reg->csiphy_reg.csiphy_2ph_config_array_size;
 
 		lane_mask = csiphy_dev->csiphy_info.lane_mask & 0x1f;
 		for (i = 0; i < MAX_DPHY_DATA_LN; i++) {
@@ -262,8 +253,8 @@
 			reg_array =
 				csiphy_dev->ctrl_reg->csiphy_3ph_reg;
 		csiphy_dev->num_irq_registers = 11;
-		cfg_size = csiphy_dev->ctrl_reg->csiphy_reg.
-			csiphy_3ph_config_array_size;
+		cfg_size =
+		csiphy_dev->ctrl_reg->csiphy_reg.csiphy_3ph_config_array_size;
 
 		lane_mask = csiphy_dev->csiphy_info.lane_mask & 0x7;
 		mask = lane_mask;
@@ -276,32 +267,24 @@
 	}
 
 	size = csiphy_dev->ctrl_reg->csiphy_reg.csiphy_common_array_size;
-
 	for (i = 0; i < size; i++) {
-		switch (csiphy_dev->ctrl_reg->
-			csiphy_common_reg[i].csiphy_param_type) {
-			case CSIPHY_LANE_ENABLE:
+		csiphy_common_reg = &csiphy_dev->ctrl_reg->csiphy_common_reg[i];
+		switch (csiphy_common_reg->csiphy_param_type) {
+		case CSIPHY_LANE_ENABLE:
 				cam_io_w_mb(lane_enable,
 					csiphybase +
-					csiphy_dev->ctrl_reg->
-					csiphy_common_reg[i].reg_addr);
-				usleep_range(csiphy_dev->ctrl_reg->
-					csiphy_common_reg[i].delay*1000,
-					csiphy_dev->ctrl_reg->
-					csiphy_common_reg[i].delay*1000 + 10);
+					csiphy_common_reg->reg_addr);
+				usleep_range(csiphy_common_reg->delay * 1000,
+					csiphy_common_reg->delay * 1000 + 10);
 			break;
-			case CSIPHY_DEFAULT_PARAMS:
-				cam_io_w_mb(csiphy_dev->ctrl_reg->
-					csiphy_common_reg[i].reg_data,
+		case CSIPHY_DEFAULT_PARAMS:
+				cam_io_w_mb(csiphy_common_reg->reg_data,
 					csiphybase +
-					csiphy_dev->ctrl_reg->
-					csiphy_common_reg[i].reg_addr);
-				usleep_range(csiphy_dev->ctrl_reg->
-					csiphy_common_reg[i].delay*1000,
-					csiphy_dev->ctrl_reg->
-					csiphy_common_reg[i].delay*1000 + 10);
+					csiphy_common_reg->reg_addr);
+				usleep_range(csiphy_common_reg->delay * 1000,
+					csiphy_common_reg->delay * 1000 + 10);
 			break;
-			default:
+		default:
 			break;
 		}
 	}
@@ -317,8 +300,8 @@
 		if (csiphy_dev->csiphy_info.combo_mode == 1 &&
 			(lane_pos >= 3))
 			settle_cnt =
-				(csiphy_dev->csiphy_info.
-				settle_time_combo_sensor / 200000000);
+			(csiphy_dev->csiphy_info.settle_time_combo_sensor /
+				200000000);
 		for (i = 0; i < cfg_size; i++) {
 			switch (reg_array[lane_pos][i].csiphy_param_type) {
 			case CSIPHY_LANE_ENABLE:
@@ -400,6 +383,7 @@
 	csiphy_dev->ref_count = 0;
 	csiphy_dev->is_acquired_dev_combo_mode = 0;
 	csiphy_dev->acquire_count = 0;
+	csiphy_dev->start_dev_count = 0;
 	csiphy_dev->csiphy_state = CAM_CSIPHY_INIT;
 }
 
@@ -445,6 +429,7 @@
 {
 	struct csiphy_device *csiphy_dev =
 		(struct csiphy_device *)phy_dev;
+	struct intf_params   *bridge_intf = NULL;
 	struct cam_control   *cmd = (struct cam_control *)arg;
 	int32_t              rc = 0;
 
@@ -523,11 +508,10 @@
 
 		csiphy_acq_dev.device_handle =
 			cam_create_device_hdl(&bridge_params);
-		csiphy_dev->bridge_intf.
-			device_hdl[csiphy_acq_params.combo_mode] =
-				csiphy_acq_dev.device_handle;
-		csiphy_dev->bridge_intf.
-			session_hdl[csiphy_acq_params.combo_mode] =
+		bridge_intf = &csiphy_dev->bridge_intf;
+		bridge_intf->device_hdl[csiphy_acq_params.combo_mode]
+			= csiphy_acq_dev.device_handle;
+		bridge_intf->session_hdl[csiphy_acq_params.combo_mode] =
 			csiphy_acq_dev.session_handle;
 
 		if (copy_to_user((void __user *)cmd->handle,
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 e7110b8..9b74826 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
@@ -284,8 +284,8 @@
 			for (i = 0; i < flash_data->cmn_attr.count; i++)
 				flash_data->led_current_ma[i] = 0;
 		} else {
-			fctrl->flash_init_setting.cmn_attr.
-				is_settings_valid = false;
+			fctrl->flash_init_setting.cmn_attr.is_settings_valid
+				= false;
 		}
 	} else {
 		for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
@@ -513,7 +513,7 @@
 	uint64_t generic_ptr;
 	uint32_t *cmd_buf =  NULL;
 	uint32_t *offset = NULL;
-	uint32_t frame_offset = 0;
+	uint32_t frm_offset = 0;
 	size_t len_of_buffer;
 	struct cam_control *ioctl_ctrl = NULL;
 	struct cam_packet *csl_packet = NULL;
@@ -525,6 +525,7 @@
 	struct cam_flash_set_rer *flash_rer_info = NULL;
 	struct cam_flash_set_on_off *flash_operation_info = NULL;
 	struct cam_flash_query_curr *flash_query_info = NULL;
+	struct cam_flash_frame_setting *flash_data = NULL;
 
 	if (!fctrl || !arg) {
 		CAM_ERR(CAM_FLASH, "fctrl/arg is NULL");
@@ -616,25 +617,19 @@
 	case CAM_FLASH_PACKET_OPCODE_SET_OPS: {
 		offset = (uint32_t *)((uint8_t *)&csl_packet->payload +
 			csl_packet->cmd_buf_offset);
-		frame_offset = csl_packet->header.request_id %
+		frm_offset = csl_packet->header.request_id %
 			MAX_PER_FRAME_ARRAY;
-		if (fctrl->per_frame[frame_offset].cmn_attr.is_settings_valid
-			== true) {
-			fctrl->per_frame[frame_offset].cmn_attr.request_id = 0;
-			fctrl->per_frame[frame_offset].
-				cmn_attr.is_settings_valid = false;
-			for (i = 0;
-			i < fctrl->per_frame[frame_offset].cmn_attr.count;
-			i++) {
-				fctrl->per_frame[frame_offset].
-					led_current_ma[i] = 0;
-			}
+		flash_data = &fctrl->per_frame[frm_offset];
+
+		if (flash_data->cmn_attr.is_settings_valid == true) {
+			flash_data->cmn_attr.request_id = 0;
+			flash_data->cmn_attr.is_settings_valid = false;
+			for (i = 0; i < flash_data->cmn_attr.count; i++)
+				flash_data->led_current_ma[i] = 0;
 		}
 
-		fctrl->per_frame[frame_offset].cmn_attr.request_id =
-			csl_packet->header.request_id;
-		fctrl->per_frame[frame_offset].cmn_attr.is_settings_valid =
-			true;
+		flash_data->cmn_attr.request_id = csl_packet->header.request_id;
+		flash_data->cmn_attr.is_settings_valid = true;
 		cmd_desc = (struct cam_cmd_buf_desc *)(offset);
 		rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
 			(uint64_t *)&generic_ptr, &len_of_buffer);
@@ -655,8 +650,7 @@
 					CAM_FLASH_STATE_ACQUIRE)) {
 				CAM_WARN(CAM_FLASH,
 					"Rxed Flash fire ops without linking");
-				fctrl->per_frame[frame_offset].
-					cmn_attr.is_settings_valid = false;
+				flash_data->cmn_attr.is_settings_valid = false;
 				return 0;
 			}
 
@@ -668,16 +662,12 @@
 				return -EINVAL;
 			}
 
-			fctrl->per_frame[frame_offset].opcode =
-				flash_operation_info->opcode;
-			fctrl->per_frame[frame_offset].cmn_attr.count =
+			flash_data->opcode = flash_operation_info->opcode;
+			flash_data->cmn_attr.count =
 				flash_operation_info->count;
-			for (i = 0;
-				i < flash_operation_info->count; i++)
-				fctrl->per_frame[frame_offset].
-					led_current_ma[i]
-					= flash_operation_info->
-					led_current_ma[i];
+			for (i = 0; i < flash_operation_info->count; i++)
+				flash_data->led_current_ma[i]
+				= flash_operation_info->led_current_ma[i];
 			}
 			break;
 		default:
@@ -782,8 +772,10 @@
 			(fctrl->flash_state == CAM_FLASH_STATE_ACQUIRE)) {
 			CAM_WARN(CAM_FLASH,
 				"Rxed NOP packets without linking");
-			fctrl->per_frame[frame_offset].
-				cmn_attr.is_settings_valid = false;
+			frm_offset = csl_packet->header.request_id %
+				MAX_PER_FRAME_ARRAY;
+			fctrl->per_frame[frm_offset].cmn_attr.is_settings_valid
+				= false;
 			return 0;
 		}
 
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 3a0a6d6..fbdaee7 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
@@ -233,17 +233,13 @@
 			size = i2c_list->i2c_settings.size;
 			for (i = 0; i < size; i++) {
 				rc = camera_io_dev_poll(
-					&(o_ctrl->io_master_info),
-					i2c_list->i2c_settings.
-						reg_setting[i].reg_addr,
-					i2c_list->i2c_settings.
-						reg_setting[i].reg_data,
-					i2c_list->i2c_settings.
-						reg_setting[i].data_mask,
-					i2c_list->i2c_settings.addr_type,
-					i2c_list->i2c_settings.data_type,
-					i2c_list->i2c_settings.
-						reg_setting[i].delay);
+				&(o_ctrl->io_master_info),
+				i2c_list->i2c_settings.reg_setting[i].reg_addr,
+				i2c_list->i2c_settings.reg_setting[i].reg_data,
+				i2c_list->i2c_settings.reg_setting[i].data_mask,
+				i2c_list->i2c_settings.addr_type,
+				i2c_list->i2c_settings.data_type,
+				i2c_list->i2c_settings.reg_setting[i].delay);
 				if (rc < 0) {
 					CAM_ERR(CAM_OIS,
 						"i2c poll apply setting Fail");
@@ -529,8 +525,8 @@
 					return rc;
 				}
 			} else if ((o_ctrl->is_ois_calib != 0) &&
-				(o_ctrl->i2c_calib_data.
-					is_settings_valid == 0)) {
+				(o_ctrl->i2c_calib_data.is_settings_valid ==
+				0)) {
 				CAM_DBG(CAM_OIS,
 					"Received calib settings");
 				i2c_reg_settings = &(o_ctrl->i2c_calib_data);
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 5a1b67c..b3f3a35 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
@@ -190,9 +190,8 @@
 		}
 
 		i2c_reg_settings =
-			&i2c_data->
-			per_frame[csl_packet->header.request_id %
-			MAX_PER_FRAME_ARRAY];
+			&i2c_data->per_frame[csl_packet->header.request_id %
+				MAX_PER_FRAME_ARRAY];
 		CAM_DBG(CAM_SENSOR, "Received Packet: %lld req: %lld",
 			csl_packet->header.request_id % MAX_PER_FRAME_ARRAY,
 			csl_packet->header.request_id);
@@ -290,16 +289,12 @@
 		for (i = 0; i < size; i++) {
 			rc = camera_io_dev_poll(
 			io_master_info,
-			i2c_list->i2c_settings.
-				reg_setting[i].reg_addr,
-			i2c_list->i2c_settings.
-				reg_setting[i].reg_data,
-			i2c_list->i2c_settings.
-				reg_setting[i].data_mask,
+			i2c_list->i2c_settings.reg_setting[i].reg_addr,
+			i2c_list->i2c_settings.reg_setting[i].reg_data,
+			i2c_list->i2c_settings.reg_setting[i].data_mask,
 			i2c_list->i2c_settings.addr_type,
-				i2c_list->i2c_settings.data_type,
-			i2c_list->i2c_settings.
-				reg_setting[i].delay);
+			i2c_list->i2c_settings.data_type,
+			i2c_list->i2c_settings.reg_setting[i].delay);
 			if (rc < 0) {
 				CAM_ERR(CAM_SENSOR,
 					"i2c poll apply setting Fail: %d", rc);
@@ -1104,9 +1099,9 @@
 
 		for (i = 0; i < MAX_PER_FRAME_ARRAY; i++) {
 			if ((del_req_id >
-				 s_ctrl->i2c_data.per_frame[i].request_id) &&
-				(s_ctrl->i2c_data.per_frame[i].
-					is_settings_valid == 1)) {
+				 s_ctrl->i2c_data.per_frame[i].request_id) && (
+				 s_ctrl->i2c_data.per_frame[i].is_settings_valid
+					== 1)) {
 				s_ctrl->i2c_data.per_frame[i].request_id = 0;
 				rc = delete_request(
 					&(s_ctrl->i2c_data.per_frame[i]));
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 f9b846b..ac60dc8 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
@@ -93,12 +93,10 @@
 			list_entry(list_ptr, struct i2c_settings_list, list);
 		if (generic_op_code ==
 			CAMERA_SENSOR_WAIT_OP_HW_UCND)
-			i2c_list->i2c_settings.
-				reg_setting[offset - 1].delay =
+			i2c_list->i2c_settings.reg_setting[offset - 1].delay =
 				cmd_uncond_wait->delay;
 		else
-			i2c_list->i2c_settings.delay =
-				cmd_uncond_wait->delay;
+			i2c_list->i2c_settings.delay = cmd_uncond_wait->delay;
 		(*cmd_buf) +=
 			sizeof(
 			struct cam_cmd_unconditional_wait) / sizeof(uint32_t);
@@ -182,14 +180,10 @@
 	for (cnt = 0; cnt < (cam_cmd_i2c_random_wr->header.count);
 		cnt++) {
 		i2c_list->i2c_settings.reg_setting[cnt].reg_addr =
-			cam_cmd_i2c_random_wr->
-			random_wr_payload[cnt].reg_addr;
-		i2c_list->i2c_settings.
-			reg_setting[cnt].reg_data =
-			cam_cmd_i2c_random_wr->
-			random_wr_payload[cnt].reg_data;
-		i2c_list->i2c_settings.
-			reg_setting[cnt].data_mask = 0;
+			cam_cmd_i2c_random_wr->random_wr_payload[cnt].reg_addr;
+		i2c_list->i2c_settings.reg_setting[cnt].reg_data =
+			cam_cmd_i2c_random_wr->random_wr_payload[cnt].reg_data;
+		i2c_list->i2c_settings.reg_setting[cnt].data_mask = 0;
 	}
 	*offset = cnt;
 	*list = &(i2c_list->list);
@@ -237,14 +231,10 @@
 	for (cnt = 0; cnt < (cam_cmd_i2c_continuous_wr->header.count);
 		cnt++) {
 		i2c_list->i2c_settings.reg_setting[cnt].reg_addr =
-			cam_cmd_i2c_continuous_wr->
-			reg_addr;
-		i2c_list->i2c_settings.
-			reg_setting[cnt].reg_data =
-			cam_cmd_i2c_continuous_wr->
-			data_read[cnt].reg_data;
-		i2c_list->i2c_settings.
-			reg_setting[cnt].data_mask = 0;
+			cam_cmd_i2c_continuous_wr->reg_addr;
+		i2c_list->i2c_settings.reg_setting[cnt].reg_data =
+			cam_cmd_i2c_continuous_wr->data_read[cnt].reg_data;
+		i2c_list->i2c_settings.reg_setting[cnt].data_mask = 0;
 	}
 	*offset = cnt;
 	*list = &(i2c_list->list);
@@ -642,6 +632,7 @@
 {
 	int32_t rc = 0, tot_size = 0, last_cmd_type = 0;
 	int32_t i = 0, pwr_up = 0, pwr_down = 0;
+	struct cam_sensor_power_setting *pwr_settings;
 	void *ptr = cmd_buf, *scr;
 	struct cam_cmd_power *pwr_cmd = (struct cam_cmd_power *)cmd_buf;
 	struct common_header *cmm_hdr = (struct common_header *)cmd_buf;
@@ -684,14 +675,10 @@
 				CAM_WARN(CAM_SENSOR, "Un expected Command");
 
 			for (i = 0; i < pwr_cmd->count; i++, pwr_up++) {
-				power_info->
-					power_setting[pwr_up].seq_type =
-					pwr_cmd->power_settings[i].
-						power_seq_type;
-				power_info->
-					power_setting[pwr_up].config_val =
-					pwr_cmd->power_settings[i].
-						config_val_low;
+				power_info->power_setting[pwr_up].seq_type =
+				pwr_cmd->power_settings[i].power_seq_type;
+				power_info->power_setting[pwr_up].config_val =
+				pwr_cmd->power_settings[i].config_val_low;
 				power_info->power_setting[pwr_up].delay = 0;
 				if (i) {
 					scr = scr +
@@ -708,13 +695,9 @@
 					goto free_power_down_settings;
 				}
 				CAM_DBG(CAM_SENSOR,
-					"Seq Type[%d]: %d Config_val: %ld",
-					pwr_up,
-					power_info->
-						power_setting[pwr_up].seq_type,
-					power_info->
-						power_setting[pwr_up].
-						config_val);
+				"Seq Type[%d]: %d Config_val: %ld", pwr_up,
+				power_info->power_setting[pwr_up].seq_type,
+				power_info->power_setting[pwr_up].config_val);
 			}
 			last_cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_UP;
 			ptr = (void *) scr;
@@ -722,32 +705,38 @@
 		} else if (cmm_hdr->cmd_type == CAMERA_SENSOR_CMD_TYPE_WAIT) {
 			struct cam_cmd_unconditional_wait *wait_cmd =
 				(struct cam_cmd_unconditional_wait *)ptr;
-			if (wait_cmd->op_code ==
-				CAMERA_SENSOR_WAIT_OP_SW_UCND) {
-				if (last_cmd_type ==
-					CAMERA_SENSOR_CMD_TYPE_PWR_UP) {
-					if (pwr_up > 0)
-						power_info->
-							power_setting
-							[pwr_up - 1].delay +=
-							wait_cmd->delay;
-					else
-						CAM_ERR(CAM_SENSOR,
-							"Delay is expected only after valid power up setting");
-				} else if (last_cmd_type ==
-					CAMERA_SENSOR_CMD_TYPE_PWR_DOWN) {
-					if (pwr_down > 0)
-						power_info->
-							power_down_setting
-							[pwr_down - 1].delay +=
-							wait_cmd->delay;
-					else
-						CAM_ERR(CAM_SENSOR,
-							"Delay is expected only after valid power up setting");
+			if ((wait_cmd->op_code ==
+				CAMERA_SENSOR_WAIT_OP_SW_UCND) &&
+				(last_cmd_type ==
+				CAMERA_SENSOR_CMD_TYPE_PWR_UP)) {
+				if (pwr_up > 0) {
+					pwr_settings =
+					&power_info->power_setting[pwr_up - 1];
+					pwr_settings->delay +=
+						wait_cmd->delay;
+				} else {
+					CAM_ERR(CAM_SENSOR,
+					"Delay is expected only after valid power up setting");
 				}
-			} else
+			} else if ((wait_cmd->op_code ==
+				CAMERA_SENSOR_WAIT_OP_SW_UCND) &&
+				(last_cmd_type ==
+				CAMERA_SENSOR_CMD_TYPE_PWR_DOWN)) {
+				if (pwr_down > 0) {
+					pwr_settings =
+					&power_info->power_down_setting[
+						pwr_down - 1];
+					pwr_settings->delay +=
+						wait_cmd->delay;
+				} else {
+					CAM_ERR(CAM_SENSOR,
+					"Delay is expected only after valid power up setting");
+				}
+			} else {
 				CAM_DBG(CAM_SENSOR, "Invalid op code: %d",
 					wait_cmd->op_code);
+			}
+
 			tot_size = tot_size +
 				sizeof(struct cam_cmd_unconditional_wait);
 			if (tot_size > cmd_length) {
@@ -776,18 +765,14 @@
 				CAM_ERR(CAM_SENSOR, "Invalid Command");
 
 			for (i = 0; i < pwr_cmd->count; i++, pwr_down++) {
-				power_info->
-					power_down_setting[pwr_down].
-					seq_type =
-					pwr_cmd->power_settings[i].
-					power_seq_type;
-				power_info->
-					power_down_setting[pwr_down].
-					config_val =
-					pwr_cmd->power_settings[i].
-					config_val_low;
-				power_info->
-					power_down_setting[pwr_down].delay = 0;
+				pwr_settings =
+				&power_info->power_down_setting[pwr_down];
+				pwr_settings->seq_type =
+				pwr_cmd->power_settings[i].power_seq_type;
+				pwr_settings->config_val =
+				pwr_cmd->power_settings[i].config_val_low;
+				power_info->power_down_setting[pwr_down].delay
+					= 0;
 				if (i) {
 					scr = scr +
 						sizeof(
@@ -805,13 +790,8 @@
 				}
 				CAM_DBG(CAM_SENSOR,
 					"Seq Type[%d]: %d Config_val: %ld",
-					pwr_down,
-					power_info->
-						power_down_setting[pwr_down].
-						seq_type,
-					power_info->
-						power_down_setting[pwr_down].
-						config_val);
+					pwr_down, pwr_settings->seq_type,
+					pwr_settings->config_val);
 			}
 			last_cmd_type = CAMERA_SENSOR_CMD_TYPE_PWR_DOWN;
 			ptr = (void *) scr;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
index fda45cb..691b492 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.c
@@ -26,6 +26,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 #include <media/videobuf2-core.h>
+#include <media/msmb_generic_buf_mgr.h>
 
 #include "msm.h"
 #include "msm_buf_mgr.h"
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 269d563..7a8e621 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -1048,15 +1048,18 @@
 				fe_cfg->stream_id);
 		vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;
 
+		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
 			vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
 		if (rc < 0 || !buf) {
 			pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
 				__func__, rc, buf);
+			mutex_unlock(&vfe_dev->buf_mgr->lock);
 			return -EINVAL;
 		}
 		mapped_info = buf->mapped_info[0];
 		buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 	} else {
 		rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
 			&mapped_info, fe_cfg->fd);
@@ -1109,14 +1112,15 @@
 		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
 			vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
-		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		if (rc < 0 || !buf) {
 			pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
 				__func__, rc, buf);
+			mutex_unlock(&vfe_dev->buf_mgr->lock);
 			return -EINVAL;
 		}
 		mapped_info = buf->mapped_info[0];
 		buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 	} else {
 		rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
 			&mapped_info, fe_cfg->fd);
@@ -1214,6 +1218,10 @@
 	case V4L2_PIX_FMT_P16GBRG10:
 	case V4L2_PIX_FMT_P16GRBG10:
 	case V4L2_PIX_FMT_P16RGGB10:
+	case V4L2_PIX_FMT_P16BGGR12:
+	case V4L2_PIX_FMT_P16GBRG12:
+	case V4L2_PIX_FMT_P16GRBG12:
+	case V4L2_PIX_FMT_P16RGGB12:
 		main_unpack_pattern = 0xB210;
 		break;
 	default:
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
index a9ff454..8bd50d5 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
@@ -895,13 +895,14 @@
 		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
 			vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
-		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		if (rc < 0) {
 			pr_err("%s: No fetch buffer\n", __func__);
+			mutex_unlock(&vfe_dev->buf_mgr->lock);
 			return -EINVAL;
 		}
 		mapped_info = buf->mapped_info[0];
 		buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 	} else {
 		rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
 			&mapped_info, fe_cfg->fd);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
index 0239fe7..e0712f7 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
@@ -833,14 +833,15 @@
 		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
 			vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
-		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		if (rc < 0 || !buf) {
 			pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
 				__func__, rc, buf);
+			mutex_unlock(&vfe_dev->buf_mgr->lock);
 			return -EINVAL;
 		}
 		mapped_info = buf->mapped_info[0];
 		buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 	} else {
 		rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
 			&mapped_info, fe_cfg->fd);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
index 410689f..b867eb3 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -1102,15 +1102,18 @@
 			fe_cfg->stream_id);
 		vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;
 
+		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
 			vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
 		if (rc < 0 || !buf) {
 			pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
 				__func__, rc, buf);
+			mutex_unlock(&vfe_dev->buf_mgr->lock);
 			return -EINVAL;
 		}
 		mapped_info = buf->mapped_info[0];
 		buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 	} else {
 		rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
 			&mapped_info, fe_cfg->fd);
@@ -1163,14 +1166,15 @@
 		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
 			vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
-		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		if (rc < 0 || !buf) {
 			pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
 				__func__, rc, buf);
+			mutex_unlock(&vfe_dev->buf_mgr->lock);
 			return -EINVAL;
 		}
 		mapped_info = buf->mapped_info[0];
 		buf->state = MSM_ISP_BUFFER_STATE_DISPATCHED;
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 	} else {
 		rc = vfe_dev->buf_mgr->ops->map_buf(vfe_dev->buf_mgr,
 			&mapped_info, fe_cfg->fd);
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 5b1a804..73a5ebc 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
@@ -235,6 +235,10 @@
 	case V4L2_PIX_FMT_P16GBRG10:
 	case V4L2_PIX_FMT_P16GRBG10:
 	case V4L2_PIX_FMT_P16RGGB10:
+	case V4L2_PIX_FMT_P16BGGR12:
+	case V4L2_PIX_FMT_P16GBRG12:
+	case V4L2_PIX_FMT_P16GRBG12:
+	case V4L2_PIX_FMT_P16RGGB12:
 	case V4L2_PIX_FMT_JPEG:
 	case V4L2_PIX_FMT_META:
 	case V4L2_PIX_FMT_META10:
@@ -376,6 +380,10 @@
 	case V4L2_PIX_FMT_P16GBRG10:
 	case V4L2_PIX_FMT_P16GRBG10:
 	case V4L2_PIX_FMT_P16RGGB10:
+	case V4L2_PIX_FMT_P16BGGR12:
+	case V4L2_PIX_FMT_P16GBRG12:
+	case V4L2_PIX_FMT_P16GRBG12:
+	case V4L2_PIX_FMT_P16RGGB12:
 		size = plane_cfg[plane_idx].output_height *
 		plane_cfg[plane_idx].output_width;
 		break;
@@ -4032,10 +4040,12 @@
 				pr_err("%s: stream_info is null", __func__);
 				return -EINVAL;
 			}
+			mutex_lock(&vfe_dev->buf_mgr->lock);
 			rc = msm_isp_request_frame(vfe_dev, stream_info,
 				update_info->user_stream_id,
 				update_info->frame_id,
 				MSM_ISP_INVALID_BUF_INDEX);
+			mutex_unlock(&vfe_dev->buf_mgr->lock);
 			if (rc)
 				pr_err("%s failed to request frame!\n",
 					__func__);
@@ -4087,10 +4097,12 @@
 			pr_err("%s: stream_info is null", __func__);
 			return -EINVAL;
 		}
+		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = msm_isp_request_frame(vfe_dev, stream_info,
 			req_frm->user_stream_id,
 			req_frm->frame_id,
 			req_frm->buf_index);
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		if (rc)
 			pr_err("%s failed to request frame!\n",
 				__func__);
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 99dc054..d3a68b1 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
@@ -402,8 +402,10 @@
 		vfe_idx = msm_isp_get_vfe_idx_for_stream(vfe_dev, stream_info);
 		msm_isp_reset_framedrop(vfe_dev, stream_info);
 
+		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = msm_isp_cfg_offline_ping_pong_address(vfe_dev, stream_info,
 			VFE_PING_FLAG, fe_cfg->output_buf_idx);
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		if (rc < 0) {
 			pr_err("%s: Fetch engine config failed\n", __func__);
 			return -EINVAL;
@@ -894,7 +896,9 @@
 	case VIDIOC_MSM_ISP_CFG_STREAM:
 		mutex_lock(&vfe_dev->core_mutex);
 		MSM_ISP_DUAL_VFE_MUTEX_LOCK(vfe_dev);
+		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = msm_isp_cfg_axi_stream(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
 		mutex_unlock(&vfe_dev->core_mutex);
 		break;
@@ -924,6 +928,7 @@
 	case VIDIOC_MSM_ISP_AXI_RESTART:
 		mutex_lock(&vfe_dev->core_mutex);
 		MSM_ISP_DUAL_VFE_MUTEX_LOCK(vfe_dev);
+		mutex_lock(&vfe_dev->buf_mgr->lock);
 		if (atomic_read(&vfe_dev->error_info.overflow_state)
 			!= HALT_ENFORCED) {
 			rc = msm_isp_stats_restart(vfe_dev);
@@ -934,6 +939,7 @@
 			pr_err_ratelimited("%s: no AXI restart, halt enforced.\n",
 				__func__);
 		}
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
 		mutex_unlock(&vfe_dev->core_mutex);
 		break;
@@ -1009,7 +1015,9 @@
 	case VIDIOC_MSM_ISP_CFG_STATS_STREAM:
 		mutex_lock(&vfe_dev->core_mutex);
 		MSM_ISP_DUAL_VFE_MUTEX_LOCK(vfe_dev);
+		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = msm_isp_cfg_stats_stream(vfe_dev, arg);
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
 		mutex_unlock(&vfe_dev->core_mutex);
 		break;
@@ -1623,6 +1631,10 @@
 	case V4L2_PIX_FMT_P16GBRG10:
 	case V4L2_PIX_FMT_P16GRBG10:
 	case V4L2_PIX_FMT_P16RGGB10:
+	case V4L2_PIX_FMT_P16BGGR12:
+	case V4L2_PIX_FMT_P16GBRG12:
+	case V4L2_PIX_FMT_P16GRBG12:
+	case V4L2_PIX_FMT_P16RGGB12:
 		val = CAL_WORD(pixel_per_line, 1, 4);
 	break;
 	case V4L2_PIX_FMT_NV24:
@@ -1686,6 +1698,10 @@
 	case V4L2_PIX_FMT_P16GBRG10:
 	case V4L2_PIX_FMT_P16GRBG10:
 	case V4L2_PIX_FMT_P16RGGB10:
+	case V4L2_PIX_FMT_P16BGGR12:
+	case V4L2_PIX_FMT_P16GBRG12:
+	case V4L2_PIX_FMT_P16GRBG12:
+	case V4L2_PIX_FMT_P16RGGB12:
 		return PLAIN16;
 	default:
 		msm_isp_print_fourcc_error(__func__, output_format);
@@ -1770,6 +1786,10 @@
 	case V4L2_PIX_FMT_QGRBG12:
 	case V4L2_PIX_FMT_QRGGB12:
 	case V4L2_PIX_FMT_Y12:
+	case V4L2_PIX_FMT_P16BGGR12:
+	case V4L2_PIX_FMT_P16GBRG12:
+	case V4L2_PIX_FMT_P16GRBG12:
+	case V4L2_PIX_FMT_P16RGGB12:
 		return 12;
 	case V4L2_PIX_FMT_SBGGR14:
 	case V4L2_PIX_FMT_SGBRG14:
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
index e350096..e458b4df 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -167,6 +167,33 @@
 	return ret;
 }
 
+static int32_t msm_buf_mngr_buf_error(struct msm_buf_mngr_device *buf_mngr_dev,
+	struct msm_buf_mngr_info *buf_info)
+{
+	unsigned long flags;
+	struct msm_get_bufs *bufs, *save;
+	int32_t ret = -EINVAL;
+
+	spin_lock_irqsave(&buf_mngr_dev->buf_q_spinlock, flags);
+	list_for_each_entry_safe(bufs, save, &buf_mngr_dev->buf_qhead, entry) {
+		if ((bufs->session_id == buf_info->session_id) &&
+			(bufs->stream_id == buf_info->stream_id) &&
+			(bufs->index == buf_info->index)) {
+			ret = buf_mngr_dev->vb2_ops.buf_error
+					(bufs->vb2_v4l2_buf,
+						buf_info->session_id,
+						buf_info->stream_id,
+						buf_info->frame_id,
+						&buf_info->timestamp,
+						buf_info->reserved);
+			list_del_init(&bufs->entry);
+			kfree(bufs);
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&buf_mngr_dev->buf_q_spinlock, flags);
+	return ret;
+}
 
 static int32_t msm_buf_mngr_put_buf(struct msm_buf_mngr_device *buf_mngr_dev,
 	struct msm_buf_mngr_info *buf_info)
@@ -478,6 +505,9 @@
 	case VIDIOC_MSM_BUF_MNGR_BUF_DONE:
 		rc = msm_buf_mngr_buf_done(msm_buf_mngr_dev, argp);
 		break;
+	case VIDIOC_MSM_BUF_MNGR_BUF_ERROR:
+		rc = msm_buf_mngr_buf_error(msm_buf_mngr_dev, argp);
+		break;
 	case VIDIOC_MSM_BUF_MNGR_PUT_BUF:
 		rc = msm_buf_mngr_put_buf(msm_buf_mngr_dev, argp);
 		break;
@@ -576,6 +606,7 @@
 	case VIDIOC_MSM_BUF_MNGR_GET_BUF:
 	case VIDIOC_MSM_BUF_MNGR_BUF_DONE:
 	case VIDIOC_MSM_BUF_MNGR_PUT_BUF:
+	case VIDIOC_MSM_BUF_MNGR_BUF_ERROR:
 		rc = msm_cam_buf_mgr_ops(cmd, argp);
 		break;
 	case VIDIOC_MSM_BUF_MNGR_INIT:
@@ -724,6 +755,9 @@
 	case VIDIOC_MSM_BUF_MNGR_BUF_DONE32:
 		cmd = VIDIOC_MSM_BUF_MNGR_BUF_DONE;
 		break;
+	case VIDIOC_MSM_BUF_MNGR_BUF_ERROR32:
+		cmd = VIDIOC_MSM_BUF_MNGR_BUF_ERROR;
+		break;
 	case VIDIOC_MSM_BUF_MNGR_PUT_BUF32:
 		cmd = VIDIOC_MSM_BUF_MNGR_PUT_BUF;
 		break;
@@ -742,6 +776,7 @@
 	switch (cmd) {
 	case VIDIOC_MSM_BUF_MNGR_GET_BUF:
 	case VIDIOC_MSM_BUF_MNGR_BUF_DONE:
+	case VIDIOC_MSM_BUF_MNGR_BUF_ERROR:
 	case VIDIOC_MSM_BUF_MNGR_FLUSH:
 	case VIDIOC_MSM_BUF_MNGR_PUT_BUF: {
 		struct msm_buf_mngr_info32_t buf_info32;
diff --git a/drivers/media/platform/msm/camera_v2/msm_sd.h b/drivers/media/platform/msm/camera_v2/msm_sd.h
index f45c0d7..64cb785 100644
--- a/drivers/media/platform/msm/camera_v2/msm_sd.h
+++ b/drivers/media/platform/msm/camera_v2/msm_sd.h
@@ -81,6 +81,9 @@
 		unsigned int stream_id, uint32_t sequence, struct timeval *ts,
 		uint32_t reserved);
 	int (*flush_buf)(int session_id, unsigned int stream_id);
+	int (*buf_error)(struct vb2_v4l2_buffer *vb2_v4l2_buf, int session_id,
+		unsigned int stream_id, uint32_t sequence, struct timeval *ts,
+		uint32_t reserved);
 };
 
 #define MSM_SD_NOTIFY_GET_SD 0x00000001
diff --git a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
index 87e0172..6e528a6 100644
--- a/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
+++ b/drivers/media/platform/msm/camera_v2/msm_vb2/msm_vb2.c
@@ -461,6 +461,69 @@
 	return rc;
 }
 
+static int msm_vb2_buf_error(struct vb2_v4l2_buffer *vb, int session_id,
+				unsigned int stream_id, uint32_t sequence,
+				struct timeval *ts, uint32_t buf_type)
+{
+	unsigned long flags, rl_flags;
+	struct msm_vb2_buffer *msm_vb2;
+	struct msm_stream *stream;
+	struct msm_session *session;
+	struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
+	int rc = 0;
+
+	session = msm_get_session(session_id);
+	if (IS_ERR_OR_NULL(session))
+		return -EINVAL;
+
+	read_lock_irqsave(&session->stream_rwlock, rl_flags);
+
+	stream = msm_get_stream(session, stream_id);
+	if (IS_ERR_OR_NULL(stream)) {
+		read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&stream->stream_lock, flags);
+	if (vb) {
+		list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
+			vb2_v4l2_buf = &(msm_vb2->vb2_v4l2_buf);
+			if (vb2_v4l2_buf == vb)
+				break;
+		}
+		if (vb2_v4l2_buf != vb) {
+			pr_err("VB buffer is INVALID ses_id=%d, str_id=%d, vb=%pK\n",
+				    session_id, stream_id, vb);
+			spin_unlock_irqrestore(&stream->stream_lock, flags);
+			read_unlock_irqrestore(&session->stream_rwlock,
+				rl_flags);
+			return -EINVAL;
+		}
+		msm_vb2 =
+			container_of(vb2_v4l2_buf, struct msm_vb2_buffer,
+				vb2_v4l2_buf);
+		/* put buf before buf done */
+		if (msm_vb2->in_freeq) {
+			vb2_v4l2_buf->sequence = sequence;
+			vb2_v4l2_buf->timecode.type = buf_type;
+			vb2_v4l2_buf->vb2_buf.timestamp =
+				(ts->tv_sec * 1000000 + ts->tv_usec) * 1000;
+			vb2_buffer_done(&vb2_v4l2_buf->vb2_buf,
+				VB2_BUF_STATE_ERROR);
+			msm_vb2->in_freeq = 0;
+			rc = 0;
+		} else
+			rc = -EINVAL;
+	} else {
+		pr_err(" VB buffer is NULL for ses_id=%d, str_id=%d\n",
+			    session_id, stream_id);
+		rc = -EINVAL;
+	}
+	spin_unlock_irqrestore(&stream->stream_lock, flags);
+	read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
+	return rc;
+}
+
 long msm_vb2_return_buf_by_idx(int session_id, unsigned int stream_id,
 				uint32_t index)
 {
@@ -559,6 +622,7 @@
 	req->put_buf = msm_vb2_put_buf;
 	req->buf_done = msm_vb2_buf_done;
 	req->flush_buf = msm_vb2_flush_buf;
+	req->buf_error = msm_vb2_buf_error;
 	return 0;
 }
 
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
index 70bb3f2..1ad2f257 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c
@@ -1617,6 +1617,7 @@
 	case VIDIOC_MSM_BUF_MNGR_PUT_BUF:
 	case VIDIOC_MSM_BUF_MNGR_BUF_DONE:
 	case VIDIOC_MSM_BUF_MNGR_GET_BUF:
+	case VIDIOC_MSM_BUF_MNGR_BUF_ERROR:
 	default: {
 		struct msm_buf_mngr_info *buff_mgr_info =
 			(struct msm_buf_mngr_info *)arg;
@@ -3604,7 +3605,7 @@
 			break;
 		}
 		buff_mgr_info.frame_id = frame_info.frame_id;
-		rc = msm_cpp_buffer_ops(cpp_dev, VIDIOC_MSM_BUF_MNGR_BUF_DONE,
+		rc = msm_cpp_buffer_ops(cpp_dev, VIDIOC_MSM_BUF_MNGR_BUF_ERROR,
 			0x0, &buff_mgr_info);
 		if (rc < 0) {
 			pr_err("error in buf done\n");
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
index d044a50..9e99ba2 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
@@ -67,6 +67,8 @@
 					break;
 				}
 			}
+			if (j == num_vreg)
+				power_setting[i].seq_val = INVALID_VREG;
 			break;
 
 		case CAM_VIO:
@@ -86,6 +88,8 @@
 					break;
 				}
 			}
+			if (j == num_vreg)
+				power_setting[i].seq_val = INVALID_VREG;
 			break;
 
 		case CAM_VANA:
@@ -105,6 +109,8 @@
 					break;
 				}
 			}
+			if (j == num_vreg)
+				power_setting[i].seq_val = INVALID_VREG;
 			break;
 
 		case CAM_VAF:
@@ -124,6 +130,8 @@
 					break;
 				}
 			}
+			if (j == num_vreg)
+				power_setting[i].seq_val = INVALID_VREG;
 			break;
 
 		case CAM_V_CUSTOM1:
@@ -144,7 +152,9 @@
 					break;
 				}
 			}
-
+			if (j == num_vreg)
+				power_setting[i].seq_val = INVALID_VREG;
+			break;
 		case CAM_V_CUSTOM2:
 			for (j = 0; j < num_vreg; j++) {
 				if (!strcmp(cam_vreg[j].reg_name,
@@ -163,6 +173,8 @@
 					break;
 				}
 			}
+			if (j == num_vreg)
+				power_setting[i].seq_val = INVALID_VREG;
 			break;
 
 		default:
@@ -1489,6 +1501,9 @@
 				(int) power_setting->config_val);
 			break;
 		case SENSOR_VREG:
+			if (power_setting->seq_val == INVALID_VREG)
+				break;
+
 			if (power_setting->seq_val >= CAM_VREG_MAX) {
 				pr_err("%s vreg index %d >= max %d\n", __func__,
 					power_setting->seq_val,
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 fa5eb49..f3814e0 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -417,9 +417,6 @@
 			if (ret)
 				goto error_rot_sub;
 
-			/* reinitialize static vbif setting */
-			sde_mdp_init_vbif();
-
 			/* Active+Sleep */
 			msm_bus_scale_client_update_context(
 				mgr->data_bus.bus_hdl, false,
@@ -3329,6 +3326,7 @@
 	 */
 	pm_runtime_disable(dev);
 	pm_runtime_set_suspended(dev);
+	pm_runtime_set_active(dev);
 	pm_runtime_enable(dev);
 
 	sde_rot_mgr_lock(mgr);
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
index 916f978..f902135 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -568,6 +568,11 @@
 	if (__sde_rot_evtlog_dump_calc_range()) {
 		len = sde_rot_evtlog_dump_entry(evtlog_buf,
 				SDE_ROT_EVTLOG_BUF_MAX);
+		if (len < 0 || len > count) {
+			pr_err("len is more than the user buffer size\n");
+			return 0;
+		}
+
 		if (copy_to_user(buff, evtlog_buf, len))
 			return -EFAULT;
 		*ppos += len;
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 9f2ce5f..84efd3d 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -2714,6 +2714,9 @@
 			item->input.format, item->output.format,
 			entry->perf->config.frame_rate);
 
+	/* initialize static vbif setting */
+	sde_mdp_init_vbif();
+
 	if (!ctx->sbuf_mode && mdata->default_ot_rd_limit) {
 		struct sde_mdp_set_ot_params ot_params;
 
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index cef5396..97f5ca2 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -1501,6 +1501,8 @@
 		data_done.output_done.timestamp_hi = pkt->time_stamp_hi;
 		data_done.output_done.timestamp_lo = pkt->time_stamp_lo;
 		data_done.output_done.flags1 = pkt->flags;
+		data_done.output_done.input_tag = pkt->input_tag;
+		data_done.output_done.output_tag = pkt->output_tag;
 		data_done.output_done.mark_target = pkt->mark_target;
 		data_done.output_done.mark_data = pkt->mark_data;
 		data_done.output_done.stats = pkt->stats;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 0f74c7c..4a0aa58 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -340,6 +340,33 @@
 	return fw_out_qsize;
 }
 
+static inline int msm_dcvs_count_active_instances(struct msm_vidc_core *core,
+	enum session_type session_type)
+{
+	int active_instances = 0;
+	struct msm_vidc_inst *temp = NULL;
+
+	if (!core) {
+		dprintk(VIDC_ERR, "%s: Invalid args: %pK\n", __func__, core);
+		return -EINVAL;
+	}
+
+	/* DCVS condition is as following
+	 * Decoder DCVS : Only for ONE decoder session.
+	 * Encoder DCVS : Only for ONE encoder session + ONE decoder session
+	 */
+	mutex_lock(&core->lock);
+	list_for_each_entry(temp, &core->instances, list) {
+		if (temp->state >= MSM_VIDC_OPEN_DONE &&
+			temp->state < MSM_VIDC_STOP_DONE &&
+			(temp->session_type == session_type ||
+			 temp->session_type == MSM_VIDC_ENCODER))
+			active_instances++;
+	}
+	mutex_unlock(&core->lock);
+	return active_instances;
+}
+
 static int msm_dcvs_scale_clocks(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
@@ -347,6 +374,7 @@
 	int total_output_buf = 0;
 	int min_output_buf = 0;
 	int buffers_outside_fw = 0;
+	int instance_count = 0;
 	struct msm_vidc_core *core;
 	struct hal_buffer_requirements *output_buf_req;
 	struct clock_data *dcvs;
@@ -356,14 +384,17 @@
 		return -EINVAL;
 	}
 
-	if (!inst->clk_data.dcvs_mode) {
+	core = inst->core;
+	instance_count = msm_dcvs_count_active_instances(
+		inst->core, inst->session_type);
+
+	if (!inst->clk_data.dcvs_mode || instance_count > 1) {
 		dprintk(VIDC_DBG, "DCVS is not enabled\n");
-		return 0;
+		return -EINVAL;
 	}
 
 	dcvs = &inst->clk_data;
 
-	core = inst->core;
 	mutex_lock(&inst->lock);
 	buffers_outside_fw = get_bufs_outside_fw(inst);
 
@@ -496,8 +527,8 @@
 
 	if (freq < inst->clk_data.load_norm) {
 		dprintk(VIDC_DBG, "Calling DCVS now\n");
-		msm_dcvs_scale_clocks(inst);
-		freq = inst->clk_data.load;
+		if (!msm_dcvs_scale_clocks(inst))
+			freq = inst->clk_data.load;
 	}
 	dprintk(VIDC_PROF, "%s Inst %pK : Freq = %lu\n", __func__, inst, freq);
 
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_platform.c b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
index cb581b7..f80d9b0 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_platform.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
@@ -179,7 +179,7 @@
 	},
 	{
 		.key = "qcom,max-hw-load",
-		.value = 2009280,
+		.value = 2219400,
 	},
 	{
 		.key = "qcom,max-hq-mbs-per-frame",
diff --git a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
index ffcbdd9..ca9edc8 100644
--- a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
@@ -116,7 +116,7 @@
 	struct hfi_colour_space *colour_info;
 
 	 /* Initialize pic_struct to unknown as default */
-	//event_notify.pic_struct = MSM_VIDC_PIC_STRUCT_UNKNOWN;
+	event_notify.pic_struct = MSM_VIDC_PIC_STRUCT_UNKNOWN;
 
 	if (sizeof(struct hfi_msg_event_notify_packet) > pkt->size) {
 		dprintk(VIDC_ERR,
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
index 192f36f2..3d29ed4 100644
--- a/drivers/media/radio/Kconfig
+++ b/drivers/media/radio/Kconfig
@@ -499,3 +499,25 @@
 endif # V4L_RADIO_ISA_DRIVERS
 
 endif # RADIO_ADAPTERS
+
+config RADIO_IRIS
+        tristate "QTI IRIS FM support"
+        depends on VIDEO_V4L2
+        ---help---
+          Say Y here if you want to use the QTI FM chip (IRIS).
+          This FM chip uses SMD interface
+
+          To compile this driver as a module, choose M here: the
+          module will be called radio-iris.
+
+
+config RADIO_IRIS_TRANSPORT
+        tristate "QTI IRIS Transport"
+        depends on RADIO_IRIS
+        ---help---
+          Say Y here if you want to use the QTI FM chip (IRIS).
+          with SMD as transport.
+
+          To compile this driver as a module, choose M here: the
+          module will be called radio-iris-transport.
+
diff --git a/drivers/media/radio/Makefile b/drivers/media/radio/Makefile
index 120e791..efda39b 100644
--- a/drivers/media/radio/Makefile
+++ b/drivers/media/radio/Makefile
@@ -33,6 +33,8 @@
 obj-$(CONFIG_RADIO_WL128X) += wl128x/
 obj-$(CONFIG_RADIO_TEA575X) += tea575x.o
 obj-$(CONFIG_USB_RAREMONO) += radio-raremono.o
+obj-$(CONFIG_RADIO_IRIS) += radio-iris.o
+obj-$(CONFIG_RADIO_IRIS_TRANSPORT) += radio-iris-transport.o
 
 shark2-objs := radio-shark2.o radio-tea5777.o
 
diff --git a/drivers/media/radio/radio-iris-transport.c b/drivers/media/radio/radio-iris-transport.c
new file mode 100644
index 0000000..98afd19
--- /dev/null
+++ b/drivers/media/radio/radio-iris-transport.c
@@ -0,0 +1,274 @@
+/*
+ *  QTI's FM Shared Memory Transport Driver
+ *
+ *  FM HCI_SMD ( FM HCI Shared Memory Driver) is QTI's Shared memory driver
+ *  for the HCI protocol. This file is based on drivers/bluetooth/hci_vhci.c
+ *
+ *  Copyright (c) 2000-2001, 2011-2012, 2014-2015 The Linux Foundation.
+ *  All rights reserved.
+ *
+ *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
+ *  Copyright (C) 2004-2006  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2
+ *  as published by the Free Software Foundation
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/workqueue.h>
+#include <soc/qcom/smd.h>
+#include <media/radio-iris.h>
+#include <linux/uaccess.h>
+
+struct radio_data {
+	struct radio_hci_dev *hdev;
+	struct tasklet_struct   rx_task;
+	struct smd_channel  *fm_channel;
+};
+struct radio_data hs;
+DEFINE_MUTEX(fm_smd_enable);
+static int fmsmd_set;
+static bool chan_opened;
+static int hcismd_fm_set_enable(const char *val, struct kernel_param *kp);
+module_param_call(fmsmd_set, hcismd_fm_set_enable, NULL, &fmsmd_set, 0644);
+static struct work_struct *reset_worker;
+static void radio_hci_smd_deregister(void);
+static void radio_hci_smd_exit(void);
+
+static void radio_hci_smd_destruct(struct radio_hci_dev *hdev)
+{
+	radio_hci_unregister_dev();
+}
+
+
+static void radio_hci_smd_recv_event(unsigned long temp)
+{
+	int len;
+	int rc;
+	struct sk_buff *skb;
+	unsigned  char *buf;
+	struct radio_data *hsmd = &hs;
+
+	len = smd_read_avail(hsmd->fm_channel);
+
+	while (len) {
+		skb = alloc_skb(len, GFP_ATOMIC);
+		if (!skb) {
+			FMDERR("Memory not allocated for the socket\n");
+			return;
+		}
+
+		buf = kmalloc(len, GFP_ATOMIC);
+		if (!buf) {
+			kfree_skb(skb);
+			return;
+		}
+
+		rc = smd_read(hsmd->fm_channel, (void *)buf, len);
+
+		memcpy(skb_put(skb, len), buf, len);
+
+		skb_orphan(skb);
+		skb->dev = (struct net_device   *)hs.hdev;
+
+		rc = radio_hci_recv_frame(skb);
+
+		kfree(buf);
+		len = smd_read_avail(hsmd->fm_channel);
+	}
+}
+
+static int radio_hci_smd_send_frame(struct sk_buff *skb)
+{
+	int len = 0;
+
+	FMDBG("skb %pK\n", skb);
+
+	len = smd_write(hs.fm_channel, skb->data, skb->len);
+	if (len < skb->len) {
+		FMDERR("Failed to write Data %d\n", len);
+		kfree_skb(skb);
+		return -ENODEV;
+	}
+	kfree_skb(skb);
+	return 0;
+}
+
+
+static void send_disable_event(struct work_struct *worker)
+{
+	struct sk_buff *skb;
+	unsigned char buf[6] = { 0x0f, 0x04, 0x01, 0x02, 0x4c, 0x00 };
+	int len = sizeof(buf);
+
+	skb = alloc_skb(len, GFP_ATOMIC);
+	if (!skb) {
+		FMDERR("Memory not allocated for the socket\n");
+		kfree(worker);
+		return;
+	}
+
+	FMDBG("FM INSERT DISABLE Rx Event\n");
+
+	memcpy(skb_put(skb, len), buf, len);
+
+	skb_orphan(skb);
+	skb->dev = (struct net_device   *)hs.hdev;
+
+	radio_hci_recv_frame(skb);
+	kfree(worker);
+}
+
+static void radio_hci_smd_notify_cmd(void *data, unsigned int event)
+{
+	struct radio_hci_dev *hdev = (struct radio_hci_dev *)data;
+
+	FMDBG("data %p event %u\n", data, event);
+
+	if (!hdev) {
+		FMDERR("Frame for unknown HCI device (hdev=NULL)\n");
+		return;
+	}
+
+	switch (event) {
+	case SMD_EVENT_DATA:
+		tasklet_schedule(&hs.rx_task);
+		break;
+	case SMD_EVENT_OPEN:
+		break;
+	case SMD_EVENT_CLOSE:
+		reset_worker = kzalloc(sizeof(*reset_worker), GFP_ATOMIC);
+		if (reset_worker) {
+			INIT_WORK(reset_worker, send_disable_event);
+			schedule_work(reset_worker);
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+static int radio_hci_smd_register_dev(struct radio_data *hsmd)
+{
+	struct radio_hci_dev *hdev;
+	int rc;
+
+	FMDBG("hsmd: %pK\n", hsmd);
+
+	if (hsmd == NULL)
+		return -ENODEV;
+
+	hdev = kmalloc(sizeof(struct radio_hci_dev), GFP_KERNEL);
+	if (hdev == NULL)
+		return -ENODEV;
+
+	tasklet_init(&hsmd->rx_task, radio_hci_smd_recv_event,
+		(unsigned long) hsmd);
+	hdev->send  = radio_hci_smd_send_frame;
+	hdev->destruct = radio_hci_smd_destruct;
+	hdev->close_smd = radio_hci_smd_exit;
+
+	/* Open the SMD Channel and device and register the callback function */
+	rc = smd_named_open_on_edge("APPS_FM", SMD_APPS_WCNSS,
+		&hsmd->fm_channel, hdev, radio_hci_smd_notify_cmd);
+
+	if (rc < 0) {
+		FMDERR("Cannot open the command channel\n");
+		hsmd->hdev = NULL;
+		kfree(hdev);
+		return -ENODEV;
+	}
+
+	smd_disable_read_intr(hsmd->fm_channel);
+
+	if (radio_hci_register_dev(hdev) < 0) {
+		FMDERR("Can't register HCI device\n");
+		smd_close(hsmd->fm_channel);
+		hsmd->hdev = NULL;
+		kfree(hdev);
+		return -ENODEV;
+	}
+
+	hsmd->hdev = hdev;
+	return 0;
+}
+
+static void radio_hci_smd_deregister(void)
+{
+	radio_hci_unregister_dev();
+	kfree(hs.hdev);
+	hs.hdev = NULL;
+
+	smd_close(hs.fm_channel);
+	hs.fm_channel = 0;
+	fmsmd_set = 0;
+}
+
+static int radio_hci_smd_init(void)
+{
+	int ret;
+
+	if (chan_opened) {
+		FMDBG("Channel is already opened\n");
+		return 0;
+	}
+
+	/* this should be called with fm_smd_enable lock held */
+	ret = radio_hci_smd_register_dev(&hs);
+	if (ret < 0) {
+		FMDERR("Failed to register smd device\n");
+		chan_opened = false;
+		return ret;
+	}
+	chan_opened = true;
+	return ret;
+}
+
+static void radio_hci_smd_exit(void)
+{
+	if (!chan_opened) {
+		FMDBG("Channel already closed\n");
+		return;
+	}
+
+	/* this should be called with fm_smd_enable lock held */
+	radio_hci_smd_deregister();
+	chan_opened = false;
+}
+
+static int hcismd_fm_set_enable(const char *val, struct kernel_param *kp)
+{
+	int ret = 0;
+
+	mutex_lock(&fm_smd_enable);
+	ret = param_set_int(val, kp);
+	if (ret)
+		goto done;
+	switch (fmsmd_set) {
+
+	case 1:
+		radio_hci_smd_init();
+		break;
+	case 0:
+		radio_hci_smd_exit();
+		break;
+	default:
+		ret = -EFAULT;
+	}
+done:
+	mutex_unlock(&fm_smd_enable);
+	return ret;
+}
+MODULE_DESCRIPTION("FM SMD driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
new file mode 100644
index 0000000..7671049
--- /dev/null
+++ b/drivers/media/radio/radio-iris.c
@@ -0,0 +1,5646 @@
+/* Copyright (c) 2011-2015, The Linux Foundation. All rights reserved
+ *
+ * program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define DRIVER_NAME "radio-iris"
+#define DRIVER_CARD "QTI FM Radio Transceiver"
+#define DRIVER_DESC "Driver for QTI FM Radio Transceiver "
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/kfifo.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/version.h>
+#include <linux/videodev2.h>
+#include <linux/mutex.h>
+#include <linux/unistd.h>
+#include <linux/atomic.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/radio-iris.h>
+#include <asm/unaligned.h>
+
+static unsigned int rds_buf = 100;
+static int oda_agt;
+static int grp_mask;
+static int rt_plus_carrier = -1;
+static int ert_carrier = -1;
+static unsigned char ert_buf[256];
+static unsigned char ert_len;
+static unsigned char c_byt_pair_index;
+static char utf_8_flag;
+static char rt_ert_flag;
+static char formatting_dir;
+static unsigned char sig_blend = CTRL_ON;
+static DEFINE_MUTEX(iris_fm);
+
+module_param(rds_buf, uint, 0000);
+MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
+
+module_param(sig_blend, byte, 0200 | 0400 | 0040 | 0004);
+MODULE_PARM_DESC(sig_blend, "signal blending switch: 0:OFF 1:ON");
+
+static void radio_hci_cmd_task(unsigned long arg);
+static void radio_hci_rx_task(unsigned long arg);
+static struct video_device *video_get_dev(void);
+static DEFINE_RWLOCK(hci_task_lock);
+
+typedef int (*radio_hci_request_func)(struct radio_hci_dev *hdev,
+		int (*req)(struct radio_hci_dev *hdev, unsigned long param),
+		unsigned long param, unsigned long timeout_msecs);
+
+struct iris_device {
+	struct device *dev;
+	struct kfifo data_buf[IRIS_BUF_MAX];
+
+	int pending_xfrs[IRIS_XFR_MAX];
+	int xfr_bytes_left;
+	int xfr_in_progress;
+	struct completion sync_xfr_start;
+	int tune_req;
+	unsigned int mode;
+	bool is_fm_closing;
+
+	__u16 pi;
+	__u8 pty;
+	__u8 ps_repeatcount;
+	__u8 prev_trans_rds;
+	__u8 af_jump_bit;
+	struct video_device *videodev;
+	struct v4l2_device v4l2_dev;
+
+	struct mutex lock;
+	spinlock_t buf_lock[IRIS_BUF_MAX];
+	wait_queue_head_t event_queue;
+	wait_queue_head_t read_queue;
+
+	struct radio_hci_dev *fm_hdev;
+
+	struct v4l2_capability g_cap;
+	struct v4l2_control *g_ctl;
+
+	struct hci_fm_mute_mode_req mute_mode;
+	struct hci_fm_stereo_mode_req stereo_mode;
+	struct hci_fm_station_rsp fm_st_rsp;
+	struct hci_fm_search_station_req srch_st;
+	struct hci_fm_search_rds_station_req srch_rds;
+	struct hci_fm_search_station_list_req srch_st_list;
+	struct hci_fm_recv_conf_req recv_conf;
+	struct hci_fm_trans_conf_req_struct trans_conf;
+	struct hci_fm_rds_grp_req rds_grp;
+	unsigned char g_search_mode;
+	unsigned char power_mode;
+	int search_on;
+	unsigned int tone_freq;
+	unsigned char spur_table_size;
+	unsigned char g_scan_time;
+	unsigned int g_antenna;
+	unsigned int g_rds_grp_proc_ps;
+	unsigned char event_mask;
+	enum iris_region_t region;
+	struct hci_fm_dbg_param_rsp st_dbg_param;
+	struct hci_ev_srch_list_compl srch_st_result;
+	struct hci_fm_riva_poke   riva_data_req;
+	struct hci_fm_ssbi_req    ssbi_data_accs;
+	struct hci_fm_ssbi_peek   ssbi_peek_reg;
+	struct hci_fm_sig_threshold_rsp sig_th;
+	struct hci_fm_ch_det_threshold ch_det_threshold;
+	struct hci_fm_data_rd_rsp default_data;
+	struct hci_fm_spur_data spur_data;
+	unsigned char is_station_valid;
+	struct hci_fm_blend_table blend_tbl;
+};
+
+static struct video_device *priv_videodev;
+static int iris_do_calibration(struct iris_device *radio);
+static void hci_buff_ert(struct iris_device *radio,
+		struct rds_grp_data *rds_buf);
+static void hci_ev_rt_plus(struct iris_device *radio,
+		struct rds_grp_data rds_buf);
+static void hci_ev_ert(struct iris_device *radio);
+static int update_spur_table(struct iris_device *radio);
+static int initialise_recv(struct iris_device *radio);
+static int initialise_trans(struct iris_device *radio);
+static int is_enable_rx_possible(struct iris_device *radio);
+static int is_enable_tx_possible(struct iris_device *radio);
+
+static struct v4l2_queryctrl iris_v4l2_queryctrl[] = {
+	{
+	.id	= V4L2_CID_AUDIO_VOLUME,
+	.type	= V4L2_CTRL_TYPE_INTEGER,
+	.name	= "Volume",
+	.minimum	= 0,
+	.maximum	= 15,
+	.step	=	1,
+	.default_value	=	15,
+	},
+	{
+	.id	=	V4L2_CID_AUDIO_BALANCE,
+	.flags	= V4L2_CTRL_FLAG_DISABLED,
+	},
+	{
+	.id	=	V4L2_CID_AUDIO_BASS,
+	.flags	=	V4L2_CTRL_FLAG_DISABLED,
+	},
+	{
+	.id	=	V4L2_CID_AUDIO_TREBLE,
+	.flags	=	V4L2_CTRL_FLAG_DISABLED,
+	},
+	{
+	.id	=	V4L2_CID_AUDIO_MUTE,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"Mute",
+	.minimum	=	0,
+	.maximum	=	1,
+	.step	=	1,
+	.default_value	= 1,
+	},
+	{
+	.id	=	V4L2_CID_AUDIO_LOUDNESS,
+	.flags	=	V4L2_CTRL_FLAG_DISABLED,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_SRCHMODE,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Search mode",
+	.minimum	=	0,
+	.maximum	= 7,
+	.step	= 1,
+	.default_value	= 0,
+	},
+	{
+	.id	= V4L2_CID_PRIVATE_IRIS_SCANDWELL,
+	.type	= V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Search dwell time",
+	.minimum	= 0,
+	.maximum	= 7,
+	.step	= 1,
+	.default_value	= 0,
+	},
+	{
+	.id	= V4L2_CID_PRIVATE_IRIS_SRCHON,
+	.type	= V4L2_CTRL_TYPE_BOOLEAN,
+	.name	= "Search on/off",
+	.minimum	= 0,
+	.maximum	= 1,
+	.step	= 1,
+	.default_value	= 1,
+
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_STATE,
+	.type	= V4L2_CTRL_TYPE_INTEGER,
+	.name	= "radio 0ff/rx/tx/reset",
+	.minimum	= 0,
+	.maximum	= 3,
+	.step	= 1,
+	.default_value	=	1,
+
+	},
+	{
+	.id	= V4L2_CID_PRIVATE_IRIS_REGION,
+	.type	= V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"radio standard",
+	.minimum	=	0,
+	.maximum	=	2,
+	.step	=	1,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_SIGNAL_TH,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Signal Threshold",
+	.minimum	=	0x80,
+	.maximum	=	0x7F,
+	.step	=	1,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_SRCH_PTY,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Search PTY",
+	.minimum	=	0,
+	.maximum	=	31,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_SRCH_PI,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Search PI",
+	.minimum	=	0,
+	.maximum	=	0xFF,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_SRCH_CNT,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Preset num",
+	.minimum	=	0,
+	.maximum	=	12,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_EMPHASIS,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"Emphasis",
+	.minimum	=	0,
+	.maximum	=	1,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_RDS_STD,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"RDS standard",
+	.minimum	=	0,
+	.maximum	=	1,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_SPACING,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Channel spacing",
+	.minimum	=	0,
+	.maximum	=	2,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_RDSON,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"RDS on/off",
+	.minimum	=	0,
+	.maximum	=	1,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_RDSGROUP_MASK,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"RDS group mask",
+	.minimum	=	0,
+	.maximum	=	0xFFFFFFFF,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_RDSGROUP_PROC,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"RDS processing",
+	.minimum	=	0,
+	.maximum	=	0xFF,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_RDSD_BUF,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"RDS data groups to buffer",
+	.minimum	=	1,
+	.maximum	=	21,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_PSALL,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"pass all ps strings",
+	.minimum	=	0,
+	.maximum	=	1,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_LP_MODE,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"Low power mode",
+	.minimum	=	0,
+	.maximum	=	1,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_ANTENNA,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"headset/internal",
+	.minimum	=	0,
+	.maximum	=	1,
+	.default_value	=	0,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_TX_SETPSREPEATCOUNT,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Set PS REPEATCOUNT",
+	.minimum	=	0,
+	.maximum	=	15,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_STOP_RDS_TX_PS_NAME,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"Stop PS NAME",
+	.minimum	=	0,
+	.maximum	=	1,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_STOP_RDS_TX_RT,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"Stop RT",
+	.minimum	=	0,
+	.maximum	=	1,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_SOFT_MUTE,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"Soft Mute",
+	.minimum	=	0,
+	.maximum	=	1,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_ADDR,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"Riva addr",
+	.minimum	=	0x3180000,
+	.maximum	=	0x31E0004,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_LEN,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Data len",
+	.minimum	=	0,
+	.maximum	=	0xFF,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_RIVA_PEEK,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"Riva peek",
+	.minimum	=	0,
+	.maximum	=	1,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_RIVA_POKE,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Riva poke",
+	.minimum	=	0x3180000,
+	.maximum	=	0x31E0004,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_SSBI_ACCS_ADDR,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Ssbi addr",
+	.minimum	=	0x280,
+	.maximum	=	0x37F,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_SSBI_PEEK,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Ssbi peek",
+	.minimum	=	0,
+	.maximum	=	0x37F,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_SSBI_POKE,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"ssbi poke",
+	.minimum	=	0x01,
+	.maximum	=	0xFF,
+	},
+	{
+	.id =	 V4L2_CID_PRIVATE_IRIS_HLSI,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"set hlsi",
+	.minimum	=	0,
+	.maximum	=	2,
+	},
+	{
+	.id =	 V4L2_CID_PRIVATE_IRIS_RDS_GRP_COUNTERS,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"RDS grp",
+	.minimum	=	0,
+	.maximum	=	1,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_SET_NOTCH_FILTER,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Notch filter",
+	.minimum	=	0,
+	.maximum	=	2,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_READ_DEFAULT,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Read default",
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_WRITE_DEFAULT,
+	.type	=	V4L2_CTRL_TYPE_INTEGER,
+	.name	=	"Write default",
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"SET Calibration",
+	.minimum	=	0,
+	.maximum	=	1,
+	},
+	{
+	.id	=	V4L2_CID_PRIVATE_IRIS_DO_CALIBRATION,
+	.type	=	V4L2_CTRL_TYPE_BOOLEAN,
+	.name	=	"SET Calibration",
+	.minimum	=	0,
+	.maximum	=	1,
+	},
+	{
+	.id     =       V4L2_CID_PRIVATE_IRIS_GET_SINR,
+	.type   =       V4L2_CTRL_TYPE_INTEGER,
+	.name   =       "GET SINR",
+	.minimum        =       -128,
+	.maximum        =       127,
+	},
+	{
+	.id     =       V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD,
+	.type   =       V4L2_CTRL_TYPE_INTEGER,
+	.name   =       "Intf High Threshold",
+	.minimum        =       0,
+	.maximum        =       0xFF,
+	.default_value  =       0,
+	},
+	{
+	.id     =       V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD,
+	.type   =       V4L2_CTRL_TYPE_INTEGER,
+	.name   =       "Intf low Threshold",
+	.minimum        =       0,
+	.maximum        =       0xFF,
+	.default_value  =       0,
+	},
+	{
+	.id     =       V4L2_CID_PRIVATE_SINR_THRESHOLD,
+	.type   =       V4L2_CTRL_TYPE_INTEGER,
+	.name   =       "SINR Threshold",
+	.minimum        =       -128,
+	.maximum        =       127,
+	.default_value  =       0,
+	},
+	{
+	.id     =       V4L2_CID_PRIVATE_SINR_SAMPLES,
+	.type   =       V4L2_CTRL_TYPE_INTEGER,
+	.name   =       "SINR samples",
+	.minimum        =       1,
+	.maximum        =       0xFF,
+	.default_value  =       0,
+	},
+};
+
+static void iris_q_event(struct iris_device *radio,
+				enum iris_evt_t event)
+{
+	struct kfifo *data_b;
+	unsigned char evt = event;
+
+	FMDBG("radio %pK event %d", radio, event);
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+
+	data_b = &radio->data_buf[IRIS_BUF_EVENTS];
+	if (kfifo_in_locked(data_b, &evt, 1, &radio->buf_lock[IRIS_BUF_EVENTS]))
+		wake_up_interruptible(&radio->event_queue);
+}
+
+static int hci_send_frame(struct sk_buff *skb)
+{
+	struct radio_hci_dev *hdev;
+
+	FMDBG("skb %pK", skb);
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return -EINVAL;
+	}
+	hdev = (struct radio_hci_dev *) skb->dev;
+	if (unlikely(!hdev)) {
+		kfree_skb(skb);
+		return -ENODEV;
+	}
+
+	__net_timestamp(skb);
+
+	skb_orphan(skb);
+	return hdev->send(skb);
+}
+
+static void radio_hci_cmd_task(unsigned long arg)
+{
+	struct radio_hci_dev *hdev = (struct radio_hci_dev *) arg;
+	struct sk_buff *skb;
+
+	FMDBG("hdev %pK", hdev);
+
+	if (unlikely(hdev == NULL)) {
+		FMDERR("%s, HCI Device is null\n", __func__);
+		return;
+	}
+	if (!(atomic_read(&hdev->cmd_cnt))
+		&& time_after(jiffies, hdev->cmd_last_tx + HZ)) {
+		FMDERR("%s command tx timeout\n", hdev->name);
+		atomic_set(&hdev->cmd_cnt, 1);
+	}
+
+	skb = skb_dequeue(&hdev->cmd_q);
+	if (atomic_read(&hdev->cmd_cnt) && skb) {
+		kfree_skb(hdev->sent_cmd);
+		hdev->sent_cmd = skb_clone(skb, GFP_ATOMIC);
+		if (hdev->sent_cmd) {
+			atomic_dec(&hdev->cmd_cnt);
+			hci_send_frame(skb);
+			hdev->cmd_last_tx = jiffies;
+		} else {
+			skb_queue_head(&hdev->cmd_q, skb);
+			tasklet_schedule(&hdev->cmd_task);
+		}
+	}
+
+}
+
+static void radio_hci_rx_task(unsigned long arg)
+{
+	struct radio_hci_dev *hdev = (struct radio_hci_dev *) arg;
+	struct sk_buff *skb;
+
+	FMDBG("hdev %pK", hdev);
+
+	if (unlikely(hdev == NULL)) {
+		FMDERR("%s, HCI Device is null\n", __func__);
+		return;
+	}
+	read_lock(&hci_task_lock);
+
+	skb = skb_dequeue(&hdev->rx_q);
+	radio_hci_event_packet(hdev, skb);
+
+	read_unlock(&hci_task_lock);
+}
+
+int radio_hci_register_dev(struct radio_hci_dev *hdev)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+
+	FMDBG("radio %pK", radio);
+
+	if (!radio) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+
+	if (!hdev) {
+		FMDERR("hdev is null\n");
+		return -EINVAL;
+	}
+
+	hdev->flags = 0;
+
+	tasklet_init(&hdev->cmd_task, radio_hci_cmd_task, (unsigned long)
+		hdev);
+	tasklet_init(&hdev->rx_task, radio_hci_rx_task, (unsigned long)
+		hdev);
+
+	init_waitqueue_head(&hdev->req_wait_q);
+
+	skb_queue_head_init(&hdev->rx_q);
+	skb_queue_head_init(&hdev->cmd_q);
+	skb_queue_head_init(&hdev->raw_q);
+
+
+	radio->fm_hdev = hdev;
+
+	return 0;
+}
+EXPORT_SYMBOL(radio_hci_register_dev);
+
+int radio_hci_unregister_dev(void)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	struct radio_hci_dev *hdev = NULL;
+
+	if (!radio) {
+		FMDERR("radio is null\n");
+		return -EINVAL;
+	}
+	hdev = radio->fm_hdev;
+	if (!hdev) {
+		FMDERR("hdev is null\n");
+		return -EINVAL;
+	}
+
+	tasklet_kill(&hdev->rx_task);
+	tasklet_kill(&hdev->cmd_task);
+	skb_queue_purge(&hdev->rx_q);
+	skb_queue_purge(&hdev->cmd_q);
+	skb_queue_purge(&hdev->raw_q);
+
+	radio->fm_hdev = NULL;
+	return 0;
+}
+EXPORT_SYMBOL(radio_hci_unregister_dev);
+
+int radio_hci_recv_frame(struct sk_buff *skb)
+{
+	struct radio_hci_dev *hdev;
+
+	FMDBG("hdev %pK", skb);
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return -EINVAL;
+	}
+	hdev = (struct radio_hci_dev *) skb->dev;
+	if (unlikely(!hdev)) {
+		FMDERR("%s hdev is null while receiving frame\n", hdev->name);
+		kfree_skb(skb);
+		return -ENXIO;
+	}
+
+	__net_timestamp(skb);
+
+	radio_hci_event_packet(hdev, skb);
+	kfree_skb(skb);
+	return 0;
+}
+EXPORT_SYMBOL(radio_hci_recv_frame);
+
+int radio_hci_send_cmd(struct radio_hci_dev *hdev, __u16 opcode, __u32 plen,
+		void *param)
+{
+	int len = RADIO_HCI_COMMAND_HDR_SIZE + plen;
+	struct radio_hci_command_hdr *hdr;
+	struct sk_buff *skb;
+	int ret = 0;
+
+	FMDBG("hdev %pK opcode %u len %u", hdev, opcode, plen);
+
+	if (unlikely(hdev == NULL)) {
+		FMDERR("%s, hci device is null\n", __func__);
+		return -EINVAL;
+	}
+	skb = alloc_skb(len, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	hdr = (struct radio_hci_command_hdr *) skb_put(skb,
+		RADIO_HCI_COMMAND_HDR_SIZE);
+	hdr->opcode = cpu_to_le16(opcode);
+	hdr->plen   = plen;
+
+	if (plen)
+		memcpy(skb_put(skb, plen), param, plen);
+
+	skb->dev = (void *) hdev;
+
+	ret = hci_send_frame(skb);
+
+	return ret;
+}
+EXPORT_SYMBOL(radio_hci_send_cmd);
+
+static int hci_fm_enable_recv_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_ENABLE_RECV_REQ);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_fm_tone_generator(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	__u16 opcode = 0;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
+		HCI_FM_SET_INTERNAL_TONE_GENRATOR);
+	return radio_hci_send_cmd(hdev, opcode,
+			sizeof(radio->tone_freq), &radio->tone_freq);
+}
+
+static int hci_fm_enable_trans_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_TRANS_CTRL_CMD_REQ,
+		HCI_OCF_FM_ENABLE_TRANS_REQ);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_fm_disable_recv_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_DISABLE_RECV_REQ);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_fm_disable_trans_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_TRANS_CTRL_CMD_REQ,
+		HCI_OCF_FM_DISABLE_TRANS_REQ);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_get_fm_recv_conf_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_GET_RECV_CONF_REQ);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_get_fm_trans_conf_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_TRANS_CTRL_CMD_REQ,
+		HCI_OCF_FM_GET_TRANS_CONF_REQ);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+static int hci_set_fm_recv_conf_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+
+	struct hci_fm_recv_conf_req *recv_conf_req =
+		(struct hci_fm_recv_conf_req *) param;
+
+	if (recv_conf_req == NULL) {
+		FMDERR("%s, recv conf is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_SET_RECV_CONF_REQ);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*recv_conf_req)),
+		recv_conf_req);
+}
+
+static int hci_set_fm_trans_conf_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+
+	struct hci_fm_trans_conf_req_struct *trans_conf_req =
+		(struct hci_fm_trans_conf_req_struct *) param;
+
+	if (trans_conf_req == NULL) {
+		FMDERR("%s, tx conf is null\n", __func__);
+		return -EINVAL;
+	}
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_TRANS_CTRL_CMD_REQ,
+		HCI_OCF_FM_SET_TRANS_CONF_REQ);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*trans_conf_req)),
+		trans_conf_req);
+}
+
+static int hci_fm_get_station_param_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_GET_STATION_PARAM_REQ);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_set_fm_mute_mode_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+	struct hci_fm_mute_mode_req *mute_mode_req =
+		(struct hci_fm_mute_mode_req *) param;
+
+	if (mute_mode_req == NULL) {
+		FMDERR("%s, mute mode is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_SET_MUTE_MODE_REQ);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*mute_mode_req)),
+		mute_mode_req);
+}
+
+
+static int hci_trans_ps_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+	struct hci_fm_tx_ps *tx_ps_req =
+		(struct hci_fm_tx_ps *) param;
+
+	if (tx_ps_req == NULL) {
+		FMDERR("%s, tx ps req is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_TRANS_CTRL_CMD_REQ,
+		HCI_OCF_FM_RDS_PS_REQ);
+
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*tx_ps_req)),
+		tx_ps_req);
+}
+
+static int hci_trans_rt_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+	struct hci_fm_tx_rt *tx_rt_req =
+		(struct hci_fm_tx_rt *) param;
+
+	if (tx_rt_req == NULL) {
+		FMDERR("%s, tx rt req is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_TRANS_CTRL_CMD_REQ,
+		HCI_OCF_FM_RDS_RT_REQ);
+
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*tx_rt_req)),
+		tx_rt_req);
+}
+
+static int hci_set_fm_stereo_mode_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+	struct hci_fm_stereo_mode_req *stereo_mode_req =
+		(struct hci_fm_stereo_mode_req *) param;
+
+	if (stereo_mode_req == NULL) {
+		FMDERR("%s, stere mode req is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_SET_STEREO_MODE_REQ);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*stereo_mode_req)),
+		stereo_mode_req);
+}
+
+static int hci_fm_set_antenna_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+
+	__u8 antenna = param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_SET_ANTENNA);
+	return radio_hci_send_cmd(hdev, opcode, sizeof(antenna), &antenna);
+}
+
+static int hci_fm_set_sig_threshold_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+
+	__u8 sig_threshold = param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_SET_SIGNAL_THRESHOLD);
+	return radio_hci_send_cmd(hdev, opcode, sizeof(sig_threshold),
+		&sig_threshold);
+}
+
+static int hci_fm_set_event_mask(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	u16 opcode = 0;
+	u8 event_mask = param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_SET_EVENT_MASK);
+	return radio_hci_send_cmd(hdev, opcode, sizeof(event_mask),
+		&event_mask);
+}
+static int hci_fm_get_sig_threshold_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_GET_SIGNAL_THRESHOLD);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_fm_get_program_service_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_GET_PROGRAM_SERVICE_REQ);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_fm_get_radio_text_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_GET_RADIO_TEXT_REQ);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_fm_get_af_list_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_GET_AF_LIST_REQ);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_fm_search_stations_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+	struct hci_fm_search_station_req *srch_stations =
+		(struct hci_fm_search_station_req *) param;
+
+	if (srch_stations == NULL) {
+		FMDERR("%s, search station param is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_SEARCH_STATIONS);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*srch_stations)),
+		srch_stations);
+}
+
+static int hci_fm_srch_rds_stations_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+	struct hci_fm_search_rds_station_req *srch_stations =
+		(struct hci_fm_search_rds_station_req *) param;
+
+	if (srch_stations == NULL) {
+		FMDERR("%s, rds stations param is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_SEARCH_RDS_STATIONS);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*srch_stations)),
+		srch_stations);
+}
+
+static int hci_fm_srch_station_list_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+	struct hci_fm_search_station_list_req *srch_list =
+		(struct hci_fm_search_station_list_req *) param;
+
+	if (srch_list == NULL) {
+		FMDERR("%s, search list param is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_SEARCH_STATIONS_LIST);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*srch_list)),
+		srch_list);
+}
+
+static int hci_fm_cancel_search_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_CANCEL_SEARCH);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_fm_rds_grp_mask_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	 __u16 opcode = 0;
+
+	struct hci_fm_rds_grp_req *fm_grp_mask =
+		(struct hci_fm_rds_grp_req *)param;
+
+	if (fm_grp_mask == NULL) {
+		FMDERR("%s, grp mask param is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_RDS_GRP);
+	return radio_hci_send_cmd(hdev, opcode, sizeof(*fm_grp_mask),
+		fm_grp_mask);
+}
+
+static int hci_fm_rds_grp_process_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+
+	__u32 fm_grps_process = param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_RDS_GRP_PROCESS);
+	return radio_hci_send_cmd(hdev, opcode, sizeof(fm_grps_process),
+		&fm_grps_process);
+}
+
+static int hci_fm_tune_station_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+
+	__u32 tune_freq = param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
+		HCI_OCF_FM_TUNE_STATION_REQ);
+	return radio_hci_send_cmd(hdev, opcode, sizeof(tune_freq), &tune_freq);
+}
+
+static int hci_def_data_read_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+	struct hci_fm_def_data_rd_req *def_data_rd =
+		(struct hci_fm_def_data_rd_req *) param;
+
+	if (def_data_rd == NULL) {
+		FMDERR("%s, def data read param is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
+		HCI_OCF_FM_DEFAULT_DATA_READ);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*def_data_rd)),
+	def_data_rd);
+}
+
+static int hci_def_data_write_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+	struct hci_fm_def_data_wr_req *def_data_wr =
+		(struct hci_fm_def_data_wr_req *) param;
+
+	if (def_data_wr == NULL) {
+		FMDERR("%s, def data write param is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
+		HCI_OCF_FM_DEFAULT_DATA_WRITE);
+
+	return radio_hci_send_cmd(hdev, opcode, (def_data_wr->length+2),
+	def_data_wr);
+}
+
+static int hci_set_notch_filter_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+	__u8 notch_filter_val = param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_EN_NOTCH_CTRL);
+	return radio_hci_send_cmd(hdev, opcode, sizeof(notch_filter_val),
+	&notch_filter_val);
+}
+
+static int hci_fm_reset_req(struct radio_hci_dev *hdev, unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
+		HCI_OCF_FM_RESET);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_fm_get_feature_lists_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
+		HCI_OCF_FM_GET_FEATURE_LIST);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_fm_do_calibration_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+
+	__u8 mode = param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
+		HCI_OCF_FM_DO_CALIBRATION);
+	return radio_hci_send_cmd(hdev, opcode, sizeof(mode), &mode);
+}
+
+static int hci_read_grp_counters_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+	__u8 reset_counters = param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_STATUS_PARAMETERS_CMD_REQ,
+		HCI_OCF_FM_READ_GRP_COUNTERS);
+	return radio_hci_send_cmd(hdev, opcode, sizeof(reset_counters),
+		&reset_counters);
+}
+
+static int hci_peek_data_req(struct radio_hci_dev *hdev, unsigned long param)
+{
+	__u16 opcode = 0;
+	struct hci_fm_riva_data *peek_data = (struct hci_fm_riva_data *)param;
+
+	if (peek_data == NULL) {
+		FMDERR("%s, peek data param is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
+		HCI_OCF_FM_PEEK_DATA);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*peek_data)),
+	peek_data);
+}
+
+static int hci_poke_data_req(struct radio_hci_dev *hdev, unsigned long param)
+{
+	__u16 opcode = 0;
+	struct hci_fm_riva_poke *poke_data = (struct hci_fm_riva_poke *) param;
+
+	if (poke_data == NULL) {
+		FMDERR("%s, poke data param is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
+		HCI_OCF_FM_POKE_DATA);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*poke_data)),
+	poke_data);
+}
+
+static int hci_ssbi_peek_reg_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+	struct hci_fm_ssbi_peek *ssbi_peek = (struct hci_fm_ssbi_peek *) param;
+
+	if (ssbi_peek == NULL) {
+		FMDERR("%s, ssbi peek param is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
+		HCI_OCF_FM_SSBI_PEEK_REG);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*ssbi_peek)),
+	ssbi_peek);
+}
+
+static int hci_ssbi_poke_reg_req(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	__u16 opcode = 0;
+	struct hci_fm_ssbi_req *ssbi_poke = (struct hci_fm_ssbi_req *) param;
+
+	if (ssbi_poke == NULL) {
+		FMDERR("%s, ssbi poke param is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
+		HCI_OCF_FM_SSBI_POKE_REG);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*ssbi_poke)),
+	ssbi_poke);
+}
+
+static int hci_fm_get_station_dbg_param_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	__u16 opcode = 0;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_DIAGNOSTIC_CMD_REQ,
+		HCI_OCF_FM_STATION_DBG_PARAM);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_fm_set_ch_det_th(struct radio_hci_dev *hdev,
+	unsigned long param)
+{
+	struct hci_fm_ch_det_threshold *ch_det_th =
+			 (struct hci_fm_ch_det_threshold *) param;
+	u16 opcode;
+
+	if (ch_det_th == NULL) {
+		FMDERR("%s, channel det thrshld is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+		HCI_OCF_FM_SET_CH_DET_THRESHOLD);
+	return radio_hci_send_cmd(hdev, opcode, sizeof((*ch_det_th)),
+		ch_det_th);
+}
+
+static int hci_fm_get_ch_det_th(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	u16 opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+			HCI_OCF_FM_GET_CH_DET_THRESHOLD);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_fm_get_blend_tbl(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	u16 opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+				HCI_OCF_FM_GET_BLND_TBL);
+	return radio_hci_send_cmd(hdev, opcode, 0, NULL);
+}
+
+static int hci_fm_set_blend_tbl(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	struct hci_fm_blend_table *blnd_tbl =
+			 (struct hci_fm_blend_table *) param;
+	u16 opcode;
+
+	if (blnd_tbl == NULL) {
+		FMDERR("%s, blend tbl is null\n", __func__);
+		return -EINVAL;
+	}
+	opcode = hci_opcode_pack(HCI_OGF_FM_RECV_CTRL_CMD_REQ,
+			HCI_OCF_FM_SET_BLND_TBL);
+	return radio_hci_send_cmd(hdev, opcode,
+			sizeof(struct hci_fm_blend_table), blnd_tbl);
+}
+
+static int radio_hci_err(__u32 code)
+{
+	switch (code) {
+	case 0:
+		return 0;
+	case 0x01:
+		return -EBADRQC;
+	case 0x02:
+		return -ENOTCONN;
+	case 0x03:
+		return -EIO;
+	case 0x07:
+		return -ENOMEM;
+	case 0x0c:
+		return -EBUSY;
+	case 0x11:
+		return -EOPNOTSUPP;
+	case 0x12:
+		return -EINVAL;
+	default:
+		return -EINVAL;
+	}
+}
+
+static int __radio_hci_request(struct radio_hci_dev *hdev,
+		int (*req)(struct radio_hci_dev *hdev,
+			unsigned long param),
+			unsigned long param, unsigned long timeout_msecs,
+			bool interruptible)
+{
+	int err = 0;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (unlikely(hdev == NULL)) {
+		FMDERR("%s, hci dev is null\n", __func__);
+		return -EINVAL;
+	}
+
+	mutex_lock(&iris_fm);
+	hdev->req_status = HCI_REQ_PEND;
+
+	add_wait_queue(&hdev->req_wait_q, &wait);
+	if (interruptible)
+		set_current_state(TASK_INTERRUPTIBLE);
+	else
+		set_current_state(TASK_UNINTERRUPTIBLE);
+
+	err = req(hdev, param);
+
+	schedule_timeout(msecs_to_jiffies(timeout_msecs));
+
+	remove_wait_queue(&hdev->req_wait_q, &wait);
+
+	if (interruptible && signal_pending(current)) {
+		mutex_unlock(&iris_fm);
+		return -EINTR;
+	}
+
+	switch (hdev->req_status) {
+	case HCI_REQ_DONE:
+	case HCI_REQ_STATUS:
+		err = radio_hci_err(hdev->req_result);
+		break;
+	default:
+		err = -ETIMEDOUT;
+		break;
+	}
+
+	hdev->req_status = hdev->req_result = 0;
+	mutex_unlock(&iris_fm);
+
+	return err;
+}
+
+static inline int radio_hci_request_interruptible(struct radio_hci_dev *hdev,
+		int (*req)(struct
+		radio_hci_dev * hdev, unsigned long param),
+		unsigned long param, unsigned long timeout_msecs)
+{
+	int ret = 0;
+
+	ret = __radio_hci_request(hdev, req, param, timeout_msecs, true);
+
+	return ret;
+}
+
+static inline int radio_hci_request_uninterruptible(struct radio_hci_dev *hdev,
+		int (*req)(struct
+		radio_hci_dev * hdev, unsigned long param),
+		unsigned long param, unsigned long timeout_msecs)
+{
+	int ret = 0;
+
+	ret = __radio_hci_request(hdev, req, param, timeout_msecs, false);
+
+	return ret;
+}
+
+static inline int radio_hci_request(struct radio_hci_dev *hdev,
+		int (*req)(struct
+		radio_hci_dev * hdev, unsigned long param),
+		unsigned long param, unsigned long timeout_msecs)
+{
+	return radio_hci_request_interruptible(hdev, req, param, timeout_msecs);
+}
+
+static inline int hci_conf_event_mask(__u8 *arg,
+		struct radio_hci_dev *hdev)
+{
+	u8 event_mask;
+
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	event_mask = *arg;
+	return  radio_hci_request(hdev, hci_fm_set_event_mask,
+				event_mask, RADIO_HCI_TIMEOUT);
+}
+static int hci_set_fm_recv_conf(struct hci_fm_recv_conf_req *arg,
+		struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_recv_conf_req *set_recv_conf = arg;
+
+	ret = radio_hci_request(hdev, hci_set_fm_recv_conf_req, (unsigned
+		long)set_recv_conf, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_set_fm_trans_conf(struct hci_fm_trans_conf_req_struct *arg,
+		struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_trans_conf_req_struct *set_trans_conf = arg;
+
+	ret = radio_hci_request(hdev, hci_set_fm_trans_conf_req, (unsigned
+		long)set_trans_conf, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_fm_tune_station(__u32 *arg, struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	__u32 tune_freq;
+
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	tune_freq = *arg;
+	ret = radio_hci_request(hdev, hci_fm_tune_station_req, tune_freq,
+		RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_set_fm_mute_mode(struct hci_fm_mute_mode_req *arg,
+	struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_mute_mode_req *set_mute_conf = arg;
+
+	ret = radio_hci_request(hdev, hci_set_fm_mute_mode_req, (unsigned
+		long)set_mute_conf, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_set_fm_stereo_mode(struct hci_fm_stereo_mode_req *arg,
+	struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_stereo_mode_req *set_stereo_conf = arg;
+
+	ret = radio_hci_request(hdev, hci_set_fm_stereo_mode_req, (unsigned
+		long)set_stereo_conf, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_fm_set_antenna(__u8 *arg, struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	__u8 antenna;
+
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	antenna = *arg;
+	ret = radio_hci_request(hdev, hci_fm_set_antenna_req, antenna,
+		RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_fm_set_signal_threshold(__u8 *arg,
+	struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	__u8 sig_threshold;
+
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	sig_threshold = *arg;
+	ret = radio_hci_request(hdev, hci_fm_set_sig_threshold_req,
+		sig_threshold, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_fm_search_stations(struct hci_fm_search_station_req *arg,
+	struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_search_station_req *srch_stations = arg;
+
+	ret = radio_hci_request(hdev, hci_fm_search_stations_req, (unsigned
+		long)srch_stations, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_fm_search_rds_stations(struct hci_fm_search_rds_station_req *arg,
+	struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_search_rds_station_req *srch_stations = arg;
+
+	ret = radio_hci_request(hdev, hci_fm_srch_rds_stations_req, (unsigned
+		long)srch_stations, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_fm_search_station_list
+	(struct hci_fm_search_station_list_req *arg,
+	struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_search_station_list_req *srch_list = arg;
+
+	ret = radio_hci_request(hdev, hci_fm_srch_station_list_req, (unsigned
+		long)srch_list, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_fm_rds_grp(struct hci_fm_rds_grp_req *arg,
+	struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_rds_grp_req *fm_grp_mask = arg;
+
+	ret = radio_hci_request(hdev, hci_fm_rds_grp_mask_req, (unsigned
+		long)fm_grp_mask, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_fm_rds_grps_process(__u32 *arg, struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	__u32 fm_grps_process;
+
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	fm_grps_process = *arg;
+	ret = radio_hci_request(hdev, hci_fm_rds_grp_process_req,
+		fm_grps_process, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+int hci_def_data_read(struct hci_fm_def_data_rd_req *arg,
+	struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_def_data_rd_req *def_data_rd = arg;
+
+	ret = radio_hci_request(hdev, hci_def_data_read_req, (unsigned
+		long)def_data_rd, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+int hci_def_data_write(struct hci_fm_def_data_wr_req *arg,
+	struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_def_data_wr_req *def_data_wr = arg;
+
+	ret = radio_hci_request(hdev, hci_def_data_write_req, (unsigned
+		long)def_data_wr, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+int hci_fm_do_calibration(__u8 *arg, struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	__u8 mode;
+
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	mode = *arg;
+	ret = radio_hci_request(hdev, hci_fm_do_calibration_req, mode,
+		RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_read_grp_counters(__u8 *arg, struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	__u8 reset_counters;
+
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+	reset_counters = *arg;
+	ret = radio_hci_request(hdev, hci_read_grp_counters_req,
+		reset_counters, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_set_notch_filter(__u8 *arg, struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	__u8 notch_filter;
+
+	if (arg == NULL) {
+		FMDERR("%s, arg is null\n", __func__);
+		return -EINVAL;
+	}
+
+	notch_filter = *arg;
+	ret = radio_hci_request(hdev, hci_set_notch_filter_req,
+		notch_filter, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_peek_data(struct hci_fm_riva_data *arg,
+				struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_riva_data *peek_data = arg;
+
+	ret = radio_hci_request(hdev, hci_peek_data_req, (unsigned
+		long)peek_data, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_poke_data(struct hci_fm_riva_poke *arg,
+			struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_riva_poke *poke_data = arg;
+
+	ret = radio_hci_request(hdev, hci_poke_data_req, (unsigned
+		long)poke_data, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_ssbi_peek_reg(struct hci_fm_ssbi_peek *arg,
+	struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_ssbi_peek *ssbi_peek_reg = arg;
+
+	ret = radio_hci_request(hdev, hci_ssbi_peek_reg_req, (unsigned
+		long)ssbi_peek_reg, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_ssbi_poke_reg(struct hci_fm_ssbi_req *arg,
+			struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_ssbi_req *ssbi_poke_reg = arg;
+
+	ret = radio_hci_request(hdev, hci_ssbi_poke_reg_req, (unsigned
+		long)ssbi_poke_reg, RADIO_HCI_TIMEOUT);
+
+	return ret;
+}
+
+static int hci_set_ch_det_thresholds_req(struct hci_fm_ch_det_threshold *arg,
+		struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_ch_det_threshold *ch_det_threshold = arg;
+
+	ret = radio_hci_request(hdev, hci_fm_set_ch_det_th,
+		 (unsigned long)ch_det_threshold, RADIO_HCI_TIMEOUT);
+	return ret;
+}
+
+static int hci_fm_set_cal_req_proc(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	u16 opcode = 0;
+	struct hci_fm_set_cal_req_proc *cal_req =
+		(struct hci_fm_set_cal_req_proc *)param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
+		HCI_OCF_FM_SET_CALIBRATION);
+	return radio_hci_send_cmd(hdev, opcode,
+		sizeof(struct hci_fm_set_cal_req_proc), cal_req);
+}
+
+static int hci_fm_do_cal_req(struct radio_hci_dev *hdev,
+		unsigned long param)
+{
+	u16 opcode = 0;
+	u8 cal_mode = param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
+		HCI_OCF_FM_DO_CALIBRATION);
+	return radio_hci_send_cmd(hdev, opcode, sizeof(cal_mode),
+		&cal_mode);
+
+}
+
+static int hci_fm_set_spur_tbl_req(struct radio_hci_dev *hdev,
+					unsigned long param)
+{
+	u16 opcode = 0, len = 0;
+	struct hci_fm_set_spur_table_req *spur_req =
+		(struct hci_fm_set_spur_table_req *)param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
+			HCI_OCF_FM_SET_SPUR_TABLE);
+	if (spur_req->no_of_freqs_entries > ENTRIES_EACH_CMD)
+		len = (ENTRIES_EACH_CMD * SPUR_DATA_LEN)
+			+ SPUR_DATA_INDEX;
+	else
+		len = (spur_req->no_of_freqs_entries * SPUR_DATA_LEN)
+			+ SPUR_DATA_INDEX;
+
+	return radio_hci_send_cmd(hdev, opcode, len, spur_req);
+}
+
+static int hci_fm_get_spur_tbl_data(struct radio_hci_dev *hdev,
+					unsigned long param)
+{
+	u16 opcode = 0;
+	unsigned int spur_freq = (unsigned int)param;
+
+	opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
+			HCI_OCF_FM_GET_SPUR_TABLE);
+	return radio_hci_send_cmd(hdev, opcode, sizeof(int), &spur_freq);
+}
+
+static int hci_set_blend_tbl_req(struct hci_fm_blend_table *arg,
+		struct radio_hci_dev *hdev)
+{
+	int ret = 0;
+	struct hci_fm_blend_table *blend_tbl = arg;
+
+	ret = radio_hci_request(hdev, hci_fm_set_blend_tbl,
+		 (unsigned long)blend_tbl, RADIO_HCI_TIMEOUT);
+	return ret;
+}
+
+static int hci_cmd_internal(unsigned int cmd, struct radio_hci_dev *hdev,
+						bool interruptible)
+{
+	int ret = 0;
+	unsigned long arg = 0;
+	radio_hci_request_func radio_hci_request;
+
+	FMDBG("hdev %pK cmd 0x%x", hdev, cmd);
+
+	if (!hdev)
+		return -ENODEV;
+
+	radio_hci_request = interruptible ? radio_hci_request_interruptible :
+			radio_hci_request_uninterruptible;
+
+	switch (cmd) {
+	case HCI_FM_ENABLE_RECV_CMD:
+		ret = radio_hci_request(hdev, hci_fm_enable_recv_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_DISABLE_RECV_CMD:
+		ret = radio_hci_request(hdev, hci_fm_disable_recv_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_GET_RECV_CONF_CMD:
+		ret = radio_hci_request(hdev, hci_get_fm_recv_conf_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_GET_STATION_PARAM_CMD:
+		ret = radio_hci_request(hdev,
+			hci_fm_get_station_param_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_GET_SIGNAL_TH_CMD:
+		ret = radio_hci_request(hdev,
+			hci_fm_get_sig_threshold_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_GET_PROGRAM_SERVICE_CMD:
+		ret = radio_hci_request(hdev,
+			hci_fm_get_program_service_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_GET_RADIO_TEXT_CMD:
+		ret = radio_hci_request(hdev, hci_fm_get_radio_text_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_GET_AF_LIST_CMD:
+		ret = radio_hci_request(hdev, hci_fm_get_af_list_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_CANCEL_SEARCH_CMD:
+		ret = radio_hci_request(hdev, hci_fm_cancel_search_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_RESET_CMD:
+		ret = radio_hci_request(hdev, hci_fm_reset_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_GET_FEATURES_CMD:
+		ret = radio_hci_request(hdev,
+		hci_fm_get_feature_lists_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_STATION_DBG_PARAM_CMD:
+		ret = radio_hci_request(hdev,
+		hci_fm_get_station_dbg_param_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_ENABLE_TRANS_CMD:
+		ret = radio_hci_request(hdev, hci_fm_enable_trans_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_DISABLE_TRANS_CMD:
+		ret = radio_hci_request(hdev, hci_fm_disable_trans_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+
+	case HCI_FM_GET_TX_CONFIG:
+		ret = radio_hci_request(hdev, hci_get_fm_trans_conf_req, arg,
+			RADIO_HCI_TIMEOUT);
+		break;
+	case HCI_FM_GET_DET_CH_TH_CMD:
+		ret = radio_hci_request(hdev, hci_fm_get_ch_det_th, arg,
+					RADIO_HCI_TIMEOUT);
+		break;
+	case HCI_FM_GET_BLND_TBL_CMD:
+		ret = radio_hci_request(hdev, hci_fm_get_blend_tbl, arg,
+					RADIO_HCI_TIMEOUT);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+
+static int hci_cmd(unsigned int cmd, struct radio_hci_dev *hdev)
+{
+	return hci_cmd_internal(cmd, hdev, true);
+}
+
+static int hci_cmd_uninterruptible(unsigned int cmd, struct radio_hci_dev *hdev)
+{
+	return hci_cmd_internal(cmd, hdev, false);
+}
+
+static void radio_hci_req_complete(struct radio_hci_dev *hdev, int result)
+{
+
+	if (unlikely(hdev == NULL)) {
+		FMDERR("%s, hci device is null\n", __func__);
+		return;
+	}
+	hdev->req_result = result;
+	hdev->req_status = HCI_REQ_DONE;
+	wake_up(&hdev->req_wait_q);
+}
+
+static void radio_hci_status_complete(struct radio_hci_dev *hdev, int result)
+{
+	if (unlikely(hdev == NULL)) {
+		FMDERR("%s, hci device is null\n", __func__);
+		return;
+	}
+	hdev->req_result = result;
+	hdev->req_status = HCI_REQ_STATUS;
+	wake_up(&hdev->req_wait_q);
+}
+
+static void hci_cc_rsp(struct radio_hci_dev *hdev, struct sk_buff *skb)
+{
+	__u8 status;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	status = *((__u8 *) skb->data);
+
+	radio_hci_req_complete(hdev, status);
+}
+
+static void hci_cc_fm_disable_rsp(struct radio_hci_dev *hdev,
+	struct sk_buff *skb)
+{
+	__u8 status;
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+
+	FMDBG("hdev %pK skb %p", hdev, skb);
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null");
+		return;
+	}
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	status = *((__u8 *) skb->data);
+	if ((radio->mode == FM_TURNING_OFF) && (status == 0)) {
+		if (!radio->is_fm_closing)
+			iris_q_event(radio, IRIS_EVT_RADIO_DISABLED);
+		radio_hci_req_complete(hdev, status);
+		radio->mode = FM_OFF;
+	} else if (radio->mode == FM_CALIB) {
+		radio_hci_req_complete(hdev, status);
+	} else if ((radio->mode == FM_RECV) || (radio->mode == FM_TRANS)) {
+		iris_q_event(radio, IRIS_EVT_RADIO_DISABLED);
+		radio->mode = FM_OFF;
+	} else if ((radio->mode == FM_TURNING_OFF) && (status != 0)) {
+		radio_hci_req_complete(hdev, status);
+	}
+}
+
+static void hci_cc_conf_rsp(struct radio_hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_fm_conf_rsp  *rsp;
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null");
+		return;
+	}
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	rsp = (struct hci_fm_conf_rsp *)skb->data;
+	if (!rsp->status)
+		radio->recv_conf = rsp->recv_conf_rsp;
+	radio_hci_req_complete(hdev, rsp->status);
+}
+
+static void hci_cc_fm_trans_get_conf_rsp(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct hci_fm_get_trans_conf_rsp  *rsp;
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rsp = (struct hci_fm_get_trans_conf_rsp *)skb->data;
+	if (!rsp->status)
+		memcpy((void *)&radio->trans_conf,
+			(void *)&rsp->trans_conf_rsp,
+			sizeof(rsp->trans_conf_rsp));
+
+	radio_hci_req_complete(hdev, rsp->status);
+}
+
+static void hci_cc_fm_enable_rsp(struct radio_hci_dev *hdev,
+	struct sk_buff *skb)
+{
+	struct hci_fm_conf_rsp  *rsp;
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+
+	FMDBG("hdev %pK skb %p", hdev, skb);
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rsp = (struct hci_fm_conf_rsp *)skb->data;
+	if (rsp->status) {
+		radio_hci_req_complete(hdev, rsp->status);
+		return;
+	}
+
+	radio_hci_req_complete(hdev, rsp->status);
+}
+
+
+static void hci_cc_fm_trans_set_conf_rsp(struct radio_hci_dev *hdev,
+	struct sk_buff *skb)
+{
+	struct hci_fm_conf_rsp  *rsp;
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	rsp = (struct hci_fm_conf_rsp  *)skb->data;
+	if (!rsp->status)
+		iris_q_event(radio, HCI_EV_CMD_COMPLETE);
+
+	radio_hci_req_complete(hdev, rsp->status);
+}
+
+
+static void hci_cc_sig_threshold_rsp(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct hci_fm_sig_threshold_rsp  *rsp;
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rsp = (struct hci_fm_sig_threshold_rsp  *)skb->data;
+	if (!rsp->status)
+		memcpy(&radio->sig_th, rsp,
+			sizeof(struct hci_fm_sig_threshold_rsp));
+	radio_hci_req_complete(hdev, rsp->status);
+}
+
+static void hci_cc_station_rsp(struct radio_hci_dev *hdev, struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	struct hci_fm_station_rsp *rsp;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rsp = (struct hci_fm_station_rsp *)skb->data;
+	radio->fm_st_rsp = *(rsp);
+
+	/* Tune is always successful */
+	radio_hci_req_complete(hdev, 0);
+}
+
+static void hci_cc_prg_srv_rsp(struct radio_hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_fm_prgm_srv_rsp  *rsp;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rsp = (struct hci_fm_prgm_srv_rsp  *)skb->data;
+
+	radio_hci_req_complete(hdev, rsp->status);
+}
+
+static void hci_cc_rd_txt_rsp(struct radio_hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_fm_radio_txt_rsp  *rsp;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rsp = (struct hci_fm_radio_txt_rsp  *)skb->data;
+	radio_hci_req_complete(hdev, rsp->status);
+}
+
+static void hci_cc_af_list_rsp(struct radio_hci_dev *hdev, struct sk_buff *skb)
+{
+	struct hci_fm_af_list_rsp  *rsp;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rsp = (struct hci_fm_af_list_rsp  *)skb->data;
+	radio_hci_req_complete(hdev, rsp->status);
+}
+
+static void hci_cc_feature_list_rsp(struct radio_hci_dev *hdev,
+	struct sk_buff *skb)
+{
+	struct v4l2_capability *v4l_cap;
+	struct hci_fm_feature_list_rsp  *rsp;
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rsp = (struct hci_fm_feature_list_rsp  *)skb->data;
+	v4l_cap = &radio->g_cap;
+
+	if (!rsp->status)
+		v4l_cap->capabilities = (rsp->feature_mask & 0x000002) |
+						(rsp->feature_mask & 0x000001);
+
+	radio_hci_req_complete(hdev, rsp->status);
+}
+
+static void hci_cc_dbg_param_rsp(struct radio_hci_dev *hdev,
+	struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	struct hci_fm_dbg_param_rsp *rsp;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rsp = (struct hci_fm_dbg_param_rsp *)skb->data;
+	radio->st_dbg_param = *(rsp);
+	radio_hci_req_complete(hdev, radio->st_dbg_param.status);
+}
+
+static void iris_q_evt_data(struct iris_device *radio,
+				char *data, int len, int event)
+{
+	struct kfifo *data_b;
+
+	FMDBG("radio %pK data %p len %d event %d", radio, data, len, event);
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+	data_b = &radio->data_buf[event];
+	if (kfifo_in_locked(data_b, data, len, &radio->buf_lock[event]))
+		wake_up_interruptible(&radio->event_queue);
+}
+
+static void hci_cc_riva_peek_rsp(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	__u8 status;
+	int len;
+	char *data;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	status = *((__u8 *) skb->data);
+	if (!status) {
+		len = skb->data[RIVA_PEEK_LEN_OFSET] + RIVA_PEEK_PARAM;
+		data = kmalloc(len, GFP_ATOMIC);
+
+		if (data != NULL) {
+			memcpy(data, &skb->data[PEEK_DATA_OFSET], len);
+			iris_q_evt_data(radio, data, len, IRIS_BUF_PEEK);
+			kfree(data);
+		}
+	}
+
+	radio_hci_req_complete(hdev, status);
+}
+
+static void hci_cc_riva_read_default_rsp(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	__u8 status;
+	__u8 len;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	status = *((__u8 *) skb->data);
+	if (!status) {
+		len = skb->data[1];
+		memset(&radio->default_data, 0,
+			sizeof(struct hci_fm_data_rd_rsp));
+		memcpy(&radio->default_data, &skb->data[0], len+2);
+		iris_q_evt_data(radio, &skb->data[0], len+2,
+				IRIS_BUF_RD_DEFAULT);
+	}
+	radio_hci_req_complete(hdev, status);
+}
+
+static void hci_cc_get_spur_tbl(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	__u8 status;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	status = *((__u8 *) skb->data);
+	if (!status) {
+		iris_q_evt_data(radio, &skb->data[1], SPUR_DATA_LEN,
+							IRIS_BUF_SPUR);
+		iris_q_event(radio, IRIS_EVT_SPUR_TBL);
+	}
+	radio_hci_req_complete(hdev, status);
+}
+
+static void hci_cc_ssbi_peek_rsp(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	__u8 status;
+	char *data;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	status = *((__u8 *) skb->data);
+	if (!status) {
+		data = kmalloc(SSBI_PEEK_LEN, GFP_ATOMIC);
+		if (data != NULL) {
+			data[0] = skb->data[PEEK_DATA_OFSET];
+			iris_q_evt_data(radio, data, SSBI_PEEK_LEN,
+					IRIS_BUF_SSBI_PEEK);
+			kfree(data);
+		}
+	}
+
+	radio_hci_req_complete(hdev, status);
+}
+
+static void hci_cc_rds_grp_cntrs_rsp(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	__u8 status;
+	char *data;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	status = *((__u8 *) skb->data);
+	if (!status) {
+		data = kmalloc(RDS_GRP_CNTR_LEN, GFP_ATOMIC);
+		if (data != NULL) {
+			memcpy(data, &skb->data[1], RDS_GRP_CNTR_LEN);
+			iris_q_evt_data(radio, data, RDS_GRP_CNTR_LEN,
+						IRIS_BUF_RDS_CNTRS);
+			kfree(data);
+		}
+	}
+	radio_hci_req_complete(hdev, status);
+}
+
+static void hci_cc_do_calibration_rsp(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	static struct hci_cc_do_calibration_rsp rsp;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rsp.status = skb->data[0];
+	rsp.mode = skb->data[CALIB_MODE_OFSET];
+
+	if (!rsp.status) {
+		if (rsp.mode == PROCS_CALIB_MODE) {
+			memcpy(&rsp.data[0], &skb->data[CALIB_DATA_OFSET],
+				PROCS_CALIB_SIZE);
+			iris_q_evt_data(radio, rsp.data, PROCS_CALIB_SIZE,
+					IRIS_BUF_CAL_DATA);
+		}
+	}
+	radio_hci_req_complete(hdev, rsp.status);
+}
+
+static void hci_cc_get_ch_det_threshold_rsp(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	u8  status;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	status = skb->data[0];
+	if (!status)
+		memcpy(&radio->ch_det_threshold, &skb->data[1],
+			sizeof(struct hci_fm_ch_det_threshold));
+
+	radio_hci_req_complete(hdev, status);
+}
+
+static void hci_cc_get_blend_tbl_rsp(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	u8  status;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	status = skb->data[0];
+	if (!status)
+		memcpy(&radio->blend_tbl, &skb->data[1],
+			sizeof(struct hci_fm_blend_table));
+
+	radio_hci_req_complete(hdev, status);
+}
+
+static inline void hci_cmd_complete_event(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct hci_ev_cmd_complete *cmd_compl_ev;
+	__u16 opcode;
+
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	cmd_compl_ev = (struct hci_ev_cmd_complete *)skb->data;
+	skb_pull(skb, sizeof(*cmd_compl_ev));
+
+	opcode = __le16_to_cpu(cmd_compl_ev->cmd_opcode);
+
+	FMDBG("opcode 0x%x", opcode);
+	switch (opcode) {
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_ENABLE_RECV_REQ):
+	case hci_trans_ctrl_cmd_op_pack(HCI_OCF_FM_ENABLE_TRANS_REQ):
+		hci_cc_fm_enable_rsp(hdev, skb);
+		break;
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_RECV_CONF_REQ):
+		hci_cc_conf_rsp(hdev, skb);
+		break;
+
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_DISABLE_RECV_REQ):
+	case hci_trans_ctrl_cmd_op_pack(HCI_OCF_FM_DISABLE_TRANS_REQ):
+		hci_cc_fm_disable_rsp(hdev, skb);
+		break;
+
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_SET_RECV_CONF_REQ):
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_SET_MUTE_MODE_REQ):
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_SET_STEREO_MODE_REQ):
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_SET_ANTENNA):
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_SET_SIGNAL_THRESHOLD):
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_CANCEL_SEARCH):
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_RDS_GRP):
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_RDS_GRP_PROCESS):
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_EN_WAN_AVD_CTRL):
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_EN_NOTCH_CTRL):
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_SET_CH_DET_THRESHOLD):
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_SET_BLND_TBL):
+	case hci_trans_ctrl_cmd_op_pack(HCI_OCF_FM_RDS_RT_REQ):
+	case hci_trans_ctrl_cmd_op_pack(HCI_OCF_FM_RDS_PS_REQ):
+	case hci_common_cmd_op_pack(HCI_OCF_FM_DEFAULT_DATA_WRITE):
+		hci_cc_rsp(hdev, skb);
+		break;
+	case hci_common_cmd_op_pack(HCI_OCF_FM_RESET):
+	case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_SSBI_POKE_REG):
+	case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_POKE_DATA):
+	case hci_diagnostic_cmd_op_pack(HCI_FM_SET_INTERNAL_TONE_GENRATOR):
+	case hci_common_cmd_op_pack(HCI_OCF_FM_SET_CALIBRATION):
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_SET_EVENT_MASK):
+	case hci_common_cmd_op_pack(HCI_OCF_FM_SET_SPUR_TABLE):
+		hci_cc_rsp(hdev, skb);
+		break;
+	case hci_common_cmd_op_pack(HCI_OCF_FM_GET_SPUR_TABLE):
+		hci_cc_get_spur_tbl(hdev, skb);
+		break;
+	case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_SSBI_PEEK_REG):
+		hci_cc_ssbi_peek_rsp(hdev, skb);
+		break;
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_SIGNAL_THRESHOLD):
+		hci_cc_sig_threshold_rsp(hdev, skb);
+		break;
+
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_STATION_PARAM_REQ):
+		hci_cc_station_rsp(hdev, skb);
+		break;
+
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_PROGRAM_SERVICE_REQ):
+		hci_cc_prg_srv_rsp(hdev, skb);
+		break;
+
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_RADIO_TEXT_REQ):
+		hci_cc_rd_txt_rsp(hdev, skb);
+		break;
+
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_AF_LIST_REQ):
+		hci_cc_af_list_rsp(hdev, skb);
+		break;
+
+	case hci_common_cmd_op_pack(HCI_OCF_FM_DEFAULT_DATA_READ):
+		hci_cc_riva_read_default_rsp(hdev, skb);
+		break;
+
+	case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_PEEK_DATA):
+		hci_cc_riva_peek_rsp(hdev, skb);
+		break;
+
+	case hci_common_cmd_op_pack(HCI_OCF_FM_GET_FEATURE_LIST):
+		hci_cc_feature_list_rsp(hdev, skb);
+		break;
+
+	case hci_diagnostic_cmd_op_pack(HCI_OCF_FM_STATION_DBG_PARAM):
+		hci_cc_dbg_param_rsp(hdev, skb);
+		break;
+	case hci_trans_ctrl_cmd_op_pack(HCI_OCF_FM_SET_TRANS_CONF_REQ):
+		hci_cc_fm_trans_set_conf_rsp(hdev, skb);
+		break;
+
+	case hci_status_param_op_pack(HCI_OCF_FM_READ_GRP_COUNTERS):
+		hci_cc_rds_grp_cntrs_rsp(hdev, skb);
+		break;
+	case hci_common_cmd_op_pack(HCI_OCF_FM_DO_CALIBRATION):
+		hci_cc_do_calibration_rsp(hdev, skb);
+		break;
+
+	case hci_trans_ctrl_cmd_op_pack(HCI_OCF_FM_GET_TRANS_CONF_REQ):
+		hci_cc_fm_trans_get_conf_rsp(hdev, skb);
+		break;
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_CH_DET_THRESHOLD):
+		hci_cc_get_ch_det_threshold_rsp(hdev, skb);
+		break;
+	case hci_recv_ctrl_cmd_op_pack(HCI_OCF_FM_GET_BLND_TBL):
+		hci_cc_get_blend_tbl_rsp(hdev, skb);
+		break;
+	default:
+		FMDERR("%s opcode 0x%x\n", hdev->name, opcode);
+		break;
+	}
+
+}
+
+static inline void hci_cmd_status_event(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct hci_ev_cmd_status *ev = (void *) skb->data;
+
+	radio_hci_status_complete(hdev, ev->status);
+}
+
+static inline void hci_ev_tune_status(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	int i;
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+	memcpy(&radio->fm_st_rsp.station_rsp, &skb->data[0],
+				sizeof(struct hci_ev_tune_status));
+	iris_q_event(radio, IRIS_EVT_TUNE_SUCC);
+
+	for (i = 0; i < IRIS_BUF_MAX; i++) {
+		if (i >= IRIS_BUF_RT_RDS)
+			kfifo_reset(&radio->data_buf[i]);
+	}
+	if (radio->fm_st_rsp.station_rsp.serv_avble)
+		iris_q_event(radio, IRIS_EVT_ABOVE_TH);
+	else
+		iris_q_event(radio, IRIS_EVT_BELOW_TH);
+
+	if (radio->fm_st_rsp.station_rsp.stereo_prg)
+		iris_q_event(radio, IRIS_EVT_STEREO);
+	else if (radio->fm_st_rsp.station_rsp.stereo_prg == 0)
+		iris_q_event(radio, IRIS_EVT_MONO);
+
+	if (radio->fm_st_rsp.station_rsp.rds_sync_status)
+		iris_q_event(radio, IRIS_EVT_RDS_AVAIL);
+	else
+		iris_q_event(radio, IRIS_EVT_RDS_NOT_AVAIL);
+}
+
+static inline void hci_ev_search_compl(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+
+	radio->search_on = 0;
+	iris_q_event(radio, IRIS_EVT_SEEK_COMPLETE);
+}
+
+static inline void hci_ev_srch_st_list_compl(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	struct hci_ev_srch_list_compl *ev;
+	int cnt;
+	int stn_num;
+	int rel_freq;
+	int abs_freq;
+	int len;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+	if (!ev)
+		return;
+
+	ev->num_stations_found = skb->data[STN_NUM_OFFSET];
+	len = ev->num_stations_found * PARAMS_PER_STATION + STN_FREQ_OFFSET;
+
+	for (cnt = STN_FREQ_OFFSET, stn_num = 0;
+		(cnt < len) && (stn_num < ev->num_stations_found)
+		&& (stn_num < ARRAY_SIZE(ev->rel_freq));
+		cnt += PARAMS_PER_STATION, stn_num++) {
+		abs_freq = *((int *)&skb->data[cnt]);
+		rel_freq = abs_freq - radio->recv_conf.band_low_limit;
+		rel_freq = (rel_freq * 20) / KHZ_TO_MHZ;
+
+		ev->rel_freq[stn_num].rel_freq_lsb = GET_LSB(rel_freq);
+		ev->rel_freq[stn_num].rel_freq_msb = GET_MSB(rel_freq);
+	}
+
+	len = ev->num_stations_found * 2 + sizeof(ev->num_stations_found);
+	iris_q_event(radio, IRIS_EVT_NEW_SRCH_LIST);
+	iris_q_evt_data(radio, (char *)ev, len, IRIS_BUF_SRCH_LIST);
+	kfree(ev);
+}
+
+static inline void hci_ev_search_next(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+
+	iris_q_event(radio, IRIS_EVT_SCAN_NEXT);
+}
+
+static inline void hci_ev_stereo_status(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	__u8 st_status;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	st_status = *((__u8 *) skb->data);
+	if (st_status)
+		iris_q_event(radio, IRIS_EVT_STEREO);
+	else
+		iris_q_event(radio, IRIS_EVT_MONO);
+}
+
+static void hci_ev_raw_rds_group_data(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio;
+	unsigned char blocknum, index;
+	struct rds_grp_data temp;
+	unsigned int mask_bit;
+	unsigned short int aid, agt, gtc;
+	unsigned short int carrier;
+
+	radio = video_get_drvdata(video_get_dev());
+	index = RDSGRP_DATA_OFFSET;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return;
+	}
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	for (blocknum = 0; blocknum < RDS_BLOCKS_NUM; blocknum++) {
+		temp.rdsBlk[blocknum].rdsLsb =
+			(skb->data[index]);
+		temp.rdsBlk[blocknum].rdsMsb =
+			(skb->data[index+1]);
+		index = index + 2;
+	}
+
+	aid = AID(temp.rdsBlk[3].rdsLsb, temp.rdsBlk[3].rdsMsb);
+	gtc = GTC(temp.rdsBlk[1].rdsMsb);
+	agt = AGT(temp.rdsBlk[1].rdsLsb);
+
+	if (gtc == GRP_3A) {
+		switch (aid) {
+		case ERT_AID:
+			/* calculate the grp mask for RDS grp
+			 * which will contain actual eRT text
+			 *
+			 * Bit Pos  0  1  2  3  4   5  6   7
+			 * Grp Type 0A 0B 1A 1B 2A  2B 3A  3B
+			 *
+			 * similarly for rest grps
+			 */
+			mask_bit = (((agt >> 1) << 1) + (agt & 1));
+			oda_agt = (1 << mask_bit);
+			utf_8_flag = (temp.rdsBlk[2].rdsLsb & 1);
+			formatting_dir = EXTRACT_BIT(temp.rdsBlk[2].rdsLsb,
+							ERT_FORMAT_DIR_BIT);
+			if (ert_carrier != agt)
+				iris_q_event(radio, IRIS_EVT_NEW_ODA);
+			ert_carrier = agt;
+			break;
+		case RT_PLUS_AID:
+			/* calculate the grp mask for RDS grp
+			 * which will contain actual eRT text
+			 *
+			 * Bit Pos  0  1  2  3  4   5  6   7
+			 * Grp Type 0A 0B 1A 1B 2A  2B 3A  3B
+			 *
+			 * similarly for rest grps
+			 */
+			mask_bit = (((agt >> 1) << 1) + (agt & 1));
+			oda_agt =  (1 << mask_bit);
+			/*Extract 5th bit of MSB (b7b6b5b4b3b2b1b0)*/
+			rt_ert_flag = EXTRACT_BIT(temp.rdsBlk[2].rdsMsb,
+					 RT_ERT_FLAG_BIT);
+			if (rt_plus_carrier != agt)
+				iris_q_event(radio, IRIS_EVT_NEW_ODA);
+			rt_plus_carrier = agt;
+			break;
+		default:
+			oda_agt = 0;
+			break;
+		}
+	} else {
+		carrier = gtc;
+		if (carrier == rt_plus_carrier)
+			hci_ev_rt_plus(radio, temp);
+		else if (carrier == ert_carrier)
+			hci_buff_ert(radio, &temp);
+	}
+}
+
+static void hci_buff_ert(struct iris_device *radio,
+	struct rds_grp_data *rds_buf)
+{
+	int i;
+	unsigned short int info_byte = 0;
+	unsigned short int byte_pair_index;
+
+	if (rds_buf == NULL) {
+		FMDERR("%s, rds buffer is null\n", __func__);
+		return;
+	}
+	byte_pair_index = AGT(rds_buf->rdsBlk[1].rdsLsb);
+	if (byte_pair_index == 0) {
+		c_byt_pair_index = 0;
+		ert_len = 0;
+	}
+	if (c_byt_pair_index == byte_pair_index) {
+		c_byt_pair_index++;
+		for (i = 2; i <= 3; i++) {
+			info_byte = rds_buf->rdsBlk[i].rdsLsb;
+			info_byte |= (rds_buf->rdsBlk[i].rdsMsb << 8);
+			ert_buf[ert_len++] = rds_buf->rdsBlk[i].rdsMsb;
+			ert_buf[ert_len++] = rds_buf->rdsBlk[i].rdsLsb;
+			if ((utf_8_flag == 0)
+				 && (info_byte == CARRIAGE_RETURN)) {
+				ert_len -= 2;
+				break;
+			} else if ((utf_8_flag == 1)
+					&&
+					(rds_buf->rdsBlk[i].rdsMsb
+						 == CARRIAGE_RETURN)) {
+				info_byte = CARRIAGE_RETURN;
+				ert_len -= 2;
+				break;
+			} else if ((utf_8_flag == 1)
+					&&
+					(rds_buf->rdsBlk[i].rdsLsb
+						 == CARRIAGE_RETURN)) {
+				info_byte = CARRIAGE_RETURN;
+				ert_len--;
+				break;
+			}
+		}
+		if ((byte_pair_index == MAX_ERT_SEGMENT) ||
+			(info_byte == CARRIAGE_RETURN)) {
+			hci_ev_ert(radio);
+			c_byt_pair_index = 0;
+			ert_len = 0;
+		}
+	} else {
+		ert_len = 0;
+		c_byt_pair_index = 0;
+	}
+}
+static void hci_ev_ert(struct iris_device *radio)
+
+{
+	char *data = NULL;
+
+	if (ert_len <= 0)
+		return;
+	data = kmalloc((ert_len + 3), GFP_ATOMIC);
+	if (data != NULL) {
+		data[0] = ert_len;
+		data[1] = utf_8_flag;
+		data[2] = formatting_dir;
+		memcpy((data + 3), ert_buf, ert_len);
+		iris_q_evt_data(radio, data, (ert_len + 3), IRIS_BUF_ERT);
+		iris_q_event(radio, IRIS_EVT_NEW_ERT);
+		kfree(data);
+	}
+}
+
+static void hci_ev_rt_plus(struct iris_device *radio,
+		 struct rds_grp_data rds_buf)
+{
+	char tag_type1, tag_type2;
+	char *data = NULL;
+	int len = 0;
+	unsigned short int agt;
+
+	agt = AGT(rds_buf.rdsBlk[1].rdsLsb);
+	/*right most 3 bits of Lsb of block 2
+	 * and left most 3 bits of Msb of block 3
+	 */
+	tag_type1 = (((agt & TAG1_MSB_MASK) << TAG1_MSB_OFFSET) |
+			 (rds_buf.rdsBlk[2].rdsMsb >> TAG1_LSB_OFFSET));
+
+	/*right most 1 bit of lsb of 3rd block
+	 * and left most 5 bits of Msb of 4th block
+	 */
+	tag_type2 = (((rds_buf.rdsBlk[2].rdsLsb & TAG2_MSB_MASK)
+			 << TAG2_MSB_OFFSET) |
+			 (rds_buf.rdsBlk[3].rdsMsb >> TAG2_LSB_OFFSET));
+
+	if (tag_type1 != DUMMY_CLASS)
+		len += RT_PLUS_LEN_1_TAG;
+	if (tag_type2 != DUMMY_CLASS)
+		len += RT_PLUS_LEN_1_TAG;
+
+	if (len != 0) {
+		len += 2;
+		data = kmalloc(len, GFP_ATOMIC);
+	} else {
+		FMDERR("Len is zero\n");
+		return;
+	}
+	if (data != NULL) {
+		data[0] = len;
+		len = 1;
+		data[len++] = rt_ert_flag;
+		if (tag_type1 != DUMMY_CLASS) {
+			data[len++] = tag_type1;
+			/*start position of tag1
+			 *right most 5 bits of msb of 3rd block
+			 *and left most bit of lsb of 3rd block
+			 */
+			data[len++] = (((rds_buf.rdsBlk[2].rdsMsb &
+						 TAG1_POS_MSB_MASK)
+						<< TAG1_POS_MSB_OFFSET)
+						|
+					(rds_buf.rdsBlk[2].rdsLsb >>
+						TAG1_POS_LSB_OFFSET));
+			/*length of tag1
+			 *left most 6 bits of lsb of 3rd block
+			 */
+			data[len++] = ((rds_buf.rdsBlk[2].rdsLsb
+						>> TAG1_LEN_OFFSET)
+							 &
+						TAG1_LEN_MASK) + 1;
+		}
+		if (tag_type2 != DUMMY_CLASS) {
+			data[len++] = tag_type2;
+			/*start position of tag2
+			 *right most 3 bit of msb of 4th block
+			 *and left most 3 bits of lsb of 4th block
+			 */
+			data[len++] = (((rds_buf.rdsBlk[3].rdsMsb
+						& TAG2_POS_MSB_MASK)
+						<< TAG2_POS_MSB_OFFSET)
+						|
+					(rds_buf.rdsBlk[3].rdsLsb
+						>> TAG2_POS_LSB_OFFSET));
+			/*length of tag2
+			 *right most 5 bits of lsb of 4th block
+			 */
+			data[len++] = (rds_buf.rdsBlk[3].rdsLsb
+						& TAG2_LEN_MASK) + 1;
+		}
+		iris_q_evt_data(radio, data, len, IRIS_BUF_RT_PLUS);
+		iris_q_event(radio,  IRIS_EVT_NEW_RT_PLUS);
+		kfree(data);
+	}
+}
+
+static inline void hci_ev_program_service(struct radio_hci_dev *hdev,
+		struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	int len;
+	char *data;
+
+	len = (skb->data[RDS_PS_LENGTH_OFFSET] * RDS_STRING) + RDS_OFFSET;
+	iris_q_event(radio, IRIS_EVT_NEW_PS_RDS);
+	data = kmalloc(len, GFP_ATOMIC);
+	if (!data)
+		return;
+
+	data[0] = skb->data[RDS_PS_LENGTH_OFFSET];
+	data[1] = skb->data[RDS_PTYPE];
+	data[2] = skb->data[RDS_PID_LOWER];
+	data[3] = skb->data[RDS_PID_HIGHER];
+	data[4] = 0;
+
+	memcpy(data+RDS_OFFSET, &skb->data[RDS_PS_DATA_OFFSET], len-RDS_OFFSET);
+
+	iris_q_evt_data(radio, data, len, IRIS_BUF_PS_RDS);
+
+	kfree(data);
+}
+
+
+static inline void hci_ev_radio_text(struct radio_hci_dev *hdev,
+	struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	int len = 0;
+	char *data;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	iris_q_event(radio, IRIS_EVT_NEW_RT_RDS);
+
+	while ((skb->data[len+RDS_OFFSET] != 0x0d) && (len < MAX_RT_LENGTH))
+		len++;
+	data = kmalloc(len+RDS_OFFSET, GFP_ATOMIC);
+	if (!data)
+		return;
+
+	data[0] = len;
+	data[1] = skb->data[RDS_PTYPE];
+	data[2] = skb->data[RDS_PID_LOWER];
+	data[3] = skb->data[RDS_PID_HIGHER];
+	data[4] = skb->data[RT_A_B_FLAG_OFFSET];
+
+	memcpy(data+RDS_OFFSET, &skb->data[RDS_OFFSET], len);
+	data[len+RDS_OFFSET] = 0x00;
+
+	iris_q_evt_data(radio, data, len+RDS_OFFSET, IRIS_BUF_RT_RDS);
+
+	kfree(data);
+}
+
+static void hci_ev_af_list(struct radio_hci_dev *hdev,
+	struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	struct hci_ev_af_list ev;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	ev.tune_freq = *((int *) &skb->data[0]);
+	ev.pi_code = *((__le16 *) &skb->data[PI_CODE_OFFSET]);
+	ev.af_size = skb->data[AF_SIZE_OFFSET];
+	if (ev.af_size > AF_LIST_MAX) {
+		FMDERR("AF list size received more than available size\n");
+		return;
+	}
+	memcpy(&ev.af_list[0], &skb->data[AF_LIST_OFFSET],
+					ev.af_size * sizeof(int));
+	iris_q_event(radio, IRIS_EVT_NEW_AF_LIST);
+	iris_q_evt_data(radio, (char *)&ev, (7 + ev.af_size * sizeof(int)),
+							IRIS_BUF_AF_LIST);
+}
+
+static void hci_ev_rds_lock_status(struct radio_hci_dev *hdev,
+	struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	__u8 rds_status;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+
+	rds_status = skb->data[0];
+
+	if (rds_status)
+		iris_q_event(radio, IRIS_EVT_RDS_AVAIL);
+	else
+		iris_q_event(radio, IRIS_EVT_RDS_NOT_AVAIL);
+}
+
+static void hci_ev_service_available(struct radio_hci_dev *hdev,
+	struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+	u8 serv_avble;
+
+	if (unlikely(skb == NULL)) {
+		FMDERR("%s, socket buffer is null\n", __func__);
+		return;
+	}
+	serv_avble = skb->data[0];
+	if (serv_avble)
+		iris_q_event(radio, IRIS_EVT_ABOVE_TH);
+	else
+		iris_q_event(radio, IRIS_EVT_BELOW_TH);
+}
+
+static void hci_ev_rds_grp_complete(struct radio_hci_dev *hdev,
+	struct sk_buff *skb)
+{
+	struct iris_device *radio = video_get_drvdata(video_get_dev());
+
+	iris_q_event(radio, IRIS_EVT_TXRDSDONE);
+}
+
+void radio_hci_event_packet(struct radio_hci_dev *hdev, struct sk_buff *skb)
+{
+	struct radio_hci_event_hdr *hdr;
+	u8 event;
+
+	if (skb == NULL) {
+		FMDERR("Socket buffer is NULL\n");
+		return;
+	}
+
+	hdr = (void *) skb->data;
+	event = hdr->evt;
+
+	skb_pull(skb, RADIO_HCI_EVENT_HDR_SIZE);
+
+	FMDBG("event 0x%x", event);
+	switch (event) {
+	case HCI_EV_TUNE_STATUS:
+		hci_ev_tune_status(hdev, skb);
+		break;
+	case HCI_EV_SEARCH_PROGRESS:
+	case HCI_EV_SEARCH_RDS_PROGRESS:
+	case HCI_EV_SEARCH_LIST_PROGRESS:
+		hci_ev_search_next(hdev, skb);
+		break;
+	case HCI_EV_STEREO_STATUS:
+		hci_ev_stereo_status(hdev, skb);
+		break;
+	case HCI_EV_RDS_LOCK_STATUS:
+		hci_ev_rds_lock_status(hdev, skb);
+		break;
+	case HCI_EV_SERVICE_AVAILABLE:
+		hci_ev_service_available(hdev, skb);
+		break;
+	case HCI_EV_RDS_RX_DATA:
+		hci_ev_raw_rds_group_data(hdev, skb);
+		break;
+	case HCI_EV_PROGRAM_SERVICE:
+		hci_ev_program_service(hdev, skb);
+		break;
+	case HCI_EV_RADIO_TEXT:
+		hci_ev_radio_text(hdev, skb);
+		break;
+	case HCI_EV_FM_AF_LIST:
+		hci_ev_af_list(hdev, skb);
+		break;
+	case HCI_EV_TX_RDS_GRP_COMPL:
+		hci_ev_rds_grp_complete(hdev, skb);
+		break;
+	case HCI_EV_TX_RDS_CONT_GRP_COMPL:
+		break;
+
+	case HCI_EV_CMD_COMPLETE:
+		hci_cmd_complete_event(hdev, skb);
+		break;
+
+	case HCI_EV_CMD_STATUS:
+		hci_cmd_status_event(hdev, skb);
+		break;
+
+	case HCI_EV_SEARCH_COMPLETE:
+	case HCI_EV_SEARCH_RDS_COMPLETE:
+		hci_ev_search_compl(hdev, skb);
+		break;
+
+	case HCI_EV_SEARCH_LIST_COMPLETE:
+		hci_ev_srch_st_list_compl(hdev, skb);
+		break;
+
+	default:
+		break;
+	}
+}
+
+/*
+ * fops/IOCTL helper functions
+ */
+
+static int iris_search(struct iris_device *radio, int on, int dir)
+{
+	int retval = 0;
+	enum search_t srch;
+	int saved_val;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+
+	srch = radio->g_search_mode & SRCH_MODE;
+	saved_val = radio->search_on;
+	radio->search_on = on;
+	if (on) {
+		switch (srch) {
+		case SCAN_FOR_STRONG:
+		case SCAN_FOR_WEAK:
+			radio->srch_st_list.srch_list_dir = dir;
+			radio->srch_st_list.srch_list_mode = srch;
+			retval = hci_fm_search_station_list(
+				&radio->srch_st_list, radio->fm_hdev);
+			break;
+		case RDS_SEEK_PTY:
+		case RDS_SCAN_PTY:
+		case RDS_SEEK_PI:
+			srch = srch - SEARCH_RDS_STNS_MODE_OFFSET;
+			radio->srch_rds.srch_station.srch_mode = srch;
+			radio->srch_rds.srch_station.srch_dir = dir;
+			radio->srch_rds.srch_station.scan_time =
+				radio->g_scan_time;
+			retval = hci_fm_search_rds_stations(&radio->srch_rds,
+				radio->fm_hdev);
+			break;
+		default:
+			radio->srch_st.srch_mode = srch;
+			radio->srch_st.scan_time = radio->g_scan_time;
+			radio->srch_st.srch_dir = dir;
+			retval = hci_fm_search_stations(
+				&radio->srch_st, radio->fm_hdev);
+			break;
+		}
+
+	} else {
+		retval = hci_cmd(HCI_FM_CANCEL_SEARCH_CMD, radio->fm_hdev);
+	}
+
+	if (retval < 0)
+		radio->search_on = saved_val;
+	return retval;
+}
+
+static int set_low_power_mode(struct iris_device *radio, int power_mode)
+{
+
+	int rds_grps_proc = 0x00;
+	int retval = 0;
+	struct hci_fm_rds_grp_req grp_3a;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+
+	FMDBG("power mode old 0x%x new 0x%x", radio->power_mode, power_mode);
+	if (radio->power_mode != power_mode) {
+
+		if (power_mode) {
+			memcpy(&grp_3a, &radio->rds_grp,
+					sizeof(struct hci_fm_rds_grp_req));
+			/* Disable 3A group */
+			grp_3a.rds_grp_enable_mask &= ~FM_RDS_3A_GRP;
+			retval = hci_fm_rds_grp(&grp_3a, radio->fm_hdev);
+			if (retval < 0)
+				FMDERR("error in disable 3A group mask\n");
+			radio->event_mask = 0x00;
+			if (radio->af_jump_bit)
+				rds_grps_proc = 0x00 | AF_JUMP_ENABLE;
+			else
+				rds_grps_proc = 0x00;
+			retval = hci_fm_rds_grps_process(
+				&rds_grps_proc,
+				radio->fm_hdev);
+			if (retval < 0) {
+				FMDERR("Disable RDS failed\n");
+				return retval;
+			}
+			retval = hci_conf_event_mask(&radio->event_mask,
+				radio->fm_hdev);
+		} else {
+			/* Enable RDS group to normal */
+			retval = hci_fm_rds_grp(&radio->rds_grp,
+							radio->fm_hdev);
+			if (retval < 0)
+				FMDERR("error in enable 3A group mask\n");
+			radio->event_mask = SIG_LEVEL_INTR |
+					RDS_SYNC_INTR | AUDIO_CTRL_INTR;
+			retval = hci_conf_event_mask(&radio->event_mask,
+				radio->fm_hdev);
+			if (retval < 0) {
+				FMDERR("Enable Async events failed\n");
+				return retval;
+			}
+			retval = hci_fm_rds_grps_process(
+				&radio->g_rds_grp_proc_ps,
+				radio->fm_hdev);
+		}
+		radio->power_mode = power_mode;
+	}
+	return retval;
+}
+static int iris_recv_set_region(struct iris_device *radio, int req_region)
+{
+	int retval;
+	int saved_val;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+	saved_val = radio->region;
+	radio->region = req_region;
+
+	retval = hci_set_fm_recv_conf(
+			&radio->recv_conf,
+			radio->fm_hdev);
+
+	if (retval < 0)
+		radio->region = saved_val;
+
+	return retval;
+}
+
+
+static int iris_trans_set_region(struct iris_device *radio, int req_region)
+{
+	int retval;
+	int saved_val;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+
+	saved_val = radio->region;
+	radio->region = req_region;
+
+	retval = hci_set_fm_trans_conf(
+			&radio->trans_conf,
+				radio->fm_hdev);
+
+	if (retval < 0)
+		radio->region = saved_val;
+	return retval;
+}
+
+
+static int iris_set_freq(struct iris_device *radio, unsigned int freq)
+{
+
+	int retval;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+	retval = hci_fm_tune_station(&freq, radio->fm_hdev);
+	if (retval < 0)
+		FMDERR("Error while setting the frequency : %d\n", retval);
+	return retval;
+}
+
+
+static int iris_vidioc_queryctrl(struct file *file, void *priv,
+		struct v4l2_queryctrl *qc)
+{
+	unsigned char i;
+	int retval = -EINVAL;
+
+	if (qc == NULL) {
+		FMDERR("%s, query ctrl is null\n", __func__);
+		return retval;
+	}
+	for (i = 0; i < ARRAY_SIZE(iris_v4l2_queryctrl); i++) {
+		if (qc->id && qc->id == iris_v4l2_queryctrl[i].id) {
+			memcpy(qc, &(iris_v4l2_queryctrl[i]), sizeof(*qc));
+			retval = 0;
+			break;
+		}
+	}
+
+	return retval;
+}
+
+static int iris_do_calibration(struct iris_device *radio)
+{
+	char cal_mode = 0x00;
+	int retval = 0x00;
+
+	FMDBG("radio %pK", radio);
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+
+	cal_mode = PROCS_CALIB_MODE;
+	radio->mode = FM_CALIB;
+	retval = hci_cmd(HCI_FM_ENABLE_RECV_CMD,
+			radio->fm_hdev);
+	if (retval < 0) {
+		FMDERR("Enable failed before calibration %x\n", retval);
+		radio->mode = FM_OFF;
+		return retval;
+	}
+	retval = radio_hci_request(radio->fm_hdev, hci_fm_do_cal_req,
+		(unsigned long)cal_mode, RADIO_HCI_TIMEOUT);
+	if (retval < 0) {
+		FMDERR("Do Process calibration failed %x\n", retval);
+		radio->mode = FM_RECV;
+		return retval;
+	}
+	retval = hci_cmd(HCI_FM_DISABLE_RECV_CMD,
+			radio->fm_hdev);
+	if (retval < 0)
+		FMDERR("Disable Failed after calibration %d\n", retval);
+
+	return retval;
+}
+static int iris_vidioc_g_ctrl(struct file *file, void *priv,
+		struct v4l2_control *ctrl)
+{
+	struct iris_device *radio = video_get_drvdata(video_devdata(file));
+	int retval = 0;
+	int cf0;
+	struct hci_fm_def_data_rd_req rd;
+	int lsb, msb;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		retval = -EINVAL;
+		goto end;
+	}
+
+	if (ctrl == NULL) {
+		FMDERR("%s, v4l2 ctrl is null\n", __func__);
+		retval = -EINVAL;
+		goto end;
+	}
+
+	FMDBG("id 0x%x", ctrl->id);
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_VOLUME:
+		break;
+	case V4L2_CID_AUDIO_MUTE:
+		if (is_valid_hard_mute(radio->mute_mode.hard_mute))
+			ctrl->value = radio->mute_mode.hard_mute;
+		else
+			retval = -EINVAL;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SRCHMODE:
+		if (is_valid_srch_mode(radio->g_search_mode))
+			ctrl->value = radio->g_search_mode;
+		else
+			retval = -EINVAL;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SCANDWELL:
+		if (is_valid_scan_dwell_prd(radio->g_scan_time))
+			ctrl->value = radio->g_scan_time;
+		else
+			retval = -EINVAL;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SRCHON:
+		ctrl->value = radio->search_on;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_STATE:
+		if (is_valid_fm_state(radio->mode))
+			ctrl->value = radio->mode;
+		else
+			retval = -EINVAL;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_IOVERC:
+		retval = hci_cmd(HCI_FM_STATION_DBG_PARAM_CMD, radio->fm_hdev);
+		if (retval < 0)
+			return retval;
+		ctrl->value = radio->st_dbg_param.io_verc;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_INTDET:
+		retval = hci_cmd(HCI_FM_STATION_DBG_PARAM_CMD, radio->fm_hdev);
+		if (retval == 0)
+			ctrl->value = radio->st_dbg_param.in_det_out;
+		else
+			retval = -EINVAL;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_REGION:
+		ctrl->value = radio->region;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SIGNAL_TH:
+		retval = hci_cmd(HCI_FM_GET_SIGNAL_TH_CMD, radio->fm_hdev);
+		if ((retval == 0) &&
+			is_valid_sig_th(radio->sig_th.sig_threshold))
+			ctrl->value = radio->sig_th.sig_threshold;
+		else
+			retval = -EINVAL;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SRCH_PTY:
+		if (is_valid_pty(radio->srch_rds.srch_pty))
+			ctrl->value = radio->srch_rds.srch_pty;
+		else
+			retval = -EINVAL;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SRCH_PI:
+		if (is_valid_pi(radio->srch_rds.srch_pi))
+			ctrl->value = radio->srch_rds.srch_pi;
+		else
+			retval = -EINVAL;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SRCH_CNT:
+		if (is_valid_srch_station_cnt(
+			radio->srch_st_result.num_stations_found))
+			ctrl->value = radio->srch_st_result.num_stations_found;
+		else
+			retval = -EINVAL;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_EMPHASIS:
+		if (radio->mode == FM_RECV) {
+			retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+						radio->fm_hdev);
+			if ((retval == 0) &&
+				is_valid_emphasis(radio->recv_conf.emphasis))
+				ctrl->value = radio->recv_conf.emphasis;
+			else
+				retval = -EINVAL;
+		} else if (radio->mode == FM_TRANS) {
+			retval =  hci_cmd(HCI_FM_GET_TX_CONFIG,
+						radio->fm_hdev);
+			if ((retval == 0) &&
+				is_valid_emphasis(radio->trans_conf.emphasis))
+				ctrl->value = radio->trans_conf.emphasis;
+			else
+				retval = -EINVAL;
+		} else {
+			retval = -EINVAL;
+			FMDERR("Error in radio mode %d\n", retval);
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RDS_STD:
+		if (radio->mode == FM_RECV) {
+			retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+						radio->fm_hdev);
+			if ((retval == 0) &&
+				is_valid_rds_std(radio->recv_conf.rds_std))
+				ctrl->value = radio->recv_conf.rds_std;
+			else
+				retval = -EINVAL;
+		} else if (radio->mode == FM_TRANS) {
+			retval =  hci_cmd(HCI_FM_GET_TX_CONFIG,
+						radio->fm_hdev);
+			if ((retval == 0) &&
+				is_valid_rds_std(radio->trans_conf.rds_std))
+				ctrl->value = radio->trans_conf.rds_std;
+			else
+				retval = -EINVAL;
+		} else {
+			retval = -EINVAL;
+			FMDERR("Error in radio mode %d\n", retval);
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SPACING:
+		if (radio->mode == FM_RECV) {
+			retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+						radio->fm_hdev);
+			if ((retval == 0) &&
+				is_valid_chan_spacing(
+						radio->recv_conf.ch_spacing))
+				ctrl->value = radio->recv_conf.ch_spacing;
+			else
+				retval = -EINVAL;
+		} else {
+			retval = -EINVAL;
+			FMDERR("Error in radio mode %d\n", retval);
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RDSON:
+		if (radio->mode == FM_RECV) {
+			retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+						radio->fm_hdev);
+			if ((retval == 0) &&
+				is_valid_rds_std(radio->recv_conf.rds_std))
+				ctrl->value = radio->recv_conf.rds_std;
+			else
+				retval = -EINVAL;
+		} else {
+			retval = -EINVAL;
+			FMDERR("Error in radio mode %d\n", retval);
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RDSGROUP_MASK:
+		ctrl->value = radio->rds_grp.rds_grp_enable_mask;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RDSGROUP_PROC:
+	case V4L2_CID_PRIVATE_IRIS_PSALL:
+		ctrl->value = radio->g_rds_grp_proc_ps;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RDSD_BUF:
+		ctrl->value = radio->rds_grp.rds_buf_size;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_LP_MODE:
+		ctrl->value = radio->power_mode;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_ANTENNA:
+		ctrl->value = radio->g_antenna;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SOFT_MUTE:
+		retval = hci_cmd(HCI_FM_STATION_DBG_PARAM_CMD, radio->fm_hdev);
+		if ((retval == 0) &&
+			is_valid_soft_mute(radio->mute_mode.soft_mute))
+			ctrl->value = radio->mute_mode.soft_mute;
+		else
+			retval = -EINVAL;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_DO_CALIBRATION:
+		retval = iris_do_calibration(radio);
+		break;
+	case V4L2_CID_PRIVATE_IRIS_GET_SINR:
+		if (radio->mode == FM_RECV) {
+			retval = hci_cmd(HCI_FM_GET_STATION_PARAM_CMD,
+						 radio->fm_hdev);
+			if (retval == 0)
+				ctrl->value = radio->fm_st_rsp.station_rsp.sinr;
+		} else
+			retval = -EINVAL;
+		break;
+	case V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD:
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval == 0)
+			ctrl->value = radio->ch_det_threshold.high_th;
+		break;
+	case V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD:
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval == 0)
+			ctrl->value = radio->ch_det_threshold.low_th;
+		break;
+	case V4L2_CID_PRIVATE_SINR_THRESHOLD:
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval == 0)
+			ctrl->value = radio->ch_det_threshold.sinr;
+		break;
+	case V4L2_CID_PRIVATE_SINR_SAMPLES:
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval == 0)
+			ctrl->value = radio->ch_det_threshold.sinr_samples;
+		break;
+	case V4L2_CID_PRIVATE_VALID_CHANNEL:
+		ctrl->value = radio->is_station_valid;
+		break;
+	case V4L2_CID_PRIVATE_AF_RMSSI_TH:
+		rd.mode = FM_RDS_CNFG_MODE;
+		rd.length = FM_RDS_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval == 0) {
+			lsb = radio->default_data.data[AF_RMSSI_TH_LSB_OFFSET];
+			msb = radio->default_data.data[AF_RMSSI_TH_MSB_OFFSET];
+			ctrl->value = ((msb << 8) | lsb);
+		}
+		break;
+	case V4L2_CID_PRIVATE_AF_RMSSI_SAMPLES:
+		rd.mode = FM_RDS_CNFG_MODE;
+		rd.length = FM_RDS_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval == 0)
+			ctrl->value =
+			radio->default_data.data[AF_RMSSI_SAMPLES_OFFSET];
+		break;
+	case V4L2_CID_PRIVATE_GOOD_CH_RMSSI_TH:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval == 0) {
+			ctrl->value =
+			radio->default_data.data[GD_CH_RMSSI_TH_OFFSET];
+			if (ctrl->value > MAX_GD_CH_RMSSI_TH)
+				ctrl->value -= 256;
+		}
+		break;
+	case V4L2_CID_PRIVATE_SRCHALGOTYPE:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval == 0)
+			ctrl->value =
+			radio->default_data.data[SRCH_ALGO_TYPE_OFFSET];
+		break;
+	case V4L2_CID_PRIVATE_SINRFIRSTSTAGE:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval == 0) {
+			ctrl->value =
+			radio->default_data.data[SINRFIRSTSTAGE_OFFSET];
+			if (ctrl->value > MAX_SINR_FIRSTSTAGE)
+				ctrl->value -= 256;
+		}
+		break;
+	case V4L2_CID_PRIVATE_RMSSIFIRSTSTAGE:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval == 0) {
+			ctrl->value =
+			radio->default_data.data[RMSSIFIRSTSTAGE_OFFSET];
+			if (ctrl->value > MAX_RMSSI_FIRSTSTAGE)
+				ctrl->value -= 256;
+		}
+		break;
+	case V4L2_CID_PRIVATE_CF0TH12:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval == 0) {
+			ctrl->value =
+			radio->default_data.data[CF0TH12_BYTE1_OFFSET];
+			cf0 = radio->default_data.data[CF0TH12_BYTE2_OFFSET];
+			ctrl->value |= (cf0 << 8);
+			cf0 = radio->default_data.data[CF0TH12_BYTE3_OFFSET];
+			ctrl->value |= (cf0 << 16);
+			cf0 = radio->default_data.data[CF0TH12_BYTE4_OFFSET];
+			if (cf0 > 127)
+				cf0 -= 256;
+			ctrl->value |= (cf0 << 24);
+		}
+		break;
+	case V4L2_CID_PRIVATE_BLEND_SINRHI:
+		retval = hci_cmd(HCI_FM_GET_BLND_TBL_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to get blend table %d", retval);
+			goto end;
+		}
+		ctrl->value = radio->blend_tbl.scBlendSinrHi;
+		break;
+	case V4L2_CID_PRIVATE_BLEND_RMSSIHI:
+		retval = hci_cmd(HCI_FM_GET_BLND_TBL_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to get blend table %d", retval);
+			goto end;
+		}
+		ctrl->value = radio->blend_tbl.scBlendRmssiHi;
+		break;
+	default:
+		retval = -EINVAL;
+		break;
+	}
+
+end:
+	if (retval > 0)
+		retval = -EINVAL;
+	if (ctrl != NULL && retval < 0)
+		FMDERR("get control failed: %d, ret: %d\n", ctrl->id, retval);
+
+	return retval;
+}
+
+static int iris_vidioc_g_ext_ctrls(struct file *file, void *priv,
+			struct v4l2_ext_controls *ctrl)
+{
+	int retval = 0;
+	char *data = NULL;
+	struct iris_device *radio = video_get_drvdata(video_devdata(file));
+	struct hci_fm_def_data_rd_req default_data_rd;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		retval = -EINVAL;
+		goto end;
+	}
+
+	if ((ctrl == NULL) || (ctrl->count == 0)
+		|| (ctrl->controls == NULL)) {
+		FMDERR("%s, invalid v4l2 ctrl\n", __func__);
+		retval = -EINVAL;
+		goto end;
+	}
+
+	FMDBG("0x%x", ctrl->controls[0].id);
+	switch ((ctrl->controls[0]).id) {
+	case V4L2_CID_PRIVATE_IRIS_READ_DEFAULT:
+		data = (ctrl->controls[0]).string;
+		memset(&default_data_rd, 0, sizeof(default_data_rd));
+		if (copy_from_user(&default_data_rd.mode, data,
+					sizeof(default_data_rd))) {
+			retval = -EFAULT;
+			goto end;
+		}
+		retval = hci_def_data_read(&default_data_rd, radio->fm_hdev);
+		break;
+	default:
+		retval = -EINVAL;
+		break;
+	}
+
+end:
+	if (retval > 0)
+		retval = -EINVAL;
+
+	return retval;
+}
+
+static int iris_vidioc_s_ext_ctrls(struct file *file, void *priv,
+			struct v4l2_ext_controls *ctrl)
+{
+	int retval = 0;
+	size_t bytes_to_copy;
+	struct hci_fm_tx_ps tx_ps;
+	struct hci_fm_tx_rt tx_rt;
+	struct hci_fm_def_data_wr_req default_data;
+	struct hci_fm_set_cal_req_proc proc_cal_req;
+	struct hci_fm_set_spur_table_req spur_tbl_req;
+	char *spur_data;
+	char tmp_buf[2];
+
+	struct iris_device *radio = video_get_drvdata(video_devdata(file));
+	char *data = NULL;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null");
+		retval = -EINVAL;
+		goto end;
+	}
+
+	if ((ctrl == NULL) || (ctrl->count == 0)
+		|| (ctrl->controls == NULL)) {
+		FMDERR("%s, invalid v4l2 ctrl\n", __func__);
+		retval = -EINVAL;
+		goto end;
+	}
+
+	FMDBG("0x%x\n", ctrl->controls[0].id);
+	switch ((ctrl->controls[0]).id) {
+	case V4L2_CID_RDS_TX_PS_NAME:
+		FMDBG("In V4L2_CID_RDS_TX_PS_NAME\n");
+		/*Pass a sample PS string */
+
+		memset(tx_ps.ps_data, 0, MAX_PS_LENGTH);
+		bytes_to_copy = min_t(size_t, ctrl->controls[0].size,
+					MAX_PS_LENGTH);
+		data = (ctrl->controls[0]).string;
+
+		if (copy_from_user(tx_ps.ps_data,
+				data, bytes_to_copy)) {
+			FMDERR("%s: copy from user for tx ps name failed\n",
+				__func__);
+			retval = -EFAULT;
+			goto end;
+		} else {
+			tx_ps.ps_control =  0x01;
+			tx_ps.pi = radio->pi;
+			tx_ps.pty = radio->pty;
+			tx_ps.ps_repeatcount = radio->ps_repeatcount;
+			tx_ps.ps_num = (bytes_to_copy / PS_STRING_LEN);
+
+			retval = radio_hci_request(radio->fm_hdev,
+							hci_trans_ps_req,
+							(unsigned long)&tx_ps,
+							RADIO_HCI_TIMEOUT);
+		}
+		break;
+	case V4L2_CID_RDS_TX_RADIO_TEXT:
+		bytes_to_copy =
+		    min_t(size_t, (ctrl->controls[0]).size, MAX_RT_LENGTH);
+		data = (ctrl->controls[0]).string;
+
+		memset(tx_rt.rt_data, 0, MAX_RT_LENGTH);
+
+		if (copy_from_user(tx_rt.rt_data,
+				data, bytes_to_copy)) {
+			FMDERR("%s: copy from user for tx rt failed\n",
+				 __func__);
+			retval = -EFAULT;
+			goto end;
+		} else {
+			tx_rt.rt_control = 0x01;
+			tx_rt.pi = radio->pi;
+			tx_rt.pty = radio->pty;
+			tx_rt.rt_len = bytes_to_copy;
+
+			retval = radio_hci_request(radio->fm_hdev,
+							hci_trans_rt_req,
+							(unsigned long)&tx_rt,
+							RADIO_HCI_TIMEOUT);
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_WRITE_DEFAULT:
+		data = (ctrl->controls[0]).string;
+		memset(&default_data, 0, sizeof(default_data));
+		/*
+		 * Check if length of the 'FM Default Data' to be sent
+		 * is within the maximum  'FM Default Data' packet limit.
+		 * Max. 'FM Default Data' packet length is 251 bytes:
+		 *	1 byte    - XFR Mode
+		 *	1 byte    - length of the default data
+		 *	249 bytes - actual data to be configured
+		 */
+		if (ctrl->controls[0].size > (DEFAULT_DATA_SIZE + 2)) {
+			pr_err("%s: Default data buffer overflow\n", __func__);
+			retval = -EINVAL;
+			goto end;
+		}
+
+		/* copy only 'size' bytes of data as requested by user */
+		retval = copy_from_user(&default_data, data,
+			ctrl->controls[0].size);
+		if (retval > 0) {
+			FMDERR("Failed to copy %d bytes data\n", retval);
+			retval = -EFAULT;
+			goto end;
+		}
+		FMDBG("XFR Mode\t: 0x%x", default_data.mode);
+		FMDBG("XFR Data Length\t: %d\n", default_data.length);
+		/*
+		 * Check if the 'length' of the actual XFR data to be configured
+		 * is valid or not. Length of actual XFR data should be always
+		 * 2 bytes less than the total length of the 'FM Default Data'.
+		 * Length of 'FM Default Data' DEF_DATA_LEN: (1+1+XFR Data Size)
+		 * Length of 'Actual XFR Data' XFR_DATA_LEN: (DEF_DATA_LEN - 2)
+		 */
+		if (default_data.length != (ctrl->controls[0].size - 2)) {
+			FMDERR("Invalid 'length' parameter\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		retval = hci_def_data_write(&default_data, radio->fm_hdev);
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION:
+		data = (ctrl->controls[0]).string;
+		bytes_to_copy = (ctrl->controls[0]).size;
+		if (bytes_to_copy < PROCS_CALIB_SIZE) {
+			FMDERR("data is less than required size\n");
+			retval = -EFAULT;
+			goto end;
+		}
+		memset(proc_cal_req.data, 0, PROCS_CALIB_SIZE);
+		proc_cal_req.mode = PROCS_CALIB_MODE;
+		if (copy_from_user(&proc_cal_req.data[0],
+				data, sizeof(proc_cal_req.data))) {
+			retval = -EFAULT;
+			goto end;
+		}
+		retval = radio_hci_request(radio->fm_hdev,
+				hci_fm_set_cal_req_proc,
+				(unsigned long)&proc_cal_req,
+				 RADIO_HCI_TIMEOUT);
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SET_SPURTABLE:
+		memset(&spur_tbl_req, 0, sizeof(spur_tbl_req));
+		data = (ctrl->controls[0]).string;
+		if (copy_from_user(&bytes_to_copy, &((ctrl->controls[0]).size),
+					sizeof(bytes_to_copy))) {
+			retval = -EFAULT;
+			goto end;
+		}
+		if (copy_from_user(&tmp_buf[0], &data[0],
+					sizeof(tmp_buf))) {
+			retval = -EFAULT;
+			goto end;
+		}
+		spur_tbl_req.mode = tmp_buf[0];
+		spur_tbl_req.no_of_freqs_entries = tmp_buf[1];
+
+		if (((spur_tbl_req.no_of_freqs_entries * SPUR_DATA_LEN) !=
+					bytes_to_copy - 2) ||
+		    ((spur_tbl_req.no_of_freqs_entries * SPUR_DATA_LEN) >
+					2 * FM_SPUR_TBL_SIZE)) {
+			FMDERR("Invalid data len: data[1] = %d, bytes = %zu\n",
+				spur_tbl_req.no_of_freqs_entries,
+				bytes_to_copy);
+			retval = -EINVAL;
+			goto end;
+		}
+		spur_data =
+		    kmalloc((spur_tbl_req.no_of_freqs_entries * SPUR_DATA_LEN)
+							+ 2, GFP_ATOMIC);
+		if (!spur_data) {
+			retval = -EFAULT;
+			goto end;
+		}
+		if (copy_from_user(spur_data,
+				&data[2], (bytes_to_copy - 2))) {
+			kfree(spur_data);
+			retval = -EFAULT;
+			goto end;
+		}
+
+		if (spur_tbl_req.no_of_freqs_entries <= ENTRIES_EACH_CMD) {
+			memcpy(&spur_tbl_req.spur_data[0], spur_data,
+				(spur_tbl_req.no_of_freqs_entries *
+							SPUR_DATA_LEN));
+			retval = radio_hci_request(radio->fm_hdev,
+					hci_fm_set_spur_tbl_req,
+					(unsigned long)&spur_tbl_req,
+					RADIO_HCI_TIMEOUT);
+		} else {
+			memcpy(&spur_tbl_req.spur_data[0], spur_data,
+				(ENTRIES_EACH_CMD * SPUR_DATA_LEN));
+			retval = radio_hci_request(radio->fm_hdev,
+					hci_fm_set_spur_tbl_req,
+					(unsigned long)&spur_tbl_req,
+					RADIO_HCI_TIMEOUT);
+			if (retval < 0) {
+				FMDERR("Spur command failed to execute\n");
+				kfree(spur_data);
+				goto end;
+			}
+			spur_tbl_req.mode = 0x02;/* 02-Continue mode */
+			spur_tbl_req.no_of_freqs_entries =
+				spur_tbl_req.no_of_freqs_entries
+					- ENTRIES_EACH_CMD;
+			memcpy(&spur_tbl_req.spur_data[0],
+				&spur_data[ENTRIES_EACH_CMD * SPUR_DATA_LEN],
+			(spur_tbl_req.no_of_freqs_entries * SPUR_DATA_LEN));
+			retval = radio_hci_request(radio->fm_hdev,
+					hci_fm_set_spur_tbl_req,
+					(unsigned long)&spur_tbl_req,
+					RADIO_HCI_TIMEOUT);
+		}
+		kfree(spur_data);
+		break;
+	default:
+		FMDBG("Shouldn't reach here\n");
+		retval = -EINVAL;
+		goto end;
+	}
+
+end:
+	if (retval > 0)
+		retval = -EINVAL;
+
+	return retval;
+}
+
+static int iris_vidioc_s_ctrl(struct file *file, void *priv,
+		struct v4l2_control *ctrl)
+{
+	struct iris_device *radio = video_get_drvdata(video_devdata(file));
+	int retval = 0;
+	unsigned int rds_grps_proc = 0;
+	__u8 temp_val = 0;
+	int saved_val;
+	unsigned long arg = 0;
+	struct hci_fm_tx_ps tx_ps = {0};
+	struct hci_fm_tx_rt tx_rt = {0};
+	struct hci_fm_def_data_rd_req rd;
+	struct hci_fm_def_data_wr_req wrd;
+	char sinr_th, sinr;
+	__u8 intf_det_low_th, intf_det_high_th, intf_det_out;
+	unsigned int spur_freq;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		retval = -EINVAL;
+		goto end;
+	}
+
+	if (ctrl == NULL) {
+		FMDERR("%s, v4l2 ctrl is null\n", __func__);
+		retval = -EINVAL;
+		goto end;
+	}
+
+	FMDBG("id 0x%x", ctrl->id);
+	switch (ctrl->id) {
+	case V4L2_CID_PRIVATE_IRIS_TX_TONE:
+		if (!is_valid_tone(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: tone value is not valid\n", __func__);
+			goto end;
+		}
+		saved_val = radio->tone_freq;
+		radio->tone_freq = ctrl->value;
+		retval = radio_hci_request(radio->fm_hdev,
+				hci_fm_tone_generator, arg,
+				RADIO_HCI_TIMEOUT);
+		if (retval < 0) {
+			FMDERR("Error while setting the tone %d\n", retval);
+			radio->tone_freq = saved_val;
+		}
+		break;
+	case V4L2_CID_AUDIO_VOLUME:
+		break;
+	case V4L2_CID_AUDIO_MUTE:
+		if (!is_valid_hard_mute(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: hard mute value is not valid\n", __func__);
+			goto end;
+		}
+		saved_val = radio->mute_mode.hard_mute;
+		radio->mute_mode.hard_mute = ctrl->value;
+		retval = hci_set_fm_mute_mode(
+				&radio->mute_mode,
+				radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Error while set FM hard mute %d\n",
+				retval);
+			radio->mute_mode.hard_mute = saved_val;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SRCHMODE:
+		if (is_valid_srch_mode(ctrl->value)) {
+			radio->g_search_mode = ctrl->value;
+		} else {
+			FMDERR("%s: srch mode is not valid\n", __func__);
+			retval = -EINVAL;
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SCANDWELL:
+		if (is_valid_scan_dwell_prd(ctrl->value)) {
+			radio->g_scan_time = ctrl->value;
+		} else {
+			FMDERR("%s: scandwell period is not valid\n", __func__);
+			retval = -EINVAL;
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SRCHON:
+		iris_search(radio, ctrl->value, SRCH_DIR_UP);
+		break;
+	case V4L2_CID_PRIVATE_IRIS_STATE:
+		switch (ctrl->value) {
+		case FM_RECV:
+			if (radio->mode != FM_OFF) {
+				FMDERR("FM mode is not off %d\n", radio->mode);
+				retval = -EINVAL;
+				goto end;
+			}
+			if (is_enable_rx_possible(radio) != 0) {
+				FMDERR("%s: fm is not in proper state\n",
+					 __func__);
+				retval = -EINVAL;
+				goto end;
+			}
+			radio->mode = FM_RECV_TURNING_ON;
+			retval = hci_cmd(HCI_FM_ENABLE_RECV_CMD,
+							 radio->fm_hdev);
+			if (retval < 0) {
+				FMDERR("Enabling RECV FM fail %d\n", retval);
+				radio->mode = FM_OFF;
+				goto end;
+			} else {
+				retval = initialise_recv(radio);
+				if (retval < 0) {
+					FMDERR("Error while initialising\n");
+					FMDERR("radio %d\n", retval);
+					hci_cmd(HCI_FM_DISABLE_RECV_CMD,
+							radio->fm_hdev);
+					radio->mode = FM_OFF;
+					goto end;
+				}
+			}
+			if (radio->mode == FM_RECV_TURNING_ON) {
+				radio->mode = FM_RECV;
+				iris_q_event(radio, IRIS_EVT_RADIO_READY);
+			}
+			break;
+		case FM_TRANS:
+			if (is_enable_tx_possible(radio) != 0) {
+				retval = -EINVAL;
+				goto end;
+			}
+			radio->mode = FM_TRANS_TURNING_ON;
+			retval = hci_cmd(HCI_FM_ENABLE_TRANS_CMD,
+							 radio->fm_hdev);
+			if (retval < 0) {
+				FMDERR("Enabling TRANS FM fail %d\n", retval);
+				radio->mode = FM_OFF;
+				goto end;
+			} else {
+				retval = initialise_trans(radio);
+				if (retval < 0) {
+					FMDERR("Error while initialising\n");
+					FMDERR("radio %d\n", retval);
+					hci_cmd(HCI_FM_DISABLE_TRANS_CMD,
+								radio->fm_hdev);
+					radio->mode = FM_OFF;
+					goto end;
+				}
+			}
+			if (radio->mode == FM_TRANS_TURNING_ON) {
+				radio->mode = FM_TRANS;
+				iris_q_event(radio, IRIS_EVT_RADIO_READY);
+			}
+			break;
+		case FM_OFF:
+			radio->spur_table_size = 0;
+			switch (radio->mode) {
+			case FM_RECV:
+				radio->mode = FM_TURNING_OFF;
+				retval = hci_cmd(HCI_FM_DISABLE_RECV_CMD,
+						radio->fm_hdev);
+				if (retval < 0) {
+					FMDERR("Err on disable recv FM\n");
+					FMDERR("%d\n", retval);
+					radio->mode = FM_RECV;
+					goto end;
+				}
+				break;
+			case FM_TRANS:
+				radio->mode = FM_TURNING_OFF;
+				retval = hci_cmd(HCI_FM_DISABLE_TRANS_CMD,
+						radio->fm_hdev);
+
+				if (retval < 0) {
+					FMDERR("Err disabling trans FM\n");
+					FMDERR("%d\n", retval);
+					radio->mode = FM_TRANS;
+					goto end;
+				}
+				break;
+			default:
+				retval = -EINVAL;
+			}
+			break;
+		default:
+			retval = -EINVAL;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_REGION:
+		if (radio->mode == FM_RECV) {
+			retval = iris_recv_set_region(radio, ctrl->value);
+		} else {
+			if (radio->mode == FM_TRANS) {
+				retval = iris_trans_set_region(radio,
+						ctrl->value);
+			} else {
+				FMDERR("%s: fm is not in proper state\n",
+					__func__);
+				retval = -EINVAL;
+				goto end;
+			}
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SIGNAL_TH:
+		if (!is_valid_sig_th(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: sig threshold is not valid\n", __func__);
+			goto end;
+		}
+		temp_val = ctrl->value;
+		retval = hci_fm_set_signal_threshold(
+				&temp_val,
+				radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Error while setting signal threshold\n");
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SRCH_PTY:
+		if (is_valid_pty(ctrl->value)) {
+			radio->srch_rds.srch_pty = ctrl->value;
+			radio->srch_st_list.srch_pty = ctrl->value;
+		} else {
+			FMDERR("%s: pty is not valid\n", __func__);
+			retval = -EINVAL;
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SRCH_PI:
+		if (is_valid_pi(ctrl->value)) {
+			radio->srch_rds.srch_pi = ctrl->value;
+		} else {
+			retval = -EINVAL;
+			FMDERR("%s: Pi is not valid\n", __func__);
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SRCH_CNT:
+		if (is_valid_srch_station_cnt(ctrl->value)) {
+			radio->srch_st_list.srch_list_max = ctrl->value;
+		} else {
+			retval = -EINVAL;
+			FMDERR("%s: srch station count is not valid\n",
+				__func__);
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SPACING:
+		if (!is_valid_chan_spacing(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: channel spacing is not valid\n", __func__);
+			goto end;
+		}
+		if (radio->mode == FM_RECV) {
+			saved_val = radio->recv_conf.ch_spacing;
+			radio->recv_conf.ch_spacing = ctrl->value;
+			retval = hci_set_fm_recv_conf(
+					&radio->recv_conf,
+						radio->fm_hdev);
+			if (retval < 0) {
+				FMDERR("Error in setting channel spacing\n");
+				radio->recv_conf.ch_spacing = saved_val;
+				goto end;
+			}
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_EMPHASIS:
+		if (!is_valid_emphasis(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s, emphasis is not valid\n", __func__);
+			goto end;
+		}
+		switch (radio->mode) {
+		case FM_RECV:
+			saved_val = radio->recv_conf.emphasis;
+			radio->recv_conf.emphasis = ctrl->value;
+			retval = hci_set_fm_recv_conf(
+					&radio->recv_conf,
+						radio->fm_hdev);
+			if (retval < 0) {
+				FMDERR("Error in setting emphasis\n");
+				radio->recv_conf.emphasis = saved_val;
+				goto end;
+			}
+			break;
+		case FM_TRANS:
+			saved_val = radio->trans_conf.emphasis;
+			radio->trans_conf.emphasis = ctrl->value;
+			retval = hci_set_fm_trans_conf(
+					&radio->trans_conf,
+						radio->fm_hdev);
+			if (retval < 0) {
+				FMDERR("Error in setting emphasis\n");
+				radio->trans_conf.emphasis = saved_val;
+				goto end;
+			}
+			break;
+		default:
+			retval = -EINVAL;
+			FMDERR("FM mode is unknown %d\n", radio->mode);
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RDS_STD:
+		if (!is_valid_rds_std(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: rds std is not valid\n", __func__);
+			goto end;
+		}
+		switch (radio->mode) {
+		case FM_RECV:
+			saved_val = radio->recv_conf.rds_std;
+			radio->recv_conf.rds_std = ctrl->value;
+			retval = hci_set_fm_recv_conf(
+					&radio->recv_conf,
+						radio->fm_hdev);
+			if (retval < 0) {
+				FMDERR("Error in rds_std\n");
+				radio->recv_conf.rds_std = saved_val;
+				goto end;
+			}
+			break;
+		case FM_TRANS:
+			saved_val = radio->trans_conf.rds_std;
+			radio->trans_conf.rds_std = ctrl->value;
+			retval = hci_set_fm_trans_conf(
+					&radio->trans_conf,
+						radio->fm_hdev);
+			if (retval < 0) {
+				FMDERR("Error in rds_Std\n");
+				radio->trans_conf.rds_std = saved_val;
+				goto end;
+			}
+			break;
+		default:
+			retval = -EINVAL;
+			FMDERR("%s: fm is not in proper state\n", __func__);
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RDSON:
+		if (!is_valid_rds_std(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: rds std is not valid\n", __func__);
+			goto end;
+		}
+		switch (radio->mode) {
+		case FM_RECV:
+			saved_val = radio->recv_conf.rds_std;
+			radio->recv_conf.rds_std = ctrl->value;
+			retval = hci_set_fm_recv_conf(
+					&radio->recv_conf,
+						radio->fm_hdev);
+			if (retval < 0) {
+				FMDERR("Error in rds_std\n");
+				radio->recv_conf.rds_std = saved_val;
+				goto end;
+			}
+			break;
+		case FM_TRANS:
+			saved_val = radio->trans_conf.rds_std;
+			radio->trans_conf.rds_std = ctrl->value;
+			retval = hci_set_fm_trans_conf(
+					&radio->trans_conf,
+						radio->fm_hdev);
+			if (retval < 0) {
+				FMDERR("Error in rds_Std\n");
+				radio->trans_conf.rds_std = saved_val;
+				goto end;
+			}
+			break;
+		default:
+			retval = -EINVAL;
+			FMDERR("%s: fm is not in proper state\n", __func__);
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RDSGROUP_MASK:
+		saved_val = radio->rds_grp.rds_grp_enable_mask;
+		grp_mask = (grp_mask | oda_agt | ctrl->value);
+		radio->rds_grp.rds_grp_enable_mask = grp_mask;
+		radio->rds_grp.rds_buf_size = 1;
+		radio->rds_grp.en_rds_change_filter = 0;
+		retval = hci_fm_rds_grp(&radio->rds_grp, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("error in setting group mask\n");
+			radio->rds_grp.rds_grp_enable_mask = saved_val;
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RDSGROUP_PROC:
+		saved_val = radio->g_rds_grp_proc_ps;
+		radio->g_rds_grp_proc_ps |= ctrl->value;
+		retval = hci_fm_rds_grps_process(
+				&radio->g_rds_grp_proc_ps,
+				radio->fm_hdev);
+		if (retval < 0) {
+			radio->g_rds_grp_proc_ps = saved_val;
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RDSD_BUF:
+		radio->rds_grp.rds_buf_size = ctrl->value;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_PSALL:
+		saved_val = radio->g_rds_grp_proc_ps;
+		rds_grps_proc = (ctrl->value << RDS_PS_SIMPLE_OFFSET);
+		radio->g_rds_grp_proc_ps |= rds_grps_proc;
+		retval = hci_fm_rds_grps_process(
+				&radio->g_rds_grp_proc_ps,
+				radio->fm_hdev);
+		if (retval < 0) {
+			radio->g_rds_grp_proc_ps = saved_val;
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_AF_JUMP:
+		saved_val = radio->g_rds_grp_proc_ps;
+		/*Clear the current AF jump settings*/
+		radio->g_rds_grp_proc_ps &= ~(1 << RDS_AF_JUMP_OFFSET);
+		radio->af_jump_bit = ctrl->value;
+		rds_grps_proc = 0x00;
+		rds_grps_proc = (ctrl->value << RDS_AF_JUMP_OFFSET);
+		radio->g_rds_grp_proc_ps |= rds_grps_proc;
+		retval = hci_fm_rds_grps_process(
+				&radio->g_rds_grp_proc_ps,
+				radio->fm_hdev);
+		if (retval < 0) {
+			radio->g_rds_grp_proc_ps = saved_val;
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_LP_MODE:
+		set_low_power_mode(radio, ctrl->value);
+		break;
+	case V4L2_CID_PRIVATE_IRIS_ANTENNA:
+		if (!is_valid_antenna(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: antenna type is not valid\n", __func__);
+			goto end;
+		}
+		temp_val = ctrl->value;
+		retval = hci_fm_set_antenna(&temp_val, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Set Antenna failed retval = %x\n", retval);
+			goto end;
+		}
+		radio->g_antenna =  ctrl->value;
+		break;
+	case V4L2_CID_RDS_TX_PTY:
+		if (is_valid_pty(ctrl->value)) {
+			radio->pty = ctrl->value;
+		} else {
+			retval = -EINVAL;
+			FMDERR("%s: pty is not valid\n", __func__);
+			goto end;
+		}
+		break;
+	case V4L2_CID_RDS_TX_PI:
+		if (is_valid_pi(ctrl->value)) {
+			radio->pi = ctrl->value;
+		} else {
+			retval = -EINVAL;
+			FMDERR("%s: pi is not valid\n", __func__);
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_STOP_RDS_TX_PS_NAME:
+		tx_ps.ps_control =  0x00;
+		retval = radio_hci_request(radio->fm_hdev, hci_trans_ps_req,
+				(unsigned long)&tx_ps, RADIO_HCI_TIMEOUT);
+		break;
+	case V4L2_CID_PRIVATE_IRIS_STOP_RDS_TX_RT:
+		tx_rt.rt_control =  0x00;
+		retval = radio_hci_request(radio->fm_hdev, hci_trans_rt_req,
+				(unsigned long)&tx_rt, RADIO_HCI_TIMEOUT);
+		break;
+	case V4L2_CID_PRIVATE_IRIS_TX_SETPSREPEATCOUNT:
+		if (is_valid_ps_repeat_cnt(ctrl->value)) {
+			radio->ps_repeatcount = ctrl->value;
+		} else {
+			retval = -EINVAL;
+			FMDERR("%s: ps repeat count is not valid\n", __func__);
+			goto end;
+		}
+		break;
+	case V4L2_CID_TUNE_POWER_LEVEL:
+		if (ctrl->value > FM_TX_PWR_LVL_MAX)
+			ctrl->value = FM_TX_PWR_LVL_MAX;
+		if (ctrl->value < FM_TX_PWR_LVL_0)
+			ctrl->value = FM_TX_PWR_LVL_0;
+		rd.mode = FM_TX_PHY_CFG_MODE;
+		rd.length = FM_TX_PHY_CFG_LEN;
+		rd.param_len = 0x00;
+		rd.param = 0x00;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Default data read failed for PHY_CFG %d\n",
+				retval);
+			goto end;
+		}
+		memset(&wrd, 0, sizeof(wrd));
+		wrd.mode = FM_TX_PHY_CFG_MODE;
+		wrd.length = FM_TX_PHY_CFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+					radio->default_data.ret_data_len);
+		wrd.data[FM_TX_PWR_GAIN_OFFSET] =
+				(ctrl->value) * FM_TX_PWR_LVL_STEP_SIZE;
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("Default write failed for PHY_TXGAIN %d\n",
+				retval);
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SOFT_MUTE:
+		if (!is_valid_soft_mute(ctrl->value)) {
+			retval = -EINVAL;
+			FMDERR("%s: soft mute is not valid\n", __func__);
+			goto end;
+		}
+		saved_val = radio->mute_mode.soft_mute;
+		radio->mute_mode.soft_mute = ctrl->value;
+		retval = hci_set_fm_mute_mode(
+				&radio->mute_mode,
+				radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Error while setting FM soft mute %d\n",
+				retval);
+			radio->mute_mode.soft_mute = saved_val;
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_ADDR:
+		radio->riva_data_req.cmd_params.start_addr = ctrl->value;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RIVA_ACCS_LEN:
+		if (is_valid_peek_len(ctrl->value)) {
+			radio->riva_data_req.cmd_params.length = ctrl->value;
+		} else {
+			retval = -EINVAL;
+			FMDERR("%s: riva access len is not valid\n", __func__);
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RIVA_POKE:
+		if (radio->riva_data_req.cmd_params.length <=
+		    MAX_RIVA_PEEK_RSP_SIZE) {
+#ifdef CONFIG_COMPAT
+			retval = copy_from_user(
+					radio->riva_data_req.data,
+					(void *)(__s64)ctrl->value,
+					radio->riva_data_req.cmd_params.length);
+#else
+			retval = copy_from_user(
+					radio->riva_data_req.data,
+					(void *)ctrl->value,
+					radio->riva_data_req.cmd_params.length);
+#endif
+			if (retval != 0) {
+				retval = -retval;
+				goto end;
+			}
+			radio->riva_data_req.cmd_params.subopcode =
+						RIVA_POKE_OPCODE;
+			retval = hci_poke_data(
+					&radio->riva_data_req,
+					radio->fm_hdev);
+		} else {
+			FMDERR("Can not copy into driver buffer\n");
+			retval = -EINVAL;
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SSBI_ACCS_ADDR:
+		radio->ssbi_data_accs.start_addr = ctrl->value;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SSBI_POKE:
+		radio->ssbi_data_accs.data = ctrl->value;
+		retval = hci_ssbi_poke_reg(&radio->ssbi_data_accs,
+								radio->fm_hdev);
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RIVA_PEEK:
+		radio->riva_data_req.cmd_params.subopcode = RIVA_PEEK_OPCODE;
+		ctrl->value = hci_peek_data(&radio->riva_data_req.cmd_params,
+						radio->fm_hdev);
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SSBI_PEEK:
+		radio->ssbi_peek_reg.start_address = ctrl->value;
+		hci_ssbi_peek_reg(&radio->ssbi_peek_reg, radio->fm_hdev);
+		break;
+	case V4L2_CID_PRIVATE_IRIS_RDS_GRP_COUNTERS:
+		if (is_valid_reset_cntr(ctrl->value)) {
+			temp_val = ctrl->value;
+			hci_read_grp_counters(&temp_val, radio->fm_hdev);
+		} else {
+			FMDERR("%s: reset counter value is not valid\n",
+				__func__);
+			retval = -EINVAL;
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_IRIS_HLSI:
+		if (!is_valid_hlsi(ctrl->value)) {
+			FMDERR("%s: hlsi value is not valid\n", __func__);
+			retval = -EINVAL;
+			goto end;
+		}
+		retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD,
+						radio->fm_hdev);
+		if (retval)
+			goto end;
+		saved_val = radio->recv_conf.hlsi;
+		radio->recv_conf.hlsi = ctrl->value;
+		retval = hci_set_fm_recv_conf(
+					&radio->recv_conf,
+						radio->fm_hdev);
+		if (retval < 0)
+			radio->recv_conf.hlsi = saved_val;
+		break;
+	case V4L2_CID_PRIVATE_IRIS_SET_NOTCH_FILTER:
+		if (is_valid_notch_filter(ctrl->value)) {
+			temp_val = ctrl->value;
+			retval = hci_set_notch_filter(&temp_val,
+							radio->fm_hdev);
+		} else {
+			FMDERR("%s: notch filter is not valid\n", __func__);
+			retval = -EINVAL;
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_INTF_HIGH_THRESHOLD:
+		if (!is_valid_intf_det_hgh_th(ctrl->value)) {
+			FMDERR("%s: intf high threshold is not valid\n",
+				__func__);
+			retval = -EINVAL;
+			goto end;
+		}
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Fail to get chnl det thresholds %d\n", retval);
+			goto end;
+		}
+		saved_val = radio->ch_det_threshold.high_th;
+		radio->ch_det_threshold.high_th = ctrl->value;
+		retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
+							 radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to set High det threshold %d\n", retval);
+			radio->ch_det_threshold.high_th = saved_val;
+			goto end;
+		}
+		break;
+
+	case V4L2_CID_PRIVATE_INTF_LOW_THRESHOLD:
+		if (!is_valid_intf_det_low_th(ctrl->value)) {
+			FMDERR("%s: intf det low threshold is not valid\n",
+				__func__);
+			retval = -EINVAL;
+			goto end;
+		}
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Fail to get chnl det thresholds %d\n", retval);
+			goto end;
+		}
+		saved_val = radio->ch_det_threshold.low_th;
+		radio->ch_det_threshold.low_th = ctrl->value;
+		retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
+							 radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Fail to Set Low det threshold %d\n", retval);
+			radio->ch_det_threshold.low_th = saved_val;
+			goto end;
+		}
+		break;
+
+	case V4L2_CID_PRIVATE_SINR_THRESHOLD:
+		if (!is_valid_sinr_th(ctrl->value)) {
+			FMDERR("%s: sinr threshold is not valid\n", __func__);
+			retval = -EINVAL;
+			goto end;
+		}
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Fail to get chnl det thresholds %d\n", retval);
+			goto end;
+		}
+		saved_val = radio->ch_det_threshold.sinr;
+		radio->ch_det_threshold.sinr = ctrl->value;
+		retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
+							 radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Fail to set SINR threshold %d\n", retval);
+			radio->ch_det_threshold.sinr = saved_val;
+			goto end;
+		}
+		break;
+
+	case V4L2_CID_PRIVATE_SINR_SAMPLES:
+		if (!is_valid_sinr_samples(ctrl->value)) {
+			FMDERR("%s: sinr samples count is not valid\n",
+				__func__);
+			retval = -EINVAL;
+			goto end;
+		}
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Fail to get chnl det thresholds %d\n", retval);
+			goto end;
+		}
+		saved_val = radio->ch_det_threshold.sinr_samples;
+		radio->ch_det_threshold.sinr_samples = ctrl->value;
+		retval = hci_set_ch_det_thresholds_req(&radio->ch_det_threshold,
+							 radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Fail to set SINR samples %d\n", retval);
+			radio->ch_det_threshold.sinr_samples = saved_val;
+			goto end;
+		}
+		break;
+
+	case V4L2_CID_PRIVATE_IRIS_SRCH_ALGORITHM:
+	case V4L2_CID_PRIVATE_IRIS_SET_AUDIO_PATH:
+		/*
+		 * These private controls are place holders to keep the
+		 * driver compatible with changes done in the frameworks
+		 * which are specific to TAVARUA.
+		 */
+		retval = 0;
+		break;
+	case V4L2_CID_PRIVATE_SPUR_FREQ:
+		if (radio->spur_table_size >= MAX_SPUR_FREQ_LIMIT) {
+			FMDERR("%s: Spur Table Full\n", __func__);
+			retval = -1;
+		} else
+			radio->spur_data.freq[radio->spur_table_size] =
+				ctrl->value;
+		break;
+	case V4L2_CID_PRIVATE_SPUR_FREQ_RMSSI:
+		if (radio->spur_table_size >= MAX_SPUR_FREQ_LIMIT) {
+			FMDERR("%s: Spur Table Full\n", __func__);
+			retval = -1;
+		} else
+			radio->spur_data.rmssi[radio->spur_table_size] =
+				ctrl->value;
+		break;
+	case V4L2_CID_PRIVATE_SPUR_SELECTION:
+		if (radio->spur_table_size >= MAX_SPUR_FREQ_LIMIT) {
+			FMDERR("%s: Spur Table Full\n", __func__);
+			retval = -1;
+		} else {
+			radio->spur_data.enable[radio->spur_table_size] =
+				ctrl->value;
+			radio->spur_table_size++;
+		}
+		break;
+	case V4L2_CID_PRIVATE_UPDATE_SPUR_TABLE:
+		update_spur_table(radio);
+		break;
+	case V4L2_CID_PRIVATE_VALID_CHANNEL:
+		retval = hci_cmd(HCI_FM_GET_DET_CH_TH_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("%s: Failed to determine channel validity\n",
+				__func__);
+			goto end;
+		} else {
+			sinr_th = radio->ch_det_threshold.sinr;
+			intf_det_low_th = radio->ch_det_threshold.low_th;
+			intf_det_high_th = radio->ch_det_threshold.high_th;
+		}
+		if (!is_valid_sinr_th(sinr_th) ||
+			!is_valid_intf_det_low_th(intf_det_low_th) ||
+			!is_valid_intf_det_hgh_th(intf_det_high_th)) {
+			retval = -EINVAL;
+			goto end;
+		}
+		retval = hci_cmd(HCI_FM_GET_STATION_PARAM_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("%s: Failed to determine channel validity\n",
+				__func__);
+			goto end;
+		} else
+			sinr = radio->fm_st_rsp.station_rsp.sinr;
+
+		retval = hci_cmd(HCI_FM_STATION_DBG_PARAM_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("%s: Failed to determine channel validity\n",
+				 __func__);
+			goto end;
+		} else
+			intf_det_out = radio->st_dbg_param.in_det_out;
+
+		if ((sinr >= sinr_th) && (intf_det_out >= intf_det_low_th) &&
+			(intf_det_out <= intf_det_high_th))
+			radio->is_station_valid = VALID_CHANNEL;
+		else
+			radio->is_station_valid = INVALID_CHANNEL;
+		break;
+	case V4L2_CID_PRIVATE_AF_RMSSI_TH:
+		rd.mode = FM_RDS_CNFG_MODE;
+		rd.length = FM_RDS_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x\n", retval);
+			goto end;
+		}
+		wrd.mode = FM_RDS_CNFG_MODE;
+		wrd.length = FM_RDS_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[AF_RMSSI_TH_LSB_OFFSET] = ((ctrl->value) & 255);
+		wrd.data[AF_RMSSI_TH_MSB_OFFSET] = ((ctrl->value) >> 8);
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set AF jump RMSSI threshold failed\n");
+		break;
+	case V4L2_CID_PRIVATE_AF_RMSSI_SAMPLES:
+		rd.mode = FM_RDS_CNFG_MODE;
+		rd.length = FM_RDS_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x\n", retval);
+			goto end;
+		}
+		wrd.mode = FM_RDS_CNFG_MODE;
+		wrd.length = FM_RDS_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[AF_RMSSI_SAMPLES_OFFSET] = ctrl->value;
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set AF jump RMSSI Samples failed\n");
+		break;
+	case V4L2_CID_PRIVATE_GOOD_CH_RMSSI_TH:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x\n", retval);
+			goto end;
+		}
+		wrd.mode = FM_RX_CONFG_MODE;
+		wrd.length = FM_RX_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[GD_CH_RMSSI_TH_OFFSET] = ctrl->value;
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set good channel RMSSI th failed\n");
+		break;
+	case V4L2_CID_PRIVATE_SRCHALGOTYPE:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x\n", retval);
+			goto end;
+		}
+		wrd.mode = FM_RX_CONFG_MODE;
+		wrd.length = FM_RX_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[SRCH_ALGO_TYPE_OFFSET] = ctrl->value;
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set Search Algo Type failed\n");
+		break;
+	case V4L2_CID_PRIVATE_SINRFIRSTSTAGE:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x\n", retval);
+			goto end;
+		}
+		wrd.mode = FM_RX_CONFG_MODE;
+		wrd.length = FM_RX_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[SINRFIRSTSTAGE_OFFSET] = ctrl->value;
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set SINR First Stage failed\n");
+		break;
+	case V4L2_CID_PRIVATE_RMSSIFIRSTSTAGE:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x\n", retval);
+			goto end;
+		}
+		wrd.mode = FM_RX_CONFG_MODE;
+		wrd.length = FM_RX_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[RMSSIFIRSTSTAGE_OFFSET] = ctrl->value;
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set RMSSI First Stage failed\n");
+		break;
+	case V4L2_CID_PRIVATE_CF0TH12:
+		rd.mode = FM_RX_CONFG_MODE;
+		rd.length = FM_RX_CNFG_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed %x\n", retval);
+			goto end;
+		}
+		wrd.mode = FM_RX_CONFG_MODE;
+		wrd.length = FM_RX_CNFG_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[CF0TH12_BYTE1_OFFSET] = (ctrl->value & 255);
+		wrd.data[CF0TH12_BYTE2_OFFSET] = ((ctrl->value >> 8) & 255);
+		wrd.data[CF0TH12_BYTE3_OFFSET] = ((ctrl->value >> 16) & 255);
+		wrd.data[CF0TH12_BYTE4_OFFSET] = ((ctrl->value >> 24) & 255);
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set CF0 Threshold failed\n");
+		break;
+	case V4L2_CID_PRIVATE_RXREPEATCOUNT:
+		rd.mode = RDS_PS0_XFR_MODE;
+		rd.length = RDS_PS0_LEN;
+		rd.param_len = 0;
+		rd.param = 0;
+
+		retval = hci_def_data_read(&rd, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("default data read failed for PS0 %x\n", retval);
+			goto end;
+		}
+		wrd.mode = RDS_PS0_XFR_MODE;
+		wrd.length = RDS_PS0_LEN;
+		memcpy(&wrd.data, &radio->default_data.data,
+				radio->default_data.ret_data_len);
+		wrd.data[RX_REPEATE_BYTE_OFFSET] = ctrl->value;
+
+		retval = hci_def_data_write(&wrd, radio->fm_hdev);
+		if (retval < 0)
+			FMDERR("set RxRePeat count failed\n");
+		break;
+	case V4L2_CID_PRIVATE_IRIS_GET_SPUR_TBL:
+		spur_freq = ctrl->value;
+		retval = radio_hci_request(radio->fm_hdev,
+					hci_fm_get_spur_tbl_data,
+					(unsigned long)spur_freq,
+					RADIO_HCI_TIMEOUT);
+		if (retval < 0)
+			FMDERR("get Spur data failed\n");
+		break;
+	case V4L2_CID_PRIVATE_BLEND_SINRHI:
+		if (!is_valid_blend_value(ctrl->value)) {
+			FMDERR("%s: blend sinr count is not valid\n",
+				__func__);
+			retval = -EINVAL;
+			goto end;
+		}
+		retval = hci_cmd(HCI_FM_GET_BLND_TBL_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to get blend table %d\n", retval);
+			goto end;
+		}
+		radio->blend_tbl.scBlendSinrHi = ctrl->value;
+		retval = hci_set_blend_tbl_req(&radio->blend_tbl,
+					 radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to set blend table %d\n", retval);
+			goto end;
+		}
+		break;
+	case V4L2_CID_PRIVATE_BLEND_RMSSIHI:
+		if (!is_valid_blend_value(ctrl->value)) {
+			FMDERR("%s: blend rmssi count is not valid\n",
+				__func__);
+			retval = -EINVAL;
+			goto end;
+		}
+		retval = hci_cmd(HCI_FM_GET_BLND_TBL_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to get blend table %d\n", retval);
+			goto end;
+		}
+		radio->blend_tbl.scBlendRmssiHi = ctrl->value;
+		retval = hci_set_blend_tbl_req(&radio->blend_tbl,
+					 radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to set blend table %d\n", retval);
+			goto end;
+		}
+		break;
+	default:
+		retval = -EINVAL;
+		break;
+	}
+
+end:
+	if (retval > 0)
+		retval = -EINVAL;
+
+	return retval;
+}
+
+static int update_spur_table(struct iris_device *radio)
+{
+	struct hci_fm_def_data_wr_req default_data;
+	int len = 0, index = 0, offset = 0, i = 0;
+	int retval = 0, temp = 0, cnt = 0;
+
+	memset(&default_data, 0, sizeof(default_data));
+
+	/* Pass the mode of SPUR_CLK */
+	default_data.mode = CKK_SPUR;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+	temp = radio->spur_table_size;
+	for (cnt = 0; cnt < (temp / 5); cnt++) {
+		offset = 0;
+		/*
+		 * Program the spur entries in spur table in following order:
+		 *    Spur index
+		 *    Length of the spur data
+		 *    Spur Data:
+		 *        MSB of the spur frequency
+		 *        LSB of the spur frequency
+		 *        Enable/Disable the spur frequency
+		 *        RMSSI value of the spur frequency
+		 */
+		default_data.data[offset++] = ENTRY_0 + cnt;
+		for (i = 0; i < SPUR_ENTRIES_PER_ID; i++) {
+			default_data.data[offset++] = GET_FREQ(COMPUTE_SPUR(
+				radio->spur_data.freq[index]), 0);
+			default_data.data[offset++] = GET_FREQ(COMPUTE_SPUR(
+				radio->spur_data.freq[index]), 1);
+			default_data.data[offset++] =
+				radio->spur_data.enable[index];
+			default_data.data[offset++] =
+				radio->spur_data.rmssi[index];
+			index++;
+		}
+		len = (SPUR_ENTRIES_PER_ID * SPUR_DATA_SIZE);
+		default_data.length = (len + 1);
+		retval = hci_def_data_write(&default_data, radio->fm_hdev);
+		if (retval < 0) {
+			FMDBG("%s: Failed to configure entries for ID : %d\n",
+				__func__, default_data.data[0]);
+			return retval;
+		}
+	}
+
+	/* Compute balance SPUR frequencies to be programmed */
+	temp %= SPUR_ENTRIES_PER_ID;
+	if (temp > 0) {
+		offset = 0;
+		default_data.data[offset++] = (radio->spur_table_size / 5);
+		for (i = 0; i < temp; i++) {
+			default_data.data[offset++] = GET_FREQ(COMPUTE_SPUR(
+				radio->spur_data.freq[index]), 0);
+			default_data.data[offset++] = GET_FREQ(COMPUTE_SPUR(
+				radio->spur_data.freq[index]), 1);
+			default_data.data[offset++] =
+				radio->spur_data.enable[index];
+			default_data.data[offset++] =
+				radio->spur_data.rmssi[index];
+			index++;
+		}
+		len = (temp * SPUR_DATA_SIZE);
+		default_data.length = (len + 1);
+		retval = hci_def_data_write(&default_data, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("%s: Failed to configure entries for ID : %d\n",
+				__func__, default_data.data[0]);
+			return retval;
+		}
+	}
+
+	return retval;
+}
+
+static int iris_vidioc_g_tuner(struct file *file, void *priv,
+		struct v4l2_tuner *tuner)
+{
+	int retval;
+	struct iris_device *radio = video_get_drvdata(video_devdata(file));
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+	if (tuner == NULL) {
+		FMDERR("%s, tuner is null\n", __func__);
+		return -EINVAL;
+	}
+	if (tuner->index > 0) {
+		FMDERR("Invalid Tuner Index\n");
+		return -EINVAL;
+	}
+	if (radio->mode == FM_RECV) {
+		retval = hci_cmd(HCI_FM_GET_STATION_PARAM_CMD, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("Failed to Get station params\n");
+			return retval;
+		}
+		tuner->type = V4L2_TUNER_RADIO;
+		tuner->rangelow  =
+			radio->recv_conf.band_low_limit * TUNE_PARAM;
+		tuner->rangehigh =
+			radio->recv_conf.band_high_limit * TUNE_PARAM;
+		tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+		tuner->capability = V4L2_TUNER_CAP_LOW;
+		tuner->signal = radio->fm_st_rsp.station_rsp.rssi;
+		tuner->audmode = radio->fm_st_rsp.station_rsp.stereo_prg;
+		tuner->afc = 0;
+	} else if (radio->mode == FM_TRANS) {
+		retval = hci_cmd(HCI_FM_GET_TX_CONFIG, radio->fm_hdev);
+		if (retval < 0) {
+			FMDERR("get Tx config failed %d\n", retval);
+			return retval;
+		}
+		tuner->type = V4L2_TUNER_RADIO;
+		tuner->rangelow =
+			radio->trans_conf.band_low_limit * TUNE_PARAM;
+		tuner->rangehigh =
+			radio->trans_conf.band_high_limit * TUNE_PARAM;
+	} else
+		return -EINVAL;
+	return 0;
+}
+
+static int iris_vidioc_s_tuner(struct file *file, void *priv,
+		const struct v4l2_tuner *tuner)
+{
+	struct iris_device *radio = video_get_drvdata(video_devdata(file));
+	int retval = 0;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+
+	if (tuner == NULL) {
+		FMDERR("%s, tuner is null\n", __func__);
+		return -EINVAL;
+	}
+
+	if (tuner->index > 0)
+		return -EINVAL;
+
+	if (radio->mode == FM_RECV) {
+		radio->recv_conf.band_low_limit = tuner->rangelow / TUNE_PARAM;
+		radio->recv_conf.band_high_limit =
+			tuner->rangehigh / TUNE_PARAM;
+		if (tuner->audmode == V4L2_TUNER_MODE_MONO) {
+			radio->stereo_mode.stereo_mode = 0x01;
+			retval = hci_set_fm_stereo_mode(
+					&radio->stereo_mode,
+					radio->fm_hdev);
+		} else {
+			radio->stereo_mode.stereo_mode = 0x00;
+			retval = hci_set_fm_stereo_mode(
+					&radio->stereo_mode,
+					radio->fm_hdev);
+		}
+		if (retval < 0)
+			FMDERR(": set tuner failed with %d\n", retval);
+		return retval;
+	} else if (radio->mode == FM_TRANS) {
+		radio->trans_conf.band_low_limit = tuner->rangelow / TUNE_PARAM;
+		radio->trans_conf.band_high_limit =
+			tuner->rangehigh / TUNE_PARAM;
+	} else
+		return -EINVAL;
+
+	return retval;
+}
+
+static int iris_vidioc_g_frequency(struct file *file, void *priv,
+		struct v4l2_frequency *freq)
+{
+	struct iris_device *radio = video_get_drvdata(video_devdata(file));
+
+	if ((freq != NULL) && (radio != NULL)) {
+		freq->frequency =
+			radio->fm_st_rsp.station_rsp.station_freq * TUNE_PARAM;
+	} else
+		return -EINVAL;
+	return 0;
+}
+
+static int iris_vidioc_s_frequency(struct file *file, void *priv,
+					const struct v4l2_frequency *freq)
+{
+	struct iris_device  *radio = video_get_drvdata(video_devdata(file));
+	int retval = -1;
+	u32 f;
+
+	if (freq == NULL) {
+		FMDERR("%s, v4l2 freq is null\n", __func__);
+		return -EINVAL;
+	}
+	f = (freq->frequency / TUNE_PARAM);
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+	if (freq->type != V4L2_TUNER_RADIO)
+		return -EINVAL;
+
+	/* We turn off RDS prior to tuning to a new station.
+	 * because of a bug in SoC which prevents tuning
+	 * during RDS transmission.
+	 */
+	if (radio->mode == FM_TRANS
+		&& (radio->trans_conf.rds_std == 0 ||
+			radio->trans_conf.rds_std == 1)) {
+		radio->prev_trans_rds = radio->trans_conf.rds_std;
+		radio->trans_conf.rds_std = 2;
+		hci_set_fm_trans_conf(&radio->trans_conf,
+				radio->fm_hdev);
+	}
+
+	retval = iris_set_freq(radio, f);
+
+	if (radio->mode == FM_TRANS
+		 && radio->trans_conf.rds_std == 2
+			&& (radio->prev_trans_rds == 1
+				|| radio->prev_trans_rds == 0)) {
+		radio->trans_conf.rds_std = radio->prev_trans_rds;
+		hci_set_fm_trans_conf(&radio->trans_conf,
+				radio->fm_hdev);
+	}
+
+	if (retval < 0)
+		FMDERR(" set frequency failed with %d\n", retval);
+	return retval;
+}
+
+static int iris_fops_release(struct file *file)
+{
+	struct iris_device *radio = video_get_drvdata(video_devdata(file));
+	int retval = 0;
+
+	FMDBG("radio %pK", radio);
+
+	if (radio == NULL)
+		return -EINVAL;
+
+	FMDBG("state %d", radio->mode);
+	mutex_lock(&radio->lock);
+
+	if (radio->mode == FM_OFF)
+		goto end;
+
+	if (radio->mode == FM_RECV) {
+		radio->is_fm_closing = true;
+		radio->mode = FM_TURNING_OFF;
+		retval = hci_cmd_uninterruptible(HCI_FM_DISABLE_RECV_CMD,
+				radio->fm_hdev);
+		radio->mode = FM_OFF;
+		radio->is_fm_closing = false;
+	} else if (radio->mode == FM_TRANS) {
+		radio->is_fm_closing = true;
+		radio->mode = FM_TURNING_OFF;
+		retval = hci_cmd_uninterruptible(HCI_FM_DISABLE_TRANS_CMD,
+				radio->fm_hdev);
+		radio->mode = FM_OFF;
+		radio->is_fm_closing = false;
+	} else if (radio->mode == FM_CALIB) {
+		radio->mode = FM_OFF;
+		mutex_unlock(&radio->lock);
+		return retval;
+	}
+end:
+	FMDBG("mode %d", radio->mode);
+	mutex_lock(&fm_smd_enable);
+	if (radio->fm_hdev != NULL)
+		radio->fm_hdev->close_smd();
+	mutex_unlock(&fm_smd_enable);
+
+	mutex_unlock(&radio->lock);
+
+	if (retval < 0)
+		FMDERR("Err on disable FM %d\n", retval);
+
+	FMDBG("ret %d", retval);
+	return retval;
+}
+
+static int iris_vidioc_dqbuf(struct file *file, void *priv,
+				struct v4l2_buffer *buffer)
+{
+	struct iris_device  *radio = video_get_drvdata(video_devdata(file));
+	enum iris_buf_t buf_type = -1;
+	unsigned char buf_fifo[STD_BUF_SIZE] = {0};
+	struct kfifo *data_fifo = NULL;
+	unsigned char *buf = NULL;
+	unsigned int len = 0, retval = -1;
+
+	FMDBG("buffer %pK", buffer);
+
+	if ((radio == NULL) || (buffer == NULL)) {
+		FMDERR("radio/buffer is NULL\n");
+		return -ENXIO;
+	}
+	buf_type = buffer->index;
+	buf = (unsigned char *)buffer->m.userptr;
+	len = buffer->length;
+
+	if ((buf_type < IRIS_BUF_MAX) && (buf_type >= 0)) {
+		data_fifo = &radio->data_buf[buf_type];
+		if (buf_type == IRIS_BUF_EVENTS)
+			if (wait_event_interruptible(radio->event_queue,
+				kfifo_len(data_fifo)) < 0)
+				return -EINTR;
+	} else {
+		FMDERR("invalid buffer type\n");
+		return -EINVAL;
+	}
+	if (len <= STD_BUF_SIZE) {
+		buffer->bytesused = kfifo_out_locked(data_fifo, &buf_fifo[0],
+					len, &radio->buf_lock[buf_type]);
+	} else {
+		FMDERR("kfifo_out_locked can not use len more than 128\n");
+		return -EINVAL;
+	}
+	retval = copy_to_user(buf, &buf_fifo[0], buffer->bytesused);
+	if (retval > 0) {
+		FMDERR("Failed to copy %d bytes of data\n", retval);
+		return -EAGAIN;
+	}
+
+	return retval;
+}
+
+static int iris_vidioc_g_fmt_type_private(struct file *file, void *priv,
+						struct v4l2_format *f)
+{
+	return 0;
+
+}
+
+static int iris_vidioc_s_hw_freq_seek(struct file *file, void *priv,
+					const struct v4l2_hw_freq_seek *seek)
+{
+	struct iris_device *radio = video_get_drvdata(video_devdata(file));
+	int dir;
+
+	if (seek == NULL) {
+		FMDERR("%s, v4l2_hw_freq_seek is null\n", __func__);
+		return -EINVAL;
+	}
+	if (seek->seek_upward)
+		dir = SRCH_DIR_UP;
+	else
+		dir = SRCH_DIR_DOWN;
+	return iris_search(radio, CTRL_ON, dir);
+}
+
+static int iris_vidioc_querycap(struct file *file, void *priv,
+	struct v4l2_capability *capability)
+{
+	struct iris_device *radio;
+
+	FMDBG("caps %pK", capability);
+
+	radio = video_get_drvdata(video_devdata(file));
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+	if (capability == NULL) {
+		FMDERR("%s, capability struct is null\n", __func__);
+		return -EINVAL;
+	}
+	strlcpy(capability->driver, DRIVER_NAME, sizeof(capability->driver));
+	strlcpy(capability->card, DRIVER_CARD, sizeof(capability->card));
+
+	strlcpy(radio->g_cap.driver, DRIVER_NAME, sizeof(radio->g_cap.driver));
+	strlcpy(radio->g_cap.card, DRIVER_CARD, sizeof(radio->g_cap.card));
+
+	radio->g_cap.capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+	capability->capabilities = radio->g_cap.capabilities;
+	return 0;
+}
+
+static int initialise_recv(struct iris_device *radio)
+{
+	int retval;
+
+	FMDBG("radio %pK", radio);
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+
+	radio->mute_mode.soft_mute = CTRL_ON;
+	retval = hci_set_fm_mute_mode(&radio->mute_mode,
+					radio->fm_hdev);
+
+	if (retval < 0) {
+		FMDERR("Failed to enable Smute\n");
+		return retval;
+	}
+
+	radio->stereo_mode.stereo_mode = CTRL_OFF;
+	radio->stereo_mode.sig_blend = sig_blend;
+	radio->stereo_mode.intf_blend = CTRL_ON;
+	radio->stereo_mode.most_switch = CTRL_ON;
+	retval = hci_set_fm_stereo_mode(&radio->stereo_mode,
+						radio->fm_hdev);
+
+	if (retval < 0) {
+		FMDERR("Failed to set stereo mode\n");
+		return retval;
+	}
+
+	radio->event_mask = SIG_LEVEL_INTR | RDS_SYNC_INTR | AUDIO_CTRL_INTR;
+	retval = hci_conf_event_mask(&radio->event_mask, radio->fm_hdev);
+	if (retval < 0) {
+		FMDERR("Enable Async events failed\n");
+		return retval;
+	}
+
+	retval = hci_cmd(HCI_FM_GET_RECV_CONF_CMD, radio->fm_hdev);
+	if (retval < 0)
+		FMDERR("Failed to get the Recv Config\n");
+	return retval;
+}
+
+static int initialise_trans(struct iris_device *radio)
+{
+
+	int retval;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null");
+		return -EINVAL;
+	}
+
+	retval = hci_cmd(HCI_FM_GET_TX_CONFIG, radio->fm_hdev);
+	if (retval < 0)
+		FMDERR("get frequency failed %d\n", retval);
+
+	return retval;
+}
+
+static int is_enable_rx_possible(struct iris_device *radio)
+{
+	int retval = 1;
+
+	if (unlikely(radio == NULL)) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+
+	if (radio->mode == FM_OFF || radio->mode == FM_RECV)
+		retval = 0;
+
+	return retval;
+}
+
+static int is_enable_tx_possible(struct iris_device *radio)
+{
+	int retval = 1;
+
+	if (radio->mode == FM_OFF || radio->mode == FM_TRANS)
+		retval = 0;
+
+	return retval;
+}
+
+static const struct v4l2_ioctl_ops iris_ioctl_ops = {
+	.vidioc_querycap              = iris_vidioc_querycap,
+	.vidioc_queryctrl             = iris_vidioc_queryctrl,
+	.vidioc_g_ctrl                = iris_vidioc_g_ctrl,
+	.vidioc_s_ctrl                = iris_vidioc_s_ctrl,
+	.vidioc_g_tuner               = iris_vidioc_g_tuner,
+	.vidioc_s_tuner               = iris_vidioc_s_tuner,
+	.vidioc_g_frequency           = iris_vidioc_g_frequency,
+	.vidioc_s_frequency           = iris_vidioc_s_frequency,
+	.vidioc_s_hw_freq_seek        = iris_vidioc_s_hw_freq_seek,
+	.vidioc_dqbuf                 = iris_vidioc_dqbuf,
+	.vidioc_g_fmt_type_private    = iris_vidioc_g_fmt_type_private,
+	.vidioc_s_ext_ctrls           = iris_vidioc_s_ext_ctrls,
+	.vidioc_g_ext_ctrls           = iris_vidioc_g_ext_ctrls,
+};
+
+static const struct v4l2_file_operations iris_fops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = video_ioctl2,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl32 = v4l2_compat_ioctl32,
+#endif
+	.release        = iris_fops_release,
+};
+
+static struct video_device iris_viddev_template = {
+	.fops                   = &iris_fops,
+	.ioctl_ops              = &iris_ioctl_ops,
+	.name                   = DRIVER_NAME,
+	.release                = video_device_release,
+};
+
+static struct video_device *video_get_dev(void)
+{
+	return priv_videodev;
+}
+
+static int iris_probe(struct platform_device *pdev)
+{
+	struct iris_device *radio;
+	int retval;
+	int radio_nr = -1;
+	int i;
+
+	FMDBG("pdev %pK", pdev);
+
+	if (!pdev) {
+		FMDERR(": pdev is null\n");
+		return -ENOMEM;
+	}
+
+	radio = kzalloc(sizeof(struct iris_device), GFP_KERNEL);
+	if (!radio)
+		return -ENOMEM;
+
+	radio->dev = &pdev->dev;
+	platform_set_drvdata(pdev, radio);
+
+	radio->videodev = video_device_alloc();
+	if (!radio->videodev) {
+		kfree(radio);
+		return -ENOMEM;
+	}
+
+	memcpy(radio->videodev, &iris_viddev_template,
+	  sizeof(iris_viddev_template));
+	strlcpy(radio->v4l2_dev.name, DRIVER_NAME,
+			sizeof(radio->v4l2_dev.name));
+	retval = v4l2_device_register(NULL, &radio->v4l2_dev);
+	if (retval)
+		return -EINVAL;
+	radio->videodev->v4l2_dev = &radio->v4l2_dev;
+
+	for (i = 0; i < IRIS_BUF_MAX; i++) {
+		int kfifo_alloc_rc = 0;
+
+		spin_lock_init(&radio->buf_lock[i]);
+
+		if ((i == IRIS_BUF_RAW_RDS) || (i == IRIS_BUF_PEEK))
+			kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
+				rds_buf*3, GFP_KERNEL);
+		else if ((i == IRIS_BUF_CAL_DATA) || (i == IRIS_BUF_RT_RDS))
+			kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
+				STD_BUF_SIZE*2, GFP_KERNEL);
+		else
+			kfifo_alloc_rc = kfifo_alloc(&radio->data_buf[i],
+				STD_BUF_SIZE, GFP_KERNEL);
+
+		if (kfifo_alloc_rc != 0) {
+			FMDERR("failed allocating buffers %d\n",
+				   kfifo_alloc_rc);
+			for (; i > -1; i--)
+				kfifo_free(&radio->data_buf[i]);
+			video_device_release(radio->videodev);
+			kfree(radio);
+			return -ENOMEM;
+		}
+	}
+
+	mutex_init(&radio->lock);
+	init_completion(&radio->sync_xfr_start);
+	radio->tune_req = 0;
+	radio->prev_trans_rds = 2;
+	radio->is_fm_closing = false;
+	init_waitqueue_head(&radio->event_queue);
+	init_waitqueue_head(&radio->read_queue);
+
+	video_set_drvdata(radio->videodev, radio);
+
+	if (video_get_drvdata(radio->videodev) == NULL)
+		FMDERR(": video_get_drvdata failed\n");
+
+	retval = video_register_device(radio->videodev, VFL_TYPE_RADIO,
+								   radio_nr);
+	if (retval) {
+		FMDERR(": Could not register video device\n");
+		video_device_release(radio->videodev);
+		for (; i > -1; i--)
+			kfifo_free(&radio->data_buf[i]);
+		kfree(radio);
+		return retval;
+	}
+	priv_videodev = kzalloc(sizeof(struct video_device),
+			GFP_KERNEL);
+	if (priv_videodev != NULL) {
+		memcpy(priv_videodev, radio->videodev,
+			sizeof(struct video_device));
+	} else {
+		video_unregister_device(radio->videodev);
+		video_device_release(radio->videodev);
+		for (; i > -1; i--)
+			kfifo_free(&radio->data_buf[i]);
+		kfree(radio);
+	}
+	return 0;
+}
+
+
+static int iris_remove(struct platform_device *pdev)
+{
+	int i;
+	struct iris_device *radio = platform_get_drvdata(pdev);
+
+	if (radio == NULL) {
+		FMDERR(":radio is null\n");
+		return -EINVAL;
+	}
+	video_unregister_device(radio->videodev);
+
+	for (i = 0; i < IRIS_BUF_MAX; i++)
+		kfifo_free(&radio->data_buf[i]);
+
+	kfree(radio);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static const struct of_device_id iris_fm_match[] = {
+	{.compatible = "qcom,iris_fm"},
+	{}
+};
+
+static struct platform_driver iris_driver = {
+	.probe	= iris_probe,
+	.driver = {
+		.owner  = THIS_MODULE,
+		.name   = "iris_fm",
+		.of_match_table = iris_fm_match,
+	},
+	.remove = iris_remove,
+};
+
+static int __init iris_radio_init(void)
+{
+	return platform_driver_register(&iris_driver);
+}
+module_init(iris_radio_init);
+
+static void __exit iris_radio_exit(void)
+{
+	platform_driver_unregister(&iris_driver);
+}
+module_exit(iris_radio_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 8be561a..9f98e4d 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -710,7 +710,11 @@
 		SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings);
 		SET_VALID_IOCTL(ops, VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap);
 		SET_VALID_IOCTL(ops, VIDIOC_G_EDID, vidioc_g_edid);
+	} else {
+		/* ioctls valid for radio */
+		SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
 	}
+
 	if (is_tx && (is_radio || is_sdr)) {
 		/* radio transmitter only ioctls */
 		SET_VALID_IOCTL(ops, VIDIOC_G_MODULATOR, vidioc_g_modulator);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index e2e23ff..d4ee140 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -982,6 +982,9 @@
 		if (is_sdr && is_tx && ops->vidioc_g_fmt_sdr_out)
 			return 0;
 		break;
+	case V4L2_BUF_TYPE_PRIVATE:
+		if (ops->vidioc_g_fmt_type_private)
+			return 0;
 	default:
 		break;
 	}
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 980c1c0..e04e0f0 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -1040,6 +1040,12 @@
 		goto idata_free;
 	}
 
+	/*
+	 * Ensure rpmb_req_pending flag is synchronized between multiple
+	 * entities which may use rpmb ioclts with a lock.
+	 */
+	mutex_lock(&card->host->rpmb_req_mutex);
+	atomic_set(&card->host->rpmb_req_pending, 1);
 	mmc_get_card(card);
 
 	if (mmc_card_doing_bkops(card)) {
@@ -1155,6 +1161,9 @@
 
 cmd_rel_host:
 	mmc_put_card(card);
+	atomic_set(&card->host->rpmb_req_pending, 0);
+	mutex_unlock(&card->host->rpmb_req_mutex);
+
 
 idata_free:
 	for (i = 0; i < MMC_IOC_MAX_RPMB_CMD; i++) {
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index b34a143..aa8373d 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -98,7 +98,9 @@
 	 *    be any other direct command active.
 	 * 3. cmdq state should be unhalted.
 	 * 4. cmdq state shouldn't be in error state.
-	 * 5. free tag available to process the new request.
+	 * 5. There is no outstanding RPMB request pending.
+	 * 6. free tag available to process the new request.
+	 *    (This must be the last condtion to check)
 	 */
 	wait_event(ctx->wait, kthread_should_stop()
 		|| (mmc_peek_request(mq) &&
@@ -109,6 +111,7 @@
 		&& !(!host->card->part_curr && mmc_host_cq_disable(host) &&
 			!mmc_card_suspended(host->card))
 		&& !test_bit(CMDQ_STATE_ERR, &ctx->curr_state)
+		&& !atomic_read(&host->rpmb_req_pending)
 		&& !mmc_check_blk_queue_start_tag(q, mq->cmdq_req_peeked)));
 }
 
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index 2958473..45df01b 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -717,6 +717,8 @@
 	INIT_DELAYED_WORK(&host->detect, mmc_rescan);
 	setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host);
 
+	mutex_init(&host->rpmb_req_mutex);
+
 	/*
 	 * By default, hosts do not support SGIO or large requests.
 	 * They have to set these according to their abilities.
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 0bea2cb..47094d5 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -158,6 +158,8 @@
 #define DDR_CONFIG_PRG_RCLK_DLY_MASK	0x1FF
 #define DDR_CONFIG_PRG_RCLK_DLY		115
 #define DDR_CONFIG_2_POR_VAL		0x80040873
+#define DLL_USR_CTL_POR_VAL		0x10800
+#define ENABLE_DLL_LOCK_STATUS		(1 << 26)
 
 /* 512 descriptors */
 #define SDHCI_MSM_MAX_SEGMENTS  (1 << 9)
@@ -200,6 +202,7 @@
 	u32 CORE_DLL_CONFIG_2;
 	u32 CORE_DDR_CONFIG;
 	u32 CORE_DDR_CONFIG_2;
+	u32 CORE_DLL_USR_CTL; /* Present on SDCC5.1 onwards */
 };
 
 struct sdhci_msm_offset sdhci_msm_offset_mci_removed = {
@@ -229,6 +232,7 @@
 	.CORE_DLL_CONFIG_2 = 0x254,
 	.CORE_DDR_CONFIG = 0x258,
 	.CORE_DDR_CONFIG_2 = 0x25C,
+	.CORE_DLL_USR_CTL = 0x388,
 };
 
 struct sdhci_msm_offset sdhci_msm_offset_mci_present = {
@@ -795,6 +799,15 @@
 				msm_host_offset->CORE_DLL_CONFIG_2);
 	}
 
+	/*
+	 * Configure DLL user control register to enable DLL status
+	 * This setting is applicable to SDCC v5.1 onwards only
+	 */
+	if (msm_host->need_dll_user_ctl) {
+		writel_relaxed(DLL_USR_CTL_POR_VAL | ENABLE_DLL_LOCK_STATUS,
+			host->ioaddr + msm_host_offset->CORE_DLL_USR_CTL);
+	}
+
 	/* Set DLL_EN bit to 1. */
 	writel_relaxed((readl_relaxed(host->ioaddr +
 			msm_host_offset->CORE_DLL_CONFIG) | CORE_DLL_EN),
@@ -3952,8 +3965,9 @@
 		return;
 
 	if (async) {
-		schedule_delayed_work(&msm_host->pm_qos_irq.unvote_work,
-				      msecs_to_jiffies(QOS_REMOVE_DELAY_MS));
+		queue_delayed_work(msm_host->pm_qos_wq,
+				&msm_host->pm_qos_irq.unvote_work,
+				msecs_to_jiffies(QOS_REMOVE_DELAY_MS));
 		return;
 	}
 
@@ -4030,6 +4044,33 @@
 				struct sdhci_host *host) { }
 #endif
 
+static bool sdhci_msm_pm_qos_wq_init(struct sdhci_msm_host *msm_host)
+{
+	char *wq = NULL;
+	bool ret = true;
+
+	wq = kasprintf(GFP_KERNEL, "sdhci_msm_pm_qos/%s",
+			dev_name(&msm_host->pdev->dev));
+	if (!wq)
+		return false;
+	/*
+	 * Create a work queue with flag WQ_MEM_RECLAIM set for
+	 * pm_qos_unvote work. Because mmc thread is created with
+	 * flag PF_MEMALLOC set, kernel will check for work queue
+	 * flag WQ_MEM_RECLAIM when flush the work queue. If work
+	 * queue flag WQ_MEM_RECLAIM is not set, kernel warning
+	 * will be triggered.
+	 */
+	msm_host->pm_qos_wq = create_workqueue(wq);
+	if (!msm_host->pm_qos_wq) {
+		ret = false;
+		dev_err(&msm_host->pdev->dev,
+				"failed to create pm qos unvote work queue\n");
+	}
+	kfree(wq);
+	return ret;
+}
+
 void sdhci_msm_pm_qos_irq_init(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
@@ -4054,6 +4095,8 @@
 		cpumask_copy(&msm_host->pm_qos_irq.req.cpus_affine,
 			cpumask_of(msm_host->pdata->pm_qos_data.irq_cpu));
 
+	sdhci_msm_pm_qos_wq_init(msm_host);
+
 	INIT_DELAYED_WORK(&msm_host->pm_qos_irq.unvote_work,
 		sdhci_msm_pm_qos_irq_unvote_work);
 	/* For initialization phase, set the performance latency */
@@ -4228,8 +4271,9 @@
 		return false;
 
 	if (async) {
-		schedule_delayed_work(&msm_host->pm_qos[group].unvote_work,
-				      msecs_to_jiffies(QOS_REMOVE_DELAY_MS));
+		queue_delayed_work(msm_host->pm_qos_wq,
+				&msm_host->pm_qos[group].unvote_work,
+				msecs_to_jiffies(QOS_REMOVE_DELAY_MS));
 		return true;
 	}
 
@@ -4532,6 +4576,10 @@
 		msm_host->ice_hci_support = true;
 		host->cdr_support = true;
 	}
+
+	if ((major == 1) && (minor >= 0x71))
+		msm_host->need_dll_user_ctl = true;
+
 }
 
 #ifdef CONFIG_MMC_CQ_HCI
@@ -5169,6 +5217,9 @@
 		device_remove_file(&pdev->dev, &msm_host->polling);
 	device_remove_file(&pdev->dev, &msm_host->msm_bus_vote.max_bus_bw);
 	pm_runtime_disable(&pdev->dev);
+
+	if (msm_host->pm_qos_wq)
+		destroy_workqueue(msm_host->pm_qos_wq);
 	sdhci_remove_host(host, dead);
 	sdhci_pltfm_free(pdev);
 
diff --git a/drivers/mmc/host/sdhci-msm.h b/drivers/mmc/host/sdhci-msm.h
index 9c2442d..27c4f23 100644
--- a/drivers/mmc/host/sdhci-msm.h
+++ b/drivers/mmc/host/sdhci-msm.h
@@ -256,6 +256,8 @@
 	bool pltfm_init_done;
 	struct sdhci_msm_regs_restore regs_restore;
 	int soc_min_rev;
+	struct workqueue_struct *pm_qos_wq;
+	bool need_dll_user_ctl;
 };
 
 extern char *saved_command_line;
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index 3c5bc72..795b905 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.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
@@ -223,10 +223,13 @@
 	struct dma_iommu_mapping *mapping;
 	int atomic_ctx = 1;
 	int s1_bypass = 1;
+	int fast = 1;
+
+	cnss_pr_dbg("Initializing SMMU\n");
 
 	dev = &pci_priv->pci_dev->dev;
 
-	mapping = arm_iommu_create_mapping(&platform_bus_type,
+	mapping = arm_iommu_create_mapping(dev->bus,
 					   pci_priv->smmu_iova_start,
 					   pci_priv->smmu_iova_len);
 	if (IS_ERR(mapping)) {
@@ -235,22 +238,35 @@
 		goto out;
 	}
 
-	ret = iommu_domain_set_attr(mapping->domain,
-				    DOMAIN_ATTR_ATOMIC,
-				    &atomic_ctx);
-	if (ret) {
-		pr_err("Failed to set SMMU atomic_ctx attribute, err = %d\n",
-		       ret);
-		goto release_mapping;
-	}
+	if (pci_priv->smmu_s1_enable) {
+		cnss_pr_dbg("Enabling SMMU S1 stage\n");
 
-	ret = iommu_domain_set_attr(mapping->domain,
-				    DOMAIN_ATTR_S1_BYPASS,
-				    &s1_bypass);
-	if (ret) {
-		pr_err("Failed to set SMMU s1_bypass attribute, err = %d\n",
-		       ret);
-		goto release_mapping;
+		ret = iommu_domain_set_attr(mapping->domain,
+					    DOMAIN_ATTR_ATOMIC,
+					    &atomic_ctx);
+		if (ret) {
+			pr_err("Failed to set SMMU atomic_ctx attribute, err = %d\n",
+			       ret);
+			goto release_mapping;
+		}
+
+		ret = iommu_domain_set_attr(mapping->domain,
+					    DOMAIN_ATTR_FAST,
+					    &fast);
+		if (ret) {
+			pr_err("Failed to set SMMU fast attribute, err = %d\n",
+			       ret);
+			goto release_mapping;
+		}
+	} else {
+		ret = iommu_domain_set_attr(mapping->domain,
+					    DOMAIN_ATTR_S1_BYPASS,
+					    &s1_bypass);
+		if (ret) {
+			pr_err("Failed to set SMMU s1_bypass attribute, err = %d\n",
+			       ret);
+			goto release_mapping;
+		}
 	}
 
 	ret = arm_iommu_attach_device(dev, mapping);
@@ -849,13 +865,15 @@
 		goto out;
 	}
 
-	num_vectors = pci_enable_msi_range(pci_dev,
-					   msi_config->total_vectors,
-					   msi_config->total_vectors);
+	num_vectors = pci_alloc_irq_vectors(pci_dev,
+					    msi_config->total_vectors,
+					    msi_config->total_vectors,
+					    PCI_IRQ_MSI);
 	if (num_vectors != msi_config->total_vectors) {
 		cnss_pr_err("Failed to get enough MSI vectors (%d), available vectors = %d",
 			    msi_config->total_vectors, num_vectors);
-		ret = -EINVAL;
+		if (num_vectors >= 0)
+			ret = -EINVAL;
 		goto reset_msi_config;
 	}
 
@@ -863,7 +881,7 @@
 	if (!msi_desc) {
 		cnss_pr_err("msi_desc is NULL!\n");
 		ret = -EINVAL;
-		goto disable_msi;
+		goto free_msi_vector;
 	}
 
 	pci_priv->msi_ep_base_data = msi_desc->msg.data;
@@ -876,8 +894,8 @@
 
 	return 0;
 
-disable_msi:
-	pci_disable_msi(pci_priv->pci_dev);
+free_msi_vector:
+	pci_free_irq_vectors(pci_priv->pci_dev);
 reset_msi_config:
 	pci_priv->msi_config = NULL;
 out:
@@ -886,7 +904,7 @@
 
 static void cnss_pci_disable_msi(struct cnss_pci_data *pci_priv)
 {
-	pci_disable_msi(pci_priv->pci_dev);
+	pci_free_irq_vectors(pci_priv->pci_dev);
 }
 
 int cnss_get_user_msi_assignment(struct device *dev, char *user_name,
@@ -930,8 +948,12 @@
 int cnss_get_msi_irq(struct device *dev, unsigned int vector)
 {
 	struct pci_dev *pci_dev = to_pci_dev(dev);
+	int irq_num;
 
-	return pci_dev->irq + vector;
+	irq_num = pci_irq_vector(pci_dev, vector);
+	cnss_pr_dbg("Get IRQ number %d for vector index %d\n", irq_num, vector);
+
+	return irq_num;
 }
 EXPORT_SYMBOL(cnss_get_msi_irq);
 
@@ -1443,6 +1465,10 @@
 	res = platform_get_resource_byname(plat_priv->plat_dev, IORESOURCE_MEM,
 					   "smmu_iova_base");
 	if (res) {
+		if (of_property_read_bool(plat_priv->plat_dev->dev.of_node,
+					  "qcom,smmu-s1-enable"))
+			pci_priv->smmu_s1_enable = true;
+
 		pci_priv->smmu_iova_start = res->start;
 		pci_priv->smmu_iova_len = resource_size(res);
 		cnss_pr_dbg("smmu_iova_start: %pa, smmu_iova_len: %zu\n",
diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h
index 89edc60..4a82998 100644
--- a/drivers/net/wireless/cnss2/pci.h
+++ b/drivers/net/wireless/cnss2/pci.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -70,6 +70,7 @@
 	atomic_t auto_suspended;
 	bool monitor_wake_intr;
 	struct dma_iommu_mapping *smmu_mapping;
+	bool smmu_s1_enable;
 	dma_addr_t smmu_iova_start;
 	size_t smmu_iova_len;
 	void __iomem *bar;
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index dab5db5..9413da3 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -73,6 +73,16 @@
 	  platform.
 	  Say Y here to enable pinctrl settings for MDM9650.
 
+config PINCTRL_MDM9607
+	tristate "QTI MDM9607 pin controller driver"
+	depends on GPIOLIB && OF
+	select PINCTRL_MSM
+	help
+	  This is the pinctrl, pinmux, pinconf and gpiolib driver settings
+	  for the QTI TLMM block which is found in the QTI 9607
+	  platform.
+	  Say Y here to enable pinctrl settings for MDM9607.
+
 config PINCTRL_MSM8X74
 	tristate "Qualcomm 8x74 pin controller driver"
 	depends on GPIOLIB && OF
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 5389139..9b20604 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -23,3 +23,4 @@
 obj-$(CONFIG_PINCTRL_SDM670) += pinctrl-sdm670.o
 obj-$(CONFIG_PINCTRL_SDXPOORWILLS)	+= pinctrl-sdxpoorwills.o
 obj-$(CONFIG_PINCTRL_MDM9650)	+= pinctrl-mdm9650.o
+obj-$(CONFIG_PINCTRL_MDM9607)	+= pinctrl-mdm9607.o
diff --git a/drivers/pinctrl/qcom/pinctrl-mdm9607.c b/drivers/pinctrl/qcom/pinctrl-mdm9607.c
new file mode 100644
index 0000000..59688ff
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-mdm9607.c
@@ -0,0 +1,1128 @@
+/*
+ * Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+#define FUNCTION(fname)			                \
+	[msm_mux_##fname] = {		                \
+		.name = #fname,				\
+		.groups = fname##_groups,               \
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+#define REG_BASE 0x0
+#define REG_SIZE 0x1000
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9)	\
+	{					        \
+		.name = "gpio" #id,			\
+		.pins = gpio##id##_pins,		\
+		.npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins),	\
+		.funcs = (int[]){			\
+			msm_mux_gpio, /* gpio mode */	\
+			msm_mux_##f1,			\
+			msm_mux_##f2,			\
+			msm_mux_##f3,			\
+			msm_mux_##f4,			\
+			msm_mux_##f5,			\
+			msm_mux_##f6,			\
+			msm_mux_##f7,			\
+			msm_mux_##f8,			\
+			msm_mux_##f9			\
+		},				        \
+		.nfuncs = 10,				\
+		.ctl_reg = REG_BASE + REG_SIZE * id,			\
+		.io_reg = REG_BASE + 0x4 + REG_SIZE * id,		\
+		.intr_cfg_reg = REG_BASE + 0x8 + REG_SIZE * id,		\
+		.intr_status_reg = REG_BASE + 0xc + REG_SIZE * id,	\
+		.intr_target_reg = REG_BASE + 0x8 + REG_SIZE * id,	\
+		.mux_bit = 2,			\
+		.pull_bit = 0,			\
+		.drv_bit = 6,			\
+		.oe_bit = 9,			\
+		.in_bit = 0,			\
+		.out_bit = 1,			\
+		.intr_enable_bit = 0,		\
+		.intr_status_bit = 0,		\
+		.intr_target_bit = 5,		\
+		.intr_target_kpss_val = 4,	\
+		.intr_raw_status_bit = 4,	\
+		.intr_polarity_bit = 1,		\
+		.intr_detection_bit = 2,	\
+		.intr_detection_width = 2,	\
+	}
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv)	\
+	{					        \
+		.name = #pg_name,			\
+		.pins = pg_name##_pins,			\
+		.npins = (unsigned int)ARRAY_SIZE(pg_name##_pins),	\
+		.ctl_reg = ctl,				\
+		.io_reg = 0,				\
+		.intr_cfg_reg = 0,			\
+		.intr_status_reg = 0,			\
+		.intr_target_reg = 0,			\
+		.mux_bit = -1,				\
+		.pull_bit = pull,			\
+		.drv_bit = drv,				\
+		.oe_bit = -1,				\
+		.in_bit = -1,				\
+		.out_bit = -1,				\
+		.intr_enable_bit = -1,			\
+		.intr_status_bit = -1,			\
+		.intr_target_bit = -1,			\
+		.intr_raw_status_bit = -1,		\
+		.intr_polarity_bit = -1,		\
+		.intr_detection_bit = -1,		\
+		.intr_detection_width = -1,		\
+	}
+static const struct pinctrl_pin_desc mdm9607_pins[] = {
+	PINCTRL_PIN(0, "GPIO_0"),
+	PINCTRL_PIN(1, "GPIO_1"),
+	PINCTRL_PIN(2, "GPIO_2"),
+	PINCTRL_PIN(3, "GPIO_3"),
+	PINCTRL_PIN(4, "GPIO_4"),
+	PINCTRL_PIN(5, "GPIO_5"),
+	PINCTRL_PIN(6, "GPIO_6"),
+	PINCTRL_PIN(7, "GPIO_7"),
+	PINCTRL_PIN(8, "GPIO_8"),
+	PINCTRL_PIN(9, "GPIO_9"),
+	PINCTRL_PIN(10, "GPIO_10"),
+	PINCTRL_PIN(11, "GPIO_11"),
+	PINCTRL_PIN(12, "GPIO_12"),
+	PINCTRL_PIN(13, "GPIO_13"),
+	PINCTRL_PIN(14, "GPIO_14"),
+	PINCTRL_PIN(15, "GPIO_15"),
+	PINCTRL_PIN(16, "GPIO_16"),
+	PINCTRL_PIN(17, "GPIO_17"),
+	PINCTRL_PIN(18, "GPIO_18"),
+	PINCTRL_PIN(19, "GPIO_19"),
+	PINCTRL_PIN(20, "GPIO_20"),
+	PINCTRL_PIN(21, "GPIO_21"),
+	PINCTRL_PIN(22, "GPIO_22"),
+	PINCTRL_PIN(23, "GPIO_23"),
+	PINCTRL_PIN(24, "GPIO_24"),
+	PINCTRL_PIN(25, "GPIO_25"),
+	PINCTRL_PIN(26, "GPIO_26"),
+	PINCTRL_PIN(27, "GPIO_27"),
+	PINCTRL_PIN(28, "GPIO_28"),
+	PINCTRL_PIN(29, "GPIO_29"),
+	PINCTRL_PIN(30, "GPIO_30"),
+	PINCTRL_PIN(31, "GPIO_31"),
+	PINCTRL_PIN(32, "GPIO_32"),
+	PINCTRL_PIN(33, "GPIO_33"),
+	PINCTRL_PIN(34, "GPIO_34"),
+	PINCTRL_PIN(35, "GPIO_35"),
+	PINCTRL_PIN(36, "GPIO_36"),
+	PINCTRL_PIN(37, "GPIO_37"),
+	PINCTRL_PIN(38, "GPIO_38"),
+	PINCTRL_PIN(39, "GPIO_39"),
+	PINCTRL_PIN(40, "GPIO_40"),
+	PINCTRL_PIN(41, "GPIO_41"),
+	PINCTRL_PIN(42, "GPIO_42"),
+	PINCTRL_PIN(43, "GPIO_43"),
+	PINCTRL_PIN(44, "GPIO_44"),
+	PINCTRL_PIN(45, "GPIO_45"),
+	PINCTRL_PIN(46, "GPIO_46"),
+	PINCTRL_PIN(47, "GPIO_47"),
+	PINCTRL_PIN(48, "GPIO_48"),
+	PINCTRL_PIN(49, "GPIO_49"),
+	PINCTRL_PIN(50, "GPIO_50"),
+	PINCTRL_PIN(51, "GPIO_51"),
+	PINCTRL_PIN(52, "GPIO_52"),
+	PINCTRL_PIN(53, "GPIO_53"),
+	PINCTRL_PIN(54, "GPIO_54"),
+	PINCTRL_PIN(55, "GPIO_55"),
+	PINCTRL_PIN(56, "GPIO_56"),
+	PINCTRL_PIN(57, "GPIO_57"),
+	PINCTRL_PIN(58, "GPIO_58"),
+	PINCTRL_PIN(59, "GPIO_59"),
+	PINCTRL_PIN(60, "GPIO_60"),
+	PINCTRL_PIN(61, "GPIO_61"),
+	PINCTRL_PIN(62, "GPIO_62"),
+	PINCTRL_PIN(63, "GPIO_63"),
+	PINCTRL_PIN(64, "GPIO_64"),
+	PINCTRL_PIN(65, "GPIO_65"),
+	PINCTRL_PIN(66, "GPIO_66"),
+	PINCTRL_PIN(67, "GPIO_67"),
+	PINCTRL_PIN(68, "GPIO_68"),
+	PINCTRL_PIN(69, "GPIO_69"),
+	PINCTRL_PIN(70, "GPIO_70"),
+	PINCTRL_PIN(71, "GPIO_71"),
+	PINCTRL_PIN(72, "GPIO_72"),
+	PINCTRL_PIN(73, "GPIO_73"),
+	PINCTRL_PIN(74, "GPIO_74"),
+	PINCTRL_PIN(75, "GPIO_75"),
+	PINCTRL_PIN(76, "GPIO_76"),
+	PINCTRL_PIN(77, "GPIO_77"),
+	PINCTRL_PIN(78, "GPIO_78"),
+	PINCTRL_PIN(79, "GPIO_79"),
+	PINCTRL_PIN(80, "SDC1_CLK"),
+	PINCTRL_PIN(81, "SDC1_CMD"),
+	PINCTRL_PIN(82, "SDC1_DATA"),
+	PINCTRL_PIN(83, "SDC2_CLK"),
+	PINCTRL_PIN(84, "SDC2_CMD"),
+	PINCTRL_PIN(85, "SDC2_DATA"),
+	PINCTRL_PIN(86, "QDSD_CLK"),
+	PINCTRL_PIN(87, "QDSD_CMD"),
+	PINCTRL_PIN(88, "QDSD_DATA0"),
+	PINCTRL_PIN(89, "QDSD_DATA1"),
+	PINCTRL_PIN(90, "QDSD_DATA2"),
+	PINCTRL_PIN(91, "QDSD_DATA3"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+	static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+
+static const unsigned int sdc1_clk_pins[] = { 80 };
+static const unsigned int sdc1_cmd_pins[] = { 81 };
+static const unsigned int sdc1_data_pins[] = { 82 };
+static const unsigned int sdc2_clk_pins[] = { 83 };
+static const unsigned int sdc2_cmd_pins[] = { 84 };
+static const unsigned int sdc2_data_pins[] = { 85 };
+static const unsigned int qdsd_clk_pins[] = { 86 };
+static const unsigned int qdsd_cmd_pins[] = { 87 };
+static const unsigned int qdsd_data0_pins[] = { 88 };
+static const unsigned int qdsd_data1_pins[] = { 89 };
+static const unsigned int qdsd_data2_pins[] = { 90 };
+static const unsigned int qdsd_data3_pins[] = { 91 };
+
+enum mdm9607_functions {
+	msm_mux_blsp_spi3,
+	msm_mux_gpio,
+	msm_mux_blsp_uart3,
+	msm_mux_qdss_tracedata_a,
+	msm_mux_bimc_dte1,
+	msm_mux_blsp_i2c3,
+	msm_mux_qdss_traceclk_a,
+	msm_mux_bimc_dte0,
+	msm_mux_qdss_cti_trig_in_a1,
+	msm_mux_blsp_spi2,
+	msm_mux_blsp_uart2,
+	msm_mux_blsp_uim2,
+	msm_mux_blsp_i2c2,
+	msm_mux_qdss_tracectl_a,
+	msm_mux_sensor_int2,
+	msm_mux_blsp_spi5,
+	msm_mux_blsp_uart5,
+	msm_mux_ebi2_lcd,
+	msm_mux_m_voc,
+	msm_mux_sensor_int3,
+	msm_mux_sensor_en,
+	msm_mux_blsp_i2c5,
+	msm_mux_ebi2_a,
+	msm_mux_qdss_tracedata_b,
+	msm_mux_sensor_rst,
+	msm_mux_blsp2_spi,
+	msm_mux_blsp_spi1,
+	msm_mux_blsp_uart1,
+	msm_mux_blsp_uim1,
+	msm_mux_blsp3_spi,
+	msm_mux_gcc_gp2_clk_b,
+	msm_mux_gcc_gp3_clk_b,
+	msm_mux_blsp_i2c1,
+	msm_mux_gcc_gp1_clk_b,
+	msm_mux_blsp_spi4,
+	msm_mux_blsp_uart4,
+	msm_mux_rcm_marker1,
+	msm_mux_blsp_i2c4,
+	msm_mux_qdss_cti_trig_out_a1,
+	msm_mux_rcm_marker2,
+	msm_mux_qdss_cti_trig_out_a0,
+	msm_mux_blsp_spi6,
+	msm_mux_blsp_uart6,
+	msm_mux_pri_mi2s_ws_a,
+	msm_mux_ebi2_lcd_te_b,
+	msm_mux_blsp1_spi,
+	msm_mux_backlight_en_b,
+	msm_mux_pri_mi2s_data0_a,
+	msm_mux_pri_mi2s_data1_a,
+	msm_mux_blsp_i2c6,
+	msm_mux_ebi2_a_d_8_b,
+	msm_mux_pri_mi2s_sck_a,
+	msm_mux_ebi2_lcd_cs_n_b,
+	msm_mux_touch_rst,
+	msm_mux_pri_mi2s_mclk_a,
+	msm_mux_pwr_nav_enabled_a,
+	msm_mux_ts_int,
+	msm_mux_sd_write,
+	msm_mux_pwr_crypto_enabled_a,
+	msm_mux_codec_rst,
+	msm_mux_adsp_ext,
+	msm_mux_atest_combodac_to_gpio_native,
+	msm_mux_uim2_data,
+	msm_mux_gmac_mdio,
+	msm_mux_gcc_gp1_clk_a,
+	msm_mux_uim2_clk,
+	msm_mux_gcc_gp2_clk_a,
+	msm_mux_eth_irq,
+	msm_mux_uim2_reset,
+	msm_mux_gcc_gp3_clk_a,
+	msm_mux_eth_rst,
+	msm_mux_uim2_present,
+	msm_mux_prng_rosc,
+	msm_mux_uim1_data,
+	msm_mux_uim1_clk,
+	msm_mux_uim1_reset,
+	msm_mux_uim1_present,
+	msm_mux_gcc_plltest,
+	msm_mux_uim_batt,
+	msm_mux_coex_uart,
+	msm_mux_codec_int,
+	msm_mux_qdss_cti_trig_in_a0,
+	msm_mux_atest_bbrx1,
+	msm_mux_cri_trng0,
+	msm_mux_atest_bbrx0,
+	msm_mux_cri_trng,
+	msm_mux_qdss_cti_trig_in_b0,
+	msm_mux_atest_gpsadc_dtest0_native,
+	msm_mux_qdss_cti_trig_out_b0,
+	msm_mux_qdss_tracectl_b,
+	msm_mux_qdss_traceclk_b,
+	msm_mux_pa_indicator,
+	msm_mux_modem_tsync,
+	msm_mux_nav_tsync_out_a,
+	msm_mux_nav_ptp_pps_in_a,
+	msm_mux_ptp_pps_out_a,
+	msm_mux_gsm0_tx,
+	msm_mux_qdss_cti_trig_in_b1,
+	msm_mux_cri_trng1,
+	msm_mux_qdss_cti_trig_out_b1,
+	msm_mux_ssbi1,
+	msm_mux_atest_gpsadc_dtest1_native,
+	msm_mux_ssbi2,
+	msm_mux_atest_char3,
+	msm_mux_atest_char2,
+	msm_mux_atest_char1,
+	msm_mux_atest_char0,
+	msm_mux_atest_char,
+	msm_mux_ebi0_wrcdc,
+	msm_mux_ldo_update,
+	msm_mux_gcc_tlmm,
+	msm_mux_ldo_en,
+	msm_mux_dbg_out,
+	msm_mux_atest_tsens,
+	msm_mux_lcd_rst,
+	msm_mux_wlan_en1,
+	msm_mux_nav_tsync_out_b,
+	msm_mux_nav_ptp_pps_in_b,
+	msm_mux_ptp_pps_out_b,
+	msm_mux_pbs0,
+	msm_mux_sec_mi2s,
+	msm_mux_pwr_modem_enabled_a,
+	msm_mux_pbs1,
+	msm_mux_pwr_modem_enabled_b,
+	msm_mux_pbs2,
+	msm_mux_pwr_nav_enabled_b,
+	msm_mux_pwr_crypto_enabled_b,
+	msm_mux_NA,
+};
+
+static const char * const blsp_spi3_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const gpio_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+	"gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+	"gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+	"gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+	"gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+	"gpio78", "gpio79",
+};
+static const char * const blsp_uart3_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const qdss_tracedata_a_groups[] = {
+	"gpio0", "gpio1", "gpio4", "gpio5", "gpio20", "gpio21", "gpio22",
+	"gpio23", "gpio24", "gpio25", "gpio26", "gpio75", "gpio76", "gpio77",
+	"gpio78", "gpio79",
+};
+static const char * const bimc_dte1_groups[] = {
+	"gpio1", "gpio24",
+};
+static const char * const blsp_i2c3_groups[] = {
+	"gpio2", "gpio3",
+};
+static const char * const qdss_traceclk_a_groups[] = {
+	"gpio2",
+};
+static const char * const bimc_dte0_groups[] = {
+	"gpio2", "gpio15",
+};
+static const char * const qdss_cti_trig_in_a1_groups[] = {
+	"gpio3",
+};
+static const char * const blsp_spi2_groups[] = {
+	"gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uart2_groups[] = {
+	"gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uim2_groups[] = {
+	"gpio4", "gpio5",
+};
+static const char * const blsp_i2c2_groups[] = {
+	"gpio6", "gpio7",
+};
+static const char * const qdss_tracectl_a_groups[] = {
+	"gpio6",
+};
+static const char * const sensor_int2_groups[] = {
+	"gpio8",
+};
+static const char * const blsp_spi5_groups[] = {
+	"gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const blsp_uart5_groups[] = {
+	"gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const ebi2_lcd_groups[] = {
+	"gpio8", "gpio11", "gpio74", "gpio78",
+};
+static const char * const m_voc_groups[] = {
+	"gpio8", "gpio78",
+};
+static const char * const sensor_int3_groups[] = {
+	"gpio9",
+};
+static const char * const sensor_en_groups[] = {
+	"gpio10",
+};
+static const char * const blsp_i2c5_groups[] = {
+	"gpio10", "gpio11",
+};
+static const char * const ebi2_a_groups[] = {
+	"gpio10",
+};
+static const char * const qdss_tracedata_b_groups[] = {
+	"gpio10", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43", "gpio46",
+	"gpio47", "gpio48", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55",
+	"gpio58", "gpio59",
+};
+static const char * const sensor_rst_groups[] = {
+	"gpio11",
+};
+static const char * const blsp2_spi_groups[] = {
+	"gpio11", "gpio13", "gpio77",
+};
+static const char * const blsp_spi1_groups[] = {
+	"gpio12", "gpio13", "gpio14", "gpio15",
+};
+static const char * const blsp_uart1_groups[] = {
+	"gpio12", "gpio13", "gpio14", "gpio15",
+};
+static const char * const blsp_uim1_groups[] = {
+	"gpio12", "gpio13",
+};
+static const char * const blsp3_spi_groups[] = {
+	"gpio12", "gpio26", "gpio76",
+};
+static const char * const gcc_gp2_clk_b_groups[] = {
+	"gpio12",
+};
+static const char * const gcc_gp3_clk_b_groups[] = {
+	"gpio13",
+};
+static const char * const blsp_i2c1_groups[] = {
+	"gpio14", "gpio15",
+};
+static const char * const gcc_gp1_clk_b_groups[] = {
+	"gpio14",
+};
+static const char * const blsp_spi4_groups[] = {
+	"gpio16", "gpio17", "gpio18", "gpio19",
+};
+static const char * const blsp_uart4_groups[] = {
+	"gpio16", "gpio17", "gpio18", "gpio19",
+};
+static const char * const rcm_marker1_groups[] = {
+	"gpio18",
+};
+static const char * const blsp_i2c4_groups[] = {
+	"gpio18", "gpio19",
+};
+static const char * const qdss_cti_trig_out_a1_groups[] = {
+	"gpio18",
+};
+static const char * const rcm_marker2_groups[] = {
+	"gpio19",
+};
+static const char * const qdss_cti_trig_out_a0_groups[] = {
+	"gpio19",
+};
+static const char * const blsp_spi6_groups[] = {
+	"gpio20", "gpio21", "gpio22", "gpio23",
+};
+static const char * const blsp_uart6_groups[] = {
+	"gpio20", "gpio21", "gpio22", "gpio23",
+};
+static const char * const pri_mi2s_ws_a_groups[] = {
+	"gpio20",
+};
+static const char * const ebi2_lcd_te_b_groups[] = {
+	"gpio20",
+};
+static const char * const blsp1_spi_groups[] = {
+	"gpio20", "gpio21", "gpio78",
+};
+static const char * const backlight_en_b_groups[] = {
+	"gpio21",
+};
+static const char * const pri_mi2s_data0_a_groups[] = {
+	"gpio21",
+};
+static const char * const pri_mi2s_data1_a_groups[] = {
+	"gpio22",
+};
+static const char * const blsp_i2c6_groups[] = {
+	"gpio22", "gpio23",
+};
+static const char * const ebi2_a_d_8_b_groups[] = {
+	"gpio22",
+};
+static const char * const pri_mi2s_sck_a_groups[] = {
+	"gpio23",
+};
+static const char * const ebi2_lcd_cs_n_b_groups[] = {
+	"gpio23",
+};
+static const char * const touch_rst_groups[] = {
+	"gpio24",
+};
+static const char * const pri_mi2s_mclk_a_groups[] = {
+	"gpio24",
+};
+static const char * const pwr_nav_enabled_a_groups[] = {
+	"gpio24",
+};
+static const char * const ts_int_groups[] = {
+	"gpio25",
+};
+static const char * const sd_write_groups[] = {
+	"gpio25",
+};
+static const char * const pwr_crypto_enabled_a_groups[] = {
+	"gpio25",
+};
+static const char * const codec_rst_groups[] = {
+	"gpio26",
+};
+static const char * const adsp_ext_groups[] = {
+	"gpio26",
+};
+static const char * const atest_combodac_to_gpio_native_groups[] = {
+	"gpio26", "gpio27", "gpio28", "gpio29", "gpio30", "gpio31", "gpio32",
+	"gpio33", "gpio34", "gpio35", "gpio41", "gpio45", "gpio49", "gpio50",
+	"gpio51", "gpio52", "gpio54", "gpio55", "gpio57", "gpio59",
+};
+static const char * const uim2_data_groups[] = {
+	"gpio27",
+};
+static const char * const gmac_mdio_groups[] = {
+	"gpio27", "gpio28",
+};
+static const char * const gcc_gp1_clk_a_groups[] = {
+	"gpio27",
+};
+static const char * const uim2_clk_groups[] = {
+	"gpio28",
+};
+static const char * const gcc_gp2_clk_a_groups[] = {
+	"gpio28",
+};
+static const char * const eth_irq_groups[] = {
+	"gpio29",
+};
+static const char * const uim2_reset_groups[] = {
+	"gpio29",
+};
+static const char * const gcc_gp3_clk_a_groups[] = {
+	"gpio29",
+};
+static const char * const eth_rst_groups[] = {
+	"gpio30",
+};
+static const char * const uim2_present_groups[] = {
+	"gpio30",
+};
+static const char * const prng_rosc_groups[] = {
+	"gpio30",
+};
+static const char * const uim1_data_groups[] = {
+	"gpio31",
+};
+static const char * const uim1_clk_groups[] = {
+	"gpio32",
+};
+static const char * const uim1_reset_groups[] = {
+	"gpio33",
+};
+static const char * const uim1_present_groups[] = {
+	"gpio34",
+};
+static const char * const gcc_plltest_groups[] = {
+	"gpio34", "gpio35",
+};
+static const char * const uim_batt_groups[] = {
+	"gpio35",
+};
+static const char * const coex_uart_groups[] = {
+	"gpio36", "gpio37",
+};
+static const char * const codec_int_groups[] = {
+	"gpio38",
+};
+static const char * const qdss_cti_trig_in_a0_groups[] = {
+	"gpio38",
+};
+static const char * const atest_bbrx1_groups[] = {
+	"gpio39",
+};
+static const char * const cri_trng0_groups[] = {
+	"gpio40",
+};
+static const char * const atest_bbrx0_groups[] = {
+	"gpio40",
+};
+static const char * const cri_trng_groups[] = {
+	"gpio42",
+};
+static const char * const qdss_cti_trig_in_b0_groups[] = {
+	"gpio44",
+};
+static const char * const atest_gpsadc_dtest0_native_groups[] = {
+	"gpio44",
+};
+static const char * const qdss_cti_trig_out_b0_groups[] = {
+	"gpio45",
+};
+static const char * const qdss_tracectl_b_groups[] = {
+	"gpio49",
+};
+static const char * const qdss_traceclk_b_groups[] = {
+	"gpio50",
+};
+static const char * const pa_indicator_groups[] = {
+	"gpio51",
+};
+static const char * const modem_tsync_groups[] = {
+	"gpio53",
+};
+static const char * const nav_tsync_out_a_groups[] = {
+	"gpio53",
+};
+static const char * const nav_ptp_pps_in_a_groups[] = {
+	"gpio53",
+};
+static const char * const ptp_pps_out_a_groups[] = {
+	"gpio53",
+};
+static const char * const gsm0_tx_groups[] = {
+	"gpio55",
+};
+static const char * const qdss_cti_trig_in_b1_groups[] = {
+	"gpio56",
+};
+static const char * const cri_trng1_groups[] = {
+	"gpio57",
+};
+static const char * const qdss_cti_trig_out_b1_groups[] = {
+	"gpio57",
+};
+static const char * const ssbi1_groups[] = {
+	"gpio58",
+};
+static const char * const atest_gpsadc_dtest1_native_groups[] = {
+	"gpio58",
+};
+static const char * const ssbi2_groups[] = {
+	"gpio59",
+};
+static const char * const atest_char3_groups[] = {
+	"gpio60",
+};
+static const char * const atest_char2_groups[] = {
+	"gpio61",
+};
+static const char * const atest_char1_groups[] = {
+	"gpio62",
+};
+static const char * const atest_char0_groups[] = {
+	"gpio63",
+};
+static const char * const atest_char_groups[] = {
+	"gpio64",
+};
+static const char * const ebi0_wrcdc_groups[] = {
+	"gpio70",
+};
+static const char * const ldo_update_groups[] = {
+	"gpio72",
+};
+static const char * const gcc_tlmm_groups[] = {
+	"gpio72",
+};
+static const char * const ldo_en_groups[] = {
+	"gpio73",
+};
+static const char * const dbg_out_groups[] = {
+	"gpio73",
+};
+static const char * const atest_tsens_groups[] = {
+	"gpio73",
+};
+static const char * const lcd_rst_groups[] = {
+	"gpio74",
+};
+static const char * const wlan_en1_groups[] = {
+	"gpio75",
+};
+static const char * const nav_tsync_out_b_groups[] = {
+	"gpio75",
+};
+static const char * const nav_ptp_pps_in_b_groups[] = {
+	"gpio75",
+};
+static const char * const ptp_pps_out_b_groups[] = {
+	"gpio75",
+};
+static const char * const pbs0_groups[] = {
+	"gpio76",
+};
+static const char * const sec_mi2s_groups[] = {
+	"gpio76", "gpio77", "gpio78", "gpio79",
+};
+static const char * const pwr_modem_enabled_a_groups[] = {
+	"gpio76",
+};
+static const char * const pbs1_groups[] = {
+	"gpio77",
+};
+static const char * const pwr_modem_enabled_b_groups[] = {
+	"gpio77",
+};
+static const char * const pbs2_groups[] = {
+	"gpio78",
+};
+static const char * const pwr_nav_enabled_b_groups[] = {
+	"gpio78",
+};
+static const char * const pwr_crypto_enabled_b_groups[] = {
+	"gpio79",
+};
+
+static const struct msm_function mdm9607_functions[] = {
+	FUNCTION(blsp_spi3),
+	FUNCTION(gpio),
+	FUNCTION(blsp_uart3),
+	FUNCTION(qdss_tracedata_a),
+	FUNCTION(bimc_dte1),
+	FUNCTION(blsp_i2c3),
+	FUNCTION(qdss_traceclk_a),
+	FUNCTION(bimc_dte0),
+	FUNCTION(qdss_cti_trig_in_a1),
+	FUNCTION(blsp_spi2),
+	FUNCTION(blsp_uart2),
+	FUNCTION(blsp_uim2),
+	FUNCTION(blsp_i2c2),
+	FUNCTION(qdss_tracectl_a),
+	FUNCTION(sensor_int2),
+	FUNCTION(blsp_spi5),
+	FUNCTION(blsp_uart5),
+	FUNCTION(ebi2_lcd),
+	FUNCTION(m_voc),
+	FUNCTION(sensor_int3),
+	FUNCTION(sensor_en),
+	FUNCTION(blsp_i2c5),
+	FUNCTION(ebi2_a),
+	FUNCTION(qdss_tracedata_b),
+	FUNCTION(sensor_rst),
+	FUNCTION(blsp2_spi),
+	FUNCTION(blsp_spi1),
+	FUNCTION(blsp_uart1),
+	FUNCTION(blsp_uim1),
+	FUNCTION(blsp3_spi),
+	FUNCTION(gcc_gp2_clk_b),
+	FUNCTION(gcc_gp3_clk_b),
+	FUNCTION(blsp_i2c1),
+	FUNCTION(gcc_gp1_clk_b),
+	FUNCTION(blsp_spi4),
+	FUNCTION(blsp_uart4),
+	FUNCTION(rcm_marker1),
+	FUNCTION(blsp_i2c4),
+	FUNCTION(qdss_cti_trig_out_a1),
+	FUNCTION(rcm_marker2),
+	FUNCTION(qdss_cti_trig_out_a0),
+	FUNCTION(blsp_spi6),
+	FUNCTION(blsp_uart6),
+	FUNCTION(pri_mi2s_ws_a),
+	FUNCTION(ebi2_lcd_te_b),
+	FUNCTION(blsp1_spi),
+	FUNCTION(backlight_en_b),
+	FUNCTION(pri_mi2s_data0_a),
+	FUNCTION(pri_mi2s_data1_a),
+	FUNCTION(blsp_i2c6),
+	FUNCTION(ebi2_a_d_8_b),
+	FUNCTION(pri_mi2s_sck_a),
+	FUNCTION(ebi2_lcd_cs_n_b),
+	FUNCTION(touch_rst),
+	FUNCTION(pri_mi2s_mclk_a),
+	FUNCTION(pwr_nav_enabled_a),
+	FUNCTION(ts_int),
+	FUNCTION(sd_write),
+	FUNCTION(pwr_crypto_enabled_a),
+	FUNCTION(codec_rst),
+	FUNCTION(adsp_ext),
+	FUNCTION(atest_combodac_to_gpio_native),
+	FUNCTION(uim2_data),
+	FUNCTION(gmac_mdio),
+	FUNCTION(gcc_gp1_clk_a),
+	FUNCTION(uim2_clk),
+	FUNCTION(gcc_gp2_clk_a),
+	FUNCTION(eth_irq),
+	FUNCTION(uim2_reset),
+	FUNCTION(gcc_gp3_clk_a),
+	FUNCTION(eth_rst),
+	FUNCTION(uim2_present),
+	FUNCTION(prng_rosc),
+	FUNCTION(uim1_data),
+	FUNCTION(uim1_clk),
+	FUNCTION(uim1_reset),
+	FUNCTION(uim1_present),
+	FUNCTION(gcc_plltest),
+	FUNCTION(uim_batt),
+	FUNCTION(coex_uart),
+	FUNCTION(codec_int),
+	FUNCTION(qdss_cti_trig_in_a0),
+	FUNCTION(atest_bbrx1),
+	FUNCTION(cri_trng0),
+	FUNCTION(atest_bbrx0),
+	FUNCTION(cri_trng),
+	FUNCTION(qdss_cti_trig_in_b0),
+	FUNCTION(atest_gpsadc_dtest0_native),
+	FUNCTION(qdss_cti_trig_out_b0),
+	FUNCTION(qdss_tracectl_b),
+	FUNCTION(qdss_traceclk_b),
+	FUNCTION(pa_indicator),
+	FUNCTION(modem_tsync),
+	FUNCTION(nav_tsync_out_a),
+	FUNCTION(nav_ptp_pps_in_a),
+	FUNCTION(ptp_pps_out_a),
+	FUNCTION(gsm0_tx),
+	FUNCTION(qdss_cti_trig_in_b1),
+	FUNCTION(cri_trng1),
+	FUNCTION(qdss_cti_trig_out_b1),
+	FUNCTION(ssbi1),
+	FUNCTION(atest_gpsadc_dtest1_native),
+	FUNCTION(ssbi2),
+	FUNCTION(atest_char3),
+	FUNCTION(atest_char2),
+	FUNCTION(atest_char1),
+	FUNCTION(atest_char0),
+	FUNCTION(atest_char),
+	FUNCTION(ebi0_wrcdc),
+	FUNCTION(ldo_update),
+	FUNCTION(gcc_tlmm),
+	FUNCTION(ldo_en),
+	FUNCTION(dbg_out),
+	FUNCTION(atest_tsens),
+	FUNCTION(lcd_rst),
+	FUNCTION(wlan_en1),
+	FUNCTION(nav_tsync_out_b),
+	FUNCTION(nav_ptp_pps_in_b),
+	FUNCTION(ptp_pps_out_b),
+	FUNCTION(pbs0),
+	FUNCTION(sec_mi2s),
+	FUNCTION(pwr_modem_enabled_a),
+	FUNCTION(pbs1),
+	FUNCTION(pwr_modem_enabled_b),
+	FUNCTION(pbs2),
+	FUNCTION(pwr_nav_enabled_b),
+	FUNCTION(pwr_crypto_enabled_b),
+};
+
+static const struct msm_pingroup mdm9607_groups[] = {
+	PINGROUP(0, blsp_uart3, blsp_spi3, NA, NA, NA, NA, NA,
+		 qdss_tracedata_a, NA),
+	PINGROUP(1, blsp_uart3, blsp_spi3, NA, NA, NA, NA, NA,
+		 qdss_tracedata_a, bimc_dte1),
+	PINGROUP(2, blsp_uart3, blsp_i2c3, blsp_spi3, NA, NA, NA, NA, NA,
+		 qdss_traceclk_a),
+	PINGROUP(3, blsp_uart3, blsp_i2c3, blsp_spi3, NA, NA, NA, NA, NA, NA),
+	PINGROUP(4, blsp_spi2, blsp_uart2, blsp_uim2, NA, NA, NA, NA,
+		 qdss_tracedata_a, NA),
+	PINGROUP(5, blsp_spi2, blsp_uart2, blsp_uim2, NA, NA, NA, NA,
+		 qdss_tracedata_a, NA),
+	PINGROUP(6, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA),
+	PINGROUP(7, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA),
+	PINGROUP(8, blsp_spi5, blsp_uart5, ebi2_lcd, m_voc, NA, NA, NA, NA, NA),
+	PINGROUP(9, blsp_spi5, blsp_uart5, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(10, blsp_spi5, blsp_i2c5, blsp_uart5, ebi2_a, NA, NA,
+		 qdss_tracedata_b, NA, NA),
+	PINGROUP(11, blsp_spi5, blsp_i2c5, blsp_uart5, blsp2_spi, ebi2_lcd, NA,
+		 NA, NA, NA),
+	PINGROUP(12, blsp_spi1, blsp_uart1, blsp_uim1, blsp3_spi,
+		 gcc_gp2_clk_b, NA, NA, NA, NA),
+	PINGROUP(13, blsp_spi1, blsp_uart1, blsp_uim1, blsp2_spi,
+		 gcc_gp3_clk_b, NA, NA, NA, NA),
+	PINGROUP(14, blsp_spi1, blsp_uart1, blsp_i2c1, gcc_gp1_clk_b, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(15, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA),
+	PINGROUP(16, blsp_spi4, blsp_uart4, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(17, blsp_spi4, blsp_uart4, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(18, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA, NA, NA, NA),
+	PINGROUP(19, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA, NA, NA, NA),
+	PINGROUP(20, blsp_spi6, blsp_uart6, pri_mi2s_ws_a, ebi2_lcd_te_b,
+		 blsp1_spi, NA, NA, NA, qdss_tracedata_a),
+	PINGROUP(21, blsp_spi6, blsp_uart6, pri_mi2s_data0_a, blsp1_spi, NA,
+		 NA, NA, NA, NA),
+	PINGROUP(22, blsp_spi6, blsp_uart6, pri_mi2s_data1_a, blsp_i2c6,
+		 ebi2_a_d_8_b, NA, NA, NA, NA),
+	PINGROUP(23, blsp_spi6, blsp_uart6, pri_mi2s_sck_a, blsp_i2c6,
+		 ebi2_lcd_cs_n_b, NA, NA, NA, NA),
+	PINGROUP(24, pri_mi2s_mclk_a, NA, pwr_nav_enabled_a, NA, NA, NA, NA,
+		 qdss_tracedata_a, bimc_dte1),
+	PINGROUP(25, sd_write, NA, pwr_crypto_enabled_a, NA, NA, NA, NA,
+		 qdss_tracedata_a, NA),
+	PINGROUP(26, blsp3_spi, adsp_ext, NA, qdss_tracedata_a, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA),
+	PINGROUP(27, uim2_data, gmac_mdio, gcc_gp1_clk_a, NA, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA),
+	PINGROUP(28, uim2_clk, gmac_mdio, gcc_gp2_clk_a, NA, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA),
+	PINGROUP(29, uim2_reset, gcc_gp3_clk_a, NA, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA),
+	PINGROUP(30, uim2_present, prng_rosc, NA, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA),
+	PINGROUP(31, uim1_data, NA, NA, atest_combodac_to_gpio_native, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(32, uim1_clk, NA, NA, atest_combodac_to_gpio_native, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(33, uim1_reset, NA, NA, atest_combodac_to_gpio_native, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(34, uim1_present, gcc_plltest, NA, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA),
+	PINGROUP(35, uim_batt, gcc_plltest, NA, atest_combodac_to_gpio_native,
+		 NA, NA, NA, NA, NA),
+	PINGROUP(36, coex_uart, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(37, coex_uart, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(38, NA, NA, NA, qdss_cti_trig_in_a0, NA, NA, NA, NA, NA),
+	PINGROUP(39, NA, NA, NA, qdss_tracedata_b, NA, atest_bbrx1, NA, NA, NA),
+	PINGROUP(40, NA, cri_trng0, NA, NA, NA, NA, qdss_tracedata_b, NA,
+		 atest_bbrx0),
+	PINGROUP(41, NA, NA, NA, NA, NA, qdss_tracedata_b, NA,
+		 atest_combodac_to_gpio_native, NA),
+	PINGROUP(42, NA, cri_trng, NA, NA, qdss_tracedata_b, NA, NA, NA, NA),
+	PINGROUP(43, NA, NA, NA, NA, qdss_tracedata_b, NA, NA, NA, NA),
+	PINGROUP(44, NA, NA, qdss_cti_trig_in_b0, NA,
+		 atest_gpsadc_dtest0_native, NA, NA, NA, NA),
+	PINGROUP(45, NA, NA, qdss_cti_trig_out_b0, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA),
+	PINGROUP(46, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA),
+	PINGROUP(47, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA),
+	PINGROUP(48, NA, NA, qdss_tracedata_b, NA, NA, NA, NA, NA, NA),
+	PINGROUP(49, NA, NA, qdss_tracectl_b, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA),
+	PINGROUP(50, NA, NA, qdss_traceclk_b, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA),
+	PINGROUP(51, NA, pa_indicator, NA, qdss_tracedata_b, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA),
+	PINGROUP(52, NA, NA, NA, qdss_tracedata_b, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA),
+	PINGROUP(53, NA, modem_tsync, nav_tsync_out_a, nav_ptp_pps_in_a,
+		 ptp_pps_out_a, qdss_tracedata_b, NA, NA, NA),
+	PINGROUP(54, NA, qdss_tracedata_b, NA, atest_combodac_to_gpio_native,
+		 NA, NA, NA, NA, NA),
+	PINGROUP(55, gsm0_tx, NA, qdss_tracedata_b, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA),
+	PINGROUP(56, NA, NA, qdss_cti_trig_in_b1, NA, NA, NA, NA, NA, NA),
+	PINGROUP(57, NA, cri_trng1, NA, qdss_cti_trig_out_b1, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA),
+	PINGROUP(58, NA, ssbi1, NA, qdss_tracedata_b, NA,
+		 atest_gpsadc_dtest1_native, NA, NA, NA),
+	PINGROUP(59, NA, ssbi2, NA, qdss_tracedata_b, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA),
+	PINGROUP(60, atest_char3, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(61, atest_char2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(62, atest_char1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(63, atest_char0, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(64, atest_char, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(65, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(66, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(67, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(68, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(69, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(70, NA, NA, ebi0_wrcdc, NA, NA, NA, NA, NA, NA),
+	PINGROUP(71, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(72, ldo_update, NA, gcc_tlmm, NA, NA, NA, NA, NA, NA),
+	PINGROUP(73, ldo_en, dbg_out, NA, NA, NA, atest_tsens, NA, NA, NA),
+	PINGROUP(74, ebi2_lcd, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(75, nav_tsync_out_b, nav_ptp_pps_in_b, ptp_pps_out_b, NA,
+		 qdss_tracedata_a, NA, NA, NA, NA),
+	PINGROUP(76, pbs0, sec_mi2s, blsp3_spi, pwr_modem_enabled_a, NA,
+		 qdss_tracedata_a, NA, NA, NA),
+	PINGROUP(77, pbs1, sec_mi2s, blsp2_spi, pwr_modem_enabled_b, NA,
+		 qdss_tracedata_a, NA, NA, NA),
+	PINGROUP(78, pbs2, sec_mi2s, blsp1_spi, ebi2_lcd, m_voc,
+		 pwr_nav_enabled_b, NA, qdss_tracedata_a, NA),
+	PINGROUP(79, sec_mi2s, NA, pwr_crypto_enabled_b, NA, qdss_tracedata_a,
+		 NA, NA, NA, NA),
+	SDC_QDSD_PINGROUP(sdc1_clk, 0x10a000, 13, 6),
+	SDC_QDSD_PINGROUP(sdc1_cmd, 0x10a000, 11, 3),
+	SDC_QDSD_PINGROUP(sdc1_data, 0x10a000, 9, 0),
+	SDC_QDSD_PINGROUP(sdc2_clk, 0x109000, 14, 6),
+	SDC_QDSD_PINGROUP(sdc2_cmd, 0x109000, 11, 3),
+	SDC_QDSD_PINGROUP(sdc2_data, 0x109000, 9, 0),
+	SDC_QDSD_PINGROUP(qdsd_clk, 0x19c000, 3, 0),
+	SDC_QDSD_PINGROUP(qdsd_cmd, 0x19c000, 8, 5),
+	SDC_QDSD_PINGROUP(qdsd_data0, 0x19c000, 13, 10),
+	SDC_QDSD_PINGROUP(qdsd_data1, 0x19c000, 18, 15),
+	SDC_QDSD_PINGROUP(qdsd_data2, 0x19c000, 23, 20),
+	SDC_QDSD_PINGROUP(qdsd_data3, 0x19c000, 28, 25),
+};
+
+static const struct msm_pinctrl_soc_data mdm9607_pinctrl = {
+	.pins = mdm9607_pins,
+	.npins = ARRAY_SIZE(mdm9607_pins),
+	.functions = mdm9607_functions,
+	.nfunctions = ARRAY_SIZE(mdm9607_functions),
+	.groups = mdm9607_groups,
+	.ngroups = ARRAY_SIZE(mdm9607_groups),
+	.ngpios = 80,
+};
+
+static int mdm9607_pinctrl_probe(struct platform_device *pdev)
+{
+	return msm_pinctrl_probe(pdev, &mdm9607_pinctrl);
+}
+
+static const struct of_device_id mdm9607_pinctrl_of_match[] = {
+	{ .compatible = "qcom,mdm9607-pinctrl", },
+	{ },
+};
+
+static struct platform_driver mdm9607_pinctrl_driver = {
+	.driver = {
+		.name = "mdm9607-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = mdm9607_pinctrl_of_match,
+	},
+	.probe = mdm9607_pinctrl_probe,
+	.remove = msm_pinctrl_remove,
+};
+
+static int __init mdm9607_pinctrl_init(void)
+{
+	return platform_driver_register(&mdm9607_pinctrl_driver);
+}
+arch_initcall(mdm9607_pinctrl_init);
+
+static void __exit mdm9607_pinctrl_exit(void)
+{
+	platform_driver_unregister(&mdm9607_pinctrl_driver);
+}
+module_exit(mdm9607_pinctrl_exit);
+
+MODULE_DESCRIPTION("QTI mdm9607 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, mdm9607_pinctrl_of_match);
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 782ce62..5b34bbcd 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -47,6 +47,16 @@
 	  Kernel and user-space processes can call the IPA driver
 	  to configure IPA core.
 
+config IPA_WDI_UNIFIED_API
+	bool "IPA WDI unified API support"
+	depends on IPA3
+	help
+	  This driver supports IPA WDI unified API.
+	  WDI is the interface between IPA micro controller and WLAN chipset.
+	  It is designed to support IPA HW accelerating path for WLAN use case.
+	  The IPA WDI unified API supports all WDI versions through a unified
+	  interface.
+
 config RMNET_IPA3
 	tristate "IPA3 RMNET WWAN Network Device"
 	depends on IPA3 && MSM_QMI_INTERFACE
@@ -214,4 +224,14 @@
 	  External Display driver was added to support the communication
 	  between external display driver and its counterparts.
 
+config MSM_RMNET_BAM
+        bool "RMNET BAM Driver"
+        depends on MSM_BAM_DMUX
+        default n
+        help
+          Implements RMNET over BAM interface.
+          RMNET provides a virtual ethernet interface
+          for routing IP packets within the MSM using
+          BAM as a physical transport.
+
 endmenu
diff --git a/drivers/platform/msm/Makefile b/drivers/platform/msm/Makefile
index d0f0216f..06ff2ca 100644
--- a/drivers/platform/msm/Makefile
+++ b/drivers/platform/msm/Makefile
@@ -7,6 +7,7 @@
 obj-$(CONFIG_SPS) += sps/
 obj-$(CONFIG_QPNP_COINCELL) += qpnp-coincell.o
 obj-$(CONFIG_QPNP_REVID) += qpnp-revid.o
+obj-$(CONFIG_MSM_RMNET_BAM) += msm_rmnet_bam.o
 obj-$(CONFIG_GPIO_USB_DETECT) += gpio-usbdetect.o
 obj-$(CONFIG_EP_PCIE) += ep_pcie/
 obj-$(CONFIG_MSM_MHI_DEV) += mhi_dev/
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_com.h b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
index 00ca8dc4..33e0314 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_com.h
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
@@ -120,6 +120,12 @@
 
 #define PCIE20_MHICFG                  0x110
 #define PCIE20_BHI_EXECENV             0x228
+#define PCIE20_MHIVER                  0x108
+#define PCIE20_MHICTRL                 0x138
+#define PCIE20_MHISTATUS               0x148
+#define PCIE20_BHI_VERSION_LOWER	0x200
+#define PCIE20_BHI_VERSION_UPPER	0x204
+#define PCIE20_BHI_INTVEC		0x220
 
 #define PCIE20_AUX_CLK_FREQ_REG        0xB40
 
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
index 055f026..db6f689 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
@@ -497,6 +497,22 @@
 	ep_pcie_write_mask(dev->dm_core + PCIE20_MISC_CONTROL_1, BIT(0), 0);
 }
 
+static void ep_pcie_config_mmio(struct ep_pcie_dev_t *dev)
+{
+	EP_PCIE_DBG(dev,
+		"Initial version of MMIO is:0x%x\n",
+		readl_relaxed(dev->mmio + PCIE20_MHIVER));
+
+	ep_pcie_write_reg(dev->mmio, PCIE20_MHICFG, 0x02800880);
+	ep_pcie_write_reg(dev->mmio, PCIE20_BHI_EXECENV, 0x2);
+	ep_pcie_write_reg(dev->mmio, PCIE20_MHICTRL, 0x0);
+	ep_pcie_write_reg(dev->mmio, PCIE20_MHISTATUS, 0x0);
+	ep_pcie_write_reg(dev->mmio, PCIE20_MHIVER, 0x1000000);
+	ep_pcie_write_reg(dev->mmio, PCIE20_BHI_VERSION_LOWER, 0x2);
+	ep_pcie_write_reg(dev->mmio, PCIE20_BHI_VERSION_UPPER, 0x1);
+	ep_pcie_write_reg(dev->mmio, PCIE20_BHI_INTVEC, 0xffffffff);
+}
+
 static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
 {
 	EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev);
@@ -667,9 +683,6 @@
 
 		/* Configure BARs */
 		ep_pcie_bar_init(dev);
-
-		ep_pcie_write_reg(dev->mmio, PCIE20_MHICFG, 0x02800880);
-		ep_pcie_write_reg(dev->mmio, PCIE20_BHI_EXECENV, 0x2);
 	}
 
 	/* Configure IRQ events */
@@ -690,6 +703,16 @@
 			dev->rev,
 			readl_relaxed(dev->parf + PCIE20_PARF_INT_ALL_MASK));
 	}
+
+	if (dev->active_config) {
+		ep_pcie_write_reg(dev->dm_core, PCIE20_AUX_CLK_FREQ_REG, 0x14);
+
+		EP_PCIE_DBG2(dev, "PCIe V%d: Enable L1.\n", dev->rev);
+		ep_pcie_write_mask(dev->parf + PCIE20_PARF_PM_CTRL, BIT(5), 0);
+	}
+
+	/* Configure MMIO */
+	ep_pcie_config_mmio(dev);
 }
 
 static void ep_pcie_config_inbound_iatu(struct ep_pcie_dev_t *dev)
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 754c1f4..da60ff5 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -269,6 +269,9 @@
 	ipa3_transport_release_resource);
 static void ipa_gsi_notify_cb(struct gsi_per_notify *notify);
 
+static int ipa3_attach_to_smmu(void);
+static int ipa3_alloc_pkt_init(void);
+
 static void ipa3_load_ipa_fw(struct work_struct *work);
 static DECLARE_WORK(ipa3_fw_loading_work, ipa3_load_ipa_fw);
 
@@ -277,15 +280,12 @@
 	ipa_dec_clients_disable_clks_on_wq);
 
 static struct ipa3_plat_drv_res ipa3_res = {0, };
-struct msm_bus_scale_pdata *ipa3_bus_scale_table;
 
 static struct clk *ipa3_clk;
 
 struct ipa3_context *ipa3_ctx;
-static struct device *master_dev;
-struct platform_device *ipa3_pdev;
 static struct {
-	bool present;
+	bool present[IPA_SMMU_CB_MAX];
 	bool arm_smmu;
 	bool fast_map;
 	bool s1_bypass_arr[IPA_SMMU_CB_MAX];
@@ -508,42 +508,19 @@
 }
 
 /**
- * ipa3_get_smmu_ctx()- Return the wlan smmu context
+ * ipa3_get_smmu_ctx()- Return smmu context for the given cb_type
  *
  * Return value: pointer to smmu context address
  */
-struct ipa_smmu_cb_ctx *ipa3_get_smmu_ctx(void)
+struct ipa_smmu_cb_ctx *ipa3_get_smmu_ctx(enum ipa_smmu_cb_type cb_type)
 {
-	return &smmu_cb[IPA_SMMU_CB_AP];
-}
-
-/**
- * ipa3_get_wlan_smmu_ctx()- Return the wlan smmu context
- *
- * Return value: pointer to smmu context address
- */
-struct ipa_smmu_cb_ctx *ipa3_get_wlan_smmu_ctx(void)
-{
-	return &smmu_cb[IPA_SMMU_CB_WLAN];
-}
-
-/**
- * ipa3_get_uc_smmu_ctx()- Return the uc smmu context
- *
- * Return value: pointer to smmu context address
- */
-struct ipa_smmu_cb_ctx *ipa3_get_uc_smmu_ctx(void)
-{
-	return &smmu_cb[IPA_SMMU_CB_UC];
+	return &smmu_cb[cb_type];
 }
 
 static int ipa3_open(struct inode *inode, struct file *filp)
 {
-	struct ipa3_context *ctx = NULL;
-
 	IPADBG_LOW("ENTER\n");
-	ctx = container_of(inode->i_cdev, struct ipa3_context, cdev);
-	filp->private_data = ctx;
+	filp->private_data = ipa3_ctx;
 
 	return 0;
 }
@@ -3509,6 +3486,11 @@
 */
 void ipa3_enable_clks(void)
 {
+	if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) {
+		IPAERR("not supported in this mode\n");
+		return;
+	}
+
 	IPADBG("enabling IPA clocks and bus voting\n");
 
 	if (msm_bus_scale_client_update_request(ipa3_ctx->ipa_bus_hdl,
@@ -3540,6 +3522,11 @@
 */
 void ipa3_disable_clks(void)
 {
+	if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) {
+		IPAERR("not supported in this mode\n");
+		return;
+	}
+
 	IPADBG("disabling IPA clocks and bus voting\n");
 
 	ipa3_ctx->ctrl->ipa3_disable_clks();
@@ -3870,6 +3857,11 @@
 	if (!ipa3_ctx->enable_clock_scaling)
 		return 0;
 
+	if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) {
+		IPAERR("not supported in this mode\n");
+		return 0;
+	}
+
 	IPADBG_LOW("idx = %d\n", idx);
 
 	if (idx <= 0 || idx >= ipa3_ctx->ctrl->msm_bus_data_ptr->num_usecases) {
@@ -3921,6 +3913,11 @@
 	enum ipa_voltage_level needed_voltage;
 	u32 clk_rate;
 
+	if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL) {
+		IPAERR("not supported in this mode\n");
+		return 0;
+	}
+
 	IPADBG_LOW("floor_voltage=%d, bandwidth_mbps=%u",
 					floor_voltage, bandwidth_mbps);
 
@@ -4177,7 +4174,7 @@
 
 	/*register IPA IRQ handler*/
 	result = ipa3_interrupts_init(ipa3_res.ipa_irq, 0,
-			master_dev);
+			&ipa3_ctx->master_pdev->dev);
 	if (result) {
 		IPAERR("ipa interrupts initialization failed\n");
 		return -ENODEV;
@@ -4195,7 +4192,7 @@
 	return 0;
 
 fail_add_interrupt_handler:
-	free_irq(ipa3_res.ipa_irq, master_dev);
+	free_irq(ipa3_res.ipa_irq, &ipa3_ctx->master_pdev->dev);
 	return result;
 }
 
@@ -4411,6 +4408,78 @@
 	if (ipa3_ctx->ipa_hw_type != IPA_HW_v4_0)
 		ipa3_proxy_clk_vote();
 
+	/* SMMU was already attached if used, safe to do allocations */
+	if (ipahal_init(ipa3_ctx->ipa_hw_type, ipa3_ctx->mmio,
+		ipa3_ctx->pdev)) {
+		IPAERR("fail to init ipahal\n");
+		result = -EFAULT;
+		goto fail_ipahal;
+	}
+
+	result = ipa3_init_hw();
+	if (result) {
+		IPAERR(":error initializing HW\n");
+		result = -ENODEV;
+		goto fail_init_hw;
+	}
+	IPADBG("IPA HW initialization sequence completed");
+
+	ipa3_ctx->ipa_num_pipes = ipa3_get_num_pipes();
+	if (ipa3_ctx->ipa_num_pipes > IPA3_MAX_NUM_PIPES) {
+		IPAERR("IPA has more pipes then supported has %d, max %d\n",
+			ipa3_ctx->ipa_num_pipes, IPA3_MAX_NUM_PIPES);
+		result = -ENODEV;
+		goto fail_init_hw;
+	}
+
+	ipa3_ctx->ctrl->ipa_sram_read_settings();
+	IPADBG("SRAM, size: 0x%x, restricted bytes: 0x%x\n",
+		ipa3_ctx->smem_sz, ipa3_ctx->smem_restricted_bytes);
+
+	IPADBG("hdr_lcl=%u ip4_rt_hash=%u ip4_rt_nonhash=%u\n",
+		ipa3_ctx->hdr_tbl_lcl, ipa3_ctx->ip4_rt_tbl_hash_lcl,
+		ipa3_ctx->ip4_rt_tbl_nhash_lcl);
+
+	IPADBG("ip6_rt_hash=%u ip6_rt_nonhash=%u\n",
+		ipa3_ctx->ip6_rt_tbl_hash_lcl, ipa3_ctx->ip6_rt_tbl_nhash_lcl);
+
+	IPADBG("ip4_flt_hash=%u ip4_flt_nonhash=%u\n",
+		ipa3_ctx->ip4_flt_tbl_hash_lcl,
+		ipa3_ctx->ip4_flt_tbl_nhash_lcl);
+
+	IPADBG("ip6_flt_hash=%u ip6_flt_nonhash=%u\n",
+		ipa3_ctx->ip6_flt_tbl_hash_lcl,
+		ipa3_ctx->ip6_flt_tbl_nhash_lcl);
+
+	if (ipa3_ctx->smem_reqd_sz > ipa3_ctx->smem_sz) {
+		IPAERR("SW expect more core memory, needed %d, avail %d\n",
+			ipa3_ctx->smem_reqd_sz, ipa3_ctx->smem_sz);
+		result = -ENOMEM;
+		goto fail_init_hw;
+	}
+
+	result = ipa3_allocate_dma_task_for_gsi();
+	if (result) {
+		IPAERR("failed to allocate dma task\n");
+		goto fail_dma_task;
+	}
+
+	if (ipa3_nat_ipv6ct_init_devices()) {
+		IPAERR("unable to init NAT and IPv6CT devices\n");
+		result = -ENODEV;
+		goto fail_nat_ipv6ct_init_dev;
+	}
+
+	result = ipa3_alloc_pkt_init();
+	if (result) {
+		IPAERR("Failed to alloc pkt_init payload\n");
+		result = -ENODEV;
+		goto fail_allok_pkt_init;
+	}
+
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5)
+		ipa3_enable_dcd();
+
 	/*
 	 * indication whether working in MHI config or non MHI config is given
 	 * in ipa3_write which is launched before ipa3_post_init. i.e. from
@@ -4563,6 +4632,15 @@
 fail_register_device:
 	ipa3_destroy_flt_tbl_idrs();
 	ipa3_proxy_clk_unvote();
+fail_allok_pkt_init:
+	ipa3_nat_ipv6ct_destroy_devices();
+fail_nat_ipv6ct_init_dev:
+	ipa3_free_dma_task_for_gsi();
+fail_dma_task:
+fail_init_hw:
+	ipahal_destroy();
+fail_ipahal:
+
 	return result;
 }
 
@@ -4573,7 +4651,7 @@
 
 	IPADBG("Manual FW loading process initiated\n");
 
-	result = request_firmware(&fw, IPA_FWS_PATH, ipa3_ctx->dev);
+	result = request_firmware(&fw, IPA_FWS_PATH, ipa3_ctx->cdev.dev);
 	if (result < 0) {
 		IPAERR("request_firmware failed, error %d\n", result);
 		return result;
@@ -4629,6 +4707,12 @@
 
 	IPADBG("Entry\n");
 
+	result = ipa3_attach_to_smmu();
+	if (result) {
+		IPAERR("IPA attach to smmu failed %d\n", result);
+		return;
+	}
+
 	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
 
 	if (ipa3_is_msm_device() || (ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5))
@@ -4644,7 +4728,7 @@
 	}
 	pr_info("IPA FW loaded successfully\n");
 
-	result = ipa3_post_init(&ipa3_res, ipa3_ctx->dev);
+	result = ipa3_post_init(&ipa3_res, ipa3_ctx->cdev.dev);
 	if (result)
 		IPAERR("IPA post init failed %d\n", result);
 }
@@ -4867,12 +4951,13 @@
 * Configure GSI registers (in GSI case)
 */
 static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
-		struct device *ipa_dev)
+		struct platform_device *ipa_pdev)
 {
 	int result = 0;
 	int i;
 	struct ipa3_rt_tbl_set *rset;
 	struct ipa_active_client_logging_info log_info;
+	struct cdev *cdev;
 
 	IPADBG("IPA Driver initialization started\n");
 
@@ -4887,16 +4972,10 @@
 	if (ipa3_ctx->logbuf == NULL)
 		IPAERR("failed to create IPC log, continue...\n");
 
-	ipa3_ctx->pdev = ipa_dev;
-	ipa3_ctx->uc_pdev = ipa_dev;
-	ipa3_ctx->smmu_present = smmu_info.present;
-	if (!ipa3_ctx->smmu_present) {
-		for (i = 0; i < IPA_SMMU_CB_MAX; i++)
-			ipa3_ctx->s1_bypass_arr[i] = true;
-	} else {
-		ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_AP] =
-			smmu_info.s1_bypass_arr[IPA_SMMU_CB_AP];
-	}
+	/* ipa3_ctx->pdev and ipa3_ctx->uc_pdev will be set in the smmu probes*/
+	ipa3_ctx->master_pdev = ipa_pdev;
+	for (i = 0; i < IPA_SMMU_CB_MAX; i++)
+		ipa3_ctx->s1_bypass_arr[i] = true;
 
 	ipa3_ctx->ipa_wrapper_base = resource_p->ipa_mem_base;
 	ipa3_ctx->ipa_wrapper_size = resource_p->ipa_mem_size;
@@ -4917,6 +4996,10 @@
 	ipa3_ctx->ipa3_active_clients_logging.log_rdy = false;
 	ipa3_ctx->mhi_evid_limits[0] = resource_p->mhi_evid_limits[0];
 	ipa3_ctx->mhi_evid_limits[1] = resource_p->mhi_evid_limits[1];
+
+	WARN(ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_NORMAL,
+		"Non NORMAL IPA HW mode, is this emulation platform ?");
+
 	if (resource_p->ipa_tz_unlock_reg) {
 		ipa3_ctx->ipa_tz_unlock_reg_num =
 			resource_p->ipa_tz_unlock_reg_num;
@@ -4961,31 +5044,36 @@
 		goto fail_bind;
 	}
 
-	result = ipa3_init_mem_partition(master_dev->of_node);
+	result = ipa3_init_mem_partition(ipa3_ctx->master_pdev->dev.of_node);
 	if (result) {
 		IPAERR(":ipa3_init_mem_partition failed!\n");
 		result = -ENODEV;
 		goto fail_init_mem_partition;
 	}
 
-	if (ipa3_bus_scale_table) {
+	if (ipa3_ctx->ipa3_hw_mode != IPA_HW_MODE_VIRTUAL) {
+		ipa3_ctx->ctrl->msm_bus_data_ptr =
+			msm_bus_cl_get_pdata(ipa3_ctx->master_pdev);
+		if (ipa3_ctx->ctrl->msm_bus_data_ptr == NULL) {
+			IPAERR("failed to get bus scaling\n");
+			goto fail_bus_reg;
+		}
 		IPADBG("Use bus scaling info from device tree #usecases=%d\n",
-			ipa3_bus_scale_table->num_usecases);
-		ipa3_ctx->ctrl->msm_bus_data_ptr = ipa3_bus_scale_table;
-	}
+			ipa3_ctx->ctrl->msm_bus_data_ptr->num_usecases);
 
-	/* get BUS handle */
-	ipa3_ctx->ipa_bus_hdl =
-		msm_bus_scale_register_client(
-			ipa3_ctx->ctrl->msm_bus_data_ptr);
-	if (!ipa3_ctx->ipa_bus_hdl) {
-		IPAERR("fail to register with bus mgr!\n");
-		result = -ENODEV;
-		goto fail_bus_reg;
+		/* get BUS handle */
+		ipa3_ctx->ipa_bus_hdl =
+			msm_bus_scale_register_client(
+				ipa3_ctx->ctrl->msm_bus_data_ptr);
+		if (!ipa3_ctx->ipa_bus_hdl) {
+			IPAERR("fail to register with bus mgr!\n");
+			result = -ENODEV;
+			goto fail_bus_reg;
+		}
 	}
 
 	/* get IPA clocks */
-	result = ipa3_get_clks(master_dev);
+	result = ipa3_get_clks(&ipa3_ctx->master_pdev->dev);
 	if (result)
 		goto fail_clk;
 
@@ -5013,55 +5101,6 @@
 		goto fail_remap;
 	}
 
-	if (ipahal_init(ipa3_ctx->ipa_hw_type, ipa3_ctx->mmio,
-		ipa3_ctx->pdev)) {
-		IPAERR("fail to init ipahal\n");
-		result = -EFAULT;
-		goto fail_ipahal;
-	}
-
-	result = ipa3_init_hw();
-	if (result) {
-		IPAERR(":error initializing HW.\n");
-		result = -ENODEV;
-		goto fail_init_hw;
-	}
-	IPADBG("IPA HW initialization sequence completed");
-
-	ipa3_ctx->ipa_num_pipes = ipa3_get_num_pipes();
-	if (ipa3_ctx->ipa_num_pipes > IPA3_MAX_NUM_PIPES) {
-		IPAERR("IPA has more pipes then supported! has %d, max %d\n",
-			ipa3_ctx->ipa_num_pipes, IPA3_MAX_NUM_PIPES);
-		result = -ENODEV;
-		goto fail_init_hw;
-	}
-
-	ipa3_ctx->ctrl->ipa_sram_read_settings();
-	IPADBG("SRAM, size: 0x%x, restricted bytes: 0x%x\n",
-		ipa3_ctx->smem_sz, ipa3_ctx->smem_restricted_bytes);
-
-	IPADBG("hdr_lcl=%u ip4_rt_hash=%u ip4_rt_nonhash=%u\n",
-		ipa3_ctx->hdr_tbl_lcl, ipa3_ctx->ip4_rt_tbl_hash_lcl,
-		ipa3_ctx->ip4_rt_tbl_nhash_lcl);
-
-	IPADBG("ip6_rt_hash=%u ip6_rt_nonhash=%u\n",
-		ipa3_ctx->ip6_rt_tbl_hash_lcl, ipa3_ctx->ip6_rt_tbl_nhash_lcl);
-
-	IPADBG("ip4_flt_hash=%u ip4_flt_nonhash=%u\n",
-		ipa3_ctx->ip4_flt_tbl_hash_lcl,
-		ipa3_ctx->ip4_flt_tbl_nhash_lcl);
-
-	IPADBG("ip6_flt_hash=%u ip6_flt_nonhash=%u\n",
-		ipa3_ctx->ip6_flt_tbl_hash_lcl,
-		ipa3_ctx->ip6_flt_tbl_nhash_lcl);
-
-	if (ipa3_ctx->smem_reqd_sz > ipa3_ctx->smem_sz) {
-		IPAERR("SW expect more core memory, needed %d, avail %d\n",
-			ipa3_ctx->smem_reqd_sz, ipa3_ctx->smem_sz);
-		result = -ENOMEM;
-		goto fail_init_hw;
-	}
-
 	mutex_init(&ipa3_ctx->ipa3_active_clients.mutex);
 
 	IPA_ACTIVE_CLIENTS_PREP_SPECIAL(log_info, "PROXY_CLK_VOTE");
@@ -5160,13 +5199,6 @@
 		goto fail_rx_pkt_wrapper_cache;
 	}
 
-	/* allocate memory for DMA_TASK workaround */
-	result = ipa3_allocate_dma_task_for_gsi();
-	if (result) {
-		IPAERR("failed to allocate dma task\n");
-		goto fail_dma_task;
-	}
-
 	/* init the various list heads */
 	INIT_LIST_HEAD(&ipa3_ctx->hdr_tbl.head_hdr_entry_list);
 	for (i = 0; i < IPA_HDR_BIN_MAX; i++) {
@@ -5210,29 +5242,23 @@
 	spin_lock_init(&ipa3_ctx->wc_memb.ipa_tx_mul_spinlock);
 	INIT_LIST_HEAD(&ipa3_ctx->wc_memb.wlan_comm_desc_list);
 
-	ipa3_ctx->class = class_create(THIS_MODULE, DRV_NAME);
+	ipa3_ctx->cdev.class = class_create(THIS_MODULE, DRV_NAME);
 
-	result = alloc_chrdev_region(&ipa3_ctx->dev_num, 0, 1, DRV_NAME);
+	result = alloc_chrdev_region(&ipa3_ctx->cdev.dev_num, 0, 1, DRV_NAME);
 	if (result) {
 		IPAERR("alloc_chrdev_region err.\n");
 		result = -ENODEV;
 		goto fail_alloc_chrdev_region;
 	}
 
-	ipa3_ctx->dev = device_create(ipa3_ctx->class, NULL, ipa3_ctx->dev_num,
-			ipa3_ctx, DRV_NAME);
-	if (IS_ERR(ipa3_ctx->dev)) {
+	ipa3_ctx->cdev.dev = device_create(ipa3_ctx->cdev.class, NULL,
+		 ipa3_ctx->cdev.dev_num, ipa3_ctx, DRV_NAME);
+	if (IS_ERR(ipa3_ctx->cdev.dev)) {
 		IPAERR(":device_create err.\n");
 		result = -ENODEV;
 		goto fail_device_create;
 	}
 
-	if (ipa3_nat_ipv6ct_init_devices()) {
-		IPAERR("unable to init NAT and IPv6CT devices\n");
-		result = -ENODEV;
-		goto fail_nat_ipv6ct_init_dev;
-	}
-
 	/* Create a wakeup source. */
 	wakeup_source_init(&ipa3_ctx->w_lock, "IPA_WS");
 	spin_lock_init(&ipa3_ctx->wakelock_ref_cnt.spinlock);
@@ -5263,16 +5289,6 @@
 		}
 	}
 
-	result = ipa3_alloc_pkt_init();
-	if (result) {
-		IPAERR("Failed to alloc pkt_init payload\n");
-		result = -ENODEV;
-		goto fail_allok_pkt_init;
-	}
-
-	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v3_5)
-		ipa3_enable_dcd();
-
 	INIT_LIST_HEAD(&ipa3_ctx->ipa_ready_cb_list);
 
 	init_completion(&ipa3_ctx->init_completion_obj);
@@ -5301,19 +5317,20 @@
 		}
 	}
 
-	cdev_init(&ipa3_ctx->cdev, &ipa3_drv_fops);
-	ipa3_ctx->cdev.owner = THIS_MODULE;
-	ipa3_ctx->cdev.ops = &ipa3_drv_fops;  /* from LDD3 */
+	cdev = &ipa3_ctx->cdev.cdev;
+	cdev_init(cdev, &ipa3_drv_fops);
+	cdev->owner = THIS_MODULE;
+	cdev->ops = &ipa3_drv_fops;  /* from LDD3 */
 
-	result = cdev_add(&ipa3_ctx->cdev, ipa3_ctx->dev_num, 1);
+	result = cdev_add(cdev, ipa3_ctx->cdev.dev_num, 1);
 	if (result) {
 		IPAERR(":cdev_add err=%d\n", -result);
 		result = -ENODEV;
 		goto fail_cdev_add;
 	}
 	IPADBG("ipa cdev added successful. major:%d minor:%d\n",
-			MAJOR(ipa3_ctx->dev_num),
-			MINOR(ipa3_ctx->dev_num));
+			MAJOR(ipa3_ctx->cdev.dev_num),
+			MINOR(ipa3_ctx->cdev.dev_num));
 	/*
 	 * for IPA 4.0 offline charge is not needed and we need to prevent
 	 * power collapse until IPA uC is loaded.
@@ -5328,7 +5345,6 @@
 fail_gsi_pre_fw_load_init:
 	ipa3_dma_shutdown();
 fail_ipa_dma_setup:
-fail_allok_pkt_init:
 	if (ipa3_ctx->use_ipa_pm)
 		ipa_pm_destroy();
 	else
@@ -5337,11 +5353,9 @@
 	if (!ipa3_ctx->use_ipa_pm)
 		ipa_rm_exit();
 fail_ipa_rm_init:
-	ipa3_nat_ipv6ct_destroy_devices();
-fail_nat_ipv6ct_init_dev:
-	device_destroy(ipa3_ctx->class, ipa3_ctx->dev_num);
+	device_destroy(ipa3_ctx->cdev.class, ipa3_ctx->cdev.dev_num);
 fail_device_create:
-	unregister_chrdev_region(ipa3_ctx->dev_num, 1);
+	unregister_chrdev_region(ipa3_ctx->cdev.dev_num, 1);
 fail_alloc_chrdev_region:
 	idr_destroy(&ipa3_ctx->ipa_idr);
 	rset = &ipa3_ctx->reap_rt_tbl_set[IPA_IP_v6];
@@ -5350,8 +5364,6 @@
 	idr_destroy(&rset->rule_ids);
 	idr_destroy(&ipa3_ctx->rt_tbl_set[IPA_IP_v6].rule_ids);
 	idr_destroy(&ipa3_ctx->rt_tbl_set[IPA_IP_v4].rule_ids);
-	ipa3_free_dma_task_for_gsi();
-fail_dma_task:
 	kmem_cache_destroy(ipa3_ctx->rx_pkt_wrapper_cache);
 fail_rx_pkt_wrapper_cache:
 	kmem_cache_destroy(ipa3_ctx->tx_pkt_wrapper_cache);
@@ -5374,8 +5386,6 @@
 fail_create_transport_wq:
 	destroy_workqueue(ipa3_ctx->power_mgmt_wq);
 fail_init_hw:
-	ipahal_destroy();
-fail_ipahal:
 	iounmap(ipa3_ctx->mmio);
 fail_remap:
 	ipa3_disable_clks();
@@ -5385,12 +5395,11 @@
 		clk_put(ipa3_clk);
 	ipa3_clk = NULL;
 fail_clk:
-	msm_bus_scale_unregister_client(ipa3_ctx->ipa_bus_hdl);
+	if (ipa3_ctx->ipa_bus_hdl)
+		msm_bus_scale_unregister_client(ipa3_ctx->ipa_bus_hdl);
 fail_bus_reg:
-	if (ipa3_bus_scale_table) {
-		msm_bus_cl_clear_pdata(ipa3_bus_scale_table);
-		ipa3_bus_scale_table = NULL;
-	}
+	if (ipa3_ctx->ctrl->msm_bus_data_ptr)
+		msm_bus_cl_clear_pdata(ipa3_ctx->ctrl->msm_bus_data_ptr);
 fail_init_mem_partition:
 fail_bind:
 	kfree(ipa3_ctx->ctrl);
@@ -5777,7 +5786,7 @@
 
 static int ipa_smmu_wlan_cb_probe(struct device *dev)
 {
-	struct ipa_smmu_cb_ctx *cb = ipa3_get_wlan_smmu_ctx();
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN);
 	int atomic_ctx = 1;
 	int fast = 1;
 	int bypass = 1;
@@ -5788,6 +5797,11 @@
 
 	IPADBG("sub pdev=%p\n", dev);
 
+	if (!smmu_info.present[IPA_SMMU_CB_WLAN]) {
+		IPAERR("WLAN SMMU is disabled\n");
+		return 0;
+	}
+
 	cb->dev = dev;
 	cb->iommu = iommu_domain_alloc(dev->bus);
 	if (!cb->iommu) {
@@ -5797,7 +5811,8 @@
 	}
 	cb->valid = true;
 
-	if (of_property_read_bool(dev->of_node, "qcom,smmu-s1-bypass")) {
+	if (of_property_read_bool(dev->of_node, "qcom,smmu-s1-bypass") ||
+		ipa3_ctx->ipa_config_is_mhi) {
 		smmu_info.s1_bypass_arr[IPA_SMMU_CB_WLAN] = true;
 		ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_WLAN] = true;
 
@@ -5877,7 +5892,7 @@
 
 static int ipa_smmu_uc_cb_probe(struct device *dev)
 {
-	struct ipa_smmu_cb_ctx *cb = ipa3_get_uc_smmu_ctx();
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
 	int atomic_ctx = 1;
 	int bypass = 1;
 	int fast = 1;
@@ -5886,6 +5901,11 @@
 
 	IPADBG("UC CB PROBE sub pdev=%p\n", dev);
 
+	if (!smmu_info.present[IPA_SMMU_CB_UC]) {
+		IPAERR("UC SMMU is disabled\n");
+		return 0;
+	}
+
 	ret = of_property_read_u32_array(dev->of_node, "qcom,iova-mapping",
 			iova_ap_mapping, 2);
 	if (ret) {
@@ -5925,7 +5945,8 @@
 
 	IPADBG("UC CB PROBE sub pdev=%p set attribute\n", dev);
 
-	if (of_property_read_bool(dev->of_node, "qcom,smmu-s1-bypass")) {
+	if (of_property_read_bool(dev->of_node, "qcom,smmu-s1-bypass") ||
+		ipa3_ctx->ipa_config_is_mhi) {
 		smmu_info.s1_bypass_arr[IPA_SMMU_CB_UC] = true;
 		ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_UC] = true;
 
@@ -5985,7 +6006,7 @@
 
 static int ipa_smmu_ap_cb_probe(struct device *dev)
 {
-	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx();
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
 	int result;
 	int atomic_ctx = 1;
 	int fast = 1;
@@ -5999,6 +6020,11 @@
 
 	IPADBG("AP CB probe: sub pdev=%p\n", dev);
 
+	if (!smmu_info.present[IPA_SMMU_CB_AP]) {
+		IPAERR("AP SMMU is disabled");
+		return 0;
+	}
+
 	result = of_property_read_u32_array(dev->of_node, "qcom,iova-mapping",
 		iova_ap_mapping, 2);
 	if (result) {
@@ -6036,8 +6062,9 @@
 	cb->valid = true;
 
 	if (of_property_read_bool(dev->of_node,
-		"qcom,smmu-s1-bypass")) {
+		"qcom,smmu-s1-bypass") || ipa3_ctx->ipa_config_is_mhi) {
 		smmu_info.s1_bypass_arr[IPA_SMMU_CB_AP] = true;
+		ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_AP] = true;
 		if (iommu_domain_set_attr(cb->mapping->domain,
 				DOMAIN_ATTR_S1_BYPASS,
 				&bypass)) {
@@ -6049,6 +6076,7 @@
 		IPADBG("AP/USB SMMU S1 BYPASS\n");
 	} else {
 		smmu_info.s1_bypass_arr[IPA_SMMU_CB_AP] = false;
+		ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_AP] = false;
 		if (iommu_domain_set_attr(cb->mapping->domain,
 				DOMAIN_ATTR_ATOMIC,
 				&atomic_ctx)) {
@@ -6138,22 +6166,47 @@
 	}
 
 
-	smmu_info.present = true;
+	smmu_info.present[IPA_SMMU_CB_AP] = true;
+	ipa3_ctx->pdev = dev;
 
-	if (!ipa3_bus_scale_table)
-		ipa3_bus_scale_table = msm_bus_cl_get_pdata(ipa3_pdev);
+	return 0;
+}
 
-	/* Proceed to real initialization */
-	result = ipa3_pre_init(&ipa3_res, dev);
-	if (result) {
-		IPAERR("ipa_init failed\n");
-		arm_iommu_detach_device(cb->dev);
-		arm_iommu_release_mapping(cb->mapping);
-		cb->valid = false;
-		return result;
+static int ipa_smmu_cb_probe(struct device *dev, enum ipa_smmu_cb_type cb_type)
+{
+	switch (cb_type) {
+	case IPA_SMMU_CB_AP:
+		return ipa_smmu_ap_cb_probe(dev);
+	case IPA_SMMU_CB_WLAN:
+		return ipa_smmu_wlan_cb_probe(dev);
+	case IPA_SMMU_CB_UC:
+		return ipa_smmu_uc_cb_probe(dev);
+	case IPA_SMMU_CB_MAX:
+		IPAERR("Invalid cb_type\n");
 	}
+	return 0;
+}
 
-	return result;
+static int ipa3_attach_to_smmu(void)
+{
+	struct ipa_smmu_cb_ctx *cb;
+	int i, result;
+
+	ipa3_ctx->pdev = &ipa3_ctx->master_pdev->dev;
+	ipa3_ctx->uc_pdev = &ipa3_ctx->master_pdev->dev;
+
+	if (smmu_info.arm_smmu) {
+		IPADBG("smmu is enabled\n");
+		for (i = 0; i < IPA_SMMU_CB_MAX; i++) {
+			cb = ipa3_get_smmu_ctx(i);
+			result = ipa_smmu_cb_probe(cb->dev, i);
+			if (result)
+				IPAERR("probe failed for cb %d\n", i);
+		}
+	} else {
+		IPADBG("smmu is disabled\n");
+	}
+	return 0;
 }
 
 static irqreturn_t ipa3_smp2p_modem_clk_query_isr(int irq, void *ctxt)
@@ -6226,18 +6279,34 @@
 {
 	int result;
 	struct device *dev = &pdev_p->dev;
+	struct ipa_smmu_cb_ctx *cb;
 
 	IPADBG("IPA driver probing started\n");
 	IPADBG("dev->of_node->name = %s\n", dev->of_node->name);
 
-	if (of_device_is_compatible(dev->of_node, "qcom,ipa-smmu-ap-cb"))
-		return ipa_smmu_ap_cb_probe(dev);
+	if (of_device_is_compatible(dev->of_node, "qcom,ipa-smmu-ap-cb")) {
+		cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
+		cb->dev = dev;
+		smmu_info.present[IPA_SMMU_CB_AP] = true;
 
-	if (of_device_is_compatible(dev->of_node, "qcom,ipa-smmu-wlan-cb"))
-		return ipa_smmu_wlan_cb_probe(dev);
+		return 0;
+	}
 
-	if (of_device_is_compatible(dev->of_node, "qcom,ipa-smmu-uc-cb"))
-		return ipa_smmu_uc_cb_probe(dev);
+	if (of_device_is_compatible(dev->of_node, "qcom,ipa-smmu-wlan-cb")) {
+		cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN);
+		cb->dev = dev;
+		smmu_info.present[IPA_SMMU_CB_WLAN] = true;
+
+		return 0;
+	}
+
+	if (of_device_is_compatible(dev->of_node, "qcom,ipa-smmu-uc-cb")) {
+		cb =  ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
+		cb->dev = dev;
+		smmu_info.present[IPA_SMMU_CB_UC] = true;
+
+		return 0;
+	}
 
 	if (of_device_is_compatible(dev->of_node,
 	    "qcom,smp2pgpio-map-ipa-1-in"))
@@ -6247,10 +6316,6 @@
 	    "qcom,smp2pgpio-map-ipa-1-out"))
 		return ipa3_smp2p_probe(dev);
 
-	master_dev = dev;
-	if (!ipa3_pdev)
-		ipa3_pdev = pdev_p;
-
 	result = get_ipa_dts_configuration(pdev_p, &ipa3_res);
 	if (result) {
 		IPAERR("IPA dts parsing failed\n");
@@ -6292,15 +6357,13 @@
 				return -EOPNOTSUPP;
 			}
 		}
+	}
 
-		if (!ipa3_bus_scale_table)
-			ipa3_bus_scale_table = msm_bus_cl_get_pdata(pdev_p);
-		/* Proceed to real initialization */
-		result = ipa3_pre_init(&ipa3_res, dev);
-		if (result) {
-			IPAERR("ipa3_init failed\n");
-			return result;
-		}
+	/* Proceed to real initialization */
+	result = ipa3_pre_init(&ipa3_res, pdev_p);
+	if (result) {
+		IPAERR("ipa3_init failed\n");
+		return result;
 	}
 
 	result = of_platform_populate(pdev_p->dev.of_node,
@@ -6448,8 +6511,8 @@
 int ipa3_iommu_map(struct iommu_domain *domain,
 	unsigned long iova, phys_addr_t paddr, size_t size, int prot)
 {
-	struct ipa_smmu_cb_ctx *ap_cb = ipa3_get_smmu_ctx();
-	struct ipa_smmu_cb_ctx *uc_cb = ipa3_get_uc_smmu_ctx();
+	struct ipa_smmu_cb_ctx *ap_cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP);
+	struct ipa_smmu_cb_ctx *uc_cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
 
 	IPADBG("domain =0x%p iova 0x%lx\n", domain, iova);
 	IPADBG("paddr =0x%pa size 0x%x\n", &paddr, (u32)size);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index e88ab27..07773eb 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.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
@@ -1517,6 +1517,7 @@
 	char *entry;
 	size_t entry_size;
 	bool entry_zeroed;
+	bool entry_valid;
 	u32 i, num_entries = 0, id = *rule_id, pos = 0;
 
 	IPADBG("\n");
@@ -1538,20 +1539,33 @@
 			&entry_zeroed);
 		if (result) {
 			IPAERR(
-				"Failed to determine whether the %s entry is definitely zero",
-				ipahal_nat_type_str(nat_type));
+				"Failed to determine whether the %s entry is definitely zero\n"
+					, ipahal_nat_type_str(nat_type));
 			goto bail;
 		}
 		if (entry_zeroed)
 			continue;
 
-		pos += scnprintf(buff + pos, buff_size - pos,
-			"\tEntry_Index=%d\n", id);
+		result = ipahal_nat_is_entry_valid(nat_type, entry,
+			&entry_valid);
+		if (result) {
+			IPAERR(
+				"Failed to determine whether the %s entry is valid\n"
+					, ipahal_nat_type_str(nat_type));
+			goto bail;
+		}
+
+		if (entry_valid) {
+			++num_entries;
+			pos += scnprintf(buff + pos, buff_size - pos,
+				"\tEntry_Index=%d\n", id);
+		} else {
+			pos += scnprintf(buff + pos, buff_size - pos,
+				"\tEntry_Index=%d - Invalid Entry\n", id);
+		}
 
 		pos += ipahal_nat_stringify_entry(nat_type, entry,
 			buff + pos, buff_size - pos);
-
-		++num_entries;
 	}
 
 	if (num_entries)
@@ -1637,6 +1651,7 @@
 	char *pdn_entry;
 	size_t pdn_entry_size;
 	bool entry_zeroed;
+	bool entry_valid;
 	u32 pos = 0;
 
 	IPADBG("\n");
@@ -1654,13 +1669,25 @@
 			pdn_entry, &entry_zeroed);
 		if (result) {
 			IPAERR(
-				"Failed to determine whether the PDN entry is definitely zero");
+				"Failed to determine whether the PDN entry is definitely zero\n");
 			goto bail;
 		}
 		if (entry_zeroed)
 			continue;
 
-		pos += scnprintf(buff + pos, buff_size - pos, "PDN %d: ", i);
+		result = ipahal_nat_is_entry_valid(IPAHAL_NAT_IPV4_PDN,
+			pdn_entry, &entry_valid);
+		if (result) {
+			IPAERR(
+				"Failed to determine whether the PDN entry is valid\n");
+			goto bail;
+		}
+		if (entry_valid)
+			pos += scnprintf(buff + pos, buff_size - pos,
+				"PDN %d: ", i);
+		else
+			pos += scnprintf(buff + pos, buff_size - pos,
+				"PDN %d - Invalid: ", i);
 
 		pos += ipahal_nat_stringify_entry(IPAHAL_NAT_IPV4_PDN,
 			pdn_entry, buff + pos, buff_size - pos);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index d0db35a..386ad51 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1161,11 +1161,22 @@
 };
 
 /**
- * struct ipa3_context - IPA context
+ * struct ipa3_char_device_context - IPA character device
  * @class: pointer to the struct class
  * @dev_num: device number
  * @dev: the dev_t of the device
  * @cdev: cdev of the device
+ */
+struct ipa3_char_device_context {
+	struct class *class;
+	dev_t dev_num;
+	struct device *dev;
+	struct cdev cdev;
+};
+
+/**
+ * struct ipa3_context - IPA context
+ * @cdev: cdev context
  * @ep: list of all end points
  * @skip_ep_cfg_shadow: state to update filter table correctly across
   power-save
@@ -1251,10 +1262,7 @@
  * IPA context - holds all relevant info about IPA driver and its state
  */
 struct ipa3_context {
-	struct class *class;
-	dev_t dev_num;
-	struct device *dev;
-	struct cdev cdev;
+	struct ipa3_char_device_context cdev;
 	struct ipa3_ep_context ep[IPA3_MAX_NUM_PIPES];
 	bool skip_ep_cfg_shadow[IPA3_MAX_NUM_PIPES];
 	u32 ep_flt_bitmap;
@@ -1336,6 +1344,7 @@
 	u32 ipa_bus_hdl;
 	struct ipa3_controller *ctrl;
 	struct idr ipa_idr;
+	struct platform_device *master_pdev;
 	struct device *pdev;
 	struct device *uc_pdev;
 	spinlock_t idr_lock;
@@ -1361,7 +1370,6 @@
 	u32 ee;
 	bool apply_rg10_wa;
 	bool gsi_ch20_wa;
-	bool smmu_present;
 	bool s1_bypass_arr[IPA_SMMU_CB_MAX];
 	u32 wdi_map_cnt;
 	struct wakeup_source w_lock;
@@ -2278,9 +2286,7 @@
 int ipa_reset_all_flt_rt_stats(enum ipa_ip_type ip, bool filtering);
 
 u32 ipa3_get_num_pipes(void);
-struct ipa_smmu_cb_ctx *ipa3_get_smmu_ctx(void);
-struct ipa_smmu_cb_ctx *ipa3_get_wlan_smmu_ctx(void);
-struct ipa_smmu_cb_ctx *ipa3_get_uc_smmu_ctx(void);
+struct ipa_smmu_cb_ctx *ipa3_get_smmu_ctx(enum ipa_smmu_cb_type);
 struct iommu_domain *ipa3_get_smmu_domain(void);
 struct iommu_domain *ipa3_get_uc_smmu_domain(void);
 struct iommu_domain *ipa3_get_wlan_smmu_domain(void);
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 ec777bc..13d2511 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
@@ -495,7 +495,7 @@
 static int ipa_create_uc_smmu_mapping_pa(phys_addr_t pa, size_t len,
 		bool device, unsigned long *iova)
 {
-	struct ipa_smmu_cb_ctx *cb = ipa3_get_uc_smmu_ctx();
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
 	unsigned long va = roundup(cb->next_addr, PAGE_SIZE);
 	int prot = IOMMU_READ | IOMMU_WRITE;
 	size_t true_len = roundup(len + pa - rounddown(pa, PAGE_SIZE),
@@ -524,7 +524,7 @@
 static int ipa_create_uc_smmu_mapping_sgt(struct sg_table *sgt,
 		unsigned long *iova)
 {
-	struct ipa_smmu_cb_ctx *cb = ipa3_get_uc_smmu_ctx();
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
 	unsigned long va = roundup(cb->next_addr, PAGE_SIZE);
 	int prot = IOMMU_READ | IOMMU_WRITE;
 	int ret;
@@ -573,7 +573,7 @@
 
 static void ipa_release_uc_smmu_mappings(enum ipa_client_type client)
 {
-	struct ipa_smmu_cb_ctx *cb = ipa3_get_uc_smmu_ctx();
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_UC);
 	int i;
 	int j;
 	int start;
@@ -1810,7 +1810,7 @@
 
 int ipa3_create_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info)
 {
-	struct ipa_smmu_cb_ctx *cb = ipa3_get_wlan_smmu_ctx();
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN);
 	int i;
 	int ret = 0;
 	int prot = IOMMU_READ | IOMMU_WRITE;
@@ -1846,7 +1846,7 @@
 
 int ipa3_release_wdi_mapping(u32 num_buffers, struct ipa_wdi_buffer_info *info)
 {
-	struct ipa_smmu_cb_ctx *cb = ipa3_get_wlan_smmu_ctx();
+	struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN);
 	int i;
 	int ret = 0;
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 897da58..d33fc0f 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -1223,7 +1223,7 @@
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
-			QMB_MASTER_SELECT_PCIE,
+			QMB_MASTER_SELECT_DDR,
 			{ 19, 12, 9, 9, IPA_EE_AP } },
 	[IPA_4_0][IPA_CLIENT_USB_DPL_CONS]        = {
 			true, IPA_v4_0_GROUP_UL_DL,
@@ -1477,53 +1477,6 @@
 			{ 31, 31, 8, 8, IPA_EE_AP } },
 };
 
-static struct msm_bus_vectors ipa_init_vectors_v3_0[]  = {
-	{
-		.src = MSM_BUS_MASTER_IPA,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 0,
-		.ib = 0,
-	},
-	{
-		.src = MSM_BUS_MASTER_IPA,
-		.dst = MSM_BUS_SLAVE_OCIMEM,
-		.ab = 0,
-		.ib = 0,
-	},
-};
-
-static struct msm_bus_vectors ipa_nominal_perf_vectors_v3_0[]  = {
-	{
-		.src = MSM_BUS_MASTER_IPA,
-		.dst = MSM_BUS_SLAVE_EBI_CH0,
-		.ab = 100000000,
-		.ib = 1300000000,
-	},
-	{
-		.src = MSM_BUS_MASTER_IPA,
-		.dst = MSM_BUS_SLAVE_OCIMEM,
-		.ab = 100000000,
-		.ib = 1300000000,
-	},
-};
-
-static struct msm_bus_paths ipa_usecases_v3_0[]  = {
-	{
-		.num_paths = ARRAY_SIZE(ipa_init_vectors_v3_0),
-		.vectors = ipa_init_vectors_v3_0,
-	},
-	{
-		.num_paths = ARRAY_SIZE(ipa_nominal_perf_vectors_v3_0),
-		.vectors = ipa_nominal_perf_vectors_v3_0,
-	},
-};
-
-static struct msm_bus_scale_pdata ipa_bus_client_pdata_v3_0 = {
-	.usecase = ipa_usecases_v3_0,
-	.num_usecases = ARRAY_SIZE(ipa_usecases_v3_0),
-	.name = "ipa",
-};
-
 /**
  * ipa3_get_clients_from_rm_resource() - get IPA clients which are related to an
  * IPA_RM resource
@@ -1972,6 +1925,49 @@
 }
 
 /**
+ * ipa_comp_cfg() - Configure QMB/Master port selection
+ *
+ * Returns:	None
+ */
+static void ipa_comp_cfg(void)
+{
+	struct ipahal_reg_comp_cfg comp_cfg;
+
+	/* IPAv4 specific, on NON-MHI config*/
+	if ((ipa3_ctx->ipa_hw_type == IPA_HW_v4_0) &&
+		(ipa3_ctx->ipa_config_is_mhi == false)) {
+
+		ipahal_read_reg_fields(IPA_COMP_CFG, &comp_cfg);
+		IPADBG("Before comp config\n");
+		IPADBG("ipa_qmb_select_by_address_global_en = %d\n",
+			comp_cfg.ipa_qmb_select_by_address_global_en);
+
+		IPADBG("ipa_qmb_select_by_address_prod_en = %d\n",
+				comp_cfg.ipa_qmb_select_by_address_prod_en);
+
+		IPADBG("ipa_qmb_select_by_address_cons_en = %d\n",
+				comp_cfg.ipa_qmb_select_by_address_cons_en);
+
+		comp_cfg.ipa_qmb_select_by_address_global_en = false;
+		comp_cfg.ipa_qmb_select_by_address_prod_en = false;
+		comp_cfg.ipa_qmb_select_by_address_cons_en = false;
+
+		ipahal_write_reg_fields(IPA_COMP_CFG, &comp_cfg);
+
+		ipahal_read_reg_fields(IPA_COMP_CFG, &comp_cfg);
+		IPADBG("After comp config\n");
+		IPADBG("ipa_qmb_select_by_address_global_en = %d\n",
+			comp_cfg.ipa_qmb_select_by_address_global_en);
+
+		IPADBG("ipa_qmb_select_by_address_prod_en = %d\n",
+				comp_cfg.ipa_qmb_select_by_address_prod_en);
+
+		IPADBG("ipa_qmb_select_by_address_cons_en = %d\n",
+				comp_cfg.ipa_qmb_select_by_address_cons_en);
+	}
+}
+
+/**
  * ipa3_cfg_qsb() - Configure IPA QSB maximal reads and writes
  *
  * Returns:	None
@@ -2050,6 +2046,8 @@
 
 	ipa3_cfg_qsb();
 
+	ipa_comp_cfg();
+
 	return 0;
 }
 
@@ -3741,7 +3739,6 @@
 	ctrl->ipa3_commit_hdr = __ipa_commit_hdr_v3_0;
 	ctrl->ipa3_enable_clks = _ipa_enable_clks_v3_0;
 	ctrl->ipa3_disable_clks = _ipa_disable_clks_v3_0;
-	ctrl->msm_bus_data_ptr = &ipa_bus_client_pdata_v3_0;
 	ctrl->clock_scaling_bw_threshold_svs =
 		IPA_V3_0_BW_THRESHOLD_SVS_MBPS;
 	ctrl->clock_scaling_bw_threshold_nominal =
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c
index d335ba6..016b4f3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.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
@@ -17,6 +17,7 @@
 
 #define IPA_64_LOW_32_MASK (0xFFFFFFFF)
 #define IPA_64_HIGH_32_MASK (0xFFFFFFFF00000000ULL)
+#define IPAHAL_NAT_INVALID_PROTOCOL (0xFF)
 
 static const char *ipahal_nat_type_to_str[IPA_NAT_MAX] = {
 	__stringify(IPAHAL_NAT_IPV4),
@@ -73,6 +74,40 @@
 	return (memcmp(&zero_entry, entry, sizeof(zero_entry))) ? false : true;
 }
 
+static bool ipa_nat_ipv4_is_entry_valid_v_3_0(const void *entry)
+{
+	struct ipa_nat_hw_ipv4_entry *hw_entry =
+		(struct ipa_nat_hw_ipv4_entry *)entry;
+
+	return hw_entry->enable &&
+		hw_entry->protocol != IPAHAL_NAT_INVALID_PROTOCOL;
+}
+
+static bool ipa_nat_ipv4_is_index_entry_valid_v_3_0(const void *entry)
+{
+	struct ipa_nat_hw_indx_entry *hw_entry =
+		(struct ipa_nat_hw_indx_entry *)entry;
+
+	return hw_entry->tbl_entry != 0;
+}
+
+static bool ipa_nat_ipv4_is_pdn_entry_valid_v_4_0(const void *entry)
+{
+	struct ipa_nat_hw_pdn_entry *hw_entry =
+		(struct ipa_nat_hw_pdn_entry *)entry;
+
+	return hw_entry->public_ip != 0;
+}
+
+static bool ipa_nat_ipv6ct_is_entry_valid_v_4_0(const void *entry)
+{
+	struct ipa_nat_hw_ipv6ct_entry *hw_entry =
+		(struct ipa_nat_hw_ipv6ct_entry *)entry;
+
+	return hw_entry->enable &&
+		hw_entry->protocol != IPAHAL_NAT_INVALID_PROTOCOL;
+}
+
 static int ipa_nat_ipv4_stringify_entry_v_3_0(const void *entry,
 	char *buff, size_t buff_size)
 {
@@ -194,11 +229,15 @@
  * struct ipahal_nat_obj - H/W information for specific IPA version
  * @entry_size - CB to get the size of the entry
  * @is_entry_zeroed - CB to determine whether an entry is definitely zero
+ * @is_entry_valid - CB to determine whether an entry is valid
+ *  Validity criterium depends on entry type. E.g. for NAT base table
+ *   Entry need to be with valid protocol and enabled.
  * @stringify_entry - CB to create string that represents an entry
  */
 struct ipahal_nat_obj {
 	size_t (*entry_size)(void);
 	bool (*is_entry_zeroed)(const void *entry);
+	bool (*is_entry_valid)(const void *entry);
 	int (*stringify_entry)(const void *entry, char *buff, size_t buff_size);
 };
 
@@ -216,11 +255,13 @@
 	[IPA_HW_v3_0][IPAHAL_NAT_IPV4] = {
 			ipa_nat_ipv4_entry_size_v_3_0,
 			ipa_nat_ipv4_is_entry_zeroed_v_3_0,
+			ipa_nat_ipv4_is_entry_valid_v_3_0,
 			ipa_nat_ipv4_stringify_entry_v_3_0
 		},
 	[IPA_HW_v3_0][IPAHAL_NAT_IPV4_INDEX] = {
 			ipa_nat_ipv4_index_entry_size_v_3_0,
 			ipa_nat_ipv4_is_index_entry_zeroed_v_3_0,
+			ipa_nat_ipv4_is_index_entry_valid_v_3_0,
 			ipa_nat_ipv4_index_stringify_entry_v_3_0
 		},
 
@@ -228,16 +269,19 @@
 	[IPA_HW_v4_0][IPAHAL_NAT_IPV4] = {
 			ipa_nat_ipv4_entry_size_v_3_0,
 			ipa_nat_ipv4_is_entry_zeroed_v_3_0,
+			ipa_nat_ipv4_is_entry_valid_v_3_0,
 			ipa_nat_ipv4_stringify_entry_v_4_0
 		},
 	[IPA_HW_v4_0][IPAHAL_NAT_IPV4_PDN] = {
 			ipa_nat_ipv4_pdn_entry_size_v_4_0,
 			ipa_nat_ipv4_is_pdn_entry_zeroed_v_4_0,
+			ipa_nat_ipv4_is_pdn_entry_valid_v_4_0,
 			ipa_nat_ipv4_pdn_stringify_entry_v_4_0
 		},
 	[IPA_HW_v4_0][IPAHAL_NAT_IPV6CT] = {
 			ipa_nat_ipv6ct_entry_size_v_4_0,
 			ipa_nat_ipv6ct_is_entry_zeroed_v_4_0,
+			ipa_nat_ipv6ct_is_entry_valid_v_4_0,
 			ipa_nat_ipv6ct_stringify_entry_v_4_0
 		}
 };
@@ -335,6 +379,25 @@
 	return 0;
 }
 
+int ipahal_nat_is_entry_valid(enum ipahal_nat_type nat_type, void *entry,
+	bool *entry_valid)
+{
+	if (WARN(entry == NULL || entry_valid == NULL,
+		"NULL pointer received\n"))
+		return -EINVAL;
+	if (WARN(nat_type < 0 || nat_type >= IPA_NAT_MAX,
+		"requested NAT type %d is invalid\n", nat_type))
+		return -EINVAL;
+
+	IPAHAL_DBG("Determine whether the entry is valid for NAT type=%s\n",
+		ipahal_nat_type_str(nat_type));
+	*entry_valid = ipahal_nat_objs[ipahal_ctx->hw_type][nat_type].
+		is_entry_valid(entry);
+	IPAHAL_DBG("The entry is %svalid\n", (*entry_valid) ? "" : "not ");
+
+	return 0;
+}
+
 int ipahal_nat_stringify_entry(enum ipahal_nat_type nat_type, void *entry,
 	char *buff, size_t buff_size)
 {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h
index f99c1a0..2461d3e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.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
@@ -53,6 +53,18 @@
 	bool *entry_zeroed);
 
 /*
+ * ipahal_nat_is_entry_valid() - Determines whether HW NAT entry is
+ *                                valid.
+ *  Validity criterium depends on entry type. E.g. for NAT base table
+ *   Entry need to be with valid protocol and enabled.
+ * @nat_type: [in] The type of the NAT entry
+ * @entry: [in] The NAT entry
+ * @entry_valid: [out] True if the received entry is valid
+ */
+int ipahal_nat_is_entry_valid(enum ipahal_nat_type nat_type, void *entry,
+	bool *entry_valid);
+
+/*
  * ipahal_nat_stringify_entry() - Creates a string for HW NAT entry
  * @nat_type: [in] The type of the NAT entry
  * @entry: [in] The NAT entry
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 c3422d1..66837d0 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -654,6 +654,202 @@
 			IPA_CLKON_CFG_OPEN_RX_BMSK);
 }
 
+static void ipareg_construct_comp_cfg(
+	enum ipahal_reg_name reg, const void *fields, u32 *val)
+{
+	struct ipahal_reg_comp_cfg *comp_cfg =
+		(struct ipahal_reg_comp_cfg *)fields;
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->ipa_atomic_fetcher_arb_lock_dis,
+		IPA_COMP_CFG_IPA_ATOMIC_FETCHER_ARB_LOCK_DIS_SHFT,
+		IPA_COMP_CFG_IPA_ATOMIC_FETCHER_ARB_LOCK_DIS_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->ipa_qmb_select_by_address_global_en,
+		IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_GLOBAL_EN_SHFT,
+		IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_GLOBAL_EN_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->gsi_multi_axi_masters_dis,
+		IPA_COMP_CFG_GSI_MULTI_AXI_MASTERS_DIS_SHFT,
+		IPA_COMP_CFG_GSI_MULTI_AXI_MASTERS_DIS_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->gsi_snoc_cnoc_loop_protection_disable,
+		IPA_COMP_CFG_GSI_SNOC_CNOC_LOOP_PROTECTION_DISABLE_SHFT,
+		IPA_COMP_CFG_GSI_SNOC_CNOC_LOOP_PROTECTION_DISABLE_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->gen_qmb_0_snoc_cnoc_loop_protection_disable,
+		IPA_COMP_CFG_GEN_QMB_0_SNOC_CNOC_LOOP_PROTECTION_DISABLE_SHFT,
+		IPA_COMP_CFG_GEN_QMB_0_SNOC_CNOC_LOOP_PROTECTION_DISABLE_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->gen_qmb_1_multi_inorder_wr_dis,
+		IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_WR_DIS_SHFT,
+		IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_WR_DIS_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->gen_qmb_0_multi_inorder_wr_dis,
+		IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_WR_DIS_SHFT,
+		IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_WR_DIS_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->gen_qmb_1_multi_inorder_rd_dis,
+		IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_RD_DIS_SHFT,
+		IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_RD_DIS_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->gen_qmb_0_multi_inorder_rd_dis,
+		IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_RD_DIS_SHFT,
+		IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_RD_DIS_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->gsi_multi_inorder_wr_dis,
+		IPA_COMP_CFG_GSI_MULTI_INORDER_WR_DIS_SHFT,
+		IPA_COMP_CFG_GSI_MULTI_INORDER_WR_DIS_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->gsi_multi_inorder_rd_dis,
+		IPA_COMP_CFG_GSI_MULTI_INORDER_RD_DIS_SHFT,
+		IPA_COMP_CFG_GSI_MULTI_INORDER_RD_DIS_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->ipa_qmb_select_by_address_prod_en,
+		IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_PROD_EN_SHFT,
+		IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_PROD_EN_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->ipa_qmb_select_by_address_cons_en,
+		IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_CONS_EN_SHFT,
+		IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_CONS_EN_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->ipa_dcmp_fast_clk_en,
+		IPA_COMP_CFG_IPA_DCMP_FAST_CLK_EN_SHFT,
+		IPA_COMP_CFG_IPA_DCMP_FAST_CLK_EN_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->gen_qmb_1_snoc_bypass_dis,
+		IPA_COMP_CFG_GEN_QMB_1_SNOC_BYPASS_DIS_SHFT,
+		IPA_COMP_CFG_GEN_QMB_1_SNOC_BYPASS_DIS_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->gen_qmb_0_snoc_bypass_dis,
+		IPA_COMP_CFG_GEN_QMB_0_SNOC_BYPASS_DIS_SHFT,
+		IPA_COMP_CFG_GEN_QMB_0_SNOC_BYPASS_DIS_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->gsi_snoc_bypass_dis,
+		IPA_COMP_CFG_GSI_SNOC_BYPASS_DIS_SHFT,
+		IPA_COMP_CFG_GSI_SNOC_BYPASS_DIS_BMSK);
+
+	IPA_SETFIELD_IN_REG(*val,
+		comp_cfg->enable,
+		IPA_COMP_CFG_ENABLE_SHFT,
+		IPA_COMP_CFG_ENABLE_BMSK);
+}
+
+static void ipareg_parse_comp_cfg(
+	enum ipahal_reg_name reg, void *fields, u32 val)
+{
+	struct ipahal_reg_comp_cfg *comp_cfg =
+		(struct ipahal_reg_comp_cfg *)fields;
+
+	memset(comp_cfg, 0, sizeof(struct ipahal_reg_comp_cfg));
+
+	comp_cfg->ipa_atomic_fetcher_arb_lock_dis =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_IPA_ATOMIC_FETCHER_ARB_LOCK_DIS_SHFT,
+		IPA_COMP_CFG_IPA_ATOMIC_FETCHER_ARB_LOCK_DIS_BMSK);
+
+	comp_cfg->ipa_qmb_select_by_address_global_en =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_GLOBAL_EN_SHFT,
+		IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_GLOBAL_EN_BMSK);
+
+	comp_cfg->gsi_multi_axi_masters_dis =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_GSI_MULTI_AXI_MASTERS_DIS_SHFT,
+		IPA_COMP_CFG_GSI_MULTI_AXI_MASTERS_DIS_BMSK);
+
+	comp_cfg->gsi_snoc_cnoc_loop_protection_disable =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_GSI_SNOC_CNOC_LOOP_PROTECTION_DISABLE_SHFT,
+		IPA_COMP_CFG_GSI_SNOC_CNOC_LOOP_PROTECTION_DISABLE_BMSK);
+
+	comp_cfg->gen_qmb_0_snoc_cnoc_loop_protection_disable =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_GEN_QMB_0_SNOC_CNOC_LOOP_PROTECTION_DISABLE_SHFT,
+		IPA_COMP_CFG_GEN_QMB_0_SNOC_CNOC_LOOP_PROTECTION_DISABLE_BMSK);
+
+	comp_cfg->gen_qmb_1_multi_inorder_wr_dis =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_WR_DIS_SHFT,
+		IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_WR_DIS_BMSK);
+
+	comp_cfg->gen_qmb_0_multi_inorder_wr_dis =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_WR_DIS_SHFT,
+		IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_WR_DIS_BMSK);
+
+	comp_cfg->gen_qmb_1_multi_inorder_rd_dis =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_RD_DIS_SHFT,
+		IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_RD_DIS_BMSK);
+
+	comp_cfg->gen_qmb_0_multi_inorder_rd_dis =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_RD_DIS_SHFT,
+		IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_RD_DIS_BMSK);
+
+	comp_cfg->gsi_multi_inorder_wr_dis =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_GSI_MULTI_INORDER_WR_DIS_SHFT,
+		IPA_COMP_CFG_GSI_MULTI_INORDER_WR_DIS_BMSK);
+
+	comp_cfg->gsi_multi_inorder_rd_dis =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_GSI_MULTI_INORDER_RD_DIS_SHFT,
+		IPA_COMP_CFG_GSI_MULTI_INORDER_RD_DIS_BMSK);
+
+	comp_cfg->ipa_qmb_select_by_address_prod_en =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_PROD_EN_SHFT,
+		IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_PROD_EN_BMSK);
+
+	comp_cfg->ipa_qmb_select_by_address_cons_en =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_CONS_EN_SHFT,
+		IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_CONS_EN_BMSK);
+
+	comp_cfg->ipa_dcmp_fast_clk_en =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_IPA_DCMP_FAST_CLK_EN_SHFT,
+		IPA_COMP_CFG_IPA_DCMP_FAST_CLK_EN_BMSK);
+
+	comp_cfg->gen_qmb_1_snoc_bypass_dis =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_GEN_QMB_1_SNOC_BYPASS_DIS_SHFT,
+		IPA_COMP_CFG_GEN_QMB_1_SNOC_BYPASS_DIS_BMSK);
+
+	comp_cfg->gen_qmb_0_snoc_bypass_dis =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_GEN_QMB_0_SNOC_BYPASS_DIS_SHFT,
+		IPA_COMP_CFG_GEN_QMB_0_SNOC_BYPASS_DIS_BMSK);
+
+	comp_cfg->gsi_snoc_bypass_dis =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_GSI_SNOC_BYPASS_DIS_SHFT,
+		IPA_COMP_CFG_GSI_SNOC_BYPASS_DIS_BMSK);
+
+	comp_cfg->enable =
+		IPA_GETFIELD_FROM_REG(val,
+		IPA_COMP_CFG_ENABLE_SHFT,
+		IPA_COMP_CFG_ENABLE_BMSK);
+}
+
 static void ipareg_construct_qcncm(
 	enum ipahal_reg_name reg, const void *fields, u32 *val)
 {
@@ -1518,7 +1714,7 @@
 		ipareg_construct_dummy, ipareg_parse_dummy,
 		0x00005094, 0},
 	[IPA_HW_v3_0][IPA_COMP_CFG] = {
-		ipareg_construct_dummy, ipareg_parse_dummy,
+		ipareg_construct_comp_cfg, ipareg_parse_comp_cfg,
 		0x0000003C, 0},
 	[IPA_HW_v3_0][IPA_STATE_AGGR_ACTIVE] = {
 		ipareg_construct_dummy, ipareg_parse_dummy,
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 98481a1..2675771 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
@@ -240,6 +240,34 @@
 };
 
 /*
+ * struct ipahal_reg_comp_cfg- IPA Core QMB/Master Port selection
+ *
+ * @all: QMB/Master port selection policy is configured via IPA_COMP_CFG
+ *	- Address based Selection
+ *	- Endpoint based selection / Legacy Mode
+ */
+struct ipahal_reg_comp_cfg {
+	bool ipa_atomic_fetcher_arb_lock_dis;
+	bool ipa_qmb_select_by_address_global_en;
+	bool gsi_multi_axi_masters_dis;
+	bool gsi_snoc_cnoc_loop_protection_disable;
+	bool gen_qmb_0_snoc_cnoc_loop_protection_disable;
+	bool gen_qmb_1_multi_inorder_wr_dis;
+	bool gen_qmb_0_multi_inorder_wr_dis;
+	bool gen_qmb_1_multi_inorder_rd_dis;
+	bool gen_qmb_0_multi_inorder_rd_dis;
+	bool gsi_multi_inorder_wr_dis;
+	bool gsi_multi_inorder_rd_dis;
+	bool ipa_qmb_select_by_address_prod_en;
+	bool ipa_qmb_select_by_address_cons_en;
+	bool ipa_dcmp_fast_clk_en;
+	bool gen_qmb_1_snoc_bypass_dis;
+	bool gen_qmb_0_snoc_bypass_dis;
+	bool gsi_snoc_bypass_dis;
+	bool enable;
+};
+
+/*
  * struct ipa_hash_tuple - Hash tuple members for flt and rt
  *  the fields tells if to be masked or not
  * @src_id: pipe number for flt, table index for rt
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
index 35a36e1..38a17bd 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
@@ -422,4 +422,42 @@
 #define IPA_HPS_FTCH_ARB_QUEUE_WEIGHTS_RX_HPS_QUEUE_WEIGHT_3_BMSK (0xf000)
 #define IPA_HPS_FTCH_ARB_QUEUE_WEIGHTS_RX_HPS_QUEUE_WEIGHT_3_SHFT (0xc)
 
+/* IPA_COMP_CFG register*/
+#define IPA_COMP_CFG_IPA_ATOMIC_FETCHER_ARB_LOCK_DIS_BMSK 0x1E0000
+#define IPA_COMP_CFG_IPA_ATOMIC_FETCHER_ARB_LOCK_DIS_SHFT 17
+#define IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_GLOBAL_EN_BMSK 0x10000
+#define IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_GLOBAL_EN_SHFT 16
+#define IPA_COMP_CFG_GSI_MULTI_AXI_MASTERS_DIS_BMSK 0x8000
+#define IPA_COMP_CFG_GSI_MULTI_AXI_MASTERS_DIS_SHFT 15
+#define IPA_COMP_CFG_GSI_SNOC_CNOC_LOOP_PROTECTION_DISABLE_BMSK 0x4000
+#define IPA_COMP_CFG_GSI_SNOC_CNOC_LOOP_PROTECTION_DISABLE_SHFT 14
+#define IPA_COMP_CFG_GEN_QMB_0_SNOC_CNOC_LOOP_PROTECTION_DISABLE_BMSK 0x2000
+#define IPA_COMP_CFG_GEN_QMB_0_SNOC_CNOC_LOOP_PROTECTION_DISABLE_SHFT 13
+#define IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_WR_DIS_BMSK 0x1000
+#define IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_WR_DIS_SHFT 12
+#define IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_WR_DIS_BMSK 0x800
+#define IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_WR_DIS_SHFT 11
+#define IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_RD_DIS_BMSK 0x400
+#define IPA_COMP_CFG_GEN_QMB_1_MULTI_INORDER_RD_DIS_SHFT 10
+#define IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_RD_DIS_BMSK 0x200
+#define IPA_COMP_CFG_GEN_QMB_0_MULTI_INORDER_RD_DIS_SHFT 9
+#define IPA_COMP_CFG_GSI_MULTI_INORDER_WR_DIS_BMSK 0x100
+#define IPA_COMP_CFG_GSI_MULTI_INORDER_WR_DIS_SHFT 8
+#define IPA_COMP_CFG_GSI_MULTI_INORDER_RD_DIS_BMSK 0x80
+#define IPA_COMP_CFG_GSI_MULTI_INORDER_RD_DIS_SHFT 7
+#define IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_PROD_EN_BMSK 0x40
+#define IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_PROD_EN_SHFT 6
+#define IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_CONS_EN_BMSK 0x20
+#define IPA_COMP_CFG_IPA_QMB_SELECT_BY_ADDRESS_CONS_EN_SHFT 5
+#define IPA_COMP_CFG_IPA_DCMP_FAST_CLK_EN_BMSK 0x10
+#define IPA_COMP_CFG_IPA_DCMP_FAST_CLK_EN_SHFT 4
+#define IPA_COMP_CFG_GEN_QMB_1_SNOC_BYPASS_DIS_BMSK 0x8
+#define IPA_COMP_CFG_GEN_QMB_1_SNOC_BYPASS_DIS_SHFT 3
+#define IPA_COMP_CFG_GEN_QMB_0_SNOC_BYPASS_DIS_BMSK 0x4
+#define IPA_COMP_CFG_GEN_QMB_0_SNOC_BYPASS_DIS_SHFT 2
+#define IPA_COMP_CFG_GSI_SNOC_BYPASS_DIS_BMSK 0x2
+#define IPA_COMP_CFG_GSI_SNOC_BYPASS_DIS_SHFT 1
+#define IPA_COMP_CFG_ENABLE_BMSK 0x1
+#define IPA_COMP_CFG_ENABLE_SHFT 0
+
 #endif /* _IPAHAL_REG_I_H_ */
diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c
index c2187c6..47d5292 100644
--- a/drivers/platform/msm/mhi_dev/mhi.c
+++ b/drivers/platform/msm/mhi_dev/mhi.c
@@ -71,11 +71,12 @@
 static void mhi_hwc_cb(void *priv, enum ipa_mhi_event_type event,
 	unsigned long data);
 static void mhi_ring_init_cb(void *user_data);
-static void mhi_update_state_info(uint32_t info);
+static void mhi_update_state_info(uint32_t uevent_idx, enum mhi_ctrl_info info);
 static int mhi_deinit(struct mhi_dev *mhi);
 static void mhi_dev_resume_init_with_link_up(struct ep_pcie_notify *notify);
 static int mhi_dev_pcie_notify_event;
 static void mhi_dev_transfer_completion_cb(void *mreq);
+static struct mhi_dev_uevent_info channel_state_info[MHI_MAX_CHANNELS];
 
 /*
  * mhi_dev_ring_cache_completion_cb () - Call back function called
@@ -454,7 +455,7 @@
 			return;
 		}
 
-		mhi_update_state_info(MHI_STATE_CONNECTED);
+		mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONNECTED);
 
 		ep_pcie_mask_irq_event(mhi_ctx->phandle,
 				EP_PCIE_INT_EVT_MHI_A7, true);
@@ -825,16 +826,14 @@
 static void mhi_dev_trigger_cb(void)
 {
 	struct mhi_dev_ready_cb_info *info;
-	uint32_t state_data;
+	enum mhi_ctrl_info state_data;
 
-	mutex_lock(&mhi_ctx->mhi_lock);
 	list_for_each_entry(info, &mhi_ctx->client_cb_list, list)
 		if (info->cb) {
-			mhi_ctrl_state_info(&state_data);
+			mhi_ctrl_state_info(info->cb_data.channel, &state_data);
 			info->cb_data.ctrl_info = state_data;
 			info->cb(&info->cb_data);
 		}
-	mutex_unlock(&mhi_ctx->mhi_lock);
 }
 
 int mhi_dev_trigger_hw_acc_wakeup(struct mhi_dev *mhi)
@@ -855,11 +854,18 @@
 }
 EXPORT_SYMBOL(mhi_dev_trigger_hw_acc_wakeup);
 
-static int mhi_dev_send_cmd_comp_event(struct mhi_dev *mhi)
+static int mhi_dev_send_cmd_comp_event(struct mhi_dev *mhi,
+				enum mhi_dev_cmd_completion_code code)
 {
 	int rc = 0;
 	union mhi_dev_ring_element_type event;
 
+	if (code > MHI_CMD_COMPL_CODE_RES) {
+		mhi_log(MHI_MSG_ERROR,
+			"Invalid cmd compl code: %d\n", code);
+		return -EINVAL;
+	}
+
 	/* send the command completion event to the host */
 	event.evt_cmd_comp.ptr = mhi->cmd_ctx_cache->rbase
 			+ (mhi->ring[MHI_RING_CMD_ID].rd_offset *
@@ -867,11 +873,10 @@
 	mhi_log(MHI_MSG_VERBOSE, "evt cmd comp ptr :%d\n",
 			(uint32_t) event.evt_cmd_comp.ptr);
 	event.evt_cmd_comp.type = MHI_DEV_RING_EL_CMD_COMPLETION_EVT;
-	event.evt_cmd_comp.code = MHI_CMD_COMPL_CODE_SUCCESS;
-
+	event.evt_cmd_comp.code = code;
 	rc = mhi_dev_send_event(mhi, 0, &event);
 	if (rc)
-		pr_err("channel start command faied\n");
+		mhi_log(MHI_MSG_ERROR, "Send completion failed\n");
 
 	return rc;
 }
@@ -914,7 +919,8 @@
 	mhi_dev_write_to_host(mhi, &data_transfer, NULL, MHI_DEV_DMA_SYNC);
 
 	/* send the completion event to the host */
-	rc = mhi_dev_send_cmd_comp_event(mhi);
+	rc = mhi_dev_send_cmd_comp_event(mhi,
+					MHI_CMD_COMPL_CODE_SUCCESS);
 	if (rc)
 		pr_err("Error sending command completion event\n");
 
@@ -930,6 +936,8 @@
 	struct mhi_addr host_addr;
 	struct mhi_dev_channel *ch;
 	struct mhi_dev_ring *ring;
+	char *connected[2] = { "MHI_CHANNEL_STATE_12=CONNECTED", NULL};
+	char *disconnected[2] = { "MHI_CHANNEL_STATE_12=DISCONNECTED", NULL};
 
 	ch_id = el->generic.chid;
 	mhi_log(MHI_MSG_VERBOSE, "for channel:%d and cmd:%d\n",
@@ -942,7 +950,13 @@
 		if (ch_id >= (HW_CHANNEL_BASE)) {
 			rc = mhi_hwc_chcmd(mhi, ch_id, el->generic.type);
 			if (rc) {
-				pr_err("Error with HW channel cmd :%d\n", rc);
+				mhi_log(MHI_MSG_ERROR,
+					"Error with HW channel cmd %d\n", rc);
+				rc = mhi_dev_send_cmd_comp_event(mhi,
+						MHI_CMD_COMPL_CODE_UNDEFINED);
+				if (rc)
+					mhi_log(MHI_MSG_ERROR,
+						"Error with compl event\n");
 				return;
 			}
 			goto send_start_completion_event;
@@ -958,6 +972,11 @@
 		if (rc) {
 			mhi_log(MHI_MSG_ERROR,
 				"start ring failed for ch %d\n", ch_id);
+			rc = mhi_dev_send_cmd_comp_event(mhi,
+						MHI_CMD_COMPL_CODE_UNDEFINED);
+			if (rc)
+				mhi_log(MHI_MSG_ERROR,
+					"Error with compl event\n");
 			return;
 		}
 
@@ -975,6 +994,11 @@
 		rc = mhi_dev_mmio_enable_chdb_a7(mhi, ch_id);
 		if (rc) {
 			pr_err("Failed to enable channel db\n");
+			rc = mhi_dev_send_cmd_comp_event(mhi,
+						MHI_CMD_COMPL_CODE_UNDEFINED);
+			if (rc)
+				mhi_log(MHI_MSG_ERROR,
+					"Error with compl event\n");
 			return;
 		}
 
@@ -991,22 +1015,25 @@
 		mhi_dev_write_to_host(mhi, &host_addr, NULL, MHI_DEV_DMA_SYNC);
 
 send_start_completion_event:
-		rc = mhi_dev_send_cmd_comp_event(mhi);
+		rc = mhi_dev_send_cmd_comp_event(mhi,
+						MHI_CMD_COMPL_CODE_SUCCESS);
 		if (rc)
 			pr_err("Error sending command completion event\n");
 
 		/* Trigger callback to clients */
 		mhi_dev_trigger_cb();
 
+		mhi_update_state_info(ch_id, MHI_STATE_CONNECTED);
+		if (ch_id == MHI_CLIENT_MBIM_OUT)
+			kobject_uevent_env(&mhi_ctx->dev->kobj,
+						KOBJ_CHANGE, connected);
 		break;
 	case MHI_DEV_RING_EL_STOP:
 		if (ch_id >= HW_CHANNEL_BASE) {
 			rc = mhi_hwc_chcmd(mhi, ch_id, el->generic.type);
-			if (rc) {
+			if (rc)
 				mhi_log(MHI_MSG_ERROR,
 					"send channel stop cmd event failed\n");
-				return;
-			}
 
 			/* send the completion event to the host */
 			event.evt_cmd_comp.ptr = mhi->cmd_ctx_cache->rbase +
@@ -1052,6 +1079,10 @@
 				pr_err("stop event send failed\n");
 
 			mutex_unlock(&ch->ch_lock);
+			mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED);
+			if (ch_id == MHI_CLIENT_MBIM_OUT)
+				kobject_uevent_env(&mhi_ctx->dev->kobj,
+						KOBJ_CHANGE, disconnected);
 		}
 		break;
 	case MHI_DEV_RING_EL_RESET:
@@ -1059,11 +1090,9 @@
 			"received reset cmd for channel %d\n", ch_id);
 		if (ch_id >= HW_CHANNEL_BASE) {
 			rc = mhi_hwc_chcmd(mhi, ch_id, el->generic.type);
-			if (rc) {
+			if (rc)
 				mhi_log(MHI_MSG_ERROR,
 					"send channel stop cmd event failed\n");
-				return;
-			}
 
 			/* send the completion event to the host */
 			event.evt_cmd_comp.ptr = mhi->cmd_ctx_cache->rbase +
@@ -1121,10 +1150,15 @@
 					MHI_DEV_DMA_SYNC);
 
 			/* send the completion event to the host */
-			rc = mhi_dev_send_cmd_comp_event(mhi);
+			rc = mhi_dev_send_cmd_comp_event(mhi,
+						MHI_CMD_COMPL_CODE_SUCCESS);
 			if (rc)
 				pr_err("Error sending command completion event\n");
 			mutex_unlock(&ch->ch_lock);
+			mhi_update_state_info(ch_id, MHI_STATE_DISCONNECTED);
+			if (ch_id == MHI_CLIENT_MBIM_OUT)
+				kobject_uevent_env(&mhi_ctx->dev->kobj,
+						KOBJ_CHANGE, disconnected);
 		}
 		break;
 	default:
@@ -1306,7 +1340,7 @@
 	}
 
 	/* Update ctrl node */
-	mhi_update_state_info(MHI_STATE_DISCONNECTED);
+	mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_DISCONNECTED);
 
 	flush_workqueue(mhi->ring_init_wq);
 	flush_workqueue(mhi->pending_ring_wq);
@@ -1787,7 +1821,7 @@
 		mhi_dev_write_to_host(mhi, &data_transfer, NULL,
 				MHI_DEV_DMA_SYNC);
 	}
-	mhi_update_state_info(MHI_STATE_CONNECTED);
+	mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONNECTED);
 
 	atomic_set(&mhi->is_suspended, 0);
 
@@ -2348,7 +2382,7 @@
 	if (mhi_ctx->config_iatu || mhi_ctx->mhi_int)
 		enable_irq(mhi_ctx->mhi_irq);
 
-	mhi_update_state_info(MHI_STATE_CONNECTED);
+	mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONFIGURED);
 }
 
 static void mhi_ring_init_cb(void *data)
@@ -2408,28 +2442,32 @@
 }
 EXPORT_SYMBOL(mhi_register_state_cb);
 
-static void mhi_update_state_info(uint32_t info)
+static void mhi_update_state_info(uint32_t uevent_idx, enum mhi_ctrl_info info)
 {
 	struct mhi_dev_client_cb_reason reason;
 
-	mhi_ctx->ctrl_info = info;
+	if (uevent_idx == MHI_DEV_UEVENT_CTRL)
+		mhi_ctx->ctrl_info = info;
 
-	if (info == MHI_STATE_CONNECTED)
-		return;
+	channel_state_info[uevent_idx].ctrl_info = info;
 
-	reason.reason = MHI_DEV_CTRL_UPDATE;
-	uci_ctrl_update(&reason);
-}
-
-int mhi_ctrl_state_info(uint32_t *info)
-{
-	if (!info) {
-		pr_err("Invalid info\n");
-		return -EINVAL;
+	if (uevent_idx == MHI_CLIENT_QMI_OUT ||
+			uevent_idx == MHI_CLIENT_QMI_IN) {
+		/* For legacy reasons for QTI client */
+		reason.reason = MHI_DEV_CTRL_UPDATE;
+		uci_ctrl_update(&reason);
 	}
 
-	*info = mhi_ctx->ctrl_info;
-	mhi_log(MHI_MSG_VERBOSE, "ctrl:%d", mhi_ctx->ctrl_info);
+}
+
+int mhi_ctrl_state_info(uint32_t idx, uint32_t *info)
+{
+	if (idx == MHI_DEV_UEVENT_CTRL)
+		*info = mhi_ctx->ctrl_info;
+	else
+		*info = channel_state_info[idx].ctrl_info;
+
+	mhi_log(MHI_MSG_VERBOSE, "idx:%d, ctrl:%d", idx, *info);
 
 	return 0;
 }
@@ -2924,7 +2962,8 @@
 				"Failed to create IPC logging context\n");
 		}
 		mhi_uci_init();
-		mhi_update_state_info(MHI_STATE_CONFIGURED);
+		mhi_update_state_info(MHI_DEV_UEVENT_CTRL,
+						MHI_STATE_CONFIGURED);
 	}
 
 	INIT_WORK(&mhi_ctx->pcie_event, mhi_dev_pcie_handle_event);
diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h
index 38e52e2..b9120fc 100644
--- a/drivers/platform/msm/mhi_dev/mhi.h
+++ b/drivers/platform/msm/mhi_dev/mhi.h
@@ -275,7 +275,7 @@
 #define MHI_ENV_VALUE			2
 #define MHI_MASK_ROWS_CH_EV_DB		4
 #define TRB_MAX_DATA_SIZE		8192
-#define MHI_CTRL_STATE			25
+#define MHI_CTRL_STATE			100
 #define IPA_DMA_SYNC                    1
 #define IPA_DMA_ASYNC                   0
 
@@ -607,6 +607,8 @@
 	bool				mhi_int;
 	/* Registered client callback list */
 	struct list_head		client_cb_list;
+
+	struct kobj_uevent_env		kobj_env;
 };
 
 struct mhi_req {
@@ -712,6 +714,14 @@
 	MHI_MAX_CHANNELS = 102,
 };
 
+/* Use ID 0 for legacy /dev/mhi_ctrl. Channel 0 is used for internal only */
+#define MHI_DEV_UEVENT_CTRL	0
+
+struct mhi_dev_uevent_info {
+	enum mhi_client_channel	channel;
+	enum mhi_ctrl_info	ctrl_info;
+};
+
 struct mhi_dev_iov {
 	void		*addr;
 	uint32_t	buf_size;
@@ -1251,6 +1261,9 @@
 
 /**
  * mhi_ctrl_state_info() - Provide MHI state info
+ *		@idx: Channel number idx. Look at channel_state_info and
+ *		pass the index for the corresponding channel.
+ *		@info: Return the control info.
  *		MHI_STATE=CONFIGURED - MHI device is present but not ready
  *					for data traffic.
  *		MHI_STATE=CONNECTED - MHI device is ready for data transfer.
@@ -1258,7 +1271,7 @@
  *		exposes device nodes for the supported MHI software
  *		channels.
  */
-int mhi_ctrl_state_info(uint32_t *info);
+int mhi_ctrl_state_info(uint32_t idx, uint32_t *info);
 
 /**
  * uci_ctrl_update() - Update UCI once TRE's are available for clients to
diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c
index 244cf04..ed02d0d 100644
--- a/drivers/platform/msm/mhi_dev/mhi_uci.c
+++ b/drivers/platform/msm/mhi_dev/mhi_uci.c
@@ -441,6 +441,61 @@
 	return rc;
 }
 
+static void  mhi_parse_state(char *buf, int *nbytes, uint32_t info)
+{
+	switch (info) {
+	case MHI_STATE_CONNECTED:
+		*nbytes = scnprintf(buf, MHI_CTRL_STATE,
+			"CONNECTED");
+		break;
+	case MHI_STATE_DISCONNECTED:
+		*nbytes = scnprintf(buf, MHI_CTRL_STATE,
+			"DISCONNECTED");
+		break;
+	case MHI_STATE_CONFIGURED:
+	default:
+		*nbytes = scnprintf(buf, MHI_CTRL_STATE,
+			"CONFIGURED");
+		break;
+	}
+}
+
+static int mhi_state_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+	int rc, nbytes = 0;
+	uint32_t info = 0;
+	char buf[MHI_CTRL_STATE];
+
+	rc = mhi_ctrl_state_info(MHI_DEV_UEVENT_CTRL, &info);
+	if (rc) {
+		pr_err("Failed to obtain MHI_STATE\n");
+		return -EINVAL;
+	}
+
+	mhi_parse_state(buf, &nbytes, info);
+	add_uevent_var(env, "MHI_STATE=%s", buf);
+
+	rc = mhi_ctrl_state_info(MHI_CLIENT_QMI_OUT, &info);
+	if (rc) {
+		pr_err("Failed to obtain channel 14 state\n");
+		return -EINVAL;
+	}
+	nbytes = 0;
+	mhi_parse_state(buf, &nbytes, info);
+	add_uevent_var(env, "MHI_CHANNEL_STATE_14=%s", buf);
+
+	rc = mhi_ctrl_state_info(MHI_CLIENT_MBIM_OUT, &info);
+	if (rc) {
+		pr_err("Failed to obtain channel 12 state\n");
+		return -EINVAL;
+	}
+	nbytes = 0;
+	mhi_parse_state(buf, &nbytes, info);
+	add_uevent_var(env, "MHI_CHANNEL_STATE_12=%s", buf);
+
+	return 0;
+}
+
 static ssize_t mhi_uci_ctrl_client_read(struct file *file,
 		char __user *user_buf,
 		size_t count, loff_t *offp)
@@ -455,7 +510,7 @@
 		return -EINVAL;
 
 	uci_ctrl_handle = file->private_data;
-	rc = mhi_ctrl_state_info(&info);
+	rc = mhi_ctrl_state_info(MHI_CLIENT_QMI_OUT, &info);
 	if (rc)
 		return -EINVAL;
 
@@ -993,6 +1048,8 @@
 		uci_ctxt.cdev_ctrl = NULL;
 	}
 
+	uci_ctxt.mhi_uci_class->dev_uevent = mhi_state_uevent;
+
 	return 0;
 
 failed_char_add:
diff --git a/drivers/platform/msm/msm_rmnet_bam.c b/drivers/platform/msm/msm_rmnet_bam.c
new file mode 100644
index 0000000..8d59af0
--- /dev/null
+++ b/drivers/platform/msm/msm_rmnet_bam.c
@@ -0,0 +1,945 @@
+/* Copyright (c) 2011-2016, 2018 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * 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.
+ *
+ */
+
+/*
+ * RMNET BAM Module.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/msm_rmnet.h>
+#include <linux/platform_device.h>
+#include <linux/workqueue.h>
+
+#include <net/pkt_sched.h>
+
+#include <soc/qcom/bam_dmux.h>
+
+/* Debug message support */
+static int msm_rmnet_bam_debug_mask;
+module_param_named(debug_enable, msm_rmnet_bam_debug_mask, int, 0664);
+			/* S_IRUGO | S_IWUSR | S_IWGRP */
+
+static unsigned long int msm_rmnet_bam_headroom_check_failure;
+module_param(msm_rmnet_bam_headroom_check_failure, ulong, 0444); /*S_IRUGO*/
+MODULE_PARM_DESC(msm_rmnet_bam_headroom_check_failure,
+		 "Number of packets with insufficient headroom");
+
+/* Packet threshold. */
+static unsigned int pkt_threshold = 1;
+module_param(pkt_threshold, uint, 0664); /* S_IRUGO | S_IWUSR | S_IWGRP */
+
+#define DEBUG_MASK_LVL0 (1U << 0)
+#define DEBUG_MASK_LVL1 (1U << 1)
+#define DEBUG_MASK_LVL2 (1U << 2)
+
+#define DBG(m, x...) do {			   \
+		if (msm_rmnet_bam_debug_mask & m) \
+			pr_info(x);		   \
+} while (0)
+#define DBG0(x...) DBG(DEBUG_MASK_LVL0, x)
+#define DBG1(x...) DBG(DEBUG_MASK_LVL1, x)
+#define DBG2(x...) DBG(DEBUG_MASK_LVL2, x)
+
+/* allow larger frames */
+#define RMNET_DATA_LEN 2000
+
+#define RMNET_BAM_DRIVER_NAME "rmnet_bam"
+
+#define DEVICE_ID_INVALID   -1
+
+#define DEVICE_INACTIVE      2
+#define DEVICE_ACTIVE        1
+#define DEVICE_UNINITIALIZED 0
+
+#define HEADROOM_FOR_BAM   8 /* for mux header */
+#define HEADROOM_FOR_QOS    8
+#define TAILROOM            8 /* for padding by mux layer */
+
+struct rmnet_private {
+	struct net_device_stats stats;
+	uint32_t ch_id;
+#ifdef CONFIG_MSM_RMNET_DEBUG
+	ktime_t last_packet;
+	unsigned long wakeups_xmit;
+	unsigned long wakeups_rcv;
+	unsigned long timeout_us;
+#endif
+	struct sk_buff *waiting_for_ul_skb;
+	spinlock_t lock;
+	spinlock_t tx_queue_lock;
+	struct tasklet_struct tsklt;
+	u32 operation_mode; /* IOCTL specified mode (protocol, QoS header) */
+	uint8_t device_up;
+	uint8_t in_reset;
+};
+
+struct rmnet_free_bam_work {
+	struct work_struct work;
+	uint32_t ch_id;
+};
+
+#ifdef CONFIG_MSM_RMNET_DEBUG
+static unsigned long timeout_us;
+
+/* Returns 1 if packet caused rmnet to wakeup, 0 otherwise. */
+static int rmnet_cause_wakeup(struct rmnet_private *p)
+{
+	int ret = 0;
+	ktime_t now;
+
+	if (p->timeout_us == 0) /* Check if disabled */
+		return 0;
+
+	/* Use real (wall) time. */
+	now = ktime_get_real();
+
+	if (ktime_us_delta(now, p->last_packet) > p->timeout_us)
+		ret = 1;
+
+	p->last_packet = now;
+	return ret;
+}
+
+static ssize_t wakeups_xmit_show(struct device *d,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct rmnet_private *p = netdev_priv(to_net_dev(d));
+
+	return snprintf(buf, PAGE_SIZE, "%lu\n", p->wakeups_xmit);
+}
+
+DEVICE_ATTR(wakeups_xmit, 0444, wakeups_xmit_show, NULL);
+
+static ssize_t wakeups_rcv_show(struct device *d, struct device_attribute *attr,
+				char *buf)
+{
+	struct rmnet_private *p = netdev_priv(to_net_dev(d));
+
+	return snprintf(buf, PAGE_SIZE, "%lu\n", p->wakeups_rcv);
+}
+
+DEVICE_ATTR(wakeups_rcv, 0444, wakeups_rcv_show, NULL);
+
+/* Set timeout in us. */
+static ssize_t timeout_store(struct device *d, struct device_attribute *attr,
+			     const char *buf, size_t n)
+{
+	struct rmnet_private *p = netdev_priv(to_net_dev(d));
+	int ret;
+
+	ret = kstrtoul(buf, 0, &timeout_us);
+	if (ret < 0)
+		return n;
+	p->timeout_us = timeout_us;
+	return n;
+}
+
+static ssize_t timeout_show(struct device *d, struct device_attribute *attr,
+			    char *buf)
+{
+	struct rmnet_private *p = netdev_priv(to_net_dev(d));
+
+	p = netdev_priv(to_net_dev(d));
+	return snprintf(buf, PAGE_SIZE, "%lu\n", timeout_us);
+}
+
+DEVICE_ATTR(timeout, 0664, timeout_show, timeout_store);
+#endif
+
+
+/* Forward declaration */
+static int rmnet_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
+static struct platform_driver bam_rmnet_drivers[BAM_DMUX_NUM_CHANNELS];
+
+static struct net_device *netdevs[BAM_DMUX_NUM_CHANNELS];
+
+static __be16 rmnet_ip_type_trans(struct sk_buff *skb, struct net_device *dev)
+{
+	__be16 protocol = 0;
+
+	skb->dev = dev;
+
+	/* Determine L3 protocol */
+	switch (skb->data[0] & 0xf0) {
+	case 0x40:
+		protocol = htons(ETH_P_IP);
+		break;
+	case 0x60:
+		protocol = htons(ETH_P_IPV6);
+		break;
+	default:
+		protocol = htons(ETH_P_MAP);
+	}
+	return protocol;
+}
+
+static int count_this_packet(void *_hdr, int len)
+{
+	struct ethhdr *hdr = _hdr;
+
+	if (len >= ETH_HLEN && hdr->h_proto == htons(ETH_P_ARP))
+		return 0;
+
+	return 1;
+}
+
+/* Rx Callback, Called in Work Queue context */
+static void bam_recv_notify(void *dev, struct sk_buff *skb)
+{
+	struct rmnet_private *p = netdev_priv(dev);
+	unsigned long flags;
+	u32 opmode;
+
+	if (skb) {
+		skb->dev = dev;
+		/* Handle Rx frame format */
+		spin_lock_irqsave(&p->lock, flags);
+		opmode = p->operation_mode;
+		spin_unlock_irqrestore(&p->lock, flags);
+
+		if (RMNET_IS_MODE_IP(opmode)) {
+			/* Driver in IP mode */
+			skb->protocol = rmnet_ip_type_trans(skb, dev);
+		} else {
+			/* Driver in Ethernet mode */
+			skb->protocol = eth_type_trans(skb, dev);
+		}
+		if (RMNET_IS_MODE_IP(opmode) ||
+		    count_this_packet(skb->data, skb->len)) {
+#ifdef CONFIG_MSM_RMNET_DEBUG
+			p->wakeups_rcv += rmnet_cause_wakeup(p);
+#endif
+			p->stats.rx_packets++;
+			p->stats.rx_bytes += skb->len;
+		}
+		DBG1("[%s] Rx packet #%lu len=%d\n",
+			((struct net_device *)dev)->name,
+			p->stats.rx_packets, skb->len);
+
+		/* Deliver to network stack */
+		if (pkt_threshold == 1) {
+			netif_rx_ni(skb);
+		} else {
+			/* For every nth packet, use netif_rx_ni(). */
+			if (p->stats.rx_packets % pkt_threshold == 0)
+				netif_rx_ni(skb);
+			else
+				netif_rx(skb);
+		}
+	} else
+		pr_err("[%s] %s: No skb received",
+			((struct net_device *)dev)->name, __func__);
+}
+
+static struct sk_buff *_rmnet_add_headroom(struct sk_buff **skb,
+					   struct net_device *dev)
+{
+	struct sk_buff *skbn;
+
+	if (skb_headroom(*skb) < dev->needed_headroom) {
+		msm_rmnet_bam_headroom_check_failure++;
+		skbn = skb_realloc_headroom(*skb, dev->needed_headroom);
+		kfree_skb(*skb);
+		*skb = skbn;
+	} else {
+		skbn = *skb;
+	}
+
+	return skbn;
+}
+
+static int _rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct rmnet_private *p = netdev_priv(dev);
+	int bam_ret;
+	struct QMI_QOS_HDR_S *qmih;
+	u32 opmode;
+	unsigned long flags;
+
+	if (unlikely(!_rmnet_add_headroom(&skb, dev))) {
+		dev->stats.tx_dropped++;
+		return NETDEV_TX_OK;
+	}
+	/* For QoS mode, prepend QMI header and assign flow ID from skb->mark */
+	spin_lock_irqsave(&p->lock, flags);
+	opmode = p->operation_mode;
+	spin_unlock_irqrestore(&p->lock, flags);
+
+	if (RMNET_IS_MODE_QOS(opmode)) {
+		qmih = (struct QMI_QOS_HDR_S *)
+			skb_push(skb, sizeof(struct QMI_QOS_HDR_S));
+		qmih->version = 1;
+		qmih->flags = 0;
+		qmih->flow_id = skb->mark;
+	}
+
+	//Mayank dev->trans_start = jiffies;
+	/* if write() succeeds, skb access is unsafe in this process */
+	bam_ret = msm_bam_dmux_write(p->ch_id, skb);
+
+	if (bam_ret != 0 && bam_ret != -EAGAIN && bam_ret != -EFAULT) {
+		pr_err("[%s] %s: write returned error %d",
+			dev->name, __func__, bam_ret);
+		if (RMNET_IS_MODE_QOS(opmode))
+			skb_pull(skb, sizeof(struct QMI_QOS_HDR_S));
+		return -EPERM;
+	}
+
+	return bam_ret;
+}
+
+static void bam_write_done(void *dev, struct sk_buff *skb)
+{
+	struct rmnet_private *p = netdev_priv(dev);
+	u32 opmode = p->operation_mode;
+	unsigned long flags;
+
+	DBG1("%s: write complete\n", __func__);
+	if (RMNET_IS_MODE_IP(opmode) ||
+				count_this_packet(skb->data, skb->len)) {
+		p->stats.tx_packets++;
+		p->stats.tx_bytes += skb->len;
+#ifdef CONFIG_MSM_RMNET_DEBUG
+		p->wakeups_xmit += rmnet_cause_wakeup(p);
+#endif
+	}
+	DBG1("[%s] Tx packet #%lu len=%d mark=0x%x\n",
+	    ((struct net_device *)(dev))->name, p->stats.tx_packets,
+	    skb->len, skb->mark);
+	dev_kfree_skb_any(skb);
+
+	spin_lock_irqsave(&p->tx_queue_lock, flags);
+	if (netif_queue_stopped(dev) &&
+	    msm_bam_dmux_is_ch_low(p->ch_id)) {
+		DBG0("%s: Low WM hit, waking queue=%pK\n",
+		      __func__, skb);
+		netif_wake_queue(dev);
+	}
+	spin_unlock_irqrestore(&p->tx_queue_lock, flags);
+}
+
+static void bam_notify(void *dev, int event, unsigned long data)
+{
+	struct rmnet_private *p = netdev_priv(dev);
+	unsigned long flags;
+
+	switch (event) {
+	case BAM_DMUX_RECEIVE:
+		bam_recv_notify(dev, (struct sk_buff *)(data));
+		break;
+	case BAM_DMUX_WRITE_DONE:
+		bam_write_done(dev, (struct sk_buff *)(data));
+		break;
+	case BAM_DMUX_UL_CONNECTED:
+		spin_lock_irqsave(&p->lock, flags);
+		if (p->waiting_for_ul_skb != NULL) {
+			struct sk_buff *skb;
+			int ret;
+
+			skb = p->waiting_for_ul_skb;
+			p->waiting_for_ul_skb = NULL;
+			spin_unlock_irqrestore(&p->lock, flags);
+			ret = _rmnet_xmit(skb, dev);
+			if (ret) {
+				pr_err("%s: error %d dropping delayed TX SKB %pK\n",
+						__func__, ret, skb);
+				dev_kfree_skb_any(skb);
+			}
+			netif_wake_queue(dev);
+		} else {
+			spin_unlock_irqrestore(&p->lock, flags);
+		}
+		break;
+	case BAM_DMUX_UL_DISCONNECTED:
+		break;
+	}
+}
+
+static int __rmnet_open(struct net_device *dev)
+{
+	int r;
+	struct rmnet_private *p = netdev_priv(dev);
+
+	DBG0("[%s] __rmnet_open()\n", dev->name);
+
+	if (p->device_up == DEVICE_UNINITIALIZED) {
+		r = msm_bam_dmux_open(p->ch_id, dev, bam_notify);
+		if (r < 0) {
+			DBG0("%s: ch=%d failed with rc %d\n",
+					__func__, p->ch_id, r);
+			return -ENODEV;
+		}
+	}
+
+	p->device_up = DEVICE_ACTIVE;
+	return 0;
+}
+
+static int rmnet_open(struct net_device *dev)
+{
+	int rc = 0;
+
+	DBG0("[%s] rmnet_open()\n", dev->name);
+
+	rc = __rmnet_open(dev);
+
+	if (rc == 0)
+		netif_start_queue(dev);
+
+	return rc;
+}
+
+
+static int __rmnet_close(struct net_device *dev)
+{
+	struct rmnet_private *p = netdev_priv(dev);
+	int rc = 0;
+
+	if (p->device_up == DEVICE_ACTIVE) {
+		/* do not close rmnet port once up,  this causes
+		 * remote side to hang if tried to open again
+		 */
+		p->device_up = DEVICE_INACTIVE;
+		return rc;
+	} else
+		return -EBADF;
+}
+
+
+static int rmnet_stop(struct net_device *dev)
+{
+	DBG0("[%s] rmnet_stop()\n", dev->name);
+
+	__rmnet_close(dev);
+	netif_stop_queue(dev);
+
+	return 0;
+}
+
+static int rmnet_change_mtu(struct net_device *dev, int new_mtu)
+{
+	if (0 > new_mtu || RMNET_DATA_LEN < new_mtu)
+		return -EINVAL;
+
+	DBG0("[%s] MTU change: old=%d new=%d\n",
+		dev->name, dev->mtu, new_mtu);
+	dev->mtu = new_mtu;
+
+	return 0;
+}
+
+static int rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct rmnet_private *p = netdev_priv(dev);
+	unsigned long flags;
+	int awake;
+	int ret = 0;
+
+	if (netif_queue_stopped(dev)) {
+		pr_err("[%s]debug: rmnet_xmit called when netif_queue is stopped\n",
+				dev->name);
+		return NETDEV_TX_BUSY;
+	}
+
+	spin_lock_irqsave(&p->lock, flags);
+	awake = msm_bam_dmux_ul_power_vote();
+	if (!awake) {
+		/* send SKB once wakeup is complete */
+		netif_stop_queue(dev);
+		p->waiting_for_ul_skb = skb;
+		spin_unlock_irqrestore(&p->lock, flags);
+		ret = 0;
+		goto exit;
+	}
+	spin_unlock_irqrestore(&p->lock, flags);
+
+	ret = _rmnet_xmit(skb, dev);
+	if (ret == -EPERM) {
+		ret = NETDEV_TX_BUSY;
+		goto exit;
+	}
+
+	/*
+	 * detected SSR a bit early.  shut some things down now, and leave
+	 * the rest to the main ssr handling code when that happens later
+	 */
+	if (ret == -EFAULT) {
+		netif_carrier_off(dev);
+		dev_kfree_skb_any(skb);
+		ret = 0;
+		goto exit;
+	}
+
+	if (ret == -EAGAIN) {
+		/*
+		 * This should not happen
+		 * EAGAIN means we attempted to overflow the high watermark
+		 * Clearly the queue is not stopped like it should be, so
+		 * stop it and return BUSY to the TCP/IP framework.  It will
+		 * retry this packet with the queue is restarted which happens
+		 * in the write_done callback when the low watermark is hit.
+		 */
+		netif_stop_queue(dev);
+		ret = NETDEV_TX_BUSY;
+		goto exit;
+	}
+
+	spin_lock_irqsave(&p->tx_queue_lock, flags);
+	if (msm_bam_dmux_is_ch_full(p->ch_id)) {
+		netif_stop_queue(dev);
+		DBG0("%s: High WM hit, stopping queue=%pK\n",    __func__, skb);
+	}
+	spin_unlock_irqrestore(&p->tx_queue_lock, flags);
+
+exit:
+	msm_bam_dmux_ul_power_unvote();
+	return ret;
+}
+
+static struct net_device_stats *rmnet_get_stats(struct net_device *dev)
+{
+	struct rmnet_private *p = netdev_priv(dev);
+
+	return &p->stats;
+}
+
+static void rmnet_tx_timeout(struct net_device *dev)
+{
+	pr_warn("[%s] rmnet_tx_timeout()\n", dev->name);
+}
+
+static const struct net_device_ops rmnet_ops_ether = {
+	.ndo_open = rmnet_open,
+	.ndo_stop = rmnet_stop,
+	.ndo_start_xmit = rmnet_xmit,
+	.ndo_get_stats = rmnet_get_stats,
+	.ndo_tx_timeout = rmnet_tx_timeout,
+	.ndo_do_ioctl = rmnet_ioctl,
+	.ndo_change_mtu = rmnet_change_mtu,
+	.ndo_set_mac_address = eth_mac_addr,
+	.ndo_validate_addr = eth_validate_addr,
+};
+
+static const struct net_device_ops rmnet_ops_ip = {
+	.ndo_open = rmnet_open,
+	.ndo_stop = rmnet_stop,
+	.ndo_start_xmit = rmnet_xmit,
+	.ndo_get_stats = rmnet_get_stats,
+	.ndo_tx_timeout = rmnet_tx_timeout,
+	.ndo_do_ioctl = rmnet_ioctl,
+	.ndo_change_mtu = rmnet_change_mtu,
+	.ndo_set_mac_address = NULL,
+	.ndo_validate_addr = NULL,
+};
+
+static void _rmnet_free_bam_later(struct work_struct *work)
+{
+	struct rmnet_free_bam_work *fwork;
+
+	fwork = container_of(work, struct rmnet_free_bam_work, work);
+
+	DBG0("%s: unregister_netdev, done\n", __func__);
+
+	if (bam_rmnet_drivers[fwork->ch_id].remove) {
+		platform_driver_unregister(&bam_rmnet_drivers[fwork->ch_id]);
+		bam_rmnet_drivers[fwork->ch_id].remove = NULL;
+	}
+
+	DBG0("%s: free_netdev, done\n", __func__);
+
+	kfree(work);
+}
+
+static int rmnet_ioctl_extended(struct net_device *dev, struct ifreq *ifr)
+{
+	struct rmnet_ioctl_extended_s ext_cmd;
+	int rc = 0;
+	struct rmnet_private *p = netdev_priv(dev);
+	struct rmnet_free_bam_work *work;
+
+	rc = copy_from_user(&ext_cmd, ifr->ifr_ifru.ifru_data,
+			    sizeof(ext_cmd));
+
+	if (rc) {
+		pr_err("%s: copy_from_user failed ,error %d\n", __func__, rc);
+		return -EFAULT;
+	}
+
+	switch (ext_cmd.extended_ioctl) {
+	case RMNET_IOCTL_SET_MRU:
+		/* Transport MRU is fixed, so do nothing */
+		break;
+	case RMNET_IOCTL_GET_EPID:
+		ext_cmd.u.data = p->ch_id;
+		break;
+	case RMNET_IOCTL_GET_SUPPORTED_FEATURES:
+		ext_cmd.u.data = 0;
+		break;
+	case RMNET_IOCTL_GET_DRIVER_NAME:
+		strlcpy(ext_cmd.u.if_name, RMNET_BAM_DRIVER_NAME,
+			sizeof(ext_cmd.u.if_name));
+		break;
+	case RMNET_IOCTL_DEREGISTER_DEV:
+		work = kmalloc(sizeof(*work), GFP_KERNEL);
+		if (!work)
+			break;
+		INIT_WORK(&work->work, _rmnet_free_bam_later);
+
+		work->ch_id = p->ch_id;
+		schedule_work(&work->work);
+		break;
+	default:
+		rc = -EINVAL;
+		break;
+	}
+
+	rc = copy_to_user(ifr->ifr_ifru.ifru_data, &ext_cmd, sizeof(ext_cmd));
+
+	if (rc)
+		pr_err("%s: copy_to_user failed, error %d\n", __func__, rc);
+
+	return rc ? -EFAULT : 0;
+}
+
+static int rmnet_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	struct rmnet_private *p = netdev_priv(dev);
+	u32 old_opmode = p->operation_mode;
+	unsigned long flags;
+	int prev_mtu = dev->mtu;
+	int rc = 0;
+	struct rmnet_ioctl_data_s ioctl_data;
+
+	/* Process IOCTL command */
+	switch (cmd) {
+	case RMNET_IOCTL_SET_LLP_ETHERNET:  /* Set Ethernet protocol   */
+		/* Perform Ethernet config only if in IP mode currently*/
+		if (p->operation_mode & RMNET_MODE_LLP_IP) {
+			ether_setup(dev);
+			random_ether_addr(dev->dev_addr);
+			dev->mtu = prev_mtu;
+
+			dev->netdev_ops = &rmnet_ops_ether;
+			spin_lock_irqsave(&p->lock, flags);
+			p->operation_mode &= ~RMNET_MODE_LLP_IP;
+			p->operation_mode |= RMNET_MODE_LLP_ETH;
+			spin_unlock_irqrestore(&p->lock, flags);
+			DBG0("[%s] rmnet_ioctl():set Ethernet protocol mode\n",
+				dev->name);
+		}
+		break;
+
+	case RMNET_IOCTL_SET_LLP_IP:        /* Set RAWIP protocol      */
+		/* Perform IP config only if in Ethernet mode currently*/
+		if (p->operation_mode & RMNET_MODE_LLP_ETH) {
+
+			/* Undo config done in ether_setup() */
+			dev->header_ops         = NULL;  /* No header */
+			dev->type               = ARPHRD_RAWIP;
+			dev->hard_header_len    = 0;
+			dev->mtu                = prev_mtu;
+			dev->addr_len           = 0;
+			dev->flags              &= ~(IFF_BROADCAST|
+						     IFF_MULTICAST);
+
+			dev->needed_headroom = HEADROOM_FOR_BAM +
+			  HEADROOM_FOR_QOS;
+			dev->needed_tailroom = TAILROOM;
+			dev->netdev_ops = &rmnet_ops_ip;
+			spin_lock_irqsave(&p->lock, flags);
+			p->operation_mode &= ~RMNET_MODE_LLP_ETH;
+			p->operation_mode |= RMNET_MODE_LLP_IP;
+			spin_unlock_irqrestore(&p->lock, flags);
+			DBG0("[%s] rmnet_ioctl(): set IP protocol mode\n",
+				dev->name);
+		}
+		break;
+
+	case RMNET_IOCTL_GET_LLP:           /* Get link protocol state */
+		ioctl_data.u.operation_mode = (p->operation_mode &
+				 (RMNET_MODE_LLP_ETH|RMNET_MODE_LLP_IP));
+		if (copy_to_user(ifr->ifr_ifru.ifru_data, &ioctl_data,
+			sizeof(struct rmnet_ioctl_data_s)))
+			rc = -EFAULT;
+		break;
+
+	case RMNET_IOCTL_SET_QOS_ENABLE:    /* Set QoS header enabled  */
+		spin_lock_irqsave(&p->lock, flags);
+		p->operation_mode |= RMNET_MODE_QOS;
+		spin_unlock_irqrestore(&p->lock, flags);
+		DBG0("[%s] rmnet_ioctl(): set QMI QOS header enable\n",
+			dev->name);
+		break;
+
+	case RMNET_IOCTL_SET_QOS_DISABLE:   /* Set QoS header disabled */
+		spin_lock_irqsave(&p->lock, flags);
+		p->operation_mode &= ~RMNET_MODE_QOS;
+		spin_unlock_irqrestore(&p->lock, flags);
+		DBG0("[%s] rmnet_ioctl(): set QMI QOS header disable\n",
+			dev->name);
+		break;
+
+	case RMNET_IOCTL_FLOW_ENABLE:
+		if (copy_from_user(&ioctl_data, ifr->ifr_ifru.ifru_data,
+			sizeof(struct rmnet_ioctl_data_s))) {
+			rc = -EFAULT;
+			break;
+		}
+		tc_qdisc_flow_control(dev, ioctl_data.u.tcm_handle, 1);
+		DBG0("[%s] rmnet_ioctl(): enabled flow\n", dev->name);
+		break;
+
+	case RMNET_IOCTL_FLOW_DISABLE:
+		if (copy_from_user(&ioctl_data, ifr->ifr_ifru.ifru_data,
+			sizeof(struct rmnet_ioctl_data_s))) {
+			rc = -EFAULT;
+			break;
+		}
+		tc_qdisc_flow_control(dev, ioctl_data.u.tcm_handle, 0);
+		DBG0("[%s] rmnet_ioctl(): disabled flow\n", dev->name);
+		break;
+
+	case RMNET_IOCTL_GET_QOS:           /* Get QoS header state    */
+		ioctl_data.u.operation_mode = (p->operation_mode
+						& RMNET_MODE_QOS);
+		if (copy_to_user(ifr->ifr_ifru.ifru_data, &ioctl_data,
+			sizeof(struct rmnet_ioctl_data_s)))
+			rc = -EFAULT;
+		break;
+
+	case RMNET_IOCTL_GET_OPMODE:        /* Get operation mode      */
+		ioctl_data.u.operation_mode = p->operation_mode;
+		if (copy_to_user(ifr->ifr_ifru.ifru_data, &ioctl_data,
+			sizeof(struct rmnet_ioctl_data_s)))
+			rc = -EFAULT;
+		break;
+
+	case RMNET_IOCTL_OPEN:              /* Open transport port     */
+		rc = __rmnet_open(dev);
+		DBG0("[%s] rmnet_ioctl(): open transport port\n",
+			dev->name);
+		break;
+
+	case RMNET_IOCTL_CLOSE:             /* Close transport port    */
+		rc = __rmnet_close(dev);
+		DBG0("[%s] rmnet_ioctl(): close transport port\n",
+			dev->name);
+		break;
+
+	case RMNET_IOCTL_EXTENDED:          /* Extended IOCTL's        */
+		rc = rmnet_ioctl_extended(dev, ifr);
+		break;
+
+	default:
+		pr_err("[%s] error: rmnet_ioct called for unsupported cmd[%x]\n",
+			dev->name, cmd);
+		return -EINVAL;
+	}
+
+	DBG2("[%s] %s: cmd=0x%x opmode old=0x%08x new=0x%08x\n",
+		dev->name, __func__, cmd, old_opmode, p->operation_mode);
+	return rc;
+}
+
+static void rmnet_setup(struct net_device *dev)
+{
+	/* Using Ethernet mode by default */
+	dev->netdev_ops = &rmnet_ops_ether;
+	ether_setup(dev);
+
+	/* set this after calling ether_setup */
+	dev->mtu = RMNET_DATA_LEN;
+	dev->needed_headroom = HEADROOM_FOR_BAM + HEADROOM_FOR_QOS;
+	dev->needed_tailroom = TAILROOM;
+	random_ether_addr(dev->dev_addr);
+
+	dev->watchdog_timeo = 1000; /* 10 seconds? */
+}
+
+
+#ifdef CONFIG_MSM_RMNET_DEBUG
+static int rmnet_debug_init(struct net_device *dev)
+{
+
+	struct device *d;
+	struct rmnet_private *p;
+	int err = 0;
+
+	d = &(dev->dev);
+	p = netdev_priv(dev);
+	p->timeout_us = 0;
+	p->wakeups_xmit = p->wakeups_rcv = 0;
+	err = device_create_file(d, &dev_attr_timeout);
+	if (err)
+		return err;
+	err = device_create_file(d, &dev_attr_wakeups_xmit);
+	if (err)
+		return err;
+	err = device_create_file(d, &dev_attr_wakeups_rcv);
+	return err;
+}
+#else
+static int rmnet_debug_init(struct net_device *dev)
+{
+	return 0;
+}
+#endif
+
+static int bam_rmnet_probe(struct platform_device *pdev)
+{
+	int i, ret;
+	struct rmnet_private *p;
+	struct device *d;
+	char name[BAM_DMUX_CH_NAME_MAX_LEN];
+	struct net_device *dev;
+	const char *dev_name;
+
+	for (i = 0; i < BAM_DMUX_NUM_CHANNELS; ++i) {
+		scnprintf(name, BAM_DMUX_CH_NAME_MAX_LEN, "bam_dmux_ch_%d", i);
+		if (!strcmp(pdev->name, name))
+			break;
+	}
+
+	if (((i > BAM_DMUX_DATA_RMNET_7) && (i < BAM_DMUX_DATA_REV_RMNET_0)) ||
+	    (i >= BAM_DMUX_NUM_CHANNELS)) {
+		pr_err("%s: wrong netdev %s\n", __func__, pdev->name);
+		return -ENODEV;
+	}
+
+	if (i <= BAM_DMUX_DATA_RMNET_7)
+		dev_name = "rmnet%d";
+	else
+		dev_name = "rev_rmnet%d";
+
+	dev = alloc_netdev(sizeof(*p), dev_name, NET_NAME_ENUM, rmnet_setup);
+	if (!dev) {
+		pr_err("%s: no memory for netdev %d\n", __func__, i);
+		return -ENOMEM;
+	}
+
+	netdevs[i] = dev;
+	d = &(dev->dev);
+	p = netdev_priv(dev);
+	/* Initial config uses Ethernet */
+	p->operation_mode = RMNET_MODE_LLP_ETH;
+	p->ch_id = i;
+	p->waiting_for_ul_skb = NULL;
+	p->device_up = DEVICE_UNINITIALIZED;
+	spin_lock_init(&p->lock);
+	spin_lock_init(&p->tx_queue_lock);
+
+	ret = register_netdev(dev);
+	if (ret) {
+		pr_err("%s: unable to register netdev %d rc=%d\n",
+			__func__, i, ret);
+		netdevs[i] = NULL;
+		free_netdev(dev);
+		return ret;
+	}
+
+	rmnet_debug_init(dev);
+
+	return 0;
+}
+
+static int bam_rmnet_remove(struct platform_device *pdev)
+{
+	int i;
+	struct rmnet_private *p;
+	char name[BAM_DMUX_CH_NAME_MAX_LEN];
+
+	for (i = 0; i < BAM_DMUX_NUM_CHANNELS; ++i) {
+		scnprintf(name, BAM_DMUX_CH_NAME_MAX_LEN, "bam_dmux_ch_%d", i);
+		if (!strcmp(pdev->name, name))
+			break;
+	}
+
+	if (((i > BAM_DMUX_DATA_RMNET_7) && (i < BAM_DMUX_DATA_REV_RMNET_0)) ||
+	    (i >= BAM_DMUX_NUM_CHANNELS)) {
+		pr_err("%s: wrong netdev %s\n", __func__, pdev->name);
+		return -ENODEV;
+	}
+
+	p = netdev_priv(netdevs[i]);
+	if (p->waiting_for_ul_skb != NULL) {
+		dev_kfree_skb_any(p->waiting_for_ul_skb);
+		p->waiting_for_ul_skb = NULL;
+	}
+	msm_bam_dmux_close(p->ch_id);
+	netif_carrier_off(netdevs[i]);
+	netif_stop_queue(netdevs[i]);
+
+	unregister_netdev(netdevs[i]);
+	free_netdev(netdevs[i]);
+
+	return 0;
+}
+
+#ifdef CONFIG_MSM_RMNET_DEBUG
+static void rmnet_clear_timeout_us(void)
+{
+	timeout_us = 0;
+}
+#else
+static void rmnet_clear_timeout_us(void)
+{
+	; /*Do Nothing*/
+}
+#endif /* CONFIG_MSM_RMNET_DEBUG */
+
+static int __init rmnet_init(void)
+{
+	unsigned int n;
+	char *tempname;
+
+	rmnet_clear_timeout_us();
+
+	n = 0;
+	while (n <= BAM_DMUX_DATA_REV_RMNET_8) {
+		if ((n > BAM_DMUX_DATA_RMNET_7) &&
+		    (n < BAM_DMUX_DATA_REV_RMNET_0)) {
+			n++;
+			continue;
+		}
+		bam_rmnet_drivers[n].probe = bam_rmnet_probe;
+		bam_rmnet_drivers[n].remove = bam_rmnet_remove;
+		tempname = kmalloc(BAM_DMUX_CH_NAME_MAX_LEN, GFP_KERNEL);
+		if (tempname == NULL) {
+			netdevs[n] = NULL;
+			return -ENOMEM;
+		}
+		scnprintf(tempname, BAM_DMUX_CH_NAME_MAX_LEN, "bam_dmux_ch_%d",
+			  n);
+		bam_rmnet_drivers[n].driver.name = tempname;
+		bam_rmnet_drivers[n].driver.owner = THIS_MODULE;
+		platform_driver_register(&bam_rmnet_drivers[n]);
+		n++;
+	}
+
+	return 0;
+}
+
+module_init(rmnet_init);
+MODULE_DESCRIPTION("MSM RMNET BAM TRANSPORT");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index e01839f..6e54fbf 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -2336,8 +2336,11 @@
 	mutex_lock(&bam->lock);
 	sps_bam_device_de_init(bam);
 	mutex_unlock(&bam->lock);
+	ipc_log_context_destroy(bam->ipc_log0);
 	ipc_log_context_destroy(bam->ipc_log1);
 	ipc_log_context_destroy(bam->ipc_log2);
+	ipc_log_context_destroy(bam->ipc_log3);
+	ipc_log_context_destroy(bam->ipc_log4);
 	if (bam->props.virt_size)
 		(void)iounmap(bam->props.virt_addr);
 
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index c1ab20c..7d6a7eb 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -646,11 +646,18 @@
 		      pipe_index++) {
 			pipe = dev->pipes[pipe_index];
 			if (BAM_PIPE_IS_ASSIGNED(pipe)) {
-				SPS_ERR(dev,
-					"sps:BAM device %pa RESET failed: pipe %d in use\n",
+				if (!(dev->props.options &
+							SPS_BAM_FORCE_RESET)) {
+					SPS_ERR(dev,
+						"sps:BAM device %pa RESET failed: pipe %d in use\n",
+						BAM_ID(dev), pipe_index);
+					result = SPS_ERROR;
+					break;
+				}
+
+				SPS_DBG2(dev,
+					"sps: BAM %pa is force reset with pipe %d in use\n",
 					BAM_ID(dev), pipe_index);
-				result = SPS_ERROR;
-				break;
 			}
 		}
 
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 6314270..b4cd640 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -2729,12 +2729,12 @@
 
 		if (bam_type == CI_CTRL)
 			msm_hw_bam_disable(0);
-		/* Enable usb irq here which is disabled in function drivers
-		 * during disconnect after BAM reset.
-		 */
-		if (bam_type == CI_CTRL)
-			msm_usb_irq_disable(false);
 	}
+	/* Enable usb irq here which is disabled in function drivers
+	 * during disconnect after BAM reset.
+	 */
+	if (!ctx->pipes_enabled_per_bam && (bam_type == CI_CTRL))
+		msm_usb_irq_disable(false);
 	/* This function is directly called by USB Transport drivers
 	 * to disconnect pipes. Drop runtime usage count here. For
 	 * IPA, caller takes care of it
@@ -3136,6 +3136,7 @@
 					&& bam_type == CI_CTRL) {
 		pr_debug("Register and enable HSUSB BAM\n");
 		props.options |= SPS_BAM_OPT_ENABLE_AT_BOOT;
+		props.options |= SPS_BAM_FORCE_RESET;
 	}
 
 	dev = &ctx->usb_bam_pdev->dev;
@@ -3406,6 +3407,127 @@
 }
 EXPORT_SYMBOL(usb_bam_get_bam_type);
 
+/*
+ * This function makes sure ipa endpoints are disabled for both USB->IPA
+ * and IPA->USB pipes before USB bam reset. USB BAM reset is required to
+ * to avoid EP flush issues while disabling USB endpoints on disconnect.
+ */
+int msm_do_bam_disable_enable(enum usb_ctrl bam)
+{
+	struct usb_bam_ctx_type *ctx = &msm_usb_bam[bam];
+	struct sps_pipe *pipe;
+	u32 timeout = 10, pipe_empty;
+	int ret = 0, i;
+	struct sps_connect *sps_connection;
+	struct usb_bam_sps_type usb_bam_sps = ctx->usb_bam_sps;
+	struct usb_bam_pipe_connect *pipe_connect;
+	int qdss_idx;
+	struct msm_usb_bam_data *usb_bam_data;
+
+	if (!ctx->usb_bam_pdev)
+		return 0;
+
+	usb_bam_data = ctx->usb_bam_data;
+	if ((bam != CI_CTRL) || !usb_bam_data->enable_hsusb_bam_on_boot)
+		return 0;
+
+	if (!ctx->pipes_enabled_per_bam || info[bam].pipes_suspended)
+		return 0;
+
+	if (in_interrupt()) {
+		pr_err("%s:API called in interrupt context\n", __func__);
+		return 0;
+	}
+
+	mutex_lock(&info[bam].suspend_resume_mutex);
+	log_event_dbg("%s: Perform USB BAM reset\n", __func__);
+	/* Get QDSS pipe index to avoid pipe reset */
+	qdss_idx = usb_bam_get_connection_idx(qdss_usb_bam_type, QDSS_P_BAM,
+		PEER_PERIPHERAL_TO_USB, USB_BAM_DEVICE, 0);
+
+	for (i = 0; i < ctx->max_connections; i++) {
+		pipe_connect = &ctx->usb_bam_connections[i];
+		if (pipe_connect->enabled &&
+				(pipe_connect->dir == PEER_PERIPHERAL_TO_USB) &&
+							(qdss_idx != i)) {
+			/* Call to disable IPA producer endpoint */
+			ipa_disable_endpoint(pipe_connect->ipa_clnt_hdl);
+			sps_pipe_reset(ctx->h_bam,
+						pipe_connect->dst_pipe_index);
+		}
+	}
+
+	for (i = 0; i < ctx->max_connections; i++) {
+		pipe_connect = &ctx->usb_bam_connections[i];
+		if (pipe_connect->enabled &&
+				(pipe_connect->dir == USB_TO_PEER_PERIPHERAL) &&
+							(qdss_idx != i)) {
+			pipe = ctx->usb_bam_sps.sps_pipes[i];
+			sps_connection = &usb_bam_sps.sps_connections[i];
+			timeout = 10;
+			/*
+			 * On some platforms, there is a chance that flow
+			 * control is disabled from IPA side, due to this IPA
+			 * core may not consume data from USB. Hence notify IPA
+			 * to enable flow control and then check sps pipe is
+			 * empty or not before processing USB->IPA disconnect.
+			 */
+			ipa_clear_endpoint_delay(pipe_connect->ipa_clnt_hdl);
+
+			/* Make sure pipes are empty before disconnecting it */
+			while (1) {
+				ret = sps_is_pipe_empty(pipe, &pipe_empty);
+				if (ret) {
+					log_event_err("%s: pipeempty fail %d\n",
+								__func__, ret);
+					goto err;
+				}
+				if (pipe_empty || !--timeout)
+					break;
+
+				/* Check again */
+				usleep_range(1000, 2000);
+			}
+			if (!pipe_empty) {
+				log_event_dbg("%s: Inject ZLT\n", __func__);
+				sps_pipe_inject_zlt(sps_connection->destination,
+					sps_connection->dest_pipe_index);
+
+				timeout = 0;
+				while (1) {
+					ret = sps_is_pipe_empty(pipe,
+								&pipe_empty);
+					if (ret)
+						goto err;
+
+					if (pipe_empty)
+						break;
+
+					timeout++;
+					/* Check again */
+					usleep_range(1000, 2000);
+				}
+			}
+			/* Call to disable IPA consumer endpoint */
+			ipa_disable_endpoint(pipe_connect->ipa_clnt_hdl);
+			sps_pipe_reset(ctx->h_bam,
+						pipe_connect->src_pipe_index);
+		}
+	}
+
+	/* Perform USB BAM reset */
+	msm_hw_bam_disable(1);
+	sps_device_reset(ctx->h_bam);
+	msm_hw_bam_disable(0);
+	log_event_dbg("%s: USB BAM reset done\n", __func__);
+	ret = 0;
+
+err:
+	mutex_unlock(&info[bam].suspend_resume_mutex);
+	return ret;
+}
+EXPORT_SYMBOL(msm_do_bam_disable_enable);
+
 bool msm_usb_bam_enable(enum usb_ctrl bam, bool bam_enable)
 {
 	struct msm_usb_bam_data *usb_bam_data;
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index f4a36a3..03bfd48 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -327,6 +327,8 @@
 	POWER_SUPPLY_ATTR(batt_profile_version),
 	POWER_SUPPLY_ATTR(batt_full_current),
 	POWER_SUPPLY_ATTR(recharge_soc),
+	POWER_SUPPLY_ATTR(toggle_stat),
+	POWER_SUPPLY_ATTR(allow_hvdcp3),
 	/* Local extensions of type int64_t */
 	POWER_SUPPLY_ATTR(charge_counter_ext),
 	/* Properties of type `const char *' */
diff --git a/drivers/power/supply/qcom/Kconfig b/drivers/power/supply/qcom/Kconfig
index e653475..e571eb4 100644
--- a/drivers/power/supply/qcom/Kconfig
+++ b/drivers/power/supply/qcom/Kconfig
@@ -124,4 +124,12 @@
 	  to determine the battery state-of-charge (SOC) and supports other
 	  battery management features.
 
+config SMB1390_CHARGE_PUMP
+	tristate "SMB1390 Charge Pump"
+	depends on MFD_I2C_PMIC
+	help
+	  Say Y to include support for SMB1390 Charge Pump.
+	  SMB1390 is a div2 charge pump capable of delivering 6A charge current
+	  with very high efficiency.
+
 endmenu
diff --git a/drivers/power/supply/qcom/Makefile b/drivers/power/supply/qcom/Makefile
index 662f18d..de76a5b 100644
--- a/drivers/power/supply/qcom/Makefile
+++ b/drivers/power/supply/qcom/Makefile
@@ -10,3 +10,4 @@
 obj-$(CONFIG_QPNP_QNOVO)	+= qpnp-qnovo.o battery.o
 obj-$(CONFIG_QPNP_TYPEC)	+= qpnp-typec.o
 obj-$(CONFIG_QPNP_SMB5)		+= step-chg-jeita.o battery.o qpnp-smb5.o smb5-lib.o pmic-voter.o storm-watch.o schgm-flash.o
+obj-$(CONFIG_SMB1390_CHARGE_PUMP)	+= smb1390-charger.o pmic-voter.o
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index 76bb974..4bd6c4f 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -13,6 +13,7 @@
 #ifndef __FG_CORE_H__
 #define __FG_CORE_H__
 
+#include <linux/alarmtimer.h>
 #include <linux/atomic.h>
 #include <linux/bitops.h>
 #include <linux/debugfs.h>
@@ -249,6 +250,12 @@
 	SLOPE_LIMIT_NUM_COEFFS,
 };
 
+enum esr_filter_status {
+	ROOM_TEMP = 1,
+	LOW_TEMP,
+	RELAX_TEMP,
+};
+
 enum esr_timer_config {
 	TIMER_RETRY = 0,
 	TIMER_MAX,
@@ -296,6 +303,9 @@
 	int	esr_broad_flt_upct;
 	int	esr_tight_lt_flt_upct;
 	int	esr_broad_lt_flt_upct;
+	int	esr_flt_rt_switch_temp;
+	int	esr_tight_rt_flt_upct;
+	int	esr_broad_rt_flt_upct;
 	int	slope_limit_temp;
 	int	esr_pulse_thresh_ma;
 	int	esr_meas_curr_ma;
@@ -434,6 +444,7 @@
 	struct mutex		sram_rw_lock;
 	struct mutex		charge_full_lock;
 	struct mutex		qnovo_esr_ctrl_lock;
+	spinlock_t		suspend_lock;
 	u32			batt_soc_base;
 	u32			batt_info_base;
 	u32			mem_if_base;
@@ -453,8 +464,10 @@
 	int			delta_soc;
 	int			last_msoc;
 	int			last_recharge_volt_mv;
+	int			delta_temp_irq_count;
 	int			esr_timer_charging_default[NUM_ESR_TIMERS];
 	enum slope_limit_status	slope_limit_sts;
+	enum esr_filter_status	esr_flt_sts;
 	bool			profile_available;
 	bool			profile_loaded;
 	enum prof_load_status	profile_load_status;
@@ -470,6 +483,7 @@
 	bool			use_ima_single_mode;
 	bool			use_dma;
 	bool			qnovo_enable;
+	bool			suspended;
 	struct completion	soc_update;
 	struct completion	soc_ready;
 	struct delayed_work	profile_load_work;
@@ -477,6 +491,9 @@
 	struct delayed_work	ttf_work;
 	struct delayed_work	sram_dump_work;
 	struct delayed_work	pl_enable_work;
+	struct work_struct	esr_filter_work;
+	struct alarm		esr_filter_alarm;
+	ktime_t			last_delta_temp_time;
 };
 
 /* Debugfs data structures are below */
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 420f2fd..5a9b8f6 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -2205,10 +2205,66 @@
 	return 0;
 }
 
-static int fg_esr_filter_config(struct fg_chip *chip, int batt_temp)
+static int __fg_esr_filter_config(struct fg_chip *chip,
+				enum esr_filter_status esr_flt_sts)
 {
-	u8 esr_tight_lt_flt, esr_broad_lt_flt;
-	bool cold_temp = false;
+	u8 esr_tight_flt, esr_broad_flt;
+	int esr_tight_flt_upct, esr_broad_flt_upct;
+	int rc;
+
+	if (esr_flt_sts == chip->esr_flt_sts)
+		return 0;
+
+	if (esr_flt_sts == ROOM_TEMP) {
+		esr_tight_flt_upct = chip->dt.esr_tight_flt_upct;
+		esr_broad_flt_upct = chip->dt.esr_broad_flt_upct;
+	} else if (esr_flt_sts == LOW_TEMP) {
+		esr_tight_flt_upct = chip->dt.esr_tight_lt_flt_upct;
+		esr_broad_flt_upct = chip->dt.esr_broad_lt_flt_upct;
+	} else if (esr_flt_sts == RELAX_TEMP) {
+		esr_tight_flt_upct = chip->dt.esr_tight_rt_flt_upct;
+		esr_broad_flt_upct = chip->dt.esr_broad_rt_flt_upct;
+	} else {
+		pr_err("Unknown esr filter config\n");
+		return 0;
+	}
+
+	fg_encode(chip->sp, FG_SRAM_ESR_TIGHT_FILTER, esr_tight_flt_upct,
+		&esr_tight_flt);
+	rc = fg_sram_write(chip, chip->sp[FG_SRAM_ESR_TIGHT_FILTER].addr_word,
+			chip->sp[FG_SRAM_ESR_TIGHT_FILTER].addr_byte,
+			&esr_tight_flt,
+			chip->sp[FG_SRAM_ESR_TIGHT_FILTER].len, FG_IMA_DEFAULT);
+	if (rc < 0) {
+		pr_err("Error in writing ESR LT tight filter, rc=%d\n", rc);
+		return rc;
+	}
+
+	fg_encode(chip->sp, FG_SRAM_ESR_BROAD_FILTER, esr_broad_flt_upct,
+		&esr_broad_flt);
+	rc = fg_sram_write(chip, chip->sp[FG_SRAM_ESR_BROAD_FILTER].addr_word,
+			chip->sp[FG_SRAM_ESR_BROAD_FILTER].addr_byte,
+			&esr_broad_flt,
+			chip->sp[FG_SRAM_ESR_BROAD_FILTER].len, FG_IMA_DEFAULT);
+	if (rc < 0) {
+		pr_err("Error in writing ESR LT broad filter, rc=%d\n", rc);
+		return rc;
+	}
+
+	chip->esr_flt_sts = esr_flt_sts;
+	fg_dbg(chip, FG_STATUS, "applied ESR filter %d values\n", esr_flt_sts);
+	return 0;
+}
+
+#define DT_IRQ_COUNT			3
+#define DELTA_TEMP_IRQ_TIME_MS		300000
+#define ESR_FILTER_ALARM_TIME_MS	900000
+static int fg_esr_filter_config(struct fg_chip *chip, int batt_temp,
+				bool override)
+{
+	enum esr_filter_status esr_flt_sts = ROOM_TEMP;
+	bool qnovo_en, input_present, count_temp_irq = false;
+	s64 time_ms;
 	int rc;
 
 	/*
@@ -2218,6 +2274,47 @@
 	if (batt_temp < -210)
 		return 0;
 
+	qnovo_en = is_qnovo_en(chip);
+	input_present = is_input_present(chip);
+
+	/*
+	 * If Qnovo is enabled, after hitting a lower battery temperature of
+	 * say 6 C, count the delta battery temperature interrupts for a
+	 * certain period of time when the battery temperature increases.
+	 * Switch to relaxed filter coefficients once the temperature increase
+	 * is qualified so that ESR accuracy can be improved.
+	 */
+	if (qnovo_en && !override) {
+		if (input_present) {
+			if (chip->esr_flt_sts == RELAX_TEMP) {
+				/* do nothing */
+				return 0;
+			}
+
+			count_temp_irq =  true;
+			if (chip->delta_temp_irq_count) {
+				/* Don't count when temperature is dropping. */
+				if (batt_temp <= chip->last_batt_temp)
+					count_temp_irq = false;
+			} else {
+				/*
+				 * Starting point for counting. Check if the
+				 * temperature is qualified.
+				 */
+				if (batt_temp > chip->dt.esr_flt_rt_switch_temp)
+					count_temp_irq = false;
+				else
+					chip->last_delta_temp_time =
+						ktime_get();
+			}
+		} else {
+			chip->delta_temp_irq_count = 0;
+			rc = alarm_try_to_cancel(&chip->esr_filter_alarm);
+			if (rc < 0)
+				pr_err("Couldn't cancel esr_filter_alarm\n");
+		}
+	}
+
 	/*
 	 * If battery temperature is lesser than 10 C (default), then apply the
 	 * ESR low temperature tight and broad filter values to ESR room
@@ -2225,47 +2322,82 @@
 	 * than 10 C, then apply back the room temperature ESR filter
 	 * coefficients to ESR room temperature tight and broad filters.
 	 */
-	if (batt_temp > chip->dt.esr_flt_switch_temp
-		&& chip->esr_flt_cold_temp_en) {
-		fg_encode(chip->sp, FG_SRAM_ESR_TIGHT_FILTER,
-			chip->dt.esr_tight_flt_upct, &esr_tight_lt_flt);
-		fg_encode(chip->sp, FG_SRAM_ESR_BROAD_FILTER,
-			chip->dt.esr_broad_flt_upct, &esr_broad_lt_flt);
-	} else if (batt_temp <= chip->dt.esr_flt_switch_temp
-			&& !chip->esr_flt_cold_temp_en) {
-		fg_encode(chip->sp, FG_SRAM_ESR_TIGHT_FILTER,
-			chip->dt.esr_tight_lt_flt_upct, &esr_tight_lt_flt);
-		fg_encode(chip->sp, FG_SRAM_ESR_BROAD_FILTER,
-			chip->dt.esr_broad_lt_flt_upct, &esr_broad_lt_flt);
-		cold_temp = true;
-	} else {
-		return 0;
+	if (batt_temp > chip->dt.esr_flt_switch_temp)
+		esr_flt_sts = ROOM_TEMP;
+	else
+		esr_flt_sts = LOW_TEMP;
+
+	if (count_temp_irq) {
+		time_ms = ktime_ms_delta(ktime_get(),
+				chip->last_delta_temp_time);
+		chip->delta_temp_irq_count++;
+		fg_dbg(chip, FG_STATUS, "dt_irq_count: %d\n",
+			chip->delta_temp_irq_count);
+
+		if (chip->delta_temp_irq_count >= DT_IRQ_COUNT
+			&& time_ms <= DELTA_TEMP_IRQ_TIME_MS) {
+			fg_dbg(chip, FG_STATUS, "%d interrupts in %lld ms\n",
+				chip->delta_temp_irq_count, time_ms);
+			esr_flt_sts = RELAX_TEMP;
+		}
 	}
 
-	rc = fg_sram_write(chip, chip->sp[FG_SRAM_ESR_TIGHT_FILTER].addr_word,
-			chip->sp[FG_SRAM_ESR_TIGHT_FILTER].addr_byte,
-			&esr_tight_lt_flt,
-			chip->sp[FG_SRAM_ESR_TIGHT_FILTER].len, FG_IMA_DEFAULT);
-	if (rc < 0) {
-		pr_err("Error in writing ESR LT tight filter, rc=%d\n", rc);
+	rc = __fg_esr_filter_config(chip, esr_flt_sts);
+	if (rc < 0)
 		return rc;
-	}
 
-	rc = fg_sram_write(chip, chip->sp[FG_SRAM_ESR_BROAD_FILTER].addr_word,
-			chip->sp[FG_SRAM_ESR_BROAD_FILTER].addr_byte,
-			&esr_broad_lt_flt,
-			chip->sp[FG_SRAM_ESR_BROAD_FILTER].len, FG_IMA_DEFAULT);
-	if (rc < 0) {
-		pr_err("Error in writing ESR LT broad filter, rc=%d\n", rc);
-		return rc;
-	}
+	if (esr_flt_sts == RELAX_TEMP)
+		alarm_start_relative(&chip->esr_filter_alarm,
+			ms_to_ktime(ESR_FILTER_ALARM_TIME_MS));
 
-	chip->esr_flt_cold_temp_en = cold_temp;
-	fg_dbg(chip, FG_STATUS, "applied %s ESR filter values\n",
-		cold_temp ? "cold" : "normal");
 	return 0;
 }
 
+#define FG_ESR_FILTER_RESTART_MS	60000
+static void esr_filter_work(struct work_struct *work)
+{
+	struct fg_chip *chip = container_of(work,
+			struct fg_chip, esr_filter_work);
+	int rc, batt_temp;
+
+	rc = fg_get_battery_temp(chip, &batt_temp);
+	if (rc < 0) {
+		pr_err("Error in getting batt_temp\n");
+		alarm_start_relative(&chip->esr_filter_alarm,
+			ms_to_ktime(FG_ESR_FILTER_RESTART_MS));
+		goto out;
+	}
+
+	rc = fg_esr_filter_config(chip, batt_temp, true);
+	if (rc < 0) {
+		pr_err("Error in configuring ESR filter rc:%d\n", rc);
+		alarm_start_relative(&chip->esr_filter_alarm,
+			ms_to_ktime(FG_ESR_FILTER_RESTART_MS));
+	}
+
+out:
+	chip->delta_temp_irq_count = 0;
+	pm_relax(chip->dev);
+}
+
+static enum alarmtimer_restart fg_esr_filter_alarm_cb(struct alarm *alarm,
+							ktime_t now)
+{
+	struct fg_chip *chip = container_of(alarm, struct fg_chip,
+					esr_filter_alarm);
+
+	fg_dbg(chip, FG_STATUS, "ESR filter alarm triggered %lld\n",
+		ktime_to_ms(now));
+	/*
+	 * We cannot vote for awake votable here as that takes a mutex lock
+	 * and this is executed in an atomic context.
+	 */
+	pm_stay_awake(chip->dev);
+	schedule_work(&chip->esr_filter_work);
+
+	return ALARMTIMER_NORESTART;
+}
+
 static int fg_esr_fcc_config(struct fg_chip *chip)
 {
 	union power_supply_propval prop = {0, };
@@ -3891,6 +4023,14 @@
 	struct power_supply *psy = data;
 	struct fg_chip *chip = container_of(nb, struct fg_chip, nb);
 
+	spin_lock(&chip->suspend_lock);
+	if (chip->suspended) {
+		/* Return if we are still suspended */
+		spin_unlock(&chip->suspend_lock);
+		return NOTIFY_OK;
+	}
+	spin_unlock(&chip->suspend_lock);
+
 	if (event != PSY_EVENT_PROP_CHANGED)
 		return NOTIFY_OK;
 
@@ -4385,14 +4525,14 @@
 	union power_supply_propval prop = {0, };
 	int rc, batt_temp;
 
-	fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
 	rc = fg_get_battery_temp(chip, &batt_temp);
 	if (rc < 0) {
 		pr_err("Error in getting batt_temp\n");
 		return IRQ_HANDLED;
 	}
+	fg_dbg(chip, FG_IRQ, "irq %d triggered bat_temp: %d\n", irq, batt_temp);
 
-	rc = fg_esr_filter_config(chip, batt_temp);
+	rc = fg_esr_filter_config(chip, batt_temp, false);
 	if (rc < 0)
 		pr_err("Error in configuring ESR filter rc:%d\n", rc);
 
@@ -4793,8 +4933,11 @@
 #define DEFAULT_ESR_FLT_TEMP_DECIDEGC	100
 #define DEFAULT_ESR_TIGHT_FLT_UPCT	3907
 #define DEFAULT_ESR_BROAD_FLT_UPCT	99610
-#define DEFAULT_ESR_TIGHT_LT_FLT_UPCT	48829
-#define DEFAULT_ESR_BROAD_LT_FLT_UPCT	148438
+#define DEFAULT_ESR_TIGHT_LT_FLT_UPCT	30000
+#define DEFAULT_ESR_BROAD_LT_FLT_UPCT	30000
+#define DEFAULT_ESR_FLT_RT_DECIDEGC	60
+#define DEFAULT_ESR_TIGHT_RT_FLT_UPCT	5860
+#define DEFAULT_ESR_BROAD_RT_FLT_UPCT	156250
 #define DEFAULT_ESR_CLAMP_MOHMS		20
 #define DEFAULT_ESR_PULSE_THRESH_MA	110
 #define DEFAULT_ESR_MEAS_CURR_MA	120
@@ -5128,6 +5271,27 @@
 	else
 		chip->dt.esr_broad_lt_flt_upct = temp;
 
+	rc = of_property_read_u32(node, "qcom,fg-esr-rt-filter-switch-temp",
+			&temp);
+	if (rc < 0)
+		chip->dt.esr_flt_rt_switch_temp = DEFAULT_ESR_FLT_RT_DECIDEGC;
+	else
+		chip->dt.esr_flt_rt_switch_temp = temp;
+
+	rc = of_property_read_u32(node, "qcom,fg-esr-tight-rt-filter-micro-pct",
+			&temp);
+	if (rc < 0)
+		chip->dt.esr_tight_rt_flt_upct = DEFAULT_ESR_TIGHT_RT_FLT_UPCT;
+	else
+		chip->dt.esr_tight_rt_flt_upct = temp;
+
+	rc = of_property_read_u32(node, "qcom,fg-esr-broad-rt-filter-micro-pct",
+			&temp);
+	if (rc < 0)
+		chip->dt.esr_broad_rt_flt_upct = DEFAULT_ESR_BROAD_RT_FLT_UPCT;
+	else
+		chip->dt.esr_broad_rt_flt_upct = temp;
+
 	rc = fg_parse_slope_limit_coefficients(chip);
 	if (rc < 0)
 		pr_err("Error in parsing slope limit coeffs, rc=%d\n", rc);
@@ -5173,6 +5337,7 @@
 			devm_free_irq(chip->dev, fg_irqs[i].irq, chip);
 	}
 
+	alarm_try_to_cancel(&chip->esr_filter_alarm);
 	power_supply_unreg_notifier(&chip->nb);
 	debugfs_remove_recursive(chip->dfs_root);
 	if (chip->awake_votable)
@@ -5285,6 +5450,7 @@
 	mutex_init(&chip->ttf.lock);
 	mutex_init(&chip->charge_full_lock);
 	mutex_init(&chip->qnovo_esr_ctrl_lock);
+	spin_lock_init(&chip->suspend_lock);
 	init_completion(&chip->soc_update);
 	init_completion(&chip->soc_ready);
 	INIT_DELAYED_WORK(&chip->profile_load_work, profile_load_work);
@@ -5292,6 +5458,9 @@
 	INIT_WORK(&chip->status_change_work, status_change_work);
 	INIT_DELAYED_WORK(&chip->ttf_work, ttf_work);
 	INIT_DELAYED_WORK(&chip->sram_dump_work, sram_dump_work);
+	INIT_WORK(&chip->esr_filter_work, esr_filter_work);
+	alarm_init(&chip->esr_filter_alarm, ALARM_BOOTTIME,
+			fg_esr_filter_alarm_cb);
 
 	rc = fg_memif_init(chip);
 	if (rc < 0) {
@@ -5363,7 +5532,7 @@
 	if (!rc) {
 		pr_info("battery SOC:%d voltage: %duV temp: %d\n",
 				msoc, volt_uv, batt_temp);
-		rc = fg_esr_filter_config(chip, batt_temp);
+		rc = fg_esr_filter_config(chip, batt_temp, false);
 		if (rc < 0)
 			pr_err("Error in configuring ESR filter rc:%d\n", rc);
 	}
@@ -5383,6 +5552,10 @@
 	struct fg_chip *chip = dev_get_drvdata(dev);
 	int rc;
 
+	spin_lock(&chip->suspend_lock);
+	chip->suspended = true;
+	spin_unlock(&chip->suspend_lock);
+
 	rc = fg_esr_timer_config(chip, true);
 	if (rc < 0)
 		pr_err("Error in configuring ESR timer, rc=%d\n", rc);
@@ -5406,6 +5579,16 @@
 	if (fg_sram_dump)
 		schedule_delayed_work(&chip->sram_dump_work,
 				msecs_to_jiffies(fg_sram_dump_period_ms));
+
+	if (!work_pending(&chip->status_change_work)) {
+		pm_stay_awake(chip->dev);
+		schedule_work(&chip->status_change_work);
+	}
+
+	spin_lock(&chip->suspend_lock);
+	chip->suspended = false;
+	spin_unlock(&chip->suspend_lock);
+
 	return 0;
 }
 
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index f9a29aa..ccc0d5d 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -716,6 +716,7 @@
 	POWER_SUPPLY_PROP_INPUT_VOLTAGE_SETTLED,
 	POWER_SUPPLY_PROP_FCC_DELTA,
 	POWER_SUPPLY_PROP_CURRENT_MAX,
+	POWER_SUPPLY_PROP_TOGGLE_STAT,
 	/*
 	 * TODO move the TEMP and TEMP_MAX properties here,
 	 * and update the thermal balancer to look here
@@ -753,6 +754,9 @@
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
 		rc = smblib_get_icl_current(chg, &val->intval);
 		break;
+	case POWER_SUPPLY_PROP_TOGGLE_STAT:
+		val->intval = 0;
+		break;
 	default:
 		pr_debug("get prop %d is not supported in usb-main\n", psp);
 		rc = -EINVAL;
@@ -783,6 +787,9 @@
 	case POWER_SUPPLY_PROP_CURRENT_MAX:
 		rc = smblib_set_icl_current(chg, val->intval);
 		break;
+	case POWER_SUPPLY_PROP_TOGGLE_STAT:
+		rc = smblib_toggle_stat(chg, val->intval);
+		break;
 	default:
 		pr_err("set prop %d is not supported\n", psp);
 		rc = -EINVAL;
@@ -792,6 +799,23 @@
 	return rc;
 }
 
+static int smb2_usb_main_prop_is_writeable(struct power_supply *psy,
+				enum power_supply_property psp)
+{
+	int rc;
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_TOGGLE_STAT:
+		rc = 1;
+		break;
+	default:
+		rc = 0;
+		break;
+	}
+
+	return rc;
+}
+
 static const struct power_supply_desc usb_main_psy_desc = {
 	.name		= "main",
 	.type		= POWER_SUPPLY_TYPE_MAIN,
@@ -799,6 +823,7 @@
 	.num_properties	= ARRAY_SIZE(smb2_usb_main_props),
 	.get_property	= smb2_usb_main_get_prop,
 	.set_property	= smb2_usb_main_set_prop,
+	.property_is_writeable = smb2_usb_main_prop_is_writeable,
 };
 
 static int smb2_init_usb_main_psy(struct smb2 *chip)
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index b91850d..20dd78e 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -1084,6 +1084,7 @@
 {
 	int rc = 0;
 	struct smb_charger *chg = power_supply_get_drvdata(psy);
+	bool enable;
 
 	switch (prop) {
 	case POWER_SUPPLY_PROP_STATUS:
@@ -1106,11 +1107,16 @@
 		vote(chg->fv_votable, BATT_PROFILE_VOTER, true, val->intval);
 		break;
 	case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
-		chg->step_chg_enabled = !!val->intval;
+		enable = !!val->intval || chg->sw_jeita_enabled;
+		rc = smblib_configure_wdog(chg, enable);
+		if (rc == 0)
+			chg->step_chg_enabled = !!val->intval;
 		break;
 	case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
 		if (chg->sw_jeita_enabled != (!!val->intval)) {
 			rc = smblib_disable_hw_jeita(chg, !!val->intval);
+			enable = !!val->intval || chg->step_chg_enabled;
+			rc |= smblib_configure_wdog(chg, enable);
 			if (rc == 0)
 				chg->sw_jeita_enabled = !!val->intval;
 		}
@@ -1481,6 +1487,10 @@
 		return rc;
 	}
 
+	/*
+	 * configure the one time watchdong periodic interval and
+	 * disable "watchdog bite disable charging".
+	 */
 	val = (ilog2(chip->dt.wd_bark_time / 16) << BARK_WDOG_TIMEOUT_SHIFT)
 			& BARK_WDOG_TIMEOUT_MASK;
 	val |= BITE_WDOG_TIMEOUT_8S;
@@ -1493,18 +1503,6 @@
 		return rc;
 	}
 
-	/* enable WD BARK and enable it on plugin */
-	rc = smblib_masked_write(chg, WD_CFG_REG,
-			WATCHDOG_TRIGGER_AFP_EN_BIT |
-			WDOG_TIMER_EN_ON_PLUGIN_BIT |
-			BARK_WDOG_INT_EN_BIT,
-			WDOG_TIMER_EN_ON_PLUGIN_BIT |
-			BARK_WDOG_INT_EN_BIT);
-	if (rc < 0) {
-		pr_err("Couldn't configue WD config rc=%d\n", rc);
-		return rc;
-	}
-
 	/* configure float charger options */
 	switch (chip->dt.float_option) {
 	case FLOAT_DCP:
@@ -1643,6 +1641,14 @@
 		}
 	}
 
+	rc = smblib_configure_wdog(chg,
+			chg->step_chg_enabled || chg->sw_jeita_enabled);
+	if (rc < 0) {
+		dev_err(chg->dev, "Couldn't configure watchdog rc=%d\n",
+				rc);
+		return rc;
+	}
+
 	return rc;
 }
 
@@ -1892,6 +1898,7 @@
 	[WDOG_BARK_IRQ] = {
 		.name		= "wdog-bark",
 		.handler	= wdog_bark_irq_handler,
+		.wake		= true,
 	},
 	[AICL_FAIL_IRQ] = {
 		.name		= "aicl-fail",
diff --git a/drivers/power/supply/qcom/qpnp-smbcharger.c b/drivers/power/supply/qcom/qpnp-smbcharger.c
index f9c755c..403b670 100644
--- a/drivers/power/supply/qcom/qpnp-smbcharger.c
+++ b/drivers/power/supply/qcom/qpnp-smbcharger.c
@@ -144,6 +144,7 @@
 	bool				vbat_above_headroom;
 	bool				force_aicl_rerun;
 	bool				hvdcp3_supported;
+	bool				allow_hvdcp3_detection;
 	bool				restricted_charging;
 	bool				skip_usb_suspend_for_fake_battery;
 	bool				hvdcp_not_supported;
@@ -5021,6 +5022,30 @@
 	return 0;
 }
 
+static void smbchg_handle_hvdcp3_disable(struct smbchg_chip *chip)
+{
+	enum power_supply_type usb_supply_type;
+	char *usb_type_name = "NULL";
+
+	if (chip->allow_hvdcp3_detection)
+		return;
+
+	chip->pulse_cnt = 0;
+
+	if (is_hvdcp_present(chip)) {
+		smbchg_change_usb_supply_type(chip,
+			POWER_SUPPLY_TYPE_USB_HVDCP);
+	} else if (is_usb_present(chip)) {
+		read_usb_type(chip, &usb_type_name, &usb_supply_type);
+		smbchg_change_usb_supply_type(chip, usb_supply_type);
+		if (usb_supply_type == POWER_SUPPLY_TYPE_USB_DCP)
+			schedule_delayed_work(&chip->hvdcp_det_work,
+				msecs_to_jiffies(HVDCP_NOTIFY_MS));
+	} else {
+		smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN);
+	}
+}
+
 static int smbchg_prepare_for_pulsing(struct smbchg_chip *chip)
 {
 	int rc = 0;
@@ -5241,6 +5266,9 @@
 		pr_smb(PR_MISC, "HVDCP removed\n");
 		update_usb_status(chip, 0, 0);
 	}
+
+	smbchg_handle_hvdcp3_disable(chip);
+
 	return rc;
 }
 
@@ -5425,6 +5453,8 @@
 	if (rc < 0)
 		pr_err("Couldn't retract HVDCP ICL vote rc=%d\n", rc);
 
+	smbchg_handle_hvdcp3_disable(chip);
+
 	return rc;
 }
 
@@ -5713,6 +5743,7 @@
 	POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED,
 	POWER_SUPPLY_PROP_RERUN_AICL,
 	POWER_SUPPLY_PROP_RESTRICTED_CHARGING,
+	POWER_SUPPLY_PROP_ALLOW_HVDCP3,
 };
 
 static int smbchg_battery_set_property(struct power_supply *psy,
@@ -5790,6 +5821,12 @@
 		if (chip->typec_psy)
 			update_typec_otg_status(chip, val->intval, false);
 		break;
+	case POWER_SUPPLY_PROP_ALLOW_HVDCP3:
+		if (chip->allow_hvdcp3_detection != val->intval) {
+			chip->allow_hvdcp3_detection = !!val->intval;
+			power_supply_changed(chip->batt_psy);
+		}
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -5813,6 +5850,7 @@
 	case POWER_SUPPLY_PROP_DP_DM:
 	case POWER_SUPPLY_PROP_RERUN_AICL:
 	case POWER_SUPPLY_PROP_RESTRICTED_CHARGING:
+	case POWER_SUPPLY_PROP_ALLOW_HVDCP3:
 		rc = 1;
 		break;
 	default:
@@ -5913,6 +5951,9 @@
 	case POWER_SUPPLY_PROP_INPUT_CURRENT_NOW:
 		val->intval = smbchg_get_iusb(chip);
 		break;
+	case POWER_SUPPLY_PROP_ALLOW_HVDCP3:
+		val->intval = chip->allow_hvdcp3_detection;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -8247,6 +8288,7 @@
 			goto out;
 		}
 	}
+	chip->allow_hvdcp3_detection = true;
 
 	if (chip->cfg_chg_led_support &&
 			chip->schg_version == QPNP_SCHG_LITE) {
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index fe7ae5f..7e1aa5d 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -1010,6 +1010,48 @@
 	return 0;
 }
 
+int smblib_toggle_stat(struct smb_charger *chg, int reset)
+{
+	int rc = 0;
+
+	if (reset) {
+		rc = smblib_masked_write(chg, STAT_CFG_REG,
+			STAT_SW_OVERRIDE_CFG_BIT | STAT_SW_OVERRIDE_VALUE_BIT,
+			STAT_SW_OVERRIDE_CFG_BIT | 0);
+		if (rc < 0) {
+			smblib_err(chg,
+				"Couldn't pull STAT pin low rc=%d\n", rc);
+			return rc;
+		}
+
+		/*
+		 * A minimum of 20us delay is expected before switching on STAT
+		 * pin
+		 */
+		usleep_range(20, 30);
+
+		rc = smblib_masked_write(chg, STAT_CFG_REG,
+			STAT_SW_OVERRIDE_CFG_BIT | STAT_SW_OVERRIDE_VALUE_BIT,
+			STAT_SW_OVERRIDE_CFG_BIT | STAT_SW_OVERRIDE_VALUE_BIT);
+		if (rc < 0) {
+			smblib_err(chg,
+				"Couldn't pull STAT pin high rc=%d\n", rc);
+			return rc;
+		}
+
+		rc = smblib_masked_write(chg, STAT_CFG_REG,
+			STAT_SW_OVERRIDE_CFG_BIT | STAT_SW_OVERRIDE_VALUE_BIT,
+			0);
+		if (rc < 0) {
+			smblib_err(chg,
+				"Couldn't set hardware control rc=%d\n", rc);
+			return rc;
+		}
+	}
+
+	return rc;
+}
+
 static int smblib_micro_usb_disable_power_role_switch(struct smb_charger *chg,
 				bool disable)
 {
@@ -3482,6 +3524,11 @@
 						chg->chg_freq.freq_removal);
 
 	if (vbus_rising) {
+		if (smblib_get_prop_dfp_mode(chg) != POWER_SUPPLY_TYPEC_NONE) {
+			chg->fake_usb_insertion = true;
+			return;
+		}
+
 		rc = smblib_request_dpdm(chg, true);
 		if (rc < 0)
 			smblib_err(chg, "Couldn't to enable DPDM rc=%d\n", rc);
@@ -3495,6 +3542,11 @@
 				!chg->pd_active)
 			pr_err("APSD disabled on vbus rising without PD\n");
 	} else {
+		if (chg->fake_usb_insertion) {
+			chg->fake_usb_insertion = false;
+			return;
+		}
+
 		if (chg->wa_flags & BOOST_BACK_WA) {
 			data = chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data;
 			if (data) {
@@ -3857,6 +3909,9 @@
 	int rc = 0;
 	u8 stat;
 
+	if (chg->fake_usb_insertion)
+		return IRQ_HANDLED;
+
 	rc = smblib_read(chg, APSD_STATUS_REG, &stat);
 	if (rc < 0) {
 		smblib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc);
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 32f2b4d..b9d1992 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -358,6 +358,7 @@
 	bool			try_sink_active;
 	int			boost_current_ua;
 	int			temp_speed_reading_count;
+	bool			fake_usb_insertion;
 
 	/* extcon for VBUS / ID notification to USB for uUSB */
 	struct extcon_dev	*extcon;
@@ -541,6 +542,7 @@
 				const union power_supply_propval *val);
 int smblib_stat_sw_override_cfg(struct smb_charger *chg, bool override);
 void smblib_usb_typec_change(struct smb_charger *chg);
+int smblib_toggle_stat(struct smb_charger *chg, int reset);
 
 int smblib_init(struct smb_charger *chg);
 int smblib_deinit(struct smb_charger *chg);
diff --git a/drivers/power/supply/qcom/smb1390-charger.c b/drivers/power/supply/qcom/smb1390-charger.c
new file mode 100644
index 0000000..636265b
--- /dev/null
+++ b/drivers/power/supply/qcom/smb1390-charger.c
@@ -0,0 +1,788 @@
+/* Copyright (c) 2017-18 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "SMB1390: %s: " fmt, __func__
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/pmic-voter.h>
+#include <linux/power_supply.h>
+#include <linux/qpnp/qpnp-adc.h>
+#include <linux/regmap.h>
+
+#define CORE_STATUS1_REG		0x1006
+#define WIN_OV_BIT			BIT(0)
+#define WIN_UV_BIT			BIT(1)
+#define EN_PIN_OUT_BIT			BIT(2)
+#define LCM_AUTO_BIT			BIT(3)
+#define LCM_PIN_BIT			BIT(4)
+#define ILIM_BIT			BIT(5)
+#define TEMP_ALARM_BIT			BIT(6)
+#define VPH_OV_SOFT_BIT			BIT(7)
+
+#define CORE_STATUS2_REG		0x1007
+#define SWITCHER_HOLD_OFF_BIT		BIT(0)
+#define VPH_OV_HARD_BIT			BIT(1)
+#define TSD_BIT				BIT(2)
+#define IREV_BIT			BIT(3)
+#define IOC_BIT				BIT(4)
+#define VIN_UV_BIT			BIT(5)
+#define VIN_OV_BIT			BIT(6)
+#define EN_PIN_OUT2_BIT			BIT(7)
+
+#define CORE_STATUS3_REG		0x1008
+#define EN_SL_BIT			BIT(0)
+#define IIN_REF_SS_DONE_BIT		BIT(1)
+#define FLYCAP_SS_DONE_BIT		BIT(2)
+#define SL_DETECTED_BIT			BIT(3)
+
+#define CORE_INT_RT_STS_REG		0x1010
+#define SWITCHER_OFF_WINDOW_STS_BIT	BIT(0)
+#define SWITCHER_OFF_FAULT_STS_BIT	BIT(1)
+#define TSD_STS_BIT			BIT(2)
+#define IREV_STS_BIT			BIT(3)
+#define VPH_OV_HARD_STS_BIT		BIT(4)
+#define VPH_OV_SOFT_STS_BIT		BIT(5)
+#define ILIM_STS_BIT			BIT(6)
+#define TEMP_ALARM_STS_BIT		BIT(7)
+
+#define CORE_CONTROL1_REG		0x1020
+#define CMD_EN_SWITCHER_BIT		BIT(0)
+#define CMD_EN_SL_BIT			BIT(1)
+
+#define CORE_FTRIM_ILIM_REG		0x1030
+#define CFG_ILIM_MASK			GENMASK(4, 0)
+
+#define CP_VOTER	"CP_VOTER"
+#define USER_VOTER	"USER_VOTER"
+#define ILIM_VOTER	"ILIM_VOTER"
+#define FCC_VOTER	"FCC_VOTER"
+#define ICL_VOTER	"ICL_VOTER"
+#define USB_VOTER	"USB_VOTER"
+
+enum {
+	SWITCHER_OFF_WINDOW_IRQ = 0,
+	SWITCHER_OFF_FAULT_IRQ,
+	TSD_IRQ,
+	IREV_IRQ,
+	VPH_OV_HARD_IRQ,
+	VPH_OV_SOFT_IRQ,
+	ILIM_IRQ,
+	TEMP_ALARM_IRQ,
+	NUM_IRQS,
+};
+
+struct smb1390 {
+	struct device		*dev;
+	struct regmap		*regmap;
+	struct notifier_block	nb;
+	struct class		cp_class;
+
+	/* work structs */
+	struct work_struct	status_change_work;
+	struct work_struct	taper_work;
+
+	/* mutexes */
+	spinlock_t		status_change_lock;
+
+	/* votables */
+	struct votable		*disable_votable;
+	struct votable		*ilim_votable;
+	struct votable		*pl_disable_votable;
+	struct votable		*fcc_votable;
+	struct votable		*hvdcp_hw_inov_dis_votable;
+
+	/* power supplies */
+	struct power_supply	*usb_psy;
+	struct power_supply	*batt_psy;
+
+	struct qpnp_vadc_chip	*vadc_dev;
+	int			irqs[NUM_IRQS];
+	bool			status_change_running;
+	bool			taper_work_running;
+	int			adc_channel;
+};
+
+struct smb_irq {
+	const char		*name;
+	const irq_handler_t	handler;
+	const bool		wake;
+};
+
+static const struct smb_irq smb_irqs[];
+
+static int smb1390_read(struct smb1390 *chip, int reg, int *val)
+{
+	int rc;
+
+	rc = regmap_read(chip->regmap, reg, val);
+	if (rc < 0)
+		pr_err("Couldn't read 0x%04x\n", reg);
+
+	return rc;
+}
+
+static int smb1390_masked_write(struct smb1390 *chip, int reg, int mask,
+				int val)
+{
+	int rc;
+
+	pr_debug("Writing 0x%02x to 0x%04x with mask 0x%02x\n", val, reg, mask);
+	rc = regmap_update_bits(chip->regmap, reg, mask, val);
+	if (rc < 0)
+		pr_err("Couldn't write 0x%02x to 0x%04x with mask 0x%02x\n",
+		       val, reg, mask);
+
+	return rc;
+}
+
+static bool is_psy_voter_available(struct smb1390 *chip)
+{
+	if (!chip->batt_psy) {
+		chip->batt_psy = power_supply_get_by_name("battery");
+		if (!chip->batt_psy) {
+			pr_debug("Couldn't find battery psy\n");
+			return false;
+		}
+	}
+
+	if (!chip->usb_psy) {
+		chip->usb_psy = power_supply_get_by_name("usb");
+		if (!chip->usb_psy) {
+			pr_debug("Couldn't find usb psy\n");
+			return false;
+		}
+	}
+
+	if (!chip->fcc_votable) {
+		chip->fcc_votable = find_votable("FCC");
+		if (!chip->fcc_votable) {
+			pr_debug("Couldn't find FCC votable\n");
+			return false;
+		}
+	}
+
+	if (!chip->pl_disable_votable) {
+	chip->pl_disable_votable = find_votable("PL_DISABLE");
+		if (!chip->pl_disable_votable) {
+			pr_debug("Couldn't find PL_DISABLE votable\n");
+			return false;
+		}
+	}
+
+	if (!chip->hvdcp_hw_inov_dis_votable) {
+	chip->hvdcp_hw_inov_dis_votable = find_votable("HVDCP_HW_INOV_DIS");
+		if (!chip->hvdcp_hw_inov_dis_votable) {
+			pr_debug("Couldn't find HVDCP_HW_INOV_DIS votable\n");
+			return false;
+		}
+	}
+
+	return true;
+}
+
+static irqreturn_t default_irq_handler(int irq, void *data)
+{
+	struct smb1390 *chip = data;
+	int i;
+
+	for (i = 0; i < NUM_IRQS; ++i) {
+		if (irq == chip->irqs[i])
+			pr_debug("%s IRQ triggered\n", smb_irqs[i].name);
+	}
+
+	kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t irev_irq_handler(int irq, void *data)
+{
+	struct smb1390 *chip = data;
+	int rc;
+
+	pr_debug("IREV IRQ triggered\n");
+
+	rc = smb1390_masked_write(chip, CORE_CONTROL1_REG,
+			CMD_EN_SWITCHER_BIT, 0);
+	if (rc < 0) {
+		pr_err("Couldn't disable switcher by command mode, rc=%d\n",
+			rc);
+		goto out;
+	}
+
+	rc = smb1390_masked_write(chip, CORE_CONTROL1_REG,
+			CMD_EN_SWITCHER_BIT, CMD_EN_SWITCHER_BIT);
+	if (rc < 0) {
+		pr_err("Couldn't enable switcher by command mode, rc=%d\n",
+			rc);
+		goto out;
+	}
+
+out:
+	kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE);
+	return IRQ_HANDLED;
+}
+
+static const struct smb_irq smb_irqs[] = {
+	[SWITCHER_OFF_WINDOW_IRQ] = {
+		.name		= "switcher-off-window",
+		.handler	= default_irq_handler,
+		.wake		= true,
+	},
+	[SWITCHER_OFF_FAULT_IRQ] = {
+		.name		= "switcher-off-fault",
+		.handler	= default_irq_handler,
+		.wake		= true,
+	},
+	[TSD_IRQ] = {
+		.name		= "tsd-fault",
+		.handler	= default_irq_handler,
+		.wake		= true,
+	},
+	[IREV_IRQ] = {
+		.name		= "irev-fault",
+		.handler	= irev_irq_handler,
+		.wake		= true,
+	},
+	[VPH_OV_HARD_IRQ] = {
+		.name		= "vph-ov-hard",
+		.handler	= default_irq_handler,
+		.wake		= true,
+	},
+	[VPH_OV_SOFT_IRQ] = {
+		.name		= "vph-ov-soft",
+		.handler	= default_irq_handler,
+		.wake		= true,
+	},
+	[ILIM_IRQ] = {
+		.name		= "ilim",
+		.handler	= default_irq_handler,
+		.wake		= true,
+	},
+	[TEMP_ALARM_IRQ] = {
+		.name		= "temp-alarm",
+		.handler	= default_irq_handler,
+		.wake		= true,
+	},
+};
+
+/* SYSFS functions for reporting smb1390 charge pump state */
+static ssize_t stat1_show(struct class *c, struct class_attribute *attr,
+			 char *buf)
+{
+	struct smb1390 *chip = container_of(c, struct smb1390, cp_class);
+	int rc, val;
+
+	rc = smb1390_read(chip, CORE_STATUS1_REG, &val);
+	if (rc < 0)
+		return -EINVAL;
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", val);
+}
+
+static ssize_t stat2_show(struct class *c, struct class_attribute *attr,
+			 char *buf)
+{
+	struct smb1390 *chip = container_of(c, struct smb1390, cp_class);
+	int rc, val;
+
+	rc = smb1390_read(chip, CORE_STATUS2_REG, &val);
+	if (rc < 0)
+		return -EINVAL;
+
+	return snprintf(buf, PAGE_SIZE, "%x\n", val);
+}
+
+static ssize_t enable_show(struct class *c, struct class_attribute *attr,
+			   char *buf)
+{
+	struct smb1390 *chip = container_of(c, struct smb1390, cp_class);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			!get_effective_result(chip->disable_votable));
+}
+
+static ssize_t enable_store(struct class *c, struct class_attribute *attr,
+			    const char *buf, size_t count)
+{
+	struct smb1390 *chip = container_of(c, struct smb1390, cp_class);
+	unsigned long val;
+
+	if (kstrtoul(buf, 0, &val))
+		return -EINVAL;
+
+	vote(chip->disable_votable, USER_VOTER, !val, 0);
+	return count;
+}
+
+static ssize_t die_temp_show(struct class *c, struct class_attribute *attr,
+			     char *buf)
+{
+	struct smb1390 *chip = container_of(c, struct smb1390, cp_class);
+	struct qpnp_vadc_result vadc_result;
+	int rc;
+
+	rc = qpnp_vadc_read(chip->vadc_dev, chip->adc_channel, &vadc_result);
+	if (rc < 0) {
+		pr_err("Couldn't read die temp rc=%d\n", rc);
+		return -EINVAL;
+	}
+
+	return snprintf(buf, PAGE_SIZE, "%lld\n", vadc_result.physical);
+}
+
+static struct class_attribute cp_class_attrs[] = {
+	__ATTR_RO(stat1),
+	__ATTR_RO(stat2),
+	__ATTR_RW(enable),
+	__ATTR_RO(die_temp),
+	__ATTR_NULL,
+};
+
+/* voter callbacks */
+static int smb1390_disable_vote_cb(struct votable *votable, void *data,
+				  int disable, const char *client)
+{
+	struct smb1390 *chip = data;
+	int rc = 0;
+
+	if (!is_psy_voter_available(chip))
+		return -EAGAIN;
+
+	if (disable) {
+		rc = smb1390_masked_write(chip, CORE_CONTROL1_REG,
+				   CMD_EN_SWITCHER_BIT, 0);
+		if (rc < 0)
+			return rc;
+
+		vote(chip->hvdcp_hw_inov_dis_votable, CP_VOTER, false, 0);
+		vote(chip->pl_disable_votable, CP_VOTER, false, 0);
+	} else {
+		vote(chip->hvdcp_hw_inov_dis_votable, CP_VOTER, true, 0);
+		vote(chip->pl_disable_votable, CP_VOTER, true, 0);
+		rc = smb1390_masked_write(chip, CORE_CONTROL1_REG,
+				   CMD_EN_SWITCHER_BIT, CMD_EN_SWITCHER_BIT);
+		if (rc < 0)
+			return rc;
+	}
+	pr_debug("%s charge pump\n", disable ? "Disabled" : "Enabled");
+
+	/* charging may have been disabled by ILIM; send uevent */
+	kobject_uevent(&chip->dev->kobj, KOBJ_CHANGE);
+	return rc;
+}
+
+static int smb1390_ilim_vote_cb(struct votable *votable, void *data,
+			      int ilim_uA, const char *client)
+{
+	struct smb1390 *chip = data;
+	int rc = 0;
+
+	if (!is_psy_voter_available(chip))
+		return -EAGAIN;
+
+	/* ILIM should always have at least one active vote */
+	if (!client) {
+		pr_err("Client missing\n");
+		return -EINVAL;
+	}
+
+	/* ILIM less than 1A is not accurate; disable charging */
+	if (ilim_uA < 1000000) {
+		pr_debug("ILIM %duA is too low to allow charging\n", ilim_uA);
+		vote(chip->disable_votable, ILIM_VOTER, true, 0);
+	} else {
+		pr_debug("setting ILIM to %duA\n", ilim_uA);
+		rc = smb1390_masked_write(chip, CORE_FTRIM_ILIM_REG,
+				CFG_ILIM_MASK,
+				DIV_ROUND_CLOSEST(ilim_uA - 500000, 100000));
+		if (rc < 0)
+			pr_err("Failed to write ILIM Register, rc=%d\n", rc);
+		else
+			vote(chip->disable_votable, ILIM_VOTER, false, 0);
+	}
+
+	return rc;
+}
+
+static int smb1390_notifier_cb(struct notifier_block *nb,
+			       unsigned long event, void *data)
+{
+	struct smb1390 *chip = container_of(nb, struct smb1390, nb);
+	struct power_supply *psy = data;
+	unsigned long flags;
+
+	if (event != PSY_EVENT_PROP_CHANGED)
+		return NOTIFY_OK;
+
+	if (strcmp(psy->desc->name, "battery") == 0
+				|| strcmp(psy->desc->name, "usb") == 0
+				|| strcmp(psy->desc->name, "main") == 0) {
+		spin_lock_irqsave(&chip->status_change_lock, flags);
+		if (!chip->status_change_running) {
+			chip->status_change_running = true;
+			pm_stay_awake(chip->dev);
+			schedule_work(&chip->status_change_work);
+		}
+		spin_unlock_irqrestore(&chip->status_change_lock, flags);
+	}
+
+	return NOTIFY_OK;
+}
+
+static void smb1390_status_change_work(struct work_struct *work)
+{
+	struct smb1390 *chip = container_of(work, struct smb1390,
+					    status_change_work);
+	union power_supply_propval pval = {0, };
+	int rc;
+
+	if (!is_psy_voter_available(chip))
+		goto out;
+
+	/*
+	 * Check for USB present status. The support for SMB1390 is
+	 * limited to Type-C devices only, hence the check is limited
+	 * to Type-C detection.
+	 */
+	rc = power_supply_get_property(chip->usb_psy,
+			POWER_SUPPLY_PROP_TYPEC_MODE, &pval);
+	if (rc < 0) {
+		pr_err("Couldn't get usb present rc=%d\n", rc);
+		goto out;
+	}
+
+	if (pval.intval != POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
+			&& pval.intval != POWER_SUPPLY_TYPEC_SOURCE_MEDIUM
+			&& pval.intval != POWER_SUPPLY_TYPEC_SOURCE_HIGH) {
+		vote(chip->disable_votable, USB_VOTER, true, 0);
+		vote(chip->fcc_votable, CP_VOTER, false, 0);
+	} else {
+		vote(chip->disable_votable, USB_VOTER, false, 0);
+
+		/*
+		 * ILIM is set based on the primary chargers AICL result. This
+		 * ensures VBUS does not collapse due to the current drawn via
+		 * MID.
+		 */
+		rc = power_supply_get_property(chip->usb_psy,
+				POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED, &pval);
+		if (rc < 0)
+			pr_err("Couldn't get usb icl rc=%d\n", rc);
+		else
+			vote(chip->ilim_votable, ICL_VOTER, true, pval.intval);
+
+		/* input current is always half the charge current */
+		vote(chip->ilim_votable, FCC_VOTER, true,
+				get_effective_result(chip->fcc_votable) / 2);
+
+		/*
+		 * all votes that would result in disabling the charge pump have
+		 * been cast; ensure the charhe pump is still enabled before
+		 * continuing.
+		 */
+		if (get_effective_result(chip->disable_votable))
+			goto out;
+
+		rc = power_supply_get_property(chip->batt_psy,
+				POWER_SUPPLY_PROP_CHARGE_TYPE, &pval);
+		if (rc < 0) {
+			pr_err("Couldn't get charge type rc=%d\n", rc);
+		} else if (pval.intval ==
+				POWER_SUPPLY_CHARGE_TYPE_TAPER) {
+			/*
+			 * mutual exclusion is already guaranteed by
+			 * chip->status_change_running
+			 */
+			if (!chip->taper_work_running) {
+				chip->taper_work_running = true;
+				queue_work(system_long_wq,
+					   &chip->taper_work);
+			}
+		}
+	}
+
+out:
+	pm_relax(chip->dev);
+	chip->status_change_running = false;
+}
+
+static void smb1390_taper_work(struct work_struct *work)
+{
+	struct smb1390 *chip = container_of(work, struct smb1390, taper_work);
+	union power_supply_propval pval = {0, };
+	int rc, fcc_uA;
+
+	if (!is_psy_voter_available(chip))
+		goto out;
+
+	do {
+		fcc_uA = get_effective_result(chip->fcc_votable) - 100000;
+		pr_debug("taper work reducing FCC to %duA\n", fcc_uA);
+		vote(chip->fcc_votable, CP_VOTER, true, fcc_uA);
+
+		rc = power_supply_get_property(chip->batt_psy,
+					POWER_SUPPLY_PROP_CHARGE_TYPE, &pval);
+		if (rc < 0) {
+			pr_err("Couldn't get charge type rc=%d\n", rc);
+			goto out;
+		}
+
+		msleep(500);
+	} while (fcc_uA >= 2000000
+		 && pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER);
+
+out:
+	pr_debug("taper work exit\n");
+	chip->taper_work_running = false;
+}
+
+static int smb1390_parse_dt(struct smb1390 *chip)
+{
+	int rc;
+
+	rc = of_property_read_u32(chip->dev->of_node, "qcom,channel-num",
+			&chip->adc_channel);
+	if (!rc) {
+		if (chip->adc_channel < 0 || chip->adc_channel >= ADC_MAX_NUM) {
+			pr_err("Invalid qcom,channel-num=%d specified\n",
+				chip->adc_channel);
+			return -EINVAL;
+		}
+	}
+
+	return rc;
+}
+
+static int smb1390_create_votables(struct smb1390 *chip)
+{
+	chip->disable_votable = create_votable("CP_DISABLE",
+			VOTE_SET_ANY, smb1390_disable_vote_cb, chip);
+	if (IS_ERR(chip->disable_votable))
+		return PTR_ERR(chip->disable_votable);
+
+	chip->ilim_votable = create_votable("CP_ILIM",
+			VOTE_MIN, smb1390_ilim_vote_cb, chip);
+	if (IS_ERR(chip->ilim_votable))
+		return PTR_ERR(chip->ilim_votable);
+
+	return 0;
+}
+
+static void smb1390_destroy_votables(struct smb1390 *chip)
+{
+	destroy_votable(chip->disable_votable);
+	destroy_votable(chip->ilim_votable);
+}
+
+static int smb1390_init_hw(struct smb1390 *chip)
+{
+	/*
+	 * charge pump is initially disabled; this indirectly votes to allow
+	 * traditional parallel charging if present
+	 */
+	vote(chip->disable_votable, USER_VOTER, true, 0);
+	return 0;
+}
+
+static int smb1390_get_irq_index_byname(const char *irq_name)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(smb_irqs); i++) {
+		if (strcmp(smb_irqs[i].name, irq_name) == 0)
+			return i;
+	}
+
+	return -ENOENT;
+}
+
+static int smb1390_request_interrupt(struct smb1390 *chip,
+				struct device_node *node,
+				const char *irq_name)
+{
+	int rc = 0, irq, irq_index;
+
+	irq = of_irq_get_byname(node, irq_name);
+	if (irq < 0) {
+		pr_err("Couldn't get irq %s byname\n", irq_name);
+		return irq;
+	}
+
+	irq_index = smb1390_get_irq_index_byname(irq_name);
+	if (irq_index < 0) {
+		pr_err("%s is not a defined irq\n", irq_name);
+		return irq_index;
+	}
+
+	if (!smb_irqs[irq_index].handler)
+		return 0;
+
+	rc = devm_request_threaded_irq(chip->dev, irq, NULL,
+				smb_irqs[irq_index].handler,
+				IRQF_ONESHOT, irq_name, chip);
+	if (rc < 0) {
+		pr_err("Couldn't request irq %d rc=%d\n", irq, rc);
+		return rc;
+	}
+
+	chip->irqs[irq_index] = irq;
+	if (smb_irqs[irq_index].wake)
+		enable_irq_wake(irq);
+
+	return rc;
+}
+
+static int smb1390_request_interrupts(struct smb1390 *chip)
+{
+	struct device_node *node = chip->dev->of_node;
+	struct device_node *child;
+	int rc = 0;
+	const char *name;
+	struct property *prop;
+
+	for_each_available_child_of_node(node, child) {
+		of_property_for_each_string(child, "interrupt-names",
+					    prop, name) {
+			rc = smb1390_request_interrupt(chip, child, name);
+			if (rc < 0) {
+				pr_err("Couldn't request interrupt %s rc=%d\n",
+					name, rc);
+				return rc;
+			}
+		}
+	}
+
+	return rc;
+}
+
+static int smb1390_probe(struct platform_device *pdev)
+{
+	struct smb1390 *chip;
+	int rc;
+
+	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	chip->dev = &pdev->dev;
+	spin_lock_init(&chip->status_change_lock);
+
+	chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
+	if (!chip->regmap) {
+		pr_err("Couldn't get regmap\n");
+		return -EINVAL;
+	}
+
+	INIT_WORK(&chip->status_change_work, smb1390_status_change_work);
+	INIT_WORK(&chip->taper_work, smb1390_taper_work);
+
+	rc = smb1390_parse_dt(chip);
+	if (rc < 0) {
+		pr_err("Couldn't parse device tree rc=%d\n", rc);
+		goto out_work;
+	}
+
+	chip->vadc_dev = qpnp_get_vadc(chip->dev, "smb");
+	if (IS_ERR(chip->vadc_dev)) {
+		rc = PTR_ERR(chip->vadc_dev);
+		pr_err("Couldn't get vadc dev rc=%d\n", rc);
+		goto out_work;
+	}
+
+	rc = smb1390_create_votables(chip);
+	if (rc < 0) {
+		pr_err("Couldn't create votables rc=%d\n", rc);
+		goto out_work;
+	}
+
+	rc = smb1390_init_hw(chip);
+	if (rc < 0) {
+		pr_err("Couldn't init hardware rc=%d\n", rc);
+		goto out_votables;
+	}
+
+	chip->nb.notifier_call = smb1390_notifier_cb;
+	rc = power_supply_reg_notifier(&chip->nb);
+	if (rc < 0) {
+		pr_err("Couldn't register psy notifier rc=%d\n", rc);
+		goto out_votables;
+	}
+
+	chip->cp_class.name = "charge_pump",
+	chip->cp_class.owner = THIS_MODULE,
+	chip->cp_class.class_attrs = cp_class_attrs,
+	rc = class_register(&chip->cp_class);
+	if (rc < 0) {
+		pr_err("Couldn't register charge_pump sysfs class rc=%d\n", rc);
+		goto out_notifier;
+
+	}
+
+	rc = smb1390_request_interrupts(chip);
+	if (rc < 0) {
+		pr_err("Couldn't request interrupts rc=%d\n", rc);
+		goto out_class;
+	}
+
+	return 0;
+
+out_class:
+	class_unregister(&chip->cp_class);
+out_notifier:
+	power_supply_unreg_notifier(&chip->nb);
+out_votables:
+	smb1390_destroy_votables(chip);
+out_work:
+	cancel_work(&chip->taper_work);
+	cancel_work(&chip->status_change_work);
+	return rc;
+}
+
+static int smb1390_remove(struct platform_device *pdev)
+{
+	struct smb1390 *chip = platform_get_drvdata(pdev);
+
+	class_unregister(&chip->cp_class);
+	power_supply_unreg_notifier(&chip->nb);
+
+	/* explicitly disable charging */
+	vote(chip->disable_votable, USER_VOTER, true, 0);
+	cancel_work(&chip->taper_work);
+	cancel_work(&chip->status_change_work);
+	smb1390_destroy_votables(chip);
+	return 0;
+}
+
+static const struct of_device_id match_table[] = {
+	{ .compatible = "qcom,smb1390-charger", },
+	{ },
+};
+
+static struct platform_driver smb1390_driver = {
+	.driver	= {
+		.name		= "qcom,smb1390-charger",
+		.owner		= THIS_MODULE,
+		.of_match_table	= match_table,
+	},
+	.probe	= smb1390_probe,
+	.remove	= smb1390_remove,
+};
+module_platform_driver(smb1390_driver);
+
+MODULE_DESCRIPTION("SMB1390 Charge Pump Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index d20607c..5df7c9e 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -1682,6 +1682,27 @@
 	return 0;
 }
 
+int smblib_configure_wdog(struct smb_charger *chg, bool enable)
+{
+	int rc;
+	u8 val = 0;
+
+	if (enable)
+		val = WDOG_TIMER_EN_ON_PLUGIN_BIT | BARK_WDOG_INT_EN_BIT;
+
+	/* enable WD BARK and enable it on plugin */
+	rc = smblib_masked_write(chg, WD_CFG_REG,
+				WATCHDOG_TRIGGER_AFP_EN_BIT |
+				WDOG_TIMER_EN_ON_PLUGIN_BIT |
+				BARK_WDOG_INT_EN_BIT, val);
+	if (rc < 0) {
+		pr_err("Couldn't configue WD config rc=%d\n", rc);
+		return rc;
+	}
+
+	return 0;
+}
+
 /*******************
  * DC PSY GETTERS *
  *******************/
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index 335764e..39cc921 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -523,6 +523,7 @@
 int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg,
 				const union power_supply_propval *val);
 int smblib_stat_sw_override_cfg(struct smb_charger *chg, bool override);
+int smblib_configure_wdog(struct smb_charger *chg, bool enable);
 
 int smblib_init(struct smb_charger *chg);
 int smblib_deinit(struct smb_charger *chg);
diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h
index afc45ab..3334f67 100644
--- a/drivers/power/supply/qcom/smb5-reg.h
+++ b/drivers/power/supply/qcom/smb5-reg.h
@@ -335,11 +335,6 @@
 #define AICL_CMD_REG				(MISC_BASE + 0x44)
 #define RERUN_AICL_BIT				BIT(0)
 
-#define SNARL_BARK_BITE_WD_CFG_REG		(MISC_BASE + 0x43)
-#define BITE_WDOG_DISABLE_CHARGING_CFG_BIT	BIT(7)
-#define BARK_WDOG_TIMEOUT_MASK			GENMASK(3, 2)
-#define BITE_WDOG_TIMEOUT_MASK			GENMASK(1, 0)
-
 #define MISC_SMB_EN_CMD_REG			(MISC_BASE + 0x48)
 #define SMB_EN_OVERRIDE_VALUE_BIT		BIT(4)
 #define SMB_EN_OVERRIDE_BIT			BIT(3)
@@ -352,6 +347,11 @@
 #define BARK_WDOG_INT_EN_BIT			BIT(6)
 #define WDOG_TIMER_EN_ON_PLUGIN_BIT		BIT(1)
 
+#define SNARL_BARK_BITE_WD_CFG_REG		(MISC_BASE + 0x53)
+#define BITE_WDOG_DISABLE_CHARGING_CFG_BIT	BIT(7)
+#define BARK_WDOG_TIMEOUT_MASK			GENMASK(3, 2)
+#define BITE_WDOG_TIMEOUT_MASK			GENMASK(1, 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 a75cbbb..2d147d4 100644
--- a/drivers/power/supply/qcom/step-chg-jeita.c
+++ b/drivers/power/supply/qcom/step-chg-jeita.c
@@ -82,6 +82,7 @@
 	struct wakeup_source	*step_chg_ws;
 	struct power_supply	*batt_psy;
 	struct power_supply	*bms_psy;
+	struct power_supply	*main_psy;
 	struct delayed_work	status_change_work;
 	struct delayed_work	get_config_work;
 	struct notifier_block	nb;
@@ -534,6 +535,12 @@
 
 update_time:
 	chip->jeita_last_update_time = ktime_get();
+
+	if (!chip->main_psy)
+		chip->main_psy = power_supply_get_by_name("main");
+	if (chip->main_psy)
+		power_supply_changed(chip->main_psy);
+
 	return 0;
 
 reschedule:
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 1ddfabf..46c8268 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -2626,7 +2626,7 @@
 		return;
 
 	host->testbus.select_major = TSTBUS_UTP_HCI;
-	for (i = 0; i <= nminor; i++) {
+	for (i = 0; i < nminor; i++) {
 		host->testbus.select_minor = i;
 		ufs_qcom_testbus_config(host);
 		testbus[i] = ufshcd_readl(hba, UFS_TEST_BUS);
@@ -2636,48 +2636,6 @@
 	kfree(testbus);
 }
 
-void ufs_qcom_read_custom_testbus(struct ufs_hba *hba)
-{
-	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
-
-	host->testbus.select_major = TSTBUS_UTP_HCI;
-	host->testbus.select_minor = 5;
-	ufs_qcom_testbus_config(host);
-	hba->tb_ah8_ctrl_0 = ufshcd_readl(hba, UFS_TEST_BUS);
-
-	host->testbus.select_major = TSTBUS_UNIPRO;
-	host->testbus.select_minor = 33;
-	ufs_qcom_testbus_config(host);
-	hba->tb_dme = ufshcd_readl(hba, UFS_TEST_BUS);
-
-	host->testbus.select_major = TSTBUS_UNIPRO;
-	host->testbus.select_minor = 37;
-	ufs_qcom_testbus_config(host);
-	hba->tb_pa_power_ctrl = ufshcd_readl(hba, UFS_TEST_BUS);
-
-	host->testbus.select_major = TSTBUS_UNIPRO;
-	host->testbus.select_minor = 55;
-	ufs_qcom_testbus_config(host);
-	hba->tb_pa_attr_1 = ufshcd_readl(hba, UFS_TEST_BUS);
-
-	host->testbus.select_major = TSTBUS_UNIPRO;
-	host->testbus.select_minor = 56;
-	ufs_qcom_testbus_config(host);
-	hba->tb_pa_attr_2 = ufshcd_readl(hba, UFS_TEST_BUS);
-}
-
-int ufs_qcom_read_pa_vs_status_reg1(struct ufs_hba *hba, u32 *pa_vs_status_reg1)
-{
-	int err;
-
-	err = ufshcd_dme_get(hba, UIC_ARG_MIB(PA_VS_STATUS_REG1),
-				pa_vs_status_reg1);
-	if (err)
-		dev_err(hba->dev, "%s: couldn't read PA_VS_STATUS_REG1 %d\n",
-								__func__, err);
-	return err;
-}
-
 static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba, bool no_sleep)
 {
 	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h
index 1c48a85..a03ecb0 100644
--- a/drivers/scsi/ufs/ufs-qcom.h
+++ b/drivers/scsi/ufs/ufs-qcom.h
@@ -161,7 +161,6 @@
 
 /* QUniPro Vendor specific attributes */
 #define PA_VS_CONFIG_REG1		0x9000
-#define PA_VS_STATUS_REG1		0x9001
 #define SAVECONFIGTIME_MODE_MASK	0x6000
 
 #define PA_VS_CLK_CFG_REG	0x9004
@@ -397,9 +396,6 @@
 void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba, void *priv,
 		void (*print_fn)(struct ufs_hba *hba, int offset, int num_regs,
 				char *str, void *priv));
-void ufs_qcom_read_custom_testbus(struct ufs_hba *hba);
-int ufs_qcom_read_pa_vs_status_reg1(struct ufs_hba *hba,
-		u32 *pa_vs_status_reg1);
 
 static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host)
 {
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index f3e79e3..d427fb3 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -54,8 +54,6 @@
 
 #ifdef CONFIG_DEBUG_FS
 
-static u32 pa_vs_status_reg1;
-
 static int ufshcd_tag_req_type(struct request *rq)
 {
 	int rq_type = TS_WRITE;
@@ -630,23 +628,6 @@
 	entry->tag = tag;
 	entry->tstamp = ktime_get();
 	entry->outstanding_reqs = hba->outstanding_reqs;
-	if (!strcmp(cmd_type, "custom")) {
-		ufs_qcom_read_custom_testbus(hba);
-		entry->tb_ah8_ctrl_0 = hba->tb_ah8_ctrl_0;
-		entry->tb_dme = hba->tb_dme;
-		entry->tb_pa_power_ctrl = hba->tb_pa_power_ctrl;
-		entry->tb_pa_attr_1 = hba->tb_pa_attr_1;
-		entry->tb_pa_attr_2 = hba->tb_pa_attr_2;
-		entry->pa_vs_status_reg1 = pa_vs_status_reg1;
-		pa_vs_status_reg1 = 0;
-	} else {
-		entry->tb_ah8_ctrl_0 = 0;
-		entry->tb_dme = 0;
-		entry->tb_pa_power_ctrl = 0;
-		entry->tb_pa_attr_1 = 0;
-		entry->tb_pa_attr_2 = 0;
-		entry->pa_vs_status_reg1 = 0;
-	}
 	entry->seq_num = hba->cmd_log.seq_num;
 	hba->cmd_log.seq_num++;
 	hba->cmd_log.pos =
@@ -686,14 +667,11 @@
 		pos = (pos + 1) % UFSHCD_MAX_CMD_LOGGING;
 
 		if (ktime_to_us(p->tstamp)) {
-			pr_err("%s: %s: seq_no=%u lun=0x%x cmd_id=0x%02x lba=0x%llx txfer_len=%d tag=%u, doorbell=0x%x outstanding=0x%x idn=%d ah8_ctrl_0=0x%x dme=0x%x pa_power_ctrl=0x%x pa_attr_1=0x%x pa_attr_2=0x%x pa_vs_status_reg1=0x%x time=%lld us\n",
+			pr_err("%s: %s: seq_no=%u lun=0x%x cmd_id=0x%02x lba=0x%llx txfer_len=%d tag=%u, doorbell=0x%x outstanding=0x%x idn=%d time=%lld us\n",
 				p->cmd_type, p->str, p->seq_num,
 				p->lun, p->cmd_id, (unsigned long long)p->lba,
 				p->transfer_len, p->tag, p->doorbell,
 				p->outstanding_reqs, p->idn,
-				p->tb_ah8_ctrl_0, p->tb_dme,
-				p->tb_pa_power_ctrl, p->tb_pa_attr_1,
-				p->tb_pa_attr_2, p->pa_vs_status_reg1,
 				ktime_to_us(p->tstamp));
 				usleep_range(1000, 1100);
 		}
@@ -10235,7 +10213,6 @@
 	if (ret)
 		goto out;
 
-	ufs_qcom_read_pa_vs_status_reg1(hba, &pa_vs_status_reg1);
 	ufshcd_custom_cmd_log(hba, "waited-for-DB-clear");
 
 	/* scale down the gear before scaling down clocks */
@@ -10243,7 +10220,6 @@
 		ret = ufshcd_scale_gear(hba, false);
 		if (ret)
 			goto clk_scaling_unprepare;
-		ufs_qcom_read_pa_vs_status_reg1(hba, &pa_vs_status_reg1);
 		ufshcd_custom_cmd_log(hba, "Gear-scaled-down");
 	}
 
@@ -10257,14 +10233,12 @@
 		if (ret)
 			/* link will be bad state so no need to scale_up_gear */
 			return ret;
-		ufs_qcom_read_pa_vs_status_reg1(hba, &pa_vs_status_reg1);
 		ufshcd_custom_cmd_log(hba, "Hibern8-entered");
 	}
 
 	ret = ufshcd_scale_clks(hba, scale_up);
 	if (ret)
 		goto scale_up_gear;
-	ufs_qcom_read_pa_vs_status_reg1(hba, &pa_vs_status_reg1);
 	ufshcd_custom_cmd_log(hba, "Clk-freq-switched");
 
 	if (ufshcd_is_auto_hibern8_supported(hba)) {
@@ -10272,7 +10246,6 @@
 		if (ret)
 			/* link will be bad state so no need to scale_up_gear */
 			return ret;
-		ufs_qcom_read_pa_vs_status_reg1(hba, &pa_vs_status_reg1);
 		ufshcd_custom_cmd_log(hba, "Hibern8-Exited");
 	}
 
@@ -10283,7 +10256,6 @@
 			ufshcd_scale_clks(hba, false);
 			goto clk_scaling_unprepare;
 		}
-		ufs_qcom_read_pa_vs_status_reg1(hba, &pa_vs_status_reg1);
 		ufshcd_custom_cmd_log(hba, "Gear-scaled-up");
 	}
 
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index a6b47aa..6e329c0 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -686,12 +686,6 @@
 	u32 seq_num;
 	unsigned int tag;
 	ktime_t tstamp;
-	u32 tb_ah8_ctrl_0;
-	u32 tb_dme;
-	u32 tb_pa_power_ctrl;
-	u32 tb_pa_attr_1;
-	u32 tb_pa_attr_2;
-	u32 pa_vs_status_reg1;
 };
 
 struct ufshcd_cmd_log {
@@ -1001,13 +995,6 @@
 	struct io_latency_state io_lat_write;
 	struct ufs_desc_size desc_size;
 	bool restore_needed;
-
-	/* Custom test bus data */
-	u32 tb_ah8_ctrl_0;
-	u32 tb_dme;
-	u32 tb_pa_power_ctrl;
-	u32 tb_pa_attr_1;
-	u32 tb_pa_attr_2;
 };
 
 static inline void ufshcd_mark_shutdown_ongoing(struct ufs_hba *hba)
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index c5a15b2..4e412497 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -278,6 +278,15 @@
 	  of deadlocks or cpu hangs these dump regions are captured to
 	  give a snapshot of the system at the time of the crash.
 
+config MSM_DEBUG_LAR_UNLOCK
+        bool "MSM Debug LAR Unlock Support"
+        depends on QCOM_MEMORY_DUMP_V2
+        help
+         This allows unlocking Core Debug lock to allow capture
+         of upper 32 bits of program counter at the time of
+         system crash. This is useful in getting correct crash
+         location.
+
 config QCOM_MINIDUMP
 	bool "QCOM Minidump Support"
 	depends on MSM_SMEM && QCOM_DLOAD_MODE
@@ -377,7 +386,7 @@
 	  configured separately.
 
 config MSM_TZ_SMMU
-	depends on ARCH_MSM8953
+	depends on ARCH_MSM8953 || ARCH_MSM8909
 	bool "Helper functions for SMMU configuration through TZ"
 	help
 	  Say 'Y' here for targets that need to call into TZ to configure
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index d9cd0fa..baebb25 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -2548,7 +2548,7 @@
 
 	einfo->irq_line = irq_line;
 	rc = request_irq(irq_line, irq_handler,
-			IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND | IRQF_SHARED,
+			IRQF_TRIGGER_RISING | IRQF_SHARED,
 			node->name, einfo);
 	if (rc < 0) {
 		pr_err("%s: request_irq on %d failed: %d\n", __func__, irq_line,
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index d92b495..8e0a61d 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -1164,8 +1164,9 @@
 {
 	if (!penv)
 		return false;
-	else
-		return test_bit(ICNSS_FW_DOWN, &penv->state);
+
+	return test_bit(ICNSS_FW_DOWN, &penv->state) ||
+		test_bit(ICNSS_PD_RESTART, &penv->state);
 }
 EXPORT_SYMBOL(icnss_is_fw_down);
 
diff --git a/drivers/soc/qcom/ipc_router_smd_xprt.c b/drivers/soc/qcom/ipc_router_smd_xprt.c
index 513689a..c722451 100644
--- a/drivers/soc/qcom/ipc_router_smd_xprt.c
+++ b/drivers/soc/qcom/ipc_router_smd_xprt.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2016, 2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -296,8 +296,10 @@
 	spin_lock_irqsave(&smd_xprtp->ss_reset_lock, flags);
 	if (smd_xprtp->ss_reset) {
 		spin_unlock_irqrestore(&smd_xprtp->ss_reset_lock, flags);
-		if (smd_xprtp->in_pkt)
+		if (smd_xprtp->in_pkt) {
 			release_pkt(smd_xprtp->in_pkt);
+			smd_xprtp->in_pkt = NULL;
+		}
 		smd_xprtp->is_partial_in_pkt = 0;
 		IPC_RTR_ERR("%s: %s channel reset\n",
 			__func__, smd_xprtp->xprt.name);
@@ -350,6 +352,7 @@
 				__func__, smd_xprtp->xprt.name);
 			kfree_skb(ipc_rtr_pkt);
 			release_pkt(smd_xprtp->in_pkt);
+			smd_xprtp->in_pkt = NULL;
 			smd_xprtp->is_partial_in_pkt = 0;
 			return;
 		}
diff --git a/drivers/soc/qcom/memory_dump_v2.c b/drivers/soc/qcom/memory_dump_v2.c
index b76fe86..5912ff2 100644
--- a/drivers/soc/qcom/memory_dump_v2.c
+++ b/drivers/soc/qcom/memory_dump_v2.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,15 +39,6 @@
 	struct msm_dump_table *table;
 };
 
-struct dump_vaddr_entry {
-	uint32_t id;
-	void *dump_vaddr;
-};
-
-struct msm_mem_dump_vaddr_tbl {
-	uint8_t num_node;
-	struct dump_vaddr_entry *entries;
-};
 
 static struct msm_memory_dump memdump;
 static struct msm_mem_dump_vaddr_tbl vaddr_tbl;
@@ -156,7 +147,7 @@
 }
 EXPORT_SYMBOL(msm_dump_data_register);
 
-void *get_msm_dump_ptr(enum msm_dump_data_ids id)
+struct dump_vaddr_entry *get_msm_dump_ptr(enum msm_dump_data_ids id)
 {
 	int i;
 
@@ -174,7 +165,7 @@
 	if (i == vaddr_tbl.num_node)
 		return NULL;
 
-	return (void *)vaddr_tbl.entries[i].dump_vaddr;
+	return &vaddr_tbl.entries[i];
 }
 EXPORT_SYMBOL(get_msm_dump_ptr);
 
@@ -333,6 +324,7 @@
 		} else if (vaddr_tbl.entries) {
 			vaddr_tbl.entries[i].id = id;
 			vaddr_tbl.entries[i].dump_vaddr = dump_vaddr;
+			vaddr_tbl.entries[i].dump_data_vaddr = dump_data;
 			i++;
 		}
 	}
diff --git a/drivers/soc/qcom/peripheral-loader.c b/drivers/soc/qcom/peripheral-loader.c
index 3b6c0bd..360dbcf 100644
--- a/drivers/soc/qcom/peripheral-loader.c
+++ b/drivers/soc/qcom/peripheral-loader.c
@@ -141,28 +141,50 @@
 
 static int pil_do_minidump(struct pil_desc *desc, void *ramdump_dev)
 {
-	struct md_ss_region __iomem *region_info;
+	struct md_ss_region __iomem *region_info_ss;
+	struct md_ss_region __iomem *region_info_pdr;
 	struct ramdump_segment *ramdump_segs, *s;
 	struct pil_priv *priv = desc->priv;
-	void __iomem *subsys_segtable_base;
+	void __iomem *subsys_segtable_base_ss;
+	void __iomem *subsys_segtable_base_pdr;
 	u64 ss_region_ptr = 0;
-	void __iomem *offset;
-	int ss_mdump_seg_cnt;
+	void __iomem *offset_ss;
+	void __iomem *offset_pdr;
+	int ss_mdump_seg_cnt_ss = 0, ss_mdump_seg_cnt_pdr = 0, total_segs;
 	int ss_valid_seg_cnt;
 	int ret, i;
 
-	ss_region_ptr = desc->minidump->md_ss_smem_regions_baseptr;
 	if (!ramdump_dev)
 		return -ENODEV;
-	ss_mdump_seg_cnt = desc->minidump->ss_region_count;
-	subsys_segtable_base =
+
+	ss_region_ptr = desc->minidump_ss->md_ss_smem_regions_baseptr;
+	ss_mdump_seg_cnt_ss = desc->minidump_ss->ss_region_count;
+	subsys_segtable_base_ss =
 		ioremap((unsigned long)ss_region_ptr,
-		ss_mdump_seg_cnt * sizeof(struct md_ss_region));
-	region_info = (struct md_ss_region __iomem *)subsys_segtable_base;
-	if (!region_info)
+		ss_mdump_seg_cnt_ss * sizeof(struct md_ss_region));
+	region_info_ss =
+		(struct md_ss_region __iomem *)subsys_segtable_base_ss;
+	if (!region_info_ss)
 		return -EINVAL;
-	pr_info("Minidump : Segments in minidump 0x%x\n", ss_mdump_seg_cnt);
-	ramdump_segs = kcalloc(ss_mdump_seg_cnt,
+	pr_info("Minidump : SS Segments in minidump 0x%x\n",
+		ss_mdump_seg_cnt_ss);
+
+	if (desc->minidump_pdr &&
+		(desc->minidump_pdr->md_ss_enable_status == MD_SS_ENABLED)) {
+		ss_region_ptr = desc->minidump_pdr->md_ss_smem_regions_baseptr;
+		ss_mdump_seg_cnt_pdr = desc->minidump_pdr->ss_region_count;
+		subsys_segtable_base_pdr =
+			ioremap((unsigned long)ss_region_ptr,
+			ss_mdump_seg_cnt_pdr * sizeof(struct md_ss_region));
+		region_info_pdr =
+			(struct md_ss_region __iomem *)subsys_segtable_base_pdr;
+		if (!region_info_pdr)
+			return -EINVAL;
+		pr_info("Minidump : PDR Segments in minidump 0x%x\n",
+			ss_mdump_seg_cnt_pdr);
+	}
+	total_segs = ss_mdump_seg_cnt_ss + ss_mdump_seg_cnt_pdr;
+	ramdump_segs = kcalloc(total_segs,
 			       sizeof(*ramdump_segs), GFP_KERNEL);
 	if (!ramdump_segs)
 		return -ENOMEM;
@@ -172,24 +194,47 @@
 			(priv->region_end - priv->region_start));
 
 	s = ramdump_segs;
-	ss_valid_seg_cnt = ss_mdump_seg_cnt;
-	for (i = 0; i < ss_mdump_seg_cnt; i++) {
-		memcpy(&offset, &region_info, sizeof(region_info));
-		offset = offset + sizeof(region_info->name) +
-				sizeof(region_info->seq_num);
-		if (__raw_readl(offset) == MD_REGION_VALID) {
-			memcpy(&s->name, &region_info, sizeof(region_info));
-			offset = offset + sizeof(region_info->md_valid);
-			s->address = __raw_readl(offset);
-			offset = offset +
-				sizeof(region_info->region_base_address);
-			s->size = __raw_readl(offset);
+	ss_valid_seg_cnt = total_segs;
+	for (i = 0; i < ss_mdump_seg_cnt_ss; i++) {
+		memcpy(&offset_ss, &region_info_ss, sizeof(region_info_ss));
+		offset_ss = offset_ss + sizeof(region_info_ss->name) +
+				sizeof(region_info_ss->seq_num);
+		if (__raw_readl(offset_ss) == MD_REGION_VALID) {
+			memcpy(&s->name, &region_info_ss,
+				sizeof(region_info_ss));
+			offset_ss = offset_ss +
+				sizeof(region_info_ss->md_valid);
+			s->address = __raw_readl(offset_ss);
+			offset_ss = offset_ss +
+				sizeof(region_info_ss->region_base_address);
+			s->size = __raw_readl(offset_ss);
 			pr_info("Minidump : Dumping segment %s with address 0x%lx and size 0x%x\n",
 				s->name, s->address, (unsigned int)s->size);
 		} else
 			ss_valid_seg_cnt--;
 		s++;
-		region_info++;
+		region_info_ss++;
+	}
+
+	for (i = 0; i < ss_mdump_seg_cnt_pdr; i++) {
+		memcpy(&offset_pdr, &region_info_pdr, sizeof(region_info_pdr));
+		offset_pdr = offset_pdr + sizeof(region_info_pdr->name) +
+				sizeof(region_info_pdr->seq_num);
+		if (__raw_readl(offset_pdr) == MD_REGION_VALID) {
+			memcpy(&s->name, &region_info_pdr,
+				sizeof(region_info_pdr));
+			offset_pdr = offset_pdr +
+				sizeof(region_info_pdr->md_valid);
+			s->address = __raw_readl(offset_pdr);
+			offset_pdr = offset_pdr +
+				sizeof(region_info_pdr->region_base_address);
+			s->size = __raw_readl(offset_pdr);
+			pr_info("Minidump : Dumping segment %s with address 0x%lx and size 0x%x\n",
+				s->name, s->address, (unsigned int)s->size);
+		} else
+			ss_valid_seg_cnt--;
+		s++;
+		region_info_pdr++;
 	}
 	ret = do_minidump(ramdump_dev, ramdump_segs, ss_valid_seg_cnt);
 	kfree(ramdump_segs);
@@ -219,27 +264,27 @@
 	struct pil_seg *seg;
 	int count = 0, ret;
 
-	if (desc->minidump) {
+	if (desc->minidump_ss) {
 		pr_info("Minidump : md_ss_toc->md_ss_toc_init is 0x%x\n",
-			(unsigned int)desc->minidump->md_ss_toc_init);
+			(unsigned int)desc->minidump_ss->md_ss_toc_init);
 		pr_info("Minidump : md_ss_toc->md_ss_enable_status is 0x%x\n",
-			(unsigned int)desc->minidump->md_ss_enable_status);
+			(unsigned int)desc->minidump_ss->md_ss_enable_status);
 		pr_info("Minidump : md_ss_toc->encryption_status is 0x%x\n",
-			(unsigned int)desc->minidump->encryption_status);
+			(unsigned int)desc->minidump_ss->encryption_status);
 		pr_info("Minidump : md_ss_toc->ss_region_count is 0x%x\n",
-			(unsigned int)desc->minidump->ss_region_count);
+			(unsigned int)desc->minidump_ss->ss_region_count);
 		pr_info("Minidump : md_ss_toc->md_ss_smem_regions_baseptr is 0x%x\n",
 			(unsigned int)
-			desc->minidump->md_ss_smem_regions_baseptr);
+			desc->minidump_ss->md_ss_smem_regions_baseptr);
 		/**
 		 * Collect minidump if SS ToC is valid and segment table
 		 * is initialized in memory and encryption status is set.
 		 */
-		if ((desc->minidump->md_ss_smem_regions_baseptr != 0) &&
-			(desc->minidump->md_ss_toc_init == true) &&
-			(desc->minidump->md_ss_enable_status ==
+		if ((desc->minidump_ss->md_ss_smem_regions_baseptr != 0) &&
+			(desc->minidump_ss->md_ss_toc_init == true) &&
+			(desc->minidump_ss->md_ss_enable_status ==
 				MD_SS_ENABLED)) {
-			if (desc->minidump->encryption_status ==
+			if (desc->minidump_ss->encryption_status ==
 				MD_SS_ENCR_DONE) {
 				pr_info("Minidump : Dumping for %s\n",
 					desc->name);
@@ -1184,9 +1229,15 @@
 	else {
 		if (g_md_toc && g_md_toc->md_toc_init == true) {
 			ss_toc_addr = &g_md_toc->md_ss_toc[desc->minidump_id];
-			pr_debug("Minidump : ss_toc_addr is %pa and desc->minidump_id is %d\n",
+			pr_debug("Minidump : ss_toc_addr for ss is %pa and desc->minidump_id is %d\n",
 				&ss_toc_addr, desc->minidump_id);
-			memcpy(&desc->minidump, &ss_toc_addr,
+			memcpy(&desc->minidump_ss, &ss_toc_addr,
+			       sizeof(ss_toc_addr));
+			ss_toc_addr =
+				&g_md_toc->md_ss_toc[desc->minidump_id + 1];
+			pr_debug("Minidump : ss_toc_addr for pdr is %pa and desc->minidump_id is %d\n",
+				&ss_toc_addr, desc->minidump_id);
+			memcpy(&desc->minidump_pdr, &ss_toc_addr,
 			       sizeof(ss_toc_addr));
 		}
 	}
diff --git a/drivers/soc/qcom/peripheral-loader.h b/drivers/soc/qcom/peripheral-loader.h
index 78c00fe..6ea6b2a 100644
--- a/drivers/soc/qcom/peripheral-loader.h
+++ b/drivers/soc/qcom/peripheral-loader.h
@@ -64,7 +64,8 @@
 	bool signal_aop;
 	struct mbox_client cl;
 	struct mbox_chan *mbox;
-	struct md_ss_toc *minidump;
+	struct md_ss_toc *minidump_ss;
+	struct md_ss_toc *minidump_pdr;
 	int minidump_id;
 };
 
diff --git a/drivers/soc/qcom/pil-msa.c b/drivers/soc/qcom/pil-msa.c
index 80dd2f7..6283477 100644
--- a/drivers/soc/qcom/pil-msa.c
+++ b/drivers/soc/qcom/pil-msa.c
@@ -582,7 +582,7 @@
 	if (ret)
 		goto err_clks;
 
-	if (!pil->minidump || !pil->modem_ssr) {
+	if (!pil->minidump_ss || !pil->modem_ssr) {
 		/* Save state of modem debug register before full reset */
 		debug_val = readl_relaxed(drv->reg_base + QDSP6SS_DBG_CFG);
 	}
@@ -595,7 +595,7 @@
 	if (ret)
 		goto err_restart;
 
-	if (!pil->minidump || !pil->modem_ssr) {
+	if (!pil->minidump_ss || !pil->modem_ssr) {
 		writel_relaxed(debug_val, drv->reg_base + QDSP6SS_DBG_CFG);
 		if (modem_dbg_cfg)
 			writel_relaxed(modem_dbg_cfg,
@@ -799,8 +799,13 @@
 	struct q6v5_data *drv = container_of(pil, struct q6v5_data, desc);
 	int ret;
 
-	if (!pil->minidump)
+	if (!pil->minidump_ss)
 		return 0;
+	if (pil->minidump_ss) {
+		if (pil->minidump_ss->md_ss_enable_status != MD_SS_ENABLED)
+			return 0;
+	}
+
 	/*
 	 * Bring subsystem out of reset and enable required
 	 * regulators and clocks.
@@ -809,7 +814,7 @@
 	if (ret)
 		return ret;
 
-	if (pil->minidump) {
+	if (pil->minidump_ss) {
 		writel_relaxed(0x1, drv->reg_base + QDSP6SS_NMI_CFG);
 		/* Let write complete before proceeding */
 		mb();
@@ -832,7 +837,7 @@
 	 */
 	pr_info("Minidump: waiting encryption to complete\n");
 	msleep(10000);
-	if (pil->minidump) {
+	if (pil->minidump_ss) {
 		writel_relaxed(0x2, drv->reg_base + QDSP6SS_NMI_CFG);
 		/* Let write complete before proceeding */
 		mb();
diff --git a/drivers/soc/qcom/pil-q6v5-mss.c b/drivers/soc/qcom/pil-q6v5-mss.c
index ac322f8..4ede3b6 100644
--- a/drivers/soc/qcom/pil-q6v5-mss.c
+++ b/drivers/soc/qcom/pil-q6v5-mss.c
@@ -209,7 +209,7 @@
 static int pil_subsys_init(struct modem_data *drv,
 					struct platform_device *pdev)
 {
-	int ret;
+	int ret = -EINVAL;
 
 	drv->subsys_desc.name = "modem";
 	drv->subsys_desc.dev = &pdev->dev;
@@ -222,6 +222,13 @@
 	drv->subsys_desc.stop_ack_handler = modem_stop_ack_intr_handler;
 	drv->subsys_desc.wdog_bite_handler = modem_wdog_bite_intr_handler;
 
+	if (IS_ERR_OR_NULL(drv->q6)) {
+		ret = PTR_ERR(drv->q6);
+		dev_err(&pdev->dev, "Pil q6 data is err %pK %d!!!\n",
+			drv->q6, ret);
+		goto err_subsys;
+	}
+
 	drv->q6->desc.modem_ssr = false;
 	drv->q6->desc.signal_aop = of_property_read_bool(pdev->dev.of_node,
 						"qcom,signal-aop");
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index f7902e1..036990c 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.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
@@ -884,7 +884,6 @@
 	rpm_msg.cmd[0].addr = addr;
 	rpm_msg.cmd[0].data = data;
 	rpm_msg.msg.num_payload = 1;
-	rpm_msg.msg.is_complete = false;
 
 	return mbox_write_controller_data(rc->chan, &rpm_msg.msg);
 }
diff --git a/drivers/soc/qcom/rpmh_master_stat.c b/drivers/soc/qcom/rpmh_master_stat.c
index bc665fd..e696d4d 100644
--- a/drivers/soc/qcom/rpmh_master_stat.c
+++ b/drivers/soc/qcom/rpmh_master_stat.c
@@ -23,6 +23,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/uaccess.h>
+#include <asm/arch_timer.h>
 #include <soc/qcom/smem.h>
 #include "rpmh_master_stat.h"
 
@@ -102,6 +103,17 @@
 				struct msm_rpmh_master_stats *record,
 				const char *name)
 {
+	/*
+	 * If a master is in sleep when reading the sleep stats from SMEM
+	 * adjust the accumulated sleep duration to show actual sleep time.
+	 * This ensures that the displayed stats are real when used for
+	 * the purpose of computing battery utilization.
+	 */
+	if (record->last_entered > record->last_exited)
+		record->accumulated_duration +=
+				(arch_counter_get_cntvct()
+				- record->last_entered);
+
 	return snprintf(prvbuf, length, "%s\n\tVersion:0x%x\n"
 			"\tSleep Count:0x%x\n"
 			"\tSleep Last Entered At:0x%llx\n"
diff --git a/drivers/soc/qcom/scm.c b/drivers/soc/qcom/scm.c
index fec6f17..a64ddae 100644
--- a/drivers/soc/qcom/scm.c
+++ b/drivers/soc/qcom/scm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -635,28 +635,7 @@
 	return 0;
 }
 
-/**
- * scm_call2() - Invoke a syscall in the secure world
- * @fn_id: The function ID for this syscall
- * @desc: Descriptor structure containing arguments and return values
- *
- * Sends a command to the SCM and waits for the command to finish processing.
- * This should *only* be called in pre-emptible context.
- *
- * A note on cache maintenance:
- * Note that any buffers that are expected to be accessed by the secure world
- * must be flushed before invoking scm_call and invalidated in the cache
- * immediately after scm_call returns. An important point that must be noted
- * is that on ARMV8 architectures, invalidation actually also causes a dirty
- * cache line to be cleaned (flushed + unset-dirty-bit). Therefore it is of
- * paramount importance that the buffer be flushed before invoking scm_call2,
- * even if you don't care about the contents of that buffer.
- *
- * Note that cache maintenance on the argument buffer (desc->args) is taken care
- * of by scm_call2; however, callers are responsible for any other cached
- * buffers passed over to the secure world.
-*/
-int scm_call2(u32 fn_id, struct scm_desc *desc)
+static int __scm_call2(u32 fn_id, struct scm_desc *desc, bool retry)
 {
 	int arglen = desc->arginfo & 0xf;
 	int ret, retry_count = 0;
@@ -670,7 +649,6 @@
 		return ret;
 
 	x0 = fn_id | scm_version_mask;
-
 	do {
 		mutex_lock(&scm_lock);
 
@@ -700,13 +678,15 @@
 			mutex_unlock(&scm_lmh_lock);
 
 		mutex_unlock(&scm_lock);
+		if (!retry)
+			goto out;
 
 		if (ret == SCM_V2_EBUSY)
 			msleep(SCM_EBUSY_WAIT_MS);
 		if (retry_count == 33)
 			pr_warn("scm: secure world has been busy for 1 second!\n");
-	}  while (ret == SCM_V2_EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY));
-
+	} while (ret == SCM_V2_EBUSY && (retry_count++ < SCM_EBUSY_MAX_RETRY));
+out:
 	if (ret < 0)
 		pr_err("scm_call failed: func id %#llx, ret: %d, syscall returns: %#llx, %#llx, %#llx\n",
 			x0, ret, desc->ret[0], desc->ret[1], desc->ret[2]);
@@ -717,9 +697,47 @@
 		return scm_remap_error(ret);
 	return 0;
 }
+
+/**
+ * scm_call2() - Invoke a syscall in the secure world
+ * @fn_id: The function ID for this syscall
+ * @desc: Descriptor structure containing arguments and return values
+ *
+ * Sends a command to the SCM and waits for the command to finish processing.
+ * This should *only* be called in pre-emptible context.
+ *
+ * A note on cache maintenance:
+ * Note that any buffers that are expected to be accessed by the secure world
+ * must be flushed before invoking scm_call and invalidated in the cache
+ * immediately after scm_call returns. An important point that must be noted
+ * is that on ARMV8 architectures, invalidation actually also causes a dirty
+ * cache line to be cleaned (flushed + unset-dirty-bit). Therefore it is of
+ * paramount importance that the buffer be flushed before invoking scm_call2,
+ * even if you don't care about the contents of that buffer.
+ *
+ * Note that cache maintenance on the argument buffer (desc->args) is taken care
+ * of by scm_call2; however, callers are responsible for any other cached
+ * buffers passed over to the secure world.
+ */
+int scm_call2(u32 fn_id, struct scm_desc *desc)
+{
+	return __scm_call2(fn_id, desc, true);
+}
 EXPORT_SYMBOL(scm_call2);
 
 /**
+ * scm_call2_noretry() - Invoke a syscall in the secure world
+ *
+ * Similar to scm_call2 except that there is no retry mechanism
+ * implemented.
+ */
+int scm_call2_noretry(u32 fn_id, struct scm_desc *desc)
+{
+	return __scm_call2(fn_id, desc, false);
+}
+EXPORT_SYMBOL(scm_call2_noretry);
+
+/**
  * scm_call2_atomic() - Invoke a syscall in the secure world
  *
  * Similar to scm_call2 except that this can be invoked in atomic context.
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index d5de12b..d8fcf5f 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -570,6 +570,7 @@
 
 	/* sdxpoorwills ID */
 	[334] = {SDX_CPU_SDXPOORWILLS, "SDXPOORWILLS"},
+	[335] = {SDX_CPU_SDXPOORWILLS, "SDXPOORWILLS"},
 
 	/* 9650 IDs */
 	[279] = {MSM_CPU_9650, "MDM9650"},
@@ -578,6 +579,14 @@
 	[285] = {MSM_CPU_9650, "MDM9650"},
 	[286] = {MSM_CPU_9650, "MDM9650"},
 
+	/* 9607 IDs */
+	[290] = {MSM_CPU_9607, "MDM9607"},
+	[296] = {MSM_CPU_9607, "MDM8207"},
+	[297] = {MSM_CPU_9607, "MDM9207"},
+	[298] = {MSM_CPU_9607, "MDM9307"},
+	[299] = {MSM_CPU_9607, "MDM9628"},
+	[322] = {MSM_CPU_9607, "MDM9206"},
+
 	/* SDM670 ID */
 	[336] = {MSM_CPU_SDM670, "SDM670"},
 
@@ -1564,6 +1573,10 @@
 		dummy_socinfo.id = 354;
 		strlcpy(dummy_socinfo.build_id, "sdm429 - ",
 				sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_mdm9607()) {
+		dummy_socinfo.id = 290;
+		strlcpy(dummy_socinfo.build_id, "mdm9607 - ",
+				sizeof(dummy_socinfo.build_id));
 	}
 
 	strlcat(dummy_socinfo.build_id, "Dummy socinfo",
diff --git a/drivers/soc/qcom/watchdog_v2.c b/drivers/soc/qcom/watchdog_v2.c
index 5630dc0..b924bc8 100644
--- a/drivers/soc/qcom/watchdog_v2.c
+++ b/drivers/soc/qcom/watchdog_v2.c
@@ -93,6 +93,7 @@
 
 	bool timer_expired;
 	bool user_pet_complete;
+	unsigned int scandump_size;
 };
 
 /*
@@ -581,6 +582,41 @@
 	return;
 }
 
+static void register_scan_dump(struct msm_watchdog_data *wdog_dd)
+{
+	static void *dump_addr;
+	int ret;
+	struct msm_dump_entry dump_entry;
+	struct msm_dump_data *dump_data;
+
+	if (!wdog_dd->scandump_size)
+		return;
+
+	dump_data = kzalloc(sizeof(struct msm_dump_data), GFP_KERNEL);
+	if (!dump_data)
+		return;
+	dump_addr = kzalloc(wdog_dd->scandump_size, GFP_KERNEL);
+	if (!dump_addr)
+		goto err0;
+
+	dump_data->addr = virt_to_phys(dump_addr);
+	dump_data->len = wdog_dd->scandump_size;
+	strlcpy(dump_data->name, "KSCANDUMP", sizeof(dump_data->name));
+
+	dump_entry.id = MSM_DUMP_DATA_SCANDUMP;
+	dump_entry.addr = virt_to_phys(dump_data);
+	ret = msm_dump_data_register(MSM_DUMP_TABLE_APPS, &dump_entry);
+	if (ret) {
+		pr_err("Registering scandump region failed\n");
+		goto err1;
+	}
+	return;
+err1:
+	kfree(dump_addr);
+err0:
+	kfree(dump_data);
+}
+
 static void configure_scandump(struct msm_watchdog_data *wdog_dd)
 {
 	int ret;
@@ -624,6 +660,8 @@
 			devm_kfree(wdog_dd->dev, cpu_data);
 		}
 	}
+
+	register_scan_dump(wdog_dd);
 }
 
 static int init_watchdog_sysfs(struct msm_watchdog_data *wdog_dd)
@@ -805,6 +843,11 @@
 	pdata->wakeup_irq_enable = of_property_read_bool(node,
 							 "qcom,wakeup-enable");
 
+	if (of_property_read_u32(node, "qcom,scandump-size",
+				 &pdata->scandump_size))
+		dev_info(&pdev->dev,
+			 "No need to allocate memory for scandumps\n");
+
 	pdata->irq_ppi = irq_is_percpu(pdata->bark_irq);
 	dump_pdata(pdata);
 	return 0;
diff --git a/drivers/soc/qcom/wcnss/wcnss_vreg.c b/drivers/soc/qcom/wcnss/wcnss_vreg.c
index 5ce2e82..9d24ce1 100644
--- a/drivers/soc/qcom/wcnss/wcnss_vreg.c
+++ b/drivers/soc/qcom/wcnss/wcnss_vreg.c
@@ -193,27 +193,6 @@
 	}
 }
 
-static void wcnss_free_regulator(void)
-{
-	int vreg_i;
-
-	/* Free pronto voltage regulators from device node */
-	for (vreg_i = 0; vreg_i < PRONTO_REGULATORS; vreg_i++) {
-		if (pronto_vregs[vreg_i].state) {
-			regulator_put(pronto_vregs[vreg_i].regulator);
-			pronto_vregs[vreg_i].state = VREG_NULL_CONFIG;
-		}
-	}
-
-	/* Free IRIS voltage regulators from device node */
-	for (vreg_i = 0; vreg_i < IRIS_REGULATORS; vreg_i++) {
-		if (iris_vregs[vreg_i].state) {
-			regulator_put(iris_vregs[vreg_i].regulator);
-			iris_vregs[vreg_i].state = VREG_NULL_CONFIG;
-		}
-	}
-}
-
 static int
 wcnss_dt_parse_vreg_level(struct device *dev, int index,
 			  const char *current_vreg_name, const char *vreg_name,
@@ -256,13 +235,14 @@
 	/* Parse pronto voltage regulators from device node */
 	for (vreg_i = 0; vreg_i < PRONTO_REGULATORS; vreg_i++) {
 		pronto_vregs[vreg_i].regulator =
-			regulator_get(dev, pronto_vregs[vreg_i].name);
+			devm_regulator_get_optional(dev,
+						    pronto_vregs[vreg_i].name);
 		if (IS_ERR(pronto_vregs[vreg_i].regulator)) {
 			if (pronto_vregs[vreg_i].required) {
 				rc = PTR_ERR(pronto_vregs[vreg_i].regulator);
 				dev_err(dev, "regulator get of %s failed (%d)\n",
 					pronto_vregs[vreg_i].name, rc);
-				goto wcnss_vreg_get_err;
+				return rc;
 			} else {
 				dev_dbg(dev, "Skip optional regulator configuration: %s\n",
 					pronto_vregs[vreg_i].name);
@@ -270,27 +250,28 @@
 			}
 		}
 
-		pronto_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK;
 		rc = wcnss_dt_parse_vreg_level(dev, vreg_i,
 					       pronto_vregs[vreg_i].curr,
 					       pronto_vregs[vreg_i].volt,
 					       wlan_config->pronto_vlevel);
 		if (rc) {
 			dev_err(dev, "error reading voltage-level property\n");
-			goto wcnss_vreg_get_err;
+			return rc;
 		}
+		pronto_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK;
 	}
 
 	/* Parse iris voltage regulators from device node */
 	for (vreg_i = 0; vreg_i < IRIS_REGULATORS; vreg_i++) {
 		iris_vregs[vreg_i].regulator =
-			regulator_get(dev, iris_vregs[vreg_i].name);
+			devm_regulator_get_optional(dev,
+						    iris_vregs[vreg_i].name);
 		if (IS_ERR(iris_vregs[vreg_i].regulator)) {
 			if (iris_vregs[vreg_i].required) {
 				rc = PTR_ERR(iris_vregs[vreg_i].regulator);
 				dev_err(dev, "regulator get of %s failed (%d)\n",
 					iris_vregs[vreg_i].name, rc);
-				goto wcnss_vreg_get_err;
+				return rc;
 			} else {
 				dev_dbg(dev, "Skip optional regulator configuration: %s\n",
 					iris_vregs[vreg_i].name);
@@ -298,22 +279,18 @@
 			}
 		}
 
-		iris_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK;
 		rc = wcnss_dt_parse_vreg_level(dev, vreg_i,
 					       iris_vregs[vreg_i].curr,
 					       iris_vregs[vreg_i].volt,
 					       wlan_config->iris_vlevel);
 		if (rc) {
 			dev_err(dev, "error reading voltage-level property\n");
-			goto wcnss_vreg_get_err;
+			return rc;
 		}
+		iris_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK;
 	}
 
 	return 0;
-
-wcnss_vreg_get_err:
-	wcnss_free_regulator();
-	return rc;
 }
 
 void  wcnss_iris_reset(u32 reg, void __iomem *pmu_conf_reg)
@@ -587,13 +564,8 @@
 				pr_err("vreg %s disable failed (%d)\n",
 				       regulators[i].name, rc);
 		}
-
-		/* Free the regulator source */
-		if (regulators[i].state & VREG_GET_REGULATOR_MASK)
-			regulator_put(regulators[i].regulator);
-
-		regulators[i].state = VREG_NULL_CONFIG;
 	}
+
 }
 
 /* Common helper routine to turn on all WCNSS & IRIS vregs */
diff --git a/drivers/soc/qcom/wcnss/wcnss_wlan.c b/drivers/soc/qcom/wcnss/wcnss_wlan.c
index db3974b..481dbd0 100644
--- a/drivers/soc/qcom/wcnss/wcnss_wlan.c
+++ b/drivers/soc/qcom/wcnss/wcnss_wlan.c
@@ -2177,7 +2177,7 @@
 		return;
 	}
 	if (len < sizeof(struct smd_msg_hdr)) {
-		pr_err("wcnss: incomplete header available len = %d\n", len);
+		pr_debug("wcnss: incomplete header available len = %d\n", len);
 		return;
 	}
 
@@ -3329,7 +3329,7 @@
 		return NOTIFY_DONE;
 	}
 
-	pr_debug("%s: wcnss notification event: %lu : %s\n",
+	pr_info("%s: wcnss notification event: %lu : %s\n",
 		 __func__, code, wcnss_subsys_notif_type[code]);
 
 	if (code == SUBSYS_PROXY_VOTE) {
diff --git a/drivers/staging/android/ion/ion_carveout_heap.c b/drivers/staging/android/ion/ion_carveout_heap.c
index e8028d2..492a93d 100644
--- a/drivers/staging/android/ion/ion_carveout_heap.c
+++ b/drivers/staging/android/ion/ion_carveout_heap.c
@@ -206,3 +206,224 @@
 	kfree(carveout_heap);
 	carveout_heap = NULL;
 }
+
+#include "msm/msm_ion.h"
+#include <soc/qcom/secure_buffer.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/msm_ion.h>
+
+struct ion_sc_entry {
+	struct list_head list;
+	struct ion_heap *heap;
+	u32 token;
+};
+
+struct ion_sc_heap {
+	struct ion_heap heap;
+	struct device *dev;
+	struct list_head children;
+};
+
+static struct ion_heap *ion_sc_find_child(struct ion_heap *heap, u32 flags)
+{
+	struct ion_sc_heap *manager;
+	struct ion_sc_entry *entry;
+
+	manager = container_of(heap, struct ion_sc_heap, heap);
+	flags = flags & ION_FLAGS_CP_MASK;
+	list_for_each_entry(entry, &manager->children, list) {
+		if (entry->token == flags)
+			return entry->heap;
+	}
+	return NULL;
+}
+
+static int ion_sc_heap_allocate(struct ion_heap *heap,
+				struct ion_buffer *buffer, unsigned long len,
+				unsigned long align, unsigned long flags) {
+	struct ion_heap *child;
+
+	/* cache maintenance is not possible on secure memory */
+	flags &= ~((unsigned long)ION_FLAG_CACHED);
+	buffer->flags = flags;
+
+	child = ion_sc_find_child(heap, flags);
+	if (!child)
+		return -EINVAL;
+
+	return ion_carveout_heap_allocate(child, buffer, len, align, flags);
+}
+
+static void ion_sc_heap_free(struct ion_buffer *buffer)
+{
+	struct ion_heap *child;
+	struct sg_table *table = buffer->priv_virt;
+	struct page *page = sg_page(table->sgl);
+	ion_phys_addr_t paddr = PFN_PHYS(page_to_pfn(page));
+
+	child = ion_sc_find_child(buffer->heap, buffer->flags);
+	if (!child) {
+		WARN(1, "ion_secure_carvout: invalid buffer flags on free. Memory will be leaked\n.");
+		return;
+	}
+
+	ion_carveout_free(child, paddr, buffer->size);
+	sg_free_table(table);
+	kfree(table);
+}
+
+static struct ion_heap_ops ion_sc_heap_ops = {
+	.allocate = ion_sc_heap_allocate,
+	.free = ion_sc_heap_free,
+	.phys = ion_carveout_heap_phys,
+	.map_dma = ion_carveout_heap_map_dma,
+	.unmap_dma = ion_carveout_heap_unmap_dma,
+};
+
+static int ion_sc_get_dt_token(struct ion_sc_entry *entry,
+			       struct device_node *np, u64 base, u64 size)
+{
+	u32 token;
+	u32 *vmids, *modes;
+	u32 nr, i;
+	int ret = -EINVAL;
+	u32 src_vm = VMID_HLOS;
+
+	if (of_property_read_u32(np, "token", &token))
+		return -EINVAL;
+
+	nr = count_set_bits(token);
+	vmids = kcalloc(nr, sizeof(*vmids), GFP_KERNEL);
+	if (!vmids)
+		return -ENOMEM;
+
+	modes = kcalloc(nr, sizeof(*modes), GFP_KERNEL);
+	if (!modes) {
+		kfree(vmids);
+		return -ENOMEM;
+	}
+
+	if ((token & ~ION_FLAGS_CP_MASK) ||
+	    populate_vm_list(token, vmids, nr)) {
+		pr_err("secure_carveout_heap: Bad token %x\n", token);
+		goto out;
+	}
+
+	for (i = 0; i < nr; i++)
+		if (vmids[i] == VMID_CP_SEC_DISPLAY)
+			modes[i] = PERM_READ;
+		else
+			modes[i] = PERM_READ | PERM_WRITE;
+
+	ret = hyp_assign_phys(base, size, &src_vm, 1, vmids, modes, nr);
+	if (ret)
+		pr_err("secure_carveout_heap: Assign token 0x%x failed\n",
+		       token);
+	else
+		entry->token = token;
+out:
+	kfree(modes);
+	kfree(vmids);
+	return ret;
+}
+
+static int ion_sc_add_child(struct ion_sc_heap *manager,
+			    struct device_node *np)
+{
+	struct device *dev = manager->dev;
+	struct ion_platform_heap heap_data = {0};
+	struct ion_sc_entry *entry;
+	struct device_node *phandle;
+	const __be32 *basep;
+	u64 base, size;
+	int ret;
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&entry->list);
+
+	phandle = of_parse_phandle(np, "memory-region", 0);
+	if (!phandle)
+		goto out_free;
+
+	basep = of_get_address(phandle,  0, &size, NULL);
+	if (!basep)
+		goto out_free;
+
+	base = of_translate_address(phandle, basep);
+	if (base == OF_BAD_ADDR)
+		goto out_free;
+
+	heap_data.priv = dev;
+	heap_data.base = base;
+	heap_data.size = size;
+
+	/* This will zero memory initially */
+	entry->heap = ion_carveout_heap_create(&heap_data);
+	if (IS_ERR(entry->heap))
+		goto out_free;
+
+	ret = ion_sc_get_dt_token(entry, np, base, size);
+	if (ret)
+		goto out_free_carveout;
+
+	list_add(&entry->list, &manager->children);
+	dev_info(dev, "ion_secure_carveout: creating heap@0x%llx, size 0x%llx\n",
+		 base, size);
+	return 0;
+
+out_free_carveout:
+	ion_carveout_heap_destroy(entry->heap);
+out_free:
+	kfree(entry);
+	return -EINVAL;
+}
+
+void ion_secure_carveout_heap_destroy(struct ion_heap *heap)
+{
+	struct ion_sc_heap *manager =
+		container_of(heap, struct ion_sc_heap, heap);
+	struct ion_sc_entry *entry, *tmp;
+
+	list_for_each_entry_safe(entry, tmp, &manager->children, list) {
+		ion_carveout_heap_destroy(entry->heap);
+		kfree(entry);
+	}
+	kfree(manager);
+}
+
+struct ion_heap *ion_secure_carveout_heap_create(
+			struct ion_platform_heap *heap_data)
+{
+	struct device *dev = heap_data->priv;
+	int ret;
+	struct ion_sc_heap *manager;
+	struct device_node *np;
+
+	manager = kzalloc(sizeof(*manager), GFP_KERNEL);
+	if (!manager)
+		return ERR_PTR(-ENOMEM);
+
+	INIT_LIST_HEAD(&manager->children);
+	manager->dev = dev;
+
+	for_each_child_of_node(dev->of_node, np) {
+		ret = ion_sc_add_child(manager, np);
+		if (ret) {
+			dev_err(dev, "Creating child pool %s failed\n",
+				np->name);
+			goto err;
+		}
+	}
+
+	manager->heap.ops = &ion_sc_heap_ops;
+	manager->heap.type = ION_HEAP_TYPE_SECURE_CARVEOUT;
+	return &manager->heap;
+
+err:
+	ion_secure_carveout_heap_destroy(&manager->heap);
+	return ERR_PTR(-EINVAL);
+}
diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c
index 4b9e359..656eb49 100644
--- a/drivers/staging/android/ion/msm/msm_ion.c
+++ b/drivers/staging/android/ion/msm/msm_ion.c
@@ -122,6 +122,10 @@
 	{
 		.id	= ION_SECURE_DISPLAY_HEAP_ID,
 		.name	= ION_SECURE_DISPLAY_HEAP_NAME,
+	},
+	{
+		.id	= ION_SECURE_CARVEOUT_HEAP_ID,
+		.name	= ION_SECURE_CARVEOUT_HEAP_NAME,
 	}
 };
 #endif
@@ -443,6 +447,7 @@
 	MAKE_HEAP_TYPE_MAPPING(SYSTEM),
 	MAKE_HEAP_TYPE_MAPPING(SYSTEM_CONTIG),
 	MAKE_HEAP_TYPE_MAPPING(CARVEOUT),
+	MAKE_HEAP_TYPE_MAPPING(SECURE_CARVEOUT),
 	MAKE_HEAP_TYPE_MAPPING(CHUNK),
 	MAKE_HEAP_TYPE_MAPPING(DMA),
 	MAKE_HEAP_TYPE_MAPPING(SECURE_DMA),
@@ -1021,6 +1026,9 @@
 	case ION_HEAP_TYPE_HYP_CMA:
 		heap = ion_cma_secure_heap_create(heap_data);
 		break;
+	case ION_HEAP_TYPE_SECURE_CARVEOUT:
+		heap = ion_secure_carveout_heap_create(heap_data);
+		break;
 	default:
 		heap = ion_heap_create(heap_data);
 	}
@@ -1056,6 +1064,9 @@
 	case ION_HEAP_TYPE_HYP_CMA:
 		ion_cma_secure_heap_destroy(heap);
 		break;
+	case ION_HEAP_TYPE_SECURE_CARVEOUT:
+		ion_secure_carveout_heap_destroy(heap);
+		break;
 	default:
 		ion_heap_destroy(heap);
 	}
diff --git a/drivers/staging/android/ion/msm_ion_priv.h b/drivers/staging/android/ion/msm_ion_priv.h
index bbf2e8b..1318d1f 100644
--- a/drivers/staging/android/ion/msm_ion_priv.h
+++ b/drivers/staging/android/ion/msm_ion_priv.h
@@ -2,7 +2,7 @@
  * drivers/staging/android/ion/msm_ion_priv.h
  *
  * Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -40,6 +40,10 @@
 struct ion_heap *ion_cma_secure_heap_create(struct ion_platform_heap *heap);
 void ion_cma_secure_heap_destroy(struct ion_heap *heap);
 
+struct ion_heap *ion_secure_carveout_heap_create(
+			struct ion_platform_heap *heap);
+void ion_secure_carveout_heap_destroy(struct ion_heap *heap);
+
 long msm_ion_custom_ioctl(struct ion_client *client,
 			  unsigned int cmd,
 			  unsigned long arg);
diff --git a/drivers/staging/android/uapi/msm_ion.h b/drivers/staging/android/uapi/msm_ion.h
index eb60bad..a6672ff 100644
--- a/drivers/staging/android/uapi/msm_ion.h
+++ b/drivers/staging/android/uapi/msm_ion.h
@@ -10,6 +10,7 @@
 	ION_HEAP_TYPE_SECURE_DMA = ION_HEAP_TYPE_MSM_START,
 	ION_HEAP_TYPE_SYSTEM_SECURE,
 	ION_HEAP_TYPE_HYP_CMA,
+	ION_HEAP_TYPE_SECURE_CARVEOUT,
 	/*
 	 * if you add a heap type here you should also add it to
 	 * heap_types_info[] in msm_ion.c
@@ -32,6 +33,7 @@
 	ION_SECURE_DISPLAY_HEAP_ID = 10,
 	ION_CP_MFC_HEAP_ID = 12,
 	ION_SPSS_HEAP_ID = 13, /* Secure Processor ION heap */
+	ION_SECURE_CARVEOUT_HEAP_ID = 14,
 	ION_CP_WB_HEAP_ID = 16, /* 8660 only */
 	ION_QSECOM_TA_HEAP_ID = 19,
 	ION_CAMERA_HEAP_ID = 20, /* 8660 only */
@@ -133,6 +135,7 @@
 #define ION_IOMMU_HEAP_NAME	"iommu"
 #define ION_MFC_HEAP_NAME	"mfc"
 #define ION_SPSS_HEAP_NAME	"spss"
+#define ION_SECURE_CARVEOUT_HEAP_NAME	"secure_carveout"
 #define ION_WB_HEAP_NAME	"wb"
 #define ION_MM_FIRMWARE_HEAP_NAME	"mm_fw"
 #define ION_PIL1_HEAP_NAME  "pil_1"
diff --git a/drivers/thermal/qcom/qti_virtual_sensor.c b/drivers/thermal/qcom/qti_virtual_sensor.c
index 8d988eb..f01658d 100644
--- a/drivers/thermal/qcom/qti_virtual_sensor.c
+++ b/drivers/thermal/qcom/qti_virtual_sensor.c
@@ -86,9 +86,9 @@
 				"apc1-cpu1-usr",
 				"apc1-cpu2-usr",
 				"apc1-cpu3-usr",
-				"cpuss0-usr",
-				"cpuss1-usr",
-				"cpuss3-usr"},
+				"apc1-mhm-usr",
+				"apc1-l2-usr",
+				"cpuss0-usr"},
 		.logic = VIRT_MAXIMUM,
 	},
 	{
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index 6a3c06f..5c0022e 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -2232,6 +2232,71 @@
 
 static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip)
 {
+	int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0;
+	unsigned long flags;
+
+	if (qpnp_adc_tm_is_valid(chip))
+		return -ENODEV;
+
+	mutex_lock(&chip->adc->adc_lock);
+
+	rc = qpnp_adc_tm_req_sts_check(chip);
+	if (rc) {
+		pr_err("adc-tm-tm req sts check failed with %d\n", rc);
+		goto fail;
+	}
+
+	if (chip->th_info.adc_tm_high_enable) {
+		spin_lock_irqsave(&chip->th_info.adc_tm_high_lock, flags);
+		sensor_notify_num = chip->th_info.adc_tm_high_enable;
+		chip->th_info.adc_tm_high_enable = 0;
+		spin_unlock_irqrestore(&chip->th_info.adc_tm_high_lock, flags);
+		while (i < chip->max_channels_available) {
+			if ((sensor_notify_num & 0x1) == 1) {
+				sensor_num = i;
+				rc = qpnp_adc_tm_disable_rearm_high_thresholds(
+						chip, sensor_num);
+				if (rc < 0) {
+					pr_err("rearm threshold failed\n");
+					goto fail;
+				}
+			}
+			sensor_notify_num >>= 1;
+			i++;
+		}
+	}
+
+	if (chip->th_info.adc_tm_low_enable) {
+		spin_lock_irqsave(&chip->th_info.adc_tm_low_lock, flags);
+		sensor_notify_num = chip->th_info.adc_tm_low_enable;
+		chip->th_info.adc_tm_low_enable = 0;
+		spin_unlock_irqrestore(&chip->th_info.adc_tm_low_lock, flags);
+		i = 0;
+		while (i < chip->max_channels_available) {
+			if ((sensor_notify_num & 0x1) == 1) {
+				sensor_num = i;
+				rc = qpnp_adc_tm_disable_rearm_low_thresholds(
+						chip, sensor_num);
+				if (rc < 0) {
+					pr_err("rearm threshold failed\n");
+					goto fail;
+				}
+			}
+			sensor_notify_num >>= 1;
+			i++;
+		}
+	}
+
+fail:
+	mutex_unlock(&chip->adc->adc_lock);
+	if (rc < 0)
+		atomic_dec(&chip->wq_cnt);
+
+	return rc;
+}
+
+static int qpnp_adc_tm_hc_read_status(struct qpnp_adc_tm_chip *chip)
+{
 	int rc = 0, sensor_num = 0;
 
 	if (qpnp_adc_tm_is_valid(chip))
@@ -2300,9 +2365,15 @@
 
 	pr_debug("thr:0x%x\n", chip->th_info.adc_tm_high_enable);
 
-	rc = qpnp_adc_tm_read_status(chip);
-	if (rc < 0)
-		pr_err("adc-tm high thr work failed\n");
+	if (!chip->adc_tm_hc) {
+		rc = qpnp_adc_tm_read_status(chip);
+		if (rc < 0)
+			pr_err("adc-tm high thr work failed\n");
+	} else {
+		rc = qpnp_adc_tm_hc_read_status(chip);
+		if (rc < 0)
+			pr_err("adc-tm-hc high thr work failed\n");
+	}
 }
 
 static irqreturn_t qpnp_adc_tm_high_thr_isr(int irq, void *data)
@@ -2406,9 +2477,15 @@
 
 	pr_debug("thr:0x%x\n", chip->th_info.adc_tm_low_enable);
 
-	rc = qpnp_adc_tm_read_status(chip);
-	if (rc < 0)
-		pr_err("adc-tm low thr work failed\n");
+	if (!chip->adc_tm_hc) {
+		rc = qpnp_adc_tm_read_status(chip);
+		if (rc < 0)
+			pr_err("adc-tm low thr work failed\n");
+	} else {
+		rc = qpnp_adc_tm_hc_read_status(chip);
+		if (rc < 0)
+			pr_err("adc-tm-hc low thr work failed\n");
+	}
 }
 
 static irqreturn_t qpnp_adc_tm_low_thr_isr(int irq, void *data)
diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c
index 563305f..148568b 100644
--- a/drivers/tty/serial/msm_geni_serial.c
+++ b/drivers/tty/serial/msm_geni_serial.c
@@ -447,6 +447,8 @@
 							SE_UART_MANUAL_RFR);
 	/* Write to flow control must complete before return to client*/
 	mb();
+	IPC_LOG_MSG(port->ipc_log_misc, "%s: Manual_rfr 0x%x\n",
+						__func__, uart_manual_rfr);
 }
 
 static const char *msm_geni_serial_get_type(struct uart_port *uport)
@@ -2540,6 +2542,8 @@
 	 * set this to manual flow on.
 	 */
 	if (!port->manual_flow) {
+		u32 geni_ios;
+
 		uart_manual_rfr |= (UART_MANUAL_RFR_EN | UART_RFR_READY);
 		geni_write_reg_nolog(uart_manual_rfr, port->uport.membase,
 							SE_UART_MANUAL_RFR);
@@ -2548,8 +2552,11 @@
 		 * doing a stop_rx else we could end up flowing off the peer.
 		 */
 		mb();
-		IPC_LOG_MSG(port->ipc_log_pwr, "%s: Manual Flow ON 0x%x\n",
-						 __func__, uart_manual_rfr);
+		geni_ios = geni_read_reg_nolog(port->uport.membase,
+								SE_GENI_IOS);
+		IPC_LOG_MSG(port->ipc_log_pwr, "%s: Manual Flow ON 0x%x 0x%x\n",
+					 __func__, uart_manual_rfr, geni_ios);
+		udelay(10);
 	}
 	stop_rx_sequencer(&port->uport);
 	if ((geni_status & M_GENI_CMD_ACTIVE))
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index d1a63da..2095579 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -405,7 +405,7 @@
 
 	evt = dwc->ev_buf;
 	dwc3_trace(trace_dwc3_core,
-			"Event buf %p dma %08llx length %d\n",
+			"Event buf %pK dma %08llx length %d\n",
 			evt->buf, (unsigned long long) evt->dma,
 			evt->length);
 
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index ded62f1..04bce36 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -792,7 +792,7 @@
 	list_add_tail(&req_complete->list_item, &mdwc->req_complete_list);
 	request->complete = dwc3_msm_req_complete_func;
 
-	dev_vdbg(dwc->dev, "%s: queing request %p to ep %s length %d\n",
+	dev_vdbg(dwc->dev, "%s: queing request %pK to ep %s length %d\n",
 			__func__, request, ep->name, request->length);
 	size = dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTSIZ(0));
 	dbm_event_buffer_config(mdwc->dbm,
@@ -992,7 +992,7 @@
 		dev_dbg(mdwc->dev, "Failed to get GSI DBL address MSB\n");
 
 	offset = dwc3_trb_dma_offset(dep, &dep->trb_pool[num_trbs-1]);
-	dev_dbg(mdwc->dev, "Writing link TRB addr: %pa to %p (%x) for ep:%s\n",
+	dev_dbg(mdwc->dev, "Writing link TRB addr: %pa to %pK (%x) for ep:%s\n",
 		&offset, gsi_dbl_address_lsb, request->db_reg_phs_addr_lsb,
 		ep->name);
 
@@ -1959,7 +1959,7 @@
 			if (!evt)
 				break;
 
-			dev_dbg(mdwc->dev, "Evt buf %p dma %08llx length %d\n",
+			dev_dbg(mdwc->dev, "Evt buf %pK dma %08llx length %d\n",
 				evt->buf, (unsigned long long) evt->dma,
 				evt->length);
 			memset(evt->buf, 0, evt->length);
@@ -3887,10 +3887,10 @@
 	if (on) {
 		dev_dbg(mdwc->dev, "%s: turn on host\n", __func__);
 
+		mdwc->hs_phy->flags |= PHY_HOST_MODE;
 		pm_runtime_get_sync(mdwc->dev);
 		dbg_event(0xFF, "StrtHost gync",
 			atomic_read(&mdwc->dev->power.usage_count));
-		mdwc->hs_phy->flags |= PHY_HOST_MODE;
 		if (dwc->maximum_speed == USB_SPEED_SUPER) {
 			mdwc->ss_phy->flags |= PHY_HOST_MODE;
 			usb_phy_notify_connect(mdwc->ss_phy,
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 8cf49fa..381ad49 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -240,7 +240,7 @@
 	spin_lock_irqsave(&dwc->lock, flags);
 	if (!dep->endpoint.desc) {
 		dwc3_trace(trace_dwc3_ep0,
-				"trying to queue request %p to disabled %s",
+				"trying to queue request %pK to disabled %s",
 				request, dep->name);
 		ret = -ESHUTDOWN;
 		goto out;
@@ -265,7 +265,7 @@
 	}
 
 	dwc3_trace(trace_dwc3_ep0,
-			"queueing request %p to %s length %d state '%s'",
+			"queueing request %pK to %s length %d state '%s'",
 			request, dep->name, request->length,
 			dwc3_ep0_state_string(dwc->ep0state));
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index f90d0c9..3c38ee1 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -937,7 +937,7 @@
 	struct usb_gadget	*gadget = &dwc->gadget;
 	enum usb_device_speed	speed = gadget->speed;
 
-	dwc3_trace(trace_dwc3_gadget, "%s: req %p dma %08llx length %d%s",
+	dwc3_trace(trace_dwc3_gadget, "%s: req %pK dma %08llx length %d%s%s",
 			dep->name, req, (unsigned long long) dma,
 			length, chain ? " chain" : "");
 
@@ -1293,7 +1293,7 @@
 
 	if (!dep->endpoint.desc) {
 		dwc3_trace(trace_dwc3_gadget,
-				"trying to queue request %p to disabled %s",
+				"trying to queue request %pK to disabled %s",
 				&req->request, dep->endpoint.name);
 		return -ESHUTDOWN;
 	}
@@ -1432,13 +1432,13 @@
 
 	spin_lock_irqsave(&dwc->lock, flags);
 	if (!dep->endpoint.desc) {
-		dev_dbg(dwc->dev, "trying to queue request %p to disabled %s\n",
+		dev_dbg(dwc->dev, "trying to queue request %pK to disabled %s\n",
 				request, ep->name);
 		ret = -ESHUTDOWN;
 		goto out;
 	}
 
-	if (WARN(req->dep != dep, "request %p belongs to '%s'\n",
+	if (WARN(req->dep != dep, "request %pK belongs to '%s'\n",
 				request, req->dep->name)) {
 		ret = -EINVAL;
 		goto out;
diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h
index 1f75b58..bc2a8bc 100644
--- a/drivers/usb/dwc3/io.h
+++ b/drivers/usb/dwc3/io.h
@@ -40,7 +40,7 @@
 	 * documentation, so we revert it back to the proper addresses, the
 	 * same way they are described on SNPS documentation
 	 */
-	dwc3_trace(trace_dwc3_readl, "addr %p value %08x",
+	dwc3_trace(trace_dwc3_readl, "addr %pK value %08x",
 			base - DWC3_GLOBALS_REGS_START + offset, value);
 
 	return value;
@@ -60,7 +60,7 @@
 	 * documentation, so we revert it back to the proper addresses, the
 	 * same way they are described on SNPS documentation
 	 */
-	dwc3_trace(trace_dwc3_writel, "addr %p value %08x",
+	dwc3_trace(trace_dwc3_writel, "addr %pK value %08x",
 			base - DWC3_GLOBALS_REGS_START + offset, value);
 }
 
diff --git a/drivers/usb/dwc3/trace.h b/drivers/usb/dwc3/trace.h
index 88f5fb8..d9873ad 100644
--- a/drivers/usb/dwc3/trace.h
+++ b/drivers/usb/dwc3/trace.h
@@ -137,7 +137,7 @@
 		__entry->short_not_ok = req->request.short_not_ok;
 		__entry->no_interrupt = req->request.no_interrupt;
 	),
-	TP_printk("%s: req %p length %u/%u %s%s%s ==> %d",
+	TP_printk("%s: req %pK length %u/%u %s%s%s ==> %d",
 		__get_str(name), __entry->req, __entry->actual, __entry->length,
 		__entry->zero ? "Z" : "z",
 		__entry->short_not_ok ? "S" : "s",
@@ -253,7 +253,7 @@
 		__entry->size = trb->size;
 		__entry->ctrl = trb->ctrl;
 	),
-	TP_printk("%s: %d/%d trb %p buf %08x%08x size %d ctrl %08x (%c%c%c%c:%c%c:%s)",
+	TP_printk("%s: %d/%d trb %pK buf %08x%08x size %d ctrl %08x (%c%c%c%c:%c%c:%s)",
 		__get_str(name), __entry->queued, __entry->allocated,
 		__entry->trb, __entry->bph, __entry->bpl,
 		__entry->size, __entry->ctrl,
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index f6fc30a..ab2c623 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -20,6 +20,7 @@
 
 #include <linux/usb/composite.h>
 #include <linux/usb/otg.h>
+#include <linux/usb/msm_hsusb.h>
 #include <asm/unaligned.h>
 
 #include "u_os_desc.h"
@@ -856,6 +857,11 @@
 
 	DBG(cdev, "reset config\n");
 
+	if (!cdev->config) {
+		pr_err("%s:cdev->config is already NULL\n", __func__);
+		return;
+	}
+
 	list_for_each_entry(f, &cdev->config->functions, list) {
 		if (f->disable)
 			f->disable(f);
@@ -1120,8 +1126,14 @@
 
 	spin_lock_irqsave(&cdev->lock, flags);
 
-	if (cdev->config == config)
+	if (cdev->config == config) {
+		if (cdev->gadget->is_chipidea && !cdev->suspended) {
+			spin_unlock_irqrestore(&cdev->lock, flags);
+			msm_do_bam_disable_enable(CI_CTRL);
+			spin_lock_irqsave(&cdev->lock, flags);
+		}
 		reset_config(cdev);
+	}
 
 	spin_unlock_irqrestore(&cdev->lock, flags);
 
@@ -2161,8 +2173,14 @@
 	 * disconnect callbacks?
 	 */
 	spin_lock_irqsave(&cdev->lock, flags);
-	if (cdev->config)
+	if (cdev->config) {
+		if (gadget->is_chipidea && !cdev->suspended) {
+			spin_unlock_irqrestore(&cdev->lock, flags);
+			msm_do_bam_disable_enable(CI_CTRL);
+			spin_lock_irqsave(&cdev->lock, flags);
+		}
 		reset_config(cdev);
+	}
 	if (cdev->driver->disconnect)
 		cdev->driver->disconnect(cdev);
 	if (cdev->delayed_status != 0) {
diff --git a/drivers/usb/gadget/function/f_accessory.c b/drivers/usb/gadget/function/f_accessory.c
index 45339c8..bf37438 100644
--- a/drivers/usb/gadget/function/f_accessory.c
+++ b/drivers/usb/gadget/function/f_accessory.c
@@ -887,6 +887,12 @@
 	u16	w_length = le16_to_cpu(ctrl->wLength);
 	unsigned long flags;
 
+	/*
+	 * If instance is not created which is the case in power off charging
+	 * mode, dev will be NULL. Hence return error if it is the case.
+	 */
+	if (!dev)
+		return -ENODEV;
 /*
 	printk(KERN_INFO "acc_ctrlrequest "
 			"%02x.%02x v%04x i%04x l%u\n",
diff --git a/drivers/usb/gadget/function/f_audio_source.c b/drivers/usb/gadget/function/f_audio_source.c
index aaa15da..3f60bf7 100644
--- a/drivers/usb/gadget/function/f_audio_source.c
+++ b/drivers/usb/gadget/function/f_audio_source.c
@@ -337,14 +337,15 @@
 
 /*--------------------------------------------------------------------------*/
 
-static struct usb_request *audio_request_new(struct usb_ep *ep, int buffer_size)
+static struct usb_request *audio_request_new(struct usb_ep *ep, int buffer_size,
+					size_t extra_buf_alloc)
 {
 	struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL);
 
 	if (!req)
 		return NULL;
 
-	req->buf = kmalloc(buffer_size, GFP_KERNEL);
+	req->buf = kmalloc(buffer_size + extra_buf_alloc, GFP_KERNEL);
 	if (!req->buf) {
 		usb_ep_free_request(ep, req);
 		return NULL;
@@ -748,7 +749,8 @@
 	f->ss_descriptors = ss_audio_desc;
 
 	for (i = 0, status = 0; i < IN_EP_REQ_COUNT && status == 0; i++) {
-		req = audio_request_new(ep, IN_EP_MAX_PACKET_SIZE);
+		req = audio_request_new(ep, IN_EP_MAX_PACKET_SIZE,
+						cdev->gadget->extra_buf_alloc);
 		if (req) {
 			req->context = audio;
 			req->complete = audio_data_complete;
diff --git a/drivers/usb/gadget/function/f_ccid.c b/drivers/usb/gadget/function/f_ccid.c
index dbf72ab..76b181a 100644
--- a/drivers/usb/gadget/function/f_ccid.c
+++ b/drivers/usb/gadget/function/f_ccid.c
@@ -337,7 +337,8 @@
 }
 
 static struct usb_request *
-ccid_request_alloc(struct usb_ep *ep, size_t len, gfp_t kmalloc_flags)
+ccid_request_alloc(struct usb_ep *ep, size_t len, size_t extra_buf_alloc,
+							gfp_t kmalloc_flags)
 {
 	struct usb_request *req;
 
@@ -345,7 +346,7 @@
 
 	if (req != NULL) {
 		req->length = len;
-		req->buf = kmalloc(len, kmalloc_flags);
+		req->buf = kmalloc(len + extra_buf_alloc, kmalloc_flags);
 		if (req->buf == NULL) {
 			usb_ep_free_request(ep, req);
 			req = NULL;
@@ -467,7 +468,8 @@
 	int i;
 
 	ccid_dev->notify_req = ccid_request_alloc(ccid_dev->notify,
-			sizeof(struct usb_ccid_notification), GFP_ATOMIC);
+			sizeof(struct usb_ccid_notification),
+			cdev->gadget->extra_buf_alloc, GFP_ATOMIC);
 	if (IS_ERR(ccid_dev->notify_req)) {
 		pr_err("%s: unable to allocate memory for notify req\n",
 				__func__);
@@ -478,7 +480,7 @@
 
 	/* now allocate requests for our endpoints */
 	req = ccid_request_alloc(ccid_dev->out, BULK_OUT_BUFFER_SIZE,
-							GFP_ATOMIC);
+							0, GFP_ATOMIC);
 	if (IS_ERR(req)) {
 		pr_err("%s: unable to allocate memory for out req\n",
 				__func__);
@@ -491,7 +493,7 @@
 
 	for (i = 0; i < TX_REQ_MAX; i++) {
 		req = ccid_request_alloc(ccid_dev->in, BULK_IN_BUFFER_SIZE,
-				GFP_ATOMIC);
+				cdev->gadget->extra_buf_alloc, GFP_ATOMIC);
 		if (IS_ERR(req)) {
 			pr_err("%s: unable to allocate memory for in req\n",
 					__func__);
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 25b2cdd..1979156 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -218,9 +218,23 @@
 };
 
 static inline struct usb_request *midi_alloc_ep_req(struct usb_ep *ep,
-						    unsigned length)
+				unsigned int length, size_t extra_buf_alloc)
 {
-	return alloc_ep_req(ep, length);
+	struct usb_request      *req;
+
+	req = usb_ep_alloc_request(ep, GFP_ATOMIC);
+	if (!req)
+		return NULL;
+
+	req->length = usb_endpoint_dir_out(ep->desc) ?
+				usb_ep_align(ep, length) : length;
+	req->buf = kmalloc(req->length + extra_buf_alloc, GFP_ATOMIC);
+	if (!req->buf) {
+		usb_ep_free_request(ep, req);
+		return NULL;
+	}
+
+	return req;
 }
 
 static const uint8_t f_midi_cin_length[] = {
@@ -374,7 +388,8 @@
 	/* pre-allocate write usb requests to use on f_midi_transmit. */
 	while (kfifo_avail(&midi->in_req_fifo)) {
 		struct usb_request *req =
-			midi_alloc_ep_req(midi->in_ep, midi->buflen);
+			midi_alloc_ep_req(midi->in_ep, midi->buflen,
+						midi->gadget->extra_buf_alloc);
 
 		if (req == NULL)
 			return -ENOMEM;
@@ -388,7 +403,7 @@
 	/* allocate a bunch of read buffers and queue them all at once. */
 	for (i = 0; i < midi->qlen && err == 0; i++) {
 		struct usb_request *req =
-			midi_alloc_ep_req(midi->out_ep, midi->buflen);
+			midi_alloc_ep_req(midi->out_ep, midi->buflen, 0);
 
 		if (req == NULL)
 			return -ENOMEM;
diff --git a/drivers/usb/gadget/function/u_qdss.c b/drivers/usb/gadget/function/u_qdss.c
index d445e51..6e60258 100644
--- a/drivers/usb/gadget/function/u_qdss.c
+++ b/drivers/usb/gadget/function/u_qdss.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
@@ -20,6 +20,7 @@
 {
 	struct usb_request *req = NULL;
 	struct f_qdss *qdss = data_ep->driver_data;
+	struct usb_gadget *gadget = qdss->gadget;
 	u32 sps_params = 0;
 
 	pr_debug("send_sps_req\n");
@@ -30,9 +31,17 @@
 		return -ENOMEM;
 	}
 
-	req->length = 32*1024;
-	sps_params = MSM_SPS_MODE | MSM_DISABLE_WB |
-			qdss->bam_info.usb_bam_pipe_idx;
+	if (!gadget->is_chipidea) {
+		req->length = 32*1024;
+		sps_params = MSM_SPS_MODE | MSM_DISABLE_WB |
+				qdss->bam_info.usb_bam_pipe_idx;
+	} else {
+		/* non DWC3 BAM requires req->length to be 0 */
+		req->length = 0;
+		sps_params = (MSM_SPS_MODE | qdss->bam_info.usb_bam_pipe_idx |
+				MSM_VENDOR_ID) & ~MSM_IS_FINITE_TRANSFER;
+	}
+
 	req->udc_priv = sps_params;
 	qdss->endless_req = req;
 
@@ -107,10 +116,12 @@
 				NULL, bam_info.data_fifo, NULL);
 
 		alloc_sps_req(qdss->port.data);
-		msm_data_fifo_config(qdss->port.data,
-			bam_info.data_fifo->iova,
-			bam_info.data_fifo->size,
-			bam_info.usb_bam_pipe_idx);
+		if (!gadget->is_chipidea)
+			msm_data_fifo_config(qdss->port.data,
+				bam_info.data_fifo->iova,
+				bam_info.data_fifo->size,
+				bam_info.usb_bam_pipe_idx);
+
 		init_data(qdss->port.data);
 
 		res = usb_bam_connect(usb_bam_type, idx,
@@ -132,8 +143,14 @@
 static int init_data(struct usb_ep *ep)
 {
 	struct f_qdss *qdss = ep->driver_data;
+	struct usb_gadget *gadget = qdss->gadget;
 	int res = 0;
 
+	if (gadget->is_chipidea) {
+		pr_debug("QDSS is used with non DWC3 core\n");
+		return res;
+	}
+
 	pr_debug("init_data\n");
 
 	res = msm_ep_config(ep, qdss->endless_req);
@@ -145,8 +162,13 @@
 
 int uninit_data(struct usb_ep *ep)
 {
+	struct f_qdss *qdss = ep->driver_data;
+	struct usb_gadget *gadget = qdss->gadget;
 	int res = 0;
 
+	if (gadget->is_chipidea)
+		return res;
+
 	pr_err("uninit_data\n");
 
 	res = msm_ep_unconfig(ep);
diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 3ff6468..73ab200 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -89,7 +89,7 @@
 static void __maybe_unused
 dbg_qtd(const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd)
 {
-	ehci_dbg(ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd,
+	ehci_dbg(ehci, "%s td %pK n%08x %08x t%08x p0=%08x\n", label, qtd,
 		hc32_to_cpup(ehci, &qtd->hw_next),
 		hc32_to_cpup(ehci, &qtd->hw_alt_next),
 		hc32_to_cpup(ehci, &qtd->hw_token),
@@ -107,7 +107,7 @@
 {
 	struct ehci_qh_hw *hw = qh->hw;
 
-	ehci_dbg(ehci, "%s qh %p n%08x info %x %x qtd %x\n", label,
+	ehci_dbg(ehci, "%s qh %pK n%08x info %x %x qtd %x\n", label,
 		qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current);
 	dbg_qtd("overlay", ehci, (struct ehci_qtd *) &hw->hw_qtd_next);
 }
@@ -115,7 +115,7 @@
 static void __maybe_unused
 dbg_itd(const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd)
 {
-	ehci_dbg(ehci, "%s [%d] itd %p, next %08x, urb %p\n",
+	ehci_dbg(ehci, "%s [%d] itd %pK, next %08x, urb %p\n",
 		label, itd->frame, itd, hc32_to_cpu(ehci, itd->hw_next),
 		itd->urb);
 	ehci_dbg(ehci,
@@ -146,7 +146,7 @@
 static void __maybe_unused
 dbg_sitd(const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd)
 {
-	ehci_dbg(ehci, "%s [%d] sitd %p, next %08x, urb %p\n",
+	ehci_dbg(ehci, "%s [%d] sitd %pK, next %08x, urb %p\n",
 		label, sitd->frame, sitd, hc32_to_cpu(ehci, sitd->hw_next),
 		sitd->urb);
 	ehci_dbg(ehci,
@@ -406,7 +406,7 @@
 	scratch = hc32_to_cpup(ehci, &hw->hw_info1);
 	hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &hw->hw_current) : 0;
 	temp = scnprintf(next, size,
-			"qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)"
+			"qh/%pK dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)"
 			" [cur %08x next %08x buf[0] %08x]",
 			qh, scratch & 0x007f,
 			speed_char (scratch),
@@ -454,7 +454,7 @@
 			break;
 		}
 		temp = scnprintf(next, size,
-				"\n\t%p%c%s len=%d %08x urb %p"
+				"\n\t%pK%c%s len=%d %08x urb %pK"
 				" [td %08x buf[0] %08x]",
 				td, mark, type,
 				(scratch >> 16) & 0x7fff,
@@ -674,7 +674,7 @@
 			switch (hc32_to_cpu(ehci, tag)) {
 			case Q_TYPE_QH:
 				hw = p.qh->hw;
-				temp = scnprintf(next, size, " qh%d-%04x/%p",
+				temp = scnprintf(next, size, " qh%d-%04x/%pK",
 						p.qh->ps.period,
 						hc32_to_cpup(ehci,
 							&hw->hw_info2)
@@ -709,21 +709,21 @@
 				p = p.qh->qh_next;
 				break;
 			case Q_TYPE_FSTN:
-				temp = scnprintf(next, size,
-					" fstn-%8x/%p", p.fstn->hw_prev,
+				temp = scnprintf (next, size,
+					" fstn-%8x/%pK", p.fstn->hw_prev,
 					p.fstn);
 				tag = Q_NEXT_TYPE(ehci, p.fstn->hw_next);
 				p = p.fstn->fstn_next;
 				break;
 			case Q_TYPE_ITD:
-				temp = scnprintf(next, size,
-					" itd/%p", p.itd);
+				temp = scnprintf (next, size,
+					" itd/%pK", p.itd);
 				tag = Q_NEXT_TYPE(ehci, p.itd->hw_next);
 				p = p.itd->itd_next;
 				break;
 			case Q_TYPE_SITD:
-				temp = scnprintf(next, size,
-					" sitd%d-%04x/%p",
+				temp = scnprintf (next, size,
+					" sitd%d-%04x/%pK",
 					p.sitd->stream->ps.period,
 					hc32_to_cpup(ehci, &p.sitd->hw_uframe)
 						& 0x0000ffff,
@@ -895,7 +895,7 @@
 	}
 
 	if (!list_empty(&ehci->async_unlink)) {
-		temp = scnprintf(next, size, "async unlink qh %p\n",
+		temp = scnprintf(next, size, "async unlink qh %pK\n",
 				list_first_entry(&ehci->async_unlink,
 						struct ehci_qh, unlink_node));
 		size -= temp;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 0630648..142fe51 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1017,7 +1017,7 @@
 		/* caller was supposed to have unlinked any requests;
 		 * that's not our job.  just leak this memory.
 		 */
-		ehci_err (ehci, "qh %p (#%02x) state %d%s\n",
+		ehci_err (ehci, "qh %pK (#%02x) state %d%s\n",
 			qh, ep->desc.bEndpointAddress, qh->qh_state,
 			list_empty (&qh->qtd_list) ? "" : "(has tds)");
 		break;
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index eca3710..484d9d7 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -268,7 +268,7 @@
 
 #ifdef EHCI_URB_TRACE
 	ehci_dbg (ehci,
-		"%s %s urb %p ep%d%s status %d len %d/%d\n",
+		"%s %s urb %pK ep%d%s status %d len %d/%d\n",
 		__func__, urb->dev->devpath, urb,
 		usb_pipeendpoint (urb->pipe),
 		usb_pipein (urb->pipe) ? "in" : "out",
@@ -354,7 +354,7 @@
 			/* Report Data Buffer Error: non-fatal but useful */
 			if (token & QTD_STS_DBE)
 				ehci_dbg(ehci,
-					"detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n",
+					"detected DataBufferErr for urb %pK ep%d%s len %d, qtd %pK [qh %pK]\n",
 					urb,
 					usb_endpoint_num(&urb->ep->desc),
 					usb_endpoint_dir_in(&urb->ep->desc) ? "in" : "out",
@@ -933,7 +933,7 @@
 		}
 		break;
 	default:
-		ehci_dbg(ehci, "bogus dev %p speed %d\n", urb->dev,
+		ehci_dbg(ehci, "bogus dev %pK speed %d\n", urb->dev,
 			urb->dev->speed);
 done:
 		qh_destroy(ehci, qh);
@@ -1121,7 +1121,7 @@
 		struct ehci_qtd *qtd;
 		qtd = list_entry(qtd_list->next, struct ehci_qtd, qtd_list);
 		ehci_dbg(ehci,
-			 "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
+			 "%s %s urb %pK ep%d%s len %d, qtd %pK [qh %pK]\n",
 			 __func__, urb->dev->devpath, urb,
 			 epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
 			 urb->transfer_buffer_length,
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
index 1dfe54f..414e122 100644
--- a/drivers/usb/host/ehci-sched.c
+++ b/drivers/usb/host/ehci-sched.c
@@ -549,7 +549,7 @@
 	unsigned	period = qh->ps.period;
 
 	dev_dbg(&qh->ps.udev->dev,
-		"link qh%d-%04x/%p start %d [%d/%d us]\n",
+		"link qh%d-%04x/%pK start %d [%d/%d us]\n",
 		period, hc32_to_cpup(ehci, &qh->hw->hw_info2)
 			& (QH_CMASK | QH_SMASK),
 		qh, qh->ps.phase, qh->ps.usecs, qh->ps.c_usecs);
@@ -642,7 +642,7 @@
 		: (qh->ps.usecs * 8);
 
 	dev_dbg(&qh->ps.udev->dev,
-		"unlink qh%d-%04x/%p start %d [%d/%d us]\n",
+		"unlink qh%d-%04x/%pK start %d [%d/%d us]\n",
 		qh->ps.period,
 		hc32_to_cpup(ehci, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK),
 		qh, qh->ps.phase, qh->ps.usecs, qh->ps.c_usecs);
@@ -752,7 +752,7 @@
 		 * FIXME kill the now-dysfunctional queued urbs
 		 */
 		else {
-			ehci_err(ehci, "can't reschedule qh %p, err %d\n",
+			ehci_err(ehci, "can't reschedule qh %pK, err %d\n",
 					qh, rc);
 		}
 	}
@@ -870,7 +870,7 @@
 
 	/* reuse the previous schedule slots, if we can */
 	if (qh->ps.phase != NO_FRAME) {
-		ehci_dbg(ehci, "reused qh %p schedule\n", qh);
+		ehci_dbg(ehci, "reused qh %pK schedule\n", qh);
 		return 0;
 	}
 
@@ -1550,7 +1550,7 @@
 
 			/* no room in the schedule */
 			if (!done) {
-				ehci_dbg(ehci, "iso sched full %p", urb);
+				ehci_dbg(ehci, "iso sched full %pK", urb);
 				status = -ENOSPC;
 				goto fail;
 			}
@@ -1604,7 +1604,7 @@
 
 	/* Is the schedule about to wrap around? */
 	if (unlikely(!empty && start < period)) {
-		ehci_dbg(ehci, "request %p would overflow (%u-%u < %u mod %u)\n",
+		ehci_dbg(ehci, "request %pK would overflow (%u-%u < %u mod %u)\n",
 				urb, stream->next_uframe, base, period, mod);
 		status = -EFBIG;
 		goto fail;
@@ -1633,7 +1633,7 @@
 	/* How many uframes and packets do we need to skip? */
 	skip = (now2 - start + period - 1) & -period;
 	if (skip >= span) {		/* Entirely in the past? */
-		ehci_dbg(ehci, "iso underrun %p (%u+%u < %u) [%u]\n",
+		ehci_dbg(ehci, "iso underrun %pK (%u+%u < %u) [%u]\n",
 				urb, start + base, span - period, now2 + base,
 				base);
 
@@ -1660,7 +1660,7 @@
  use_start:
 	/* Tried to schedule too far into the future? */
 	if (unlikely(start + span - period >= mod + wrap)) {
-		ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n",
+		ehci_dbg(ehci, "request %pK would overflow (%u+%u >= %u)\n",
 				urb, start, span - period, mod + wrap);
 		status = -EFBIG;
 		goto fail;
@@ -1956,7 +1956,7 @@
 
 #ifdef EHCI_URB_TRACE
 	ehci_dbg(ehci,
-		"%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n",
+		"%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%pK]\n",
 		__func__, urb->dev->devpath, urb,
 		usb_pipeendpoint(urb->pipe),
 		usb_pipein(urb->pipe) ? "in" : "out",
@@ -2336,8 +2336,8 @@
 	}
 
 #ifdef EHCI_URB_TRACE
-	ehci_dbg(ehci,
-		"submit %p dev%s ep%d%s-iso len %d\n",
+	ehci_dbg (ehci,
+		"submit %pK dev%s ep%d%s-iso len %d\n",
 		urb, urb->dev->devpath,
 		usb_pipeendpoint(urb->pipe),
 		usb_pipein(urb->pipe) ? "in" : "out",
diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
index c3eded3..5617622 100644
--- a/drivers/usb/host/ohci-dbg.c
+++ b/drivers/usb/host/ohci-dbg.c
@@ -256,7 +256,7 @@
 {
 	u32	tmp = hc32_to_cpup (ohci, &td->hwINFO);
 
-	ohci_dbg (ohci, "%s td %p%s; urb %p index %d; hw next td %08x\n",
+	ohci_dbg (ohci, "%s td %pK%s; urb %pK index %d; hw next td %08x\n",
 		label, td,
 		(tmp & TD_DONE) ? " (DONE)" : "",
 		td->urb, td->index,
@@ -314,7 +314,7 @@
 	u32	tmp = hc32_to_cpu (ohci, ed->hwINFO);
 	char	*type = "";
 
-	ohci_dbg (ohci, "%s, ed %p state 0x%x type %s; next ed %08x\n",
+	ohci_dbg (ohci, "%s, ed %pK state 0x%x type %s; next ed %08x\n",
 		label,
 		ed, ed->state, edstring (ed->type),
 		hc32_to_cpup (ohci, &ed->hwNextED));
@@ -415,7 +415,7 @@
 		struct td	*td;
 
 		temp = scnprintf (buf, size,
-			"ed/%p %cs dev%d ep%d%s max %d %08x%s%s %s",
+			"ed/%pK %cs dev%d ep%d%s max %d %08x%s%s %s",
 			ed,
 			(info & ED_LOWSPEED) ? 'l' : 'f',
 			info & 0x7f,
@@ -437,7 +437,7 @@
 			cbp = hc32_to_cpup (ohci, &td->hwCBP);
 			be = hc32_to_cpup (ohci, &td->hwBE);
 			temp = scnprintf (buf, size,
-					"\n\ttd %p %s %d cc=%x urb %p (%08x)",
+					"\n\ttd %pK %s %d cc=%x urb %pK (%08x)",
 					td,
 					({ char *pid;
 					switch (info & TD_DP) {
@@ -516,7 +516,7 @@
 		next += temp;
 
 		do {
-			temp = scnprintf (next, size, " ed%d/%p",
+			temp = scnprintf (next, size, " ed%d/%pK",
 				ed->interval, ed);
 			size -= temp;
 			next += temp;
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index f6c7a27..5635a33 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -279,7 +279,7 @@
 						ed->interval);
 				if (urb_priv->td_cnt >= urb_priv->length) {
 					++urb_priv->td_cnt;	/* Mark it */
-					ohci_dbg(ohci, "iso underrun %p (%u+%u < %u)\n",
+					ohci_dbg(ohci, "iso underrun %pK (%u+%u < %u)\n",
 							urb, frame, length,
 							next);
 				}
@@ -387,7 +387,7 @@
 		/* caller was supposed to have unlinked any requests;
 		 * that's not our job.  can't recover; must leak ed.
 		 */
-		ohci_err (ohci, "leak ed %p (#%02x) state %d%s\n",
+		ohci_err (ohci, "leak ed %pK (#%02x) state %d%s\n",
 			ed, ep->desc.bEndpointAddress, ed->state,
 			list_empty (&ed->td_list) ? "" : " (has tds)");
 		td_free (ohci, ed->dummy);
@@ -1028,7 +1028,7 @@
 		case ED_UNLINK:
 			break;
 		default:
-			ohci_dbg(ohci, "bogus ed %p state %d\n",
+			ohci_dbg(ohci, "bogus ed %pK state %d\n",
 					ed, ed->state);
 		}
 
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index c9e315c..99576f3 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -109,7 +109,7 @@
 	if (*prev)
 		*prev = td->td_hash;
 	else if ((td->hwINFO & cpu_to_hc32(hc, TD_DONE)) != 0)
-		ohci_dbg (hc, "no hash for td %p\n", td);
+		ohci_dbg (hc, "no hash for td %pK\n", td);
 	dma_pool_free (hc->td_cache, td, td->td_dma);
 }
 
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 641fed6..4365dc3 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -143,7 +143,7 @@
 {
 	unsigned	i;
 
-	ohci_dbg(ohci, "link %sed %p branch %d [%dus.], interval %d\n",
+	ohci_dbg(ohci, "link %sed %pK branch %d [%dus.], interval %d\n",
 		(ed->hwINFO & cpu_to_hc32 (ohci, ED_ISO)) ? "iso " : "",
 		ed, ed->branch, ed->load, ed->interval);
 
@@ -287,7 +287,7 @@
 	}
 	ohci_to_hcd(ohci)->self.bandwidth_allocated -= ed->load / ed->interval;
 
-	ohci_dbg(ohci, "unlink %sed %p branch %d [%dus.], interval %d\n",
+	ohci_dbg(ohci, "unlink %sed %pK branch %d [%dus.], interval %d\n",
 		(ed->hwINFO & cpu_to_hc32 (ohci, ED_ISO)) ? "iso " : "",
 		ed, ed->branch, ed->load, ed->interval);
 }
@@ -787,7 +787,7 @@
 
 		if (cc != TD_CC_NOERROR)
 			ohci_dbg(ohci,
-				"urb %p iso td %p (%d) len %d cc %d\n",
+				"urb %pK iso td %pK (%d) len %d cc %d\n",
 				urb, td, 1 + td->index, dlen, cc);
 
 	/* BULK, INT, CONTROL ... drivers see aggregate length/status,
@@ -819,7 +819,7 @@
 
 		if (cc != TD_CC_NOERROR && cc < 0x0E)
 			ohci_dbg(ohci,
-				"urb %p td %p (%d) cc %d, len=%d/%d\n",
+				"urb %pK td %pK (%d) cc %d, len=%d/%d\n",
 				urb, td, 1 + td->index, cc,
 				urb->actual_length,
 				urb->transfer_buffer_length);
@@ -885,7 +885,7 @@
 		/* fallthrough */
 	default:
 		ohci_dbg (ohci,
-			"urb %p path %s ep%d%s %08x cc %d --> status %d\n",
+			"urb %pK path %s ep%d%s %08x cc %d --> status %d\n",
 			urb, urb->dev->devpath,
 			usb_pipeendpoint (urb->pipe),
 			usb_pipein (urb->pipe) ? "in" : "out",
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 9c6635d..dcb6efa 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -47,7 +47,7 @@
 	u32 status, token;
 
 	status = td_status(uhci, td);
-	out += sprintf(out, "%*s[%p] link (%08x) ", space, "", td,
+	out += sprintf(out, "%*s[%pK] link (%08x) ", space, "", td,
 		hc32_to_cpu(uhci, td->link));
 	out += sprintf(out, "e%d %s%s%s%s%s%s%s%s%s%sLength=%x ",
 		((status >> 27) & 3),
@@ -105,9 +105,9 @@
 	char *ptype;
 
 
-	out += sprintf(out, "urb_priv [%p] ", urbp);
-	out += sprintf(out, "urb [%p] ", urbp->urb);
-	out += sprintf(out, "qh [%p] ", urbp->qh);
+	out += sprintf(out, "urb_priv [%pK] ", urbp);
+	out += sprintf(out, "urb [%pK] ", urbp->urb);
+	out += sprintf(out, "qh [%pK] ", urbp->qh);
 	out += sprintf(out, "Dev=%d ", usb_pipedevice(urbp->urb->pipe));
 	out += sprintf(out, "EP=%x(%s) ", usb_pipeendpoint(urbp->urb->pipe),
 			(usb_pipein(urbp->urb->pipe) ? "IN" : "OUT"));
@@ -177,13 +177,13 @@
 	default: qtype = "Skel" ; break;
 	}
 
-	out += sprintf(out, "%*s[%p] %s QH link (%08x) element (%08x)\n",
+	out += sprintf(out, "%*s[%pK] %s QH link (%08x) element (%08x)\n",
 			space, "", qh, qtype,
 			hc32_to_cpu(uhci, qh->link),
 			hc32_to_cpu(uhci, element));
 	if (qh->type == USB_ENDPOINT_XFER_ISOC)
 		out += sprintf(out,
-				"%*s    period %d phase %d load %d us, frame %x desc [%p]\n",
+				"%*s    period %d phase %d load %d us, frame %x desc [%pK]\n",
 				space, "", qh->period, qh->phase, qh->load,
 				qh->iso_frame, qh->iso_packet_desc);
 	else if (qh->type == USB_ENDPOINT_XFER_INT)
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index c17ea15..11c9d7b 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -124,9 +124,9 @@
 static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
 {
 	if (!list_empty(&td->list))
-		dev_WARN(uhci_dev(uhci), "td %p still in list!\n", td);
+		dev_WARN(uhci_dev(uhci), "td %pK still in list!\n", td);
 	if (!list_empty(&td->fl_list))
-		dev_WARN(uhci_dev(uhci), "td %p still in fl_list!\n", td);
+		dev_WARN(uhci_dev(uhci), "td %pK still in fl_list!\n", td);
 
 	dma_pool_free(uhci->td_pool, td, td->dma_handle);
 }
@@ -293,7 +293,7 @@
 {
 	WARN_ON(qh->state != QH_STATE_IDLE && qh->udev);
 	if (!list_empty(&qh->queue))
-		dev_WARN(uhci_dev(uhci), "qh %p list not empty!\n", qh);
+		dev_WARN(uhci_dev(uhci), "qh %pK list not empty!\n", qh);
 
 	list_del(&qh->node);
 	if (qh->udev) {
@@ -743,7 +743,7 @@
 	struct uhci_td *td, *tmp;
 
 	if (!list_empty(&urbp->node))
-		dev_WARN(uhci_dev(uhci), "urb %p still on QH's list!\n",
+		dev_WARN(uhci_dev(uhci), "urb %pK still on QH's list!\n",
 				urbp->urb);
 
 	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
@@ -1316,7 +1316,7 @@
 			else if (!uhci_frame_before_eq(next,
 					frame + (urb->number_of_packets - 1) *
 						qh->period))
-				dev_dbg(uhci_dev(uhci), "iso underrun %p (%u+%u < %u)\n",
+				dev_dbg(uhci_dev(uhci), "iso underrun %pK (%u+%u < %u)\n",
 						urb, frame,
 						(urb->number_of_packets - 1) *
 							qh->period,
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index 3425154..a190c97 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -30,10 +30,10 @@
 {
 	u32 temp;
 
-	xhci_dbg(xhci, "// xHCI capability registers at %p:\n",
+	xhci_dbg(xhci, "// xHCI capability registers at %pK:\n",
 			xhci->cap_regs);
 	temp = readl(&xhci->cap_regs->hc_capbase);
-	xhci_dbg(xhci, "// @%p = 0x%x (CAPLENGTH AND HCIVERSION)\n",
+	xhci_dbg(xhci, "// @%pK = 0x%x (CAPLENGTH AND HCIVERSION)\n",
 			&xhci->cap_regs->hc_capbase, temp);
 	xhci_dbg(xhci, "//   CAPLENGTH: 0x%x\n",
 			(unsigned int) HC_LENGTH(temp));
@@ -42,17 +42,17 @@
 			(unsigned int) HC_VERSION(temp));
 #endif
 
-	xhci_dbg(xhci, "// xHCI operational registers at %p:\n", xhci->op_regs);
+	xhci_dbg(xhci, "// xHCI operational registers at %pK:\n", xhci->op_regs);
 
 	temp = readl(&xhci->cap_regs->run_regs_off);
-	xhci_dbg(xhci, "// @%p = 0x%x RTSOFF\n",
+	xhci_dbg(xhci, "// @%pK = 0x%x RTSOFF\n",
 			&xhci->cap_regs->run_regs_off,
 			(unsigned int) temp & RTSOFF_MASK);
-	xhci_dbg(xhci, "// xHCI runtime registers at %p:\n", xhci->run_regs);
+	xhci_dbg(xhci, "// xHCI runtime registers at %pK:\n", xhci->run_regs);
 
 	temp = readl(&xhci->cap_regs->db_off);
-	xhci_dbg(xhci, "// @%p = 0x%x DBOFF\n", &xhci->cap_regs->db_off, temp);
-	xhci_dbg(xhci, "// Doorbell array at %p:\n", xhci->dba);
+	xhci_dbg(xhci, "// @%pK = 0x%x DBOFF\n", &xhci->cap_regs->db_off, temp);
+	xhci_dbg(xhci, "// Doorbell array at %pK:\n", xhci->dba);
 }
 
 static void xhci_print_cap_regs(struct xhci_hcd *xhci)
@@ -60,7 +60,7 @@
 	u32 temp;
 	u32 hci_version;
 
-	xhci_dbg(xhci, "xHCI capability registers at %p:\n", xhci->cap_regs);
+	xhci_dbg(xhci, "xHCI capability registers at %pK:\n", xhci->cap_regs);
 
 	temp = readl(&xhci->cap_regs->hc_capbase);
 	hci_version = HC_VERSION(temp);
@@ -157,7 +157,7 @@
 
 static void xhci_print_op_regs(struct xhci_hcd *xhci)
 {
-	xhci_dbg(xhci, "xHCI operational registers at %p:\n", xhci->op_regs);
+	xhci_dbg(xhci, "xHCI operational registers at %pK:\n", xhci->op_regs);
 	xhci_print_command_reg(xhci);
 	xhci_print_status(xhci);
 }
@@ -178,7 +178,7 @@
 	addr = &xhci->op_regs->port_status_base;
 	for (i = 0; i < ports; i++) {
 		for (j = 0; j < NUM_PORT_REGS; ++j) {
-			xhci_dbg(xhci, "%p port %s reg = 0x%x\n",
+			xhci_dbg(xhci, "%pK port %s reg = 0x%x\n",
 					addr, names[j],
 					(unsigned int) readl(addr));
 			addr++;
@@ -198,35 +198,35 @@
 	if (temp == XHCI_INIT_VALUE)
 		return;
 
-	xhci_dbg(xhci, "  %p: ir_set[%i]\n", ir_set, set_num);
+	xhci_dbg(xhci, "  %pK: ir_set[%i]\n", ir_set, set_num);
 
-	xhci_dbg(xhci, "  %p: ir_set.pending = 0x%x\n", addr,
+	xhci_dbg(xhci, "  %pK: ir_set.pending = 0x%x\n", addr,
 			(unsigned int)temp);
 
 	addr = &ir_set->irq_control;
 	temp = readl(addr);
-	xhci_dbg(xhci, "  %p: ir_set.control = 0x%x\n", addr,
+	xhci_dbg(xhci, "  %pK: ir_set.control = 0x%x\n", addr,
 			(unsigned int)temp);
 
 	addr = &ir_set->erst_size;
 	temp = readl(addr);
-	xhci_dbg(xhci, "  %p: ir_set.erst_size = 0x%x\n", addr,
+	xhci_dbg(xhci, "  %pK: ir_set.erst_size = 0x%x\n", addr,
 			(unsigned int)temp);
 
 	addr = &ir_set->rsvd;
 	temp = readl(addr);
 	if (temp != XHCI_INIT_VALUE)
-		xhci_dbg(xhci, "  WARN: %p: ir_set.rsvd = 0x%x\n",
+		xhci_dbg(xhci, "  WARN: %pK: ir_set.rsvd = 0x%x\n",
 				addr, (unsigned int)temp);
 
 	addr = &ir_set->erst_base;
 	temp_64 = xhci_read_64(xhci, addr);
-	xhci_dbg(xhci, "  %p: ir_set.erst_base = @%08llx\n",
+	xhci_dbg(xhci, "  %pK: ir_set.erst_base = @%08llx\n",
 			addr, temp_64);
 
 	addr = &ir_set->erst_dequeue;
 	temp_64 = xhci_read_64(xhci, addr);
-	xhci_dbg(xhci, "  %p: ir_set.erst_dequeue = @%08llx\n",
+	xhci_dbg(xhci, "  %pK: ir_set.erst_dequeue = @%08llx\n",
 			addr, temp_64);
 }
 
@@ -235,15 +235,15 @@
 	u32 temp;
 	int i;
 
-	xhci_dbg(xhci, "xHCI runtime registers at %p:\n", xhci->run_regs);
+	xhci_dbg(xhci, "xHCI runtime registers at %pK:\n", xhci->run_regs);
 	temp = readl(&xhci->run_regs->microframe_index);
-	xhci_dbg(xhci, "  %p: Microframe index = 0x%x\n",
+	xhci_dbg(xhci, "  %pK: Microframe index = 0x%x\n",
 			&xhci->run_regs->microframe_index,
 			(unsigned int) temp);
 	for (i = 0; i < 7; ++i) {
 		temp = readl(&xhci->run_regs->rsvd[i]);
 		if (temp != XHCI_INIT_VALUE)
-			xhci_dbg(xhci, "  WARN: %p: Rsvd[%i] = 0x%x\n",
+			xhci_dbg(xhci, "  WARN: %pK: Rsvd[%i] = 0x%x\n",
 					&xhci->run_regs->rsvd[i],
 					i, (unsigned int) temp);
 	}
@@ -345,13 +345,13 @@
 
 void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring)
 {
-	xhci_dbg(xhci, "Ring deq = %p (virt), 0x%llx (dma)\n",
+	xhci_dbg(xhci, "Ring deq = %pK (virt), 0x%llx (dma)\n",
 			ring->dequeue,
 			(unsigned long long)xhci_trb_virt_to_dma(ring->deq_seg,
 							    ring->dequeue));
 	xhci_dbg(xhci, "Ring deq updated %u times\n",
 			ring->deq_updates);
-	xhci_dbg(xhci, "Ring enq = %p (virt), 0x%llx (dma)\n",
+	xhci_dbg(xhci, "Ring enq = %pK (virt), 0x%llx (dma)\n",
 			ring->enqueue,
 			(unsigned long long)xhci_trb_virt_to_dma(ring->enq_seg,
 							    ring->enqueue));
@@ -441,7 +441,7 @@
 {
 	int i;
 	for (i = 0; i < 4; ++i) {
-		xhci_dbg(xhci, "@%p (virt) @%08llx "
+		xhci_dbg(xhci, "@%pK (virt) @%08llx "
 			 "(dma) %#08llx - rsvd64[%d]\n",
 			 &ctx[4 + i], (unsigned long long)dma,
 			 ctx[4 + i], i);
@@ -480,24 +480,24 @@
 	int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params);
 
 	xhci_dbg(xhci, "Slot Context:\n");
-	xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info\n",
+	xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - dev_info\n",
 			&slot_ctx->dev_info,
 			(unsigned long long)dma, slot_ctx->dev_info);
 	dma += field_size;
-	xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_info2\n",
+	xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - dev_info2\n",
 			&slot_ctx->dev_info2,
 			(unsigned long long)dma, slot_ctx->dev_info2);
 	dma += field_size;
-	xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tt_info\n",
+	xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - tt_info\n",
 			&slot_ctx->tt_info,
 			(unsigned long long)dma, slot_ctx->tt_info);
 	dma += field_size;
-	xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - dev_state\n",
+	xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - dev_state\n",
 			&slot_ctx->dev_state,
 			(unsigned long long)dma, slot_ctx->dev_state);
 	dma += field_size;
 	for (i = 0; i < 4; ++i) {
-		xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
+		xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
 				&slot_ctx->reserved[i], (unsigned long long)dma,
 				slot_ctx->reserved[i], i);
 		dma += field_size;
@@ -528,24 +528,24 @@
 		xhci_dbg(xhci, "%s Endpoint %02d Context (ep_index %02d):\n",
 				usb_endpoint_out(epaddr) ? "OUT" : "IN",
 				epaddr & USB_ENDPOINT_NUMBER_MASK, i);
-		xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n",
+		xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - ep_info\n",
 				&ep_ctx->ep_info,
 				(unsigned long long)dma, ep_ctx->ep_info);
 		dma += field_size;
-		xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info2\n",
+		xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - ep_info2\n",
 				&ep_ctx->ep_info2,
 				(unsigned long long)dma, ep_ctx->ep_info2);
 		dma += field_size;
-		xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08llx - deq\n",
+		xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08llx - deq\n",
 				&ep_ctx->deq,
 				(unsigned long long)dma, ep_ctx->deq);
 		dma += 2*field_size;
-		xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - tx_info\n",
+		xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - tx_info\n",
 				&ep_ctx->tx_info,
 				(unsigned long long)dma, ep_ctx->tx_info);
 		dma += field_size;
 		for (j = 0; j < 3; ++j) {
-			xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
+			xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - rsvd[%d]\n",
 					&ep_ctx->reserved[j],
 					(unsigned long long)dma,
 					ep_ctx->reserved[j], j);
@@ -575,16 +575,16 @@
 			return;
 		}
 
-		xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - drop flags\n",
+		xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - drop flags\n",
 			 &ctrl_ctx->drop_flags, (unsigned long long)dma,
 			 ctrl_ctx->drop_flags);
 		dma += field_size;
-		xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - add flags\n",
+		xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - add flags\n",
 			 &ctrl_ctx->add_flags, (unsigned long long)dma,
 			 ctrl_ctx->add_flags);
 		dma += field_size;
 		for (i = 0; i < 6; ++i) {
-			xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - rsvd2[%d]\n",
+			xhci_dbg(xhci, "@%pK (virt) @%08llx (dma) %#08x - rsvd2[%d]\n",
 				 &ctrl_ctx->rsvd2[i], (unsigned long long)dma,
 				 ctrl_ctx->rsvd2[i], i);
 			dma += field_size;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 2911b72..588e053 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1077,7 +1077,7 @@
 
 	/* Point to output device context in dcbaa. */
 	xhci->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(dev->out_ctx->dma);
-	xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n",
+	xhci_dbg(xhci, "Set slot id %d dcbaa entry %pK to 0x%llx\n",
 		 slot_id,
 		 &xhci->dcbaa->dev_context_ptrs[slot_id],
 		 le64_to_cpu(xhci->dcbaa->dev_context_ptrs[slot_id]));
@@ -1251,7 +1251,7 @@
 		if (udev->tt->multi)
 			slot_ctx->dev_info |= cpu_to_le32(DEV_MTT);
 	}
-	xhci_dbg(xhci, "udev->tt = %p\n", udev->tt);
+	xhci_dbg(xhci, "udev->tt = %pK\n", udev->tt);
 	xhci_dbg(xhci, "udev->ttport = 0x%x\n", udev->ttport);
 
 	/* Step 4 - ring already allocated */
@@ -2101,15 +2101,15 @@
 	if (seg != result_seg) {
 		xhci_warn(xhci, "WARN: %s TRB math test %d failed!\n",
 				test_name, test_number);
-		xhci_warn(xhci, "Tested TRB math w/ seg %p and "
+		xhci_warn(xhci, "Tested TRB math w/ seg %pK and "
 				"input DMA 0x%llx\n",
 				input_seg,
 				(unsigned long long) input_dma);
-		xhci_warn(xhci, "starting TRB %p (0x%llx DMA), "
-				"ending TRB %p (0x%llx DMA)\n",
+		xhci_warn(xhci, "starting TRB %pK (0x%llx DMA), "
+				"ending TRB %pK (0x%llx DMA)\n",
 				start_trb, start_dma,
 				end_trb, end_dma);
-		xhci_warn(xhci, "Expected seg %p, got seg %p\n",
+		xhci_warn(xhci, "Expected seg %pK, got seg %pK\n",
 				result_seg, seg);
 		trb_in_td(xhci, input_seg, start_trb, end_trb, input_dma,
 			  true);
@@ -2258,7 +2258,7 @@
 		rhub = &xhci->usb2_rhub;
 	} else {
 		xhci_warn(xhci, "Ignoring unknown port speed, "
-				"Ext Cap %p, revision = 0x%x\n",
+				"Ext Cap %pK, revision = 0x%x\n",
 				addr, major_revision);
 		/* Ignoring port protocol we can't understand. FIXME */
 		return;
@@ -2273,7 +2273,7 @@
 	port_offset = XHCI_EXT_PORT_OFF(temp);
 	port_count = XHCI_EXT_PORT_COUNT(temp);
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-			"Ext Cap %p, port offset = %u, "
+			"Ext Cap %pK, port offset = %u, "
 			"count = %u, revision = 0x%x",
 			addr, port_offset, port_count, major_revision);
 	/* Port count includes the current port offset */
@@ -2335,7 +2335,7 @@
 	for (i = port_offset; i < (port_offset + port_count); i++) {
 		/* Duplicate entry.  Ignore the port if the revisions differ. */
 		if (xhci->port_array[i] != 0) {
-			xhci_warn(xhci, "Duplicate port entry, Ext Cap %p,"
+			xhci_warn(xhci, "Duplicate port entry, Ext Cap %pK,"
 					" port %u\n", addr, i);
 			xhci_warn(xhci, "Port was marked as USB %u, "
 					"duplicated as USB %u\n",
@@ -2470,7 +2470,7 @@
 				NUM_PORT_REGS*i;
 			xhci_dbg_trace(xhci, trace_xhci_dbg_init,
 					"USB 2.0 port at index %u, "
-					"addr = %p", i,
+					"addr = %pK", i,
 					xhci->usb2_ports[port_index]);
 			port_index++;
 			if (port_index == xhci->num_usb2_ports)
@@ -2491,7 +2491,7 @@
 					NUM_PORT_REGS*i;
 				xhci_dbg_trace(xhci, trace_xhci_dbg_init,
 						"USB 3.0 port at index %u, "
-						"addr = %p", i,
+						"addr = %pK", i,
 						xhci->usb3_ports[port_index]);
 				port_index++;
 				if (port_index == xhci->num_usb3_ports)
@@ -2531,7 +2531,7 @@
 	erst->num_entries = ERST_NUM_SEGS;
 	erst->erst_dma_addr = dma;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-		"intr# %d: num segs = %i, virt addr = %p, dma addr = 0x%llx",
+		"intr# %d: num segs = %i, virt addr = %pK, dma addr = 0x%llx",
 			intr_num,
 			erst->num_entries,
 			erst->entries,
@@ -2603,7 +2603,7 @@
 		|| !xhci->sec_event_ring || !xhci->sec_erst ||
 		intr_num >= xhci->max_interrupters) {
 		xhci_err(xhci,
-		"%s:state %x ir_set %p evt_ring %p erst %p intr# %d\n",
+		"%s:state %x ir_set %pK evt_ring %pK erst %pK intr# %d\n",
 		__func__, xhci->xhc_state, xhci->sec_ir_set,
 		xhci->sec_event_ring, xhci->sec_erst, intr_num);
 		return -EINVAL;
@@ -2730,7 +2730,7 @@
 	memset(xhci->dcbaa, 0, sizeof *(xhci->dcbaa));
 	xhci->dcbaa->dma = dma;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-			"// Device context base array address = 0x%llx (DMA), %p (virt)",
+			"// Device context base array address = 0x%llx (DMA), %pK (virt)",
 			(unsigned long long)xhci->dcbaa->dma, xhci->dcbaa);
 	xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr);
 
@@ -2771,7 +2771,7 @@
 	if (!xhci->cmd_ring)
 		goto fail;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-			"Allocated command ring at %p", xhci->cmd_ring);
+			"Allocated command ring at %pK", xhci->cmd_ring);
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init, "First segment DMA is 0x%llx",
 			(unsigned long long)xhci->cmd_ring->first_seg->dma);
 
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 7020b9e..f7c753f 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -290,7 +290,7 @@
 
 		i_cmd->status = COMP_CMD_STOP;
 
-		xhci_dbg(xhci, "Turn aborted command %p to no-op\n",
+		xhci_dbg(xhci, "Turn aborted command %pK to no-op\n",
 			 i_cmd->command_trb);
 		/* get cycle state from the original cmd trb */
 		cycle_state = le32_to_cpu(
@@ -555,7 +555,7 @@
 			"Cycle state = 0x%x", state->new_cycle_state);
 
 	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-			"New dequeue segment = %p (virtual)",
+			"New dequeue segment = %pK (virtual)",
 			state->new_deq_seg);
 	addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr);
 	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
@@ -590,8 +590,8 @@
 			xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 					"Cancel (unchain) link TRB");
 			xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-					"Address = %p (0x%llx dma); "
-					"in seg %p (0x%llx dma)",
+					"Address = %pK (0x%llx dma); "
+					"in seg %pK (0x%llx dma)",
 					cur_trb,
 					(unsigned long long)xhci_trb_virt_to_dma(cur_seg, cur_trb),
 					cur_seg,
@@ -752,7 +752,7 @@
 			 * short, don't muck with the stream ID after
 			 * submission.
 			 */
-			xhci_warn(xhci, "WARN Cancelled URB %p "
+			xhci_warn(xhci, "WARN Cancelled URB %pK "
 					"has invalid stream ID %u.\n",
 					cur_td->urb,
 					cur_td->urb->stream_id);
@@ -1096,7 +1096,7 @@
 				ep_ring, ep_index);
 		} else {
 			xhci_warn(xhci, "Mismatch between completed Set TR Deq Ptr command & xHCI internal state.\n");
-			xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n",
+			xhci_warn(xhci, "ep deq seg = %pK, deq ptr = %pK\n",
 				  ep->queued_deq_seg, ep->queued_deq_ptr);
 		}
 	}
@@ -2621,7 +2621,7 @@
 						 URB_SHORT_NOT_OK)) ||
 					(status != 0 &&
 					 !usb_endpoint_xfer_isoc(&urb->ep->desc)))
-				xhci_dbg(xhci, "Giveback URB %p, len = %d, "
+				xhci_dbg(xhci, "Giveback URB %pK, len = %d, "
 						"expected = %d, status = %d\n",
 						urb, urb->actual_length,
 						urb->transfer_buffer_length,
@@ -4182,7 +4182,7 @@
 	int ret;
 
 	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-		"Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), new deq ptr = %p (0x%llx dma), new cycle = %u",
+		"Set TR Deq Ptr cmd, new deq seg = %pK (0x%llx dma), new deq ptr = %pK (0x%llx dma), new cycle = %u",
 		deq_state->new_deq_seg,
 		(unsigned long long)deq_state->new_deq_seg->dma,
 		deq_state->new_deq_ptr,
@@ -4194,7 +4194,7 @@
 				    deq_state->new_deq_ptr);
 	if (addr == 0) {
 		xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n");
-		xhci_warn(xhci, "WARN deq seg = %p, deq pt = %p\n",
+		xhci_warn(xhci, "WARN deq seg = %pK, deq pt = %pK\n",
 			  deq_state->new_deq_seg, deq_state->new_deq_ptr);
 		return;
 	}
diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
index 59c0565..4ef95ac 100644
--- a/drivers/usb/host/xhci-trace.h
+++ b/drivers/usb/host/xhci-trace.h
@@ -103,7 +103,7 @@
 			((HCC_64BYTE_CONTEXT(xhci->hcc_params) + 1) * 32) *
 			((ctx->type == XHCI_CTX_TYPE_INPUT) + ep_num + 1));
 	),
-	TP_printk("\nctx_64=%d, ctx_type=%u, ctx_dma=@%llx, ctx_va=@%p",
+	TP_printk("\nctx_64=%d, ctx_type=%u, ctx_dma=@%llx, ctx_va=@%pK",
 			__entry->ctx_64, __entry->ctx_type,
 			(unsigned long long) __entry->ctx_dma, __entry->ctx_va
 	)
@@ -134,7 +134,7 @@
 		memcpy(__get_dynamic_array(trb), trb_va,
 			sizeof(struct xhci_generic_trb));
 	),
-	TP_printk("\ntrb_dma=@%llx, trb_va=@%p, status=%08x, flags=%08x",
+	TP_printk("\ntrb_dma=@%llx, trb_va=@%pK, status=%08x, flags=%08x",
 			(unsigned long long) __entry->dma, __entry->va,
 			__entry->status, __entry->flags
 	)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 84ace86..fe2bbfb 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -690,7 +690,7 @@
 
 	temp = readl(&xhci->ir_set->irq_pending);
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-			"// Enabling event ring interrupter %p by writing 0x%x to irq_pending",
+			"// Enabling event ring interrupter %pK by writing 0x%x to irq_pending",
 			xhci->ir_set, (unsigned int) ER_IRQ_ENABLE(temp));
 	writel(ER_IRQ_ENABLE(temp), &xhci->ir_set->irq_pending);
 	xhci_print_ir_set(xhci, 0);
@@ -1496,7 +1496,7 @@
 exit:
 	return ret;
 dying:
-	xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for "
+	xhci_dbg(xhci, "Ep 0x%x: URB %pK submitted for "
 			"non-responsive xHCI host.\n",
 			urb->ep->desc.bEndpointAddress, urb);
 	ret = -ESHUTDOWN;
@@ -1591,7 +1591,7 @@
 	i = urb_priv->td_cnt;
 	if (i < urb_priv->length)
 		xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-				"Cancel URB %p, dev %s, ep 0x%x, "
+				"Cancel URB %pK, dev %s, ep 0x%x, "
 				"starting at offset 0x%llx",
 				urb, urb->dev->devpath,
 				urb->ep->desc.bEndpointAddress,
@@ -1659,7 +1659,7 @@
 	if (xhci->xhc_state & XHCI_STATE_DYING)
 		return -ENODEV;
 
-	xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev);
+	xhci_dbg(xhci, "%s called for udev %pK\n", __func__, udev);
 	drop_flag = xhci_get_endpoint_flag(&ep->desc);
 	if (drop_flag == SLOT_FLAG || drop_flag == EP0_FLAG) {
 		xhci_dbg(xhci, "xHCI %s - can't drop slot or ep 0 %#x\n",
@@ -1687,7 +1687,7 @@
 	    xhci_get_endpoint_flag(&ep->desc)) {
 		/* Do not warn when called after a usb_device_reset */
 		if (xhci->devs[udev->slot_id]->eps[ep_index].ring != NULL)
-			xhci_warn(xhci, "xHCI %s called with disabled ep %p\n",
+			xhci_warn(xhci, "xHCI %s called with disabled ep %pK\n",
 				  __func__, ep);
 		return 0;
 	}
@@ -1782,7 +1782,7 @@
 	 * ignore this request.
 	 */
 	if (le32_to_cpu(ctrl_ctx->add_flags) & added_ctxs) {
-		xhci_warn(xhci, "xHCI %s called with enabled ep %p\n",
+		xhci_warn(xhci, "xHCI %s called with enabled ep %pK\n",
 				__func__, ep);
 		return 0;
 	}
@@ -2772,7 +2772,7 @@
 		(xhci->xhc_state & XHCI_STATE_REMOVING))
 		return -ENODEV;
 
-	xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev);
+	xhci_dbg(xhci, "%s called for udev %pK\n", __func__, udev);
 	virt_dev = xhci->devs[udev->slot_id];
 
 	command = xhci_alloc_command(xhci, false, true, GFP_KERNEL);
@@ -2869,7 +2869,7 @@
 		return;
 	xhci = hcd_to_xhci(hcd);
 
-	xhci_dbg(xhci, "%s called for udev %p\n", __func__, udev);
+	xhci_dbg(xhci, "%s called for udev %pK\n", __func__, udev);
 	virt_dev = xhci->devs[udev->slot_id];
 	/* Free any rings allocated for added endpoints */
 	for (i = 0; i < 31; ++i) {
@@ -2922,7 +2922,7 @@
 	if (addr == 0) {
 		xhci_warn(xhci, "WARN Cannot submit config ep after "
 				"reset ep command\n");
-		xhci_warn(xhci, "WARN deq seg = %p, deq ptr = %p\n",
+		xhci_warn(xhci, "WARN deq seg = %pK, deq ptr = %pK\n",
 				deq_state->new_deq_seg,
 				deq_state->new_deq_ptr);
 		return;
@@ -3949,7 +3949,7 @@
 	xhci_dbg_trace(xhci, trace_xhci_dbg_address,
 			"Op regs DCBAA ptr = %#016llx", temp_64);
 	xhci_dbg_trace(xhci, trace_xhci_dbg_address,
-		"Slot ID %d dcbaa entry @%p = %#016llx",
+		"Slot ID %d dcbaa entry @%pK = %#016llx",
 		udev->slot_id,
 		&xhci->dcbaa->dev_context_ptrs[udev->slot_id],
 		(unsigned long long)
diff --git a/drivers/usb/phy/phy-msm-snps-hs.c b/drivers/usb/phy/phy-msm-snps-hs.c
index a259790..28a9bf1 100644
--- a/drivers/usb/phy/phy-msm-snps-hs.c
+++ b/drivers/usb/phy/phy-msm-snps-hs.c
@@ -69,6 +69,9 @@
 #define REFCLK_SEL_MASK				(0x3 << 0)
 #define REFCLK_SEL_DEFAULT			(0x2 << 0)
 
+#define USB2PHY_USB_PHY_RTUNE_SEL		(0xb4)
+#define RTUNE_SEL				BIT(0)
+
 #define USB_HSPHY_3P3_VOL_MIN			3050000 /* uV */
 #define USB_HSPHY_3P3_VOL_MAX			3300000 /* uV */
 #define USB_HSPHY_3P3_HPM_LOAD			16000	/* uA */
@@ -390,6 +393,9 @@
 		hsusb_phy_write_seq(phy->base, phy->param_override_seq,
 				phy->param_override_seq_cnt, 0);
 
+	msm_usb_write_readback(phy->base, USB2PHY_USB_PHY_RTUNE_SEL,
+			RTUNE_SEL, RTUNE_SEL);
+
 	msm_usb_write_readback(phy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2,
 				VREGBYPASS, VREGBYPASS);
 
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index d99b582..7706a48 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -1812,51 +1812,32 @@
 {
 	struct usb_gadget *g = motg->phy.otg->gadget;
 	union power_supply_propval pval = {0};
-	bool enable;
-	int limit;
 
 	if (g && g->is_a_peripheral)
 		return;
 
 	dev_dbg(motg->phy.dev, "Requested curr from USB = %u\n", mA);
+	if (!psy) {
+		dev_dbg(motg->phy.dev, "no usb power supply registered\n");
+		return;
+	}
 
-	if (motg->cur_power == mA)
+	power_supply_get_property(psy, POWER_SUPPLY_PROP_REAL_TYPE, &pval);
+
+	if (motg->cur_power == mA || pval.intval != POWER_SUPPLY_TYPE_USB)
 		return;
 
 	dev_info(motg->phy.dev, "Avail curr from USB = %u\n", mA);
 	msm_otg_dbg_log_event(&motg->phy, "AVAIL CURR FROM USB", mA, 0);
 
-	if (!psy) {
-		dev_dbg(motg->phy.dev, "no usb power supply registered\n");
-		goto psy_error;
-	}
+	/* Set max current limit in uA */
+	pval.intval = 1000 * mA;
 
-	if (motg->cur_power == 0 && mA > 2) {
-		/* Enable charging */
-		enable = true;
-		limit = 1000 * mA;
-	} else if (motg->cur_power >= 0 && (mA == 0 || mA == 2)) {
-		/* Disable charging */
-		enable = false;
-		/* Set max current limit in uA */
-		limit = 1000 * mA;
-	} else {
-		enable = true;
-		/* Current has changed (100/2 --> 500) */
-		limit = 1000 * mA;
-	}
-
-	pval.intval = enable;
-	if (power_supply_set_property(psy, POWER_SUPPLY_PROP_ONLINE, &pval))
-		goto psy_error;
-
-	pval.intval = limit;
 	if (power_supply_set_property(psy, POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
-									&pval))
-		goto psy_error;
-
-psy_error:
-	dev_dbg(motg->phy.dev, "power supply error when setting property\n");
+								&pval)) {
+		dev_dbg(motg->phy.dev, "power supply error when setting property\n");
+		return;
+	}
 
 	motg->cur_power = mA;
 }
diff --git a/drivers/video/fbdev/msm/mdp3.c b/drivers/video/fbdev/msm/mdp3.c
index 5cf439c..00183f8 100644
--- a/drivers/video/fbdev/msm/mdp3.c
+++ b/drivers/video/fbdev/msm/mdp3.c
@@ -44,7 +44,6 @@
 
 #include <linux/msm-bus.h>
 #include <linux/msm-bus-board.h>
-#include <linux/qcom_iommu.h>
 
 #include <linux/msm_dma_iommu_mapping.h>
 
@@ -116,39 +115,14 @@
 	[MDP3_IOMMU_DOMAIN_UNSECURE] = {
 		.domain_type = MDP3_IOMMU_DOMAIN_UNSECURE,
 		.client_name = "mdp_ns",
-		.partitions = {
-			{
-				.start = SZ_128K,
-				.size = SZ_1G - SZ_128K,
-			},
-		},
 		.npartitions = 1,
+		.domain_idx = MDP3_IOMMU_DOMAIN_UNSECURE,
 	},
 	[MDP3_IOMMU_DOMAIN_SECURE] = {
 		.domain_type = MDP3_IOMMU_DOMAIN_SECURE,
 		.client_name = "mdp_secure",
-		.partitions = {
-			{
-				.start = SZ_1G,
-				.size = SZ_1G,
-			},
-		},
 		.npartitions = 1,
-	},
-};
-
-struct mdp3_iommu_ctx_map mdp3_iommu_contexts[MDP3_IOMMU_CTX_MAX] = {
-	[MDP3_IOMMU_CTX_MDP_0] = {
-		.ctx_type = MDP3_IOMMU_CTX_MDP_0,
-		.domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN_UNSECURE],
-		.ctx_name = "mdp_0",
-		.attached = 0,
-	},
-	[MDP3_IOMMU_CTX_MDP_1] = {
-		.ctx_type = MDP3_IOMMU_CTX_MDP_1,
-		.domain = &mdp3_iommu_domains[MDP3_IOMMU_DOMAIN_SECURE],
-		.ctx_name = "mdp_1",
-		.attached = 0,
+		.domain_idx = MDP3_IOMMU_DOMAIN_SECURE,
 	},
 };
 
@@ -785,7 +759,7 @@
 	ret = devm_request_irq(&mdp3_res->pdev->dev,
 				mdp3_hw->irq_info->irq,
 				mdp3_irq_handler,
-				IRQF_DISABLED, "MDP", mdp3_res);
+				0, "MDP", mdp3_res);
 	if (ret) {
 		pr_err("mdp request_irq() failed!\n");
 		return ret;
@@ -795,7 +769,6 @@
 	return 0;
 }
 
-
 static int mdp3_get_iommu_domain(u32 type)
 {
 	if (type >= MDSS_IOMMU_MAX_DOMAIN)
@@ -807,155 +780,6 @@
 	return mdp3_res->domains[type].domain_idx;
 }
 
-int mdp3_iommu_attach(int context)
-{
-	int rc = 0;
-	struct mdp3_iommu_ctx_map *context_map;
-	struct mdp3_iommu_domain_map *domain_map;
-
-	if (context >= MDP3_IOMMU_CTX_MAX)
-		return -EINVAL;
-
-	context_map = mdp3_res->iommu_contexts + context;
-	if (context_map->attached) {
-		pr_warn("mdp iommu already attached\n");
-		return 0;
-	}
-
-	domain_map = context_map->domain;
-
-	rc = iommu_attach_device(domain_map->domain, context_map->ctx);
-	if (rc) {
-		pr_err("mpd3 iommu attach failed\n");
-		return -EINVAL;
-	}
-
-	context_map->attached = true;
-	return 0;
-}
-
-int mdp3_iommu_dettach(int context)
-{
-	struct mdp3_iommu_ctx_map *context_map;
-	struct mdp3_iommu_domain_map *domain_map;
-
-	if (!mdp3_res->iommu_contexts ||
-		context >= MDP3_IOMMU_CTX_MAX)
-		return -EINVAL;
-
-	context_map = mdp3_res->iommu_contexts + context;
-	if (!context_map->attached) {
-		pr_warn("mdp iommu not attached\n");
-		return 0;
-	}
-
-	domain_map = context_map->domain;
-	iommu_detach_device(domain_map->domain, context_map->ctx);
-	context_map->attached = false;
-
-	return 0;
-}
-
-int mdp3_iommu_domain_init(void)
-{
-	struct msm_iova_layout layout;
-	int i;
-
-	if (mdp3_res->domains) {
-		pr_warn("iommu domain already initialized\n");
-		return 0;
-	}
-
-	for (i = 0; i < MDP3_IOMMU_DOMAIN_MAX; i++) {
-		int domain_idx;
-
-		layout.client_name = mdp3_iommu_domains[i].client_name;
-		layout.partitions = mdp3_iommu_domains[i].partitions;
-		layout.npartitions = mdp3_iommu_domains[i].npartitions;
-		layout.is_secure = (i == MDP3_IOMMU_DOMAIN_SECURE);
-
-		domain_idx = msm_register_domain(&layout);
-		if (IS_ERR_VALUE(domain_idx))
-			return -EINVAL;
-
-		mdp3_iommu_domains[i].domain_idx = domain_idx;
-		mdp3_iommu_domains[i].domain = msm_get_iommu_domain(domain_idx);
-		if (IS_ERR_OR_NULL(mdp3_iommu_domains[i].domain)) {
-			pr_err("unable to get iommu domain(%d)\n",
-				domain_idx);
-			if (!mdp3_iommu_domains[i].domain)
-				return -EINVAL;
-			else
-				return PTR_ERR(mdp3_iommu_domains[i].domain);
-		}
-	}
-
-	mdp3_res->domains = mdp3_iommu_domains;
-
-	return 0;
-}
-
-int mdp3_iommu_context_init(void)
-{
-	int i;
-
-	if (mdp3_res->iommu_contexts) {
-		pr_warn("iommu context already initialized\n");
-		return 0;
-	}
-
-	for (i = 0; i < MDP3_IOMMU_CTX_MAX; i++) {
-		mdp3_iommu_contexts[i].ctx =
-			msm_iommu_get_ctx(mdp3_iommu_contexts[i].ctx_name);
-
-		if (IS_ERR_OR_NULL(mdp3_iommu_contexts[i].ctx)) {
-			pr_warn("unable to get iommu ctx(%s)\n",
-				mdp3_iommu_contexts[i].ctx_name);
-			if (!mdp3_iommu_contexts[i].ctx)
-				return -EINVAL;
-			else
-				return PTR_ERR(mdp3_iommu_contexts[i].ctx);
-		}
-	}
-
-	mdp3_res->iommu_contexts = mdp3_iommu_contexts;
-
-	return 0;
-}
-
-int mdp3_iommu_init(void)
-{
-	int ret;
-
-	mutex_init(&mdp3_res->iommu_lock);
-
-	ret = mdp3_iommu_domain_init();
-	if (ret) {
-		pr_err("mdp3 iommu domain init fails\n");
-		return ret;
-	}
-
-	ret = mdp3_iommu_context_init();
-	if (ret) {
-		pr_err("mdp3 iommu context init fails\n");
-		return ret;
-	}
-	return ret;
-}
-
-void mdp3_iommu_deinit(void)
-{
-	int i;
-
-	if (!mdp3_res->domains)
-		return;
-
-	for (i = 0; i < MDP3_IOMMU_DOMAIN_MAX; i++) {
-		if (!IS_ERR_OR_NULL(mdp3_res->domains[i].domain))
-			msm_unregister_domain(mdp3_res->domains[i].domain);
-	}
-}
-
 static int mdp3_check_version(void)
 {
 	int rc;
@@ -1151,11 +975,9 @@
 		mdp3_res->ion_client = NULL;
 		return -EINVAL;
 	}
+	mutex_init(&mdp3_res->iommu_lock);
 
-	rc = mdp3_iommu_init();
-	if (rc)
-		return rc;
-
+	mdp3_res->domains = mdp3_iommu_domains;
 	mdp3_res->bus_handle = mdp3_bus_handle;
 	rc = mdp3_bus_scale_register();
 	if (rc) {
@@ -1171,18 +993,20 @@
 static void mdp3_res_deinit(void)
 {
 	struct mdss_hw *mdp3_hw;
-	int i;
+	int rc = 0;
 
 	mdp3_hw = &mdp3_res->mdp3_hw;
 	mdp3_bus_scale_unregister();
-
 	mutex_lock(&mdp3_res->iommu_lock);
-	for (i = 0; i < MDP3_IOMMU_CTX_MAX; i++)
-		mdp3_iommu_dettach(i);
+	if (mdp3_res->iommu_ref_cnt) {
+		mdp3_res->iommu_ref_cnt--;
+		if (mdp3_res->iommu_ref_cnt == 0)
+			rc = mdss_smmu_detach(mdss_res);
+		} else {
+			pr_err("iommu ref count %d\n", mdp3_res->iommu_ref_cnt);
+		}
 	mutex_unlock(&mdp3_res->iommu_lock);
 
-	mdp3_iommu_deinit();
-
 	if (!IS_ERR_OR_NULL(mdp3_res->ion_client))
 		ion_client_destroy(mdp3_res->ion_client);
 
@@ -1503,317 +1327,6 @@
 	mdp3_batfet_ctrl(enable);
 }
 
-static void mdp3_iommu_heap_unmap_iommu(struct mdp3_iommu_meta *meta)
-{
-	unsigned int domain_num;
-	unsigned int partition_num = 0;
-	struct iommu_domain *domain;
-
-	domain_num = (mdp3_res->domains +
-			MDP3_IOMMU_DOMAIN_UNSECURE)->domain_idx;
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		pr_err("Could not get domain %d. Corruption?\n", domain_num);
-		return;
-	}
-
-	iommu_unmap_range(domain, meta->iova_addr, meta->mapped_size);
-	msm_free_iova_address(meta->iova_addr, domain_num, partition_num,
-		meta->mapped_size);
-}
-
-static void mdp3_iommu_meta_destroy(struct kref *kref)
-{
-	struct mdp3_iommu_meta *meta =
-			container_of(kref, struct mdp3_iommu_meta, ref);
-
-	rb_erase(&meta->node, &mdp3_res->iommu_root);
-	mdp3_iommu_heap_unmap_iommu(meta);
-	dma_buf_put(meta->dbuf);
-	kfree(meta);
-}
-
-
-static void mdp3_iommu_meta_put(struct mdp3_iommu_meta *meta)
-{
-	/* Need to lock here to prevent race against map/unmap */
-	mutex_lock(&mdp3_res->iommu_lock);
-	kref_put(&meta->ref, mdp3_iommu_meta_destroy);
-	mutex_unlock(&mdp3_res->iommu_lock);
-}
-
-static struct mdp3_iommu_meta *mdp3_iommu_meta_lookup(struct sg_table *table)
-{
-	struct rb_root *root = &mdp3_res->iommu_root;
-	struct rb_node **p = &root->rb_node;
-	struct rb_node *parent = NULL;
-	struct mdp3_iommu_meta *entry = NULL;
-
-	while (*p) {
-		parent = *p;
-		entry = rb_entry(parent, struct mdp3_iommu_meta, node);
-
-		if (table < entry->table)
-			p = &(*p)->rb_left;
-		else if (table > entry->table)
-			p = &(*p)->rb_right;
-		else
-			return entry;
-	}
-	return NULL;
-}
-
-void mdp3_unmap_iommu(struct ion_client *client, struct ion_handle *handle)
-{
-	struct mdp3_iommu_meta *meta;
-	struct sg_table *table;
-
-	table = ion_sg_table(client, handle);
-
-	mutex_lock(&mdp3_res->iommu_lock);
-	meta = mdp3_iommu_meta_lookup(table);
-	if (!meta) {
-		WARN(1, "%s: buffer was never mapped for %pK\n", __func__,
-				handle);
-		mutex_unlock(&mdp3_res->iommu_lock);
-		return;
-	}
-	mutex_unlock(&mdp3_res->iommu_lock);
-
-	mdp3_iommu_meta_put(meta);
-}
-
-static void mdp3_iommu_meta_add(struct mdp3_iommu_meta *meta)
-{
-	struct rb_root *root = &mdp3_res->iommu_root;
-	struct rb_node **p = &root->rb_node;
-	struct rb_node *parent = NULL;
-	struct mdp3_iommu_meta *entry;
-
-	while (*p) {
-		parent = *p;
-		entry = rb_entry(parent, struct mdp3_iommu_meta, node);
-
-		if (meta->table < entry->table) {
-			p = &(*p)->rb_left;
-		} else if (meta->table > entry->table) {
-			p = &(*p)->rb_right;
-		} else {
-			pr_err("%s: handle %pK already exists\n", __func__,
-				entry->handle);
-			WARN_ON(1);
-		}
-	}
-
-	rb_link_node(&meta->node, parent, p);
-	rb_insert_color(&meta->node, root);
-}
-
-static int mdp3_iommu_map_iommu(struct mdp3_iommu_meta *meta,
-	unsigned long align, unsigned long iova_length,
-	unsigned int padding, unsigned long flags)
-{
-	struct iommu_domain *domain;
-	int ret = 0;
-	unsigned long size;
-	unsigned long unmap_size;
-	struct sg_table *table;
-	int prot = IOMMU_WRITE | IOMMU_READ;
-	unsigned int domain_num = (mdp3_res->domains +
-			MDP3_IOMMU_DOMAIN_UNSECURE)->domain_idx;
-	unsigned int partition_num = 0;
-
-	size = meta->size;
-	table = meta->table;
-
-	/* Use the biggest alignment to allow bigger IOMMU mappings.
-	 * Use the first entry since the first entry will always be the
-	 * biggest entry. To take advantage of bigger mapping sizes both the
-	 * VA and PA addresses have to be aligned to the biggest size.
-	 */
-	if (table->sgl->length > align)
-		align = table->sgl->length;
-
-	ret = msm_allocate_iova_address(domain_num, partition_num,
-			meta->mapped_size, align,
-			(unsigned long *)&meta->iova_addr);
-
-	if (ret)
-		goto out;
-
-	domain = msm_get_iommu_domain(domain_num);
-
-	if (!domain) {
-		ret = -ENOMEM;
-		goto out1;
-	}
-
-	/* Adding padding to before buffer */
-	if (padding) {
-		unsigned long phys_addr = sg_phys(table->sgl);
-
-		ret = msm_iommu_map_extra(domain, meta->iova_addr, phys_addr,
-				padding, SZ_4K, prot);
-		if (ret)
-			goto out1;
-	}
-
-	/* Mapping actual buffer */
-	ret = iommu_map_range(domain, meta->iova_addr + padding,
-			table->sgl, size, prot);
-	if (ret) {
-		pr_err("%s: could not map %pa in domain %pK\n",
-			__func__, &meta->iova_addr, domain);
-			unmap_size = padding;
-		goto out2;
-	}
-
-	/* Adding padding to end of buffer */
-	if (padding) {
-		unsigned long phys_addr = sg_phys(table->sgl);
-		unsigned long extra_iova_addr = meta->iova_addr +
-				padding + size;
-		ret = msm_iommu_map_extra(domain, extra_iova_addr, phys_addr,
-				padding, SZ_4K, prot);
-		if (ret) {
-			unmap_size = padding + size;
-			goto out2;
-		}
-	}
-	return ret;
-
-out2:
-	iommu_unmap_range(domain, meta->iova_addr, unmap_size);
-out1:
-	msm_free_iova_address(meta->iova_addr, domain_num, partition_num,
-				iova_length);
-
-out:
-	return ret;
-}
-
-static struct mdp3_iommu_meta *mdp3_iommu_meta_create(struct ion_client *client,
-	struct ion_handle *handle, struct sg_table *table, unsigned long size,
-	unsigned long align, unsigned long iova_length, unsigned int padding,
-	unsigned long flags, dma_addr_t *iova)
-{
-	struct mdp3_iommu_meta *meta;
-	int ret;
-
-	meta = kzalloc(sizeof(*meta), GFP_KERNEL);
-
-	if (!meta)
-		return ERR_PTR(-ENOMEM);
-
-	meta->handle = handle;
-	meta->table = table;
-	meta->size = size;
-	meta->mapped_size = iova_length;
-	meta->dbuf = ion_share_dma_buf(client, handle);
-	kref_init(&meta->ref);
-
-	ret = mdp3_iommu_map_iommu(meta,
-		align, iova_length, padding, flags);
-	if (ret < 0)	{
-		pr_err("%s: Unable to map buffer\n", __func__);
-		goto out;
-	}
-
-	*iova = meta->iova_addr;
-	mdp3_iommu_meta_add(meta);
-
-	return meta;
-out:
-	kfree(meta);
-	return ERR_PTR(ret);
-}
-
-/*
- * PPP hw reads in tiles of 16 which might be outside mapped region
- * need to map buffers ourseleve to add extra padding
- */
-int mdp3_self_map_iommu(struct ion_client *client, struct ion_handle *handle,
-	unsigned long align, unsigned long padding, dma_addr_t *iova,
-	unsigned long *buffer_size, unsigned long flags,
-	unsigned long iommu_flags)
-{
-	struct mdp3_iommu_meta *iommu_meta = NULL;
-	struct sg_table *table;
-	struct scatterlist *sg;
-	unsigned long size = 0, iova_length = 0;
-	int ret = 0;
-	int i;
-
-	table = ion_sg_table(client, handle);
-	if (IS_ERR_OR_NULL(table))
-		return PTR_ERR(table);
-
-	for_each_sg(table->sgl, sg, table->nents, i)
-		size += sg->length;
-
-	padding = PAGE_ALIGN(padding);
-
-	/* Adding 16 lines padding before and after buffer */
-	iova_length = size + 2 * padding;
-
-	if (size & ~PAGE_MASK) {
-		pr_debug("%s: buffer size %lx is not aligned to %lx",
-			__func__, size, PAGE_SIZE);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (iova_length & ~PAGE_MASK) {
-		pr_debug("%s: iova_length %lx is not aligned to %lx",
-			__func__, iova_length, PAGE_SIZE);
-		ret = -EINVAL;
-		goto out;
-	}
-
-	mutex_lock(&mdp3_res->iommu_lock);
-	iommu_meta = mdp3_iommu_meta_lookup(table);
-
-	if (!iommu_meta) {
-		iommu_meta = mdp3_iommu_meta_create(client, handle, table, size,
-				align, iova_length, padding, flags, iova);
-		if (!IS_ERR_OR_NULL(iommu_meta)) {
-			iommu_meta->flags = iommu_flags;
-			ret = 0;
-		} else {
-			ret = PTR_ERR(iommu_meta);
-			goto out_unlock;
-		}
-	} else {
-		if (iommu_meta->flags != iommu_flags) {
-			pr_err("%s: hndl %pK already mapped with diff flag\n",
-				__func__, handle);
-			ret = -EINVAL;
-			goto out_unlock;
-		} else if (iommu_meta->mapped_size != iova_length) {
-			pr_err("%s: hndl %pK already mapped with diff len\n",
-				__func__, handle);
-			ret = -EINVAL;
-			goto out_unlock;
-		} else {
-			kref_get(&iommu_meta->ref);
-			*iova = iommu_meta->iova_addr;
-		}
-	}
-	WARN_ON(iommu_meta->size != size);
-	mutex_unlock(&mdp3_res->iommu_lock);
-
-	*iova = *iova + padding;
-	*buffer_size = size;
-	return ret;
-
-out_unlock:
-	mutex_unlock(&mdp3_res->iommu_lock);
-out:
-	mdp3_iommu_meta_put(iommu_meta);
-	return ret;
-}
-
 int mdp3_put_img(struct mdp3_img_data *data, int client)
 {
 	struct ion_client *iclient = mdp3_res->ion_client;
@@ -1877,10 +1390,10 @@
 					img->memory_id);
 			return -EINVAL;
 		}
-		if (MAJOR(f.file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
-			fb_num = MINOR(f.file->f_dentry->d_inode->i_rdev);
+		if (MAJOR(f.file->f_path.dentry->d_inode->i_rdev) == FB_MAJOR) {
+			fb_num = MINOR(f.file->f_path.dentry->d_inode->i_rdev);
 			ret = mdss_fb_get_phys_info(&data->addr,
-						&data->len, fb_num);
+							&data->len, fb_num);
 			if (ret) {
 				pr_err("mdss_fb_get_phys_info() failed\n");
 				fdput(f);
@@ -2155,29 +1668,6 @@
 	return rc;
 }
 
-void mdp3_free(struct msm_fb_data_type *mfd)
-{
-	size_t size = 0;
-	int dom;
-	unsigned long phys;
-
-	if (!mfd->iova || !mfd->fbi->screen_base) {
-		pr_info("no fbmem allocated\n");
-		return;
-	}
-
-	size = mfd->fbi->fix.smem_len;
-	phys = mfd->fbi->fix.smem_start;
-	dom = mdp3_res->domains[MDP3_IOMMU_DOMAIN_UNSECURE].domain_idx;
-	iommu_unmap(mdp3_res->domains[MDP3_IOMMU_DOMAIN_UNSECURE].domain,
-			phys, size);
-	msm_iommu_unmap_contig_buffer(mfd->iova, dom, 0, size);
-
-	mfd->fbi->screen_base = NULL;
-	mfd->fbi->fix.smem_start = 0;
-	mfd->iova = 0;
-}
-
 void mdp3_release_splash_memory(struct msm_fb_data_type *mfd)
 {
 	/* Give back the reserved memory to the system */
@@ -2188,7 +1678,6 @@
 				mdp3_res->splash_mem_addr,
 				mdp3_res->splash_mem_size);
 		}
-		mdp3_free(mfd);
 		pr_debug("mdp3_release_splash_memory\n");
 		memblock_free(mdp3_res->splash_mem_addr,
 				mdp3_res->splash_mem_size);
@@ -3056,8 +2545,7 @@
 #define mdp3_resume  NULL
 #endif
 
-
-#ifdef CONFIG_PM_RUNTIME
+#ifdef CONFIG_PM
 static int mdp3_runtime_resume(struct device *dev)
 {
 	bool device_on = true;
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c
index 17dadf4..4a844e9 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.c
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.c
@@ -22,13 +22,13 @@
 #include <linux/delay.h>
 #include <linux/dma-buf.h>
 #include <linux/pm_runtime.h>
-#include <linux/sw_sync.h>
 #include <linux/iommu.h>
 
 #include "mdp3_ctrl.h"
 #include "mdp3.h"
 #include "mdp3_ppp.h"
 #include "mdss_smmu.h"
+#include "mdss_sync.h"
 
 #define VSYNC_EXPIRE_TICK	4
 
@@ -233,7 +233,7 @@
 
 	mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
 	if (mdp3_session->retire_cnt > 0) {
-		sw_sync_timeline_inc(mdp3_session->vsync_timeline, val);
+		mdss_inc_timeline(mfd->mdp_sync_pt_data.timeline_retire, val);
 		mdp3_session->retire_cnt -= min(val, mdp3_session->retire_cnt);
 	}
 	mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
@@ -1656,9 +1656,9 @@
 	panel = mdp3_session->panel;
 	if (mdp3_session->first_commit) {
 		/*wait to ensure frame is sent to panel*/
-		if (panel_info->mipi.init_delay)
+		if (panel_info->mipi.post_init_delay)
 			msleep(((1000 / panel_info->mipi.frame_rate) + 1) *
-					panel_info->mipi.init_delay);
+					panel_info->mipi.post_init_delay);
 		else
 			msleep(1000 / panel_info->mipi.frame_rate);
 		mdp3_session->first_commit = false;
@@ -1737,9 +1737,10 @@
 		}
 		break;
 	case metadata_op_get_ion_fd:
-		if (mfd->fb_ion_handle) {
+		if (mfd->fb_ion_handle && mfd->fb_ion_client) {
 			metadata->data.fbmem_ionfd =
-					dma_buf_fd(mfd->fbmem_buf, 0);
+				ion_share_dma_buf_fd(mfd->fb_ion_client,
+					mfd->fb_ion_handle);
 			if (metadata->data.fbmem_ionfd < 0)
 				pr_err("fd allocation failed. fd = %d\n",
 						metadata->data.fbmem_ionfd);
@@ -2116,7 +2117,7 @@
 static int mdp3_histo_ioctl(struct msm_fb_data_type *mfd, u32 cmd,
 				void __user *argp)
 {
-	int ret = -ENOTSUP;
+	int ret = -ENOTSUPP;
 	struct mdp_histogram_data hist;
 	struct mdp_histogram_start_req hist_req;
 	u32 block;
@@ -2820,8 +2821,8 @@
 	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
 
 	snprintf(name, sizeof(name), "mdss_fb%d_retire", mfd->index);
-	mdp3_session->vsync_timeline = sw_sync_timeline_create(name);
-	if (mdp3_session->vsync_timeline == NULL) {
+	mfd->mdp_sync_pt_data.timeline_retire = mdss_create_timeline(name);
+	if (mfd->mdp_sync_pt_data.timeline_retire == NULL) {
 		pr_err("cannot vsync create time line");
 		return -ENOMEM;
 	}
@@ -2874,8 +2875,9 @@
 	mutex_init(&mdp3_session->lock);
 	INIT_WORK(&mdp3_session->clk_off_work, mdp3_dispatch_clk_off);
 
-	init_kthread_worker(&mdp3_session->worker);
-	init_kthread_work(&mdp3_session->dma_done_work, mdp3_dispatch_dma_done);
+	kthread_init_worker(&mdp3_session->worker);
+	kthread_init_work(&mdp3_session->dma_done_work, mdp3_dispatch_dma_done);
+
 
 	mdp3_session->thread = kthread_run(kthread_worker_fn,
 					   &mdp3_session->worker,
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.h b/drivers/video/fbdev/msm/mdp3_ctrl.h
index 2cc3421..b7b667b 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.h
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.h
@@ -79,7 +79,7 @@
 	int (*wait_for_dma_done)(struct mdp3_session_data *session);
 
 	/* For retire fence */
-	struct sw_sync_timeline *vsync_timeline;
+	struct mdss_timeline *vsync_timeline;
 	int retire_cnt;
 	struct work_struct retire_work;
 };
diff --git a/drivers/video/fbdev/msm/mdp3_layer.c b/drivers/video/fbdev/msm/mdp3_layer.c
index 6c45395..0078466 100644
--- a/drivers/video/fbdev/msm/mdp3_layer.c
+++ b/drivers/video/fbdev/msm/mdp3_layer.c
@@ -21,8 +21,6 @@
 #include <linux/delay.h>
 #include <linux/msm_mdp.h>
 #include <linux/memblock.h>
-#include <linux/sync.h>
-#include <linux/sw_sync.h>
 #include <linux/file.h>
 
 #include <soc/qcom/event_timer.h>
@@ -31,17 +29,18 @@
 #include "mdp3_ppp.h"
 #include "mdp3_ctrl.h"
 #include "mdss_fb.h"
+#include "mdss_sync.h"
 
 enum {
 	MDP3_RELEASE_FENCE = 0,
 	MDP3_RETIRE_FENCE,
 };
 
-static struct sync_fence *__mdp3_create_fence(struct msm_fb_data_type *mfd,
+static struct mdss_fence *__mdp3_create_fence(struct msm_fb_data_type *mfd,
 	struct msm_sync_pt_data *sync_pt_data, u32 fence_type,
 	int *fence_fd, int value)
 {
-	struct sync_fence *sync_fence = NULL;
+	struct mdss_fence *sync_fence = NULL;
 	char fence_name[32];
 	struct mdp3_session_data *mdp3_session;
 
@@ -56,38 +55,42 @@
 
 	if ((fence_type == MDP3_RETIRE_FENCE) &&
 		(mfd->panel.type == MIPI_CMD_PANEL)) {
-		if (mdp3_session->vsync_timeline) {
-			value = mdp3_session->vsync_timeline->value + 1 +
-				mdp3_session->retire_cnt++;
-			sync_fence = mdss_fb_sync_get_fence(
-					mdp3_session->vsync_timeline,
+		if (sync_pt_data->timeline_retire) {
+			value = sync_pt_data->timeline_retire->value + 1 +
+						mdp3_session->retire_cnt++;
+					sync_fence = mdss_fb_sync_get_fence(
+					sync_pt_data->timeline_retire,
 						fence_name, value);
+
 		} else {
 			return ERR_PTR(-EPERM);
 		}
 	} else {
-		sync_fence = mdss_fb_sync_get_fence(sync_pt_data->timeline,
-			fence_name, value);
-	}
+		if (fence_type == MDP3_RETIRE_FENCE)
+			sync_fence = mdss_fb_sync_get_fence(
+						sync_pt_data->timeline_retire,
+							fence_name, value);
+		else
+			sync_fence = mdss_fb_sync_get_fence(
+						sync_pt_data->timeline,
+							fence_name, value);
+		}
 
 	if (IS_ERR_OR_NULL(sync_fence)) {
 		pr_err("%s: unable to retrieve release fence\n", fence_name);
 		goto end;
 	}
 
-	/* get fence fd */
-	*fence_fd = get_unused_fd_flags(0);
+	*fence_fd = mdss_get_sync_fence_fd(sync_fence);
 	if (*fence_fd < 0) {
 		pr_err("%s: get_unused_fd_flags failed error:0x%x\n",
 			fence_name, *fence_fd);
-		sync_fence_put(sync_fence);
-		sync_fence = NULL;
-		goto end;
+			mdss_put_sync_fence(sync_fence);
+			sync_fence = NULL;
+			goto end;
 	}
-
-	sync_fence_install(sync_fence, *fence_fd);
+	pr_debug("%s:val=%d\n", mdss_get_sync_fence_name(sync_fence), value);
 end:
-
 	return sync_fence;
 }
 
@@ -101,7 +104,7 @@
 static int __mdp3_handle_buffer_fences(struct msm_fb_data_type *mfd,
 	struct mdp_layer_commit_v1 *commit, struct mdp_input_layer *layer_list)
 {
-	struct sync_fence *fence, *release_fence, *retire_fence;
+	struct mdss_fence *fence, *release_fence, *retire_fence;
 	struct msm_sync_pt_data *sync_pt_data = NULL;
 	struct mdp_input_layer *layer;
 	int value;
@@ -127,7 +130,7 @@
 		if (layer->buffer.fence < 0)
 			continue;
 
-		fence = sync_fence_fdget(layer->buffer.fence);
+		fence = mdss_get_fd_sync_fence(layer->buffer.fence);
 		if (!fence) {
 			pr_err("%s: sync fence get failed! fd=%d\n",
 				sync_pt_data->fence_name, layer->buffer.fence);
@@ -142,7 +145,7 @@
 	if (ret)
 		goto sync_fence_err;
 
-	value = sync_pt_data->timeline_value + sync_pt_data->threshold +
+	value = sync_pt_data->threshold +
 			atomic_read(&sync_pt_data->commit_cnt);
 
 	release_fence = __mdp3_create_fence(mfd, sync_pt_data,
@@ -166,13 +169,13 @@
 
 retire_fence_err:
 	put_unused_fd(commit->release_fence);
-	sync_fence_put(release_fence);
+	mdss_put_sync_fence(release_fence);
 release_fence_err:
 	commit->retire_fence = -1;
 	commit->release_fence = -1;
 sync_fence_err:
 	for (i = 0; i < sync_pt_data->acq_fen_cnt; i++)
-		sync_fence_put(sync_pt_data->acq_fen[i]);
+		mdss_put_sync_fence(sync_pt_data->acq_fen[i]);
 	sync_pt_data->acq_fen_cnt = 0;
 
 	mutex_unlock(&sync_pt_data->sync_mutex);
diff --git a/drivers/video/fbdev/msm/mdp3_ppp.c b/drivers/video/fbdev/msm/mdp3_ppp.c
index 3b72b2d..612cccc 100644
--- a/drivers/video/fbdev/msm/mdp3_ppp.c
+++ b/drivers/video/fbdev/msm/mdp3_ppp.c
@@ -20,8 +20,6 @@
 #include <linux/uaccess.h>
 #include <linux/sched.h>
 #include <linux/mutex.h>
-#include <linux/sync.h>
-#include <linux/sw_sync.h>
 #include "linux/proc_fs.h"
 #include <linux/delay.h>
 
@@ -30,6 +28,7 @@
 #include "mdp3_hwio.h"
 #include "mdp3.h"
 #include "mdss_debug.h"
+#include "mdss_sync.h"
 
 #define MDP_IS_IMGTYPE_BAD(x) ((x) >= MDP_IMGTYPE_LIMIT)
 #define MDP_RELEASE_BW_TIMEOUT 50
@@ -76,12 +75,12 @@
 	struct mdp_blit_req req_list[MAX_LIST_WINDOW];
 	struct mdp3_img_data src_data[MAX_LIST_WINDOW];
 	struct mdp3_img_data dst_data[MAX_LIST_WINDOW];
-	struct sync_fence *acq_fen[MDP_MAX_FENCE_FD];
+	struct mdss_fence *acq_fen[MDP_MAX_FENCE_FD];
 	u32 acq_fen_cnt;
 	int cur_rel_fen_fd;
 	struct sync_pt *cur_rel_sync_pt;
-	struct sync_fence *cur_rel_fence;
-	struct sync_fence *last_rel_fence;
+	struct mdss_fence *cur_rel_fence;
+	struct mdss_fence *last_rel_fence;
 };
 
 struct blit_req_queue {
@@ -104,7 +103,8 @@
 	struct task_struct *blit_thread;
 	struct blit_req_queue req_q;
 
-	struct sw_sync_timeline *timeline;
+	struct mdss_timeline *timeline;
+
 	int timeline_value;
 
 	struct timer_list free_bw_timer;
@@ -1188,19 +1188,19 @@
 	ATRACE_BEGIN(__func__);
 	/* buf sync */
 	for (i = 0; i < req->acq_fen_cnt; i++) {
-		ret = sync_fence_wait(req->acq_fen[i],
+		ret = mdss_wait_sync_fence(req->acq_fen[i],
 				WAIT_FENCE_FINAL_TIMEOUT);
 		if (ret < 0) {
 			pr_err("%s: sync_fence_wait failed! ret = %x\n",
 				__func__, ret);
 			break;
 		}
-		sync_fence_put(req->acq_fen[i]);
+		mdss_put_sync_fence(req->acq_fen[i]);
 	}
 	ATRACE_END(__func__);
 	if (ret < 0) {
 		while (i < req->acq_fen_cnt) {
-			sync_fence_put(req->acq_fen[i]);
+			mdss_put_sync_fence(req->acq_fen[i]);
 			i++;
 		}
 	}
@@ -1209,7 +1209,7 @@
 
 void mdp3_ppp_signal_timeline(struct blit_req_list *req)
 {
-	sw_sync_timeline_inc(ppp_stat->timeline, 1);
+	mdss_inc_timeline(ppp_stat->timeline, 1);
 	MDSS_XLOG(ppp_stat->timeline->value, ppp_stat->timeline_value);
 	req->last_rel_fence = req->cur_rel_fence;
 	req->cur_rel_fence = 0;
@@ -1221,12 +1221,12 @@
 	int i;
 
 	put_unused_fd(req->cur_rel_fen_fd);
-	sync_fence_put(req->cur_rel_fence);
+	mdss_put_sync_fence(req->cur_rel_fence);
 	req->cur_rel_fence = NULL;
 	req->cur_rel_fen_fd = 0;
 	ppp_stat->timeline_value--;
 	for (i = 0; i < req->acq_fen_cnt; i++)
-		sync_fence_put(req->acq_fen[i]);
+		mdss_put_sync_fence(req->acq_fen[i]);
 	req->acq_fen_cnt = 0;
 }
 
@@ -1235,7 +1235,7 @@
 {
 	int i, fence_cnt = 0, ret = 0;
 	int acq_fen_fd[MDP_MAX_FENCE_FD];
-	struct sync_fence *fence;
+	struct mdss_fence *fence;
 
 	if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
 		(ppp_stat->timeline == NULL))
@@ -1249,7 +1249,7 @@
 		return ret;
 	}
 	for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
-		fence = sync_fence_fdget(acq_fen_fd[i]);
+		fence = mdss_get_fd_sync_fence(acq_fen_fd[i]);
 		if (fence == NULL) {
 			pr_info("%s: null fence! i=%d fd=%d\n", __func__, i,
 				acq_fen_fd[i]);
@@ -1265,19 +1265,12 @@
 	if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
 		mdp3_ppp_wait_for_fence(req);
 
-	req->cur_rel_sync_pt = sw_sync_pt_create(ppp_stat->timeline,
-			ppp_stat->timeline_value++);
 	MDSS_XLOG(ppp_stat->timeline_value);
-	if (req->cur_rel_sync_pt == NULL) {
-		pr_err("%s: cannot create sync point\n", __func__);
-		ret = -ENOMEM;
-		goto buf_sync_err_2;
-	}
+
 	/* create fence */
-	req->cur_rel_fence = sync_fence_create("ppp-fence",
-			req->cur_rel_sync_pt);
+	req->cur_rel_fence = mdss_get_sync_fence(ppp_stat->timeline,
+				"ppp_fence", NULL, ppp_stat->timeline_value++);
 	if (req->cur_rel_fence == NULL) {
-		sync_pt_free(req->cur_rel_sync_pt);
 		req->cur_rel_sync_pt = NULL;
 		pr_err("%s: cannot create fence\n", __func__);
 		ret = -ENOMEM;
@@ -1289,7 +1282,7 @@
 	ppp_stat->timeline_value--;
 buf_sync_err_1:
 	for (i = 0; i < fence_cnt; i++)
-		sync_fence_put(req->acq_fen[i]);
+		mdss_put_sync_fence(req->acq_fen[i]);
 	req->acq_fen_cnt = 0;
 	return ret;
 }
@@ -1586,7 +1579,7 @@
 {
 	struct blit_req_list *req;
 	struct blit_req_queue *req_q = &ppp_stat->req_q;
-	struct sync_fence *fence = NULL;
+	struct mdss_fence *fence = NULL;
 	int count, rc, idx, i;
 
 	count = req_list_header->count;
@@ -1642,13 +1635,8 @@
 	}
 
 	if (async) {
-		req->cur_rel_fen_fd = get_unused_fd_flags(0);
-		if (req->cur_rel_fen_fd < 0) {
-			pr_err("%s: get_unused_fd_flags failed\n", __func__);
-			rc  = -ENOMEM;
-			goto parse_err_1;
-		}
-		sync_fence_install(req->cur_rel_fence, req->cur_rel_fen_fd);
+		req->cur_rel_fen_fd = mdss_get_sync_fence_fd(
+							req->cur_rel_fence);
 		rc = copy_to_user(req_list_header->sync.rel_fen_fd,
 			&req->cur_rel_fen_fd, sizeof(int));
 		if (rc) {
@@ -1664,12 +1652,12 @@
 	kthread_queue_work(&ppp_stat->kworker, &ppp_stat->blit_work);
 	if (!async) {
 		/* wait for release fence */
-		rc = sync_fence_wait(fence,
+		rc = mdss_wait_sync_fence(fence,
 				5 * MSEC_PER_SEC);
 		if (rc < 0)
 			pr_err("%s: sync blit! rc = %x\n", __func__, rc);
 
-		sync_fence_put(fence);
+		mdss_put_sync_fence(fence);
 		fence = NULL;
 	}
 	return 0;
@@ -1697,15 +1685,15 @@
 		return -ENOMEM;
 
 	/*Setup sync_pt timeline for ppp*/
-	ppp_stat->timeline = sw_sync_timeline_create(timeline_name);
+	ppp_stat->timeline = mdss_create_timeline(timeline_name);
 	if (ppp_stat->timeline == NULL) {
 		pr_err("%s: cannot create time line\n", __func__);
 		return -ENOMEM;
 	}
 	ppp_stat->timeline_value = 1;
 
-	init_kthread_worker(&ppp_stat->kworker);
-	init_kthread_work(&ppp_stat->blit_work, mdp3_ppp_blit_handler);
+	kthread_init_worker(&ppp_stat->kworker);
+	kthread_init_work(&ppp_stat->blit_work, mdp3_ppp_blit_handler);
 	ppp_stat->blit_thread = kthread_run(kthread_worker_fn,
 					&ppp_stat->kworker,
 					"mdp3_ppp");
diff --git a/drivers/video/fbdev/msm/mdp3_ppp_hwio.c b/drivers/video/fbdev/msm/mdp3_ppp_hwio.c
index 6f077e2..ec806cf 100644
--- a/drivers/video/fbdev/msm/mdp3_ppp_hwio.c
+++ b/drivers/video/fbdev/msm/mdp3_ppp_hwio.c
@@ -41,7 +41,7 @@
 	LAYER_MAX,
 };
 
-static long long mdp_do_div(long long num, long long den)
+static long long mdp_do_div(uint64_t num, uint64_t den)
 {
 	do_div(num, den);
 	return num;
diff --git a/drivers/video/fbdev/msm/mdss_debug_xlog.c b/drivers/video/fbdev/msm/mdss_debug_xlog.c
index 49684f4..a651b55 100644
--- a/drivers/video/fbdev/msm/mdss_debug_xlog.c
+++ b/drivers/video/fbdev/msm/mdss_debug_xlog.c
@@ -683,6 +683,11 @@
 
 	if (__mdss_xlog_dump_calc_range()) {
 		len = mdss_xlog_dump_entry(xlog_buf, MDSS_XLOG_BUF_MAX);
+		if (len < 0 || len > count) {
+			pr_err("len is more than the size of user buffer\n");
+			return 0;
+		}
+
 		if (copy_to_user(buff, xlog_buf, len))
 			return -EFAULT;
 		*ppos += len;
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index d70c1e8..6bb0960 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -743,7 +743,7 @@
 	if (blen < 0)
 		return 0;
 
-	if (copy_to_user(buf, buffer, blen))
+	if (copy_to_user(buf, buffer, min(count, (size_t)blen+1)))
 		return -EFAULT;
 
 	*ppos += blen;
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index ae9b7cf..27299d10 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -1320,14 +1320,7 @@
 			pr_err("cannot create release fence time line\n");
 			return -ENOMEM;
 		}
-		snprintf(timeline_name, sizeof(timeline_name),
-			"mdss_fb_%d_retire", mfd->index);
-		 mfd->mdp_sync_pt_data.timeline_retire =
-				mdss_create_timeline(timeline_name);
-		if (mfd->mdp_sync_pt_data.timeline == NULL) {
-			pr_err("cannot create release fence time line\n");
-			return -ENOMEM;
-		}
+
 		mfd->mdp_sync_pt_data.notifier.notifier_call =
 			__mdss_fb_sync_buf_done_callback;
 	}
@@ -2979,15 +2972,26 @@
  */
 void mdss_fb_signal_timeline(struct msm_sync_pt_data *sync_pt_data)
 {
+	struct msm_fb_data_type *mfd;
+
+	mfd = container_of(sync_pt_data, typeof(*mfd), mdp_sync_pt_data);
 	mutex_lock(&sync_pt_data->sync_mutex);
-	if (atomic_add_unless(&sync_pt_data->commit_cnt, -1, 0) &&
+	if (atomic_read(&sync_pt_data->commit_cnt) &&
 			sync_pt_data->timeline) {
 		mdss_inc_timeline(sync_pt_data->timeline, 1);
-		mdss_inc_timeline(sync_pt_data->timeline_retire, 1);
+
+		/*
+		 * For Command mode panels, the retire timeline is incremented
+		 * whenever we receive a readptr_done. For all other panels,
+		 * the retire fence should be signaled along with the release
+		 * fence once the frame is done.
+		 */
+		if (mfd->panel.type != MIPI_CMD_PANEL)
+			mdss_inc_timeline(sync_pt_data->timeline_retire, 1);
 		MDSS_XLOG(sync_pt_data->timeline_value);
 		sync_pt_data->timeline_value++;
 
-		pr_debug("%s: buffer signaled! timeline val=%d remaining=%d\n",
+		pr_debug("%s: buffer signaled! timeline val=%d commit_cnt=%d\n",
 			sync_pt_data->fence_name, sync_pt_data->timeline_value,
 			atomic_read(&sync_pt_data->commit_cnt));
 	} else {
@@ -3016,9 +3020,10 @@
 		val = sync_pt_data->threshold +
 			atomic_read(&sync_pt_data->commit_cnt);
 		mdss_resync_timeline(sync_pt_data->timeline);
-		mdss_resync_timeline(sync_pt_data->timeline_retire);
-		sync_pt_data->timeline_value += val;
-		atomic_set(&sync_pt_data->commit_cnt, 0);
+		if (mfd->panel.type != MIPI_CMD_PANEL)
+			mdss_resync_timeline(sync_pt_data->timeline_retire);
+		sync_pt_data->timeline_value = val;
+
 	}
 	mutex_unlock(&sync_pt_data->sync_mutex);
 }
@@ -3216,7 +3221,6 @@
 	mfd->msm_fb_backup.info = *info;
 	mfd->msm_fb_backup.disp_commit = *disp_commit;
 
-	atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt);
 	atomic_inc(&mfd->commits_pending);
 	atomic_inc(&mfd->kickoff_pending);
 	wake_up_all(&mfd->commit_wait_q);
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 4307119..9497318 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -1009,7 +1009,6 @@
 	u32 splash_mem_size;
 	u32 sd_enabled;
 
-	struct mdss_timeline *vsync_timeline;
 	struct mdss_mdp_vsync_handler vsync_retire_handler;
 	int retire_cnt;
 	bool kickoff_released;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 5088117..344d6ef 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -76,13 +76,15 @@
 	u64 result = val;
 
 	if (val) {
-		u64 temp = -1UL;
+		u64 temp = U64_MAX;
 
 		do_div(temp, val);
 		if (temp > numer) {
 			/* no overflow, so we can do the operation*/
 			result = (val * (u64)numer);
 			do_div(result, denom);
+		} else {
+			pr_warn("Overflow, skip fudge factor\n");
 		}
 	}
 	return result;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index b1c8041..d898e7e 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -734,11 +734,12 @@
 
 	if ((fence_type == MDSS_MDP_RETIRE_FENCE) &&
 		(mfd->panel.type == MIPI_CMD_PANEL)) {
-		if (mdp5_data->vsync_timeline) {
-			value = 1 + mdp5_data->retire_cnt++;
+		if (sync_pt_data->timeline_retire) {
+			value = sync_pt_data->timeline_retire->value + 1 +
+				mdp5_data->retire_cnt++;
 			sync_fence = mdss_fb_sync_get_fence(
-				mdp5_data->vsync_timeline, fence_name,
-				value);
+				sync_pt_data->timeline_retire,
+				fence_name, value);
 		} else {
 			return ERR_PTR(-EPERM);
 		}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index da24e84..80708aa 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -2913,6 +2913,11 @@
 		}
 	}
 
+	if (!data) {
+		atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt);
+		MDSS_XLOG(atomic_read(&mfd->mdp_sync_pt_data.commit_cnt));
+	}
+
 	/*
 	 * Setup pipe in solid fill before unstaging,
 	 * to ensure no fetches are happening after dettach or reattach.
@@ -3619,9 +3624,8 @@
 		goto end;
 	}
 
-	if (!ctl->panel_data->panel_info.cont_splash_enabled
-		&& (!mdss_mdp_ctl_is_power_on(ctl) ||
-		mdss_panel_is_power_on_ulp(ctl->power_state))) {
+	if (!ctl->panel_data->panel_info.cont_splash_enabled &&
+	    !mdss_mdp_ctl_is_power_on(ctl)) {
 		pr_debug("fb%d vsync pending first update en=%d, ctl power state:%d\n",
 				mfd->index, en, ctl->power_state);
 		rc = -EPERM;
@@ -5939,10 +5943,8 @@
 		rc = mdss_mdp_overlay_start(mfd);
 		if (rc)
 			goto end;
-		if (mfd->panel_info->type != WRITEBACK_PANEL) {
-			atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt);
+		if (mfd->panel_info->type != WRITEBACK_PANEL)
 			rc = mdss_mdp_overlay_kickoff(mfd, NULL);
-		}
 	} else {
 		rc = mdss_mdp_ctl_setup(ctl);
 		if (rc)
@@ -6340,10 +6342,11 @@
 
 	mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
 	if (mdp5_data->retire_cnt > 0) {
-		mdss_inc_timeline(mdp5_data->vsync_timeline, val);
+		mdss_inc_timeline(mfd->mdp_sync_pt_data.timeline_retire, val);
 		mdp5_data->retire_cnt -= min(val, mdp5_data->retire_cnt);
 		pr_debug("Retire signaled! timeline val=%d remaining=%d\n",
-			mdss_get_timeline_retire_ts(mdp5_data->vsync_timeline),
+			mdss_get_timeline_retire_ts(
+			mfd->mdp_sync_pt_data.timeline_retire),
 			mdp5_data->retire_cnt);
 
 		if (mdp5_data->retire_cnt == 0) {
@@ -6382,7 +6385,7 @@
 	value = 1 + mdp5_data->retire_cnt;
 	mdp5_data->retire_cnt++;
 
-	return mdss_fb_sync_get_fence(mdp5_data->vsync_timeline,
+	return mdss_fb_sync_get_fence(mfd->mdp_sync_pt_data.timeline_retire,
 			"mdp-retire", value);
 }
 
@@ -6420,33 +6423,41 @@
 	struct sched_param param = { .sched_priority = 5 };
 
 	snprintf(name, sizeof(name), "mdss_fb%d_retire", mfd->index);
-	mdp5_data->vsync_timeline = mdss_create_timeline(name);
-	if (mdp5_data->vsync_timeline == NULL) {
+	mfd->mdp_sync_pt_data.timeline_retire = mdss_create_timeline(name);
+	if (mfd->mdp_sync_pt_data.timeline_retire == NULL) {
 		pr_err("cannot vsync create time line");
 		return -ENOMEM;
 	}
 
-	kthread_init_worker(&mdp5_data->worker);
-	kthread_init_work(&mdp5_data->vsync_work, __vsync_retire_work_handler);
+	/*
+	 * vsync_work is required only for command mode panels and for panels
+	 * with dynamic mode switch supported. For all other panels the retire
+	 * fence is signaled along with the release fence once the frame
+	 * transfer is done.
+	 */
+	if ((mfd->panel_info->mipi.dms_mode) ||
+		(mfd->panel_info->type == MIPI_CMD_PANEL)) {
+		kthread_init_worker(&mdp5_data->worker);
+		kthread_init_work(&mdp5_data->vsync_work,
+			__vsync_retire_work_handler);
 
-	mdp5_data->thread = kthread_run(kthread_worker_fn,
+		mdp5_data->thread = kthread_run(kthread_worker_fn,
 					&mdp5_data->worker,
 					"vsync_retire_work");
+		if (IS_ERR(mdp5_data->thread)) {
+			pr_err("unable to start vsync thread\n");
+			mdp5_data->thread = NULL;
+			return -ENOMEM;
+		}
 
-	if (IS_ERR(mdp5_data->thread)) {
-		pr_err("unable to start vsync thread\n");
-		mdp5_data->thread = NULL;
-		return -ENOMEM;
+		sched_setscheduler(mdp5_data->thread, SCHED_FIFO, &param);
+		mfd->mdp_sync_pt_data.get_retire_fence =
+				__vsync_retire_get_fence;
+		mdp5_data->vsync_retire_handler.vsync_handler =
+				__vsync_retire_handle_vsync;
+		mdp5_data->vsync_retire_handler.cmd_post_flush = false;
 	}
 
-	sched_setscheduler(mdp5_data->thread, SCHED_FIFO, &param);
-
-	mfd->mdp_sync_pt_data.get_retire_fence = __vsync_retire_get_fence;
-
-	mdp5_data->vsync_retire_handler.vsync_handler =
-		__vsync_retire_handle_vsync;
-	mdp5_data->vsync_retire_handler.cmd_post_flush = false;
-
 	return 0;
 }
 
@@ -6715,14 +6726,12 @@
 		}
 	}
 
-	if (mfd->panel_info->mipi.dms_mode ||
-			mfd->panel_info->type == MIPI_CMD_PANEL) {
-		rc = __vsync_retire_setup(mfd);
-		if (IS_ERR_VALUE((unsigned long)rc)) {
-			pr_err("unable to create vsync timeline\n");
-			goto init_fail;
-		}
+	rc = __vsync_retire_setup(mfd);
+	if (IS_ERR_VALUE((unsigned long)rc)) {
+		pr_err("unable to create vsync timeline\n");
+		goto init_fail;
 	}
+
 	mfd->mdp_sync_pt_data.async_wait_fences = true;
 
 	pm_runtime_set_suspended(&mfd->pdev->dev);
diff --git a/drivers/video/fbdev/msm/mdss_rotator.c b/drivers/video/fbdev/msm/mdss_rotator.c
index 2dc9a1f..f51a1b8 100644
--- a/drivers/video/fbdev/msm/mdss_rotator.c
+++ b/drivers/video/fbdev/msm/mdss_rotator.c
@@ -387,7 +387,7 @@
 	rot_timeline = &entry->queue->timeline;
 
 	mutex_lock(&rot_timeline->lock);
-	val = 1;
+	val = rot_timeline->next_value + 1;
 
 	fence = mdss_get_sync_fence(rot_timeline->timeline,
 					rot_timeline->fence_name, NULL, val);
diff --git a/drivers/video/fbdev/msm/mdss_sync.c b/drivers/video/fbdev/msm/mdss_sync.c
index 22fdcf5..8fe9461 100644
--- a/drivers/video/fbdev/msm/mdss_sync.c
+++ b/drivers/video/fbdev/msm/mdss_sync.c
@@ -37,28 +37,6 @@
 	struct list_head fence_list;
 };
 
-/**
- * struct mdss_timeline - sync timeline context
- * @kref: reference count of timeline
- * @lock: serialization lock for timeline and fence update
- * @name: name of timeline
- * @fence_name: fence name prefix
- * @next_value: next commit sequence number
- * @value: current retired sequence number
- * @context: fence context identifier
- * @fence_list_head: linked list of outstanding sync fence
- */
-struct mdss_timeline {
-	struct kref kref;
-	spinlock_t lock;
-	spinlock_t list_lock;
-	char name[MDSS_SYNC_NAME_SIZE];
-	u32 next_value;
-	u32 value;
-	u64 context;
-	struct list_head fence_list_head;
-};
-
 #if defined(CONFIG_SYNC_FILE)
 /*
  * to_mdss_fence - get mdss fence from fence base object
@@ -240,6 +218,7 @@
 	spin_lock(&tl->list_lock);
 	if (list_empty(&tl->fence_list_head)) {
 		pr_debug("fence list is empty\n");
+		tl->value += 1;
 		spin_unlock(&tl->list_lock);
 		return 0;
 	}
@@ -301,10 +280,9 @@
  */
 struct mdss_fence *mdss_get_sync_fence(
 		struct mdss_timeline *tl, const char *fence_name,
-		u32 *timestamp, int offset)
+		u32 *timestamp, int value)
 {
 	struct mdss_fence *f;
-	u32 val;
 	unsigned long flags;
 
 	if (!tl) {
@@ -318,22 +296,21 @@
 
 	INIT_LIST_HEAD(&f->fence_list);
 	spin_lock_irqsave(&tl->lock, flags);
-	val = tl->next_value + offset;
-	tl->next_value += 1;
-	fence_init(&f->base, &mdss_fence_ops, &tl->lock, tl->context, val);
+	tl->next_value = value;
+	fence_init(&f->base, &mdss_fence_ops, &tl->lock, tl->context, value);
 	mdss_get_timeline(tl);
 	spin_unlock_irqrestore(&tl->lock, flags);
 
 	spin_lock(&tl->list_lock);
 	list_add_tail(&f->fence_list, &tl->fence_list_head);
 	spin_unlock(&tl->list_lock);
-	snprintf(f->name, sizeof(f->name), "%s_%u", fence_name, val);
+	snprintf(f->name, sizeof(f->name), "%s_%u", fence_name, value);
 
 	if (timestamp)
-		*timestamp = val;
+		*timestamp = value;
 
-	pr_debug("fence created at val=%u tl->name %s next_value %d value %d offset %d\n",
-			val, tl->name, tl->next_value, tl->value, offset);
+	pr_debug("fence created at val=%u tl->name= %s tl->value = %d tl->next_value =%d\n",
+			value, tl->name, tl->value, tl->next_value);
 
 	return (struct mdss_fence *) &f->base;
 }
diff --git a/drivers/video/fbdev/msm/mdss_sync.h b/drivers/video/fbdev/msm/mdss_sync.h
index a2e84d4..7143863 100644
--- a/drivers/video/fbdev/msm/mdss_sync.h
+++ b/drivers/video/fbdev/msm/mdss_sync.h
@@ -17,8 +17,31 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 
+#define MDSS_SYNC_NAME_SIZE             64
 struct mdss_fence;
-struct mdss_timeline;
+
+/**
+ * struct mdss_timeline - sync timeline context
+ * @kref: reference count of timeline
+ * @lock: serialization lock for timeline and fence update
+ * @name: name of timeline
+ * @fence_name: fence name prefix
+ * @next_value: next commit sequence number
+ * @value: current retired sequence number
+ * @context: fence context identifier
+ * @fence_list_head: linked list of outstanding sync fence
+ */
+
+struct mdss_timeline {
+	struct kref kref;
+	spinlock_t lock;
+	spinlock_t list_lock;
+	char name[MDSS_SYNC_NAME_SIZE];
+	u32 next_value;
+	u32 value;
+	u64 context;
+	struct list_head fence_list_head;
+};
 
 #if defined(CONFIG_SYNC_FILE)
 struct mdss_timeline *mdss_create_timeline(const char *name);
diff --git a/include/dt-bindings/clock/msm-clocks-8953.h b/include/dt-bindings/clock/msm-clocks-8953.h
index 9550a41..a1b64cd 100644
--- a/include/dt-bindings/clock/msm-clocks-8953.h
+++ b/include/dt-bindings/clock/msm-clocks-8953.h
@@ -317,6 +317,11 @@
 #define clk_apcs_c1_pll					 0x17d32f1e
 #define clk_apcs_cci_pll				 0x09affb3c
 #define clk_a53ssmux_cci				 0x15560bd5
+#define clk_perf_cpussmux				 0xe6532496
+#define clk_pwr_cpussmux				 0xde339cf1
+#define clk_cci_cpussmux				 0xcaeb1b94
+#define clk_pwr_clk					 0x9283a6d8
+#define clk_perf_clk					 0x98d6ee40
 #define clk_a53_cci_clk					 0x4cdbbe58
 
 #define clk_audio_ap_clk				 0x312ac429
diff --git a/include/linux/ipc_logging.h b/include/linux/ipc_logging.h
index 780a82d..5bc8b6a 100644
--- a/include/linux/ipc_logging.h
+++ b/include/linux/ipc_logging.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2015, 2018 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -124,6 +124,13 @@
  */
 int ipc_log_string(void *ilctxt, const char *fmt, ...) __printf(2, 3);
 
+/*
+ * ipc_log_ctrl_all - disable/enable logging in all clients
+ *
+ * @ Data specified using format specifiers
+ */
+void ipc_log_ctrl_all(bool disable);
+
 /**
  * ipc_log_extract - Reads and deserializes log
  *
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 2d4d24f..2530fcc 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -650,6 +650,9 @@
 	 */
 	void *cmdq_private;
 	struct mmc_request	*err_mrq;
+
+	atomic_t rpmb_req_pending;
+	struct mutex		rpmb_req_mutex;
 	unsigned long		private[0] ____cacheline_aligned;
 };
 
diff --git a/include/linux/msm-sps.h b/include/linux/msm-sps.h
index 662cd9f..8f2c2ee 100644
--- a/include/linux/msm-sps.h
+++ b/include/linux/msm-sps.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
@@ -120,6 +120,8 @@
 #define SPS_BAM_HOLD_MEM            (1UL << 8)
 /* Use cached write pointer */
 #define SPS_BAM_CACHED_WP           (1UL << 10)
+/* Reset BAM with pipes connected */
+#define SPS_BAM_FORCE_RESET         (1UL << 11)
 
 /* BAM device management flags */
 
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 43d801e..629907a 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -278,6 +278,8 @@
 	POWER_SUPPLY_PROP_BATT_PROFILE_VERSION,
 	POWER_SUPPLY_PROP_BATT_FULL_CURRENT,
 	POWER_SUPPLY_PROP_RECHARGE_SOC,
+	POWER_SUPPLY_PROP_TOGGLE_STAT,
+	POWER_SUPPLY_PROP_ALLOW_HVDCP3,
 	/* Local extensions of type int64_t */
 	POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
 	/* Properties of type `const char *' */
diff --git a/include/linux/usb_bam.h b/include/linux/usb_bam.h
index e5d4c04..fc0647a 100644
--- a/include/linux/usb_bam.h
+++ b/include/linux/usb_bam.h
@@ -438,6 +438,7 @@
 bool msm_bam_hsic_lpm_ok(void);
 bool msm_bam_hsic_host_pipe_empty(void);
 bool msm_usb_bam_enable(enum usb_ctrl ctrl, bool bam_enable);
+int msm_do_bam_disable_enable(enum usb_ctrl ctrl);
 #else
 static inline int usb_bam_connect(enum usb_ctrl bam, u8 idx, u32 *bam_pipe_idx,
 							unsigned long iova)
@@ -543,6 +544,7 @@
 static inline bool msm_bam_hsic_host_pipe_empty(void) { return true; }
 static inline bool msm_usb_bam_enable(enum usb_ctrl ctrl, bool bam_enable)
 { return true; }
+int msm_do_bam_disable_enable(enum usb_ctrl ctrl) { return true; }
 
 #endif
 
diff --git a/include/media/msmb_generic_buf_mgr.h b/include/media/msmb_generic_buf_mgr.h
index b3e1a02..95cfcad7 100644
--- a/include/media/msmb_generic_buf_mgr.h
+++ b/include/media/msmb_generic_buf_mgr.h
@@ -43,6 +43,8 @@
 #define VIDIOC_MSM_BUF_MNGR_FLUSH32 \
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 39, struct msm_buf_mngr_info32_t)
 
+#define VIDIOC_MSM_BUF_MNGR_BUF_ERROR32 \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 41, struct msm_buf_mngr_info32_t)
 #endif
 
 #endif
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index 22888b0..aab92ad 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -34,6 +34,9 @@
 #include <linux/mutex.h>
 #include <linux/atomic.h>
 
+#define RDS_PS_SIMPLE_OFFSET 2
+extern struct mutex fm_smd_enable;
+
 struct radio_hci_dev {
 	char		name[8];
 	unsigned long	flags;
@@ -75,7 +78,7 @@
 };
 
 int radio_hci_register_dev(struct radio_hci_dev *hdev);
-int radio_hci_unregister_dev(struct radio_hci_dev *hdev);
+int radio_hci_unregister_dev(void);
 int radio_hci_recv_frame(struct sk_buff *skb);
 int radio_hci_send_cmd(struct radio_hci_dev *hdev, __u16 opcode, __u32 plen,
 	void *param);
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 574ff2a..916f1dc 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -331,7 +331,8 @@
 				    struct v4l2_format *f);
 	int (*vidioc_g_fmt_sdr_out)(struct file *file, void *fh,
 				    struct v4l2_format *f);
-
+	int (*vidioc_g_fmt_type_private)(struct file *file, void *fh,
+					struct v4l2_format *f);
 	/* VIDIOC_S_FMT handlers */
 	int (*vidioc_s_fmt_vid_cap)(struct file *file, void *fh,
 				    struct v4l2_format *f);
diff --git a/include/soc/qcom/memory_dump.h b/include/soc/qcom/memory_dump.h
index 5bc50b5..a962a16 100644
--- a/include/soc/qcom/memory_dump.h
+++ b/include/soc/qcom/memory_dump.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -87,7 +87,8 @@
 	MSM_DUMP_DATA_POWER_REGS = 0xED,
 	MSM_DUMP_DATA_TMC_ETF = 0xF0,
 	MSM_DUMP_DATA_TPDM_SWAO_MCMB = 0xF2,
-	MSM_DUMP_DATA_TMC_REG = 0x100,
+	MSM_DUMP_DATA_TMC_ETR_REG = 0x100,
+	MSM_DUMP_DATA_TMC_ETF_REG = 0x101,
 	MSM_DUMP_DATA_LOG_BUF = 0x110,
 	MSM_DUMP_DATA_LOG_BUF_FIRST_IDX = 0x111,
 	MSM_DUMP_DATA_SCANDUMP_PER_CPU = 0x130,
@@ -121,11 +122,22 @@
 	uint64_t addr;
 };
 
+struct dump_vaddr_entry {
+	uint32_t id;
+	void *dump_vaddr;
+	struct msm_dump_data *dump_data_vaddr;
+};
+
+struct msm_mem_dump_vaddr_tbl {
+	uint8_t num_node;
+	struct dump_vaddr_entry *entries;
+};
+
 #ifdef CONFIG_QCOM_MEMORY_DUMP_V2
 extern int msm_dump_data_register(enum msm_dump_table_ids id,
 				  struct msm_dump_entry *entry);
 
-extern void *get_msm_dump_ptr(enum msm_dump_data_ids id);
+extern struct dump_vaddr_entry *get_msm_dump_ptr(enum msm_dump_data_ids id);
 #else
 static inline int msm_dump_data_register(enum msm_dump_table_ids id,
 					 struct msm_dump_entry *entry)
diff --git a/include/soc/qcom/scm.h b/include/soc/qcom/scm.h
index 63698cf..fa64d5d 100644
--- a/include/soc/qcom/scm.h
+++ b/include/soc/qcom/scm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -100,6 +100,8 @@
 
 extern int scm_call2(u32 cmd_id, struct scm_desc *desc);
 
+extern int scm_call2_noretry(u32 cmd_id, struct scm_desc *desc);
+
 extern int scm_call2_atomic(u32 cmd_id, struct scm_desc *desc);
 
 extern int scm_call_noalloc(u32 svc_id, u32 cmd_id, const void *cmd_buf,
@@ -149,6 +151,11 @@
 	return 0;
 }
 
+static inline int scm_call2_noretry(u32 cmd_id, struct scm_desc *desc)
+{
+	return 0;
+}
+
 static inline int scm_call2_atomic(u32 cmd_id, struct scm_desc *desc)
 {
 	return 0;
diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h
index 280a6d9..b04052e 100644
--- a/include/soc/qcom/socinfo.h
+++ b/include/soc/qcom/socinfo.h
@@ -112,6 +112,8 @@
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8953")
 #define early_machine_is_msm8937()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8937")
+#define early_machine_is_mdm9607()      \
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mdm9607")
 #define early_machine_is_sdm450()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdm450")
 #define early_machine_is_sdm632()	\
@@ -159,6 +161,7 @@
 #define early_machine_is_apqcobalt()	0
 #define early_machine_is_msmhamster()	0
 #define early_machine_is_msmfalcon()	0
+#define early_machine_is_mdm9607()	0
 #define early_machine_is_sdxpoorwills()	0
 #define early_machine_is_sdm845()	0
 #define early_machine_is_sdm670()	0
@@ -242,6 +245,7 @@
 	MSM_CPU_SDM632,
 	MSM_CPU_SDA632,
 	MSM_CPU_8937,
+	MSM_CPU_9607,
 	MSM_CPU_SDM439,
 	MSM_CPU_SDM429,
 	MSM_CPU_9650,
diff --git a/include/trace/events/trace_msm_pil_event.h b/include/trace/events/trace_msm_pil_event.h
index 4795dc5..072bbbb 100644
--- a/include/trace/events/trace_msm_pil_event.h
+++ b/include/trace/events/trace_msm_pil_event.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
@@ -40,6 +40,7 @@
 		__get_str(fw_name))
 );
 
+#ifdef CONFIG_MSM_PIL
 TRACE_EVENT(pil_notif,
 
 	TP_PROTO(const char *event_name, unsigned long code,
@@ -64,6 +65,9 @@
 		__entry->code,
 		__get_str(fw_name))
 );
+#else
+#define trace_pil_notif(event_name, code, fw_name) do { } while (0)
+#endif
 
 TRACE_EVENT(pil_func,
 
diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h
index 7683188..12263e4 100644
--- a/include/uapi/linux/fs.h
+++ b/include/uapi/linux/fs.h
@@ -226,6 +226,7 @@
 #define BLKSECDISCARD _IO(0x12,125)
 #define BLKROTATIONAL _IO(0x12,126)
 #define BLKZEROOUT _IO(0x12,127)
+#define BLKGETSTPART _IO(0x12, 128)
 
 #define BMAP_IOCTL 1		/* obsolete - kept for compatibility */
 #define FIBMAP	   _IO(0x00,1)	/* bmap access */
diff --git a/include/uapi/media/msmb_generic_buf_mgr.h b/include/uapi/media/msmb_generic_buf_mgr.h
index 2961cae..8dad9ae 100644
--- a/include/uapi/media/msmb_generic_buf_mgr.h
+++ b/include/uapi/media/msmb_generic_buf_mgr.h
@@ -62,5 +62,7 @@
 	_IOWR('V', BASE_VIDIOC_PRIVATE + 40, \
 	struct msm_camera_private_ioctl_arg)
 
+#define VIDIOC_MSM_BUF_MNGR_BUF_ERROR \
+	_IOWR('V', BASE_VIDIOC_PRIVATE + 41, struct msm_buf_mngr_info)
 #endif
 
diff --git a/include/uapi/media/msmb_isp.h b/include/uapi/media/msmb_isp.h
index 2b10748..053fa76 100644
--- a/include/uapi/media/msmb_isp.h
+++ b/include/uapi/media/msmb_isp.h
@@ -874,6 +874,10 @@
 #define V4L2_PIX_FMT_P16GBRG10 v4l2_fourcc('P', 'G', 'B', '0')
 #define V4L2_PIX_FMT_P16GRBG10 v4l2_fourcc('P', 'G', 'R', '0')
 #define V4L2_PIX_FMT_P16RGGB10 v4l2_fourcc('P', 'R', 'G', '0')
+#define V4L2_PIX_FMT_P16BGGR12 v4l2_fourcc('P', 'B', 'G', '2')
+#define V4L2_PIX_FMT_P16GBRG12 v4l2_fourcc('P', 'G', 'B', '2')
+#define V4L2_PIX_FMT_P16GRBG12 v4l2_fourcc('P', 'G', 'R', '2')
+#define V4L2_PIX_FMT_P16RGGB12 v4l2_fourcc('P', 'R', 'G', '2')
 #define V4L2_PIX_FMT_NV14 v4l2_fourcc('N', 'V', '1', '4')
 #define V4L2_PIX_FMT_NV41 v4l2_fourcc('N', 'V', '4', '1')
 #define V4L2_PIX_FMT_META v4l2_fourcc('Q', 'M', 'E', 'T')
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 53974cc..895c63f 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -246,7 +246,7 @@
 	if (unlikely(!sysctl_sched_use_walt_cpu_util))
 		return;
 
-	WARN_ON(curr_ws < last_ws);
+	BUG_ON(curr_ws < last_ws);
 	if (curr_ws <= last_ws)
 		return;
 
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 75ea4ff..744b535 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6816,13 +6816,17 @@
 
 static bool is_packing_eligible(struct task_struct *p, int target_cpu,
 				struct find_best_target_env *fbt_env,
-				unsigned int target_cpus_count)
+				unsigned int target_cpus_count,
+				int best_idle_cstate)
 {
 	unsigned long tutil, estimated_capacity;
 
 	if (fbt_env->placement_boost || fbt_env->need_idle)
 		return false;
 
+	if (best_idle_cstate == -1)
+		return false;
+
 	if (target_cpus_count != 1)
 		return true;
 
@@ -7183,7 +7187,7 @@
 	} while (sg = sg->next, sg != sd->groups);
 
 	if (best_idle_cpu != -1 && !is_packing_eligible(p, target_cpu, fbt_env,
-					active_cpus_count)) {
+					active_cpus_count, best_idle_cstate)) {
 		if (target_cpu == task_cpu(p))
 			fbt_env->avoid_prev_cpu = true;
 
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index b2df539..78c0e04 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -348,6 +348,10 @@
 	alarm->timer.function = alarmtimer_fired;
 	alarm->function = function;
 	alarm->type = type;
+	if (type >= ALARM_NUMTYPE) {
+		/* use ALARM_BOOTTIME as the default */
+		alarm->type = ALARM_BOOTTIME;
+	}
 	alarm->state = ALARMTIMER_STATE_INACTIVE;
 }
 EXPORT_SYMBOL_GPL(alarm_init);
diff --git a/kernel/trace/ipc_logging.c b/kernel/trace/ipc_logging.c
index ec9bde7..68a9ad7 100644
--- a/kernel/trace/ipc_logging.c
+++ b/kernel/trace/ipc_logging.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
@@ -295,6 +295,8 @@
 		return;
 	}
 
+	if (ilctxt->disabled)
+		return;
 	read_lock_irqsave(&context_list_lock_lha1, flags);
 	spin_lock(&ilctxt->context_lock_lhb1);
 	while (ilctxt->write_avail <= ectxt->offset)
@@ -508,11 +510,14 @@
 {
 	struct encode_context ectxt;
 	int avail_size, data_size, hdr_size = sizeof(struct tsv_header);
+	struct ipc_log_context *ctxt = (struct ipc_log_context *)ilctxt;
 	va_list arg_list;
 
 	if (!ilctxt)
 		return -EINVAL;
 
+	if (ctxt->disabled)
+		return -EBUSY;
 	msg_encode_start(&ectxt, TSV_TYPE_STRING);
 	tsv_timestamp_write(&ectxt);
 	tsv_qtimer_write(&ectxt);
@@ -529,6 +534,32 @@
 }
 EXPORT_SYMBOL(ipc_log_string);
 
+/*
+ * ipc_log_ctrl_all - disable/enable logging in all clients
+ *
+ * @ Data specified using format specifiers
+ */
+void ipc_log_ctrl_all(bool disable)
+{
+	struct ipc_log_context *ctxt = NULL;
+	unsigned long flags;
+
+	read_lock_irqsave(&context_list_lock_lha1, flags);
+	list_for_each_entry(ctxt, &ipc_log_context_list, list) {
+		if (disable) {
+			ipc_log_string(ctxt,
+				"LOGGING DISABLED FOR ALL CLIENTS!!\n");
+			ctxt->disabled = disable;
+		} else {
+			ctxt->disabled = disable;
+			ipc_log_string(ctxt,
+				"LOGGING ENABLED FOR ALL CLIENTS!!\n");
+		}
+	}
+	read_unlock_irqrestore(&context_list_lock_lha1, flags);
+}
+EXPORT_SYMBOL(ipc_log_ctrl_all);
+
 /**
  * ipc_log_extract - Reads and deserializes log
  *
diff --git a/kernel/trace/ipc_logging_debug.c b/kernel/trace/ipc_logging_debug.c
index d733724..7a4c630 100644
--- a/kernel/trace/ipc_logging_debug.c
+++ b/kernel/trace/ipc_logging_debug.c
@@ -1,4 +1,4 @@
-/* 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
@@ -113,6 +113,83 @@
 	return bsize;
 }
 
+static ssize_t debug_write_ctrl(struct file *file, const char __user *buff,
+				 size_t count, loff_t *ppos)
+{
+	struct ipc_log_context *ilctxt;
+	struct dentry *d = file->f_path.dentry;
+	int bsize = 1;
+	int srcu_idx;
+	int r;
+	char local_buf[3];
+
+	r = debugfs_use_file_start(d, &srcu_idx);
+	if (!r) {
+		ilctxt = file->private_data;
+		r = kref_get_unless_zero(&ilctxt->refcount) ? 0 : -EIO;
+	}
+	debugfs_use_file_finish(srcu_idx);
+	if (r)
+		return r;
+
+	if (copy_from_user(local_buf, buff, bsize)) {
+		count = -EFAULT;
+		goto done;
+	}
+
+	if (*local_buf == '1') {
+		ipc_log_string(ilctxt, "LOGGING DISABLED FOR THIS CLIENT!!\n");
+		ilctxt->disabled = true;
+	} else if (*local_buf == '0') {
+		ilctxt->disabled = false;
+		ipc_log_string(ilctxt, "LOGGING ENABLED FOR THIS CLIENT!!\n");
+	}
+
+done:
+	ipc_log_context_put(ilctxt);
+	return count;
+}
+
+
+static ssize_t debug_write_ctrl_all(struct file *file, const char __user *buff,
+				 size_t count, loff_t *ppos)
+{
+	int bsize = 1;
+	char local_buf[3];
+
+	if (copy_from_user(local_buf, buff, bsize))
+		return -EFAULT;
+	if (*local_buf == '1')
+		ipc_log_ctrl_all(true);
+	else if (*local_buf == '0')
+		ipc_log_ctrl_all(false);
+	return count;
+}
+
+static ssize_t debug_read_ctrl(struct file *file, char __user *buff,
+				 size_t count, loff_t *ppos)
+{
+	struct ipc_log_context *ilctxt;
+	struct dentry *d = file->f_path.dentry;
+	int bsize = 2;
+	int srcu_idx;
+	int r;
+
+	r = debugfs_use_file_start(d, &srcu_idx);
+	if (!r) {
+		ilctxt = file->private_data;
+		r = kref_get_unless_zero(&ilctxt->refcount) ? 0 : -EIO;
+	}
+	debugfs_use_file_finish(srcu_idx);
+	if (r)
+		return r;
+
+	bsize = simple_read_from_buffer(buff, count, ppos,
+				ilctxt->disabled?"1\n":"0\n", bsize);
+	ipc_log_context_put(ilctxt);
+	return bsize;
+}
+
 static ssize_t debug_read(struct file *file, char __user *buff,
 			  size_t count, loff_t *ppos)
 {
@@ -141,6 +218,16 @@
 	.open = debug_open,
 };
 
+static const struct file_operations debug_ops_ctrl = {
+	.read = debug_read_ctrl,
+	.write = debug_write_ctrl,
+	.open = debug_open,
+};
+
+static const struct file_operations debug_ops_ctrl_all = {
+	.write = debug_write_ctrl_all,
+};
+
 static void debug_create(const char *name, mode_t mode,
 			 struct dentry *dent,
 			 struct ipc_log_context *ilctxt,
@@ -176,6 +263,9 @@
 			pr_err("%s: unable to create debugfs %ld\n",
 				__func__, PTR_ERR(root_dent));
 			root_dent = NULL;
+		} else {
+			debug_create("ctrl_all", 0444, root_dent,
+				NULL, &debug_ops_ctrl_all);
 		}
 	}
 	mutex_unlock(&ipc_log_debugfs_init_lock);
@@ -195,6 +285,8 @@
 				     ctxt, &debug_ops);
 			debug_create("log_cont", 0444, ctxt->dent,
 				     ctxt, &debug_ops_cont);
+			debug_create("log_disable", 0444, ctxt->dent,
+				     ctxt, &debug_ops_ctrl);
 		}
 	}
 	add_deserialization_func((void *)ctxt,
diff --git a/kernel/trace/ipc_logging_private.h b/kernel/trace/ipc_logging_private.h
index 47c41e9..bb91dce 100644
--- a/kernel/trace/ipc_logging_private.h
+++ b/kernel/trace/ipc_logging_private.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -121,6 +121,7 @@
 	struct completion read_avail;
 	struct kref refcount;
 	bool destroyed;
+	bool disabled;
 };
 
 struct dfunc_info {
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 9b59170..1d4429d 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -1589,8 +1589,7 @@
 }
 
 /*
- * Stop the automatic memory scanning thread. This function must be called
- * with the scan_mutex held.
+ * Stop the automatic memory scanning thread.
  */
 static void stop_scan_thread(void)
 {
@@ -1853,12 +1852,15 @@
 {
 	stop_scan_thread();
 
+	mutex_lock(&scan_mutex);
 	/*
-	 * Once the scan thread has stopped, it is safe to no longer track
-	 * object freeing. Ordering of the scan thread stopping and the memory
-	 * accesses below is guaranteed by the kthread_stop() function.
+	 * Once it is made sure that kmemleak_scan has stopped, it is safe to no
+	 * longer track object freeing. Ordering of the scan thread stopping and
+	 * the memory accesses below is guaranteed by the kthread_stop()
+	 * function.
 	 */
 	kmemleak_free_enabled = 0;
+	mutex_unlock(&scan_mutex);
 
 	if (!kmemleak_found_leaks)
 		__kmemleak_do_cleanup();
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 6fd9773..f99065f 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -202,13 +202,6 @@
 		atomic_long_read(&p->mm->nr_ptes) + mm_nr_pmds(p->mm);
 	task_unlock(p);
 
-	/*
-	 * Root processes get 3% bonus, just like the __vm_enough_memory()
-	 * implementation used by LSMs.
-	 */
-	if (has_capability_noaudit(p, CAP_SYS_ADMIN))
-		points -= (points * 3) / 100;
-
 	/* Normalize to oom_score_adj units */
 	adj *= totalpages / 1000;
 	points += adj;
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 7fe91b1..eb4cc00 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -1202,9 +1202,12 @@
 	# 60 gHz band channels 1-3, FCC
 	(57240 - 63720 @ 2160), (40)
 
-country QA:
+country QA: DFS-ETSI
 	(2402 - 2482 @ 40), (20)
-	(5735 - 5835 @ 80), (30)
+	(5170 - 5250 @ 80), (23), AUTO-BW
+	(5250 - 5330 @ 80), (23), DFS, AUTO-BW
+	(5490 - 5730 @ 80), (20), DFS
+	(5735 - 5875 @ 80), (20)
 
 country RE: DFS-ETSI
 	(2402 - 2482 @ 40), (20)